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 
00055 
00056 typedef std::vector<image_view2::ImageMarker2::ConstPtr> V_ImageMarkerMessage;
00057 
00058 #define DEFAULT_COLOR  CV_RGB(255,0,0)
00059 #define USER_ROI_COLOR CV_RGB(255,0,0)
00060 #define DEFAULT_CIRCLE_SCALE  20
00061 #define LINE_WIDTH             3
00062 
00063 inline CvScalar MsgToRGB(const std_msgs::ColorRGBA &color){
00064   if(color.a == 0.0 && color.r == 0.0 && color.g == 0.0 && color.b == 0.0)
00065     return DEFAULT_COLOR;
00066   else
00067     return CV_RGB(color.r*255, color.g*255, color.b*255);
00068 }
00069 
00070 
00071 class ImageView2
00072 {
00073 private:
00074   image_transport::Subscriber image_sub_;
00075   ros::Subscriber info_sub_;
00076   ros::Subscriber marker_sub_;
00077   std::string marker_topic_;
00078 
00079   image_transport::Publisher image_pub_;
00080 
00081   V_ImageMarkerMessage marker_queue_;
00082   boost::mutex queue_mutex_;
00083 
00084   sensor_msgs::ImageConstPtr last_msg_;
00085   sensor_msgs::CameraInfoConstPtr info_msg_;
00086   cv_bridge::CvImage img_bridge_;
00087   boost::mutex image_mutex_;
00088   cv::Mat image_, draw_;
00089 
00090   tf::TransformListener tf_listener_;
00091   image_geometry::PinholeCameraModel cam_model_;
00092   std::vector<std::string> frame_ids_;
00093   boost::mutex info_mutex_;
00094 
00095   std::string window_name_;
00096   boost::format filename_format_;
00097   int font_;
00098   static CvRect window_selection_;
00099   int count_;
00100   bool blurry_mode;
00101   bool use_window;
00102 
00103   ros::Publisher point_pub_;
00104   ros::Publisher rectangle_pub_;
00105 
00106 public:
00107   ImageView2() : marker_topic_("image_marker"), filename_format_(""), count_(0)
00108   {
00109   }
00110   ImageView2(ros::NodeHandle& nh, const std::string& transport)
00111     : marker_topic_("image_marker"), filename_format_(""), count_(0)
00112   {
00113     std::string camera = nh.resolveName("image");
00114     std::string camera_info = nh.resolveName("camera_info");
00115     ros::NodeHandle local_nh("~");
00116     bool autosize;
00117     std::string format_string;
00118     image_transport::ImageTransport it(nh);
00119 
00120     point_pub_ = nh.advertise<geometry_msgs::PointStamped>(camera + "/screenpoint",100);
00121     rectangle_pub_ = nh.advertise<geometry_msgs::PolygonStamped>(camera + "/screenrectangle",100);
00122 
00123     local_nh.param("window_name", window_name_, std::string("image_view2 [")+camera+std::string("]"));
00124 
00125     local_nh.param("autosize", autosize, false);
00126 
00127     local_nh.param("blurry", blurry_mode, false);
00128 
00129     local_nh.param("filename_format", format_string, std::string("frame%04i.jpg"));
00130     local_nh.param("use_window", use_window, true);
00131 
00132     filename_format_.parse(format_string);
00133 
00134     if ( use_window ) {
00135         cvNamedWindow(window_name_.c_str(), autosize ? CV_WINDOW_AUTOSIZE : 0);
00136         cvSetMouseCallback(window_name_.c_str(), &ImageView2::mouse_cb, this);
00137         font_ = cv::FONT_HERSHEY_DUPLEX;
00138         window_selection_.x = window_selection_.y =
00139             window_selection_.height = window_selection_.width = 0;
00140         cvStartWindowThread();
00141     }
00142 
00143     image_sub_ = it.subscribe(camera, 1, &ImageView2::image_cb, this, transport);
00144     info_sub_ = nh.subscribe(camera_info, 1, &ImageView2::info_cb, this);
00145     marker_sub_ = nh.subscribe(marker_topic_, 10, &ImageView2::marker_cb, this);
00146 
00147     image_pub_ = it.advertise("image_marked", 1);
00148   }
00149 
00150   ~ImageView2()
00151   {
00152     if ( use_window ) {
00153         cvDestroyWindow(window_name_.c_str());
00154     }
00155   }
00156 
00157   void marker_cb(const image_view2::ImageMarker2ConstPtr& marker)
00158   {
00159     ROS_DEBUG("marker_cb");
00160     // convert lifetime to duration from Time(0)
00161     if(marker->lifetime != ros::Duration(0))
00162       boost::const_pointer_cast<image_view2::ImageMarker2>(marker)->lifetime = (ros::Time::now() - ros::Time(0)) + marker->lifetime;
00163     boost::mutex::scoped_lock lock(queue_mutex_);
00164 
00165     marker_queue_.push_back(marker);
00166 
00167   }
00168 
00169   void info_cb(const sensor_msgs::CameraInfoConstPtr& msg) {
00170     ROS_DEBUG("info_cb");
00171     boost::mutex::scoped_lock lock(info_mutex_);
00172     info_msg_ = msg;
00173   }
00174 
00175   void image_cb(const sensor_msgs::ImageConstPtr& msg)
00176   {
00177     static ros::Time old_time;
00178     ROS_DEBUG("image_cb");
00179     if(old_time.toSec() - ros::Time::now().toSec() > 0) {
00180       ROS_WARN("TF Cleared for old time");
00181     }
00182 
00183     if (msg->encoding.find("bayer") != std::string::npos) {
00184       image_ = cv::Mat(msg->height, msg->width, CV_8UC1,
00185                        const_cast<uint8_t*>(&msg->data[0]), msg->step);
00186     } else {
00187       try {
00188         image_ = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8)->image;
00189       } catch (cv_bridge::Exception& e) {
00190         ROS_ERROR("Unable to convert %s image to bgr8", msg->encoding.c_str());
00191         return;
00192       }
00193     }
00194     boost::lock_guard<boost::mutex> guard(image_mutex_);
00195     // Hang on to message pointer for sake of mouse_cb
00196     last_msg_ = msg;
00197 
00198     static V_ImageMarkerMessage local_queue;
00199     {
00200       boost::mutex::scoped_lock lock(queue_mutex_);
00201 
00202       while ( ! marker_queue_.empty() ) {
00203         // remove marker by namespace and id
00204         V_ImageMarkerMessage::iterator new_msg = marker_queue_.begin();
00205         V_ImageMarkerMessage::iterator message_it = local_queue.begin();
00206         for ( ; message_it < local_queue.end(); ++message_it ) {
00207           if((*new_msg)->ns == (*message_it)->ns && (*new_msg)->id == (*message_it)->id)
00208             message_it = local_queue.erase(message_it);
00209         }
00210         local_queue.push_back(*new_msg);
00211         marker_queue_.erase(new_msg);
00212         // if action == REMOVE and id == -1, clear all marker_queue
00213         if ( (*new_msg)->action == image_view2::ImageMarker2::REMOVE &&
00214              (*new_msg)->id == -1 ) {
00215           local_queue.clear();
00216         }
00217       }
00218     }
00219 
00220     // check lifetime and remove REMOVE-type marker msg
00221     for(V_ImageMarkerMessage::iterator it = local_queue.begin(); it < local_queue.end(); it++) {
00222       if((*it)->action == image_view2::ImageMarker2::REMOVE ||
00223          ((*it)->lifetime.toSec() != 0.0 && (*it)->lifetime.toSec() < ros::Time::now().toSec())) {
00224         it = local_queue.erase(it);
00225       }
00226     }
00227 
00228     // Draw Section
00229     if ( blurry_mode ) {
00230       draw_ = cv::Mat(image_.size(), image_.type(), CV_RGB(0,0,0));
00231     } else {
00232       draw_ = image_;
00233     }
00234     if ( !local_queue.empty() )
00235       {
00236         V_ImageMarkerMessage::iterator message_it = local_queue.begin();
00237         V_ImageMarkerMessage::iterator message_end = local_queue.end();
00238         ROS_DEBUG("markers = %ld", local_queue.size());
00239         //processMessage;
00240         for ( ; message_it != message_end; ++message_it )
00241           {
00242             image_view2::ImageMarker2::ConstPtr& marker = *message_it;
00243 
00244             ROS_DEBUG_STREAM("message type = " << marker->type << ", id " << marker->id);
00245 
00246             // outline colors
00247             std::vector<CvScalar> colors;
00248             BOOST_FOREACH(std_msgs::ColorRGBA color, marker->outline_colors) {
00249               colors.push_back(MsgToRGB(color));
00250             }
00251             if(colors.size() == 0) colors.push_back(DEFAULT_COLOR);
00252             std::vector<CvScalar>::iterator col_it = colors.begin();
00253 
00254             // check camera_info
00255             if( marker->type == image_view2::ImageMarker2::FRAMES ||
00256                 marker->type == image_view2::ImageMarker2::LINE_STRIP3D ||
00257                 marker->type == image_view2::ImageMarker2::LINE_LIST3D ||
00258                 marker->type == image_view2::ImageMarker2::POLYGON3D ||
00259                 marker->type == image_view2::ImageMarker2::POINTS3D ||
00260                 marker->type == image_view2::ImageMarker2::TEXT3D) {
00261               {
00262                 boost::mutex::scoped_lock lock(info_mutex_);
00263                 if (!info_msg_) {
00264                   ROS_WARN("[image_view2] camera_info could not found");
00265                   continue;
00266                 }
00267                 cam_model_.fromCameraInfo(info_msg_);
00268               }
00269             }
00270             // CIRCLE, LINE_STRIP, LINE_LIST, POLYGON, POINTS
00271             switch ( marker->type ) {
00272             case image_view2::ImageMarker2::CIRCLE: {
00273               cv::Point2d uv = cv::Point2d(marker->position.x, marker->position.y);
00274               if ( blurry_mode ) {
00275                 int s0 = LINE_WIDTH;
00276                 CvScalar co = MsgToRGB(marker->outline_color);
00277                 for (int s1 = s0*10; s1 >= s0; s1--) {
00278                   double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
00279                   cv::circle(draw_, uv,
00280                              (marker->scale == 0 ? DEFAULT_CIRCLE_SCALE : marker->scale),
00281                              CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m),
00282                              s1);
00283                 }
00284               } else {
00285                 cv::circle(draw_, uv, (marker->scale == 0 ? DEFAULT_CIRCLE_SCALE : marker->scale), MsgToRGB(marker->outline_color), LINE_WIDTH);
00286               }
00287               break;
00288             }
00289             case image_view2::ImageMarker2::LINE_STRIP: {
00290               cv::Point2d p0, p1;
00291               if ( blurry_mode ) {
00292                 int s0 = LINE_WIDTH;
00293                 std::vector<CvScalar>::iterator col_it = colors.begin();
00294                 CvScalar co = (*col_it);
00295                 for (int s1 = s0*10; s1 >= s0; s1--) {
00296                   double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
00297                   std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00298                   std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00299                   p0 = cv::Point2d(it->x, it->y); it++;
00300                   for ( ; it!= end; it++ ) {
00301                     p1 = cv::Point2d(it->x, it->y);
00302                     cv::line(draw_, p0, p1,
00303                              CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m),
00304                              s1);
00305                     p0 = p1;
00306                     if(++col_it == colors.end()) col_it = colors.begin();
00307                   }
00308                 }
00309               } else {
00310                 std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00311                 std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00312                 p0 = cv::Point2d(it->x, it->y); it++;
00313                 for ( ; it!= end; it++ ) {
00314                   p1 = cv::Point2d(it->x, it->y);
00315                   cv::line(draw_, p0, p1, *col_it, LINE_WIDTH);
00316                   p0 = p1;
00317                   if(++col_it == colors.end()) col_it = colors.begin();
00318                 }
00319               }
00320               break;
00321             }
00322             case image_view2::ImageMarker2::LINE_LIST: {
00323               cv::Point2d p0, p1;
00324               if ( blurry_mode ) {
00325                 int s0 = LINE_WIDTH;
00326                 std::vector<CvScalar>::iterator col_it = colors.begin();
00327                 CvScalar co = (*col_it);
00328                 for (int s1 = s0*10; s1 >= s0; s1--) {
00329                   double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
00330                   std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00331                   std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00332                   for ( ; it!= end; ) {
00333                     p0 = cv::Point2d(it->x, it->y); it++;
00334                     if ( it != end ) p1 = cv::Point2d(it->x, it->y);
00335                     cv::line(draw_, p0, p1, CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m), s1);
00336                     it++;
00337                     if(++col_it == colors.end()) col_it = colors.begin();
00338                   }
00339                 }
00340               } else {
00341                 std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00342                 std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00343                 for ( ; it!= end; ) {
00344                   p0 = cv::Point2d(it->x, it->y); it++;
00345                   if ( it != end ) p1 = cv::Point2d(it->x, it->y);
00346                   cv::line(draw_, p0, p1, *col_it, LINE_WIDTH);
00347                   it++;
00348                   if(++col_it == colors.end()) col_it = colors.begin();
00349                 }
00350               }
00351               break;
00352             }
00353             case image_view2::ImageMarker2::POLYGON: {
00354               cv::Point2d p0, p1;
00355               if ( blurry_mode ) {
00356                 int s0 = LINE_WIDTH;
00357                 std::vector<CvScalar>::iterator col_it = colors.begin();
00358                 CvScalar co = (*col_it);
00359                 for (int s1 = s0*10; s1 >= s0; s1--) {
00360                   double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
00361                   std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00362                   std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00363                   p0 = cv::Point2d(it->x, it->y); it++;
00364                   for ( ; it!= end; it++ ) {
00365                     p1 = cv::Point2d(it->x, it->y);
00366                     cv::line(draw_, p0, p1, CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m), s1);
00367                     p0 = p1;
00368                     if(++col_it == colors.end()) col_it = colors.begin();
00369                   }
00370                   it = marker->points.begin();
00371                   p1 = cv::Point2d(it->x, it->y);
00372                   cv::line(draw_, p0, p1, CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m), s1);
00373                 }
00374               } else {
00375                 std::vector<geometry_msgs::Point>::const_iterator it = marker->points.begin();
00376                 std::vector<geometry_msgs::Point>::const_iterator end = marker->points.end();
00377                 p0 = cv::Point2d(it->x, it->y); it++;
00378                 for ( ; it!= end; it++ ) {
00379                   p1 = cv::Point2d(it->x, it->y);
00380                   cv::line(draw_, p0, p1, *col_it, LINE_WIDTH);
00381                   p0 = p1;
00382                   if(++col_it == colors.end()) col_it = colors.begin();
00383                 }
00384                 it = marker->points.begin();
00385                 p1 = cv::Point2d(it->x, it->y);
00386                 cv::line(draw_, p0, p1, *col_it, LINE_WIDTH);
00387               }
00388               break;
00389             }
00390             case image_view2::ImageMarker2::POINTS: {
00391               BOOST_FOREACH(geometry_msgs::Point p, marker->points) {
00392                 cv::Point2d uv = cv::Point2d(p.x, p.y);
00393                 if ( blurry_mode ) {
00394                   int s0 = (marker->scale == 0 ? 3 : marker->scale);
00395                   CvScalar co = (*col_it);
00396                   for (int s1 = s0*2; s1 >= s0; s1--) {
00397                     double m = pow((1.0-((double)(s1 - s0))/s0),2);
00398                     cv::circle(draw_, uv, s1,
00399                                CV_RGB(co.val[2] * m,co.val[1] * m,co.val[0] * m),
00400                                -1);
00401                   }
00402                 } else {
00403                   cv::circle(draw_, uv, (marker->scale == 0 ? 3 : marker->scale) , *col_it, -1);
00404                 }
00405                 if(++col_it == colors.end()) col_it = colors.begin();
00406               }
00407               break;
00408             }
00409             case image_view2::ImageMarker2::FRAMES: {
00410               static std::map<std::string, int> tf_fail;
00411               BOOST_FOREACH(std::string frame_id, marker->frames) {
00412                 tf::StampedTransform transform;
00413                 ros::Time acquisition_time = msg->header.stamp;
00414                 ros::Duration timeout(1.0 / 2); // wait 0.5 sec
00415                 try {
00416                    ros::Time tm;
00417                    tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
00418                    ros::Duration diff = ros::Time::now() - tm;
00419                    if ( diff > ros::Duration(1.0) ) { break; }
00420 
00421                   tf_listener_.waitForTransform(cam_model_.tfFrame(), frame_id,
00422                                                 acquisition_time, timeout);
00423                   tf_listener_.lookupTransform(cam_model_.tfFrame(), frame_id,
00424                                                acquisition_time, transform);
00425                   tf_fail[frame_id]=0;
00426                 }
00427                 catch (tf::TransformException& ex) {
00428                   tf_fail[frame_id]++;
00429                   if ( tf_fail[frame_id] < 5 ) {
00430                     ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
00431                   } else {
00432                     ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
00433                   }
00434                   break;
00435                 }
00436                 // center point
00437                 tf::Point pt = transform.getOrigin();
00438                 cv::Point3d pt_cv(pt.x(), pt.y(), pt.z());
00439                 cv::Point2d uv;
00440                 uv = cam_model_.project3dToPixel(pt_cv);
00441 
00442                 static const int RADIUS = 3;
00443                 cv::circle(draw_, uv, RADIUS, DEFAULT_COLOR, -1);
00444 
00445                 // x, y, z
00446                 cv::Point2d uv0, uv1, uv2;
00447                 tf::Stamped<tf::Point> pin, pout;
00448 
00449                 // x
00450                 pin = tf::Stamped<tf::Point>(tf::Point(0.05, 0, 0), acquisition_time, frame_id);
00451                 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00452                 uv0 = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00453                 // y
00454                 pin = tf::Stamped<tf::Point>(tf::Point(0, 0.05, 0), acquisition_time, frame_id);
00455                 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00456                 uv1 = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00457 
00458                 // z
00459                 pin = tf::Stamped<tf::Point>(tf::Point(0, 0, 0.05), acquisition_time, frame_id);
00460                 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00461                 uv2 = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00462 
00463                 // draw
00464                 if ( blurry_mode ) {
00465                   int s0 = 2;
00466                   CvScalar c0 = CV_RGB(255,0,0);
00467                   CvScalar c1 = CV_RGB(0,255,0);
00468                   CvScalar c2 = CV_RGB(0,0,255);
00469                   for (int s1 = s0*10; s1 >= s0; s1--) {
00470                     double m = pow((1.0-((double)(s1 - s0))/(s0*9)),2);
00471                     cv::line(draw_, uv, uv0,
00472                              CV_RGB(c0.val[2] * m,c0.val[1] * m,c0.val[0] * m),
00473                              s1);
00474                     cv::line(draw_, uv, uv1,
00475                              CV_RGB(c1.val[2] * m,c1.val[1] * m,c1.val[0] * m),
00476                              s1);
00477                     cv::line(draw_, uv, uv2,
00478                              CV_RGB(c2.val[2] * m,c2.val[1] * m,c2.val[0] * m),
00479                              s1);
00480                   }
00481                 } else {
00482                   cv::line(draw_, uv, uv0, CV_RGB(255,0,0), 2);
00483                   cv::line(draw_, uv, uv1, CV_RGB(0,255,0), 2);
00484                   cv::line(draw_, uv, uv2, CV_RGB(0,0,255), 2);
00485                 }
00486 
00487                 // index
00488                 cv::Size text_size;
00489                 int baseline;
00490                 text_size = cv::getTextSize(frame_id.c_str(), font_, 1.0, 1.0, &baseline);
00491                 cv::Point origin = cv::Point(uv.x - text_size.width / 2,
00492                                              uv.y - RADIUS - baseline - 3);
00493                 cv::putText(draw_, frame_id.c_str(), origin, font_, 1.0, DEFAULT_COLOR, 1.5);
00494               }
00495               break;
00496             }
00497             case image_view2::ImageMarker2::TEXT: {
00498               // draw text simply
00499               cv::Size text_size;
00500               int baseline;
00501               float scale = marker->scale;
00502               if ( scale == 0 ) scale = 1.0;
00503               text_size = cv::getTextSize(marker->text.c_str(), font_,
00504                                           scale, scale, &baseline);
00505               cv::Point origin = cv::Point(marker->position.x - text_size.width/2,
00506                                            marker->position.y - baseline-3);
00507               cv::putText(draw_, marker->text.c_str(), origin, font_, scale, DEFAULT_COLOR);
00508               break;
00509             }
00510             // LINE_STRIP3D, LINE_LIST3D, POLYGON3D, POINTS3D, TEXT3D
00511             case image_view2::ImageMarker2::LINE_STRIP3D: {
00512               static std::map<std::string, int> tf_fail;
00513               std::string frame_id = marker->points3D.header.frame_id;
00514               tf::StampedTransform transform;
00515               ros::Time acquisition_time = msg->header.stamp;
00516               //ros::Time acquisition_time = msg->points3D.header.stamp;
00517               ros::Duration timeout(1.0 / 2); // wait 0.5 sec
00518               try {
00519                 ros::Time tm;
00520                 tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
00521                 ros::Duration diff = ros::Time::now() - tm;
00522                 if ( diff > ros::Duration(1.0) ) { break; }
00523                 tf_listener_.waitForTransform(cam_model_.tfFrame(), frame_id,
00524                                               acquisition_time, timeout);
00525                 tf_listener_.lookupTransform(cam_model_.tfFrame(), frame_id,
00526                                              acquisition_time, transform);
00527                 tf_fail[frame_id]=0;
00528               }
00529               catch (tf::TransformException& ex) {
00530                 tf_fail[frame_id]++;
00531                 if ( tf_fail[frame_id] < 5 ) {
00532                   ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
00533                 } else {
00534                   ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
00535                 }
00536                 break;
00537               }
00538               std::vector<geometry_msgs::Point> points2D;
00539               BOOST_FOREACH(geometry_msgs::Point p, marker->points3D.points) {
00540                 tf::Point pt = transform.getOrigin();
00541                 geometry_msgs::PointStamped pt_cam, pt_;
00542                 pt_cam.header.frame_id = cam_model_.tfFrame();
00543                 pt_cam.header.stamp = acquisition_time;
00544                 pt_cam.point.x = pt.x();
00545                 pt_cam.point.y = pt.y();
00546                 pt_cam.point.z = pt.z();
00547                 tf_listener_.transformPoint(frame_id, pt_cam, pt_);
00548 
00549                 cv::Point2d uv;
00550                 tf::Stamped<tf::Point> pin, pout;
00551                 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);
00552                 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00553                 uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00554                 geometry_msgs::Point point2D;
00555                 point2D.x = uv.x;
00556                 point2D.y = uv.y;
00557                 points2D.push_back(point2D);
00558               }
00559               cv::Point2d p0, p1;
00560               std::vector<geometry_msgs::Point>::const_iterator it = points2D.begin();
00561               std::vector<geometry_msgs::Point>::const_iterator end = points2D.end();
00562               p0 = cv::Point2d(it->x, it->y); it++;
00563               for ( ; it!= end; it++ ) {
00564                 p1 = cv::Point2d(it->x, it->y);
00565                 cv::line(draw_, p0, p1, *col_it, LINE_WIDTH);
00566                 p0 = p1;
00567                 if(++col_it == colors.end()) col_it = colors.begin();
00568               }
00569               break;
00570             }
00571             case image_view2::ImageMarker2::LINE_LIST3D: {
00572               static std::map<std::string, int> tf_fail;
00573               std::string frame_id = marker->points3D.header.frame_id;
00574               tf::StampedTransform transform;
00575               ros::Time acquisition_time = msg->header.stamp;
00576               //ros::Time acquisition_time = msg->points3D.header.stamp;
00577               ros::Duration timeout(1.0 / 2); // wait 0.5 sec
00578               try {
00579                 ros::Time tm;
00580                 tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
00581                 ros::Duration diff = ros::Time::now() - tm;
00582                 if ( diff > ros::Duration(1.0) ) { break; }
00583                 tf_listener_.waitForTransform(cam_model_.tfFrame(), frame_id,
00584                                               acquisition_time, timeout);
00585                 tf_listener_.lookupTransform(cam_model_.tfFrame(), frame_id,
00586                                              acquisition_time, transform);
00587                 tf_fail[frame_id]=0;
00588               }
00589               catch (tf::TransformException& ex) {
00590                 tf_fail[frame_id]++;
00591                 if ( tf_fail[frame_id] < 5 ) {
00592                   ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
00593                 } else {
00594                   ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
00595                 }
00596                 break;
00597               }
00598               std::vector<geometry_msgs::Point> points2D;
00599               BOOST_FOREACH(geometry_msgs::Point p, marker->points3D.points) {
00600                 tf::Point pt = transform.getOrigin();
00601                 geometry_msgs::PointStamped pt_cam, pt_;
00602                 pt_cam.header.frame_id = cam_model_.tfFrame();
00603                 pt_cam.header.stamp = acquisition_time;
00604                 pt_cam.point.x = pt.x();
00605                 pt_cam.point.y = pt.y();
00606                 pt_cam.point.z = pt.z();
00607                 tf_listener_.transformPoint(frame_id, pt_cam, pt_);
00608 
00609                 cv::Point2d uv;
00610                 tf::Stamped<tf::Point> pin, pout;
00611                 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);
00612                 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00613                 uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00614                 geometry_msgs::Point point2D;
00615                 point2D.x = uv.x;
00616                 point2D.y = uv.y;
00617                 points2D.push_back(point2D);
00618               }
00619               cv::Point2d p0, p1;
00620               std::vector<geometry_msgs::Point>::const_iterator it = points2D.begin();
00621               std::vector<geometry_msgs::Point>::const_iterator end = points2D.end();
00622               for ( ; it!= end; ) {
00623                 p0 = cv::Point2d(it->x, it->y); it++;
00624                 if ( it != end ) p1 = cv::Point2d(it->x, it->y);
00625                 cv::line(draw_, p0, p1, *col_it, LINE_WIDTH);
00626                 it++;
00627                 if(++col_it == colors.end()) col_it = colors.begin();
00628               }
00629               break;
00630             }
00631             case image_view2::ImageMarker2::POLYGON3D: {
00632               static std::map<std::string, int> tf_fail;
00633               std::string frame_id = marker->points3D.header.frame_id;
00634               tf::StampedTransform transform;
00635               ros::Time acquisition_time = msg->header.stamp;
00636               //ros::Time acquisition_time = msg->points3D.header.stamp;
00637               ros::Duration timeout(1.0 / 2); // wait 0.5 sec
00638               try {
00639                 ros::Time tm;
00640                 tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
00641                 ros::Duration diff = ros::Time::now() - tm;
00642                 if ( diff > ros::Duration(1.0) ) { break; }
00643                 tf_listener_.waitForTransform(cam_model_.tfFrame(), frame_id,
00644                                               acquisition_time, timeout);
00645                 tf_listener_.lookupTransform(cam_model_.tfFrame(), frame_id,
00646                                              acquisition_time, transform);
00647                 tf_fail[frame_id]=0;
00648               }
00649               catch (tf::TransformException& ex) {
00650                 tf_fail[frame_id]++;
00651                 if ( tf_fail[frame_id] < 5 ) {
00652                   ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
00653                 } else {
00654                   ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
00655                 }
00656                 break;
00657               }
00658               std::vector<geometry_msgs::Point> points2D;
00659               BOOST_FOREACH(geometry_msgs::Point p, marker->points3D.points) {
00660                 tf::Point pt = transform.getOrigin();
00661                 geometry_msgs::PointStamped pt_cam, pt_;
00662                 pt_cam.header.frame_id = cam_model_.tfFrame();
00663                 pt_cam.header.stamp = acquisition_time;
00664                 pt_cam.point.x = pt.x();
00665                 pt_cam.point.y = pt.y();
00666                 pt_cam.point.z = pt.z();
00667                 tf_listener_.transformPoint(frame_id, pt_cam, pt_);
00668 
00669                 cv::Point2d uv;
00670                 tf::Stamped<tf::Point> pin, pout;
00671                 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);
00672                 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00673                 uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00674                 geometry_msgs::Point point2D;
00675                 point2D.x = uv.x;
00676                 point2D.y = uv.y;
00677                 points2D.push_back(point2D);
00678               }
00679               cv::Point2d p0, p1;
00680               std::vector<geometry_msgs::Point>::const_iterator it = points2D.begin();
00681               std::vector<geometry_msgs::Point>::const_iterator end = points2D.end();
00682               p0 = cv::Point2d(it->x, it->y); it++;
00683               for ( ; it!= end; it++ ) {
00684                 p1 = cv::Point2d(it->x, it->y);
00685                 cv::line(draw_, p0, p1, *col_it, LINE_WIDTH);
00686                 p0 = p1;
00687                 if(++col_it == colors.end()) col_it = colors.begin();
00688               }
00689               it = points2D.begin();
00690               p1 = cv::Point2d(it->x, it->y);
00691               cv::line(draw_, p0, p1, *col_it, LINE_WIDTH);
00692               break;
00693             }
00694             case image_view2::ImageMarker2::POINTS3D: {
00695               static std::map<std::string, int> tf_fail;
00696               std::string frame_id = marker->points3D.header.frame_id;
00697               tf::StampedTransform transform;
00698               ros::Time acquisition_time = msg->header.stamp;
00699               //ros::Time acquisition_time = msg->points3D.header.stamp;
00700               ros::Duration timeout(1.0 / 2); // wait 0.5 sec
00701               try {
00702                 ros::Time tm;
00703                 tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
00704                 ros::Duration diff = ros::Time::now() - tm;
00705                 if ( diff > ros::Duration(1.0) ) { break; }
00706                 tf_listener_.waitForTransform(cam_model_.tfFrame(), frame_id,
00707                                               acquisition_time, timeout);
00708                 tf_listener_.lookupTransform(cam_model_.tfFrame(), frame_id,
00709                                              acquisition_time, transform);
00710                 tf_fail[frame_id]=0;
00711               }
00712               catch (tf::TransformException& ex) {
00713                 tf_fail[frame_id]++;
00714                 if ( tf_fail[frame_id] < 5 ) {
00715                   ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
00716                 } else {
00717                   ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
00718                 }
00719                 break;
00720               }
00721               BOOST_FOREACH(geometry_msgs::Point p, marker->points3D.points) {
00722                 tf::Point pt = transform.getOrigin();
00723                 geometry_msgs::PointStamped pt_cam, pt_;
00724                 pt_cam.header.frame_id = cam_model_.tfFrame();
00725                 pt_cam.header.stamp = acquisition_time;
00726                 pt_cam.point.x = pt.x();
00727                 pt_cam.point.y = pt.y();
00728                 pt_cam.point.z = pt.z();
00729                 tf_listener_.transformPoint(frame_id, pt_cam, pt_);
00730 
00731                 cv::Point2d uv;
00732                 tf::Stamped<tf::Point> pin, pout;
00733                 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);
00734                 tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00735                 uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00736                 cv::circle(draw_, uv, (marker->scale == 0 ? 3 : marker->scale) , *col_it, -1);
00737               }
00738               break;
00739             }
00740             case image_view2::ImageMarker2::TEXT3D: {
00741               static std::map<std::string, int> tf_fail;
00742               std::string frame_id = marker->position3D.header.frame_id;
00743               tf::StampedTransform transform;
00744               ros::Time acquisition_time = msg->header.stamp;
00745               //ros::Time acquisition_time = msg->position3D.header.stamp;
00746               ros::Duration timeout(1.0 / 2); // wait 0.5 sec
00747               try {
00748                 ros::Time tm;
00749                 tf_listener_.getLatestCommonTime(cam_model_.tfFrame(), frame_id, tm, NULL);
00750                 ros::Duration diff = ros::Time::now() - tm;
00751                 if ( diff > ros::Duration(1.0) ) { break; }
00752                 tf_listener_.waitForTransform(cam_model_.tfFrame(), frame_id,
00753                                               acquisition_time, timeout);
00754                 tf_listener_.lookupTransform(cam_model_.tfFrame(), frame_id,
00755                                              acquisition_time, transform);
00756                 tf_fail[frame_id]=0;
00757               }
00758               catch (tf::TransformException& ex) {
00759                 tf_fail[frame_id]++;
00760                 if ( tf_fail[frame_id] < 5 ) {
00761                   ROS_ERROR("[image_view2] TF exception:\n%s", ex.what());
00762                 } else {
00763                   ROS_DEBUG("[image_view2] TF exception:\n%s", ex.what());
00764                 }
00765                 break;
00766               }
00767               tf::Point pt = transform.getOrigin();
00768               geometry_msgs::PointStamped pt_cam, pt_;
00769               pt_cam.header.frame_id = cam_model_.tfFrame();
00770               pt_cam.header.stamp = acquisition_time;
00771               pt_cam.point.x = pt.x();
00772               pt_cam.point.y = pt.y();
00773               pt_cam.point.z = pt.z();
00774               tf_listener_.transformPoint(frame_id, pt_cam, pt_);
00775 
00776               cv::Point2d uv;
00777               tf::Stamped<tf::Point> pin, pout;
00778               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);
00779               tf_listener_.transformPoint(cam_model_.tfFrame(), pin, pout);
00780               uv = cam_model_.project3dToPixel(cv::Point3d(pout.x(), pout.y(), pout.z()));
00781               cv::Size text_size;
00782               int baseline;
00783               float scale = marker->scale;
00784               if ( scale == 0 ) scale = 1.0;
00785               text_size = cv::getTextSize(marker->text.c_str(), font_,
00786                                           scale, scale, &baseline);
00787               cv::Point origin = cv::Point(uv.x - text_size.width/2,
00788                                            uv.y - baseline-3);
00789               cv::putText(draw_, marker->text.c_str(), origin, font_, scale, CV_RGB(0,255,0),3);
00790               break;
00791             }
00792             default: {
00793               ROS_WARN("Undefined Marker type(%d)", marker->type);
00794               break;
00795             }
00796           }
00797         }
00798       }
00799     cv::rectangle(draw_, cv::Point(window_selection_.x, window_selection_.y),
00800                   cv::Point(window_selection_.x + window_selection_.width,
00801                             window_selection_.y + window_selection_.height),
00802                 USER_ROI_COLOR, 3, 8, 0);
00803 
00804     if ( blurry_mode ) cv::addWeighted(image_, 0.9, draw_, 1.0, 0.0, image_);
00805     if ( use_window ) {
00806         cv::imshow(window_name_.c_str(), image_);
00807     }
00808     cv_bridge::CvImage out_msg;
00809     out_msg.header   = msg->header;
00810     out_msg.encoding = "bgr8";
00811     out_msg.image    = image_;
00812     image_pub_.publish(out_msg.toImageMsg());
00813     old_time = ros::Time::now();
00814   }
00815 
00816   static void mouse_cb(int event, int x, int y, int flags, void* param)
00817   {
00818     ImageView2 *iv = (ImageView2*)param;
00819     static ros::Time left_buttondown_time(0);
00820     switch (event){
00821     case CV_EVENT_MOUSEMOVE:
00822       if ( ( left_buttondown_time.toSec() > 0 &&
00823              ros::Time::now().toSec() - left_buttondown_time.toSec() ) >= 1.0 ) {
00824         window_selection_.width  = x - window_selection_.x;
00825         window_selection_.height = y - window_selection_.y;
00826       }
00827       break;
00828     case CV_EVENT_LBUTTONDOWN:
00829       left_buttondown_time = ros::Time::now();
00830       window_selection_.x = x;
00831       window_selection_.y = y;
00832       break;
00833     case CV_EVENT_LBUTTONUP:
00834       if ( ( ros::Time::now().toSec() - left_buttondown_time.toSec() ) < 1.0 ) {
00835         geometry_msgs::PointStamped screen_msg;
00836         screen_msg.point.x = window_selection_.x;
00837         screen_msg.point.y = window_selection_.y;
00838         screen_msg.point.z = 0;
00839         screen_msg.header.stamp = ros::Time::now();
00840         ROS_INFO("Publish screen point %s (%d %d)", iv->point_pub_.getTopic().c_str(), x, y);
00841         iv->point_pub_.publish(screen_msg);
00842       } else {
00843         geometry_msgs::PolygonStamped screen_msg;
00844         screen_msg.polygon.points.resize(2);
00845         screen_msg.polygon.points[0].x = window_selection_.x;
00846         screen_msg.polygon.points[0].y = window_selection_.y;
00847         screen_msg.polygon.points[1].x = window_selection_.x + window_selection_.width;
00848         screen_msg.polygon.points[1].y = window_selection_.y + window_selection_.height;
00849         screen_msg.header.stamp = ros::Time::now();
00850         ROS_INFO("Publish rectangle point %s (%d %d %d %d)", iv->rectangle_pub_.getTopic().c_str(), window_selection_.y, window_selection_.y, window_selection_.width, window_selection_.height);
00851         iv->rectangle_pub_.publish(screen_msg);
00852       }
00853       window_selection_.x = window_selection_.y =
00854         window_selection_.width = window_selection_.height = 0;
00855       left_buttondown_time.fromSec(0);
00856       break;
00857     case CV_EVENT_RBUTTONDOWN:
00858       boost::lock_guard<boost::mutex> guard(iv->image_mutex_);
00859       if (!iv->image_.empty()) {
00860         std::string filename = (iv->filename_format_ % iv->count_).str();
00861         cv::imwrite(filename.c_str(), iv->image_);
00862         ROS_INFO("Saved image %s", filename.c_str());
00863         iv->count_++;
00864       } else {
00865         ROS_WARN("Couldn't save image, no data!");
00866       }
00867       break;
00868     }
00869     return;
00870   }
00871 };
00872 
00873 int main(int argc, char **argv)
00874 {
00875   //ros::init(argc, argv, "image_view2", ros::init_options::AnonymousName);
00876   ros::init(argc, argv, "image_view2");
00877   ros::NodeHandle n;
00878 
00879   if ( n.resolveName("image") == "/image") {
00880     ROS_WARN("image_view: image has not been remapped! Typical command-line usage:\n"
00881              "\t$ ./image_view image:=<image topic> [transport]");
00882   }
00883 
00884   ImageView2 view(n, "raw");
00885 
00886   ros::spin();
00887 
00888   return 0;
00889 }
00890 
00891 CvRect ImageView2::window_selection_;
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


image_view2
Author(s): Kei Okada
autogenerated on Sat Mar 23 2013 15:19:51