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/or 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 
37 #include <jsk_topic_tools/log_utils.h>
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;
50  onInitPostProcess();
51  }
52 
54  // message_filters::Synchronizer needs to be called reset
55  // before message_filters::Subscriber is freed.
56  // Calling reset fixes the following error on shutdown of the nodelet:
57  // terminate called after throwing an instance of
58  // 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::lock_error> >'
59  // what(): boost: mutex lock failed in pthread_mutex_lock: Invalid argument
60  // Also see https://github.com/ros/ros_comm/issues/720 .
61  sync_.reset();
62  mask_sync_.reset();
63  }
64 
66  {
67  DiagnosticNodelet::onInit();
68  nh_ = ros::NodeHandle(getNodeHandle(), "image");
69  pnh_->param("use_mask", use_mask_, false);
72  b_hist_pub_ = advertise<jsk_recognition_msgs::ColorHistogram>(
73  *pnh_, "blue_histogram", 1);
74  g_hist_pub_ = advertise<jsk_recognition_msgs::ColorHistogram>(
75  *pnh_, "green_histogram", 1);
76  r_hist_pub_ = advertise<jsk_recognition_msgs::ColorHistogram>(
77  *pnh_, "red_histogram", 1);
78  h_hist_pub_ = advertise<jsk_recognition_msgs::ColorHistogram>(
79  *pnh_, "hue_histogram", 1);
80  s_hist_pub_ = advertise<jsk_recognition_msgs::ColorHistogram>(
81  *pnh_, "saturation_histogram", 1);
82  i_hist_pub_ = advertise<jsk_recognition_msgs::ColorHistogram>(
83  *pnh_, "intensity_histogram", 1);
84  image_pub_ = advertise<sensor_msgs::Image>(
85  *pnh_, "input_image", 1);
86 
87  srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> > (*pnh_);
88  dynamic_reconfigure::Server<Config>::CallbackType f =
89  boost::bind (&ColorHistogram::configCallback, this, _1, _2);
90  srv_->setCallback (f);
91  }
92 
94  {
95  ros::V_string names;
96  if (!use_mask_) {
98  image_sub_.subscribe(*it_, "", 1);
99  rectangle_sub_.subscribe(nh_, "screenrectangle", 1);
100  names.push_back("screenrectangle");
101  sync_
102  = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(10);
103  sync_->connectInput(image_sub_, rectangle_sub_);
104  sync_->registerCallback(boost::bind(
105  &ColorHistogram::extract, this, _1, _2));
106  }
107  else {
109  image_sub_.subscribe(*it_, "", 1);
110  image_mask_sub_.subscribe(*it_, "mask", 1);
111  names.push_back("mask");
112  mask_sync_
113  = boost::make_shared<message_filters::Synchronizer<
114  MaskSyncPolicy> >(100);
115  mask_sync_->connectInput(image_sub_, image_mask_sub_);
116  mask_sync_->registerCallback(
117  boost::bind(
118  &ColorHistogram::extractMask, this, _1, _2));
119  }
120  jsk_topic_tools::warnNoRemap(names);
121  }
122 
124  {
125  if (!use_mask_) {
128  }
129  else {
132  }
133  }
134 
135  void ColorHistogram::convertHistogramToMsg(const cv::Mat& hist,
136  int size,
137  jsk_recognition_msgs::ColorHistogram& msg)
138  {
139  msg.histogram.clear();
140  for (int i = 0; i < size; i++) {
141  float val = hist.at<float>(0, i);
142  msg.histogram.push_back(val);
143  }
144  }
145 
146  void ColorHistogram::processBGR(const cv::Mat& bgr_image,
147  const cv::Mat& mask,
148  const std_msgs::Header& header)
149  {
150  float range[] = { 0, 256 } ;
151  const float* histRange = { range };
152  cv::MatND b_hist, g_hist, r_hist;
153  bool uniform = true; bool accumulate = false;
154  std::vector<cv::Mat> bgr_planes;
155  split(bgr_image, bgr_planes);
156 
157  cv::calcHist(&bgr_planes[0], 1, 0, mask, b_hist, 1, &b_hist_size_,
158  &histRange, uniform, accumulate);
159  cv::calcHist(&bgr_planes[1], 1, 0, mask, g_hist, 1, &g_hist_size_,
160  &histRange, uniform, accumulate);
161  cv::calcHist(&bgr_planes[2], 1, 0, mask, r_hist, 1, &r_hist_size_,
162  &histRange, uniform, accumulate);
163 
164  jsk_recognition_msgs::ColorHistogram b_histogram;
165  b_histogram.header = header;
166  convertHistogramToMsg(b_hist, b_hist_size_, b_histogram);
167  b_hist_pub_.publish(b_histogram);
168 
169  jsk_recognition_msgs::ColorHistogram g_histogram;
170  g_histogram.header = header;
171  convertHistogramToMsg(g_hist, g_hist_size_, g_histogram);
172  g_hist_pub_.publish(g_histogram);
173 
174  jsk_recognition_msgs::ColorHistogram r_histogram;
175  r_histogram.header = header;
176  convertHistogramToMsg(r_hist, r_hist_size_, r_histogram);
177  r_hist_pub_.publish(r_histogram);
178  }
179 
180  void ColorHistogram::processBGR(const cv::Mat& bgr_image,
181  const std_msgs::Header& header)
182  {
183  processBGR(bgr_image, cv::Mat(), header);
184  }
185 
186  void ColorHistogram::processHSI(const cv::Mat& bgr_image,
187  const std_msgs::Header& header)
188  {
189  processHSI(bgr_image, cv::Mat(), header);
190  }
191 
192  void ColorHistogram::processHSI(const cv::Mat& bgr_image,
193  const cv::Mat& mask,
194  const std_msgs::Header& header)
195  {
196  cv::Mat hsi_image;
197  cv::cvtColor(bgr_image, hsi_image, CV_BGR2HSV);
198 
199  float range[] = { 0, 256 } ;
200  const float* histRange = { range };
201  float h_range[] = { 0, 180 } ;
202  const float* h_histRange = { h_range };
203  cv::MatND h_hist, s_hist, i_hist;
204  bool uniform = true; bool accumulate = false;
205  std::vector<cv::Mat> hsi_planes;
206  split(hsi_image, hsi_planes);
207 
208  cv::calcHist(&hsi_planes[0], 1, 0, mask, h_hist, 1, &h_hist_size_,
209  &h_histRange, uniform, accumulate);
210  cv::calcHist(&hsi_planes[1], 1, 0, mask, s_hist, 1, &s_hist_size_,
211  &histRange, uniform, accumulate);
212  cv::calcHist(&hsi_planes[2], 1, 0, mask, i_hist, 1, &i_hist_size_,
213  &histRange, uniform, accumulate);
214 
215  jsk_recognition_msgs::ColorHistogram h_histogram;
216  h_histogram.header = header;
217  convertHistogramToMsg(h_hist, h_hist_size_, h_histogram);
218  h_hist_pub_.publish(h_histogram);
219 
220  jsk_recognition_msgs::ColorHistogram s_histogram;
221  s_histogram.header = header;
222  convertHistogramToMsg(s_hist, s_hist_size_, s_histogram);
223  s_hist_pub_.publish(s_histogram);
224 
225  jsk_recognition_msgs::ColorHistogram i_histogram;
226  i_histogram.header = header;
227  convertHistogramToMsg(i_hist, i_hist_size_, i_histogram);
228  i_hist_pub_.publish(i_histogram);
229 
230  }
231 
233  const sensor_msgs::Image::ConstPtr& image,
234  const geometry_msgs::PolygonStamped::ConstPtr& rectangle)
235  {
236  vital_checker_->poke();
237  boost::mutex::scoped_lock lock(mutex_);
238  try
239  {
240  cv_bridge::CvImagePtr cv_ptr;
242  geometry_msgs::Point32 point0 = rectangle->polygon.points[0];
243  geometry_msgs::Point32 point1 = rectangle->polygon.points[1];
244  int min_x = std::max(0.0f, std::min(point0.x, point1.x));
245  int min_y = std::max(0.0f, std::min(point0.y, point1.y));
246  int max_x = std::min(std::max(point0.x, point1.x), (float)image->width);
247  int max_y = std::min(std::max(point0.y, point1.y), (float)image->height);
248  cv::Rect roi(min_x, min_y, max_x - min_x, max_y - min_y);
249  cv::Mat bgr_image, roi_image;
250  roi_image = cv_ptr->image(roi);
251  if (image->encoding == sensor_msgs::image_encodings::RGB8) {
252  cv::cvtColor(roi_image, bgr_image, CV_RGB2BGR);
253  }
254  else {
255  roi_image.copyTo(bgr_image);
256  }
258  image->header,
260  bgr_image).toImageMsg());
261  processBGR(bgr_image, image->header);
262  processHSI(bgr_image, image->header);
263  }
265  {
266  NODELET_ERROR("cv_bridge exception: %s", e.what());
267  return;
268  }
269  }
270 
272  const sensor_msgs::Image::ConstPtr& image,
273  const sensor_msgs::Image::ConstPtr& mask_image)
274  {
275  try {
276  cv_bridge::CvImagePtr cv_ptr
278  cv_bridge::CvImagePtr mask_ptr
280  cv::Mat bgr_image = cv_ptr->image;
281  cv::Mat mask_image = mask_ptr->image;
282  cv::Mat masked_image;
283  bgr_image.copyTo(masked_image, mask_image);
284  sensor_msgs::Image::Ptr ros_masked_image
285  = cv_bridge::CvImage(image->header,
287  masked_image).toImageMsg();
288  image_pub_.publish(ros_masked_image);
289 
290  processBGR(bgr_image, mask_image, image->header);
291  processHSI(bgr_image, mask_image, image->header);
292 
293  }
294  catch (cv_bridge::Exception& e)
295  {
296  NODELET_ERROR("cv_bridge exception: %s", e.what());
297  return;
298  }
299 
300  }
301 }
302 
jsk_perception::ColorHistogram::s_hist_pub_
ros::Publisher s_hist_pub_
Definition: color_histogram.h:143
jsk_perception::ColorHistogram::r_hist_size_
int r_hist_size_
Definition: color_histogram.h:145
jsk_perception::ColorHistogram
Definition: color_histogram.h:88
jsk_perception::ColorHistogram::it_
boost::shared_ptr< image_transport::ImageTransport > it_
Definition: color_histogram.h:141
jsk_perception::ColorHistogram::g_hist_pub_
ros::Publisher g_hist_pub_
Definition: color_histogram.h:142
jsk_perception::ColorHistogram::~ColorHistogram
virtual ~ColorHistogram()
Definition: color_histogram.cpp:85
NODELET_ERROR
#define NODELET_ERROR(...)
jsk_perception::ColorHistogram::configCallback
void configCallback(Config &new_config, uint32_t level)
Definition: color_histogram.cpp:73
msg
msg
image_transport::ImageTransport
jsk_perception::ColorHistogram::unsubscribe
virtual void unsubscribe()
Definition: color_histogram.cpp:155
message_filters::Synchronizer
boost::shared_ptr< CvImage >
i
int i
cv_bridge::CvImage::toImageMsg
sensor_msgs::ImagePtr toImageMsg() const
jsk_perception::ColorHistogram::h_hist_pub_
ros::Publisher h_hist_pub_
Definition: color_histogram.h:143
jsk_perception::ColorHistogram::subscribe
virtual void subscribe()
Definition: color_histogram.cpp:125
_1
boost::arg< 1 > _1
image_transport::SubscriberFilter::subscribe
void subscribe(ImageTransport &it, const std::string &base_topic, uint32_t queue_size, const TransportHints &transport_hints=TransportHints())
jsk_perception::ColorHistogram::i_hist_size_
int i_hist_size_
Definition: color_histogram.h:146
jsk_perception::ColorHistogram::i_hist_pub_
ros::Publisher i_hist_pub_
Definition: color_histogram.h:143
cv_bridge::Exception
sensor_msgs::image_encodings::RGB8
const std::string RGB8
jsk_perception::ColorHistogram::image_mask_sub_
image_transport::SubscriberFilter image_mask_sub_
Definition: color_histogram.h:138
jsk_perception::ColorHistogram::processHSI
virtual void processHSI(const cv::Mat &bgr_image, const std_msgs::Header &header)
Definition: color_histogram.cpp:218
jsk_perception::ColorHistogram::convertHistogramToMsg
virtual void convertHistogramToMsg(const cv::Mat &hist, int size, jsk_recognition_msgs::ColorHistogram &msg)
Definition: color_histogram.cpp:167
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
message_filters::Subscriber::unsubscribe
void unsubscribe()
jsk_perception::ColorHistogram::MaskSyncPolicy
message_filters::sync_policies::ApproximateTime< sensor_msgs::Image, sensor_msgs::Image > MaskSyncPolicy
Definition: color_histogram.h:129
jsk_perception::ColorHistogram::image_pub_
ros::Publisher image_pub_
Definition: color_histogram.h:144
jsk_perception::ColorHistogram::extractMask
virtual void extractMask(const sensor_msgs::Image::ConstPtr &image, const sensor_msgs::Image::ConstPtr &mask_image)
Definition: color_histogram.cpp:303
class_list_macros.h
jsk_perception::ColorHistogram::h_hist_size_
int h_hist_size_
Definition: color_histogram.h:146
jsk_perception
Definition: add_mask_image.h:48
PLUGINLIB_EXPORT_CLASS
PLUGINLIB_EXPORT_CLASS(jsk_perception::ColorHistogram, nodelet::Nodelet)
jsk_perception::ColorHistogram::rectangle_sub_
message_filters::Subscriber< geometry_msgs::PolygonStamped > rectangle_sub_
Definition: color_histogram.h:139
cv_bridge::toCvCopy
CvImagePtr toCvCopy(const sensor_msgs::CompressedImage &source, const std::string &encoding=std::string())
jsk_perception::ColorHistogram::b_hist_size_
int b_hist_size_
Definition: color_histogram.h:145
jsk_perception::ColorHistogram::mask_sync_
boost::shared_ptr< message_filters::Synchronizer< MaskSyncPolicy > > mask_sync_
Definition: color_histogram.h:135
_2
boost::arg< 2 > _2
jsk_perception::ColorHistogram::processBGR
virtual void processBGR(const cv::Mat &bgr_image, const std_msgs::Header &header)
Definition: color_histogram.cpp:212
hist
hist
lock
mutex_t * lock
jsk_perception::ColorHistogram::mutex_
boost::mutex mutex_
Definition: color_histogram.h:148
jsk_perception::ColorHistogram::r_hist_pub_
ros::Publisher r_hist_pub_
Definition: color_histogram.h:142
message_filters::Subscriber::subscribe
void subscribe()
f
f
nodelet::Nodelet
jsk_perception::ColorHistogram::extract
virtual void extract(const sensor_msgs::Image::ConstPtr &image, const geometry_msgs::PolygonStamped::ConstPtr &rectangle)
Definition: color_histogram.cpp:264
jsk_perception::ColorHistogram::nh_
ros::NodeHandle nh_
Definition: color_histogram.h:140
sensor_msgs::image_encodings::MONO8
const std::string MONO8
jsk_perception::ColorHistogram::sync_
boost::shared_ptr< message_filters::Synchronizer< SyncPolicy > > sync_
Definition: color_histogram.h:134
cv_bridge::CvImage
jsk_perception::ColorHistogram::use_mask_
bool use_mask_
Definition: color_histogram.h:147
jsk_perception::ColorHistogram::s_hist_size_
int s_hist_size_
Definition: color_histogram.h:146
jsk_perception::ColorHistogram::onInit
virtual void onInit()
Definition: color_histogram.cpp:97
sensor_msgs::image_encodings::BGR8
const std::string BGR8
jsk_perception::ColorHistogram::b_hist_pub_
ros::Publisher b_hist_pub_
Definition: color_histogram.h:142
ros::V_string
std::vector< std::string > V_string
color_histogram.h
jsk_perception::ColorHistogram::image_sub_
image_transport::SubscriberFilter image_sub_
Definition: color_histogram.h:137
jsk_perception::ColorHistogram::srv_
boost::shared_ptr< dynamic_reconfigure::Server< Config > > srv_
Definition: color_histogram.h:136
header
header
jsk_perception::ColorHistogram::g_hist_size_
int g_hist_size_
Definition: color_histogram.h:145
image_transport::SubscriberFilter::unsubscribe
void unsubscribe()
ros::NodeHandle


jsk_perception
Author(s): Manabu Saito, Ryohei Ueda
autogenerated on Fri May 16 2025 03:11:16