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 #include <opencv/cv.h>
00036 #include <opencv/highgui.h>
00037
00038 #include <ros/ros.h>
00039 #include <sensor_msgs/Image.h>
00040 #include <cv_bridge/cv_bridge.h>
00041 #include <sensor_msgs/image_encodings.h>
00042 #include <image_transport/image_transport.h>
00043 #include <image_geometry/pinhole_camera_model.h>
00044 #include <tf/transform_listener.h>
00045
00046 #include <image_view2/ImageMarker2.h>
00047 #include <geometry_msgs/PointStamped.h>
00048 #include <geometry_msgs/PolygonStamped.h>
00049 #include <std_msgs/Empty.h>
00050
00051 #include <boost/thread.hpp>
00052 #include <boost/format.hpp>
00053 #include <boost/foreach.hpp>
00054 #include <boost/circular_buffer.hpp>
00055 #include <boost/lambda/lambda.hpp>
00056 #include <pcl/point_types.h>
00057 #include <pcl_ros/publisher.h>
00058
00059 typedef std::vector<image_view2::ImageMarker2::ConstPtr> V_ImageMarkerMessage;
00060
00061 #define DEFAULT_COLOR CV_RGB(255,0,0)
00062 #define USER_ROI_COLOR CV_RGB(255,0,0)
00063 #define DEFAULT_CIRCLE_SCALE 20
00064 #define DEFAULT_LINE_WIDTH 3
00065
00066 inline CvScalar MsgToRGB(const std_msgs::ColorRGBA &color){
00067 if(color.a == 0.0 && color.r == 0.0 && color.g == 0.0 && color.b == 0.0)
00068 return DEFAULT_COLOR;
00069 else
00070 return CV_RGB(color.r*255, color.g*255, color.b*255);
00071 }
00072
00073
00074 class ImageView2
00075 {
00076 private:
00077 image_transport::Subscriber image_sub_;
00078 ros::Subscriber info_sub_;
00079 ros::Subscriber marker_sub_;
00080 std::string marker_topic_;
00081
00082 image_transport::Publisher image_pub_;
00083
00084 V_ImageMarkerMessage marker_queue_;
00085 boost::mutex queue_mutex_;
00086
00087 sensor_msgs::ImageConstPtr last_msg_;
00088 sensor_msgs::CameraInfoConstPtr info_msg_;
00089 cv_bridge::CvImage img_bridge_;
00090 boost::mutex image_mutex_;
00091 cv::Mat image_, draw_;
00092
00093 tf::TransformListener tf_listener_;
00094 image_geometry::PinholeCameraModel cam_model_;
00095 std::vector<std::string> frame_ids_;
00096 std::vector<cv::Point2d> point_array_;
00097 boost::mutex info_mutex_;
00098
00099 std::string window_name_;
00100 boost::format filename_format_;
00101 int font_;
00102
00103 static double resize_x_, resize_y_;
00104 static CvRect window_selection_;
00105 int count_;
00106 bool blurry_mode;
00107 bool use_window;
00108 bool show_info;
00109 double tf_timeout;
00110 ros::Publisher point_pub_;
00111 ros::Publisher point_array_pub_;
00112 ros::Publisher rectangle_pub_;
00113 ros::Publisher move_point_pub_;
00114
00115 public:
00116 enum KEY_MODE {
00117 MODE_RECTANGLE = 0,
00118 MODE_SERIES = 1,
00119 };
00120
00121 private:
00122 KEY_MODE mode_;
00123
00124 public:
00125
00126 ImageView2() : marker_topic_("image_marker"), filename_format_(""), count_(0), mode_(MODE_RECTANGLE)
00127 {
00128 }
00129 ImageView2(ros::NodeHandle& nh)
00130 : marker_topic_("image_marker"), filename_format_(""), count_(0), mode_(MODE_RECTANGLE)
00131 {
00132 std::string camera = nh.resolveName("image");
00133 std::string camera_info = nh.resolveName("camera_info");
00134 ros::NodeHandle local_nh("~");
00135 bool autosize;
00136 std::string format_string;
00137 std::string transport;
00138 image_transport::ImageTransport it(nh);
00139
00140 point_pub_ = nh.advertise<geometry_msgs::PointStamped>(camera + "/screenpoint",100);
00141 point_array_pub_ = nh.advertise<sensor_msgs::PointCloud2>(camera + "/screenpoint_array",100);
00142 rectangle_pub_ = nh.advertise<geometry_msgs::PolygonStamped>(camera + "/screenrectangle",100);
00143 move_point_pub_ = nh.advertise<geometry_msgs::PointStamped>(camera + "/movepoint", 100);
00144 local_nh.param("window_name", window_name_, std::string("image_view2 [")+camera+std::string("]"));
00145
00146 local_nh.param("autosize", autosize, false);
00147 local_nh.param("image_transport", transport, std::string("raw"));
00148 local_nh.param("blurry", blurry_mode, false);
00149
00150 local_nh.param("filename_format", format_string, std::string("frame%04i.jpg"));
00151 local_nh.param("use_window", use_window, true);
00152 local_nh.param("show_info", show_info, false);
00153
00154 double xx,yy;
00155 local_nh.param("resize_scale_x", xx, 1.0);
00156 local_nh.param("resize_scale_y", yy, 1.0);
00157 local_nh.param("tf_timeout", tf_timeout, 1.0);
00158
00159 resize_x_ = 1.0/xx;
00160 resize_y_ = 1.0/yy;
00161 filename_format_.parse(format_string);
00162
00163 if ( use_window ) {
00164 cvNamedWindow(window_name_.c_str(), autosize ? CV_WINDOW_AUTOSIZE : 0);
00165 cvSetMouseCallback(window_name_.c_str(), &ImageView2::mouse_cb, this);
00166 font_ = cv::FONT_HERSHEY_DUPLEX;
00167 window_selection_.x = window_selection_.y =
00168 window_selection_.height = window_selection_.width = 0;
00169 cvStartWindowThread();
00170 }
00171
00172 image_sub_ = it.subscribe(camera, 1, &ImageView2::image_cb, this, transport);
00173 info_sub_ = nh.subscribe(camera_info, 1, &ImageView2::info_cb, this);
00174 marker_sub_ = nh.subscribe(marker_topic_, 10, &ImageView2::marker_cb, this);
00175
00176 image_pub_ = it.advertise("image_marked", 1);
00177 }
00178
00179 ~ImageView2()
00180 {
00181 if ( use_window ) {
00182 cvDestroyWindow(window_name_.c_str());
00183 }
00184 }
00185
00186 void marker_cb(const image_view2::ImageMarker2ConstPtr& marker)
00187 {
00188 ROS_DEBUG("marker_cb");
00189
00190 if(marker->lifetime != ros::Duration(0))
00191 boost::const_pointer_cast<image_view2::ImageMarker2>(marker)->lifetime = (ros::Time::now() - ros::Time(0)) + marker->lifetime;
00192 boost::mutex::scoped_lock lock(queue_mutex_);
00193
00194 marker_queue_.push_back(marker);
00195
00196 }
00197
00198 void info_cb(const sensor_msgs::CameraInfoConstPtr& msg) {
00199 ROS_DEBUG("info_cb");
00200 boost::mutex::scoped_lock lock(info_mutex_);
00201 info_msg_ = msg;
00202 }
00203
00204 void image_cb(const sensor_msgs::ImageConstPtr& msg)
00205 {
00206 static ros::Time old_time, last_time;
00207 static boost::circular_buffer<double> times(100);
00208 static std::string info_str_1, info_str_2;
00209
00210 times.push_front(ros::Time::now().toSec() - old_time.toSec());
00211
00212 ROS_DEBUG("image_cb");
00213 if(old_time.toSec() - ros::Time::now().toSec() > 0) {
00214 ROS_WARN("TF Cleared for old time");
00215 }
00216 if ( show_info && ( ros::Time::now().toSec() - last_time.toSec() > 2 ) ) {
00217 int n = times.size();
00218 double mean = 0, rate = 1.0, std_dev = 0.0, max_delta, min_delta;
00219
00220 std::for_each( times.begin(), times.end(), (mean += boost::lambda::_1) );
00221 mean /= n;
00222 rate /= mean;
00223
00224 std::for_each( times.begin(), times.end(), (std_dev += (boost::lambda::_1 - mean)*(boost::lambda::_1 - mean) ) );
00225 std_dev = sqrt(std_dev/n);
00226 min_delta = *std::min_element(times.begin(), times.end());
00227 max_delta = *std::max_element(times.begin(), times.end());
00228
00229 std::stringstream f1, f2;
00230 f1.precision(3); f1 << std::fixed;
00231 f2.precision(3); f2 << std::fixed;
00232 f1 << "" << image_sub_.getTopic() << " : rate:" << rate;
00233 f2 << "min:" << min_delta << "s max: " << max_delta << "s std_dev: " << std_dev << "s n: " << n;
00234 info_str_1 = f1.str();
00235 info_str_2 = f2.str();
00236 ROS_INFO_STREAM(info_str_1 + " " + info_str_2);
00237 times.clear();
00238 last_time = ros::Time::now();
00239 }
00240
00241 if (msg->encoding.find("bayer") != std::string::npos) {
00242 image_ = cv::Mat(msg->height, msg->width, CV_8UC1,
00243 const_cast<uint8_t*>(&msg->data[0]), msg->step);
00244 } else {
00245 try {
00246 image_ = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8)->image;
00247 } catch (cv_bridge::Exception& e) {
00248 ROS_ERROR("Unable to convert %s image to bgr8", msg->encoding.c_str());
00249 return;
00250 }
00251 }
00252 boost::lock_guard<boost::mutex> guard(image_mutex_);
00253
00254 last_msg_ = msg;
00255
00256 static V_ImageMarkerMessage local_queue;
00257 {
00258 boost::mutex::scoped_lock lock(queue_mutex_);
00259
00260 while ( ! marker_queue_.empty() ) {
00261
00262 V_ImageMarkerMessage::iterator new_msg = marker_queue_.begin();
00263 V_ImageMarkerMessage::iterator message_it = local_queue.begin();
00264 for ( ; message_it < local_queue.end(); ++message_it ) {
00265 if((*new_msg)->ns == (*message_it)->ns && (*new_msg)->id == (*message_it)->id)
00266 message_it = local_queue.erase(message_it);
00267 }
00268 local_queue.push_back(*new_msg);
00269 marker_queue_.erase(new_msg);
00270
00271 if ( (*new_msg)->action == image_view2::ImageMarker2::REMOVE &&
00272 (*new_msg)->id == -1 ) {
00273 local_queue.clear();
00274 }
00275 }
00276 }
00277
00278
00279 for(V_ImageMarkerMessage::iterator it = local_queue.begin(); it < local_queue.end(); it++) {
00280 if((*it)->action == image_view2::ImageMarker2::REMOVE ||
00281 ((*it)->lifetime.toSec() != 0.0 && (*it)->lifetime.toSec() < ros::Time::now().toSec())) {
00282 it = local_queue.erase(it);
00283 }
00284 }
00285
00286
00287 if ( blurry_mode ) {
00288 draw_ = cv::Mat(image_.size(), image_.type(), CV_RGB(0,0,0));
00289 } else {
00290 draw_ = image_;
00291 }
00292 if ( !local_queue.empty() )
00293 {
00294 V_ImageMarkerMessage::iterator message_it = local_queue.begin();
00295 V_ImageMarkerMessage::iterator message_end = local_queue.end();
00296 ROS_DEBUG("markers = %ld", local_queue.size());
00297
00298 for ( ; message_it != message_end; ++message_it )
00299 {
00300 image_view2::ImageMarker2::ConstPtr& marker = *message_it;
00301
00302 ROS_DEBUG_STREAM("message type = " << marker->type << ", id " << marker->id);
00303
00304
00305 std::vector<CvScalar> colors;
00306 BOOST_FOREACH(std_msgs::ColorRGBA color, marker->outline_colors) {
00307 colors.push_back(MsgToRGB(color));
00308 }
00309 if(colors.size() == 0) colors.push_back(DEFAULT_COLOR);
00310 std::vector<CvScalar>::iterator col_it = colors.begin();
00311
00312
00313 if( marker->type == image_view2::ImageMarker2::FRAMES ||
00314 marker->type == image_view2::ImageMarker2::LINE_STRIP3D ||
00315 marker->type == image_view2::ImageMarker2::LINE_LIST3D ||
00316 marker->type == image_view2::ImageMarker2::POLYGON3D ||
00317 marker->type == image_view2::ImageMarker2::POINTS3D ||
00318 marker->type == image_view2::ImageMarker2::TEXT3D ||
00319 marker->type == image_view2::ImageMarker2::CIRCLE3D) {
00320 {
00321 boost::mutex::scoped_lock lock(info_mutex_);
00322 if (!info_msg_) {
00323 ROS_WARN("[image_view2] camera_info could not found");
00324 continue;
00325 }
00326 cam_model_.fromCameraInfo(info_msg_);
00327 }
00328 }
00329
00330 switch ( marker->type ) {
00331 case image_view2::ImageMarker2::CIRCLE: {
00332 cv::Point2d uv = cv::Point2d(marker->position.x, marker->position.y);
00333 if ( blurry_mode ) {
00334 int s0 = (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width);
00335 CvScalar co = MsgToRGB(marker->outline_color);
00336 for (int s1 = s0*10; s1 >= s0; s1--) {
00337 double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
00338 cv::circle(draw_, uv,
00339 (marker->scale == 0 ? DEFAULT_CIRCLE_SCALE : marker->scale),
00340 CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m),
00341 s1);
00342 }
00343 } else {
00344 cv::circle(draw_, uv,
00345 (marker->scale == 0 ? DEFAULT_CIRCLE_SCALE : marker->scale),
00346 MsgToRGB(marker->outline_color),
00347 (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00348 if (marker->filled) {
00349 cv::circle(draw_, uv,
00350 (marker->scale == 0 ? DEFAULT_CIRCLE_SCALE : marker->scale) - (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width) / 2.0,
00351 MsgToRGB(marker->fill_color),
00352 -1);
00353 }
00354 }
00355 break;
00356 }
00357 case image_view2::ImageMarker2::LINE_STRIP: {
00358 cv::Point2d p0, p1;
00359 if ( blurry_mode ) {
00360 int s0 = (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width);
00361 std::vector<CvScalar>::iterator col_it = colors.begin();
00362 CvScalar co = (*col_it);
00363 for (int s1 = s0*10; s1 >= s0; s1--) {
00364 double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
00365 std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00366 std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00367 p0 = cv::Point2d(it->x, it->y); it++;
00368 for ( ; it!= end; it++ ) {
00369 p1 = cv::Point2d(it->x, it->y);
00370 cv::line(draw_, p0, p1,
00371 CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m),
00372 s1);
00373 p0 = p1;
00374 if(++col_it == colors.end()) col_it = colors.begin();
00375 }
00376 }
00377 } else {
00378 std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00379 std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00380 p0 = cv::Point2d(it->x, it->y); it++;
00381 for ( ; it!= end; it++ ) {
00382 p1 = cv::Point2d(it->x, it->y);
00383 cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00384 p0 = p1;
00385 if(++col_it == colors.end()) col_it = colors.begin();
00386 }
00387 }
00388 break;
00389 }
00390 case image_view2::ImageMarker2::LINE_LIST: {
00391 cv::Point2d p0, p1;
00392 if ( blurry_mode ) {
00393 int s0 = (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width);
00394 std::vector<CvScalar>::iterator col_it = colors.begin();
00395 CvScalar co = (*col_it);
00396 for (int s1 = s0*10; s1 >= s0; s1--) {
00397 double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
00398 std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00399 std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00400 for ( ; it!= end; ) {
00401 p0 = cv::Point2d(it->x, it->y); it++;
00402 if ( it != end ) p1 = cv::Point2d(it->x, it->y);
00403 cv::line(draw_, p0, p1, CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m), s1);
00404 it++;
00405 if(++col_it == colors.end()) col_it = colors.begin();
00406 }
00407 }
00408 } else {
00409 std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00410 std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00411 for ( ; it!= end; ) {
00412 p0 = cv::Point2d(it->x, it->y); it++;
00413 if ( it != end ) p1 = cv::Point2d(it->x, it->y);
00414 cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00415 it++;
00416 if(++col_it == colors.end()) col_it = colors.begin();
00417 }
00418 }
00419 break;
00420 }
00421 case image_view2::ImageMarker2::POLYGON: {
00422 cv::Point2d p0, p1;
00423 if ( blurry_mode ) {
00424 int s0 = (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width);
00425 std::vector<CvScalar>::iterator col_it = colors.begin();
00426 CvScalar co = (*col_it);
00427 for (int s1 = s0*10; s1 >= s0; s1--) {
00428 double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
00429 std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00430 std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00431 p0 = cv::Point2d(it->x, it->y); it++;
00432 for ( ; it!= end; it++ ) {
00433 p1 = cv::Point2d(it->x, it->y);
00434 cv::line(draw_, p0, p1, CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m), s1);
00435 p0 = p1;
00436 if(++col_it == colors.end()) col_it = colors.begin();
00437 }
00438 it = marker->points.begin();
00439 p1 = cv::Point2d(it->x, it->y);
00440 cv::line(draw_, p0, p1, CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m), s1);
00441 }
00442 } else {
00443 std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00444 std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00445 std::vector<cv::Point> points;
00446
00447 if (marker->filled) {
00448 points.push_back(cv::Point(it->x, it->y));
00449 }
00450 p0 = cv::Point2d(it->x, it->y); it++;
00451 for ( ; it!= end; it++ ) {
00452 p1 = cv::Point2d(it->x, it->y);
00453 if (marker->filled) {
00454 points.push_back(cv::Point(it->x, it->y));
00455 }
00456 cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00457 p0 = p1;
00458 if(++col_it == colors.end()) col_it = colors.begin();
00459 }
00460 it = marker->points.begin();
00461 p1 = cv::Point2d(it->x, it->y);
00462 cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00463 if (marker->filled) {
00464 cv::fillConvexPoly(draw_, points.data(), points.size(), MsgToRGB(marker->fill_color));
00465 }
00466 }
00467 break;
00468 }
00469 case image_view2::ImageMarker2::POINTS: {
00470 BOOST_FOREACH(geometry_msgs::Point p, marker->points) {
00471 cv::Point2d uv = cv::Point2d(p.x, p.y);
00472 if ( blurry_mode ) {
00473 int s0 = (marker->scale == 0 ? 3 : marker->scale);
00474 CvScalar co = (*col_it);
00475 for (int s1 = s0*2; s1 >= s0; s1--) {
00476 double m = pow((1.0-((double)(s1 - s0))/s0),2);
00477 cv::circle(draw_, uv, s1,
00478 CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m),
00479 -1);
00480 }
00481 } else {
00482 cv::circle(draw_, uv, (marker->scale == 0 ? 3 : marker->scale) , *col_it, -1);
00483 }
00484 if(++col_it == colors.end()) col_it = colors.begin();
00485 }
00486 break;
00487 }
00488 case image_view2::ImageMarker2::FRAMES: {
00489 static std::map<std::string, int> tf_fail;
00490 BOOST_FOREACH(std::string frame_id, marker->frames) {
00491 tf::StampedTransform transform;
00492 ros::Time acquisition_time = msg->header.stamp;
00493 ros::Duration timeout(tf_timeout);
00494 try {
00495 ros::Time tm;
00496 tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
00497 ros::Duration diff = ros::Time::now() - tm;
00498 if ( diff > ros::Duration(1.0) ) { break; }
00499
00500 tf_listener_.waitForTransform(cam_model_.tfFrame(), frame_id,
00501 acquisition_time, timeout);
00502 tf_listener_.lookupTransform(cam_model_.tfFrame(), frame_id,
00503 acquisition_time, transform);
00504 tf_fail[frame_id]=0;
00505 }
00506 catch (tf::TransformException& ex) {
00507 tf_fail[frame_id]++;
00508 if ( tf_fail[frame_id] < 5 ) {
00509 ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
00510 } else {
00511 ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
00512 }
00513 break;
00514 }
00515
00516 tf::Point pt = transform.getOrigin();
00517 cv::Point3d pt_cv(pt.x(), pt.y(), pt.z());
00518 cv::Point2d uv;
00519 uv = cam_model_.project3dToPixel(pt_cv);
00520
00521 static const int RADIUS = 3;
00522 cv::circle(draw_, uv, RADIUS, DEFAULT_COLOR, -1);
00523
00524
00525 cv::Point2d uv0, uv1, uv2;
00526 tf::Stamped<tf::Point> pin, pout;
00527
00528
00529 pin = tf::Stamped<tf::Point>(tf::Point(0.05, 0, 0), acquisition_time, frame_id);
00530 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00531 uv0 = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00532
00533 pin = tf::Stamped<tf::Point>(tf::Point(0, 0.05, 0), acquisition_time, frame_id);
00534 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00535 uv1 = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00536
00537
00538 pin = tf::Stamped<tf::Point>(tf::Point(0, 0, 0.05), acquisition_time, frame_id);
00539 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00540 uv2 = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00541
00542
00543 if ( blurry_mode ) {
00544 int s0 = 2;
00545 CvScalar c0 = CV_RGB(255,0,0);
00546 CvScalar c1 = CV_RGB(0,255,0);
00547 CvScalar c2 = CV_RGB(0,0,255);
00548 for (int s1 = s0*10; s1 >= s0; s1--) {
00549 double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
00550 cv::line(draw_, uv, uv0,
00551 CV_RGB(c0.val[2] * m,c0.val[1] * m,c0.val[0] * m),
00552 s1);
00553 cv::line(draw_, uv, uv1,
00554 CV_RGB(c1.val[2] * m,c1.val[1] * m,c1.val[0] * m),
00555 s1);
00556 cv::line(draw_, uv, uv2,
00557 CV_RGB(c2.val[2] * m,c2.val[1] * m,c2.val[0] * m),
00558 s1);
00559 }
00560 } else {
00561 cv::line(draw_, uv, uv0, CV_RGB(255,0,0), 2);
00562 cv::line(draw_, uv, uv1, CV_RGB(0,255,0), 2);
00563 cv::line(draw_, uv, uv2, CV_RGB(0,0,255), 2);
00564 }
00565
00566
00567 cv::Size text_size;
00568 int baseline;
00569 text_size = cv::getTextSize(frame_id.c_str(), font_, 1.0, 1.0, &baseline);
00570 cv::Point origin = cv::Point(uv.x - text_size.width / 2,
00571 uv.y - RADIUS - baseline - 3);
00572 cv::putText(draw_, frame_id.c_str(), origin, font_, 1.0, DEFAULT_COLOR, 1.5);
00573 }
00574 break;
00575 }
00576 case image_view2::ImageMarker2::TEXT: {
00577
00578 cv::Size text_size;
00579 int baseline;
00580 float scale = marker->scale;
00581 if ( scale == 0 ) scale = 1.0;
00582 text_size = cv::getTextSize(marker->text.c_str(), font_,
00583 scale, scale, &baseline);
00584 cv::Point origin = cv::Point(marker->position.x - text_size.width/2,
00585 marker->position.y - baseline-3);
00586 cv::putText(draw_, marker->text.c_str(), origin, font_, scale, DEFAULT_COLOR);
00587 break;
00588 }
00589
00590 case image_view2::ImageMarker2::LINE_STRIP3D: {
00591 static std::map<std::string, int> tf_fail;
00592 std::string frame_id = marker->points3D.header.frame_id;
00593 tf::StampedTransform transform;
00594 ros::Time acquisition_time = msg->header.stamp;
00595
00596 ros::Duration timeout(tf_timeout);
00597 try {
00598 ros::Time tm;
00599 tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
00600 ros::Duration diff = ros::Time::now() - tm;
00601 if ( diff > ros::Duration(1.0) ) { break; }
00602 tf_listener_.waitForTransform(cam_model_.tfFrame(), frame_id,
00603 acquisition_time, timeout);
00604 tf_listener_.lookupTransform(cam_model_.tfFrame(), frame_id,
00605 acquisition_time, transform);
00606 tf_fail[frame_id]=0;
00607 }
00608 catch (tf::TransformException& ex) {
00609 tf_fail[frame_id]++;
00610 if ( tf_fail[frame_id] < 5 ) {
00611 ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
00612 } else {
00613 ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
00614 }
00615 break;
00616 }
00617 std::vector<geometry_msgs::Point> points2D;
00618 BOOST_FOREACH(geometry_msgs::Point p, marker->points3D.points) {
00619 tf::Point pt = transform.getOrigin();
00620 geometry_msgs::PointStamped pt_cam, pt_;
00621 pt_cam.header.frame_id = cam_model_.tfFrame();
00622 pt_cam.header.stamp = acquisition_time;
00623 pt_cam.point.x = pt.x();
00624 pt_cam.point.y = pt.y();
00625 pt_cam.point.z = pt.z();
00626 tf_listener_.transformPoint(frame_id, pt_cam, pt_);
00627
00628 cv::Point2d uv;
00629 tf::Stamped<tf::Point> pin, pout;
00630 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);
00631 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00632 uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00633 geometry_msgs::Point point2D;
00634 point2D.x = uv.x;
00635 point2D.y = uv.y;
00636 points2D.push_back(point2D);
00637 }
00638 cv::Point2d p0, p1;
00639 std::vector<geometry_msgs::Point>::const_iterator it = points2D.begin();
00640 std::vector<geometry_msgs::Point>::const_iterator end = points2D.end();
00641 p0 = cv::Point2d(it->x, it->y); it++;
00642 for ( ; it!= end; it++ ) {
00643 p1 = cv::Point2d(it->x, it->y);
00644 cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00645 p0 = p1;
00646 if(++col_it == colors.end()) col_it = colors.begin();
00647 }
00648 break;
00649 }
00650 case image_view2::ImageMarker2::LINE_LIST3D: {
00651 static std::map<std::string, int> tf_fail;
00652 std::string frame_id = marker->points3D.header.frame_id;
00653 tf::StampedTransform transform;
00654 ros::Time acquisition_time = msg->header.stamp;
00655
00656 ros::Duration timeout(tf_timeout);
00657 try {
00658 ros::Time tm;
00659 tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
00660 ros::Duration diff = ros::Time::now() - tm;
00661 if ( diff > ros::Duration(1.0) ) { break; }
00662 tf_listener_.waitForTransform(cam_model_.tfFrame(), frame_id,
00663 acquisition_time, timeout);
00664 tf_listener_.lookupTransform(cam_model_.tfFrame(), frame_id,
00665 acquisition_time, transform);
00666 tf_fail[frame_id]=0;
00667 }
00668 catch (tf::TransformException& ex) {
00669 tf_fail[frame_id]++;
00670 if ( tf_fail[frame_id] < 5 ) {
00671 ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
00672 } else {
00673 ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
00674 }
00675 break;
00676 }
00677 std::vector<geometry_msgs::Point> points2D;
00678 BOOST_FOREACH(geometry_msgs::Point p, marker->points3D.points) {
00679 tf::Point pt = transform.getOrigin();
00680 geometry_msgs::PointStamped pt_cam, pt_;
00681 pt_cam.header.frame_id = cam_model_.tfFrame();
00682 pt_cam.header.stamp = acquisition_time;
00683 pt_cam.point.x = pt.x();
00684 pt_cam.point.y = pt.y();
00685 pt_cam.point.z = pt.z();
00686 tf_listener_.transformPoint(frame_id, pt_cam, pt_);
00687
00688 cv::Point2d uv;
00689 tf::Stamped<tf::Point> pin, pout;
00690 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);
00691 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00692 uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00693 geometry_msgs::Point point2D;
00694 point2D.x = uv.x;
00695 point2D.y = uv.y;
00696 points2D.push_back(point2D);
00697 }
00698 cv::Point2d p0, p1;
00699 std::vector<geometry_msgs::Point>::const_iterator it = points2D.begin();
00700 std::vector<geometry_msgs::Point>::const_iterator end = points2D.end();
00701 for ( ; it!= end; ) {
00702 p0 = cv::Point2d(it->x, it->y); it++;
00703 if ( it != end ) p1 = cv::Point2d(it->x, it->y);
00704 cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00705 it++;
00706 if(++col_it == colors.end()) col_it = colors.begin();
00707 }
00708 break;
00709 }
00710 case image_view2::ImageMarker2::POLYGON3D: {
00711 static std::map<std::string, int> tf_fail;
00712 std::string frame_id = marker->points3D.header.frame_id;
00713 tf::StampedTransform transform;
00714 ros::Time acquisition_time = msg->header.stamp;
00715
00716 ros::Duration timeout(tf_timeout);
00717 try {
00718 ros::Time tm;
00719 tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
00720
00721
00722 tf_listener_.waitForTransform(cam_model_.tfFrame(), frame_id,
00723 acquisition_time, timeout);
00724 tf_listener_.lookupTransform(cam_model_.tfFrame(), frame_id,
00725 acquisition_time, transform);
00726 tf_fail[frame_id]=0;
00727 }
00728 catch (tf::TransformException& ex) {
00729 tf_fail[frame_id]++;
00730 if ( tf_fail[frame_id] < 5 ) {
00731 ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
00732 } else {
00733 ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
00734 }
00735 break;
00736 }
00737 std::vector<geometry_msgs::Point> points2D;
00738 BOOST_FOREACH(geometry_msgs::Point p, marker->points3D.points) {
00739 tf::Point pt = transform.getOrigin();
00740 geometry_msgs::PointStamped pt_cam, pt_;
00741 pt_cam.header.frame_id = cam_model_.tfFrame();
00742 pt_cam.header.stamp = acquisition_time;
00743 pt_cam.point.x = pt.x();
00744 pt_cam.point.y = pt.y();
00745 pt_cam.point.z = pt.z();
00746 tf_listener_.transformPoint(frame_id, pt_cam, pt_);
00747
00748 cv::Point2d uv;
00749 tf::Stamped<tf::Point> pin, pout;
00750 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);
00751 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00752 uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00753 geometry_msgs::Point point2D;
00754 point2D.x = uv.x;
00755 point2D.y = uv.y;
00756 points2D.push_back(point2D);
00757 }
00758 cv::Point2d p0, p1;
00759 std::vector<geometry_msgs::Point>::const_iterator it = points2D.begin();
00760 std::vector<geometry_msgs::Point>::const_iterator end = points2D.end();
00761 std::vector<cv::Point> points;
00762
00763 if (marker->filled) {
00764 points.push_back(cv::Point(it->x, it->y));
00765 }
00766 p0 = cv::Point2d(it->x, it->y); it++;
00767 for ( ; it!= end; it++ ) {
00768 p1 = cv::Point2d(it->x, it->y);
00769 if (marker->filled) {
00770 points.push_back(cv::Point(it->x, it->y));
00771 }
00772 cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00773 p0 = p1;
00774 if(++col_it == colors.end()) col_it = colors.begin();
00775 }
00776 it = points2D.begin();
00777 p1 = cv::Point2d(it->x, it->y);
00778 cv::line(draw_, p0, p1, *col_it, (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00779 if (marker->filled) {
00780 cv::fillConvexPoly(draw_, points.data(), points.size(), MsgToRGB(marker->fill_color));
00781 }
00782 break;
00783 }
00784 case image_view2::ImageMarker2::POINTS3D: {
00785 static std::map<std::string, int> tf_fail;
00786 std::string frame_id = marker->points3D.header.frame_id;
00787 tf::StampedTransform transform;
00788 ros::Time acquisition_time = msg->header.stamp;
00789
00790 ros::Duration timeout(tf_timeout);
00791 try {
00792 ros::Time tm;
00793 tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
00794 ros::Duration diff = ros::Time::now() - tm;
00795 if ( diff > ros::Duration(1.0) ) { break; }
00796 tf_listener_.waitForTransform(cam_model_.tfFrame(), frame_id,
00797 acquisition_time, timeout);
00798 tf_listener_.lookupTransform(cam_model_.tfFrame(), frame_id,
00799 acquisition_time, transform);
00800 tf_fail[frame_id]=0;
00801 }
00802 catch (tf::TransformException& ex) {
00803 tf_fail[frame_id]++;
00804 if ( tf_fail[frame_id] < 5 ) {
00805 ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
00806 } else {
00807 ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
00808 }
00809 break;
00810 }
00811 BOOST_FOREACH(geometry_msgs::Point p, marker->points3D.points) {
00812 tf::Point pt = transform.getOrigin();
00813 geometry_msgs::PointStamped pt_cam, pt_;
00814 pt_cam.header.frame_id = cam_model_.tfFrame();
00815 pt_cam.header.stamp = acquisition_time;
00816 pt_cam.point.x = pt.x();
00817 pt_cam.point.y = pt.y();
00818 pt_cam.point.z = pt.z();
00819 tf_listener_.transformPoint(frame_id, pt_cam, pt_);
00820
00821 cv::Point2d uv;
00822 tf::Stamped<tf::Point> pin, pout;
00823 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);
00824 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00825 uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00826 cv::circle(draw_, uv, (marker->scale == 0 ? 3 : marker->scale) , *col_it, -1);
00827 }
00828 break;
00829 }
00830 case image_view2::ImageMarker2::TEXT3D: {
00831 static std::map<std::string, int> tf_fail;
00832 std::string frame_id = marker->position3D.header.frame_id;
00833 tf::StampedTransform transform;
00834 ros::Time acquisition_time = msg->header.stamp;
00835
00836 ros::Duration timeout(tf_timeout);
00837 try {
00838 ros::Time tm;
00839 tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
00840 ros::Duration diff = ros::Time::now() - tm;
00841 if ( diff > ros::Duration(1.0) ) { break; }
00842 tf_listener_.waitForTransform(cam_model_.tfFrame(), frame_id,
00843 acquisition_time, timeout);
00844 tf_listener_.lookupTransform(cam_model_.tfFrame(), frame_id,
00845 acquisition_time, transform);
00846 tf_fail[frame_id]=0;
00847 }
00848 catch (tf::TransformException& ex) {
00849 tf_fail[frame_id]++;
00850 if ( tf_fail[frame_id] < 5 ) {
00851 ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
00852 } else {
00853 ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
00854 }
00855 break;
00856 }
00857 tf::Point pt = transform.getOrigin();
00858 geometry_msgs::PointStamped pt_cam, pt_;
00859 pt_cam.header.frame_id = cam_model_.tfFrame();
00860 pt_cam.header.stamp = acquisition_time;
00861 pt_cam.point.x = pt.x();
00862 pt_cam.point.y = pt.y();
00863 pt_cam.point.z = pt.z();
00864 tf_listener_.transformPoint(frame_id, pt_cam, pt_);
00865
00866 cv::Point2d uv;
00867 tf::Stamped<tf::Point> pin, pout;
00868 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);
00869 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00870 uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00871 cv::Size text_size;
00872 int baseline;
00873 float scale = marker->scale;
00874 if ( scale == 0 ) scale = 1.0;
00875 text_size = cv::getTextSize(marker->text.c_str(), font_,
00876 scale, scale, &baseline);
00877 cv::Point origin = cv::Point(uv.x - text_size.width/2,
00878 uv.y - baseline-3);
00879 cv::putText(draw_, marker->text.c_str(), origin, font_, scale, CV_RGB(0,255,0),3);
00880 break;
00881 }
00882 case image_view2::ImageMarker2::CIRCLE3D: {
00883 static std::map<std::string, int> tf_fail;
00884 std::string frame_id = marker->pose.header.frame_id;
00885 geometry_msgs::PoseStamped pose;
00886 ros::Time acquisition_time = msg->header.stamp;
00887 ros::Duration timeout(tf_timeout);
00888 try {
00889 ros::Time tm;
00890 tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
00891 ros::Duration diff = ros::Time::now() - tm;
00892 if ( diff > ros::Duration(1.0) ) { break; }
00893 tf_listener_.waitForTransform(cam_model_.tfFrame(), frame_id,
00894 acquisition_time, timeout);
00895 tf_listener_.transformPose(cam_model_.tfFrame(), acquisition_time, marker->pose, frame_id, pose);
00896 tf_fail[frame_id]=0;
00897 }
00898 catch (tf::TransformException& ex) {
00899 tf_fail[frame_id]++;
00900 if ( tf_fail[frame_id] < 5 ) {
00901 ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
00902 } else {
00903 ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
00904 }
00905 break;
00906 }
00907
00908 tf::Quaternion q;
00909 tf::quaternionMsgToTF(pose.pose.orientation, q);
00910 tf::Matrix3x3 rot = tf::Matrix3x3(q);
00911 double angle = (marker->arc == 0 ? 360.0 :marker->angle);
00912 double scale = (marker->scale == 0 ? DEFAULT_CIRCLE_SCALE : marker->scale);
00913 int N = 100;
00914 std::vector< std::vector<cv::Point2i> > ptss;
00915 std::vector<cv::Point2i> pts;
00916
00917 for (int i=0; i<N; ++i) {
00918 double th = angle * i / N * TFSIMD_RADS_PER_DEG;
00919 tf::Vector3 v = rot * tf::Vector3(scale * tfCos(th), scale * tfSin(th),0);
00920 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()));
00921 pts.push_back(cv::Point2i((int)pt.x, (int)pt.y));
00922 }
00923 ptss.push_back(pts);
00924
00925 cv::polylines(draw_, ptss, (marker->arc == 0 ? true : false), MsgToRGB(marker->outline_color), (marker->width == 0 ? DEFAULT_LINE_WIDTH : marker->width));
00926
00927 if (marker->filled) {
00928 if(marker->arc != 0){
00929 cv::Point2d pt = cam_model_.project3dToPixel(cv::Point3d(pose.pose.position.x, pose.pose.position.y, pose.pose.position.z));
00930 pts.push_back(cv::Point2i((int)pt.x, (int)pt.y));
00931 ptss.clear();
00932 ptss.push_back(pts);
00933 }
00934 cv::fillPoly(draw_, ptss, MsgToRGB(marker->fill_color));
00935 }
00936 break;
00937 }
00938 default: {
00939 ROS_WARN("Undefined Marker type(%d)", marker->type);
00940 break;
00941 }
00942 }
00943 }
00944 }
00945 if (mode_ == MODE_RECTANGLE) {
00946 cv::rectangle(draw_, cv::Point(window_selection_.x, window_selection_.y),
00947 cv::Point(window_selection_.x + window_selection_.width,
00948 window_selection_.y + window_selection_.height),
00949 USER_ROI_COLOR, 3, 8, 0);
00950 }
00951 else if (mode_ == MODE_SERIES) {
00952 if (point_array_.size() > 1) {
00953 cv::Point2d from, to;
00954 from = point_array_[0];
00955 for (size_t i = 1; i < point_array_.size(); i++) {
00956 to = point_array_[i];
00957 cv::line(draw_, from, to, USER_ROI_COLOR, 2, 8, 0);
00958 from = to;
00959 }
00960 }
00961 }
00962
00963 if ( blurry_mode ) cv::addWeighted(image_, 0.9, draw_, 1.0, 0.0, image_);
00964 if ( use_window ) {
00965 if (show_info) {
00966 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);
00967 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);
00968 }
00969
00970 cv::imshow(window_name_.c_str(), image_);
00971 }
00972 cv_bridge::CvImage out_msg;
00973 out_msg.header = msg->header;
00974 out_msg.encoding = "bgr8";
00975 out_msg.image = image_;
00976 image_pub_.publish(out_msg.toImageMsg());
00977 old_time = ros::Time::now();
00978 }
00979
00980 void draw_image() {
00981 if (image_.rows > 0 && image_.cols > 0) {
00982 cv::imshow(window_name_.c_str(), image_);
00983 }
00984 }
00985
00986 void addPoint(int x, int y)
00987 {
00988 cv::Point2d p;
00989 p.x = x;
00990 p.y = y;
00991 point_array_.push_back(p);
00992 }
00993
00994 void clearPointArray()
00995 {
00996 point_array_.clear();
00997 }
00998
00999 void publishPointArray()
01000 {
01001 pcl::PointCloud<pcl::PointXY> pcl_cloud;
01002 for (size_t i = 0; i < point_array_.size(); i++) {
01003 pcl::PointXY p;
01004 p.x = point_array_[i].x;
01005 p.y = point_array_[i].y;
01006 pcl_cloud.points.push_back(p);
01007 }
01008 sensor_msgs::PointCloud2::Ptr ros_cloud(new sensor_msgs::PointCloud2);
01009 pcl::toROSMsg(pcl_cloud, *ros_cloud);
01010 ros_cloud->header.stamp = ros::Time::now();
01011
01012 point_array_pub_.publish(ros_cloud);
01013 }
01014
01015
01016 void setMode(KEY_MODE mode)
01017 {
01018 mode_ = mode;
01019 }
01020
01021 KEY_MODE getMode()
01022 {
01023 return mode_;
01024 }
01025
01026 static void mouse_cb(int event, int x, int y, int flags, void* param)
01027 {
01028 ImageView2 *iv = (ImageView2*)param;
01029 static ros::Time left_buttondown_time(0);
01030 switch (event){
01031 case CV_EVENT_MOUSEMOVE:
01032 if ( ( left_buttondown_time.toSec() > 0 &&
01033 ros::Time::now().toSec() - left_buttondown_time.toSec() ) >= 1.0 ) {
01034 if (iv->getMode() == MODE_RECTANGLE) {
01035 window_selection_.width = x - window_selection_.x;
01036 window_selection_.height = y - window_selection_.y;
01037 }
01038 else if (iv->getMode() == MODE_SERIES) {
01039 iv->addPoint(x, y);
01040 }
01041 }
01042 {
01043
01044 geometry_msgs::PointStamped move_point;
01045 move_point.header.stamp = ros::Time::now();
01046 move_point.point.x = x;
01047 move_point.point.y = y;
01048 move_point.point.z = 0;
01049 iv->move_point_pub_.publish(move_point);
01050 }
01051 break;
01052 case CV_EVENT_LBUTTONDOWN:
01053 left_buttondown_time = ros::Time::now();
01054 window_selection_.x = x;
01055 window_selection_.y = y;
01056 break;
01057 case CV_EVENT_LBUTTONUP:
01058 if (iv->getMode() == MODE_SERIES) {
01059 iv->publishPointArray();
01060 iv->clearPointArray();
01061 }
01062 else {
01063 if ( ( ros::Time::now().toSec() - left_buttondown_time.toSec() ) < 0.5 ) {
01064 geometry_msgs::PointStamped screen_msg;
01065 screen_msg.point.x = window_selection_.x * resize_x_;
01066 screen_msg.point.y = window_selection_.y * resize_y_;
01067 screen_msg.point.z = 0;
01068 screen_msg.header.stamp = ros::Time::now();
01069 ROS_INFO("Publish screen point %s (%f %f)", iv->point_pub_.getTopic().c_str(), screen_msg.point.x, screen_msg.point.y);
01070 iv->point_pub_.publish(screen_msg);
01071 } else {
01072 geometry_msgs::PolygonStamped screen_msg;
01073 screen_msg.polygon.points.resize(2);
01074 screen_msg.polygon.points[0].x = window_selection_.x * resize_x_;
01075 screen_msg.polygon.points[0].y = window_selection_.y * resize_y_;
01076 screen_msg.polygon.points[1].x = (window_selection_.x + window_selection_.width) * resize_x_;
01077 screen_msg.polygon.points[1].y = (window_selection_.y + window_selection_.height) * resize_y_;
01078 screen_msg.header.stamp = ros::Time::now();
01079 ROS_INFO("Publish rectangle point %s (%f %f %f %f)", iv->rectangle_pub_.getTopic().c_str(),
01080 screen_msg.polygon.points[0].x, screen_msg.polygon.points[0].y,
01081 screen_msg.polygon.points[1].x, screen_msg.polygon.points[1].y);
01082 iv->rectangle_pub_.publish(screen_msg);
01083 }
01084 }
01085 window_selection_.x = window_selection_.y =
01086 window_selection_.width = window_selection_.height = 0;
01087 left_buttondown_time.fromSec(0);
01088 break;
01089 case CV_EVENT_RBUTTONDOWN:
01090 boost::lock_guard<boost::mutex> guard(iv->image_mutex_);
01091 if (!iv->image_.empty()) {
01092 std::string filename = (iv->filename_format_ % iv->count_).str();
01093 cv::imwrite(filename.c_str(), iv->image_);
01094 ROS_INFO("Saved image %s", filename.c_str());
01095 iv->count_++;
01096 } else {
01097 ROS_WARN("Couldn't save image, no data!");
01098 }
01099 break;
01100 }
01101 iv->draw_image();
01102 return;
01103 }
01104 };
01105
01106 int main(int argc, char **argv)
01107 {
01108
01109 ros::init(argc, argv, "image_view2");
01110 ros::NodeHandle n;
01111
01112 if ( n.resolveName("image") == "/image") {
01113 ROS_WARN("image_view: image has not been remapped! Typical command-line usage:\n"
01114 "\t$ ./image_view image:=<image topic> [transport]");
01115 }
01116
01117 ImageView2 view(n);
01118
01119
01120 while (ros::ok()) {
01121 ros::spinOnce();
01122 int key = cvWaitKey(33);
01123 if (key != -1) {
01124 if (key == 65505) {
01125 if (view.getMode() == ImageView2::MODE_RECTANGLE) {
01126 ROS_INFO("series mode");
01127 view.setMode(ImageView2::MODE_SERIES);
01128 }
01129 else {
01130 ROS_INFO("rectangle mode");
01131 view.setMode(ImageView2::MODE_RECTANGLE);
01132 }
01133 }
01134 }
01135 }
01136
01137 return 0;
01138 }
01139
01140 CvRect ImageView2::window_selection_;
01141 double ImageView2::resize_x_, ImageView2::resize_y_;