00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <ros/ros.h>
00036 #include <nodelet/nodelet.h>
00037 #include <geometry_msgs/PolygonStamped.h>
00038 #include <jsk_pcl_ros/ColorHistogram.h>
00039 #include <sensor_msgs/image_encodings.h>
00040 #include <cv_bridge/cv_bridge.h>
00041 #include <image_transport/image_transport.h>
00042 #include <image_transport/subscriber_filter.h>
00043 #include <message_filters/subscriber.h>
00044 #include <message_filters/synchronizer.h>
00045 #include <message_filters/sync_policies/exact_time.h>
00046 #include <message_filters/sync_policies/approximate_time.h>
00047 #include <dynamic_reconfigure/server.h>
00048 #include <jsk_perception/ColorHistogramConfig.h>
00049 #include "opencv2/highgui/highgui.hpp"
00050 #include "opencv2/imgproc/imgproc.hpp"
00051
00052 namespace jsk_perception
00053 {
00054 class ColorHistogram: public nodelet::Nodelet
00055 {
00056 public:
00057 typedef message_filters::sync_policies::ApproximateTime< sensor_msgs::Image,
00058 geometry_msgs::PolygonStamped > SyncPolicy;
00059 typedef jsk_perception::ColorHistogramConfig Config;
00060 protected:
00061 boost::shared_ptr<message_filters::Synchronizer<SyncPolicy> > sync_;
00062 boost::shared_ptr<dynamic_reconfigure::Server<Config> > srv_;
00063 image_transport::SubscriberFilter image_sub_;
00064 message_filters::Subscriber<geometry_msgs::PolygonStamped> rectangle_sub_;
00065 ros::NodeHandle nh_, pnh_;
00066 boost::shared_ptr<image_transport::ImageTransport> it_;
00067 ros::Publisher b_hist_pub_, r_hist_pub_, g_hist_pub_,
00068 h_hist_pub_, s_hist_pub_, i_hist_pub_;
00069 int b_hist_size_, r_hist_size_, g_hist_size_,
00070 h_hist_size_, s_hist_size_, i_hist_size_;
00071 boost::mutex mutex_;
00072
00073 void configCallback(Config &new_config, uint32_t level)
00074 {
00075 boost::mutex::scoped_lock lock(mutex_);
00076 b_hist_size_ = new_config.blue_histogram_bin;
00077 g_hist_size_ = new_config.green_histogram_bin;
00078 r_hist_size_ = new_config.red_histogram_bin;
00079 h_hist_size_ = new_config.hue_histogram_bin;
00080 s_hist_size_ = new_config.saturation_histogram_bin;
00081 i_hist_size_ = new_config.intensity_histogram_bin;
00082 }
00083 virtual void onInit()
00084 {
00085 nh_ = ros::NodeHandle(getNodeHandle(), "image");
00086 pnh_ = ros::NodeHandle("~");
00087 b_hist_size_ = r_hist_size_ = g_hist_size_ = h_hist_size_ = s_hist_size_ = i_hist_size_ = 512;
00088 b_hist_pub_ = nh_.advertise<jsk_pcl_ros::ColorHistogram>("blue_histogram", 1);
00089 g_hist_pub_ = nh_.advertise<jsk_pcl_ros::ColorHistogram>("green_histogram", 1);
00090 r_hist_pub_ = nh_.advertise<jsk_pcl_ros::ColorHistogram>("red_histogram", 1);
00091 h_hist_pub_ = nh_.advertise<jsk_pcl_ros::ColorHistogram>("hue_histogram", 1);
00092 s_hist_pub_ = nh_.advertise<jsk_pcl_ros::ColorHistogram>("saturation_histogram", 1);
00093 i_hist_pub_ = nh_.advertise<jsk_pcl_ros::ColorHistogram>("intensity_histogram", 1);
00094 srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> > (pnh_);
00095 dynamic_reconfigure::Server<Config>::CallbackType f =
00096 boost::bind (&ColorHistogram::configCallback, this, _1, _2);
00097 srv_->setCallback (f);
00098
00099 it_.reset(new image_transport::ImageTransport(nh_));
00100 image_sub_.subscribe(*it_, "", 1);
00101 rectangle_sub_.subscribe(nh_, "screenrectangle", 1);
00102 sync_ = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(10);
00103 sync_->connectInput(image_sub_, rectangle_sub_);
00104 sync_->registerCallback(boost::bind(&ColorHistogram::extract, this, _1, _2));
00105 }
00106
00107 virtual void convertHistogramToMsg(const cv::Mat& hist,
00108 int size,
00109 jsk_pcl_ros::ColorHistogram& msg)
00110 {
00111 msg.histogram.clear();
00112 for (int i = 0; i < size; i++) {
00113 float val = hist.at<float>(0, i);
00114 msg.histogram.push_back(val);
00115 }
00116 }
00117
00118 virtual void processBGR(const cv::Mat& bgr_image, const std_msgs::Header& header)
00119 {
00120
00121 float range[] = { 0, 256 } ;
00122 const float* histRange = { range };
00123 cv::MatND b_hist, g_hist, r_hist;
00124 bool uniform = true; bool accumulate = false;
00125 std::vector<cv::Mat> bgr_planes;
00126 split( bgr_image, bgr_planes );
00127
00128 cv::calcHist( &bgr_planes[0], 1, 0, cv::Mat(), b_hist, 1, &b_hist_size_, &histRange, uniform, accumulate );
00129 cv::calcHist( &bgr_planes[1], 1, 0, cv::Mat(), g_hist, 1, &g_hist_size_, &histRange, uniform, accumulate );
00130 cv::calcHist( &bgr_planes[2], 1, 0, cv::Mat(), r_hist, 1, &r_hist_size_, &histRange, uniform, accumulate );
00131
00132 jsk_pcl_ros::ColorHistogram b_histogram;
00133 b_histogram.header = header;
00134 convertHistogramToMsg(b_hist, b_hist_size_, b_histogram);
00135 b_hist_pub_.publish(b_histogram);
00136
00137 jsk_pcl_ros::ColorHistogram g_histogram;
00138 g_histogram.header = header;
00139 convertHistogramToMsg(g_hist, g_hist_size_, g_histogram);
00140 g_hist_pub_.publish(g_histogram);
00141
00142 jsk_pcl_ros::ColorHistogram r_histogram;
00143 r_histogram.header = header;
00144 convertHistogramToMsg(r_hist, r_hist_size_, r_histogram);
00145 r_hist_pub_.publish(r_histogram);
00146
00147 }
00148
00149 virtual void processHSI(const cv::Mat& bgr_image, const std_msgs::Header& header)
00150 {
00151 cv::Mat hsi_image;
00152 cv::cvtColor(bgr_image, hsi_image, CV_BGR2HSV);
00153
00154 float range[] = { 0, 256 } ;
00155 const float* histRange = { range };
00156 float h_range[] = { 0, 180 } ;
00157 const float* h_histRange = { h_range };
00158 cv::MatND h_hist, s_hist, i_hist;
00159 bool uniform = true; bool accumulate = false;
00160 std::vector<cv::Mat> hsi_planes;
00161 split( hsi_image, hsi_planes );
00162
00163 cv::calcHist( &hsi_planes[0], 1, 0, cv::Mat(), h_hist, 1, &h_hist_size_, &h_histRange, uniform, accumulate );
00164 cv::calcHist( &hsi_planes[1], 1, 0, cv::Mat(), s_hist, 1, &s_hist_size_, &histRange, uniform, accumulate );
00165 cv::calcHist( &hsi_planes[2], 1, 0, cv::Mat(), i_hist, 1, &i_hist_size_, &histRange, uniform, accumulate );
00166
00167 jsk_pcl_ros::ColorHistogram h_histogram;
00168 h_histogram.header = header;
00169 convertHistogramToMsg(h_hist, h_hist_size_, h_histogram);
00170 h_hist_pub_.publish(h_histogram);
00171
00172 jsk_pcl_ros::ColorHistogram s_histogram;
00173 s_histogram.header = header;
00174 convertHistogramToMsg(s_hist, s_hist_size_, s_histogram);
00175 s_hist_pub_.publish(s_histogram);
00176
00177 jsk_pcl_ros::ColorHistogram i_histogram;
00178 i_histogram.header = header;
00179 convertHistogramToMsg(i_hist, i_hist_size_, i_histogram);
00180 i_hist_pub_.publish(i_histogram);
00181
00182 }
00183
00184 virtual void extract(const sensor_msgs::Image::ConstPtr& image,
00185 const geometry_msgs::PolygonStamped::ConstPtr& rectangle)
00186 {
00187 boost::mutex::scoped_lock lock(mutex_);
00188 try
00189 {
00190 cv_bridge::CvImagePtr cv_ptr;
00191 cv_ptr = cv_bridge::toCvCopy(image, sensor_msgs::image_encodings::BGR8);
00192
00193 int larger_x_index = rectangle->polygon.points[0].x > rectangle->polygon.points[1].x? 0: 1;
00194 int larger_y_index = rectangle->polygon.points[0].y > rectangle->polygon.points[1].y? 0: 1;
00195 int smaller_x_index = rectangle->polygon.points[0].x < rectangle->polygon.points[1].x? 0: 1;
00196 int smaller_y_index = rectangle->polygon.points[0].y < rectangle->polygon.points[1].y? 0: 1;
00197 cv::Rect roi(rectangle->polygon.points[smaller_x_index].x,
00198 rectangle->polygon.points[smaller_y_index].y,
00199 rectangle->polygon.points[larger_x_index].x - rectangle->polygon.points[smaller_x_index].x,
00200 rectangle->polygon.points[larger_y_index].y - rectangle->polygon.points[smaller_y_index].y);
00201 cv::Mat bgr_image = cv_ptr->image(roi);
00202 processBGR(bgr_image, image->header);
00203 processHSI(bgr_image, image->header);
00204 }
00205 catch (cv_bridge::Exception& e)
00206 {
00207 NODELET_ERROR("cv_bridge exception: %s", e.what());
00208 return;
00209 }
00210 }
00211 private:
00212
00213 };
00214 }
00215
00216 #include <pluginlib/class_list_macros.h>
00217 typedef jsk_perception::ColorHistogram ColorHistogram;
00218 PLUGINLIB_DECLARE_CLASS (jsk_perception, ColorHistogram, ColorHistogram, nodelet::Nodelet);