image_view2.cpp
Go to the documentation of this file.
1 // -*- tab-width: 8; indent-tabs-mode: nil; -*-
2 /*********************************************************************
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2008, Willow Garage, Inc.
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 Willow Garage 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 
36 #include "image_view2.h"
37 #include <exception>
38 namespace image_view2{
39  ImageView2::ImageView2() : marker_topic_("image_marker"), filename_format_(""), count_(0), mode_(MODE_RECTANGLE), times_(100), window_initialized_(false),space_(10)
40  {
41  }
42 
44  : marker_topic_("image_marker"), filename_format_(""), count_(0), mode_(MODE_RECTANGLE), times_(100), selecting_fg_(true),
47  {
48  std::string camera = nh.resolveName("image");
49  std::string camera_info = nh.resolveName("camera_info");
50  ros::NodeHandle local_nh("~");
51  std::string format_string;
52  std::string transport;
54  image_transport::ImageTransport local_it(camera);
55 
56  point_pub_ = nh.advertise<geometry_msgs::PointStamped>(camera + "/screenpoint",100);
57  point_array_pub_ = nh.advertise<sensor_msgs::PointCloud2>(camera + "/screenpoint_array",100);
58  rectangle_pub_ = nh.advertise<geometry_msgs::PolygonStamped>(camera + "/screenrectangle",100);
59  rectangle_img_pub_ = nh.advertise<sensor_msgs::Image>(camera + "/screenrectangle_image", 100);
60  move_point_pub_ = nh.advertise<geometry_msgs::PointStamped>(camera + "/movepoint", 100);
61  foreground_mask_pub_ = nh.advertise<sensor_msgs::Image>(camera + "/foreground", 100);
62  background_mask_pub_ = nh.advertise<sensor_msgs::Image>(camera + "/background", 100);
63  foreground_rect_pub_ = nh.advertise<geometry_msgs::PolygonStamped>(camera + "/foreground_rect", 100);
64  background_rect_pub_ = nh.advertise<geometry_msgs::PolygonStamped>(camera + "/background_rect", 100);
65  line_pub_ = nh.advertise<geometry_msgs::PolygonStamped>(camera + "/line", 100);
66  poly_pub_ = nh.advertise<geometry_msgs::PolygonStamped>(camera + "/poly", 100);
67  local_nh.param("window_name", window_name_, std::string("image_view2 [")+camera+std::string("]"));
68  local_nh.param("skip_draw_rate", skip_draw_rate_, 0);
69  local_nh.param("autosize", autosize_, false);
70  local_nh.param("image_transport", transport, std::string("raw"));
71  local_nh.param("draw_grid", draw_grid_, false);
72  local_nh.param("blurry", blurry_mode_, false);
73  local_nh.param("region_continuous_publish", region_continuous_publish_, false);
74  local_nh.param("filename_format", format_string, std::string("frame%04i.jpg"));
75  local_nh.param("use_window", use_window, true);
76  local_nh.param("show_info", show_info_, false);
77 
78  double xx,yy;
79  local_nh.param("resize_scale_x", xx, 1.0);
80  local_nh.param("resize_scale_y", yy, 1.0);
81  local_nh.param("tf_timeout", tf_timeout_, 1.0);
82 
83  std::string interaction_mode;
84  local_nh.param("interaction_mode", interaction_mode, std::string("rectangle"));
85  setMode(stringToMode(interaction_mode));
86  resize_x_ = 1.0/xx;
87  resize_y_ = 1.0/yy;
88  filename_format_.parse(format_string);
89 
90  font_ = cv::FONT_HERSHEY_DUPLEX;
92  window_selection_.height = window_selection_.width = 0;
93 
94  image_pub_ = it.advertise("image_marked", 1);
95  local_image_pub_ = local_it.advertise("marked", 1);
96 
97  image_sub_ = it.subscribe(camera, 1, &ImageView2::imageCb, this, transport);
98  info_sub_ = nh.subscribe(camera_info, 1, &ImageView2::infoCb, this);
100  event_sub_ = local_nh.subscribe(camera + "/event", 100, &ImageView2::eventCb, this);
101 
103  "change_mode", &ImageView2::changeModeServiceCallback, this);
105  "rectangle_mode", &ImageView2::rectangleModeServiceCallback, this);
107  "grabcut_mode", &ImageView2::grabcutModeServiceCallback, this);
109  "grabcut_rect_mode", &ImageView2::grabcutRectModeServiceCallback, this);
110  line_mode_srv_ = local_nh.advertiseService(
111  "line_mode", &ImageView2::lineModeServiceCallback, this);
112  poly_mode_srv_ = local_nh.advertiseService(
113  "poly_mode", &ImageView2::polyModeServiceCallback, this);
114  none_mode_srv_ = local_nh.advertiseService(
115  "none_mode", &ImageView2::noneModeServiceCallback, this);
116 
117  srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> >(local_nh);
118  dynamic_reconfigure::Server<Config>::CallbackType f =
119  boost::bind(&ImageView2::config_callback, this, _1, _2);
120  srv_->setCallback(f);
121  }
122 
124  {
125  if ( use_window ) {
126  cv::destroyWindow(window_name_.c_str());
127  }
128  }
129 
130  void ImageView2::config_callback(Config &config, uint32_t level)
131  {
132  draw_grid_ = config.grid;
133  fisheye_mode_ = config.fisheye_mode;
134  div_u_ = config.div_u;
135  div_v_ = config.div_v;
136 
137  grid_red_ = config.grid_red;
138  grid_blue_ = config.grid_blue;
139  grid_green_ = config.grid_green;
140  grid_thickness_ = config.grid_thickness;
141  space_ = config.grid_space;
142  }
143 
144  void ImageView2::markerCb(const image_view2::ImageMarker2ConstPtr& marker)
145  {
146  ROS_DEBUG("markerCb");
147  // convert lifetime to duration from Time(0)
148  if(marker->lifetime != ros::Duration(0))
149  boost::const_pointer_cast<image_view2::ImageMarker2>(marker)->lifetime = (ros::Time::now() - ros::Time(0)) + marker->lifetime;
150  {
151  boost::mutex::scoped_lock lock(queue_mutex_);
152  marker_queue_.push_back(marker);
153  }
154  redraw();
155  }
156 
157  void ImageView2::infoCb(const sensor_msgs::CameraInfoConstPtr& msg) {
158  ROS_DEBUG("infoCb");
159  boost::mutex::scoped_lock lock(info_mutex_);
160  info_msg_ = msg;
161  }
162 
164  std::string frame_id, ros::Time& acquisition_time,
165  std::map<std::string, int>& tf_fail,
166  tf::StampedTransform &transform)
167  {
168  ros::Duration timeout(tf_timeout_); // wait 0.5 sec
169  try {
170  ros::Time tm;
171  tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
173  acquisition_time, timeout);
175  acquisition_time, transform);
176  tf_fail[frame_id]=0;
177  return true;
178  }
179  catch (tf::TransformException& ex) {
180  tf_fail[frame_id]++;
181  if ( tf_fail[frame_id] < 5 ) {
182  ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
183  } else {
184  ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
185  }
186  return false;
187  }
188  }
189 
190  void ImageView2::drawCircle(const image_view2::ImageMarker2::ConstPtr& marker)
191  {
192  cv::Point2d uv = cv::Point2d(marker->position.x, marker->position.y);
193  if ( blurry_mode_ ) {
194  int s0 = (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width);
195  CvScalar co = MsgToRGB(marker->outline_color);
196  for (int s1 = s0*10; s1 >= s0; s1--) {
197  double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
198  cv::circle(draw_, uv,
199  (marker->scale == 0 ? DEFAULT_CIRCLE_SCALE : marker->scale),
200  CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m),
201  s1);
202  }
203  } else {
204  cv::circle(draw_, uv,
205  (marker->scale == 0 ? DEFAULT_CIRCLE_SCALE : marker->scale),
206  MsgToRGB(marker->outline_color),
207  (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
208  if (marker->filled) {
209  cv::circle(draw_, uv,
210  (marker->scale == 0 ? DEFAULT_CIRCLE_SCALE : marker->scale) - (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width) / 2.0,
211  MsgToRGB(marker->fill_color),
212  -1);
213  }
214  }
215  }
216 
217  void ImageView2::drawLineStrip(const image_view2::ImageMarker2::ConstPtr& marker,
218  std::vector<CvScalar>& colors,
219  std::vector<CvScalar>::iterator& col_it)
220  {
221  cv::Point2d p0, p1;
222  if ( blurry_mode_ ) {
223  int s0 = (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width);
224  std::vector<CvScalar>::iterator col_it = colors.begin();
225  CvScalar co = (*col_it);
226  for (int s1 = s0*10; s1 >= s0; s1--) {
227  double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
228  std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
229  std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
230  p0 = cv::Point2d(it->x, it->y); it++;
231  for ( ; it!= end; it++ ) {
232  p1 = cv::Point2d(it->x, it->y);
233  cv::line(draw_, p0, p1,
234  CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m),
235  s1);
236  p0 = p1;
237  if(++col_it == colors.end()) col_it = colors.begin();
238  }
239  }
240  } else {
241  std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
242  std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
243  p0 = cv::Point2d(it->x, it->y); it++;
244  for ( ; it!= end; it++ ) {
245  p1 = cv::Point2d(it->x, it->y);
246  cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
247  p0 = p1;
248  if(++col_it == colors.end()) col_it = colors.begin();
249  }
250  }
251  }
252 
253  void ImageView2::drawLineList(const image_view2::ImageMarker2::ConstPtr& marker,
254  std::vector<CvScalar>& colors,
255  std::vector<CvScalar>::iterator& col_it)
256  {
257  cv::Point2d p0, p1;
258  if ( blurry_mode_ ) {
259  int s0 = (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width);
260  std::vector<CvScalar>::iterator col_it = colors.begin();
261  CvScalar co = (*col_it);
262  for (int s1 = s0*10; s1 >= s0; s1--) {
263  double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
264  std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
265  std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
266  for ( ; it!= end; ) {
267  p0 = cv::Point2d(it->x, it->y); it++;
268  if ( it != end ) p1 = cv::Point2d(it->x, it->y);
269  cv::line(draw_, p0, p1, CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m), s1);
270  it++;
271  if(++col_it == colors.end()) col_it = colors.begin();
272  }
273  }
274  } else {
275  std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
276  std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
277  for ( ; it!= end; ) {
278  p0 = cv::Point2d(it->x, it->y); it++;
279  if ( it != end ) p1 = cv::Point2d(it->x, it->y);
280  cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
281  it++;
282  if(++col_it == colors.end()) col_it = colors.begin();
283  }
284  }
285  }
286 
287  void ImageView2::drawPolygon(const image_view2::ImageMarker2::ConstPtr& marker,
288  std::vector<CvScalar>& colors,
289  std::vector<CvScalar>::iterator& col_it)
290  {
291  cv::Point2d p0, p1;
292  if ( blurry_mode_ ) {
293  int s0 = (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width);
294  std::vector<CvScalar>::iterator col_it = colors.begin();
295  CvScalar co = (*col_it);
296  for (int s1 = s0*10; s1 >= s0; s1--) {
297  double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
298  std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
299  std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
300  p0 = cv::Point2d(it->x, it->y); it++;
301  for ( ; it!= end; it++ ) {
302  p1 = cv::Point2d(it->x, it->y);
303  cv::line(draw_, p0, p1, CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m), s1);
304  p0 = p1;
305  if(++col_it == colors.end()) col_it = colors.begin();
306  }
307  it = marker->points.begin();
308  p1 = cv::Point2d(it->x, it->y);
309  cv::line(draw_, p0, p1, CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m), s1);
310  }
311  } else {
312  std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
313  std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
314  std::vector<cv::Point> points;
315 
316  if (marker->filled) {
317  points.push_back(cv::Point(it->x, it->y));
318  }
319  p0 = cv::Point2d(it->x, it->y); it++;
320  for ( ; it!= end; it++ ) {
321  p1 = cv::Point2d(it->x, it->y);
322  if (marker->filled) {
323  points.push_back(cv::Point(it->x, it->y));
324  }
325  cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
326  p0 = p1;
327  if(++col_it == colors.end()) col_it = colors.begin();
328  }
329  it = marker->points.begin();
330  p1 = cv::Point2d(it->x, it->y);
331  cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
332  if (marker->filled) {
333  cv::fillConvexPoly(draw_, points.data(), points.size(), MsgToRGB(marker->fill_color));
334  }
335  }
336  }
337 
338  void ImageView2::drawPoints(const image_view2::ImageMarker2::ConstPtr& marker,
339  std::vector<CvScalar>& colors,
340  std::vector<CvScalar>::iterator& col_it)
341  {
342  BOOST_FOREACH(geometry_msgs::Point p, marker->points) {
343  cv::Point2d uv = cv::Point2d(p.x, p.y);
344  if ( blurry_mode_ ) {
345  int s0 = (marker->scale == 0 ? 3 : marker->scale);
346  CvScalar co = (*col_it);
347  for (int s1 = s0*2; s1 >= s0; s1--) {
348  double m = pow((1.0-((double)(s1 - s0))/s0),2);
349  cv::circle(draw_, uv, s1,
350  CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m),
351  -1);
352  }
353  } else {
354  cv::circle(draw_, uv, (marker->scale == 0 ? 3 : marker->scale) , *col_it, -1);
355  }
356  if(++col_it == colors.end()) col_it = colors.begin();
357  }
358  }
359 
360  void ImageView2::drawFrames(const image_view2::ImageMarker2::ConstPtr& marker,
361  std::vector<CvScalar>& colors,
362  std::vector<CvScalar>::iterator& col_it)
363  {
364  static std::map<std::string, int> tf_fail;
365  BOOST_FOREACH(std::string frame_id, marker->frames) {
366  tf::StampedTransform transform;
367  ros::Time acquisition_time = last_msg_->header.stamp;
368  if(!lookupTransformation(frame_id, acquisition_time, tf_fail, transform)) {
369  return;
370  }
371  // center point
372  tf::Point pt = transform.getOrigin();
373  cv::Point3d pt_cv(pt.x(), pt.y(), pt.z());
374  cv::Point2d uv;
375  uv = cam_model_.project3dToPixel(pt_cv);
376 
377  static const int RADIUS = 3;
378  cv::circle(draw_, uv, RADIUS, DEFAULT_COLOR, -1);
379 
380  // x, y, z
381  cv::Point2d uv0, uv1, uv2;
382  tf::Stamped<tf::Point> pin, pout;
383 
384  // x
385  pin = tf::Stamped<tf::Point>(tf::Point(0.05, 0, 0), acquisition_time, frame_id);
387  uv0 = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
388  // y
389  pin = tf::Stamped<tf::Point>(tf::Point(0, 0.05, 0), acquisition_time, frame_id);
391  uv1 = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
392 
393  // z
394  pin = tf::Stamped<tf::Point>(tf::Point(0, 0, 0.05), acquisition_time, frame_id);
396  uv2 = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
397 
398  // draw
399  if ( blurry_mode_ ) {
400  int s0 = 2;
401  CvScalar c0 = CV_RGB(255,0,0);
402  CvScalar c1 = CV_RGB(0,255,0);
403  CvScalar c2 = CV_RGB(0,0,255);
404  for (int s1 = s0*10; s1 >= s0; s1--) {
405  double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
406  cv::line(draw_, uv, uv0,
407  CV_RGB(c0.val[2] * m,c0.val[1] * m,c0.val[0] * m),
408  s1);
409  cv::line(draw_, uv, uv1,
410  CV_RGB(c1.val[2] * m,c1.val[1] * m,c1.val[0] * m),
411  s1);
412  cv::line(draw_, uv, uv2,
413  CV_RGB(c2.val[2] * m,c2.val[1] * m,c2.val[0] * m),
414  s1);
415  }
416  } else {
417  cv::line(draw_, uv, uv0, CV_RGB(255,0,0), 2);
418  cv::line(draw_, uv, uv1, CV_RGB(0,255,0), 2);
419  cv::line(draw_, uv, uv2, CV_RGB(0,0,255), 2);
420  }
421 
422  // index
423  cv::Size text_size;
424  int baseline;
425  text_size = cv::getTextSize(frame_id.c_str(), font_, 1.0, 1.0, &baseline);
426  cv::Point origin = cv::Point(uv.x - text_size.width / 2,
427  uv.y - RADIUS - baseline - 3);
428  cv::putText(draw_, frame_id.c_str(), origin, font_, 1.0, DEFAULT_COLOR, 1.5);
429  }
430  }
431 
432  cv::Point ImageView2::ratioPoint(double x, double y)
433  {
434  if (last_msg_) {
435  return cv::Point(last_msg_->width * x,
436  last_msg_->height * y);
437  }
438  else {
439  return cv::Point(0, 0);
440  }
441  }
442 
443  void ImageView2::drawText(const image_view2::ImageMarker2::ConstPtr& marker,
444  std::vector<CvScalar>& colors,
445  std::vector<CvScalar>::iterator& col_it)
446  {
447  cv::Size text_size;
448  int baseline;
449  float scale = marker->scale;
450  if ( scale == 0 ) scale = 1.0;
451  text_size = cv::getTextSize(marker->text.c_str(), font_,
452  scale, scale, &baseline);
453  // fix scale
454  if (marker->ratio_scale) {
455  cv::Size a_size = cv::getTextSize("A", font_, 1.0, 1.0, &baseline);
456  int height_size = a_size.height;
457  double desired_size = last_msg_->height * scale;
458  scale = desired_size / height_size;
459  ROS_DEBUG("text scale: %f", scale);
460  }
461 
462  cv::Point origin;
463  if (marker->left_up_origin) {
464  if (marker->ratio_scale) {
465  origin = ratioPoint(marker->position.x,
466  marker->position.y);
467  }
468  else {
469  origin = cv::Point(marker->position.x,
470  marker->position.y);
471  }
472  }
473  else {
474  if (marker->ratio_scale) {
475  cv::Point p = ratioPoint(marker->position.x, marker->position.y);
476  origin = cv::Point(p.x - text_size.width/2,
477  p.y + baseline+3);
478  }
479  else {
480  origin = cv::Point(marker->position.x - text_size.width/2,
481  marker->position.y + baseline+3);
482  }
483  }
484 
485  if (marker->filled) {
486  cv::putText(draw_, marker->text.c_str(), origin, font_, scale, DEFAULT_COLOR, marker->filled);
487 
488  }
489  else {
490  cv::putText(draw_, marker->text.c_str(), origin, font_, scale, DEFAULT_COLOR);
491  }
492  }
493 
494  void ImageView2::drawLineStrip3D(const image_view2::ImageMarker2::ConstPtr& marker,
495  std::vector<CvScalar>& colors,
496  std::vector<CvScalar>::iterator& col_it)
497  {
498  static std::map<std::string, int> tf_fail;
499  std::string frame_id = marker->points3D.header.frame_id;
500  tf::StampedTransform transform;
501  ros::Time acquisition_time = last_msg_->header.stamp;
502  //ros::Time acquisition_time = msg->points3D.header.stamp;
503  ros::Duration timeout(tf_timeout_); // wait 0.5 sec
504  try {
505  ros::Time tm;
506  tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
507  ros::Duration diff = ros::Time::now() - tm;
508  if ( diff > ros::Duration(1.0) ) { return; }
510  acquisition_time, timeout);
512  acquisition_time, transform);
513  tf_fail[frame_id]=0;
514  }
515  catch (tf::TransformException& ex) {
516  tf_fail[frame_id]++;
517  if ( tf_fail[frame_id] < 5 ) {
518  ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
519  } else {
520  ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
521  }
522  return;
523  }
524  std::vector<geometry_msgs::Point> points2D;
525  BOOST_FOREACH(geometry_msgs::Point p, marker->points3D.points) {
526  tf::Point pt = transform.getOrigin();
527  geometry_msgs::PointStamped pt_cam, pt_;
528  pt_cam.header.frame_id = cam_model_.tfFrame();
529  pt_cam.header.stamp = acquisition_time;
530  pt_cam.point.x = pt.x();
531  pt_cam.point.y = pt.y();
532  pt_cam.point.z = pt.z();
533  tf_listener_.transformPoint(frame_id, pt_cam, pt_);
534 
535  cv::Point2d uv;
536  tf::Stamped<tf::Point> pin, pout;
537  pin = tf::Stamped<tf::Point>(tf::Point(pt_.point.x + p.x, pt_.point.y + p.y, pt_.point.z + p.z), acquisition_time, frame_id);
539  uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
540  geometry_msgs::Point point2D;
541  point2D.x = uv.x;
542  point2D.y = uv.y;
543  points2D.push_back(point2D);
544  }
545  cv::Point2d p0, p1;
546  std::vector<geometry_msgs::Point>::const_iterator it = points2D.begin();
547  std::vector<geometry_msgs::Point>::const_iterator end = points2D.end();
548  p0 = cv::Point2d(it->x, it->y); it++;
549  for ( ; it!= end; it++ ) {
550  p1 = cv::Point2d(it->x, it->y);
551  cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
552  p0 = p1;
553  if(++col_it == colors.end()) col_it = colors.begin();
554  }
555  }
556 
557  void ImageView2::drawLineList3D(const image_view2::ImageMarker2::ConstPtr& marker,
558  std::vector<CvScalar>& colors,
559  std::vector<CvScalar>::iterator& col_it)
560  {
561  static std::map<std::string, int> tf_fail;
562  std::string frame_id = marker->points3D.header.frame_id;
563  tf::StampedTransform transform;
564  ros::Time acquisition_time = last_msg_->header.stamp;
565  if(!lookupTransformation(frame_id, acquisition_time, tf_fail, transform)) {
566  return;
567  }
568  std::vector<geometry_msgs::Point> points2D;
569  BOOST_FOREACH(geometry_msgs::Point p, marker->points3D.points) {
570  tf::Point pt = transform.getOrigin();
571  geometry_msgs::PointStamped pt_cam, pt_;
572  pt_cam.header.frame_id = cam_model_.tfFrame();
573  pt_cam.header.stamp = acquisition_time;
574  pt_cam.point.x = pt.x();
575  pt_cam.point.y = pt.y();
576  pt_cam.point.z = pt.z();
577  tf_listener_.transformPoint(frame_id, pt_cam, pt_);
578 
579  cv::Point2d uv;
580  tf::Stamped<tf::Point> pin, pout;
581  pin = tf::Stamped<tf::Point>(tf::Point(pt_.point.x + p.x, pt_.point.y + p.y, pt_.point.z + p.z), acquisition_time, frame_id);
583  uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
584  geometry_msgs::Point point2D;
585  point2D.x = uv.x;
586  point2D.y = uv.y;
587  points2D.push_back(point2D);
588  }
589  cv::Point2d p0, p1;
590  std::vector<geometry_msgs::Point>::const_iterator it = points2D.begin();
591  std::vector<geometry_msgs::Point>::const_iterator end = points2D.end();
592  for ( ; it!= end; ) {
593  p0 = cv::Point2d(it->x, it->y); it++;
594  if ( it != end ) p1 = cv::Point2d(it->x, it->y);
595  cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
596  it++;
597  if(++col_it == colors.end()) col_it = colors.begin();
598  }
599  }
600 
601  void ImageView2::drawPolygon3D(const image_view2::ImageMarker2::ConstPtr& marker,
602  std::vector<CvScalar>& colors,
603  std::vector<CvScalar>::iterator& col_it)
604  {
605  static std::map<std::string, int> tf_fail;
606  std::string frame_id = marker->points3D.header.frame_id;
607  tf::StampedTransform transform;
608  ros::Time acquisition_time = last_msg_->header.stamp;
609  if(!lookupTransformation(frame_id, acquisition_time, tf_fail, transform)) {
610  return;
611  }
612  std::vector<geometry_msgs::Point> points2D;
613  BOOST_FOREACH(geometry_msgs::Point p, marker->points3D.points) {
614  tf::Point pt = transform.getOrigin();
615  geometry_msgs::PointStamped pt_cam, pt_;
616  pt_cam.header.frame_id = cam_model_.tfFrame();
617  pt_cam.header.stamp = acquisition_time;
618  pt_cam.point.x = pt.x();
619  pt_cam.point.y = pt.y();
620  pt_cam.point.z = pt.z();
621  tf_listener_.transformPoint(frame_id, pt_cam, pt_);
622 
623  cv::Point2d uv;
624  tf::Stamped<tf::Point> pin, pout;
625  pin = tf::Stamped<tf::Point>(tf::Point(pt_.point.x + p.x, pt_.point.y + p.y, pt_.point.z + p.z), acquisition_time, frame_id);
627  uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
628  geometry_msgs::Point point2D;
629  point2D.x = uv.x;
630  point2D.y = uv.y;
631  points2D.push_back(point2D);
632  }
633  cv::Point2d p0, p1;
634  std::vector<geometry_msgs::Point>::const_iterator it = points2D.begin();
635  std::vector<geometry_msgs::Point>::const_iterator end = points2D.end();
636  std::vector<cv::Point> points;
637 
638  if (marker->filled) {
639  points.push_back(cv::Point(it->x, it->y));
640  }
641  p0 = cv::Point2d(it->x, it->y); it++;
642  for ( ; it!= end; it++ ) {
643  p1 = cv::Point2d(it->x, it->y);
644  if (marker->filled) {
645  points.push_back(cv::Point(it->x, it->y));
646  }
647  cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
648  p0 = p1;
649  if(++col_it == colors.end()) col_it = colors.begin();
650  }
651  it = points2D.begin();
652  p1 = cv::Point2d(it->x, it->y);
653  cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
654  if (marker->filled) {
655  cv::fillConvexPoly(draw_, points.data(), points.size(), MsgToRGB(marker->fill_color));
656  }
657  }
658 
659  void ImageView2::drawPoints3D(const image_view2::ImageMarker2::ConstPtr& marker,
660  std::vector<CvScalar>& colors,
661  std::vector<CvScalar>::iterator& col_it)
662  {
663  static std::map<std::string, int> tf_fail;
664  std::string frame_id = marker->points3D.header.frame_id;
665  tf::StampedTransform transform;
666  ros::Time acquisition_time = last_msg_->header.stamp;
667  if(!lookupTransformation(frame_id, acquisition_time, tf_fail, transform)) {
668  return;
669  }
670  BOOST_FOREACH(geometry_msgs::Point p, marker->points3D.points) {
671  tf::Point pt = transform.getOrigin();
672  geometry_msgs::PointStamped pt_cam, pt_;
673  pt_cam.header.frame_id = cam_model_.tfFrame();
674  pt_cam.header.stamp = acquisition_time;
675  pt_cam.point.x = pt.x();
676  pt_cam.point.y = pt.y();
677  pt_cam.point.z = pt.z();
678  tf_listener_.transformPoint(frame_id, pt_cam, pt_);
679 
680  cv::Point2d uv;
681  tf::Stamped<tf::Point> pin, pout;
682  pin = tf::Stamped<tf::Point>(tf::Point(pt_.point.x + p.x, pt_.point.y + p.y, pt_.point.z + p.z), acquisition_time, frame_id);
684  uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
685  cv::circle(draw_, uv, (marker->scale == 0 ? 3 : marker->scale) , *col_it, -1);
686  }
687  }
688 
689  void ImageView2::drawText3D(const image_view2::ImageMarker2::ConstPtr& marker,
690  std::vector<CvScalar>& colors,
691  std::vector<CvScalar>::iterator& col_it)
692  {
693  static std::map<std::string, int> tf_fail;
694  std::string frame_id = marker->position3D.header.frame_id;
695  tf::StampedTransform transform;
696  ros::Time acquisition_time = last_msg_->header.stamp;
697  if(!lookupTransformation(frame_id, acquisition_time, tf_fail, transform)) {
698  return;
699  }
700  tf::Point pt = transform.getOrigin();
701  geometry_msgs::PointStamped pt_cam, pt_;
702  pt_cam.header.frame_id = cam_model_.tfFrame();
703  pt_cam.header.stamp = acquisition_time;
704  pt_cam.point.x = pt.x();
705  pt_cam.point.y = pt.y();
706  pt_cam.point.z = pt.z();
707  tf_listener_.transformPoint(frame_id, pt_cam, pt_);
708 
709  cv::Point2d uv;
710  tf::Stamped<tf::Point> pin, pout;
711  pin = tf::Stamped<tf::Point>(tf::Point(pt_.point.x + marker->position3D.point.x, pt_.point.y + marker->position3D.point.y, pt_.point.z + marker->position3D.point.z), acquisition_time, frame_id);
713  uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
714  cv::Size text_size;
715  int baseline;
716  float scale = marker->scale;
717  if ( scale == 0 ) scale = 1.0;
718  text_size = cv::getTextSize(marker->text.c_str(), font_,
719  scale, scale, &baseline);
720  cv::Point origin = cv::Point(uv.x - text_size.width/2,
721  uv.y - baseline-3);
722  cv::putText(draw_, marker->text.c_str(), origin, font_, scale, CV_RGB(0,255,0),3);
723  }
724 
725  void ImageView2::drawCircle3D(const image_view2::ImageMarker2::ConstPtr& marker,
726  std::vector<CvScalar>& colors,
727  std::vector<CvScalar>::iterator& col_it)
728  {
729  static std::map<std::string, int> tf_fail;
730  std::string frame_id = marker->pose.header.frame_id;
731  geometry_msgs::PoseStamped pose;
732  ros::Time acquisition_time = last_msg_->header.stamp;
733  ros::Duration timeout(tf_timeout_); // wait 0.5 sec
734  try {
735  ros::Time tm;
736  tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
738  acquisition_time, timeout);
740  acquisition_time, marker->pose, frame_id, pose);
741  tf_fail[frame_id]=0;
742  }
743  catch (tf::TransformException& ex) {
744  tf_fail[frame_id]++;
745  if ( tf_fail[frame_id] < 5 ) {
746  ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
747  } else {
748  ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
749  }
750  return;
751  }
752 
753  tf::Quaternion q;
754  tf::quaternionMsgToTF(pose.pose.orientation, q);
755  tf::Matrix3x3 rot = tf::Matrix3x3(q);
756  double angle = (marker->arc == 0 ? 360.0 :marker->angle);
757  double scale = (marker->scale == 0 ? DEFAULT_CIRCLE_SCALE : marker->scale);
758  int N = 100;
759  std::vector< std::vector<cv::Point2i> > ptss;
760  std::vector<cv::Point2i> pts;
761 
762  for (int i=0; i<N; ++i) {
763  double th = angle * i / N * TFSIMD_RADS_PER_DEG;
764  tf::Vector3 v = rot * tf::Vector3(scale * tfCos(th), scale * tfSin(th),0);
765  cv::Point2d pt = cam_model_.project3dToPixel(cv::Point3d(pose.pose.position.x + v.getX(), pose.pose.position.y + v.getY(), pose.pose.position.z + v.getZ()));
766  pts.push_back(cv::Point2i((int)pt.x, (int)pt.y));
767  }
768  ptss.push_back(pts);
769 
770  cv::polylines(draw_, ptss, (marker->arc == 0 ? true : false), MsgToRGB(marker->outline_color), (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
771 
772  if (marker->filled) {
773  if(marker->arc != 0){
774  cv::Point2d pt = cam_model_.project3dToPixel(cv::Point3d(pose.pose.position.x, pose.pose.position.y, pose.pose.position.z));
775  pts.push_back(cv::Point2i((int)pt.x, (int)pt.y));
776  ptss.clear();
777  ptss.push_back(pts);
778  }
779  cv::fillPoly(draw_, ptss, MsgToRGB(marker->fill_color));
780  }
781  }
782 
784  {
785  {
786  boost::mutex::scoped_lock lock(queue_mutex_);
787 
788  while ( ! marker_queue_.empty() ) {
789  // remove marker by namespace and id
790  V_ImageMarkerMessage::iterator new_msg = marker_queue_.begin();
791  V_ImageMarkerMessage::iterator message_it = local_queue_.begin();
792  for ( ; message_it < local_queue_.end(); ++message_it ) {
793  if((*new_msg)->ns == (*message_it)->ns && (*new_msg)->id == (*message_it)->id)
794  message_it = local_queue_.erase(message_it);
795  }
796  local_queue_.push_back(*new_msg);
797  marker_queue_.erase(new_msg);
798  // if action == REMOVE and id == -1, clear all marker_queue
799  if ( (*new_msg)->action == image_view2::ImageMarker2::REMOVE &&
800  (*new_msg)->id == -1 ) {
801  local_queue_.clear();
802  }
803  }
804  }
805 
806  // check lifetime and remove REMOVE-type marker msg
807  for(V_ImageMarkerMessage::iterator it = local_queue_.begin(); it < local_queue_.end(); it++) {
808  if((*it)->action == image_view2::ImageMarker2::REMOVE ||
809  ((*it)->lifetime.toSec() != 0.0 && (*it)->lifetime.toSec() < ros::Time::now().toSec())) {
810  it = local_queue_.erase(it);
811  }
812  }
813  }
814 
816  {
818  if ( !local_queue_.empty() )
819  {
820  V_ImageMarkerMessage::iterator message_it = local_queue_.begin();
821  V_ImageMarkerMessage::iterator message_end = local_queue_.end();
822  ROS_DEBUG("markers = %ld", local_queue_.size());
823  //processMessage;
824  for ( ; message_it != message_end; ++message_it )
825  {
826  image_view2::ImageMarker2::ConstPtr& marker = *message_it;
827 
828  ROS_DEBUG_STREAM("message type = " << marker->type << ", id " << marker->id);
829 
830  // outline colors
831  std::vector<CvScalar> colors;
832  BOOST_FOREACH(std_msgs::ColorRGBA color, marker->outline_colors) {
833  colors.push_back(MsgToRGB(color));
834  }
835  if(colors.size() == 0) colors.push_back(DEFAULT_COLOR);
836  std::vector<CvScalar>::iterator col_it = colors.begin();
837 
838  // check camera_info
839  if( marker->type == image_view2::ImageMarker2::FRAMES ||
840  marker->type == image_view2::ImageMarker2::LINE_STRIP3D ||
841  marker->type == image_view2::ImageMarker2::LINE_LIST3D ||
842  marker->type == image_view2::ImageMarker2::POLYGON3D ||
843  marker->type == image_view2::ImageMarker2::POINTS3D ||
844  marker->type == image_view2::ImageMarker2::TEXT3D ||
845  marker->type == image_view2::ImageMarker2::CIRCLE3D) {
846  {
847  boost::mutex::scoped_lock lock(info_mutex_);
848  if (!info_msg_) {
849  ROS_WARN("[image_view2] camera_info could not found");
850  continue;
851  }
853  }
854  }
855  // CIRCLE, LINE_STRIP, LINE_LIST, POLYGON, POINTS
856  switch ( marker->type ) {
857  case image_view2::ImageMarker2::CIRCLE: {
858  drawCircle(marker);
859  break;
860  }
861  case image_view2::ImageMarker2::LINE_STRIP: {
862  drawLineStrip(marker, colors, col_it);
863  break;
864  }
865  case image_view2::ImageMarker2::LINE_LIST: {
866  drawLineList(marker, colors, col_it);
867  break;
868  }
869  case image_view2::ImageMarker2::POLYGON: {
870  drawPolygon(marker, colors, col_it);
871  break;
872  }
873  case image_view2::ImageMarker2::POINTS: {
874  drawPoints(marker, colors, col_it);
875  break;
876  }
877  case image_view2::ImageMarker2::FRAMES: {
878  drawFrames(marker, colors, col_it);
879  break;
880  }
881  case image_view2::ImageMarker2::TEXT: {
882  drawText(marker, colors, col_it);
883  break;
884  }
885  case image_view2::ImageMarker2::LINE_STRIP3D: {
886  drawLineStrip3D(marker, colors, col_it);
887  break;
888  }
889  case image_view2::ImageMarker2::LINE_LIST3D: {
890  drawLineList3D(marker, colors, col_it);
891  break;
892  }
893  case image_view2::ImageMarker2::POLYGON3D: {
894  drawPolygon3D(marker, colors, col_it);
895  break;
896  }
897  case image_view2::ImageMarker2::POINTS3D: {
898  drawPoints3D(marker, colors, col_it);
899  break;
900  }
901  case image_view2::ImageMarker2::TEXT3D: {
902  drawText3D(marker, colors, col_it);
903  break;
904  }
905  case image_view2::ImageMarker2::CIRCLE3D: {
906  drawCircle3D(marker, colors, col_it);
907  break;
908  }
909  default: {
910  ROS_WARN("Undefined Marker type(%d)", marker->type);
911  break;
912  }
913  }
914  }
915  }
916  }
917 
919  {
920  if (mode_ == MODE_RECTANGLE) {
921  cv::rectangle(draw_, cv::Point(window_selection_.x, window_selection_.y),
922  cv::Point(window_selection_.x + window_selection_.width,
924  USER_ROI_COLOR, 3, 8, 0);
925  }
926  else if (mode_ == MODE_SERIES) {
927  if (point_array_.size() > 1) {
928  cv::Point2d from, to;
929  from = point_array_[0];
930  for (size_t i = 1; i < point_array_.size(); i++) {
931  to = point_array_[i];
932  cv::line(draw_, from, to, USER_ROI_COLOR, 2, 8, 0);
933  from = to;
934  }
935  }
936  }
937  else if (mode_ == MODE_SELECT_FORE_AND_BACK) {
938  boost::mutex::scoped_lock lock(point_array_mutex_);
939  if (point_fg_array_.size() > 1) {
940  cv::Point2d from, to;
941  from = point_fg_array_[0];
942  for (size_t i = 1; i < point_fg_array_.size(); i++) {
943  to = point_fg_array_[i];
944  cv::line(draw_, from, to, CV_RGB(255, 0, 0), 8, 8, 0);
945  from = to;
946  }
947  }
948  if (point_bg_array_.size() > 1) {
949  cv::Point2d from, to;
950  from = point_bg_array_[0];
951  for (size_t i = 1; i < point_bg_array_.size(); i++) {
952  to = point_bg_array_[i];
953  cv::line(draw_, from, to, CV_RGB(0, 255, 0), 8, 8, 0);
954  from = to;
955  }
956  }
957  }
959  boost::mutex::scoped_lock lock(point_array_mutex_);
960  if (rect_fg_.width != 0 && rect_fg_.height != 0) {
961  cv::rectangle(draw_,
962  cv::Point(rect_fg_.x, rect_fg_.y),
963  cv::Point(rect_fg_.x + rect_fg_.width, rect_fg_.y + rect_fg_.height),
964  CV_RGB(255, 0, 0), 4);
965  }
966  if (rect_bg_.width != 0 && rect_bg_.height != 0) {
967  cv::rectangle(draw_,
968  cv::Point(rect_bg_.x, rect_bg_.y),
969  cv::Point(rect_bg_.x + rect_bg_.width, rect_bg_.y + rect_bg_.height),
970  CV_RGB(0, 255, 0), 4);
971  }
972  }
973  else if (mode_ == MODE_LINE) {
974  boost::mutex::scoped_lock lock(line_point_mutex_);
975  if (line_selected_) {
976  cv::line(draw_, line_start_point_, line_end_point_, CV_RGB(0, 255, 0), 8, 8, 0);
977  }
978  }
979  else if (mode_ == MODE_POLY) {
980  boost::mutex::scoped_lock lock(poly_point_mutex_);
981  if (poly_points_.size() > 0) {
982  // draw selected points
983  for (size_t i = 0; i < poly_points_.size() - 1; i++) {
984  cv::line(draw_, poly_points_[i], poly_points_[i + 1], CV_RGB(255, 0, 0), 8, 8, 0);
985  }
986  // draw selecting points
987  if (poly_selecting_done_) {
988  cv::line(draw_, poly_points_[poly_points_.size() - 1],
989  poly_points_[0],
990  CV_RGB(255, 0, 0), 8, 8, 0);
991  }
992  else {
993  cv::line(draw_, poly_points_[poly_points_.size() - 1],
995  CV_RGB(0, 255, 0), 8, 8, 0);
996  }
997  }
998  }
999  }
1000 
1001  void ImageView2::drawInfo(ros::Time& before_rendering)
1002  {
1003  static ros::Time last_time;
1004  static std::string info_str_1, info_str_2;
1005  // update info_str_1, info_str_2 if possible
1006  if ( show_info_ && times_.size() > 0 && ( before_rendering.toSec() - last_time.toSec() > 2 ) ) {
1007  int n = times_.size();
1008  double mean = 0, rate = 1.0, std_dev = 0.0, max_delta, min_delta;
1009 
1010  std::for_each( times_.begin(), times_.end(), (mean += boost::lambda::_1) );
1011  mean /= n;
1012  rate /= mean;
1013 
1014  std::for_each( times_.begin(), times_.end(), (std_dev += (boost::lambda::_1 - mean)*(boost::lambda::_1 - mean) ) );
1015  std_dev = sqrt(std_dev/n);
1016  min_delta = *std::min_element(times_.begin(), times_.end());
1017  max_delta = *std::max_element(times_.begin(), times_.end());
1018 
1019  std::stringstream f1, f2;
1020  f1.precision(3); f1 << std::fixed;
1021  f2.precision(3); f2 << std::fixed;
1022  f1 << "" << image_sub_.getTopic() << " : rate:" << rate;
1023  f2 << "min:" << min_delta << "s max: " << max_delta << "s std_dev: " << std_dev << "s n: " << n;
1024  info_str_1 = f1.str();
1025  info_str_2 = f2.str();
1026  ROS_INFO_STREAM(info_str_1 + " " + info_str_2);
1027  times_.clear();
1028  last_time = before_rendering;
1029  }
1030  if (!info_str_1.empty() && !info_str_2.empty()) {
1031  cv::putText(image_, info_str_1.c_str(), cv::Point(10,image_.rows-34), cv::FONT_HERSHEY_SIMPLEX, 0.8, cv::Scalar::all(255), 2);
1032  cv::putText(image_, info_str_2.c_str(), cv::Point(10,image_.rows-10), cv::FONT_HERSHEY_SIMPLEX, 0.8, cv::Scalar::all(255), 2);
1033  }
1034  }
1035 
1037  {
1038  if (mode_ == MODE_RECTANGLE) {
1039  // publish rectangle cropped image
1040  cv::Rect screen_rect(cv::Point(window_selection_.x, window_selection_.y), cv::Point(window_selection_.x + window_selection_.width, window_selection_.y + window_selection_.height));
1041  cv::Mat cropped_img = original_image_(screen_rect);
1044  last_msg_->header,
1045  last_msg_->encoding,
1046  cropped_img).toImageMsg());
1047  }
1048  }
1049 
1051  {
1052  if (original_image_.empty()) {
1053  ROS_WARN("no image is available yet");
1054  return;
1055  }
1056  ros::Time before_rendering = ros::Time::now();
1057  original_image_.copyTo(image_);
1058  // Draw Section
1059  if ( blurry_mode_ ) {
1060  draw_ = cv::Mat(image_.size(), image_.type(), CV_RGB(0,0,0));
1061  } else {
1062  draw_ = image_;
1063  }
1064  drawMarkers();
1065  drawInteraction();
1066  cropROI();
1067 
1068  if ( draw_grid_ ) drawGrid();
1069  if ( blurry_mode_ ) cv::addWeighted(image_, 0.9, draw_, 1.0, 0.0, image_);
1070  if ( use_window ) {
1071  if (show_info_) {
1072  drawInfo(before_rendering);
1073  }
1074  }
1075  cv_bridge::CvImage out_msg;
1076  out_msg.header = last_msg_->header;
1077  out_msg.encoding = "bgr8";
1078  out_msg.image = image_;
1079  image_pub_.publish(out_msg.toImageMsg());
1080  local_image_pub_.publish(out_msg.toImageMsg());
1081  }
1082 
1084  {
1085  distort_grid_mask_.setTo(cv::Scalar(0,0,0));
1086  cv::Mat distort_grid_mask(draw_.size(), CV_8UC1);
1087  distort_grid_mask.setTo(cv::Scalar(0));
1088  const float K = 341.0;
1089  float R_divier = (1.0/(draw_.cols/2)), center_x = distort_grid_mask.rows/2, center_y = distort_grid_mask.cols/2;
1090  for(int degree = -80; degree<=80; degree+=space_){
1091  double C = draw_.cols/2.0 * tan(degree * 3.14159265/180);
1092  for(float theta = -1.57; theta <= 1.57; theta+=0.001){
1093  double sin_phi = C * R_divier / tan(theta);
1094  if (sin_phi > 1.0 || sin_phi < -1.0)
1095  continue;
1096  int x1 = K * theta * sqrt(1-sin_phi * sin_phi) + center_x;
1097  int y1 = K * theta * sin_phi + center_y;
1098  int x2 = K * theta * sin_phi + center_x;
1099  int y2 = K * theta * sqrt(1-sin_phi * sin_phi) + center_y;
1100  cv::circle(distort_grid_mask, cvPoint(y1, x1), 2, 1, grid_thickness_);
1101  cv::circle(distort_grid_mask, cvPoint(y2, x2), 2, 1, grid_thickness_);
1102  }
1103  }
1104  cv::Mat red(draw_.size(), draw_.type(), CV_8UC3);
1105  red = cv::Scalar(grid_blue_, grid_green_, grid_red_);
1106  red.copyTo(distort_grid_mask_, distort_grid_mask);
1107  }
1108 
1110  {
1111  if(fisheye_mode_){
1116  prev_space_ = space_;
1117  prev_red_ = grid_red_;
1121  }
1122  cv::add(draw_, distort_grid_mask_, draw_);
1123  }else{
1124  //Main Center Lines
1125  cv::Point2d p0 = cv::Point2d(0, last_msg_->height/2.0);
1126  cv::Point2d p1 = cv::Point2d(last_msg_->width, last_msg_->height/2.0);
1127  cv::line(draw_, p0, p1, CV_RGB(255,0,0), DEFAULT_LINE_WIDTH);
1128 
1129  cv::Point2d p2 = cv::Point2d(last_msg_->width/2.0, 0);
1130  cv::Point2d p3 = cv::Point2d(last_msg_->width/2.0, last_msg_->height);
1131  cv::line(draw_, p2, p3, CV_RGB(255,0,0), DEFAULT_LINE_WIDTH);
1132 
1133  for(int i = 1; i < div_u_ ;i ++){
1134  cv::Point2d u0 = cv::Point2d(0, last_msg_->height * i * 1.0 / div_u_);
1135  cv::Point2d u1 = cv::Point2d(last_msg_->width, last_msg_->height * i * 1.0 / div_u_);
1136  cv::line(draw_, u0, u1, CV_RGB(255,0,0), 1);
1137  }
1138 
1139  for(int i = 1; i < div_v_ ;i ++){
1140  cv::Point2d v0 = cv::Point2d(last_msg_->width * i * 1.0 / div_v_, 0);
1141  cv::Point2d v1 = cv::Point2d(last_msg_->width * i * 1.0 / div_v_, last_msg_->height);
1142  cv::line(draw_, v0, v1, CV_RGB(255,0,0), 1);
1143  }
1144  }
1145  }
1146 
1147  void ImageView2::imageCb(const sensor_msgs::ImageConstPtr& msg)
1148  {
1149  if (msg->width == 0 && msg->height == 0) {
1150  ROS_DEBUG("invalid image");
1151  return;
1152  }
1153  static int count = 0;
1154  if (count < skip_draw_rate_) {
1155  count++;
1156  return;
1157  }
1158  else {
1159  count = 0;
1160  }
1161  static ros::Time old_time;
1162  times_.push_front(ros::Time::now().toSec() - old_time.toSec());
1163  old_time = ros::Time::now();
1164 
1165  if(old_time.toSec() - ros::Time::now().toSec() > 0) {
1166  ROS_WARN("TF Cleared for old time");
1167  }
1168  {
1169  boost::mutex::scoped_lock lock(image_mutex_);
1170  if (msg->encoding.find("bayer") != std::string::npos) {
1171  original_image_ = cv::Mat(msg->height, msg->width, CV_8UC1,
1172  const_cast<uint8_t*>(&msg->data[0]), msg->step);
1173  } else if (msg->encoding == sensor_msgs::image_encodings::TYPE_16UC1) {
1174  // standardize pixel values to 0-255 to visualize depth image
1175  cv::Mat input_image = cv_bridge::toCvCopy(msg)->image;
1176  double min, max;
1177  cv::minMaxIdx(input_image, &min, &max);
1178  cv::convertScaleAbs(input_image, original_image_, 255 / max);
1179  } else {
1180  try {
1182  } catch (cv_bridge::Exception& e) {
1183  ROS_ERROR("Unable to convert %s image to bgr8", msg->encoding.c_str());
1184  return;
1185  }
1186  }
1187  // Hang on to message pointer for sake of mouseCb
1188  last_msg_ = msg;
1189  redraw();
1190  }
1193  }
1194  }
1195 
1197  if (image_.rows > 0 && image_.cols > 0) {
1198  redraw();
1199  }
1200  }
1201 
1202  void ImageView2::addPoint(int x, int y)
1203  {
1204  cv::Point2d p;
1205  p.x = x;
1206  p.y = y;
1207  {
1208  boost::mutex::scoped_lock lock(point_array_mutex_);
1209  point_array_.push_back(p);
1210  }
1211  }
1212 
1214  {
1215  boost::mutex::scoped_lock lock(point_array_mutex_);
1216  ROS_DEBUG("setRegionWindowPoint(%d, %d)", x, y);
1217  if (selecting_fg_) {
1218  rect_fg_.x = x;
1219  rect_fg_.y = y;
1220  rect_fg_.width = 0;
1221  rect_fg_.height = 0;
1222  }
1223  else {
1224  rect_bg_.x = x;
1225  rect_bg_.y = y;
1226  rect_bg_.width = 0;
1227  rect_bg_.height = 0;
1228  }
1229  }
1230 
1232  {
1233  ROS_DEBUG("updateRegionWindowPoint");
1234  boost::mutex::scoped_lock lock(point_array_mutex_);
1235  if (selecting_fg_) {
1236  rect_fg_.width = x - rect_fg_.x;
1237  rect_fg_.height = y - rect_fg_.y;
1238  }
1239  else {
1240  rect_bg_.width = x - rect_bg_.x;
1241  rect_bg_.height = y - rect_bg_.y;
1242  }
1243  }
1244 
1245  void ImageView2::addRegionPoint(int x, int y)
1246  {
1247  cv::Point2d p;
1248  p.x = x;
1249  p.y = y;
1250  {
1251  boost::mutex::scoped_lock lock(point_array_mutex_);
1252  if (selecting_fg_) {
1253  point_fg_array_.push_back(p);
1254  }
1255  else {
1256  point_bg_array_.push_back(p);
1257  }
1258  }
1259  }
1260 
1262  {
1263  boost::mutex::scoped_lock lock(point_array_mutex_);
1264  point_fg_array_.clear();
1265  point_bg_array_.clear();
1266  point_array_.clear();
1267  }
1268 
1270  {
1271  pcl::PointCloud<pcl::PointXY> pcl_cloud;
1272  for (size_t i = 0; i < point_array_.size(); i++) {
1273  pcl::PointXY p;
1274  p.x = point_array_[i].x;
1275  p.y = point_array_[i].y;
1276  pcl_cloud.points.push_back(p);
1277  }
1278  sensor_msgs::PointCloud2::Ptr ros_cloud(new sensor_msgs::PointCloud2);
1279  pcl::toROSMsg(pcl_cloud, *ros_cloud);
1280  ros_cloud->header.stamp = ros::Time::now();
1281 
1282  point_array_pub_.publish(ros_cloud);
1283  }
1284 
1285 
1287  {
1288  mode_ = mode;
1289  }
1290 
1292  {
1293  return mode_;
1294  }
1295 
1297  {
1298  boost::mutex::scoped_lock lock(point_array_mutex_);
1300  return selecting_fg_;
1301  }
1302 
1303  void ImageView2::pointArrayToMask(std::vector<cv::Point2d>& points,
1304  cv::Mat& mask)
1305  {
1306  cv::Point2d from, to;
1307  if (points.size() > 1) {
1308  from = points[0];
1309  for (size_t i = 1; i < points.size(); i++) {
1310  to = points[i];
1311  cv::line(mask, from, to, cv::Scalar(255), 8, 8, 0);
1312  from = to;
1313  }
1314  }
1315  }
1316 
1318  cv::Mat& image,
1319  const std_msgs::Header& header)
1320  {
1321  cv_bridge::CvImage image_bridge(
1322  header, sensor_msgs::image_encodings::MONO8, image);
1323  pub.publish(image_bridge.toImageMsg());
1324  }
1325 
1327  {
1328  boost::mutex::scoped_lock lock(image_mutex_);
1329  boost::mutex::scoped_lock lock2(point_array_mutex_);
1330  cv::Mat foreground_mask
1331  = cv::Mat::zeros(last_msg_->height, last_msg_->width, CV_8UC1);
1332  cv::Mat background_mask
1333  = cv::Mat::zeros(last_msg_->height, last_msg_->width, CV_8UC1);
1335  pointArrayToMask(point_fg_array_, foreground_mask);
1336  pointArrayToMask(point_bg_array_, background_mask);
1337  }
1338  else if (getMode() == MODE_SELECT_FORE_AND_BACK_RECT) {
1339  cv::rectangle(foreground_mask, rect_fg_, cv::Scalar(255), CV_FILLED);
1340  cv::rectangle(background_mask, rect_bg_, cv::Scalar(255), CV_FILLED);
1341  }
1342  publishMonoImage(foreground_mask_pub_, foreground_mask, last_msg_->header);
1343  publishMonoImage(background_mask_pub_, background_mask, last_msg_->header);
1344  publishRectFromMaskImage(foreground_rect_pub_, foreground_mask, last_msg_->header);
1345  publishRectFromMaskImage(background_rect_pub_, background_mask, last_msg_->header);
1346  }
1347 
1350  cv::Mat& image,
1351  const std_msgs::Header& header)
1352  {
1353  int min_x = image.cols;
1354  int min_y = image.rows;
1355  int max_x = 0;
1356  int max_y = 0;
1357  for (int j = 0; j < image.rows; j++) {
1358  for (int i = 0; i < image.cols; i++) {
1359  if (image.at<uchar>(j, i) != 0) {
1360  min_x = std::min(min_x, i);
1361  min_y = std::min(min_y, j);
1362  max_x = std::max(max_x, i);
1363  max_y = std::max(max_y, j);
1364  }
1365  }
1366  }
1367  geometry_msgs::PolygonStamped poly;
1368  poly.header = header;
1369  geometry_msgs::Point32 min_pt, max_pt;
1370  min_pt.x = min_x;
1371  min_pt.y = min_y;
1372  max_pt.x = max_x;
1373  max_pt.y = max_y;
1374  poly.polygon.points.push_back(min_pt);
1375  poly.polygon.points.push_back(max_pt);
1376  pub.publish(poly);
1377  }
1378 
1380  {
1381  boost::mutex::scoped_lock lock(line_point_mutex_);
1382  geometry_msgs::PolygonStamped ros_line;
1383  ros_line.header = last_msg_->header;
1384  geometry_msgs::Point32 ros_start_point, ros_end_point;
1385  ros_start_point.x = line_start_point_.x;
1386  ros_start_point.y = line_start_point_.y;
1387  ros_end_point.x = line_end_point_.x;
1388  ros_end_point.y = line_end_point_.y;
1389  ros_line.polygon.points.push_back(ros_start_point);
1390  ros_line.polygon.points.push_back(ros_end_point);
1391  line_pub_.publish(ros_line);
1392  }
1393 
1395  {
1396  if (getMode() == MODE_SERIES) {
1398  }
1399  else if (getMode() == MODE_SELECT_FORE_AND_BACK ||
1402  }
1403  else if (getMode() == MODE_LINE) {
1405  }
1406  else {
1407  cv::Point2f Pt_1(window_selection_.x, window_selection_.y);
1408  cv::Point2f Pt(button_up_pos_);
1409  std::cout << "PT_1" << Pt_1 << std::endl;
1410  std::cout << "Pt" << Pt << std::endl;
1411  if (!isValidMovement(Pt_1, Pt)) {
1412  geometry_msgs::PointStamped screen_msg;
1413  screen_msg.point.x = window_selection_.x * resize_x_;
1414  screen_msg.point.y = window_selection_.y * resize_y_;
1415  screen_msg.point.z = 0;
1416  screen_msg.header.stamp = last_msg_->header.stamp;
1417  ROS_INFO("Publish screen point %s (%f %f)", point_pub_.getTopic().c_str(), screen_msg.point.x, screen_msg.point.y);
1418  point_pub_.publish(screen_msg);
1419  } else {
1420  geometry_msgs::PolygonStamped screen_msg;
1421  screen_msg.polygon.points.resize(2);
1422  screen_msg.polygon.points[0].x = window_selection_.x * resize_x_;
1423  screen_msg.polygon.points[0].y = window_selection_.y * resize_y_;
1424  screen_msg.polygon.points[1].x = (window_selection_.x + window_selection_.width) * resize_x_;
1425  screen_msg.polygon.points[1].y = (window_selection_.y + window_selection_.height) * resize_y_;
1426  screen_msg.header = last_msg_->header;
1427  ROS_INFO("Publish rectangle point %s (%f %f %f %f)", rectangle_pub_.getTopic().c_str(),
1428  screen_msg.polygon.points[0].x, screen_msg.polygon.points[0].y,
1429  screen_msg.polygon.points[1].x, screen_msg.polygon.points[1].y);
1430  rectangle_pub_.publish(screen_msg);
1431  continuous_ready_ = true;
1432  }
1433  }
1434  }
1435 
1436 
1437  bool ImageView2::isValidMovement(const cv::Point2f& start_point,
1438  const cv::Point2f& end_point)
1439  {
1440  double dist_px = cv::norm(cv::Mat(start_point), cv::Mat(end_point));
1441  return dist_px > 3.0;
1442  }
1443 
1445  {
1446  boost::mutex::scoped_lock lock(line_point_mutex_);
1447  line_start_point_ = p;
1448  }
1449 
1451  {
1452  boost::mutex::scoped_lock lock(line_point_mutex_);
1453  line_end_point_ = p;
1454  }
1455 
1457  {
1458  boost::mutex::scoped_lock lock(line_point_mutex_);
1459  return cv::Point(line_start_point_);
1460  }
1461 
1463  {
1464  boost::mutex::scoped_lock lock(line_point_mutex_);
1465  return cv::Point(line_end_point_);
1466  }
1467 
1469  {
1470 
1471  if (isSelectingLineStartPoint()) {
1473  updateLineEndPoint(p);
1474  }
1475  else {
1476  updateLineEndPoint(p);
1477  }
1478  {
1479  boost::mutex::scoped_lock lock(line_point_mutex_);
1481  line_selected_ = true;
1482  }
1483  }
1484 
1486  {
1487  boost::mutex::scoped_lock lock(line_point_mutex_);
1488  return line_select_start_point_;
1489  }
1490 
1492  {
1493  ROS_DEBUG("processLeftButtonDown");
1494  left_button_clicked_ = true;
1495  continuous_ready_ = false;
1496  window_selection_.x = x;
1497  window_selection_.y = y;
1498  window_selection_.width = window_selection_.height = 0;
1500  setRegionWindowPoint(x, y);
1501  }
1502  if (getMode() == MODE_LINE) {
1503  continuous_ready_ = false;
1504  }
1505  }
1506 
1507  void ImageView2::processMove(int x, int y)
1508  {
1509  if (left_button_clicked_) {
1510  cv::Point2f Pt_1(window_selection_.x, window_selection_.y);
1511  cv::Point2f Pt(x, y);
1512  if (isValidMovement(Pt_1, Pt)) {
1513  if (getMode() == MODE_RECTANGLE) {
1514  window_selection_.width = x - window_selection_.x;
1515  window_selection_.height = y - window_selection_.y;
1516  }
1517  else if (getMode() == MODE_SERIES) {
1518  addPoint(x, y);
1519  }
1520  else if (getMode() == MODE_SELECT_FORE_AND_BACK) {
1521  addRegionPoint(x, y);
1522  }
1523  else if (getMode() == MODE_SELECT_FORE_AND_BACK_RECT) {
1524  updateRegionWindowSize(x, y);
1525  }
1526  }
1527  // publish the points
1528  geometry_msgs::PointStamped move_point;
1529  move_point.header.stamp = ros::Time::now();
1530  move_point.point.x = x;
1531  move_point.point.y = y;
1532  move_point.point.z = 0;
1533  move_point_pub_.publish(move_point);
1534  }
1535  else {
1536  if (getMode() == MODE_LINE) {
1537  if (!isSelectingLineStartPoint()) {
1538  updateLineEndPoint(cv::Point(x, y));
1539  }
1540  }
1541  else if (getMode() == MODE_POLY) {
1542  updatePolySelectingPoint(cv::Point(x, y));
1543  }
1544  }
1545  }
1546 
1548  {
1549  if (!left_button_clicked_) {
1550  return;
1551  }
1552  if (getMode() == MODE_SERIES) {
1554  clearPointArray();
1555  }
1556  else if (getMode() == MODE_SELECT_FORE_AND_BACK ||
1558  bool fgp = toggleSelection();
1559  if (fgp) {
1561  continuous_ready_ = true;
1562  //clearPointArray();
1563  }
1564  }
1565  else if (getMode() == MODE_RECTANGLE) {
1566  // store x and y
1567  button_up_pos_ = cv::Point2f(x, y);
1569  }
1570  else if (getMode() == MODE_LINE) {
1571  updateLinePoint(cv::Point(x, y));
1572  if (isSelectingLineStartPoint()) {
1574  continuous_ready_ = true;
1575  }
1576  }
1577  else if (getMode() == MODE_POLY) {
1578  if (isPolySelectingFirstTime()) {
1579  continuous_ready_ = false;
1580  clearPolyPoints();
1581  }
1582  updatePolyPoint(cv::Point(x, y));
1583  }
1584  left_button_clicked_ = false;
1585  }
1586 
1588  {
1589  boost::mutex::scoped_lock lock(poly_point_mutex_);
1590  poly_points_.push_back(p);
1591  }
1592 
1594  {
1595  boost::mutex::scoped_lock lock(poly_point_mutex_);
1596  geometry_msgs::PolygonStamped poly;
1597  poly.header = last_msg_->header;
1598  for (size_t i = 0; i < poly_points_.size(); i++) {
1599  geometry_msgs::Point32 p;
1600  p.x = poly_points_[i].x;
1601  p.y = poly_points_[i].y;
1602  p.z = 0;
1603  poly.polygon.points.push_back(p);
1604  }
1605  poly_pub_.publish(poly);
1606  }
1607 
1609  {
1610  boost::mutex::scoped_lock lock(poly_point_mutex_);
1612  }
1613 
1615  {
1616  boost::mutex::scoped_lock lock(poly_point_mutex_);
1617  poly_selecting_done_ = true;
1618  }
1619 
1621  {
1622  boost::mutex::scoped_lock lock(poly_point_mutex_);
1623  return poly_selecting_done_;
1624  }
1625 
1627  {
1628  boost::mutex::scoped_lock lock(poly_point_mutex_);
1629  poly_selecting_done_ = false;
1630  poly_points_.clear();
1631  }
1632 
1633  void ImageView2::processMouseEvent(int event, int x, int y, int flags, void* param)
1634  {
1635  checkMousePos(x, y);
1636  switch (event){
1637  case CV_EVENT_MOUSEMOVE: {
1638  processMove(x, y);
1639  break;
1640  }
1641  case CV_EVENT_LBUTTONDOWN: // click
1642  processLeftButtonDown(x, y);
1643  break;
1644  case CV_EVENT_LBUTTONUP:
1645  processLeftButtonUp(x, y);
1646  break;
1647  case CV_EVENT_RBUTTONDOWN:
1648  {
1649  if (getMode() == MODE_POLY) {
1650  // close the polygon
1653  continuous_ready_ = true;
1654  }
1655  else {
1656  boost::mutex::scoped_lock lock(image_mutex_);
1657  if (!image_.empty()) {
1658  std::string filename = (filename_format_ % count_).str();
1659  cv::imwrite(filename.c_str(), image_);
1660  ROS_INFO("Saved image %s", filename.c_str());
1661  count_++;
1662  } else {
1663  ROS_WARN("Couldn't save image, no data!");
1664  }
1665  }
1666  break;
1667  }
1668  }
1669  {
1670  boost::mutex::scoped_lock lock2(image_mutex_);
1671  drawImage();
1672  }
1673  return;
1674  }
1675 
1676  void ImageView2::mouseCb(int event, int x, int y, int flags, void* param)
1677  {
1678  ROS_DEBUG("mouseCB");
1679  ImageView2 *iv = (ImageView2*)param;
1680  iv->processMouseEvent(event, x, y, flags, param);
1681  return;
1682  }
1683 
1684  void ImageView2::pressKey(int key)
1685  {
1686  if (key != -1) {
1687  switch (key) {
1688  case 27: {
1689  resetInteraction();
1690  break;
1691  }
1692  }
1693  }
1694  }
1695 
1697  {
1698  if (use_window) {
1699  if (!window_initialized_) {
1700  cv::namedWindow(window_name_.c_str(), autosize_ ? CV_WINDOW_AUTOSIZE : 0);
1701  cv::setMouseCallback(window_name_.c_str(), &ImageView2::mouseCb, this);
1702  window_initialized_ = false;
1703  }
1704  if(!image_.empty()) {
1705  cv::imshow(window_name_.c_str(), image_);
1706  cv::waitKey(3);
1707  }
1708  }
1709  }
1710 
1711  void ImageView2::checkMousePos(int& x, int& y)
1712  {
1713  if (last_msg_) {
1714  x = std::max(std::min(x, (int)last_msg_->width), 0);
1715  y = std::max(std::min(y, (int)last_msg_->height), 0);
1716  }
1717  }
1719  {
1721  boost::mutex::scoped_lock lock(point_array_mutex_);
1722  point_fg_array_.clear();
1723  point_bg_array_.clear();
1724  selecting_fg_ = true;
1725  }
1726  else if (getMode() == MODE_SELECT_FORE_AND_BACK_RECT) {
1727  boost::mutex::scoped_lock lock(point_array_mutex_);
1728  rect_fg_.width = rect_fg_.height = 0;
1729  rect_bg_.width = rect_bg_.height = 0;
1730  selecting_fg_ = true;
1731  }
1732  else if (getMode() == MODE_LINE) {
1733  boost::mutex::scoped_lock lock(line_point_mutex_);
1734  line_select_start_point_ = true;
1735  line_selected_ = false;
1736  continuous_ready_ = false;
1737  }
1738  else if (getMode() == MODE_RECTANGLE) {
1739  button_up_pos_ = cv::Point2f(0, 0);
1740  window_selection_.width = 0;
1741  window_selection_.height = 0;
1742  }
1743  else if (getMode() == MODE_POLY) {
1744  clearPolyPoints();
1745  }
1746  }
1747 
1749  std_srvs::EmptyRequest& req,
1750  std_srvs::EmptyResponse& res)
1751  {
1752  resetInteraction();
1754  resetInteraction();
1755  return true;
1756  }
1757 
1759  std_srvs::EmptyRequest& req,
1760  std_srvs::EmptyResponse& res)
1761  {
1762  resetInteraction();
1764  resetInteraction();
1765  return true;
1766  }
1767 
1769  std_srvs::EmptyRequest& req,
1770  std_srvs::EmptyResponse& res)
1771  {
1772  resetInteraction();
1774  resetInteraction();
1775  return true;
1776  }
1777 
1779  std_srvs::EmptyRequest& req,
1780  std_srvs::EmptyResponse& res)
1781  {
1782  resetInteraction();
1784  resetInteraction();
1785  return true;
1786  }
1787 
1789  std_srvs::EmptyRequest& req,
1790  std_srvs::EmptyResponse& res)
1791  {
1792  resetInteraction();
1793  setMode(MODE_LINE);
1794  resetInteraction();
1795  return true;
1796  }
1797 
1799  std_srvs::EmptyRequest& req,
1800  std_srvs::EmptyResponse& res)
1801  {
1802  resetInteraction();
1803  setMode(MODE_POLY);
1804  resetInteraction();
1805  return true;
1806  }
1807 
1809  std_srvs::EmptyRequest& req,
1810  std_srvs::EmptyResponse& res)
1811  {
1812  resetInteraction();
1813  setMode(MODE_NONE);
1814  resetInteraction();
1815  return true;
1816  }
1817 
1819  image_view2::ChangeModeRequest& req,
1820  image_view2::ChangeModeResponse& res)
1821  {
1822  resetInteraction();
1823  KEY_MODE next_mode = stringToMode(req.mode);
1824  setMode(next_mode);
1825  resetInteraction();
1826  return true;
1827  }
1828 
1829  ImageView2::KEY_MODE ImageView2::stringToMode(const std::string& interaction_mode)
1830  {
1831  if (interaction_mode == "rectangle") {
1832  return MODE_RECTANGLE;
1833  }
1834  else if (interaction_mode == "freeform" ||
1835  interaction_mode == "series") {
1836  return MODE_SERIES;
1837  }
1838  else if (interaction_mode == "grabcut") {
1840  }
1841  else if (interaction_mode == "grabcut_rect") {
1843  }
1844  else if (interaction_mode == "line") {
1845  return MODE_LINE;
1846  }
1847  else if (interaction_mode == "poly") {
1848  return MODE_POLY;
1849  }
1850  else if (interaction_mode == "none") {
1851  return MODE_NONE;
1852  }
1853  else {
1854  throw std::string("Unknown mode");
1855  }
1856  }
1857 
1859  const image_view2::MouseEvent::ConstPtr& event_msg)
1860  {
1861  //ROS_INFO("eventCb");
1862  if (event_msg->type == image_view2::MouseEvent::KEY_PRESSED) {
1863  pressKey(event_msg->key);
1864  }
1865  else {
1866  // scale x, y according to width/height
1867  int x, y;
1868  {
1869  boost::mutex::scoped_lock lock(image_mutex_);
1870  if (!last_msg_) {
1871  ROS_WARN("Image is not yet available");
1872  return;
1873  }
1874  x = ((float)last_msg_->width / event_msg->width) * event_msg->x;
1875  y = ((float)last_msg_->height / event_msg->height) * event_msg->y;
1876  }
1877  // scale
1878  if (event_msg->type == image_view2::MouseEvent::MOUSE_LEFT_UP) {
1879  //ROS_INFO("mouse_left_up");
1880  processMouseEvent(CV_EVENT_LBUTTONUP, x, y, 0, NULL);
1881  }
1882  else if (event_msg->type == image_view2::MouseEvent::MOUSE_LEFT_DOWN) {
1883  //ROS_INFO("mouse_left_down");
1884  processMouseEvent(CV_EVENT_LBUTTONDOWN, x, y, 0, NULL);
1885  }
1886  else if (event_msg->type == image_view2::MouseEvent::MOUSE_MOVE) {
1887  //ROS_INFO("mouse_move");
1888  processMouseEvent(CV_EVENT_MOUSEMOVE, x, y, 0, NULL);
1889  }
1890  else if (event_msg->type == image_view2::MouseEvent::MOUSE_RIGHT_DOWN) {
1891  //ROS_INFO("mouse_right_down");
1892  processMouseEvent(CV_EVENT_RBUTTONDOWN, x, y, 0, NULL);
1893  }
1894  }
1895  }
1896 }
1897 
1898 
void config_callback(Config &config, uint32_t level)
ros::Publisher point_pub_
Definition: image_view2.h:248
Subscriber subscribe(const std::string &base_topic, uint32_t queue_size, const boost::function< void(const sensor_msgs::ImageConstPtr &)> &callback, const ros::VoidPtr &tracked_object=ros::VoidPtr(), const TransportHints &transport_hints=TransportHints())
image_transport::Subscriber image_sub_
Definition: image_view2.h:192
#define USER_ROI_COLOR
Definition: image_view2.h:69
boost::mutex image_mutex_
Definition: image_view2.h:208
filename
void setMode(KEY_MODE mode)
ros::Subscriber info_sub_
Definition: image_view2.h:194
#define DEFAULT_COLOR
Definition: image_view2.h:68
cv::Point2f button_up_pos_
Definition: image_view2.h:239
void updateLineEndPoint(cv::Point p)
void publish(const boost::shared_ptr< M > &message) const
void publishMonoImage(ros::Publisher &pub, cv::Mat &image, const std_msgs::Header &header)
ros::ServiceServer grabcut_mode_srv_
Definition: image_view2.h:287
void updatePolyPoint(cv::Point p)
ros::ServiceServer rectangle_mode_srv_
Definition: image_view2.h:285
void updateLinePoint(cv::Point p)
f
ros::Publisher rectangle_img_pub_
Definition: image_view2.h:251
ros::Publisher poly_pub_
Definition: image_view2.h:258
void addPoint(int x, int y)
bool noneModeServiceCallback(std_srvs::EmptyRequest &req, std_srvs::EmptyResponse &res)
cv::Point poly_selecting_point_
Definition: image_view2.h:229
std::vector< cv::Point2d > point_fg_array_
Definition: image_view2.h:227
void drawPolygon(const image_view2::ImageMarker2::ConstPtr &marker, std::vector< CvScalar > &colors, std::vector< CvScalar >::iterator &col_it)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
ros::Publisher background_rect_pub_
Definition: image_view2.h:256
sensor_msgs::CameraInfoConstPtr info_msg_
Definition: image_view2.h:206
std::string resolveName(const std::string &name, bool remap=true) const
boost::circular_buffer< double > times_
Definition: image_view2.h:197
ros::ServiceServer line_mode_srv_
Definition: image_view2.h:289
void drawText3D(const image_view2::ImageMarker2::ConstPtr &marker, std::vector< CvScalar > &colors, std::vector< CvScalar >::iterator &col_it)
std::string marker_topic_
Definition: image_view2.h:196
ros::ServiceServer none_mode_srv_
Definition: image_view2.h:290
bool seriesModeServiceCallback(std_srvs::EmptyRequest &req, std_srvs::EmptyResponse &res)
void drawFrames(const image_view2::ImageMarker2::ConstPtr &marker, std::vector< CvScalar > &colors, std::vector< CvScalar >::iterator &col_it)
int getLatestCommonTime(const std::string &source_frame, const std::string &target_frame, ros::Time &time, std::string *error_string) const
void setRegionWindowPoint(int x, int y)
std::string encoding
Publisher advertise(const std::string &base_topic, uint32_t queue_size, bool latch=false)
void drawLineStrip(const image_view2::ImageMarker2::ConstPtr &marker, std::vector< CvScalar > &colors, std::vector< CvScalar >::iterator &col_it)
void drawLineList(const image_view2::ImageMarker2::ConstPtr &marker, std::vector< CvScalar > &colors, std::vector< CvScalar >::iterator &col_it)
ros::ServiceServer change_mode_srv_
Definition: image_view2.h:292
void updateRegionWindowSize(int x, int y)
void drawCircle(const image_view2::ImageMarker2::ConstPtr &marker)
TFSIMD_FORCE_INLINE const tfScalar & getY() const
void transformPoint(const std::string &target_frame, const geometry_msgs::PointStamped &stamped_in, geometry_msgs::PointStamped &stamped_out) const
void publishRectFromMaskImage(ros::Publisher &pub, cv::Mat &image, const std_msgs::Header &header)
bool rectangleModeServiceCallback(std_srvs::EmptyRequest &req, std_srvs::EmptyResponse &res)
KEY_MODE stringToMode(const std::string &str)
bool polyModeServiceCallback(std_srvs::EmptyRequest &req, std_srvs::EmptyResponse &res)
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
tf::Vector3 Point
void infoCb(const sensor_msgs::CameraInfoConstPtr &msg)
TFSIMD_FORCE_INLINE const tfScalar & y() const
void drawPoints(const image_view2::ImageMarker2::ConstPtr &marker, std::vector< CvScalar > &colors, std::vector< CvScalar >::iterator &col_it)
TFSIMD_FORCE_INLINE const tfScalar & getZ() const
#define ROS_WARN(...)
V_ImageMarkerMessage marker_queue_
Definition: image_view2.h:202
void addRegionPoint(int x, int y)
boost::mutex point_array_mutex_
Definition: image_view2.h:204
static void mouseCb(int event, int x, int y, int flags, void *param)
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
bool waitForTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration &timeout, const ros::Duration &polling_sleep_duration=ros::Duration(0.01), std::string *error_msg=NULL) const
std::vector< cv::Point2d > poly_points_
Definition: image_view2.h:228
TFSIMD_FORCE_INLINE const tfScalar & x() const
boost::mutex line_point_mutex_
Definition: image_view2.h:265
ros::Publisher rectangle_pub_
Definition: image_view2.h:250
TFSIMD_FORCE_INLINE tfScalar tfCos(tfScalar x)
void drawPoints3D(const image_view2::ImageMarker2::ConstPtr &marker, std::vector< CvScalar > &colors, std::vector< CvScalar >::iterator &col_it)
void drawText(const image_view2::ImageMarker2::ConstPtr &marker, std::vector< CvScalar > &colors, std::vector< CvScalar >::iterator &col_it)
void markerCb(const image_view2::ImageMarker2ConstPtr &marker)
void drawLineList3D(const image_view2::ImageMarker2::ConstPtr &marker, std::vector< CvScalar > &colors, std::vector< CvScalar >::iterator &col_it)
std::string getTopic() const
bool lineModeServiceCallback(std_srvs::EmptyRequest &req, std_srvs::EmptyResponse &res)
#define TFSIMD_RADS_PER_DEG
TFSIMD_FORCE_INLINE const tfScalar & z() const
#define DEFAULT_LINE_WIDTH
Definition: image_view2.h:71
boost::mutex queue_mutex_
Definition: image_view2.h:203
void publish(const sensor_msgs::Image &message) const
void processLeftButtonDown(int x, int y)
ros::Publisher background_mask_pub_
Definition: image_view2.h:254
static void quaternionMsgToTF(const geometry_msgs::Quaternion &msg, Quaternion &bt)
#define ROS_INFO(...)
ros::Publisher foreground_mask_pub_
Definition: image_view2.h:253
bool fromCameraInfo(const sensor_msgs::CameraInfo &msg)
std::vector< cv::Point2d > point_array_
Definition: image_view2.h:221
sensor_msgs::ImageConstPtr last_msg_
Definition: image_view2.h:205
bool param(const std::string &param_name, T &param_val, const T &default_val) const
void drawLineStrip3D(const image_view2::ImageMarker2::ConstPtr &marker, std::vector< CvScalar > &colors, std::vector< CvScalar >::iterator &col_it)
void drawInfo(ros::Time &before_rendering)
CvImagePtr toCvCopy(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
TFSIMD_FORCE_INLINE const tfScalar & y() const
const std::string TYPE_16UC1
image_transport::Publisher local_image_pub_
Definition: image_view2.h:199
void processLeftButtonUp(int x, int y)
void imageCb(const sensor_msgs::ImageConstPtr &msg)
boost::shared_ptr< dynamic_reconfigure::Server< Config > > srv_
Definition: image_view2.h:200
TFSIMD_FORCE_INLINE const tfScalar & x() const
boost::mutex poly_point_mutex_
Definition: image_view2.h:264
bool changeModeServiceCallback(image_view2::ChangeModeRequest &req, image_view2::ChangeModeResponse &res)
void eventCb(const image_view2::MouseEvent::ConstPtr &event_msg)
boost::mutex info_mutex_
Definition: image_view2.h:222
void updatePolySelectingPoint(cv::Point p)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
image_transport::Publisher image_pub_
Definition: image_view2.h:198
boost::format filename_format_
Definition: image_view2.h:234
ros::ServiceServer poly_mode_srv_
Definition: image_view2.h:291
#define ROS_DEBUG_STREAM(args)
TFSIMD_FORCE_INLINE Vector3 & getOrigin()
void lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, StampedTransform &transform) const
image_geometry::PinholeCameraModel cam_model_
Definition: image_view2.h:219
void drawPolygon3D(const image_view2::ImageMarker2::ConstPtr &marker, std::vector< CvScalar > &colors, std::vector< CvScalar >::iterator &col_it)
bool isValidMovement(const cv::Point2f &start_point, const cv::Point2f &end_point)
#define ROS_INFO_STREAM(args)
void transformPose(const std::string &target_frame, const geometry_msgs::PoseStamped &stamped_in, geometry_msgs::PoseStamped &stamped_out) const
int min(int a, int b)
V_ImageMarkerMessage local_queue_
Definition: image_view2.h:191
ros::Publisher move_point_pub_
Definition: image_view2.h:252
ImageView2Config Config
Definition: image_view2.h:86
bool grabcutRectModeServiceCallback(std_srvs::EmptyRequest &req, std_srvs::EmptyResponse &res)
ros::Publisher line_pub_
Definition: image_view2.h:257
void toROSMsg(const sensor_msgs::PointCloud2 &cloud, sensor_msgs::Image &image)
bool lookupTransformation(std::string frame_id, ros::Time &acquisition_time, std::map< std::string, int > &tf_fail, tf::StampedTransform &transform)
TFSIMD_FORCE_INLINE const tfScalar & getX() const
static Time now()
tf::TransformListener tf_listener_
Definition: image_view2.h:218
void pointArrayToMask(std::vector< cv::Point2d > &points, cv::Mat &mask)
#define DEFAULT_CIRCLE_SCALE
Definition: image_view2.h:70
TFSIMD_FORCE_INLINE tfScalar tfSin(tfScalar x)
cv::Point2d project3dToPixel(const cv::Point3d &xyz) const
void checkMousePos(int &x, int &y)
bool grabcutModeServiceCallback(std_srvs::EmptyRequest &req, std_srvs::EmptyResponse &res)
std::string getTopic() const
void updateLineStartPoint(cv::Point p)
void processMouseEvent(int event, int x, int y, int flags, void *param)
ros::ServiceServer grabcut_rect_mode_srv_
Definition: image_view2.h:288
void processMove(int x, int y)
CvScalar MsgToRGB(const std_msgs::ColorRGBA &color)
Definition: image_view2.h:76
std::vector< cv::Point2d > point_bg_array_
Definition: image_view2.h:226
ros::Subscriber event_sub_
Definition: image_view2.h:193
ros::Publisher foreground_rect_pub_
Definition: image_view2.h:255
ros::Subscriber marker_sub_
Definition: image_view2.h:195
#define ROS_ERROR(...)
sensor_msgs::ImagePtr toImageMsg() const
std::string window_name_
Definition: image_view2.h:233
std_msgs::Header header
cv::Point ratioPoint(double x, double y)
void drawCircle3D(const image_view2::ImageMarker2::ConstPtr &marker, std::vector< CvScalar > &colors, std::vector< CvScalar >::iterator &col_it)
ros::Publisher point_array_pub_
Definition: image_view2.h:249
#define ROS_DEBUG(...)


image_view2
Author(s): Kei Okada
autogenerated on Tue Feb 6 2018 03:45:03