hough_lines.cpp
Go to the documentation of this file.
00001 #include <ros/ros.h>
00002 #include <jsk_perception/HoughLinesConfig.h>
00003 #include <jsk_perception/LineArray.h>
00004 #include <image_transport/image_transport.h>
00005 #include <cv_bridge/cv_bridge.h>
00006 #include <sensor_msgs/image_encodings.h>
00007 #include <opencv2/imgproc/imgproc.hpp>
00008 #include "opencv2/highgui/highgui.hpp"
00009 
00010 #include <dynamic_reconfigure/server.h>
00011 
00012 namespace enc = sensor_msgs::image_encodings;
00013 
00014 class HoughLines
00015 {
00016     jsk_perception::HoughLinesConfig config_;
00017     dynamic_reconfigure::Server<jsk_perception::HoughLinesConfig> srv;
00018 
00019     image_transport::Publisher img_pub_;
00020     image_transport::Subscriber img_sub_;
00021     ros::Publisher out_pub_;
00022 
00023     image_transport::ImageTransport it_;
00024     ros::NodeHandle nh_;
00025     int subscriber_count_;
00026 
00027     double _rho;
00028     double _theta;
00029     int    _threshold;
00030     double _minLineLength;
00031     double _maxLineGap;
00032 
00033     void reconfigureCallback(jsk_perception::HoughLinesConfig &new_config, uint32_t level)
00034     {
00035         config_ = new_config;
00036         _rho            = config_.rho;
00037         _theta          = config_.theta;
00038         _threshold       = config_.threshold;
00039         _minLineLength  = config_.minLineLength;
00040         _maxLineGap     = config_.maxLineGap;
00041         if (subscriber_count_)
00042             { // @todo Could do this without an interruption at some point.
00043                 unsubscribe();
00044                 subscribe();
00045             }
00046     }
00047 
00048     void imageCallback(const sensor_msgs::ImageConstPtr& msg)
00049     {
00050         do_work(msg, msg->header.frame_id);
00051     }
00052 
00053     void do_work(const sensor_msgs::ImageConstPtr& msg, const std::string input_frame_from_msg)
00054     {
00055         // Transform the image.
00056         try
00057             {
00058                 // Convert the image into something opencv can handle.
00059                 cv::Mat in_image = cv_bridge::toCvShare(msg, msg->encoding)->image;
00060 
00061                 if (msg->encoding != enc::MONO8) {
00062                     ROS_ERROR("Hough Lines assume monochrome image for input");
00063                     return;
00064                 }
00065 
00066                 cv::Mat out_image;
00067                 cvtColor(in_image, out_image, CV_GRAY2BGR);
00068 
00069                 // Do the work
00070                 ROS_INFO_STREAM("Hough Lines : rho:" << _rho << ", tehta:" << _theta << ", threshold:" <<  _threshold << ", minLineLength:" <<  _minLineLength << ", maxLineGap" <<  _maxLineGap);
00071 #if 1
00072                 std::vector<cv::Vec4i> lines;
00073                 cv::HoughLinesP( in_image, lines, _rho, _theta*CV_PI/180 , _threshold, _minLineLength, _maxLineGap );
00074                 jsk_perception::LineArray out_lines;
00075                 out_lines.header = msg->header;
00076                 out_lines.lines.resize(lines.size());
00077                 for( size_t i = 0; i < lines.size(); i++ )
00078                     {
00079                         out_lines.lines[i].x1 = lines[i][0];
00080                         out_lines.lines[i].y1 = lines[i][1];
00081                         out_lines.lines[i].x2 = lines[i][2];
00082                         out_lines.lines[i].y2 = lines[i][3];
00083                         cv::line( out_image, cv::Point(lines[i][0], lines[i][1]),
00084                                   cv::Point(lines[i][2], lines[i][3]), cv::Scalar(255,0,0), 3, 8 );
00085                     }
00086 #else
00087                 std::vector<cv::Vec2f> lines;
00088                 cv::HoughLines( in_image, lines, _rho, _theta, _threshold*CV_PI/180, _minLineLength, _maxLineGap );
00089                 jsk_perception::LineArray out_lines;
00090                 out_lines.header = msg->header;
00091                 out_lines.lines.resize(lines.size());
00092                 for( size_t i = 0; i < lines.size(); i++ )
00093                     {
00094                         float rho = lines[i][0];
00095                         float theta = lines[i][1];
00096                         double a = cos(theta), b = sin(theta);
00097                         double x0 = a*rho, y0 = b*rho;
00098                         cv::Point pt1(cvRound(x0 + 1000*(-b)),
00099                                       cvRound(y0 + 1000*(a)));
00100                         cv::Point pt2(cvRound(x0 - 1000*(-b)),
00101                                       cvRound(y0 - 1000*(a)));
00102                         cv::line( out_image, pt1, pt2, cv::Scalar(0,0,255), 3, 8 );
00103                     }
00104 #endif
00105 
00106                 // Publish the image.
00107                 sensor_msgs::Image::Ptr out_img = cv_bridge::CvImage(msg->header, enc::RGB8, out_image).toImageMsg();
00108                 out_pub_.publish(out_lines);
00109                 img_pub_.publish(out_img);
00110             }
00111         catch (cv::Exception &e)
00112             {
00113                 ROS_ERROR("Image processing error: %s %s %s %i", e.err.c_str(), e.func.c_str(), e.file.c_str(), e.line);
00114             }
00115     }
00116 
00117     void subscribe()
00118     {
00119         ROS_DEBUG("Subscribing to image topic.");
00120         img_sub_ = it_.subscribe("image", 3, &HoughLines::imageCallback, this);
00121     }
00122 
00123     void unsubscribe()
00124     {
00125         ROS_DEBUG("Unsubscribing from image topic.");
00126         img_sub_.shutdown();
00127     }
00128 
00129     void connectCb(const image_transport::SingleSubscriberPublisher& ssp)
00130     {
00131         if (subscriber_count_++ == 0) {
00132             subscribe();
00133         }
00134     }
00135 
00136     void disconnectCb(const image_transport::SingleSubscriberPublisher&)
00137     {
00138         subscriber_count_--;
00139         if (subscriber_count_ == 0) {
00140             unsubscribe();
00141         }
00142     }
00143 
00144 public:
00145     HoughLines(ros::NodeHandle nh = ros::NodeHandle()) : it_(nh), nh_(nh), subscriber_count_(0)
00146     {
00147         image_transport::SubscriberStatusCallback connect_cb    = boost::bind(&HoughLines::connectCb, this, _1);
00148         image_transport::SubscriberStatusCallback disconnect_cb = boost::bind(&HoughLines::disconnectCb, this, _1);
00149         img_pub_ = image_transport::ImageTransport(ros::NodeHandle(nh_, "hough")).advertise("image", 1, connect_cb, disconnect_cb);
00150 
00151         out_pub_ = nh.advertise<jsk_perception::LineArray>(nh_.resolveName("lines"), 1);
00152 
00153 
00154         dynamic_reconfigure::Server<jsk_perception::HoughLinesConfig>::CallbackType f =
00155             boost::bind(&HoughLines::reconfigureCallback, this, _1, _2);
00156         srv.setCallback(f);
00157     }
00158 };
00159 
00160 int main(int argc, char **argv)
00161 {
00162     ros::init(argc, argv, "hough_lines", ros::init_options::AnonymousName);
00163 
00164     HoughLines hl;
00165     ros::spin();
00166 }


jsk_perception
Author(s): Manabu Saito
autogenerated on Mon Oct 6 2014 01:16:59