image_view2.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2008, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the Willow Garage nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
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     // convert lifetime to duration from Time(0)
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     // Hang on to message pointer for sake of mouse_cb
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         // remove marker by namespace and id
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         // if action == REMOVE and id == -1, clear all marker_queue
00271         if ( (*new_msg)->action == image_view2::ImageMarker2::REMOVE &&
00272              (*new_msg)->id == -1 ) {
00273           local_queue.clear();
00274         }
00275       }
00276     }
00277 
00278     // check lifetime and remove REMOVE-type marker msg
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     // Draw Section
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         //processMessage;
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             // outline colors
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             // check camera_info
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             // CIRCLE, LINE_STRIP, LINE_LIST, POLYGON, POINTS
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               // center point
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               // x, y, z
00525               cv::Point2d uv0, uv1, uv2;
00526               tf::Stamped<tf::Point> pin, pout;
00527 
00528               // x
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               // y
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               // z
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               // draw
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               // index
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             // draw text simply
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             // LINE_STRIP3D, LINE_LIST3D, POLYGON3D, POINTS3D, TEXT3D
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             //ros::Time acquisition_time = msg->points3D.header.stamp;
00596             ros::Duration timeout(tf_timeout); // wait 0.5 sec
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             //ros::Time acquisition_time = msg->points3D.header.stamp;
00656             ros::Duration timeout(tf_timeout); // wait 0.5 sec
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             //ros::Time acquisition_time = msg->points3D.header.stamp;
00716             ros::Duration timeout(tf_timeout); // wait 0.5 sec
00717             try {
00718               ros::Time tm;
00719               tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
00720               // ros::Duration diff = ros::Time::now() - tm;
00721               // if ( diff > ros::Duration(1.0) ) { break; }
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             //ros::Time acquisition_time = msg->points3D.header.stamp;
00790             ros::Duration timeout(tf_timeout); // wait 0.5 sec
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             //ros::Time acquisition_time = msg->position3D.header.stamp;
00836             ros::Duration timeout(tf_timeout); // wait 0.5 sec
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); // wait 0.5 sec
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) {                  // todo
01039           iv->addPoint(x, y);
01040         }
01041       }
01042       {
01043         // publish the points
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   //ros::init(argc, argv, "image_view2", ros::init_options::AnonymousName);
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   //ros::spin();
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_;


image_view2
Author(s): Kei Okada
autogenerated on Mon Oct 6 2014 10:54:45