color_histogram.cpp
Go to the documentation of this file.
1 // -*- mode: C++ -*-
2 /*********************************************************************
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2014, JSK Lab
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/o2r other materials provided
17  * with the distribution.
18  * * Neither the name of the JSK Lab nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *********************************************************************/
35 
38 
39 namespace jsk_perception
40 {
41  void ColorHistogram::configCallback(Config &new_config, uint32_t level)
42  {
43  boost::mutex::scoped_lock lock(mutex_);
44  b_hist_size_ = new_config.blue_histogram_bin;
45  g_hist_size_ = new_config.green_histogram_bin;
46  r_hist_size_ = new_config.red_histogram_bin;
47  h_hist_size_ = new_config.hue_histogram_bin;
48  s_hist_size_ = new_config.saturation_histogram_bin;
49  i_hist_size_ = new_config.intensity_histogram_bin;
51  }
52 
54  {
55  DiagnosticNodelet::onInit();
56  nh_ = ros::NodeHandle(getNodeHandle(), "image");
57  pnh_->param("use_mask", use_mask_, false);
60  b_hist_pub_ = advertise<jsk_recognition_msgs::ColorHistogram>(
61  *pnh_, "blue_histogram", 1);
62  g_hist_pub_ = advertise<jsk_recognition_msgs::ColorHistogram>(
63  *pnh_, "green_histogram", 1);
64  r_hist_pub_ = advertise<jsk_recognition_msgs::ColorHistogram>(
65  *pnh_, "red_histogram", 1);
66  h_hist_pub_ = advertise<jsk_recognition_msgs::ColorHistogram>(
67  *pnh_, "hue_histogram", 1);
68  s_hist_pub_ = advertise<jsk_recognition_msgs::ColorHistogram>(
69  *pnh_, "saturation_histogram", 1);
70  i_hist_pub_ = advertise<jsk_recognition_msgs::ColorHistogram>(
71  *pnh_, "intensity_histogram", 1);
72  image_pub_ = advertise<sensor_msgs::Image>(
73  *pnh_, "input_image", 1);
74 
75  srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> > (*pnh_);
76  dynamic_reconfigure::Server<Config>::CallbackType f =
77  boost::bind (&ColorHistogram::configCallback, this, _1, _2);
78  srv_->setCallback (f);
79  }
80 
82  {
83  ros::V_string names;
84  if (!use_mask_) {
86  image_sub_.subscribe(*it_, "", 1);
87  rectangle_sub_.subscribe(nh_, "screenrectangle", 1);
88  names.push_back("screenrectangle");
89  sync_
90  = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(10);
91  sync_->connectInput(image_sub_, rectangle_sub_);
92  sync_->registerCallback(boost::bind(
93  &ColorHistogram::extract, this, _1, _2));
94  }
95  else {
97  image_sub_.subscribe(*it_, "", 1);
98  image_mask_sub_.subscribe(*it_, "mask", 1);
99  names.push_back("mask");
100  mask_sync_
101  = boost::make_shared<message_filters::Synchronizer<
102  MaskSyncPolicy> >(100);
103  mask_sync_->connectInput(image_sub_, image_mask_sub_);
104  mask_sync_->registerCallback(
105  boost::bind(
106  &ColorHistogram::extractMask, this, _1, _2));
107  }
109  }
110 
112  {
113  if (!use_mask_) {
116  }
117  else {
120  }
121  }
122 
123  void ColorHistogram::convertHistogramToMsg(const cv::Mat& hist,
124  int size,
125  jsk_recognition_msgs::ColorHistogram& msg)
126  {
127  msg.histogram.clear();
128  for (int i = 0; i < size; i++) {
129  float val = hist.at<float>(0, i);
130  msg.histogram.push_back(val);
131  }
132  }
133 
134  void ColorHistogram::processBGR(const cv::Mat& bgr_image,
135  const cv::Mat& mask,
136  const std_msgs::Header& header)
137  {
138  float range[] = { 0, 256 } ;
139  const float* histRange = { range };
140  cv::MatND b_hist, g_hist, r_hist;
141  bool uniform = true; bool accumulate = false;
142  std::vector<cv::Mat> bgr_planes;
143  split(bgr_image, bgr_planes);
144 
145  cv::calcHist(&bgr_planes[0], 1, 0, mask, b_hist, 1, &b_hist_size_,
146  &histRange, uniform, accumulate);
147  cv::calcHist(&bgr_planes[1], 1, 0, mask, g_hist, 1, &g_hist_size_,
148  &histRange, uniform, accumulate);
149  cv::calcHist(&bgr_planes[2], 1, 0, mask, r_hist, 1, &r_hist_size_,
150  &histRange, uniform, accumulate);
151 
152  jsk_recognition_msgs::ColorHistogram b_histogram;
153  b_histogram.header = header;
154  convertHistogramToMsg(b_hist, b_hist_size_, b_histogram);
155  b_hist_pub_.publish(b_histogram);
156 
157  jsk_recognition_msgs::ColorHistogram g_histogram;
158  g_histogram.header = header;
159  convertHistogramToMsg(g_hist, g_hist_size_, g_histogram);
160  g_hist_pub_.publish(g_histogram);
161 
162  jsk_recognition_msgs::ColorHistogram r_histogram;
163  r_histogram.header = header;
164  convertHistogramToMsg(r_hist, r_hist_size_, r_histogram);
165  r_hist_pub_.publish(r_histogram);
166  }
167 
168  void ColorHistogram::processBGR(const cv::Mat& bgr_image,
169  const std_msgs::Header& header)
170  {
171  processBGR(bgr_image, cv::Mat(), header);
172  }
173 
174  void ColorHistogram::processHSI(const cv::Mat& bgr_image,
175  const std_msgs::Header& header)
176  {
177  processHSI(bgr_image, cv::Mat(), header);
178  }
179 
180  void ColorHistogram::processHSI(const cv::Mat& bgr_image,
181  const cv::Mat& mask,
182  const std_msgs::Header& header)
183  {
184  cv::Mat hsi_image;
185  cv::cvtColor(bgr_image, hsi_image, CV_BGR2HSV);
186 
187  float range[] = { 0, 256 } ;
188  const float* histRange = { range };
189  float h_range[] = { 0, 180 } ;
190  const float* h_histRange = { h_range };
191  cv::MatND h_hist, s_hist, i_hist;
192  bool uniform = true; bool accumulate = false;
193  std::vector<cv::Mat> hsi_planes;
194  split(hsi_image, hsi_planes);
195 
196  cv::calcHist(&hsi_planes[0], 1, 0, mask, h_hist, 1, &h_hist_size_,
197  &h_histRange, uniform, accumulate);
198  cv::calcHist(&hsi_planes[1], 1, 0, mask, s_hist, 1, &s_hist_size_,
199  &histRange, uniform, accumulate);
200  cv::calcHist(&hsi_planes[2], 1, 0, mask, i_hist, 1, &i_hist_size_,
201  &histRange, uniform, accumulate);
202 
203  jsk_recognition_msgs::ColorHistogram h_histogram;
204  h_histogram.header = header;
205  convertHistogramToMsg(h_hist, h_hist_size_, h_histogram);
206  h_hist_pub_.publish(h_histogram);
207 
208  jsk_recognition_msgs::ColorHistogram s_histogram;
209  s_histogram.header = header;
210  convertHistogramToMsg(s_hist, s_hist_size_, s_histogram);
211  s_hist_pub_.publish(s_histogram);
212 
213  jsk_recognition_msgs::ColorHistogram i_histogram;
214  i_histogram.header = header;
215  convertHistogramToMsg(i_hist, i_hist_size_, i_histogram);
216  i_hist_pub_.publish(i_histogram);
217 
218  }
219 
221  const sensor_msgs::Image::ConstPtr& image,
222  const geometry_msgs::PolygonStamped::ConstPtr& rectangle)
223  {
224  vital_checker_->poke();
225  boost::mutex::scoped_lock lock(mutex_);
226  try
227  {
228  cv_bridge::CvImagePtr cv_ptr;
230  geometry_msgs::Point32 point0 = rectangle->polygon.points[0];
231  geometry_msgs::Point32 point1 = rectangle->polygon.points[1];
232  int min_x = std::max(0.0f, std::min(point0.x, point1.x));
233  int min_y = std::max(0.0f, std::min(point0.y, point1.y));
234  int max_x = std::min(std::max(point0.x, point1.x), (float)image->width);
235  int max_y = std::min(std::max(point0.y, point1.y), (float)image->height);
236  cv::Rect roi(min_x, min_y, max_x - min_x, max_y - min_y);
237  cv::Mat bgr_image, roi_image;
238  roi_image = cv_ptr->image(roi);
239  if (image->encoding == sensor_msgs::image_encodings::RGB8) {
240  cv::cvtColor(roi_image, bgr_image, CV_RGB2BGR);
241  }
242  else {
243  roi_image.copyTo(bgr_image);
244  }
246  image->header,
248  bgr_image).toImageMsg());
249  processBGR(bgr_image, image->header);
250  processHSI(bgr_image, image->header);
251  }
252  catch (cv_bridge::Exception& e)
253  {
254  NODELET_ERROR("cv_bridge exception: %s", e.what());
255  return;
256  }
257  }
258 
260  const sensor_msgs::Image::ConstPtr& image,
261  const sensor_msgs::Image::ConstPtr& mask_image)
262  {
263  try {
264  cv_bridge::CvImagePtr cv_ptr
266  cv_bridge::CvImagePtr mask_ptr
268  cv::Mat bgr_image = cv_ptr->image;
269  cv::Mat mask_image = mask_ptr->image;
270  cv::Mat masked_image;
271  bgr_image.copyTo(masked_image, mask_image);
272  sensor_msgs::Image::Ptr ros_masked_image
273  = cv_bridge::CvImage(image->header,
275  masked_image).toImageMsg();
276  image_pub_.publish(ros_masked_image);
277 
278  processBGR(bgr_image, mask_image, image->header);
279  processHSI(bgr_image, mask_image, image->header);
280 
281  }
282  catch (cv_bridge::Exception& e)
283  {
284  NODELET_ERROR("cv_bridge exception: %s", e.what());
285  return;
286  }
287 
288  }
289 }
290 
image_transport::SubscriberFilter image_sub_
f
#define NODELET_ERROR(...)
void publish(const boost::shared_ptr< M > &message) const
boost::shared_ptr< message_filters::Synchronizer< MaskSyncPolicy > > mask_sync_
boost::shared_ptr< message_filters::Synchronizer< SyncPolicy > > sync_
message_filters::Subscriber< geometry_msgs::PolygonStamped > rectangle_sub_
virtual void convertHistogramToMsg(const cv::Mat &hist, int size, jsk_recognition_msgs::ColorHistogram &msg)
std::vector< std::string > V_string
virtual void processBGR(const cv::Mat &bgr_image, const std_msgs::Header &header)
boost::shared_ptr< ros::NodeHandle > pnh_
bool warnNoRemap(const std::vector< std::string > names)
CvImagePtr toCvCopy(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
ros::NodeHandle & getNodeHandle() const
PLUGINLIB_EXPORT_CLASS(jsk_perception::ColorHistogram, nodelet::Nodelet)
virtual void extract(const sensor_msgs::Image::ConstPtr &image, const geometry_msgs::PolygonStamped::ConstPtr &rectangle)
void subscribe(ImageTransport &it, const std::string &base_topic, uint32_t queue_size, const TransportHints &transport_hints=TransportHints())
jsk_perception::ColorHistogramConfig Config
jsk_topic_tools::VitalChecker::Ptr vital_checker_
mutex_t * lock
void subscribe(ros::NodeHandle &nh, const std::string &topic, uint32_t queue_size, const ros::TransportHints &transport_hints=ros::TransportHints(), ros::CallbackQueueInterface *callback_queue=0)
image_transport::SubscriberFilter image_mask_sub_
virtual void processHSI(const cv::Mat &bgr_image, const std_msgs::Header &header)
boost::shared_ptr< dynamic_reconfigure::Server< Config > > srv_
virtual void extractMask(const sensor_msgs::Image::ConstPtr &image, const sensor_msgs::Image::ConstPtr &mask_image)
boost::shared_ptr< image_transport::ImageTransport > it_
void configCallback(Config &new_config, uint32_t level)
sensor_msgs::ImagePtr toImageMsg() const


jsk_perception
Author(s): Manabu Saito, Ryohei Ueda
autogenerated on Mon May 3 2021 03:03:27