linemod.cpp
Go to the documentation of this file.
1 // -*- mode: c++ -*-
2 /*********************************************************************
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2014, JSK Lab
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/o2r other materials provided
17  * with the distribution.
18  * * Neither the name of the JSK Lab nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *********************************************************************/
35 // based on opencv sample
36 // added ros interfaces
37 
38 
39 #include <opencv2/core/core.hpp>
40 #include <opencv2/imgproc/imgproc_c.h> // cvFindContours
41 #include <opencv2/imgproc/imgproc.hpp>
42 #include <opencv2/objdetect/objdetect.hpp>
43 #include <opencv2/highgui/highgui.hpp>
44 #include <iterator>
45 #include <set>
46 #include <cstdio>
47 #include <iostream>
48 
49 // ros
50 #include <ros/ros.h>
51 #include <sensor_msgs/Image.h>
52 #include <sensor_msgs/CameraInfo.h>
57 #include <cv_bridge/cv_bridge.h>
59 
60 // linemod has been moved to opencv_contrib
61 // http://code.opencv.org/projects/opencv/repository/revisions/1ad9827fc4ede1b9c42515569fcc5d8d1106a4ea
62 #if CV_MAJOR_VERSION < 3
63 
64 // Function prototypes
65 void subtractPlane(const cv::Mat& depth, cv::Mat& mask, std::vector<CvPoint>& chain, double f);
66 
67 std::vector<CvPoint> maskFromTemplate(const std::vector<cv::linemod::Template>& templates,
68  int num_modalities, cv::Point offset, cv::Size size,
69  cv::Mat& mask, cv::Mat& dst);
70 
71 void templateConvexHull(const std::vector<cv::linemod::Template>& templates,
72  int num_modalities, cv::Point offset, cv::Size size,
73  cv::Mat& dst);
74 
75 void drawResponse(const std::vector<cv::linemod::Template>& templates,
76  int num_modalities, cv::Mat& dst, cv::Point offset, int T);
77 
78 cv::Mat displayQuantized(const cv::Mat& quantized);
79 
80 // Copy of cv_mouse from cv_utilities
81 class Mouse
82 {
83 public:
84  static void start(const std::string& a_img_name)
85  {
86  cvSetMouseCallback(a_img_name.c_str(), Mouse::cv_on_mouse, 0);
87  }
88  static int event(void)
89  {
90  int l_event = m_event;
91  m_event = -1;
92  return l_event;
93  }
94  static int x(void)
95  {
96  return m_x;
97  }
98  static int y(void)
99  {
100  return m_y;
101  }
102 
103 private:
104  static void cv_on_mouse(int a_event, int a_x, int a_y, int, void *)
105  {
106  m_event = a_event;
107  m_x = a_x;
108  m_y = a_y;
109  }
110 
111  static int m_event;
112  static int m_x;
113  static int m_y;
114 };
115 int Mouse::m_event;
116 int Mouse::m_x;
117 int Mouse::m_y;
118 
119 static void help()
120 {
121  printf("Usage: openni_demo [templates.yml]\n\n"
122  "Place your object on a planar, featureless surface. With the mouse,\n"
123  "frame it in the 'color' window and right click to learn a first template.\n"
124  "Then press 'l' to enter online learning mode, and move the camera around.\n"
125  "When the match score falls between 90-95%% the demo will add a new template.\n\n"
126  "Keys:\n"
127  "\t h -- This help page\n"
128  "\t l -- Toggle online learning\n"
129  "\t m -- Toggle printing match result\n"
130  "\t t -- Toggle printing timings\n"
131  "\t w -- Write learned templates to disk\n"
132  "\t [ ] -- Adjust matching threshold: '[' down, ']' up\n"
133  "\t q -- Quit\n\n");
134 }
135 
136 // Adapted from cv_timer in cv_utilities
137 class Timer
138 {
139 public:
140  Timer() : start_(0), time_(0) {}
141 
142  void start()
143  {
144  start_ = cv::getTickCount();
145  }
146 
147  void stop()
148  {
149  CV_Assert(start_ != 0);
150  int64 end = cv::getTickCount();
151  time_ += end - start_;
152  start_ = 0;
153  }
154 
155  double time()
156  {
157  double ret = time_ / cv::getTickFrequency();
158  time_ = 0;
159  return ret;
160  }
161 
162 private:
163  int64 start_, time_;
164 };
165 
166 // Functions to store detector and templates in single XML/YAML file
167 static cv::Ptr<cv::linemod::Detector> readLinemod(const std::string& filename)
168 {
169  cv::Ptr<cv::linemod::Detector> detector = new cv::linemod::Detector;
170  cv::FileStorage fs(filename, cv::FileStorage::READ);
171  detector->read(fs.root());
172 
173  cv::FileNode fn = fs["classes"];
174  for (cv::FileNodeIterator i = fn.begin(), iend = fn.end(); i != iend; ++i)
175  detector->readClass(*i);
176 
177  return detector;
178 }
179 
180 static void writeLinemod(const cv::Ptr<cv::linemod::Detector>& detector, const std::string& filename)
181 {
182  cv::FileStorage fs(filename, cv::FileStorage::WRITE);
183  detector->write(fs);
184 
185  std::vector<std::string> ids = detector->classIds();
186  fs << "classes" << "[";
187  for (int i = 0; i < (int)ids.size(); ++i)
188  {
189  fs << "{";
190  detector->writeClass(ids[i], fs);
191  fs << "}"; // current class
192  }
193  fs << "]"; // classes
194 }
195 
196 // global
197 cv::Ptr<cv::linemod::Detector> detector;
198 std::string filename;
199 int num_classes = 0;
201 void callback(const sensor_msgs::Image::ConstPtr& rgb_image,
202  const sensor_msgs::Image::ConstPtr& depth_image,
203  const sensor_msgs::CameraInfo::ConstPtr& rgb_camera_info,
204  const sensor_msgs::CameraInfo::ConstPtr& depth_camera_info)
205 {
206  bool show_match_result = true;
207  bool show_timings = false;
208  bool learn_online = false;
209 
210 
212  cv::Size roi_size(200, 200);
213  int learning_lower_bound = 90;
214  int learning_upper_bound = 95;
215  // Timers
216  Timer extract_timer;
217  Timer match_timer;
218  int num_modalities = (int)detector->getModalities().size();
220  cv::Mat color = cv_rgb->image;
221  //cv_bridge::CvImagePtr cv_depth = cv_bridge::toCvCopy(depth_image, sensor_msgs::image_encodings::TYPE_32FC1);
224  //cv::Mat depth = 1000 * cv_rgb->image;
225  cv::Mat depth = cv_depth->image;
226  // Capture next color/depth pair
227  // capture.grab();
228  // capture.retrieve(depth, CV_CAP_OPENNI_DEPTH_MAP);
229  // capture.retrieve(color, CV_CAP_OPENNI_BGR_IMAGE);
230  //double focal_length = capture.get(CV_CAP_OPENNI_DEPTH_GENERATOR_FOCAL_LENGTH);
231  double focal_length = depth_camera_info->K[0]; // fx
232 
233  std::vector<cv::Mat> sources;
234  sources.push_back(color);
235  sources.push_back(depth);
236  cv::Mat display = color.clone();
237 
238  if (!learn_online)
239  {
240  cv::Point mouse(Mouse::x(), Mouse::y());
241  int event = Mouse::event();
242 
243  // Compute ROI centered on current mouse location
244  cv::Point roi_offset(roi_size.width / 2, roi_size.height / 2);
245  cv::Point pt1 = mouse - roi_offset; // top left
246  cv::Point pt2 = mouse + roi_offset; // bottom right
247 
248  if (event == CV_EVENT_RBUTTONDOWN)
249  {
250  // Compute object mask by subtracting the plane within the ROI
251  std::vector<CvPoint> chain(4);
252  chain[0] = pt1;
253  chain[1] = cv::Point(pt2.x, pt1.y);
254  chain[2] = pt2;
255  chain[3] = cv::Point(pt1.x, pt2.y);
256  cv::Mat mask;
257  subtractPlane(depth, mask, chain, focal_length);
258 
259  cv::imshow("mask", mask);
260 
261  // Extract template
262  std::string class_id = cv::format("class%d", num_classes);
263  cv::Rect bb;
264  extract_timer.start();
265  int template_id = detector->addTemplate(sources, class_id, mask, &bb);
266  extract_timer.stop();
267  if (template_id != -1)
268  {
269  printf("*** Added template (id %d) for new object class %d***\n",
270  template_id, num_classes);
271  //printf("Extracted at (%d, %d) size %dx%d\n", bb.x, bb.y, bb.width, bb.height);
272  }
273 
274  ++num_classes;
275  }
276 
277  // Draw ROI for display
278  cv::rectangle(display, pt1, pt2, CV_RGB(0,0,0), 3);
279  cv::rectangle(display, pt1, pt2, CV_RGB(255,255,0), 1);
280  }
281 
282  // Perform matching
283  std::vector<cv::linemod::Match> matches;
284  std::vector<std::string> class_ids;
285  std::vector<cv::Mat> quantized_images;
286  match_timer.start();
287  detector->match(sources, (float)matching_threshold, matches, class_ids, quantized_images);
288  match_timer.stop();
289 
290  int classes_visited = 0;
291  std::set<std::string> visited;
292 
293  for (int i = 0; (i < (int)matches.size()) && (classes_visited < num_classes); ++i)
294  {
295  cv::linemod::Match m = matches[i];
296 
297  if (visited.insert(m.class_id).second)
298  {
299  ++classes_visited;
300 
301  if (show_match_result)
302  {
303  printf("Similarity: %5.1f%%; x: %3d; y: %3d; class: %s; template: %3d\n",
304  m.similarity, m.x, m.y, m.class_id.c_str(), m.template_id);
305  }
306 
307  // Draw matching template
308  const std::vector<cv::linemod::Template>& templates = detector->getTemplates(m.class_id, m.template_id);
309  drawResponse(templates, num_modalities, display, cv::Point(m.x, m.y), detector->getT(0));
310 
311  if (learn_online == true)
312  {
315 
316  // Compute masks based on convex hull of matched template
317  cv::Mat color_mask, depth_mask;
318  std::vector<CvPoint> chain = maskFromTemplate(templates, num_modalities,
319  cv::Point(m.x, m.y), color.size(),
320  color_mask, display);
321  subtractPlane(depth, depth_mask, chain, focal_length);
322 
323  cv::imshow("mask", depth_mask);
324 
325  // If pretty sure (but not TOO sure), add new template
326  if (learning_lower_bound < m.similarity && m.similarity < learning_upper_bound)
327  {
328  extract_timer.start();
329  int template_id = detector->addTemplate(sources, m.class_id, depth_mask);
330  extract_timer.stop();
331  if (template_id != -1)
332  {
333  printf("*** Added template (id %d) for existing object class %s***\n",
334  template_id, m.class_id.c_str());
335  }
336  }
337  }
338  }
339  }
340 
341  if (show_match_result && matches.empty())
342  printf("No matches found...\n");
343  if (show_timings)
344  {
345  printf("Training: %.2fs\n", extract_timer.time());
346  printf("Matching: %.2fs\n", match_timer.time());
347  }
348  if (show_match_result || show_timings)
349  printf("------------------------------------------------------------\n");
350 
351  cv::imshow("color", display);
352  cv::imshow("normals", quantized_images[1]);
353 
354  cv::FileStorage fs;
355  char key = (char)cvWaitKey(10);
356  // if( key == 'q' )
357  // break;
358 
359  switch (key)
360  {
361  case 'h':
362  help();
363  break;
364  case 'm':
365  // toggle printing match result
366  show_match_result = !show_match_result;
367  printf("Show match result %s\n", show_match_result ? "ON" : "OFF");
368  break;
369  case 't':
370  // toggle printing timings
371  show_timings = !show_timings;
372  printf("Show timings %s\n", show_timings ? "ON" : "OFF");
373  break;
374  case 'l':
375  // toggle online learning
376  learn_online = !learn_online;
377  printf("Online learning %s\n", learn_online ? "ON" : "OFF");
378  break;
379  case '[':
380  // decrement threshold
381  matching_threshold = std::max(matching_threshold - 1, -100);
382  printf("New threshold: %d\n", matching_threshold);
383  break;
384  case ']':
385  // increment threshold
386  matching_threshold = std::min(matching_threshold + 1, +100);
387  printf("New threshold: %d\n", matching_threshold);
388  break;
389  case 'w':
390  // write model to disk
392  printf("Wrote detector and templates to %s\n", filename.c_str());
393  break;
394  default:
395  ;
396  }
397 }
398 
400  sensor_msgs::Image,
401  sensor_msgs::Image,
402  sensor_msgs::CameraInfo,
403  sensor_msgs::CameraInfo
405 
406 #endif
407 int main(int argc, char** argv)
408 {
409  ros::init(argc, argv, "linemod");
410  ROS_ERROR("linemod has been moved to opencv_contrib in OpenCV3");
411 #if CV_MAJOR_VERSION < 3
412  // Various settings and flags
413  help();
414  cv::namedWindow("color");
415  cv::namedWindow("normals");
416  Mouse::start("color");
417 
418  // Initialize LINEMOD data structures
419 
420 
421  if (argc == 1)
422  {
423  filename = "linemod_templates.yml";
424  detector = cv::linemod::getDefaultLINEMOD();
425  }
426  else
427  {
428  detector = readLinemod(argv[1]);
429 
430  std::vector<std::string> ids = detector->classIds();
431  num_classes = detector->numClasses();
432  printf("Loaded %s with %d classes and %d templates\n",
433  argv[1], num_classes, detector->numTemplates());
434  if (!ids.empty())
435  {
436  printf("Class ids:\n");
437  std::copy(ids.begin(), ids.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
438  }
439  }
440 
441  // register callback
442  ros::NodeHandle nh;
447  sub_rgb_image.subscribe(nh, "/camera/rgb/image_rect_color", 1);
448  sub_depth_image.subscribe(nh, "/camera/depth/image_rect_raw", 1);
449  sub_rgb_camera_info.subscribe(nh, "/camera/rgb/camera_info", 1);
450  sub_depth_camera_info.subscribe(nh, "/camera/depth/camera_info", 1);
452  = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(1000);
453  sync_->connectInput(sub_rgb_image, sub_depth_image,
454  sub_rgb_camera_info, sub_depth_camera_info);
455  sync_->registerCallback(callback);
456 #endif
457  ros::spin();
458 
459  //printf("Focal length = %f\n", focal_length);
460 
461  // Main loop
462  return 0;
463 }
464 
465 #if CV_MAJOR_VERSION < 3
466 static void reprojectPoints(const std::vector<cv::Point3d>& proj, std::vector<cv::Point3d>& real, double f)
467 {
468  real.resize(proj.size());
469  double f_inv = 1.0 / f;
470 
471  for (int i = 0; i < (int)proj.size(); ++i)
472  {
473  double Z = proj[i].z;
474  real[i].x = (proj[i].x - 320.) * (f_inv * Z);
475  real[i].y = (proj[i].y - 240.) * (f_inv * Z);
476  real[i].z = Z;
477  }
478 }
479 
480 static void filterPlane(IplImage * ap_depth, std::vector<IplImage *> & a_masks, std::vector<CvPoint> & a_chain, double f)
481 {
482  const int l_num_cost_pts = 200;
483 
484  float l_thres = 4;
485 
486  IplImage * lp_mask = cvCreateImage(cvGetSize(ap_depth), IPL_DEPTH_8U, 1);
487  cvSet(lp_mask, cvRealScalar(0));
488 
489  std::vector<CvPoint> l_chain_vector;
490 
491  float l_chain_length = 0;
492  float * lp_seg_length = new float[a_chain.size()];
493 
494  for (int l_i = 0; l_i < (int)a_chain.size(); ++l_i)
495  {
496  float x_diff = (float)(a_chain[(l_i + 1) % a_chain.size()].x - a_chain[l_i].x);
497  float y_diff = (float)(a_chain[(l_i + 1) % a_chain.size()].y - a_chain[l_i].y);
498  lp_seg_length[l_i] = sqrt(x_diff*x_diff + y_diff*y_diff);
499  l_chain_length += lp_seg_length[l_i];
500  }
501  for (int l_i = 0; l_i < (int)a_chain.size(); ++l_i)
502  {
503  if (lp_seg_length[l_i] > 0)
504  {
505  int l_cur_num = cvRound(l_num_cost_pts * lp_seg_length[l_i] / l_chain_length);
506  float l_cur_len = lp_seg_length[l_i] / l_cur_num;
507 
508  for (int l_j = 0; l_j < l_cur_num; ++l_j)
509  {
510  float l_ratio = (l_cur_len * l_j / lp_seg_length[l_i]);
511 
512  CvPoint l_pts;
513 
514  l_pts.x = cvRound(l_ratio * (a_chain[(l_i + 1) % a_chain.size()].x - a_chain[l_i].x) + a_chain[l_i].x);
515  l_pts.y = cvRound(l_ratio * (a_chain[(l_i + 1) % a_chain.size()].y - a_chain[l_i].y) + a_chain[l_i].y);
516 
517  l_chain_vector.push_back(l_pts);
518  }
519  }
520  }
521  std::vector<cv::Point3d> lp_src_3Dpts(l_chain_vector.size());
522 
523  for (int l_i = 0; l_i < (int)l_chain_vector.size(); ++l_i)
524  {
525  lp_src_3Dpts[l_i].x = l_chain_vector[l_i].x;
526  lp_src_3Dpts[l_i].y = l_chain_vector[l_i].y;
527  lp_src_3Dpts[l_i].z = CV_IMAGE_ELEM(ap_depth, unsigned short, cvRound(lp_src_3Dpts[l_i].y), cvRound(lp_src_3Dpts[l_i].x));
528  //CV_IMAGE_ELEM(lp_mask,unsigned char,(int)lp_src_3Dpts[l_i].Y,(int)lp_src_3Dpts[l_i].X)=255;
529  }
530  //cv_show_image(lp_mask,"hallo2");
531 
532  reprojectPoints(lp_src_3Dpts, lp_src_3Dpts, f);
533 
534  CvMat * lp_pts = cvCreateMat((int)l_chain_vector.size(), 4, CV_32F);
535  CvMat * lp_v = cvCreateMat(4, 4, CV_32F);
536  CvMat * lp_w = cvCreateMat(4, 1, CV_32F);
537 
538  for (int l_i = 0; l_i < (int)l_chain_vector.size(); ++l_i)
539  {
540  CV_MAT_ELEM(*lp_pts, float, l_i, 0) = (float)lp_src_3Dpts[l_i].x;
541  CV_MAT_ELEM(*lp_pts, float, l_i, 1) = (float)lp_src_3Dpts[l_i].y;
542  CV_MAT_ELEM(*lp_pts, float, l_i, 2) = (float)lp_src_3Dpts[l_i].z;
543  CV_MAT_ELEM(*lp_pts, float, l_i, 3) = 1.0f;
544  }
545  cvSVD(lp_pts, lp_w, 0, lp_v);
546 
547  float l_n[4] = {CV_MAT_ELEM(*lp_v, float, 0, 3),
548  CV_MAT_ELEM(*lp_v, float, 1, 3),
549  CV_MAT_ELEM(*lp_v, float, 2, 3),
550  CV_MAT_ELEM(*lp_v, float, 3, 3)};
551 
552  float l_norm = sqrt(l_n[0] * l_n[0] + l_n[1] * l_n[1] + l_n[2] * l_n[2]);
553 
554  l_n[0] /= l_norm;
555  l_n[1] /= l_norm;
556  l_n[2] /= l_norm;
557  l_n[3] /= l_norm;
558 
559  float l_max_dist = 0;
560 
561  for (int l_i = 0; l_i < (int)l_chain_vector.size(); ++l_i)
562  {
563  float l_dist = l_n[0] * CV_MAT_ELEM(*lp_pts, float, l_i, 0) +
564  l_n[1] * CV_MAT_ELEM(*lp_pts, float, l_i, 1) +
565  l_n[2] * CV_MAT_ELEM(*lp_pts, float, l_i, 2) +
566  l_n[3] * CV_MAT_ELEM(*lp_pts, float, l_i, 3);
567 
568  if (fabs(l_dist) > l_max_dist)
569  l_max_dist = l_dist;
570  }
571  //std::cerr << "plane: " << l_n[0] << ";" << l_n[1] << ";" << l_n[2] << ";" << l_n[3] << " maxdist: " << l_max_dist << " end" << std::endl;
572  int l_minx = ap_depth->width;
573  int l_miny = ap_depth->height;
574  int l_maxx = 0;
575  int l_maxy = 0;
576 
577  for (int l_i = 0; l_i < (int)a_chain.size(); ++l_i)
578  {
579  l_minx = std::min(l_minx, a_chain[l_i].x);
580  l_miny = std::min(l_miny, a_chain[l_i].y);
581  l_maxx = std::max(l_maxx, a_chain[l_i].x);
582  l_maxy = std::max(l_maxy, a_chain[l_i].y);
583  }
584  int l_w = l_maxx - l_minx + 1;
585  int l_h = l_maxy - l_miny + 1;
586  int l_nn = (int)a_chain.size();
587 
588  CvPoint * lp_chain = new CvPoint[l_nn];
589 
590  for (int l_i = 0; l_i < l_nn; ++l_i)
591  lp_chain[l_i] = a_chain[l_i];
592 
593  cvFillPoly(lp_mask, &lp_chain, &l_nn, 1, cvScalar(255, 255, 255));
594 
595  delete[] lp_chain;
596 
597  //cv_show_image(lp_mask,"hallo1");
598 
599  std::vector<cv::Point3d> lp_dst_3Dpts(l_h * l_w);
600 
601  int l_ind = 0;
602 
603  for (int l_r = 0; l_r < l_h; ++l_r)
604  {
605  for (int l_c = 0; l_c < l_w; ++l_c)
606  {
607  lp_dst_3Dpts[l_ind].x = l_c + l_minx;
608  lp_dst_3Dpts[l_ind].y = l_r + l_miny;
609  lp_dst_3Dpts[l_ind].z = CV_IMAGE_ELEM(ap_depth, unsigned short, l_r + l_miny, l_c + l_minx);
610  ++l_ind;
611  }
612  }
613  reprojectPoints(lp_dst_3Dpts, lp_dst_3Dpts, f);
614 
615  l_ind = 0;
616 
617  for (int l_r = 0; l_r < l_h; ++l_r)
618  {
619  for (int l_c = 0; l_c < l_w; ++l_c)
620  {
621  float l_dist = (float)(l_n[0] * lp_dst_3Dpts[l_ind].x + l_n[1] * lp_dst_3Dpts[l_ind].y + lp_dst_3Dpts[l_ind].z * l_n[2] + l_n[3]);
622 
623  ++l_ind;
624 
625  if (CV_IMAGE_ELEM(lp_mask, unsigned char, l_r + l_miny, l_c + l_minx) != 0)
626  {
627  if (fabs(l_dist) < std::max(l_thres, (l_max_dist * 2.0f)))
628  {
629  for (int l_p = 0; l_p < (int)a_masks.size(); ++l_p)
630  {
631  int l_col = cvRound((l_c + l_minx) / (l_p + 1.0));
632  int l_row = cvRound((l_r + l_miny) / (l_p + 1.0));
633 
634  CV_IMAGE_ELEM(a_masks[l_p], unsigned char, l_row, l_col) = 0;
635  }
636  }
637  else
638  {
639  for (int l_p = 0; l_p < (int)a_masks.size(); ++l_p)
640  {
641  int l_col = cvRound((l_c + l_minx) / (l_p + 1.0));
642  int l_row = cvRound((l_r + l_miny) / (l_p + 1.0));
643 
644  CV_IMAGE_ELEM(a_masks[l_p], unsigned char, l_row, l_col) = 255;
645  }
646  }
647  }
648  }
649  }
650  cvReleaseImage(&lp_mask);
651  cvReleaseMat(&lp_pts);
652  cvReleaseMat(&lp_w);
653  cvReleaseMat(&lp_v);
654 }
655 
656 void subtractPlane(const cv::Mat& depth, cv::Mat& mask, std::vector<CvPoint>& chain, double f)
657 {
658  mask = cv::Mat::zeros(depth.size(), CV_8U);
659  std::vector<IplImage*> tmp;
660  IplImage mask_ipl = mask;
661  tmp.push_back(&mask_ipl);
662  IplImage depth_ipl = depth;
663  filterPlane(&depth_ipl, tmp, chain, f);
664 }
665 
666 std::vector<CvPoint> maskFromTemplate(const std::vector<cv::linemod::Template>& templates,
667  int num_modalities, cv::Point offset, cv::Size size,
668  cv::Mat& mask, cv::Mat& dst)
669 {
670  templateConvexHull(templates, num_modalities, offset, size, mask);
671 
672  const int OFFSET = 30;
673  cv::dilate(mask, mask, cv::Mat(), cv::Point(-1,-1), OFFSET);
674 
675  CvMemStorage * lp_storage = cvCreateMemStorage(0);
676  CvTreeNodeIterator l_iterator;
677  CvSeqReader l_reader;
678  CvSeq * lp_contour = 0;
679 
680  cv::Mat mask_copy = mask.clone();
681  IplImage mask_copy_ipl = mask_copy;
682  cvFindContours(&mask_copy_ipl, lp_storage, &lp_contour, sizeof(CvContour),
683  CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
684 
685  std::vector<CvPoint> l_pts1; // to use as input to cv_primesensor::filter_plane
686 
687  cvInitTreeNodeIterator(&l_iterator, lp_contour, 1);
688  while ((lp_contour = (CvSeq *)cvNextTreeNode(&l_iterator)) != 0)
689  {
690  CvPoint l_pt0;
691  cvStartReadSeq(lp_contour, &l_reader, 0);
692  CV_READ_SEQ_ELEM(l_pt0, l_reader);
693  l_pts1.push_back(l_pt0);
694 
695  for (int i = 0; i < lp_contour->total; ++i)
696  {
697  CvPoint l_pt1;
698  CV_READ_SEQ_ELEM(l_pt1, l_reader);
700  cv::line(dst, l_pt0, l_pt1, CV_RGB(0, 255, 0), 2);
701 
702  l_pt0 = l_pt1;
703  l_pts1.push_back(l_pt0);
704  }
705  }
706  cvReleaseMemStorage(&lp_storage);
707 
708  return l_pts1;
709 }
710 
711 // Adapted from cv_show_angles
712 cv::Mat displayQuantized(const cv::Mat& quantized)
713 {
714  cv::Mat color(quantized.size(), CV_8UC3);
715  for (int r = 0; r < quantized.rows; ++r)
716  {
717  const uchar* quant_r = quantized.ptr(r);
718  cv::Vec3b* color_r = color.ptr<cv::Vec3b>(r);
719 
720  for (int c = 0; c < quantized.cols; ++c)
721  {
722  cv::Vec3b& bgr = color_r[c];
723  switch (quant_r[c])
724  {
725  case 0: bgr[0]= 0; bgr[1]= 0; bgr[2]= 0; break;
726  case 1: bgr[0]= 55; bgr[1]= 55; bgr[2]= 55; break;
727  case 2: bgr[0]= 80; bgr[1]= 80; bgr[2]= 80; break;
728  case 4: bgr[0]=105; bgr[1]=105; bgr[2]=105; break;
729  case 8: bgr[0]=130; bgr[1]=130; bgr[2]=130; break;
730  case 16: bgr[0]=155; bgr[1]=155; bgr[2]=155; break;
731  case 32: bgr[0]=180; bgr[1]=180; bgr[2]=180; break;
732  case 64: bgr[0]=205; bgr[1]=205; bgr[2]=205; break;
733  case 128: bgr[0]=230; bgr[1]=230; bgr[2]=230; break;
734  case 255: bgr[0]= 0; bgr[1]= 0; bgr[2]=255; break;
735  default: bgr[0]= 0; bgr[1]=255; bgr[2]= 0; break;
736  }
737  }
738  }
739 
740  return color;
741 }
742 
743 // Adapted from cv_line_template::convex_hull
744 void templateConvexHull(const std::vector<cv::linemod::Template>& templates,
745  int num_modalities, cv::Point offset, cv::Size size,
746  cv::Mat& dst)
747 {
748  std::vector<cv::Point> points;
749  for (int m = 0; m < num_modalities; ++m)
750  {
751  for (int i = 0; i < (int)templates[m].features.size(); ++i)
752  {
753  cv::linemod::Feature f = templates[m].features[i];
754  points.push_back(cv::Point(f.x, f.y) + offset);
755  }
756  }
757 
758  std::vector<cv::Point> hull;
759  cv::convexHull(points, hull);
760 
761  dst = cv::Mat::zeros(size, CV_8U);
762  const int hull_count = (int)hull.size();
763  const cv::Point* hull_pts = &hull[0];
764  cv::fillPoly(dst, &hull_pts, &hull_count, 1, cv::Scalar(255));
765 }
766 
767 void drawResponse(const std::vector<cv::linemod::Template>& templates,
768  int num_modalities, cv::Mat& dst, cv::Point offset, int T)
769 {
770  static const cv::Scalar COLORS[5] = { CV_RGB(0, 0, 255),
771  CV_RGB(0, 255, 0),
772  CV_RGB(255, 255, 0),
773  CV_RGB(255, 140, 0),
774  CV_RGB(255, 0, 0) };
775 
776  for (int m = 0; m < num_modalities; ++m)
777  {
778  // NOTE: Original demo recalculated max response for each feature in the TxT
779  // box around it and chose the display color based on that response. Here
780  // the display color just depends on the modality.
781  cv::Scalar color = COLORS[m];
782 
783  for (int i = 0; i < (int)templates[m].features.size(); ++i)
784  {
785  cv::linemod::Feature f = templates[m].features[i];
786  cv::Point pt(f.x + offset.x, f.y + offset.y);
787  cv::circle(dst, pt, T / 2, color);
788  }
789  }
790 }
791 #endif
static void cv_on_mouse(int a_event, int a_x, int a_y, int, void *)
Definition: linemod.cpp:104
f
int64 time_
Definition: linemod.cpp:163
int num_classes
Definition: linemod.cpp:199
cv::Ptr< cv::linemod::Detector > detector
Definition: linemod.cpp:197
void subtractPlane(const cv::Mat &depth, cv::Mat &mask, std::vector< CvPoint > &chain, double f)
Definition: linemod.cpp:656
std::vector< CvPoint > maskFromTemplate(const std::vector< cv::linemod::Template > &templates, int num_modalities, cv::Point offset, cv::Size size, cv::Mat &mask, cv::Mat &dst)
Definition: linemod.cpp:666
end
int matching_threshold
Definition: linemod.cpp:200
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
static int x(void)
Definition: linemod.cpp:94
int main(int argc, char **argv)
Definition: linemod.cpp:407
static int m_y
Definition: linemod.cpp:113
tmp
message_filters::sync_policies::ApproximateTime< sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::CameraInfo > SyncPolicy
Definition: linemod.cpp:404
ROSCPP_DECL void spin(Spinner &spinner)
static int m_x
Definition: linemod.cpp:112
float
double sqrt()
void templateConvexHull(const std::vector< cv::linemod::Template > &templates, int num_modalities, cv::Point offset, cv::Size size, cv::Mat &dst)
Definition: linemod.cpp:744
Timer()
Definition: linemod.cpp:140
CvImagePtr toCvCopy(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
const std::string TYPE_16UC1
static void filterPlane(IplImage *ap_depth, std::vector< IplImage * > &a_masks, std::vector< CvPoint > &a_chain, double f)
Definition: linemod.cpp:480
void start()
Definition: linemod.cpp:142
std::string filename
Definition: linemod.cpp:198
static cv::Ptr< cv::linemod::Detector > readLinemod(const std::string &filename)
Definition: linemod.cpp:167
static void reprojectPoints(const std::vector< cv::Point3d > &proj, std::vector< cv::Point3d > &real, double f)
Definition: linemod.cpp:466
Z
void subscribe(ros::NodeHandle &nh, const std::string &topic, uint32_t queue_size, const ros::TransportHints &transport_hints=ros::TransportHints(), ros::CallbackQueueInterface *callback_queue=0)
void callback(const sensor_msgs::Image::ConstPtr &rgb_image, const sensor_msgs::Image::ConstPtr &depth_image, const sensor_msgs::CameraInfo::ConstPtr &rgb_camera_info, const sensor_msgs::CameraInfo::ConstPtr &depth_camera_info)
Definition: linemod.cpp:201
static void help()
Definition: linemod.cpp:119
static int event(void)
Definition: linemod.cpp:88
static int y(void)
Definition: linemod.cpp:98
c
static void start(const std::string &a_img_name)
Definition: linemod.cpp:84
double time()
Definition: linemod.cpp:155
r
cv::Mat displayQuantized(const cv::Mat &quantized)
Definition: linemod.cpp:712
void drawResponse(const std::vector< cv::linemod::Template > &templates, int num_modalities, cv::Mat &dst, cv::Point offset, int T)
Definition: linemod.cpp:767
static void writeLinemod(const cv::Ptr< cv::linemod::Detector > &detector, const std::string &filename)
Definition: linemod.cpp:180
void stop()
Definition: linemod.cpp:147
#define ROS_ERROR(...)
static int m_event
Definition: linemod.cpp:111
z


jsk_perception
Author(s): Manabu Saito, Ryohei Ueda
autogenerated on Mon May 3 2021 03:03:27