point_pose_extractor.h
Go to the documentation of this file.
1 // -*- mode: c++ -*-
2 /*********************************************************************
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2015, 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/or 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 #ifndef JSK_PERCEPTION_POINT_POSE_EXTRACTOR_H_
36 #define JSK_PERCEPTION_POINT_POSE_EXTRACTOR_H_
37 
38 #include <jsk_topic_tools/diagnostic_nodelet.h>
39 #include <ros/ros.h>
40 #include <rospack/rospack.h>
41 #include <cv_bridge/cv_bridge.h>
42 #if ( CV_MAJOR_VERSION >= 4)
43 #include <opencv2/opencv.hpp>
44 #include <opencv2/highgui/highgui_c.h>
45 #include <opencv2/calib3d/calib3d_c.h>
46 #else
47 #include <opencv/highgui.h>
48 #include <opencv/cv.hpp>
49 #endif
50 #include <posedetection_msgs/Feature0DDetect.h>
51 #include <posedetection_msgs/ImageFeature0D.h>
52 #include <posedetection_msgs/ObjectDetection.h>
53 #include <posedetection_msgs/Object6DPose.h>
54 #include <geometry_msgs/PoseStamped.h>
55 #include <geometry_msgs/Pose.h>
56 #include <geometry_msgs/Quaternion.h>
60 #include <tf/tf.h>
62 #include <boost/shared_ptr.hpp>
63 #include <boost/foreach.hpp>
64 #include <boost/filesystem.hpp>
65 #include <vector>
66 #include <sstream>
67 #include <iostream>
68 #include <dynamic_reconfigure/server.h>
69 #include <jsk_perception/point_pose_extractorConfig.h>
70 #include <jsk_perception/SetTemplate.h>
71 
73 
74 void features2keypoint (posedetection_msgs::Feature0D features,
75  std::vector<cv::KeyPoint>& keypoints,
76  cv::Mat& descriptors){
77  keypoints.resize(features.scales.size());
78  descriptors.create(features.scales.size(),features.descriptor_dim,CV_32FC1);
79  std::vector<cv::KeyPoint>::iterator keypoint_it = keypoints.begin();
80  for ( int i=0; keypoint_it != keypoints.end(); ++keypoint_it, ++i ) {
81  *keypoint_it = cv::KeyPoint(cv::Point2f(features.positions[i*2+0],
82  features.positions[i*2+1]),
83  features.descriptor_dim, // size
84  features.orientations[i], //angle
85  0, // resonse
86  features.scales[i] // octave
87  );
88  for (int j = 0; j < features.descriptor_dim; j++){
89  descriptors.at<float>(i,j) =
90  features.descriptors[i*features.descriptor_dim+j];
91  }
92  }
93 }
94 
95 
97 {
98 public:
99  std::string _matching_frame;
100  cv::Mat _template_img;
101  std::vector<cv::KeyPoint> _template_keypoints;
105  double _template_width; // width of template [m]
106  double _template_height; // height of template [m]
108  cv::Mat _affine_matrix;
109  std::string _window_name;
110  // The maximum allowed reprojection error to treat a point pair as an inlier
112  // threshold on squared ratio of distances between NN and 2nd NN
114  std::vector<cv::Point2d> _correspondances;
116 
118  }
119  Matching_Template(cv::Mat img,
120  std::string matching_frame,
121  int original_width_size,
122  int original_height_size,
123  double template_width,
124  double template_height,
125  tf::Transform relativepose,
126  cv::Mat affine_matrix,
127  double reprojection_threshold,
128  double distanceratio_threshold,
129  std::string window_name,
130  bool autosize){
131 
132  _template_img = img.clone();
133  _matching_frame = matching_frame;
134  _original_width_size = original_width_size;
135  _original_height_size = original_height_size;
136  _template_width = template_width;
137  _template_height = template_height;
138  _relativepose = relativepose;
139  _affine_matrix = affine_matrix;
140  _window_name = window_name;
141  _reprojection_threshold = reprojection_threshold;
142  _distanceratio_threshold = distanceratio_threshold;
143  _template_keypoints.clear();
144  _correspondances.clear();
145  // cv::namedWindow(_window_name, autosize ? CV_WINDOW_AUTOSIZE : 0);
146  }
147 
148 
150  std::cerr << "delete " << _window_name << std::endl;
151  }
152 
153 
154  std::string get_window_name(){
155  return _window_name;
156  }
157 
158  std::vector<cv::Point2d>* correspondances(){
159  return &_correspondances;
160  }
161 
162  bool check_template (){
163  if (_template_img.empty() && _template_keypoints.size() == 0 &&
164  _template_descriptors.empty()){
165  return false;
166  }
167  else {
168  return true;
169  }
170  }
171 
172 
174  posedetection_msgs::Feature0DDetect srv;
175 
176  if ( _template_img.empty()) {
177  ROS_ERROR ("template picture is empty.");
178  return -1;
179  }
180  ROS_INFO_STREAM("read template image and call " << client.getService() << " service");
181  cv_bridge::CvImage cv_img;
182  cv_img.image = cv::Mat(_template_img);
183  cv_img.encoding = std::string("bgr8");
184  srv.request.image = *(cv_img.toImageMsg());
185  if (client.call(srv)) {
186  ROS_INFO_STREAM("get features with " << srv.response.features.scales.size() << " descriptoins");
188 
189  // inverse affine translation
190  cv::Mat M_inv;
191  cv::Mat dst;
192  cv::invert(_affine_matrix, M_inv);
193  // cv::drawKeypoints (tmp, _template_keypoints, dst, cv::Scalar::all(1), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
194  // cv::drawKeypoints (tmp, _template_keypoints, dst);
195  // cv::warpPerspective(_template_img, dst, M_inv,
196  // cv::Size(_original_width_size, _original_height_size),
197  // CV_INTER_LINEAR, IPL_BORDER_CONSTANT, 0);
198  for (int i = 0; i < (int)_template_keypoints.size(); i++){
199  cv::Point2f pt;
200  cv::Mat pt_mat(cv::Size(1,1), CV_32FC2, &pt);
201  cv::Mat pt_src_mat(cv::Size(1,1), CV_32FC2, &_template_keypoints.at(i).pt);
202  cv::perspectiveTransform (pt_src_mat, pt_mat, M_inv);
203  _template_keypoints.at(i).pt = pt_mat.at<cv::Point2f>(0,0);
204  }
205  // cvSetMouseCallback (_window_name.c_str(), &PointPoseExtractor::cvmousecb, this);
206  // _template_img = dst;
207  return 0;
208  } else {
209  ROS_ERROR("Failed to call service Feature0DDetect");
210  return 1;
211  }
212  }
213 
214 
215  double log_fac( int n )
216  {
217  static std::vector<double> slog_table;
218  int osize = slog_table.size();
219  if(osize <= n){
220  slog_table.resize(n+1);
221  if(osize == 0){
222  slog_table[0] = -1;
223  slog_table[1] = log(1.0);
224  osize = 2;
225  }
226  for(int i = osize; i <= n; i++ ){
227  slog_table[i] = slog_table[i-1] + log(i);
228  }
229  }
230  return slog_table[n];
231  }
232 
233  int min_inlier( int n, int m, double p_badsupp, double p_badxform )
234  {
235  double pi, sum;
236  int i, j;
237  double lp_badsupp = log( p_badsupp );
238  double lp_badsupp1 = log( 1.0 - p_badsupp );
239  for( j = m+1; j <= n; j++ ){
240  sum = 0;
241  for( i = j; i <= n; i++ ){
242  pi = (i-m) * lp_badsupp + (n-i+m) * lp_badsupp1 +
243  log_fac( n - m ) - log_fac( i - m ) - log_fac( n - i );
244  sum += exp( pi );
245  }
246  if( sum < p_badxform )
247  break;
248  }
249  return j;
250  }
251 
252 
253  bool estimate_od (ros::ServiceClient client, cv::Mat src_img,
254  std::vector<cv::KeyPoint> sourceimg_keypoints,
256  double err_thr, cv::Mat &stack_img,
257  cv::flann::Index* ft, posedetection_msgs::Object6DPose* o6p){
258 
259  if ( _template_keypoints.size()== 0 &&
260  _template_descriptors.empty() ){
262  }
263  if ( _template_keypoints.size()== 0 &&
264  _template_descriptors.empty() ) {
265  ROS_ERROR ("Template image was not set.");
266  return false;
267  }
268  // stacked image
269  cv::Size stack_size = cv::Size(MAX(src_img.cols,_template_img.cols),
270  src_img.rows+_template_img.rows);
271  stack_img = cv::Mat(stack_size,CV_8UC3);
272  stack_img = cv::Scalar(0);
273  cv::Mat stack_img_tmp(stack_img,cv::Rect(0,0,_template_img.cols,_template_img.rows));
274  cv::add(stack_img_tmp, _template_img, stack_img_tmp);
275  cv::Mat stack_img_src(stack_img,cv::Rect(0,_template_img.rows,src_img.cols,src_img.rows));
276  cv::add(stack_img_src, src_img, stack_img_src);
277  _previous_stack_img = stack_img.clone();
278 
279  // matching
280  cv::Mat m_indices(_template_descriptors.rows, 2, CV_32S);
281  cv::Mat m_dists(_template_descriptors.rows, 2, CV_32F);
282  ft->knnSearch(_template_descriptors, m_indices, m_dists, 2, cv::flann::SearchParams(-1) );
283 
284  // matched points
285  std::vector<cv::Point2f> pt1, pt2;
286  std::vector<int> queryIdxs,trainIdxs;
287  for ( unsigned int j = 0; j < _template_keypoints.size(); j++ ) {
288  if ( m_dists.at<float>(j,0) < m_dists.at<float>(j,1) * _distanceratio_threshold) {
289  queryIdxs.push_back(j);
290  trainIdxs.push_back(m_indices.at<int>(j,0));
291  }
292  }
293  if ( queryIdxs.size() == 0 ) {
294  ROS_WARN_STREAM("could not find matched points with distanceratio(" <<_distanceratio_threshold << ")");
295  } else {
297  cv::KeyPoint::convert(sourceimg_keypoints,pt2,trainIdxs);
298  }
299 
300  ROS_INFO ("Found %d total matches among %d template keypoints", (int)pt2.size(), (int)_template_keypoints.size());
301 
302  cv::Mat H;
303  std::vector<uchar> mask((int)pt2.size());
304 
305  if ( pt1.size() > 4 ) {
306  // ToDO for curve face
307  H = cv::findHomography(cv::Mat(pt1), cv::Mat(pt2), mask, CV_RANSAC, _reprojection_threshold);
308  }
309 
310  // draw line
311  for (int j = 0; j < (int)pt1.size(); j++){
312  cv::Point2f pt, pt_orig;
313  cv::Mat pt_mat(cv::Size(1,1), CV_32FC2, &pt);
314  cv::Mat pt_src_mat(cv::Size(1,1), CV_32FC2, &pt1.at(j));
315  cv::perspectiveTransform (pt_src_mat, pt_mat, _affine_matrix);
316  pt_orig = pt_mat.at<cv::Point2f>(0,0);
317  if ( mask.at(j)){
318  cv::line(stack_img, pt_orig, pt2.at(j)+cv::Point2f(0,_template_img.rows),
319  CV_RGB(0,255,0), 1,8,0);
320  }
321  else {
322  cv::line(stack_img, pt_orig, pt2.at(j)+cv::Point2f(0,_template_img.rows),
323  CV_RGB(255,0,255), 1,8,0);
324  }
325  }
326  int inlier_sum = 0;
327  for (int k=0; k < (int)mask.size(); k++){
328  inlier_sum += (int)mask.at(k);
329  }
330 
331  double text_scale = 1.5;
332  {
333  int fontFace = 0, thickness = 0, baseLine;
334  int x, y;
335  cv::Size text_size;
336  std::string text;
337 
338  text = "inlier: " + boost::lexical_cast<std::string>((int)inlier_sum) + " / " + boost::lexical_cast<std::string>((int)pt2.size());
339  text_size = cv::getTextSize(text, fontFace, text_scale, thickness, &baseLine);
340  x = stack_img.size().width - text_size.width;
341  y = text_size.height + thickness + 10; // 10pt pading
342  cv::putText (stack_img, text, cv::Point(x, y),
343  fontFace, text_scale, CV_RGB(0, 255, 0),
344  thickness, 8, false);
345 
346  text = "template: " + boost::lexical_cast<std::string>((int)_template_keypoints.size());
347  text_size = cv::getTextSize(text, fontFace, text_scale, thickness, &baseLine);
348  x = stack_img.size().width - text_size.width;
349  y += text_size.height + thickness + 10; // 10pt pading
350  cv::putText (stack_img, text, cv::Point(x, y),
351  fontFace, text_scale, CV_RGB(0, 255, 0),
352  thickness, 8, false);
353  }
354 
355  // draw correspondances
356  ROS_INFO(" _correspondances.size: %d", (int)_correspondances.size());
357  for (int j = 0; j < (int)_correspondances.size(); j++){
358  cv::circle(stack_img, cv::Point2f(_correspondances.at(j).x, _correspondances.at(j).y + _template_img.size().height),
359  8, CV_RGB(255,0,0), -1);
360  }
361 
362  ROS_INFO(" inlier_sum:%d min_lier:%d", inlier_sum, min_inlier((int)pt2.size(), 4, 0.10, 0.01));
363  if ((cv::countNonZero( H ) == 0) || (inlier_sum < min_inlier((int)pt2.size(), 4, 0.10, 0.01))){
364  ROS_INFO(" inlier_sum < min_lier return-from estimate-od");
365  if( _window_name != "" )
366  cv::imshow(_window_name, stack_img);
367  return false;
368  }
369 
370  std::string _type;
371  char chr[20];
372 
373  // number of match points
374  sprintf(chr, "%d", (int)pt2.size());
375  _type = _matching_frame + "_" + std::string(chr);
376 
377  sprintf(chr, "%d", inlier_sum);
378  _type = _type + "_" + std::string(chr);
379 
380  cv::Point2f corners2d[4] = {cv::Point2f(0,0),
381  cv::Point2f(_original_width_size,0),
383  cv::Point2f(0,_original_height_size)};
384  cv::Mat corners2d_mat (cv::Size(4, 1), CV_32FC2, corners2d);
385  cv::Point3f corners3d[4] = {cv::Point3f(0,0,0),
386  cv::Point3f(0,_template_width,0),
387  cv::Point3f(_template_height,_template_width,0),
388  cv::Point3f(_template_height,0,0)};
389  cv::Mat corners3d_mat (cv::Size(4, 1), CV_32FC3, corners3d);
390 
391  cv::Mat corners2d_mat_trans;
392 
393  cv::perspectiveTransform (corners2d_mat, corners2d_mat_trans, H);
394 
395  double fR3[3], fT3[3];
396  cv::Mat rvec(3, 1, CV_64FC1, fR3);
397  cv::Mat tvec(3, 1, CV_64FC1, fT3);
398  cv::Mat zero_distortion_mat = cv::Mat::zeros(4, 1, CV_64FC1);
399 
400  cv::solvePnP (corners3d_mat, corners2d_mat_trans,
401  pcam.intrinsicMatrix(),
402  zero_distortion_mat,//if unrectified: pcam.distortionCoeffs()
403  rvec, tvec);
404 
405  tf::Transform checktf, resulttf;
406 
407  checktf.setOrigin( tf::Vector3(fT3[0], fT3[1], fT3[2] ) );
408 
409  double rx = fR3[0], ry = fR3[1], rz = fR3[2];
410  tf::Quaternion quat;
411  double angle = cv::norm(rvec);
412  quat.setRotation(tf::Vector3(rx/angle, ry/angle, rz/angle), angle);
413  checktf.setRotation( quat );
414 
415  resulttf = checktf * _relativepose;
416 
417  ROS_INFO( " tx: (%0.2lf,%0.2lf,%0.2lf) rx: (%0.2lf,%0.2lf,%0.2lf)",
418  resulttf.getOrigin().getX(),
419  resulttf.getOrigin().getY(),
420  resulttf.getOrigin().getZ(),
421  resulttf.getRotation().getAxis().x() * resulttf.getRotation().getAngle(),
422  resulttf.getRotation().getAxis().y() * resulttf.getRotation().getAngle(),
423  resulttf.getRotation().getAxis().z() * resulttf.getRotation().getAngle());
424 
425  o6p->pose.position.x = resulttf.getOrigin().getX();
426  o6p->pose.position.y = resulttf.getOrigin().getY();
427  o6p->pose.position.z = resulttf.getOrigin().getZ();
428  o6p->pose.orientation.w = resulttf.getRotation().w();
429  o6p->pose.orientation.x = resulttf.getRotation().x();
430  o6p->pose.orientation.y = resulttf.getRotation().y();
431  o6p->pose.orientation.z = resulttf.getRotation().z();
432  o6p->type = _matching_frame; // _type
433 
434  // draw 3d cube model
435  std::vector<cv::Point2f> projected_top;
436  {
437  tf::Vector3 coords[8] = {tf::Vector3(0,0,0),
438  tf::Vector3(0, _template_width, 0),
439  tf::Vector3(_template_height, _template_width,0),
440  tf::Vector3(_template_height, 0, 0),
441  tf::Vector3(0, 0, -0.03),
442  tf::Vector3(0, _template_width, -0.03),
443  tf::Vector3(_template_height, _template_width, -0.03),
444  tf::Vector3(_template_height, 0, -0.03)};
445 
446  projected_top = std::vector<cv::Point2f>(8);
447 
448  for(int i=0; i<8; i++) {
449  coords[i] = checktf * coords[i];
450  cv::Point3f pt(coords[i].getX(), coords[i].getY(), coords[i].getZ());
451  projected_top[i] = pcam.project3dToPixel(pt);
452  }
453  }
454 
455  { // check if the matched region does not too big or too small
456  float max_x, max_y, min_x, min_y;
457  max_x = max_y = -1e9;
458  min_x = min_y = 1e9;
459  for (int j = 0; j < 4; j++){
460  cv::Point2f pt = corners2d_mat_trans.at<cv::Point2f>(0,j);
461  max_x = std::max(max_x, pt.x), max_y = std::max(max_y, pt.y);
462  min_x = std::min(min_x, pt.x), min_y = std::min(min_y, pt.y);
463  }
464  if((max_x - min_x) < 30 || (max_y - min_y) < 30 ||
465  src_img.rows < (max_x - min_x)/2 || src_img.cols < (max_y - min_y)/2){
466  ROS_INFO(" matched region is too big or small (2< && <30) width:%f height:%f return-from estimate-od", max_x - min_x, max_y - min_y);
467  return false;
468  }
469  }
470 
471  double err_sum = 0;
472  bool err_success = true;
473  for (int j = 0; j < 4; j++){
474  double err = sqrt(pow((corners2d_mat_trans.at<cv::Point2f>(0,j).x - projected_top.at(j).x), 2) +
475  pow((corners2d_mat_trans.at<cv::Point2f>(0,j).y - projected_top.at(j).y), 2));
476  err_sum += err;
477  }
478  if (err_sum > err_thr){
479  ROS_INFO(" err_sum:%f > err_thr:%f return-from estimate-od", err_sum, err_thr);
480  err_success = false;
481  } else {
482  o6p->reliability = 1.0 - (err_sum / err_thr);
483  }
484  // draw lines around the detected object
485  for (int j = 0; j < corners2d_mat_trans.cols; j++){
486  cv::Point2f p1(corners2d_mat_trans.at<cv::Point2f>(0,j).x,
487  corners2d_mat_trans.at<cv::Point2f>(0,j).y+_template_img.rows);
488  cv::Point2f p2(corners2d_mat_trans.at<cv::Point2f>(0,(j+1)%corners2d_mat_trans.cols).x,
489  corners2d_mat_trans.at<cv::Point2f>(0,(j+1)%corners2d_mat_trans.cols).y+_template_img.rows);
490  cv::line (stack_img, p1, p2, CV_RGB(255, 0, 0),
491  (err_success?4:1), // width
492  CV_AA, 0);
493  }
494 
495  // draw 3d cube model
496  if(projected_top.size() == 8) { // verify, the size is 8
497  int cnt = 8;
498  std::vector<cv::Point2f> ps(cnt);
499  for(int i=0; i<cnt; i++)
500  ps[i] = cv::Point2f(projected_top[i].x,
501  projected_top[i].y+_template_img.rows);
502 
503  int draw_width = ( err_success ? 3 : 1);
504  for(int i=0; i<4; i++) {
505  cv::line (stack_img, ps[i], ps[(i+1)%4], CV_RGB(0, 0, 255), draw_width, CV_AA, 0);
506  cv::line (stack_img, ps[i+4], ps[(i+1)%4+4], CV_RGB(0, 0, 255), draw_width, CV_AA, 0);
507  cv::line (stack_img, ps[i], ps[i+4], CV_RGB(0, 0, 255), draw_width, CV_AA, 0);
508  }
509  }
510 
511  // draw coords
512  if ( err_success )
513  {
514  tf::Vector3 coords[4] = { tf::Vector3(0,0,0),
515  tf::Vector3(0.05,0,0),
516  tf::Vector3(0,0.05,0),
517  tf::Vector3(0,0,0.05)};
518  std::vector<cv::Point2f> ps(4);
519 
520  for(int i=0; i<4; i++) {
521  coords[i] = resulttf * coords[i];
522  cv::Point3f pt(coords[i].getX(), coords[i].getY(), coords[i].getZ());
523  ps[i] = pcam.project3dToPixel(pt);
524  ps[i].y += _template_img.rows; // draw on camera image
525  }
526 
527  cv::line (stack_img, ps[0], ps[1], CV_RGB(255, 0, 0), 3, CV_AA, 0);
528  cv::line (stack_img, ps[0], ps[2], CV_RGB(0, 255, 0), 3, CV_AA, 0);
529  cv::line (stack_img, ps[0], ps[3], CV_RGB(0, 0, 255), 3, CV_AA, 0);
530  }
531 
532  // write text on image
533  {
534  std::string text;
535  int x, y;
536  text = "error: " + boost::lexical_cast<std::string>(err_sum);
537  x = stack_img.size().width - 16*17*text_scale; // 16pt * 17
538  y = _template_img.size().height - (16 + 2)*text_scale*6;
539  cv::putText (stack_img, text, cv::Point(x, y),
540  0, text_scale, CV_RGB(0, 255, 0),
541  2, 8, false);
542  ROS_INFO(" %s < %f (threshold)", text.c_str(), err_thr );
543  }
544  // for debug window
545  if( _window_name != "" )
546  cv::imshow(_window_name, stack_img);
547 
548  return err_success;
549  }
550 }; // the end of difinition of class Matching_Template
551 
552 
553 namespace jsk_perception
554 {
555 
556  class PointPoseExtractor: public jsk_topic_tools::DiagnosticNodelet
557  {
558  public:
559  std::vector<Matching_Template *> _templates;
560  typedef jsk_perception::point_pose_extractorConfig Config;
561  PointPoseExtractor() : DiagnosticNodelet("PointPoseExtractor") {}
562  virtual ~PointPoseExtractor();
563  protected:
575  double _th_step;
576  double _phi_step;
577  bool _autosize;
578  double _err_thr;
580  bool pnod;
582  bool _viewer;
584  std::string _child_frame_id;
585 
586  virtual void initialize ();
587  virtual cv::Mat make_homography(cv::Mat src, cv::Mat rvec, cv::Mat tvec,
588  double template_width, double template_height, cv::Size &size);
589  virtual int make_warped_images (cv::Mat src, std::vector<cv::Mat> &imgs,
590  std::vector<cv:: Mat> &Mvec,
591  double template_width, double template_height,
592  double th_step, double phi_step);
593  virtual bool add_new_template(cv::Mat img, std::string typestr, tf::Transform relative_pose,
594  double template_width, double template_height,
595  double theta_step, double phi_step);
596  virtual bool settemplate_cb (jsk_perception::SetTemplate::Request &req,
597  jsk_perception::SetTemplate::Response &res);
598  virtual void imagefeature_cb (const posedetection_msgs::ImageFeature0DConstPtr& msg);
599  virtual void onInit();
600  virtual void subscribe();
601  virtual void unsubscribe();
602  virtual void dyn_conf_callback(Config &config, uint32_t level);
603 
604  static void cvmousecb (int event, int x, int y, int flags, void* param){
605  PointPoseExtractor* ppe = static_cast<PointPoseExtractor*>(param);
606  Matching_Template *mt = ppe->_templates.back();
607  // std::cerr << "mousecb_ -> " << mt << std::endl;
608  switch (event){
609  case CV_EVENT_LBUTTONUP: {
610  cv::Point2d pt(x,y - (int)mt->_template_img.size().height);
611  ROS_INFO("add correspondence (%d, %d)", (int)pt.x, (int)pt.y);
612  mt->_correspondances.push_back(pt);
613  if ((int)mt->_correspondances.size() >= 4){
615  mt->_correspondances.clear();
616  ROS_INFO("reset");
617  }
618  break;
619  }
620  case CV_EVENT_RBUTTONUP: {
621  mt->_correspondances.clear();
622  ROS_INFO("reset");
623  break;
624  }
625  }
626  }
628  Matching_Template *mt = ppe->_templates.back();
629  cv::Mat H;
630  cv::Mat tmp_template, tmp_warp_template;
631  std::vector<cv::Point2f>pt1, pt2;
632  double width, height;
633  std::string filename;
634  std::cout << "input template's [width]" << std::endl;
635  std::cin >> width;
636  std::cout << "input template's [height]" << std::endl;
637  std::cin >> height;
638  std::cout << "input template's [filename]" << std::endl;
639  std::cin >> filename;
640 
641  for (int i = 0; i < 4; i++){
642  pt1.push_back(cv::Point2d((int)mt->_correspondances.at(i).x,
643  (int)mt->_correspondances.at(i).y + mt->_template_img.size().height));
644  }
645  cv::Rect rect = cv::boundingRect(cv::Mat(pt1));
646  double scale = std::max(width, height) / 500.0;
647  int iwidth = width / scale, iheight = height / scale;
648  pt2.push_back(cv::Point2d(0,0));
649  pt2.push_back(cv::Point2d(iwidth,0));
650  pt2.push_back(cv::Point2d(iwidth,iheight));
651  pt2.push_back(cv::Point2d(0, iheight));
652  H = cv::findHomography(cv::Mat(pt1), cv::Mat(pt2));
653 
654  cv::getRectSubPix(mt->_previous_stack_img, rect.size(),
655  cv::Point2f((rect.tl().x + rect.br().x)/2.0,(rect.tl().y + rect.br().y)/2.0),
656  tmp_template);
657  cv::warpPerspective(mt->_previous_stack_img, tmp_warp_template, H, cv::Size(iwidth, iheight));
658 
659  try {
660  cv::imwrite(filename,tmp_template);
661  boost::filesystem::path fname(filename);
662  std::stringstream ss;
663  ss << (fname.parent_path() / fname.stem()).c_str() << "_wrap" << fname.extension().c_str();
664  cv::imwrite(ss.str(),tmp_warp_template);
665  }catch (cv::Exception e) {
666  std::cerr << e.what() << std::endl;
667  }
668 
669  for (int i = 0; i < (int)pt1.size(); i++){
670  pt2.push_back(cv::Point2d((int)pt1.at(i).x - rect.x,
671  (int)pt1.at(i).y - rect.y - mt->_template_img.size().height));
672  }
673  // cv::Mat mask_img = cv::Mat::zeros(tmp_template.size(), CV_8UC3);
674  // cv::fillConvexPoly(mask_img, pt2.begin(), (int)pt2.size(), CV_RGB(255, 255, 255));
675 
676  // cv::namedWindow("hoge", 1);
677  // cv::imshow("hoge", mask_img);
678 
679  cv::Mat M = (cv::Mat_<double>(3,3) << 1,0,0, 0,1,0, 0,0,1);
680  std::string window_name = "sample" + boost::lexical_cast<std::string>((int)ppe->_templates.size());
681 
682  Matching_Template* tmplt =
683  new Matching_Template (tmp_warp_template, "sample",
684  tmp_warp_template.size().width, tmp_warp_template.size().height,
685  width, height,
686  tf::Transform(tf::Quaternion(0, 0, 0, 1), tf::Vector3(0, 0, 0)),
687  M,
690  ppe->_first_sample_change ? window_name : mt->_window_name,
691  cv::getWindowProperty(mt->_window_name, CV_WND_PROP_AUTOSIZE));
692 
693  mt->_correspondances.clear();
694  ppe->_templates.push_back(tmplt);
695  cv::namedWindow(ppe->_first_sample_change ? window_name : mt->_window_name,
696  cv::getWindowProperty(mt->_window_name, CV_WND_PROP_AUTOSIZE));
697  cvSetMouseCallback (ppe->_first_sample_change ? window_name.c_str() : mt->_window_name.c_str(),
698  &cvmousecb, ppe);
699  ppe->_first_sample_change = true;
700  }
701  private:
702  };
703 }
704 
705 
706 #endif
tf::Transform::getRotation
Quaternion getRotation() const
jsk_perception::PointPoseExtractor::_server
ros::ServiceServer _server
Definition: point_pose_extractor.h:567
sensor_msgs::image_encodings
x
x
sum
T sum(T *pf, int length)
jsk_perception::PointPoseExtractor::make_template_from_mousecb
static void make_template_from_mousecb(PointPoseExtractor *ppe)
Definition: point_pose_extractor.h:627
ros::Publisher
image_encodings.h
image_transport::ImageTransport
jsk_perception::PointPoseExtractor::_err_thr
double _err_thr
Definition: point_pose_extractor.h:578
Matching_Template::get_window_name
std::string get_window_name()
Definition: point_pose_extractor.h:154
jsk_perception::PointPoseExtractor::_debug_pub
image_transport::Publisher _debug_pub
Definition: point_pose_extractor.h:571
i
int i
jsk_perception::PointPoseExtractor::initialize
virtual void initialize()
Definition: point_pose_extractor.cpp:79
image_geometry::PinholeCameraModel::intrinsicMatrix
const cv::Matx33d & intrinsicMatrix() const
node_scripts.paper_finder.angle
def angle(pt1, pt2, pt0)
Definition: paper_finder.py:82
cv_bridge::CvImage::toImageMsg
sensor_msgs::ImagePtr toImageMsg() const
jsk_perception::PointPoseExtractor::make_warped_images
virtual int make_warped_images(cv::Mat src, std::vector< cv::Mat > &imgs, std::vector< cv::Mat > &Mvec, double template_width, double template_height, double th_step, double phi_step)
Definition: point_pose_extractor.cpp:193
jsk_perception::PointPoseExtractor::PointPoseExtractor
PointPoseExtractor()
Definition: point_pose_extractor.h:561
jsk_perception::PointPoseExtractor::~PointPoseExtractor
virtual ~PointPoseExtractor()
Definition: point_pose_extractor.cpp:72
Matching_Template::log_fac
double log_fac(int n)
Definition: point_pose_extractor.h:215
Matching_Template::_original_height_size
int _original_height_size
Definition: point_pose_extractor.h:104
pinhole_camera_model.h
ssd_train_dataset.int
int
Definition: ssd_train_dataset.py:175
jsk_perception::PointPoseExtractor::_pub_agg
ros::Publisher _pub_agg
Definition: point_pose_extractor.h:569
Matching_Template
Definition: point_pose_extractor.h:96
ros.h
jsk_perception::PointPoseExtractor::_first_sample_change
bool _first_sample_change
Definition: point_pose_extractor.h:572
Matching_Template::_affine_matrix
cv::Mat _affine_matrix
Definition: point_pose_extractor.h:108
jsk_perception::PointPoseExtractor
Definition: point_pose_extractor.h:556
jsk_perception::PointPoseExtractor::_th_step
double _th_step
Definition: point_pose_extractor.h:575
Matching_Template::set_template
int set_template(ros::ServiceClient client)
Definition: point_pose_extractor.h:173
Matching_Template::_original_width_size
int _original_width_size
Definition: point_pose_extractor.h:103
jsk_perception::PointPoseExtractor::pcam
image_geometry::PinholeCameraModel pcam
Definition: point_pose_extractor.h:579
image_geometry::PinholeCameraModel::project3dToPixel
cv::Point2d project3dToPixel(const cv::Point3d &xyz) const
jsk_perception::PointPoseExtractor::_pub
ros::Publisher _pub
Definition: point_pose_extractor.h:569
jsk_perception::PointPoseExtractor::_templates
std::vector< Matching_Template * > _templates
Definition: point_pose_extractor.h:559
random_forest_client_sample.circle
circle
Definition: random_forest_client_sample.py:78
jsk_perception::PointPoseExtractor::subscribe
virtual void subscribe()
Definition: point_pose_extractor.cpp:393
filename
std::string filename
Definition: linemod.cpp:198
Matching_Template::_reprojection_threshold
double _reprojection_threshold
Definition: point_pose_extractor.h:111
Matching_Template::Matching_Template
Matching_Template()
Definition: point_pose_extractor.h:117
jsk_perception::PointPoseExtractor::_n
ros::NodeHandle _n
Definition: point_pose_extractor.h:564
jsk_perception::PointPoseExtractor::dyn_conf_callback
virtual void dyn_conf_callback(Config &config, uint32_t level)
Definition: point_pose_extractor.cpp:405
jsk_perception::PointPoseExtractor::_publish_tf
bool _publish_tf
Definition: point_pose_extractor.h:583
transform_broadcaster.h
jsk_perception::PointPoseExtractor::unsubscribe
virtual void unsubscribe()
Definition: point_pose_extractor.cpp:399
tf::Quaternion::setRotation
void setRotation(const Vector3 &axis, const tfScalar &angle)
ros::ServiceServer
img
img
Matching_Template::_correspondances
std::vector< cv::Point2d > _correspondances
Definition: point_pose_extractor.h:114
jsk_perception
Definition: add_mask_image.h:48
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
MAX
pointer MAX(context *ctx, int n, argv)
jsk_perception::PointPoseExtractor::settemplate_cb
virtual bool settemplate_cb(jsk_perception::SetTemplate::Request &req, jsk_perception::SetTemplate::Response &res)
Definition: point_pose_extractor.cpp:269
tf::Transform::setRotation
TFSIMD_FORCE_INLINE void setRotation(const Quaternion &q)
tf::Quaternion::getAngle
tfScalar getAngle() const
jsk_perception::PointPoseExtractor::add_new_template
virtual bool add_new_template(cv::Mat img, std::string typestr, tf::Transform relative_pose, double template_width, double template_height, double theta_step, double phi_step)
Definition: point_pose_extractor.cpp:234
tf::TransformBroadcaster
features2keypoint
void features2keypoint(posedetection_msgs::Feature0D features, std::vector< cv::KeyPoint > &keypoints, cv::Mat &descriptors)
Definition: point_pose_extractor.h:74
Matching_Template::Matching_Template
Matching_Template(cv::Mat img, std::string matching_frame, int original_width_size, int original_height_size, double template_width, double template_height, tf::Transform relativepose, cv::Mat affine_matrix, double reprojection_threshold, double distanceratio_threshold, std::string window_name, bool autosize)
Definition: point_pose_extractor.h:119
Matching_Template::_window_name
std::string _window_name
Definition: point_pose_extractor.h:109
k
int k
jsk_perception::PointPoseExtractor::_reprojection_threshold
double _reprojection_threshold
Definition: point_pose_extractor.h:573
Matching_Template::_template_img
cv::Mat _template_img
Definition: point_pose_extractor.h:100
jsk_perception::PointPoseExtractor::_viewer
bool _viewer
Definition: point_pose_extractor.h:582
Matching_Template::_template_descriptors
cv::Mat _template_descriptors
Definition: point_pose_extractor.h:102
jsk_perception::PointPoseExtractor::it
image_transport::ImageTransport * it
Definition: point_pose_extractor.h:565
Matching_Template::_template_width
double _template_width
Definition: point_pose_extractor.h:105
jsk_perception::PointPoseExtractor::make_homography
virtual cv::Mat make_homography(cv::Mat src, cv::Mat rvec, cv::Mat tvec, double template_width, double template_height, cv::Size &size)
Definition: point_pose_extractor.cpp:151
vqa_request.client
client
Definition: vqa_request.py:50
ros::ServiceClient
jsk_perception::PointPoseExtractor::_sub
ros::Subscriber _sub
Definition: point_pose_extractor.h:566
Matching_Template::_relativepose
tf::Transform _relativepose
Definition: point_pose_extractor.h:107
random_forest_client_sample.req
req
Definition: random_forest_client_sample.py:45
jsk_perception::PointPoseExtractor::onInit
virtual void onInit()
Definition: point_pose_extractor.cpp:370
ROS_INFO_STREAM
#define ROS_INFO_STREAM(args)
tf::Transform
jsk_perception::PointPoseExtractor::_initialized
bool _initialized
Definition: point_pose_extractor.h:581
tf::Transform::setOrigin
TFSIMD_FORCE_INLINE void setOrigin(const Vector3 &origin)
width
width
image_transport.h
jsk_perception::PointPoseExtractor::_autosize
bool _autosize
Definition: point_pose_extractor.h:577
jsk_perception::PointPoseExtractor::imagefeature_cb
virtual void imagefeature_cb(const posedetection_msgs::ImageFeature0DConstPtr &msg)
Definition: point_pose_extractor.cpp:289
Matching_Template::_template_keypoints
std::vector< cv::KeyPoint > _template_keypoints
Definition: point_pose_extractor.h:101
Matching_Template::estimate_od
bool estimate_od(ros::ServiceClient client, cv::Mat src_img, std::vector< cv::KeyPoint > sourceimg_keypoints, image_geometry::PinholeCameraModel pcam, double err_thr, cv::Mat &stack_img, cv::flann::Index *ft, posedetection_msgs::Object6DPose *o6p)
Definition: point_pose_extractor.h:253
tf.h
jsk_perception::PointPoseExtractor::_pub_pose
ros::Publisher _pub_pose
Definition: point_pose_extractor.h:569
jsk_perception::PointPoseExtractor::_phi_step
double _phi_step
Definition: point_pose_extractor.h:576
Matching_Template::_matching_frame
std::string _matching_frame
Definition: point_pose_extractor.h:99
jsk_perception::PointPoseExtractor::_distanceratio_threshold
double _distanceratio_threshold
Definition: point_pose_extractor.h:574
Matching_Template::_distanceratio_threshold
double _distanceratio_threshold
Definition: point_pose_extractor.h:113
sqrt
double sqrt()
cv_bridge::CvImage::encoding
std::string encoding
image_geometry::PinholeCameraModel
Matching_Template::correspondances
std::vector< cv::Point2d > * correspondances()
Definition: point_pose_extractor.h:158
image_transport::Publisher
cv_bridge.h
ROS_ERROR
#define ROS_ERROR(...)
rospack.h
cv_bridge::CvImage
jsk_perception::PointPoseExtractor::cvmousecb
static void cvmousecb(int event, int x, int y, int flags, void *param)
Definition: point_pose_extractor.h:604
generate_videos.convert
def convert(filename_in, filename_out, ffmpeg_executable="ffmpeg")
Definition: generate_videos.py:7
param
T param(const std::string &param_name, const T &default_val)
tf::Quaternion::getAxis
Vector3 getAxis() const
jsk_perception::PointPoseExtractor::pnod
bool pnod
Definition: point_pose_extractor.h:580
Matching_Template::check_template
bool check_template()
Definition: point_pose_extractor.h:162
Matching_Template::_template_height
double _template_height
Definition: point_pose_extractor.h:106
jsk_perception::PointPoseExtractor::_client
ros::ServiceClient _client
Definition: point_pose_extractor.h:568
height
height
jsk_perception::PointPoseExtractor::Config
jsk_perception::point_pose_extractorConfig Config
Definition: point_pose_extractor.h:560
ROS_INFO
#define ROS_INFO(...)
cv_bridge::CvImage::image
cv::Mat image
n
GLfloat n[6][3]
jsk_perception::PointPoseExtractor::_br
tf::TransformBroadcaster _br
Definition: point_pose_extractor.h:570
tf::Quaternion
Matching_Template::_previous_stack_img
cv::Mat _previous_stack_img
Definition: point_pose_extractor.h:115
tf::Transform::getOrigin
TFSIMD_FORCE_INLINE Vector3 & getOrigin()
Matching_Template::min_inlier
int min_inlier(int n, int m, double p_badsupp, double p_badxform)
Definition: point_pose_extractor.h:233
ros::NodeHandle
ros::Subscriber
jsk_perception::PointPoseExtractor::_child_frame_id
std::string _child_frame_id
Definition: point_pose_extractor.h:584
Matching_Template::~Matching_Template
virtual ~Matching_Template()
Definition: point_pose_extractor.h:149


jsk_perception
Author(s): Manabu Saito, Ryohei Ueda
autogenerated on Fri May 16 2025 03:11:17