color_histogram.cpp
Go to the documentation of this file.
00001 // -*- mode: C++ -*-
00002 /*********************************************************************
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2014, JSK Lab
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/o2r other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of the Willow Garage nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
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);


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