00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "image_view2.h"
00037 #include <exception>
00038 namespace image_view2{
00039 ImageView2::ImageView2() : marker_topic_("image_marker"), filename_format_(""), count_(0), mode_(MODE_RECTANGLE), times_(100), window_initialized_(false),space_(10)
00040 {
00041 }
00042
00043 ImageView2::ImageView2(ros::NodeHandle& nh)
00044 : marker_topic_("image_marker"), filename_format_(""), count_(0), mode_(MODE_RECTANGLE), times_(100), selecting_fg_(true),
00045 left_button_clicked_(false), continuous_ready_(false), window_initialized_(false),
00046 line_select_start_point_(true), line_selected_(false), poly_selecting_done_(true)
00047 {
00048 std::string camera = nh.resolveName("image");
00049 std::string camera_info = nh.resolveName("camera_info");
00050 ros::NodeHandle local_nh("~");
00051 std::string format_string;
00052 std::string transport;
00053 image_transport::ImageTransport it(nh);
00054 image_transport::ImageTransport local_it(camera);
00055
00056 point_pub_ = nh.advertise<geometry_msgs::PointStamped>(camera + "/screenpoint",100);
00057 point_array_pub_ = nh.advertise<sensor_msgs::PointCloud2>(camera + "/screenpoint_array",100);
00058 rectangle_pub_ = nh.advertise<geometry_msgs::PolygonStamped>(camera + "/screenrectangle",100);
00059 rectangle_img_pub_ = nh.advertise<sensor_msgs::Image>(camera + "/screenrectangle_image", 100);
00060 move_point_pub_ = nh.advertise<geometry_msgs::PointStamped>(camera + "/movepoint", 100);
00061 foreground_mask_pub_ = nh.advertise<sensor_msgs::Image>(camera + "/foreground", 100);
00062 background_mask_pub_ = nh.advertise<sensor_msgs::Image>(camera + "/background", 100);
00063 foreground_rect_pub_ = nh.advertise<geometry_msgs::PolygonStamped>(camera + "/foreground_rect", 100);
00064 background_rect_pub_ = nh.advertise<geometry_msgs::PolygonStamped>(camera + "/background_rect", 100);
00065 line_pub_ = nh.advertise<geometry_msgs::PolygonStamped>(camera + "/line", 100);
00066 poly_pub_ = nh.advertise<geometry_msgs::PolygonStamped>(camera + "/poly", 100);
00067 local_nh.param("window_name", window_name_, std::string("image_view2 [")+camera+std::string("]"));
00068 local_nh.param("skip_draw_rate", skip_draw_rate_, 0);
00069 local_nh.param("autosize", autosize_, false);
00070 local_nh.param("image_transport", transport, std::string("raw"));
00071 local_nh.param("draw_grid", draw_grid_, false);
00072 local_nh.param("blurry", blurry_mode_, false);
00073 local_nh.param("region_continuous_publish", region_continuous_publish_, false);
00074 local_nh.param("filename_format", format_string, std::string("frame%04i.jpg"));
00075 local_nh.param("use_window", use_window, true);
00076 local_nh.param("show_info", show_info_, false);
00077
00078 double xx,yy;
00079 local_nh.param("resize_scale_x", xx, 1.0);
00080 local_nh.param("resize_scale_y", yy, 1.0);
00081 local_nh.param("tf_timeout", tf_timeout_, 1.0);
00082
00083 std::string interaction_mode;
00084 local_nh.param("interaction_mode", interaction_mode, std::string("rectangle"));
00085 setMode(stringToMode(interaction_mode));
00086 resize_x_ = 1.0/xx;
00087 resize_y_ = 1.0/yy;
00088 filename_format_.parse(format_string);
00089
00090 font_ = cv::FONT_HERSHEY_DUPLEX;
00091 window_selection_.x = window_selection_.y =
00092 window_selection_.height = window_selection_.width = 0;
00093
00094 image_pub_ = it.advertise("image_marked", 1);
00095 local_image_pub_ = local_it.advertise("marked", 1);
00096
00097 image_sub_ = it.subscribe(camera, 1, &ImageView2::imageCb, this, transport);
00098 info_sub_ = nh.subscribe(camera_info, 1, &ImageView2::infoCb, this);
00099 marker_sub_ = nh.subscribe(marker_topic_, 10, &ImageView2::markerCb, this);
00100 event_sub_ = local_nh.subscribe(camera + "/event", 100, &ImageView2::eventCb, this);
00101
00102 change_mode_srv_ = local_nh.advertiseService(
00103 "change_mode", &ImageView2::changeModeServiceCallback, this);
00104 rectangle_mode_srv_ = local_nh.advertiseService(
00105 "rectangle_mode", &ImageView2::rectangleModeServiceCallback, this);
00106 grabcut_mode_srv_ = local_nh.advertiseService(
00107 "grabcut_mode", &ImageView2::grabcutModeServiceCallback, this);
00108 grabcut_rect_mode_srv_ = local_nh.advertiseService(
00109 "grabcut_rect_mode", &ImageView2::grabcutRectModeServiceCallback, this);
00110 line_mode_srv_ = local_nh.advertiseService(
00111 "line_mode", &ImageView2::lineModeServiceCallback, this);
00112 poly_mode_srv_ = local_nh.advertiseService(
00113 "poly_mode", &ImageView2::polyModeServiceCallback, this);
00114 none_mode_srv_ = local_nh.advertiseService(
00115 "none_mode", &ImageView2::noneModeServiceCallback, this);
00116
00117 srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> >(local_nh);
00118 dynamic_reconfigure::Server<Config>::CallbackType f =
00119 boost::bind(&ImageView2::config_callback, this, _1, _2);
00120 srv_->setCallback(f);
00121 }
00122
00123 ImageView2::~ImageView2()
00124 {
00125 if ( use_window ) {
00126 cv::destroyWindow(window_name_.c_str());
00127 }
00128 }
00129
00130 void ImageView2::config_callback(Config &config, uint32_t level)
00131 {
00132 draw_grid_ = config.grid;
00133 fisheye_mode_ = config.fisheye_mode;
00134 div_u_ = config.div_u;
00135 div_v_ = config.div_v;
00136
00137 grid_red_ = config.grid_red;
00138 grid_blue_ = config.grid_blue;
00139 grid_green_ = config.grid_green;
00140 grid_thickness_ = config.grid_thickness;
00141 space_ = config.grid_space;
00142 }
00143
00144 void ImageView2::markerCb(const image_view2::ImageMarker2ConstPtr& marker)
00145 {
00146 ROS_DEBUG("markerCb");
00147
00148 if(marker->lifetime != ros::Duration(0))
00149 boost::const_pointer_cast<image_view2::ImageMarker2>(marker)->lifetime = (ros::Time::now() - ros::Time(0)) + marker->lifetime;
00150 {
00151 boost::mutex::scoped_lock lock(queue_mutex_);
00152 marker_queue_.push_back(marker);
00153 }
00154 redraw();
00155 }
00156
00157 void ImageView2::infoCb(const sensor_msgs::CameraInfoConstPtr& msg) {
00158 ROS_DEBUG("infoCb");
00159 boost::mutex::scoped_lock lock(info_mutex_);
00160 info_msg_ = msg;
00161 }
00162
00163 bool ImageView2::lookupTransformation(
00164 std::string frame_id, ros::Time& acquisition_time,
00165 std::map<std::string, int>& tf_fail,
00166 tf::StampedTransform &transform)
00167 {
00168 ros::Duration timeout(tf_timeout_);
00169 try {
00170 ros::Time tm;
00171 tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
00172 tf_listener_.waitForTransform(cam_model_.tfFrame(), frame_id,
00173 acquisition_time, timeout);
00174 tf_listener_.lookupTransform(cam_model_.tfFrame(), frame_id,
00175 acquisition_time, transform);
00176 tf_fail[frame_id]=0;
00177 return true;
00178 }
00179 catch (tf::TransformException& ex) {
00180 tf_fail[frame_id]++;
00181 if ( tf_fail[frame_id] < 5 ) {
00182 ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
00183 } else {
00184 ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
00185 }
00186 return false;
00187 }
00188 }
00189
00190 void ImageView2::drawCircle(const image_view2::ImageMarker2::ConstPtr& marker)
00191 {
00192 cv::Point2d uv = cv::Point2d(marker->position.x, marker->position.y);
00193 if ( blurry_mode_ ) {
00194 int s0 = (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width);
00195 CvScalar co = MsgToRGB(marker->outline_color);
00196 for (int s1 = s0*10; s1 >= s0; s1--) {
00197 double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
00198 cv::circle(draw_, uv,
00199 (marker->scale == 0 ? DEFAULT_CIRCLE_SCALE : marker->scale),
00200 CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m),
00201 s1);
00202 }
00203 } else {
00204 cv::circle(draw_, uv,
00205 (marker->scale == 0 ? DEFAULT_CIRCLE_SCALE : marker->scale),
00206 MsgToRGB(marker->outline_color),
00207 (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00208 if (marker->filled) {
00209 cv::circle(draw_, uv,
00210 (marker->scale == 0 ? DEFAULT_CIRCLE_SCALE : marker->scale) - (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width) / 2.0,
00211 MsgToRGB(marker->fill_color),
00212 -1);
00213 }
00214 }
00215 }
00216
00217 void ImageView2::drawLineStrip(const image_view2::ImageMarker2::ConstPtr& marker,
00218 std::vector<CvScalar>& colors,
00219 std::vector<CvScalar>::iterator& col_it)
00220 {
00221 cv::Point2d p0, p1;
00222 if ( blurry_mode_ ) {
00223 int s0 = (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width);
00224 std::vector<CvScalar>::iterator col_it = colors.begin();
00225 CvScalar co = (*col_it);
00226 for (int s1 = s0*10; s1 >= s0; s1--) {
00227 double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
00228 std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00229 std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00230 p0 = cv::Point2d(it->x, it->y); it++;
00231 for ( ; it!= end; it++ ) {
00232 p1 = cv::Point2d(it->x, it->y);
00233 cv::line(draw_, p0, p1,
00234 CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m),
00235 s1);
00236 p0 = p1;
00237 if(++col_it == colors.end()) col_it = colors.begin();
00238 }
00239 }
00240 } else {
00241 std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00242 std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00243 p0 = cv::Point2d(it->x, it->y); it++;
00244 for ( ; it!= end; it++ ) {
00245 p1 = cv::Point2d(it->x, it->y);
00246 cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00247 p0 = p1;
00248 if(++col_it == colors.end()) col_it = colors.begin();
00249 }
00250 }
00251 }
00252
00253 void ImageView2::drawLineList(const image_view2::ImageMarker2::ConstPtr& marker,
00254 std::vector<CvScalar>& colors,
00255 std::vector<CvScalar>::iterator& col_it)
00256 {
00257 cv::Point2d p0, p1;
00258 if ( blurry_mode_ ) {
00259 int s0 = (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width);
00260 std::vector<CvScalar>::iterator col_it = colors.begin();
00261 CvScalar co = (*col_it);
00262 for (int s1 = s0*10; s1 >= s0; s1--) {
00263 double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
00264 std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00265 std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00266 for ( ; it!= end; ) {
00267 p0 = cv::Point2d(it->x, it->y); it++;
00268 if ( it != end ) p1 = cv::Point2d(it->x, it->y);
00269 cv::line(draw_, p0, p1, CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m), s1);
00270 it++;
00271 if(++col_it == colors.end()) col_it = colors.begin();
00272 }
00273 }
00274 } else {
00275 std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00276 std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00277 for ( ; it!= end; ) {
00278 p0 = cv::Point2d(it->x, it->y); it++;
00279 if ( it != end ) p1 = cv::Point2d(it->x, it->y);
00280 cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00281 it++;
00282 if(++col_it == colors.end()) col_it = colors.begin();
00283 }
00284 }
00285 }
00286
00287 void ImageView2::drawPolygon(const image_view2::ImageMarker2::ConstPtr& marker,
00288 std::vector<CvScalar>& colors,
00289 std::vector<CvScalar>::iterator& col_it)
00290 {
00291 cv::Point2d p0, p1;
00292 if ( blurry_mode_ ) {
00293 int s0 = (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width);
00294 std::vector<CvScalar>::iterator col_it = colors.begin();
00295 CvScalar co = (*col_it);
00296 for (int s1 = s0*10; s1 >= s0; s1--) {
00297 double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
00298 std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00299 std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00300 p0 = cv::Point2d(it->x, it->y); it++;
00301 for ( ; it!= end; it++ ) {
00302 p1 = cv::Point2d(it->x, it->y);
00303 cv::line(draw_, p0, p1, CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m), s1);
00304 p0 = p1;
00305 if(++col_it == colors.end()) col_it = colors.begin();
00306 }
00307 it = marker->points.begin();
00308 p1 = cv::Point2d(it->x, it->y);
00309 cv::line(draw_, p0, p1, CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m), s1);
00310 }
00311 } else {
00312 std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00313 std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00314 std::vector<cv::Point> points;
00315
00316 if (marker->filled) {
00317 points.push_back(cv::Point(it->x, it->y));
00318 }
00319 p0 = cv::Point2d(it->x, it->y); it++;
00320 for ( ; it!= end; it++ ) {
00321 p1 = cv::Point2d(it->x, it->y);
00322 if (marker->filled) {
00323 points.push_back(cv::Point(it->x, it->y));
00324 }
00325 cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00326 p0 = p1;
00327 if(++col_it == colors.end()) col_it = colors.begin();
00328 }
00329 it = marker->points.begin();
00330 p1 = cv::Point2d(it->x, it->y);
00331 cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00332 if (marker->filled) {
00333 cv::fillConvexPoly(draw_, points.data(), points.size(), MsgToRGB(marker->fill_color));
00334 }
00335 }
00336 }
00337
00338 void ImageView2::drawPoints(const image_view2::ImageMarker2::ConstPtr& marker,
00339 std::vector<CvScalar>& colors,
00340 std::vector<CvScalar>::iterator& col_it)
00341 {
00342 BOOST_FOREACH(geometry_msgs::Point p, marker->points) {
00343 cv::Point2d uv = cv::Point2d(p.x, p.y);
00344 if ( blurry_mode_ ) {
00345 int s0 = (marker->scale == 0 ? 3 : marker->scale);
00346 CvScalar co = (*col_it);
00347 for (int s1 = s0*2; s1 >= s0; s1--) {
00348 double m = pow((1.0-((double)(s1 - s0))/s0),2);
00349 cv::circle(draw_, uv, s1,
00350 CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m),
00351 -1);
00352 }
00353 } else {
00354 cv::circle(draw_, uv, (marker->scale == 0 ? 3 : marker->scale) , *col_it, -1);
00355 }
00356 if(++col_it == colors.end()) col_it = colors.begin();
00357 }
00358 }
00359
00360 void ImageView2::drawFrames(const image_view2::ImageMarker2::ConstPtr& marker,
00361 std::vector<CvScalar>& colors,
00362 std::vector<CvScalar>::iterator& col_it)
00363 {
00364 static std::map<std::string, int> tf_fail;
00365 BOOST_FOREACH(std::string frame_id, marker->frames) {
00366 tf::StampedTransform transform;
00367 ros::Time acquisition_time = last_msg_->header.stamp;
00368 if(!lookupTransformation(frame_id, acquisition_time, tf_fail, transform)) {
00369 return;
00370 }
00371
00372 tf::Point pt = transform.getOrigin();
00373 cv::Point3d pt_cv(pt.x(), pt.y(), pt.z());
00374 cv::Point2d uv;
00375 uv = cam_model_.project3dToPixel(pt_cv);
00376
00377 static const int RADIUS = 3;
00378 cv::circle(draw_, uv, RADIUS, DEFAULT_COLOR, -1);
00379
00380
00381 cv::Point2d uv0, uv1, uv2;
00382 tf::Stamped<tf::Point> pin, pout;
00383
00384
00385 pin = tf::Stamped<tf::Point>(tf::Point(0.05, 0, 0), acquisition_time, frame_id);
00386 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00387 uv0 = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00388
00389 pin = tf::Stamped<tf::Point>(tf::Point(0, 0.05, 0), acquisition_time, frame_id);
00390 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00391 uv1 = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00392
00393
00394 pin = tf::Stamped<tf::Point>(tf::Point(0, 0, 0.05), acquisition_time, frame_id);
00395 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00396 uv2 = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00397
00398
00399 if ( blurry_mode_ ) {
00400 int s0 = 2;
00401 CvScalar c0 = CV_RGB(255,0,0);
00402 CvScalar c1 = CV_RGB(0,255,0);
00403 CvScalar c2 = CV_RGB(0,0,255);
00404 for (int s1 = s0*10; s1 >= s0; s1--) {
00405 double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
00406 cv::line(draw_, uv, uv0,
00407 CV_RGB(c0.val[2] * m,c0.val[1] * m,c0.val[0] * m),
00408 s1);
00409 cv::line(draw_, uv, uv1,
00410 CV_RGB(c1.val[2] * m,c1.val[1] * m,c1.val[0] * m),
00411 s1);
00412 cv::line(draw_, uv, uv2,
00413 CV_RGB(c2.val[2] * m,c2.val[1] * m,c2.val[0] * m),
00414 s1);
00415 }
00416 } else {
00417 cv::line(draw_, uv, uv0, CV_RGB(255,0,0), 2);
00418 cv::line(draw_, uv, uv1, CV_RGB(0,255,0), 2);
00419 cv::line(draw_, uv, uv2, CV_RGB(0,0,255), 2);
00420 }
00421
00422
00423 cv::Size text_size;
00424 int baseline;
00425 text_size = cv::getTextSize(frame_id.c_str(), font_, 1.0, 1.0, &baseline);
00426 cv::Point origin = cv::Point(uv.x - text_size.width / 2,
00427 uv.y - RADIUS - baseline - 3);
00428 cv::putText(draw_, frame_id.c_str(), origin, font_, 1.0, DEFAULT_COLOR, 1.5);
00429 }
00430 }
00431
00432 cv::Point ImageView2::ratioPoint(double x, double y)
00433 {
00434 if (last_msg_) {
00435 return cv::Point(last_msg_->width * x,
00436 last_msg_->height * y);
00437 }
00438 else {
00439 return cv::Point(0, 0);
00440 }
00441 }
00442
00443 void ImageView2::drawText(const image_view2::ImageMarker2::ConstPtr& marker,
00444 std::vector<CvScalar>& colors,
00445 std::vector<CvScalar>::iterator& col_it)
00446 {
00447 cv::Size text_size;
00448 int baseline;
00449 float scale = marker->scale;
00450 if ( scale == 0 ) scale = 1.0;
00451 text_size = cv::getTextSize(marker->text.c_str(), font_,
00452 scale, scale, &baseline);
00453
00454 if (marker->ratio_scale) {
00455 cv::Size a_size = cv::getTextSize("A", font_, 1.0, 1.0, &baseline);
00456 int height_size = a_size.height;
00457 double desired_size = last_msg_->height * scale;
00458 scale = desired_size / height_size;
00459 ROS_DEBUG("text scale: %f", scale);
00460 }
00461
00462 cv::Point origin;
00463 if (marker->left_up_origin) {
00464 if (marker->ratio_scale) {
00465 origin = ratioPoint(marker->position.x,
00466 marker->position.y);
00467 }
00468 else {
00469 origin = cv::Point(marker->position.x,
00470 marker->position.y);
00471 }
00472 }
00473 else {
00474 if (marker->ratio_scale) {
00475 cv::Point p = ratioPoint(marker->position.x, marker->position.y);
00476 origin = cv::Point(p.x - text_size.width/2,
00477 p.y + baseline+3);
00478 }
00479 else {
00480 origin = cv::Point(marker->position.x - text_size.width/2,
00481 marker->position.y + baseline+3);
00482 }
00483 }
00484
00485 if (marker->filled) {
00486 cv::putText(draw_, marker->text.c_str(), origin, font_, scale, DEFAULT_COLOR, marker->filled);
00487
00488 }
00489 else {
00490 cv::putText(draw_, marker->text.c_str(), origin, font_, scale, DEFAULT_COLOR);
00491 }
00492 }
00493
00494 void ImageView2::drawLineStrip3D(const image_view2::ImageMarker2::ConstPtr& marker,
00495 std::vector<CvScalar>& colors,
00496 std::vector<CvScalar>::iterator& col_it)
00497 {
00498 static std::map<std::string, int> tf_fail;
00499 std::string frame_id = marker->points3D.header.frame_id;
00500 tf::StampedTransform transform;
00501 ros::Time acquisition_time = last_msg_->header.stamp;
00502
00503 ros::Duration timeout(tf_timeout_);
00504 try {
00505 ros::Time tm;
00506 tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
00507 ros::Duration diff = ros::Time::now() - tm;
00508 if ( diff > ros::Duration(1.0) ) { return; }
00509 tf_listener_.waitForTransform(cam_model_.tfFrame(), frame_id,
00510 acquisition_time, timeout);
00511 tf_listener_.lookupTransform(cam_model_.tfFrame(), frame_id,
00512 acquisition_time, transform);
00513 tf_fail[frame_id]=0;
00514 }
00515 catch (tf::TransformException& ex) {
00516 tf_fail[frame_id]++;
00517 if ( tf_fail[frame_id] < 5 ) {
00518 ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
00519 } else {
00520 ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
00521 }
00522 return;
00523 }
00524 std::vector<geometry_msgs::Point> points2D;
00525 BOOST_FOREACH(geometry_msgs::Point p, marker->points3D.points) {
00526 tf::Point pt = transform.getOrigin();
00527 geometry_msgs::PointStamped pt_cam, pt_;
00528 pt_cam.header.frame_id = cam_model_.tfFrame();
00529 pt_cam.header.stamp = acquisition_time;
00530 pt_cam.point.x = pt.x();
00531 pt_cam.point.y = pt.y();
00532 pt_cam.point.z = pt.z();
00533 tf_listener_.transformPoint(frame_id, pt_cam, pt_);
00534
00535 cv::Point2d uv;
00536 tf::Stamped<tf::Point> pin, pout;
00537 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);
00538 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00539 uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00540 geometry_msgs::Point point2D;
00541 point2D.x = uv.x;
00542 point2D.y = uv.y;
00543 points2D.push_back(point2D);
00544 }
00545 cv::Point2d p0, p1;
00546 std::vector<geometry_msgs::Point>::const_iterator it = points2D.begin();
00547 std::vector<geometry_msgs::Point>::const_iterator end = points2D.end();
00548 p0 = cv::Point2d(it->x, it->y); it++;
00549 for ( ; it!= end; it++ ) {
00550 p1 = cv::Point2d(it->x, it->y);
00551 cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00552 p0 = p1;
00553 if(++col_it == colors.end()) col_it = colors.begin();
00554 }
00555 }
00556
00557 void ImageView2::drawLineList3D(const image_view2::ImageMarker2::ConstPtr& marker,
00558 std::vector<CvScalar>& colors,
00559 std::vector<CvScalar>::iterator& col_it)
00560 {
00561 static std::map<std::string, int> tf_fail;
00562 std::string frame_id = marker->points3D.header.frame_id;
00563 tf::StampedTransform transform;
00564 ros::Time acquisition_time = last_msg_->header.stamp;
00565 if(!lookupTransformation(frame_id, acquisition_time, tf_fail, transform)) {
00566 return;
00567 }
00568 std::vector<geometry_msgs::Point> points2D;
00569 BOOST_FOREACH(geometry_msgs::Point p, marker->points3D.points) {
00570 tf::Point pt = transform.getOrigin();
00571 geometry_msgs::PointStamped pt_cam, pt_;
00572 pt_cam.header.frame_id = cam_model_.tfFrame();
00573 pt_cam.header.stamp = acquisition_time;
00574 pt_cam.point.x = pt.x();
00575 pt_cam.point.y = pt.y();
00576 pt_cam.point.z = pt.z();
00577 tf_listener_.transformPoint(frame_id, pt_cam, pt_);
00578
00579 cv::Point2d uv;
00580 tf::Stamped<tf::Point> pin, pout;
00581 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);
00582 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00583 uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00584 geometry_msgs::Point point2D;
00585 point2D.x = uv.x;
00586 point2D.y = uv.y;
00587 points2D.push_back(point2D);
00588 }
00589 cv::Point2d p0, p1;
00590 std::vector<geometry_msgs::Point>::const_iterator it = points2D.begin();
00591 std::vector<geometry_msgs::Point>::const_iterator end = points2D.end();
00592 for ( ; it!= end; ) {
00593 p0 = cv::Point2d(it->x, it->y); it++;
00594 if ( it != end ) p1 = cv::Point2d(it->x, it->y);
00595 cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00596 it++;
00597 if(++col_it == colors.end()) col_it = colors.begin();
00598 }
00599 }
00600
00601 void ImageView2::drawPolygon3D(const image_view2::ImageMarker2::ConstPtr& marker,
00602 std::vector<CvScalar>& colors,
00603 std::vector<CvScalar>::iterator& col_it)
00604 {
00605 static std::map<std::string, int> tf_fail;
00606 std::string frame_id = marker->points3D.header.frame_id;
00607 tf::StampedTransform transform;
00608 ros::Time acquisition_time = last_msg_->header.stamp;
00609 if(!lookupTransformation(frame_id, acquisition_time, tf_fail, transform)) {
00610 return;
00611 }
00612 std::vector<geometry_msgs::Point> points2D;
00613 BOOST_FOREACH(geometry_msgs::Point p, marker->points3D.points) {
00614 tf::Point pt = transform.getOrigin();
00615 geometry_msgs::PointStamped pt_cam, pt_;
00616 pt_cam.header.frame_id = cam_model_.tfFrame();
00617 pt_cam.header.stamp = acquisition_time;
00618 pt_cam.point.x = pt.x();
00619 pt_cam.point.y = pt.y();
00620 pt_cam.point.z = pt.z();
00621 tf_listener_.transformPoint(frame_id, pt_cam, pt_);
00622
00623 cv::Point2d uv;
00624 tf::Stamped<tf::Point> pin, pout;
00625 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);
00626 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00627 uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00628 geometry_msgs::Point point2D;
00629 point2D.x = uv.x;
00630 point2D.y = uv.y;
00631 points2D.push_back(point2D);
00632 }
00633 cv::Point2d p0, p1;
00634 std::vector<geometry_msgs::Point>::const_iterator it = points2D.begin();
00635 std::vector<geometry_msgs::Point>::const_iterator end = points2D.end();
00636 std::vector<cv::Point> points;
00637
00638 if (marker->filled) {
00639 points.push_back(cv::Point(it->x, it->y));
00640 }
00641 p0 = cv::Point2d(it->x, it->y); it++;
00642 for ( ; it!= end; it++ ) {
00643 p1 = cv::Point2d(it->x, it->y);
00644 if (marker->filled) {
00645 points.push_back(cv::Point(it->x, it->y));
00646 }
00647 cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00648 p0 = p1;
00649 if(++col_it == colors.end()) col_it = colors.begin();
00650 }
00651 it = points2D.begin();
00652 p1 = cv::Point2d(it->x, it->y);
00653 cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00654 if (marker->filled) {
00655 cv::fillConvexPoly(draw_, points.data(), points.size(), MsgToRGB(marker->fill_color));
00656 }
00657 }
00658
00659 void ImageView2::drawPoints3D(const image_view2::ImageMarker2::ConstPtr& marker,
00660 std::vector<CvScalar>& colors,
00661 std::vector<CvScalar>::iterator& col_it)
00662 {
00663 static std::map<std::string, int> tf_fail;
00664 std::string frame_id = marker->points3D.header.frame_id;
00665 tf::StampedTransform transform;
00666 ros::Time acquisition_time = last_msg_->header.stamp;
00667 if(!lookupTransformation(frame_id, acquisition_time, tf_fail, transform)) {
00668 return;
00669 }
00670 BOOST_FOREACH(geometry_msgs::Point p, marker->points3D.points) {
00671 tf::Point pt = transform.getOrigin();
00672 geometry_msgs::PointStamped pt_cam, pt_;
00673 pt_cam.header.frame_id = cam_model_.tfFrame();
00674 pt_cam.header.stamp = acquisition_time;
00675 pt_cam.point.x = pt.x();
00676 pt_cam.point.y = pt.y();
00677 pt_cam.point.z = pt.z();
00678 tf_listener_.transformPoint(frame_id, pt_cam, pt_);
00679
00680 cv::Point2d uv;
00681 tf::Stamped<tf::Point> pin, pout;
00682 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);
00683 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00684 uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00685 cv::circle(draw_, uv, (marker->scale == 0 ? 3 : marker->scale) , *col_it, -1);
00686 }
00687 }
00688
00689 void ImageView2::drawText3D(const image_view2::ImageMarker2::ConstPtr& marker,
00690 std::vector<CvScalar>& colors,
00691 std::vector<CvScalar>::iterator& col_it)
00692 {
00693 static std::map<std::string, int> tf_fail;
00694 std::string frame_id = marker->position3D.header.frame_id;
00695 tf::StampedTransform transform;
00696 ros::Time acquisition_time = last_msg_->header.stamp;
00697 if(!lookupTransformation(frame_id, acquisition_time, tf_fail, transform)) {
00698 return;
00699 }
00700 tf::Point pt = transform.getOrigin();
00701 geometry_msgs::PointStamped pt_cam, pt_;
00702 pt_cam.header.frame_id = cam_model_.tfFrame();
00703 pt_cam.header.stamp = acquisition_time;
00704 pt_cam.point.x = pt.x();
00705 pt_cam.point.y = pt.y();
00706 pt_cam.point.z = pt.z();
00707 tf_listener_.transformPoint(frame_id, pt_cam, pt_);
00708
00709 cv::Point2d uv;
00710 tf::Stamped<tf::Point> pin, pout;
00711 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);
00712 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00713 uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00714 cv::Size text_size;
00715 int baseline;
00716 float scale = marker->scale;
00717 if ( scale == 0 ) scale = 1.0;
00718 text_size = cv::getTextSize(marker->text.c_str(), font_,
00719 scale, scale, &baseline);
00720 cv::Point origin = cv::Point(uv.x - text_size.width/2,
00721 uv.y - baseline-3);
00722 cv::putText(draw_, marker->text.c_str(), origin, font_, scale, CV_RGB(0,255,0),3);
00723 }
00724
00725 void ImageView2::drawCircle3D(const image_view2::ImageMarker2::ConstPtr& marker,
00726 std::vector<CvScalar>& colors,
00727 std::vector<CvScalar>::iterator& col_it)
00728 {
00729 static std::map<std::string, int> tf_fail;
00730 std::string frame_id = marker->pose.header.frame_id;
00731 geometry_msgs::PoseStamped pose;
00732 ros::Time acquisition_time = last_msg_->header.stamp;
00733 ros::Duration timeout(tf_timeout_);
00734 try {
00735 ros::Time tm;
00736 tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
00737 tf_listener_.waitForTransform(cam_model_.tfFrame(), frame_id,
00738 acquisition_time, timeout);
00739 tf_listener_.transformPose(cam_model_.tfFrame(),
00740 acquisition_time, marker->pose, frame_id, pose);
00741 tf_fail[frame_id]=0;
00742 }
00743 catch (tf::TransformException& ex) {
00744 tf_fail[frame_id]++;
00745 if ( tf_fail[frame_id] < 5 ) {
00746 ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
00747 } else {
00748 ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
00749 }
00750 return;
00751 }
00752
00753 tf::Quaternion q;
00754 tf::quaternionMsgToTF(pose.pose.orientation, q);
00755 tf::Matrix3x3 rot = tf::Matrix3x3(q);
00756 double angle = (marker->arc == 0 ? 360.0 :marker->angle);
00757 double scale = (marker->scale == 0 ? DEFAULT_CIRCLE_SCALE : marker->scale);
00758 int N = 100;
00759 std::vector< std::vector<cv::Point2i> > ptss;
00760 std::vector<cv::Point2i> pts;
00761
00762 for (int i=0; i<N; ++i) {
00763 double th = angle * i / N * TFSIMD_RADS_PER_DEG;
00764 tf::Vector3 v = rot * tf::Vector3(scale * tfCos(th), scale * tfSin(th),0);
00765 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()));
00766 pts.push_back(cv::Point2i((int)pt.x, (int)pt.y));
00767 }
00768 ptss.push_back(pts);
00769
00770 cv::polylines(draw_, ptss, (marker->arc == 0 ? true : false), MsgToRGB(marker->outline_color), (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00771
00772 if (marker->filled) {
00773 if(marker->arc != 0){
00774 cv::Point2d pt = cam_model_.project3dToPixel(cv::Point3d(pose.pose.position.x, pose.pose.position.y, pose.pose.position.z));
00775 pts.push_back(cv::Point2i((int)pt.x, (int)pt.y));
00776 ptss.clear();
00777 ptss.push_back(pts);
00778 }
00779 cv::fillPoly(draw_, ptss, MsgToRGB(marker->fill_color));
00780 }
00781 }
00782
00783 void ImageView2::resolveLocalMarkerQueue()
00784 {
00785 {
00786 boost::mutex::scoped_lock lock(queue_mutex_);
00787
00788 while ( ! marker_queue_.empty() ) {
00789
00790 V_ImageMarkerMessage::iterator new_msg = marker_queue_.begin();
00791 V_ImageMarkerMessage::iterator message_it = local_queue_.begin();
00792 for ( ; message_it < local_queue_.end(); ++message_it ) {
00793 if((*new_msg)->ns == (*message_it)->ns && (*new_msg)->id == (*message_it)->id)
00794 message_it = local_queue_.erase(message_it);
00795 }
00796 local_queue_.push_back(*new_msg);
00797 marker_queue_.erase(new_msg);
00798
00799 if ( (*new_msg)->action == image_view2::ImageMarker2::REMOVE &&
00800 (*new_msg)->id == -1 ) {
00801 local_queue_.clear();
00802 }
00803 }
00804 }
00805
00806
00807 for(V_ImageMarkerMessage::iterator it = local_queue_.begin(); it < local_queue_.end(); it++) {
00808 if((*it)->action == image_view2::ImageMarker2::REMOVE ||
00809 ((*it)->lifetime.toSec() != 0.0 && (*it)->lifetime.toSec() < ros::Time::now().toSec())) {
00810 it = local_queue_.erase(it);
00811 }
00812 }
00813 }
00814
00815 void ImageView2::drawMarkers()
00816 {
00817 resolveLocalMarkerQueue();
00818 if ( !local_queue_.empty() )
00819 {
00820 V_ImageMarkerMessage::iterator message_it = local_queue_.begin();
00821 V_ImageMarkerMessage::iterator message_end = local_queue_.end();
00822 ROS_DEBUG("markers = %ld", local_queue_.size());
00823
00824 for ( ; message_it != message_end; ++message_it )
00825 {
00826 image_view2::ImageMarker2::ConstPtr& marker = *message_it;
00827
00828 ROS_DEBUG_STREAM("message type = " << marker->type << ", id " << marker->id);
00829
00830
00831 std::vector<CvScalar> colors;
00832 BOOST_FOREACH(std_msgs::ColorRGBA color, marker->outline_colors) {
00833 colors.push_back(MsgToRGB(color));
00834 }
00835 if(colors.size() == 0) colors.push_back(DEFAULT_COLOR);
00836 std::vector<CvScalar>::iterator col_it = colors.begin();
00837
00838
00839 if( marker->type == image_view2::ImageMarker2::FRAMES ||
00840 marker->type == image_view2::ImageMarker2::LINE_STRIP3D ||
00841 marker->type == image_view2::ImageMarker2::LINE_LIST3D ||
00842 marker->type == image_view2::ImageMarker2::POLYGON3D ||
00843 marker->type == image_view2::ImageMarker2::POINTS3D ||
00844 marker->type == image_view2::ImageMarker2::TEXT3D ||
00845 marker->type == image_view2::ImageMarker2::CIRCLE3D) {
00846 {
00847 boost::mutex::scoped_lock lock(info_mutex_);
00848 if (!info_msg_) {
00849 ROS_WARN("[image_view2] camera_info could not found");
00850 continue;
00851 }
00852 cam_model_.fromCameraInfo(info_msg_);
00853 }
00854 }
00855
00856 switch ( marker->type ) {
00857 case image_view2::ImageMarker2::CIRCLE: {
00858 drawCircle(marker);
00859 break;
00860 }
00861 case image_view2::ImageMarker2::LINE_STRIP: {
00862 drawLineStrip(marker, colors, col_it);
00863 break;
00864 }
00865 case image_view2::ImageMarker2::LINE_LIST: {
00866 drawLineList(marker, colors, col_it);
00867 break;
00868 }
00869 case image_view2::ImageMarker2::POLYGON: {
00870 drawPolygon(marker, colors, col_it);
00871 break;
00872 }
00873 case image_view2::ImageMarker2::POINTS: {
00874 drawPoints(marker, colors, col_it);
00875 break;
00876 }
00877 case image_view2::ImageMarker2::FRAMES: {
00878 drawFrames(marker, colors, col_it);
00879 break;
00880 }
00881 case image_view2::ImageMarker2::TEXT: {
00882 drawText(marker, colors, col_it);
00883 break;
00884 }
00885 case image_view2::ImageMarker2::LINE_STRIP3D: {
00886 drawLineStrip3D(marker, colors, col_it);
00887 break;
00888 }
00889 case image_view2::ImageMarker2::LINE_LIST3D: {
00890 drawLineList3D(marker, colors, col_it);
00891 break;
00892 }
00893 case image_view2::ImageMarker2::POLYGON3D: {
00894 drawPolygon3D(marker, colors, col_it);
00895 break;
00896 }
00897 case image_view2::ImageMarker2::POINTS3D: {
00898 drawPoints3D(marker, colors, col_it);
00899 break;
00900 }
00901 case image_view2::ImageMarker2::TEXT3D: {
00902 drawText3D(marker, colors, col_it);
00903 break;
00904 }
00905 case image_view2::ImageMarker2::CIRCLE3D: {
00906 drawCircle3D(marker, colors, col_it);
00907 break;
00908 }
00909 default: {
00910 ROS_WARN("Undefined Marker type(%d)", marker->type);
00911 break;
00912 }
00913 }
00914 }
00915 }
00916 }
00917
00918 void ImageView2::drawInteraction()
00919 {
00920 if (mode_ == MODE_RECTANGLE) {
00921 cv::rectangle(draw_, cv::Point(window_selection_.x, window_selection_.y),
00922 cv::Point(window_selection_.x + window_selection_.width,
00923 window_selection_.y + window_selection_.height),
00924 USER_ROI_COLOR, 3, 8, 0);
00925 }
00926 else if (mode_ == MODE_SERIES) {
00927 if (point_array_.size() > 1) {
00928 cv::Point2d from, to;
00929 from = point_array_[0];
00930 for (size_t i = 1; i < point_array_.size(); i++) {
00931 to = point_array_[i];
00932 cv::line(draw_, from, to, USER_ROI_COLOR, 2, 8, 0);
00933 from = to;
00934 }
00935 }
00936 }
00937 else if (mode_ == MODE_SELECT_FORE_AND_BACK) {
00938 boost::mutex::scoped_lock lock(point_array_mutex_);
00939 if (point_fg_array_.size() > 1) {
00940 cv::Point2d from, to;
00941 from = point_fg_array_[0];
00942 for (size_t i = 1; i < point_fg_array_.size(); i++) {
00943 to = point_fg_array_[i];
00944 cv::line(draw_, from, to, CV_RGB(255, 0, 0), 8, 8, 0);
00945 from = to;
00946 }
00947 }
00948 if (point_bg_array_.size() > 1) {
00949 cv::Point2d from, to;
00950 from = point_bg_array_[0];
00951 for (size_t i = 1; i < point_bg_array_.size(); i++) {
00952 to = point_bg_array_[i];
00953 cv::line(draw_, from, to, CV_RGB(0, 255, 0), 8, 8, 0);
00954 from = to;
00955 }
00956 }
00957 }
00958 else if (mode_ == MODE_SELECT_FORE_AND_BACK_RECT) {
00959 boost::mutex::scoped_lock lock(point_array_mutex_);
00960 if (rect_fg_.width != 0 && rect_fg_.height != 0) {
00961 cv::rectangle(draw_,
00962 cv::Point(rect_fg_.x, rect_fg_.y),
00963 cv::Point(rect_fg_.x + rect_fg_.width, rect_fg_.y + rect_fg_.height),
00964 CV_RGB(255, 0, 0), 4);
00965 }
00966 if (rect_bg_.width != 0 && rect_bg_.height != 0) {
00967 cv::rectangle(draw_,
00968 cv::Point(rect_bg_.x, rect_bg_.y),
00969 cv::Point(rect_bg_.x + rect_bg_.width, rect_bg_.y + rect_bg_.height),
00970 CV_RGB(0, 255, 0), 4);
00971 }
00972 }
00973 else if (mode_ == MODE_LINE) {
00974 boost::mutex::scoped_lock lock(line_point_mutex_);
00975 if (line_selected_) {
00976 cv::line(draw_, line_start_point_, line_end_point_, CV_RGB(0, 255, 0), 8, 8, 0);
00977 }
00978 }
00979 else if (mode_ == MODE_POLY) {
00980 boost::mutex::scoped_lock lock(poly_point_mutex_);
00981 if (poly_points_.size() > 0) {
00982
00983 for (size_t i = 0; i < poly_points_.size() - 1; i++) {
00984 cv::line(draw_, poly_points_[i], poly_points_[i + 1], CV_RGB(255, 0, 0), 8, 8, 0);
00985 }
00986
00987 if (poly_selecting_done_) {
00988 cv::line(draw_, poly_points_[poly_points_.size() - 1],
00989 poly_points_[0],
00990 CV_RGB(255, 0, 0), 8, 8, 0);
00991 }
00992 else {
00993 cv::line(draw_, poly_points_[poly_points_.size() - 1],
00994 poly_selecting_point_,
00995 CV_RGB(0, 255, 0), 8, 8, 0);
00996 }
00997 }
00998 }
00999 }
01000
01001 void ImageView2::drawInfo(ros::Time& before_rendering)
01002 {
01003 static ros::Time last_time;
01004 static std::string info_str_1, info_str_2;
01005
01006 if ( show_info_ && times_.size() > 0 && ( before_rendering.toSec() - last_time.toSec() > 2 ) ) {
01007 int n = times_.size();
01008 double mean = 0, rate = 1.0, std_dev = 0.0, max_delta, min_delta;
01009
01010 std::for_each( times_.begin(), times_.end(), (mean += boost::lambda::_1) );
01011 mean /= n;
01012 rate /= mean;
01013
01014 std::for_each( times_.begin(), times_.end(), (std_dev += (boost::lambda::_1 - mean)*(boost::lambda::_1 - mean) ) );
01015 std_dev = sqrt(std_dev/n);
01016 min_delta = *std::min_element(times_.begin(), times_.end());
01017 max_delta = *std::max_element(times_.begin(), times_.end());
01018
01019 std::stringstream f1, f2;
01020 f1.precision(3); f1 << std::fixed;
01021 f2.precision(3); f2 << std::fixed;
01022 f1 << "" << image_sub_.getTopic() << " : rate:" << rate;
01023 f2 << "min:" << min_delta << "s max: " << max_delta << "s std_dev: " << std_dev << "s n: " << n;
01024 info_str_1 = f1.str();
01025 info_str_2 = f2.str();
01026 ROS_INFO_STREAM(info_str_1 + " " + info_str_2);
01027 times_.clear();
01028 last_time = before_rendering;
01029 }
01030 if (!info_str_1.empty() && !info_str_2.empty()) {
01031 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);
01032 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);
01033 }
01034 }
01035
01036 void ImageView2::cropROI()
01037 {
01038 if (mode_ == MODE_RECTANGLE) {
01039
01040 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));
01041 cv::Mat cropped_img = original_image_(screen_rect);
01042 rectangle_img_pub_.publish(
01043 cv_bridge::CvImage(
01044 last_msg_->header,
01045 last_msg_->encoding,
01046 cropped_img).toImageMsg());
01047 }
01048 }
01049
01050 void ImageView2::redraw()
01051 {
01052 if (original_image_.empty()) {
01053 ROS_WARN("no image is available yet");
01054 return;
01055 }
01056 ros::Time before_rendering = ros::Time::now();
01057 original_image_.copyTo(image_);
01058
01059 if ( blurry_mode_ ) {
01060 draw_ = cv::Mat(image_.size(), image_.type(), CV_RGB(0,0,0));
01061 } else {
01062 draw_ = image_;
01063 }
01064 drawMarkers();
01065 drawInteraction();
01066 cropROI();
01067
01068 if ( draw_grid_ ) drawGrid();
01069 if ( blurry_mode_ ) cv::addWeighted(image_, 0.9, draw_, 1.0, 0.0, image_);
01070 if ( use_window ) {
01071 if (show_info_) {
01072 drawInfo(before_rendering);
01073 }
01074 }
01075 cv_bridge::CvImage out_msg;
01076 out_msg.header = last_msg_->header;
01077 out_msg.encoding = "bgr8";
01078 out_msg.image = image_;
01079 image_pub_.publish(out_msg.toImageMsg());
01080 local_image_pub_.publish(out_msg.toImageMsg());
01081 }
01082
01083 void ImageView2::createDistortGridImage()
01084 {
01085 distort_grid_mask_.setTo(cv::Scalar(0,0,0));
01086 cv::Mat distort_grid_mask(draw_.size(), CV_8UC1);
01087 distort_grid_mask.setTo(cv::Scalar(0));
01088 const float K = 341.0;
01089 float R_divier = (1.0/(draw_.cols/2)), center_x = distort_grid_mask.rows/2, center_y = distort_grid_mask.cols/2;
01090 for(int degree = -80; degree<=80; degree+=space_){
01091 double C = draw_.cols/2.0 * tan(degree * 3.14159265/180);
01092 for(float theta = -1.57; theta <= 1.57; theta+=0.001){
01093 double sin_phi = C * R_divier / tan(theta);
01094 if (sin_phi > 1.0 || sin_phi < -1.0)
01095 continue;
01096 int x1 = K * theta * sqrt(1-sin_phi * sin_phi) + center_x;
01097 int y1 = K * theta * sin_phi + center_y;
01098 int x2 = K * theta * sin_phi + center_x;
01099 int y2 = K * theta * sqrt(1-sin_phi * sin_phi) + center_y;
01100 cv::circle(distort_grid_mask, cvPoint(y1, x1), 2, 1, grid_thickness_);
01101 cv::circle(distort_grid_mask, cvPoint(y2, x2), 2, 1, grid_thickness_);
01102 }
01103 }
01104 cv::Mat red(draw_.size(), draw_.type(), CV_8UC3);
01105 red = cv::Scalar(grid_blue_, grid_green_, grid_red_);
01106 red.copyTo(distort_grid_mask_, distort_grid_mask);
01107 }
01108
01109 void ImageView2::drawGrid()
01110 {
01111 if(fisheye_mode_){
01112 if(space_ != prev_space_ || prev_red_ != grid_red_
01113 || prev_green_ != grid_green_ || prev_blue_ != grid_blue_
01114 || prev_thickness_ != grid_thickness_){
01115 createDistortGridImage();
01116 prev_space_ = space_;
01117 prev_red_ = grid_red_;
01118 prev_green_ = grid_green_;
01119 prev_blue_ = grid_blue_;
01120 prev_thickness_ = grid_thickness_;
01121 }
01122 cv::add(draw_, distort_grid_mask_, draw_);
01123 }else{
01124
01125 cv::Point2d p0 = cv::Point2d(0, last_msg_->height/2.0);
01126 cv::Point2d p1 = cv::Point2d(last_msg_->width, last_msg_->height/2.0);
01127 cv::line(draw_, p0, p1, CV_RGB(255,0,0), DEFAULT_LINE_WIDTH);
01128
01129 cv::Point2d p2 = cv::Point2d(last_msg_->width/2.0, 0);
01130 cv::Point2d p3 = cv::Point2d(last_msg_->width/2.0, last_msg_->height);
01131 cv::line(draw_, p2, p3, CV_RGB(255,0,0), DEFAULT_LINE_WIDTH);
01132
01133 for(int i = 1; i < div_u_ ;i ++){
01134 cv::Point2d u0 = cv::Point2d(0, last_msg_->height * i * 1.0 / div_u_);
01135 cv::Point2d u1 = cv::Point2d(last_msg_->width, last_msg_->height * i * 1.0 / div_u_);
01136 cv::line(draw_, u0, u1, CV_RGB(255,0,0), 1);
01137 }
01138
01139 for(int i = 1; i < div_v_ ;i ++){
01140 cv::Point2d v0 = cv::Point2d(last_msg_->width * i * 1.0 / div_v_, 0);
01141 cv::Point2d v1 = cv::Point2d(last_msg_->width * i * 1.0 / div_v_, last_msg_->height);
01142 cv::line(draw_, v0, v1, CV_RGB(255,0,0), 1);
01143 }
01144 }
01145 }
01146
01147 void ImageView2::imageCb(const sensor_msgs::ImageConstPtr& msg)
01148 {
01149 if (msg->width == 0 && msg->height == 0) {
01150 ROS_DEBUG("invalid image");
01151 return;
01152 }
01153 static int count = 0;
01154 if (count < skip_draw_rate_) {
01155 count++;
01156 return;
01157 }
01158 else {
01159 count = 0;
01160 }
01161 static ros::Time old_time;
01162 times_.push_front(ros::Time::now().toSec() - old_time.toSec());
01163 old_time = ros::Time::now();
01164
01165 if(old_time.toSec() - ros::Time::now().toSec() > 0) {
01166 ROS_WARN("TF Cleared for old time");
01167 }
01168 {
01169 boost::mutex::scoped_lock lock(image_mutex_);
01170 if (msg->encoding.find("bayer") != std::string::npos) {
01171 original_image_ = cv::Mat(msg->height, msg->width, CV_8UC1,
01172 const_cast<uint8_t*>(&msg->data[0]), msg->step);
01173 } else if (msg->encoding == sensor_msgs::image_encodings::TYPE_16UC1) {
01174
01175 cv::Mat input_image = cv_bridge::toCvCopy(msg)->image;
01176 double min, max;
01177 cv::minMaxIdx(input_image, &min, &max);
01178 cv::convertScaleAbs(input_image, original_image_, 255 / max);
01179 } else {
01180 try {
01181 original_image_ = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8)->image;
01182 } catch (cv_bridge::Exception& e) {
01183 ROS_ERROR("Unable to convert %s image to bgr8", msg->encoding.c_str());
01184 return;
01185 }
01186 }
01187
01188 last_msg_ = msg;
01189 redraw();
01190 }
01191 if (region_continuous_publish_ && continuous_ready_) {
01192 publishMouseInteractionResult();
01193 }
01194 }
01195
01196 void ImageView2::drawImage() {
01197 if (image_.rows > 0 && image_.cols > 0) {
01198 redraw();
01199 }
01200 }
01201
01202 void ImageView2::addPoint(int x, int y)
01203 {
01204 cv::Point2d p;
01205 p.x = x;
01206 p.y = y;
01207 {
01208 boost::mutex::scoped_lock lock(point_array_mutex_);
01209 point_array_.push_back(p);
01210 }
01211 }
01212
01213 void ImageView2::setRegionWindowPoint(int x, int y)
01214 {
01215 boost::mutex::scoped_lock lock(point_array_mutex_);
01216 ROS_DEBUG("setRegionWindowPoint(%d, %d)", x, y);
01217 if (selecting_fg_) {
01218 rect_fg_.x = x;
01219 rect_fg_.y = y;
01220 rect_fg_.width = 0;
01221 rect_fg_.height = 0;
01222 }
01223 else {
01224 rect_bg_.x = x;
01225 rect_bg_.y = y;
01226 rect_bg_.width = 0;
01227 rect_bg_.height = 0;
01228 }
01229 }
01230
01231 void ImageView2::updateRegionWindowSize(int x, int y)
01232 {
01233 ROS_DEBUG("updateRegionWindowPoint");
01234 boost::mutex::scoped_lock lock(point_array_mutex_);
01235 if (selecting_fg_) {
01236 rect_fg_.width = x - rect_fg_.x;
01237 rect_fg_.height = y - rect_fg_.y;
01238 }
01239 else {
01240 rect_bg_.width = x - rect_bg_.x;
01241 rect_bg_.height = y - rect_bg_.y;
01242 }
01243 }
01244
01245 void ImageView2::addRegionPoint(int x, int y)
01246 {
01247 cv::Point2d p;
01248 p.x = x;
01249 p.y = y;
01250 {
01251 boost::mutex::scoped_lock lock(point_array_mutex_);
01252 if (selecting_fg_) {
01253 point_fg_array_.push_back(p);
01254 }
01255 else {
01256 point_bg_array_.push_back(p);
01257 }
01258 }
01259 }
01260
01261 void ImageView2::clearPointArray()
01262 {
01263 boost::mutex::scoped_lock lock(point_array_mutex_);
01264 point_fg_array_.clear();
01265 point_bg_array_.clear();
01266 point_array_.clear();
01267 }
01268
01269 void ImageView2::publishPointArray()
01270 {
01271 pcl::PointCloud<pcl::PointXY> pcl_cloud;
01272 for (size_t i = 0; i < point_array_.size(); i++) {
01273 pcl::PointXY p;
01274 p.x = point_array_[i].x;
01275 p.y = point_array_[i].y;
01276 pcl_cloud.points.push_back(p);
01277 }
01278 sensor_msgs::PointCloud2::Ptr ros_cloud(new sensor_msgs::PointCloud2);
01279 pcl::toROSMsg(pcl_cloud, *ros_cloud);
01280 ros_cloud->header.stamp = ros::Time::now();
01281
01282 point_array_pub_.publish(ros_cloud);
01283 }
01284
01285
01286 void ImageView2::setMode(KEY_MODE mode)
01287 {
01288 mode_ = mode;
01289 }
01290
01291 ImageView2::KEY_MODE ImageView2::getMode()
01292 {
01293 return mode_;
01294 }
01295
01296 bool ImageView2::toggleSelection()
01297 {
01298 boost::mutex::scoped_lock lock(point_array_mutex_);
01299 selecting_fg_ = !selecting_fg_;
01300 return selecting_fg_;
01301 }
01302
01303 void ImageView2::pointArrayToMask(std::vector<cv::Point2d>& points,
01304 cv::Mat& mask)
01305 {
01306 cv::Point2d from, to;
01307 if (points.size() > 1) {
01308 from = points[0];
01309 for (size_t i = 1; i < points.size(); i++) {
01310 to = points[i];
01311 cv::line(mask, from, to, cv::Scalar(255), 8, 8, 0);
01312 from = to;
01313 }
01314 }
01315 }
01316
01317 void ImageView2::publishMonoImage(ros::Publisher& pub,
01318 cv::Mat& image,
01319 const std_msgs::Header& header)
01320 {
01321 cv_bridge::CvImage image_bridge(
01322 header, sensor_msgs::image_encodings::MONO8, image);
01323 pub.publish(image_bridge.toImageMsg());
01324 }
01325
01326 void ImageView2::publishForegroundBackgroundMask()
01327 {
01328 boost::mutex::scoped_lock lock(image_mutex_);
01329 boost::mutex::scoped_lock lock2(point_array_mutex_);
01330 cv::Mat foreground_mask
01331 = cv::Mat::zeros(last_msg_->height, last_msg_->width, CV_8UC1);
01332 cv::Mat background_mask
01333 = cv::Mat::zeros(last_msg_->height, last_msg_->width, CV_8UC1);
01334 if (getMode() == MODE_SELECT_FORE_AND_BACK) {
01335 pointArrayToMask(point_fg_array_, foreground_mask);
01336 pointArrayToMask(point_bg_array_, background_mask);
01337 }
01338 else if (getMode() == MODE_SELECT_FORE_AND_BACK_RECT) {
01339 cv::rectangle(foreground_mask, rect_fg_, cv::Scalar(255), CV_FILLED);
01340 cv::rectangle(background_mask, rect_bg_, cv::Scalar(255), CV_FILLED);
01341 }
01342 publishMonoImage(foreground_mask_pub_, foreground_mask, last_msg_->header);
01343 publishMonoImage(background_mask_pub_, background_mask, last_msg_->header);
01344 publishRectFromMaskImage(foreground_rect_pub_, foreground_mask, last_msg_->header);
01345 publishRectFromMaskImage(background_rect_pub_, background_mask, last_msg_->header);
01346 }
01347
01348 void ImageView2::publishRectFromMaskImage(
01349 ros::Publisher& pub,
01350 cv::Mat& image,
01351 const std_msgs::Header& header)
01352 {
01353 int min_x = image.cols;
01354 int min_y = image.rows;
01355 int max_x = 0;
01356 int max_y = 0;
01357 for (int j = 0; j < image.rows; j++) {
01358 for (int i = 0; i < image.cols; i++) {
01359 if (image.at<uchar>(j, i) != 0) {
01360 min_x = std::min(min_x, i);
01361 min_y = std::min(min_y, j);
01362 max_x = std::max(max_x, i);
01363 max_y = std::max(max_y, j);
01364 }
01365 }
01366 }
01367 geometry_msgs::PolygonStamped poly;
01368 poly.header = header;
01369 geometry_msgs::Point32 min_pt, max_pt;
01370 min_pt.x = min_x;
01371 min_pt.y = min_y;
01372 max_pt.x = max_x;
01373 max_pt.y = max_y;
01374 poly.polygon.points.push_back(min_pt);
01375 poly.polygon.points.push_back(max_pt);
01376 pub.publish(poly);
01377 }
01378
01379 void ImageView2::publishLinePoints()
01380 {
01381 boost::mutex::scoped_lock lock(line_point_mutex_);
01382 geometry_msgs::PolygonStamped ros_line;
01383 ros_line.header = last_msg_->header;
01384 geometry_msgs::Point32 ros_start_point, ros_end_point;
01385 ros_start_point.x = line_start_point_.x;
01386 ros_start_point.y = line_start_point_.y;
01387 ros_end_point.x = line_end_point_.x;
01388 ros_end_point.y = line_end_point_.y;
01389 ros_line.polygon.points.push_back(ros_start_point);
01390 ros_line.polygon.points.push_back(ros_end_point);
01391 line_pub_.publish(ros_line);
01392 }
01393
01394 void ImageView2::publishMouseInteractionResult()
01395 {
01396 if (getMode() == MODE_SERIES) {
01397 publishPointArray();
01398 }
01399 else if (getMode() == MODE_SELECT_FORE_AND_BACK ||
01400 getMode() == MODE_SELECT_FORE_AND_BACK_RECT) {
01401 publishForegroundBackgroundMask();
01402 }
01403 else if (getMode() == MODE_LINE) {
01404 publishLinePoints();
01405 }
01406 else {
01407 cv::Point2f Pt_1(window_selection_.x, window_selection_.y);
01408 cv::Point2f Pt(button_up_pos_);
01409 std::cout << "PT_1" << Pt_1 << std::endl;
01410 std::cout << "Pt" << Pt << std::endl;
01411 if (!isValidMovement(Pt_1, Pt)) {
01412 geometry_msgs::PointStamped screen_msg;
01413 screen_msg.point.x = window_selection_.x * resize_x_;
01414 screen_msg.point.y = window_selection_.y * resize_y_;
01415 screen_msg.point.z = 0;
01416 screen_msg.header.stamp = last_msg_->header.stamp;
01417 ROS_INFO("Publish screen point %s (%f %f)", point_pub_.getTopic().c_str(), screen_msg.point.x, screen_msg.point.y);
01418 point_pub_.publish(screen_msg);
01419 } else {
01420 geometry_msgs::PolygonStamped screen_msg;
01421 screen_msg.polygon.points.resize(2);
01422 screen_msg.polygon.points[0].x = window_selection_.x * resize_x_;
01423 screen_msg.polygon.points[0].y = window_selection_.y * resize_y_;
01424 screen_msg.polygon.points[1].x = (window_selection_.x + window_selection_.width) * resize_x_;
01425 screen_msg.polygon.points[1].y = (window_selection_.y + window_selection_.height) * resize_y_;
01426 screen_msg.header = last_msg_->header;
01427 ROS_INFO("Publish rectangle point %s (%f %f %f %f)", rectangle_pub_.getTopic().c_str(),
01428 screen_msg.polygon.points[0].x, screen_msg.polygon.points[0].y,
01429 screen_msg.polygon.points[1].x, screen_msg.polygon.points[1].y);
01430 rectangle_pub_.publish(screen_msg);
01431 continuous_ready_ = true;
01432 }
01433 }
01434 }
01435
01436
01437 bool ImageView2::isValidMovement(const cv::Point2f& start_point,
01438 const cv::Point2f& end_point)
01439 {
01440 double dist_px = cv::norm(cv::Mat(start_point), cv::Mat(end_point));
01441 return dist_px > 3.0;
01442 }
01443
01444 void ImageView2::updateLineStartPoint(cv::Point p)
01445 {
01446 boost::mutex::scoped_lock lock(line_point_mutex_);
01447 line_start_point_ = p;
01448 }
01449
01450 void ImageView2::updateLineEndPoint(cv::Point p)
01451 {
01452 boost::mutex::scoped_lock lock(line_point_mutex_);
01453 line_end_point_ = p;
01454 }
01455
01456 cv::Point ImageView2::getLineStartPoint()
01457 {
01458 boost::mutex::scoped_lock lock(line_point_mutex_);
01459 return cv::Point(line_start_point_);
01460 }
01461
01462 cv::Point ImageView2::getLineEndPoint()
01463 {
01464 boost::mutex::scoped_lock lock(line_point_mutex_);
01465 return cv::Point(line_end_point_);
01466 }
01467
01468 void ImageView2::updateLinePoint(cv::Point p)
01469 {
01470
01471 if (isSelectingLineStartPoint()) {
01472 updateLineStartPoint(p);
01473 updateLineEndPoint(p);
01474 }
01475 else {
01476 updateLineEndPoint(p);
01477 }
01478 {
01479 boost::mutex::scoped_lock lock(line_point_mutex_);
01480 line_select_start_point_ = !line_select_start_point_;
01481 line_selected_ = true;
01482 }
01483 }
01484
01485 bool ImageView2::isSelectingLineStartPoint()
01486 {
01487 boost::mutex::scoped_lock lock(line_point_mutex_);
01488 return line_select_start_point_;
01489 }
01490
01491 void ImageView2::processLeftButtonDown(int x, int y)
01492 {
01493 ROS_DEBUG("processLeftButtonDown");
01494 left_button_clicked_ = true;
01495 continuous_ready_ = false;
01496 window_selection_.x = x;
01497 window_selection_.y = y;
01498 window_selection_.width = window_selection_.height = 0;
01499 if (getMode() == MODE_SELECT_FORE_AND_BACK_RECT) {
01500 setRegionWindowPoint(x, y);
01501 }
01502 if (getMode() == MODE_LINE) {
01503 continuous_ready_ = false;
01504 }
01505 }
01506
01507 void ImageView2::processMove(int x, int y)
01508 {
01509 if (left_button_clicked_) {
01510 cv::Point2f Pt_1(window_selection_.x, window_selection_.y);
01511 cv::Point2f Pt(x, y);
01512 if (isValidMovement(Pt_1, Pt)) {
01513 if (getMode() == MODE_RECTANGLE) {
01514 window_selection_.width = x - window_selection_.x;
01515 window_selection_.height = y - window_selection_.y;
01516 }
01517 else if (getMode() == MODE_SERIES) {
01518 addPoint(x, y);
01519 }
01520 else if (getMode() == MODE_SELECT_FORE_AND_BACK) {
01521 addRegionPoint(x, y);
01522 }
01523 else if (getMode() == MODE_SELECT_FORE_AND_BACK_RECT) {
01524 updateRegionWindowSize(x, y);
01525 }
01526 }
01527
01528 geometry_msgs::PointStamped move_point;
01529 move_point.header.stamp = ros::Time::now();
01530 move_point.point.x = x;
01531 move_point.point.y = y;
01532 move_point.point.z = 0;
01533 move_point_pub_.publish(move_point);
01534 }
01535 else {
01536 if (getMode() == MODE_LINE) {
01537 if (!isSelectingLineStartPoint()) {
01538 updateLineEndPoint(cv::Point(x, y));
01539 }
01540 }
01541 else if (getMode() == MODE_POLY) {
01542 updatePolySelectingPoint(cv::Point(x, y));
01543 }
01544 }
01545 }
01546
01547 void ImageView2::processLeftButtonUp(int x, int y)
01548 {
01549 if (!left_button_clicked_) {
01550 return;
01551 }
01552 if (getMode() == MODE_SERIES) {
01553 publishMouseInteractionResult();
01554 clearPointArray();
01555 }
01556 else if (getMode() == MODE_SELECT_FORE_AND_BACK ||
01557 getMode() == MODE_SELECT_FORE_AND_BACK_RECT) {
01558 bool fgp = toggleSelection();
01559 if (fgp) {
01560 publishMouseInteractionResult();
01561 continuous_ready_ = true;
01562
01563 }
01564 }
01565 else if (getMode() == MODE_RECTANGLE) {
01566
01567 button_up_pos_ = cv::Point2f(x, y);
01568 publishMouseInteractionResult();
01569 }
01570 else if (getMode() == MODE_LINE) {
01571 updateLinePoint(cv::Point(x, y));
01572 if (isSelectingLineStartPoint()) {
01573 publishMouseInteractionResult();
01574 continuous_ready_ = true;
01575 }
01576 }
01577 else if (getMode() == MODE_POLY) {
01578 if (isPolySelectingFirstTime()) {
01579 continuous_ready_ = false;
01580 clearPolyPoints();
01581 }
01582 updatePolyPoint(cv::Point(x, y));
01583 }
01584 left_button_clicked_ = false;
01585 }
01586
01587 void ImageView2::updatePolyPoint(cv::Point p)
01588 {
01589 boost::mutex::scoped_lock lock(poly_point_mutex_);
01590 poly_points_.push_back(p);
01591 }
01592
01593 void ImageView2::publishPolyPoints()
01594 {
01595 boost::mutex::scoped_lock lock(poly_point_mutex_);
01596 geometry_msgs::PolygonStamped poly;
01597 poly.header = last_msg_->header;
01598 for (size_t i = 0; i < poly_points_.size(); i++) {
01599 geometry_msgs::Point32 p;
01600 p.x = poly_points_[i].x;
01601 p.y = poly_points_[i].y;
01602 p.z = 0;
01603 poly.polygon.points.push_back(p);
01604 }
01605 poly_pub_.publish(poly);
01606 }
01607
01608 void ImageView2::updatePolySelectingPoint(cv::Point p)
01609 {
01610 boost::mutex::scoped_lock lock(poly_point_mutex_);
01611 poly_selecting_point_ = p;
01612 }
01613
01614 void ImageView2::finishSelectingPoly()
01615 {
01616 boost::mutex::scoped_lock lock(poly_point_mutex_);
01617 poly_selecting_done_ = true;
01618 }
01619
01620 bool ImageView2::isPolySelectingFirstTime()
01621 {
01622 boost::mutex::scoped_lock lock(poly_point_mutex_);
01623 return poly_selecting_done_;
01624 }
01625
01626 void ImageView2::clearPolyPoints()
01627 {
01628 boost::mutex::scoped_lock lock(poly_point_mutex_);
01629 poly_selecting_done_ = false;
01630 poly_points_.clear();
01631 }
01632
01633 void ImageView2::processMouseEvent(int event, int x, int y, int flags, void* param)
01634 {
01635 checkMousePos(x, y);
01636 switch (event){
01637 case CV_EVENT_MOUSEMOVE: {
01638 processMove(x, y);
01639 break;
01640 }
01641 case CV_EVENT_LBUTTONDOWN:
01642 processLeftButtonDown(x, y);
01643 break;
01644 case CV_EVENT_LBUTTONUP:
01645 processLeftButtonUp(x, y);
01646 break;
01647 case CV_EVENT_RBUTTONDOWN:
01648 {
01649 if (getMode() == MODE_POLY) {
01650
01651 finishSelectingPoly();
01652 publishPolyPoints();
01653 continuous_ready_ = true;
01654 }
01655 else {
01656 boost::mutex::scoped_lock lock(image_mutex_);
01657 if (!image_.empty()) {
01658 std::string filename = (filename_format_ % count_).str();
01659 cv::imwrite(filename.c_str(), image_);
01660 ROS_INFO("Saved image %s", filename.c_str());
01661 count_++;
01662 } else {
01663 ROS_WARN("Couldn't save image, no data!");
01664 }
01665 }
01666 break;
01667 }
01668 }
01669 {
01670 boost::mutex::scoped_lock lock2(image_mutex_);
01671 drawImage();
01672 }
01673 return;
01674 }
01675
01676 void ImageView2::mouseCb(int event, int x, int y, int flags, void* param)
01677 {
01678 ROS_DEBUG("mouseCB");
01679 ImageView2 *iv = (ImageView2*)param;
01680 iv->processMouseEvent(event, x, y, flags, param);
01681 return;
01682 }
01683
01684 void ImageView2::pressKey(int key)
01685 {
01686 if (key != -1) {
01687 switch (key) {
01688 case 27: {
01689 resetInteraction();
01690 break;
01691 }
01692 }
01693 }
01694 }
01695
01696 void ImageView2::showImage()
01697 {
01698 if (use_window) {
01699 if (!window_initialized_) {
01700 cv::namedWindow(window_name_.c_str(), autosize_ ? CV_WINDOW_AUTOSIZE : 0);
01701 cv::setMouseCallback(window_name_.c_str(), &ImageView2::mouseCb, this);
01702 window_initialized_ = false;
01703 }
01704 if(!image_.empty()) {
01705 cv::imshow(window_name_.c_str(), image_);
01706 cv::waitKey(3);
01707 }
01708 }
01709 }
01710
01711 void ImageView2::checkMousePos(int& x, int& y)
01712 {
01713 if (last_msg_) {
01714 x = std::max(std::min(x, (int)last_msg_->width), 0);
01715 y = std::max(std::min(y, (int)last_msg_->height), 0);
01716 }
01717 }
01718 void ImageView2::resetInteraction()
01719 {
01720 if (getMode() == MODE_SELECT_FORE_AND_BACK) {
01721 boost::mutex::scoped_lock lock(point_array_mutex_);
01722 point_fg_array_.clear();
01723 point_bg_array_.clear();
01724 selecting_fg_ = true;
01725 }
01726 else if (getMode() == MODE_SELECT_FORE_AND_BACK_RECT) {
01727 boost::mutex::scoped_lock lock(point_array_mutex_);
01728 rect_fg_.width = rect_fg_.height = 0;
01729 rect_bg_.width = rect_bg_.height = 0;
01730 selecting_fg_ = true;
01731 }
01732 else if (getMode() == MODE_LINE) {
01733 boost::mutex::scoped_lock lock(line_point_mutex_);
01734 line_select_start_point_ = true;
01735 line_selected_ = false;
01736 continuous_ready_ = false;
01737 }
01738 else if (getMode() == MODE_RECTANGLE) {
01739 button_up_pos_ = cv::Point2f(0, 0);
01740 window_selection_.width = 0;
01741 window_selection_.height = 0;
01742 }
01743 else if (getMode() == MODE_POLY) {
01744 clearPolyPoints();
01745 }
01746 }
01747
01748 bool ImageView2::rectangleModeServiceCallback(
01749 std_srvs::EmptyRequest& req,
01750 std_srvs::EmptyResponse& res)
01751 {
01752 resetInteraction();
01753 setMode(MODE_RECTANGLE);
01754 resetInteraction();
01755 return true;
01756 }
01757
01758 bool ImageView2::seriesModeServiceCallback(
01759 std_srvs::EmptyRequest& req,
01760 std_srvs::EmptyResponse& res)
01761 {
01762 resetInteraction();
01763 setMode(MODE_SERIES);
01764 resetInteraction();
01765 return true;
01766 }
01767
01768 bool ImageView2::grabcutModeServiceCallback(
01769 std_srvs::EmptyRequest& req,
01770 std_srvs::EmptyResponse& res)
01771 {
01772 resetInteraction();
01773 setMode(MODE_SELECT_FORE_AND_BACK);
01774 resetInteraction();
01775 return true;
01776 }
01777
01778 bool ImageView2::grabcutRectModeServiceCallback(
01779 std_srvs::EmptyRequest& req,
01780 std_srvs::EmptyResponse& res)
01781 {
01782 resetInteraction();
01783 setMode(MODE_SELECT_FORE_AND_BACK_RECT);
01784 resetInteraction();
01785 return true;
01786 }
01787
01788 bool ImageView2::lineModeServiceCallback(
01789 std_srvs::EmptyRequest& req,
01790 std_srvs::EmptyResponse& res)
01791 {
01792 resetInteraction();
01793 setMode(MODE_LINE);
01794 resetInteraction();
01795 return true;
01796 }
01797
01798 bool ImageView2::polyModeServiceCallback(
01799 std_srvs::EmptyRequest& req,
01800 std_srvs::EmptyResponse& res)
01801 {
01802 resetInteraction();
01803 setMode(MODE_POLY);
01804 resetInteraction();
01805 return true;
01806 }
01807
01808 bool ImageView2::noneModeServiceCallback(
01809 std_srvs::EmptyRequest& req,
01810 std_srvs::EmptyResponse& res)
01811 {
01812 resetInteraction();
01813 setMode(MODE_NONE);
01814 resetInteraction();
01815 return true;
01816 }
01817
01818 bool ImageView2::changeModeServiceCallback(
01819 image_view2::ChangeModeRequest& req,
01820 image_view2::ChangeModeResponse& res)
01821 {
01822 resetInteraction();
01823 KEY_MODE next_mode = stringToMode(req.mode);
01824 setMode(next_mode);
01825 resetInteraction();
01826 return true;
01827 }
01828
01829 ImageView2::KEY_MODE ImageView2::stringToMode(const std::string& interaction_mode)
01830 {
01831 if (interaction_mode == "rectangle") {
01832 return MODE_RECTANGLE;
01833 }
01834 else if (interaction_mode == "freeform" ||
01835 interaction_mode == "series") {
01836 return MODE_SERIES;
01837 }
01838 else if (interaction_mode == "grabcut") {
01839 return MODE_SELECT_FORE_AND_BACK;
01840 }
01841 else if (interaction_mode == "grabcut_rect") {
01842 return MODE_SELECT_FORE_AND_BACK_RECT;
01843 }
01844 else if (interaction_mode == "line") {
01845 return MODE_LINE;
01846 }
01847 else if (interaction_mode == "poly") {
01848 return MODE_POLY;
01849 }
01850 else if (interaction_mode == "none") {
01851 return MODE_NONE;
01852 }
01853 else {
01854 throw std::string("Unknown mode");
01855 }
01856 }
01857
01858 void ImageView2::eventCb(
01859 const image_view2::MouseEvent::ConstPtr& event_msg)
01860 {
01861
01862 if (event_msg->type == image_view2::MouseEvent::KEY_PRESSED) {
01863 pressKey(event_msg->key);
01864 }
01865 else {
01866
01867 int x, y;
01868 {
01869 boost::mutex::scoped_lock lock(image_mutex_);
01870 if (!last_msg_) {
01871 ROS_WARN("Image is not yet available");
01872 return;
01873 }
01874 x = ((float)last_msg_->width / event_msg->width) * event_msg->x;
01875 y = ((float)last_msg_->height / event_msg->height) * event_msg->y;
01876 }
01877
01878 if (event_msg->type == image_view2::MouseEvent::MOUSE_LEFT_UP) {
01879
01880 processMouseEvent(CV_EVENT_LBUTTONUP, x, y, 0, NULL);
01881 }
01882 else if (event_msg->type == image_view2::MouseEvent::MOUSE_LEFT_DOWN) {
01883
01884 processMouseEvent(CV_EVENT_LBUTTONDOWN, x, y, 0, NULL);
01885 }
01886 else if (event_msg->type == image_view2::MouseEvent::MOUSE_MOVE) {
01887
01888 processMouseEvent(CV_EVENT_MOUSEMOVE, x, y, 0, NULL);
01889 }
01890 else if (event_msg->type == image_view2::MouseEvent::MOUSE_RIGHT_DOWN) {
01891
01892 processMouseEvent(CV_EVENT_RBUTTONDOWN, x, y, 0, NULL);
01893 }
01894 }
01895 }
01896 }
01897
01898