draw_rects.cpp
Go to the documentation of this file.
1 // -*- mode: C++ -*-
2 /*********************************************************************
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2017, 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 /*
36  * draw_rects.cpp
37  * Author: furushchev <furushchev@jsk.imi.i.u-tokyo.ac.jp>
38  */
39 
41 #if ( CV_MAJOR_VERSION >= 4)
42 #include <opencv2/imgproc/imgproc_c.h>
43 #endif
44 
46 
47 namespace jsk_perception
48 {
49 
50  void DrawRects::onInit()
51  {
52  ConnectionBasedNodelet::onInit();
53 
54  srv_ = boost::make_shared<dynamic_reconfigure::Server<Config> >(*pnh_);
55  typename dynamic_reconfigure::Server<Config>::CallbackType f =
56  boost::bind(&DrawRects::configCallback, this, _1, _2);
57  srv_->setCallback(f);
58 
59  pub_image_ = advertise<sensor_msgs::Image>(*pnh_, "output", 1);
60 
61  onInitPostProcess();
62  }
63 
65  // message_filters::Synchronizer needs to be called reset
66  // before message_filters::Subscriber is freed.
67  // Calling reset fixes the following error on shutdown of the nodelet:
68  // terminate called after throwing an instance of
69  // 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::lock_error> >'
70  // what(): boost: mutex lock failed in pthread_mutex_lock: Invalid argument
71  // Also see https://github.com/ros/ros_comm/issues/720 .
72  sync_.reset();
73  async_.reset();
74  }
75 
77  {
78  sub_image_.subscribe(*pnh_, "input", 1);
79  sub_rects_.subscribe(*pnh_, "input/rects", 1);
80 
82  sub_class_.subscribe(*pnh_, "input/class", 1);
83  else
85 
86  if (use_async_)
87  {
88  async_ = boost::make_shared<message_filters::Synchronizer<AsyncPolicy> >(queue_size_);
90  async_->connectInput(sub_image_, sub_rects_, sub_class_);
91  else
92  async_->connectInput(sub_image_, sub_rects_, null_class_);
93  async_->registerCallback(boost::bind(&DrawRects::onMessage, this, _1, _2, _3));
94  } else {
95  sync_ = boost::make_shared<message_filters::Synchronizer<SyncPolicy> >(queue_size_);
97  sync_->connectInput(sub_image_, sub_rects_, sub_class_);
98  else
99  sync_->connectInput(sub_image_, sub_rects_, null_class_);
100  sync_->registerCallback(boost::bind(&DrawRects::onMessage, this, _1, _2, _3));
101  }
102  }
103 
105  {
110  }
111 
112  void DrawRects::configCallback(Config& config, uint32_t level)
113  {
114  boost::mutex::scoped_lock lock(mutex_);
115 
116  bool need_resubscribe = false;
117  if (use_async_ != config.approximate_sync ||
118  queue_size_ != config.queue_size ||
119  use_classification_result_ != config.use_classification_result)
120  need_resubscribe = true;
121 
122  use_async_ = config.approximate_sync;
123  queue_size_ = config.queue_size;
124 
125  use_classification_result_ = config.use_classification_result;
126  show_proba_ = config.show_proba;
127 
128  rect_boldness_ = config.rect_boldness;
129 
130  label_size_ = config.label_size;
131  label_boldness_ = config.label_boldness;
132  label_font_ = config.label_font;
133  label_margin_factor_ = config.label_margin_factor;
134 
135  resolution_factor_ = config.resolution_factor;
136  interpolation_method_ = config.interpolation_method;
137 #if ROS_VERSION_MINIMUM(1, 11, 4)
138  // indigo or later
139  if (need_resubscribe && isSubscribed()) {
140  unsubscribe();
141  subscribe();
142  }
143 #endif
144  }
145 
147  const jsk_recognition_msgs::RectArray::ConstPtr& rects)
148  {
149  jsk_recognition_msgs::ClassificationResult classes;
150  classes.header = rects->header;
152  boost::make_shared<jsk_recognition_msgs::ClassificationResult>(classes));
153  }
154 
156  const sensor_msgs::Image::ConstPtr& image,
157  const jsk_recognition_msgs::RectArray::ConstPtr& rects,
158  const jsk_recognition_msgs::ClassificationResult::ConstPtr& classes)
159  {
160  boost::mutex::scoped_lock lock(mutex_);
161 
163  try {
164  cv_img = cv_bridge::toCvCopy(image, enc::BGR8);
165  } catch (cv_bridge::Exception &e) {
166  NODELET_ERROR_STREAM("Failed to convert image: " << e.what());
167  return;
168  }
169 
170  cv::Mat img;
171  cv::resize(cv_img->image, img, cv::Size(),
174 
175  int label_num = \
176  use_classification_result_ ? classes->target_names.size() : rects->rects.size();
177 
178  for (size_t i = 0; i < rects->rects.size(); ++i) {
179  int label_idx = use_classification_result_ ? classes->labels[i] : i;
180  cv::Scalar color;
181  randomColor(label_num, label_idx, color);
182  drawRect(img, rects->rects[i], color);
183 
185  {
186  std::ostringstream oss;
187  oss << classes->label_names[i];
188  if (show_proba_ && classes->label_proba.size() > i) {
189  oss << std::fixed << std::setprecision(2);
190  oss << " (" << classes->label_proba[i] << ")";
191  }
192  drawLabel(img, rects->rects[i], color, oss.str());
193  }
194  }
195 
196  pub_image_.publish(*cv_bridge::CvImage(image->header, enc::BGR8, img).toImageMsg());
197  }
198 
199  void DrawRects::drawRect(
200  cv::Mat& img, const jsk_recognition_msgs::Rect& orig_rect, const cv::Scalar& color)
201  {
202  cv::Rect rect(orig_rect.x * resolution_factor_,
203  orig_rect.y * resolution_factor_,
204  orig_rect.width * resolution_factor_,
205  orig_rect.height * resolution_factor_);
206  cv::rectangle(img, rect, color, rect_boldness_, CV_AA);
207  }
208 
210  cv::Mat& img, const jsk_recognition_msgs::Rect& rect,
211  const cv::Scalar& color, const std::string& label)
212  {
213  int baseline;
214  cv::Size label_size = cv::getTextSize(label, label_font_,
216  &baseline);
217  int text_color = isDarkColor(color) ? 255 : 0;
218 
219  double orig_x = rect.x * resolution_factor_;
220  double orig_y = rect.y * resolution_factor_;
221 
222  cv::rectangle(img,
223  cv::Rect(orig_x,
224  orig_y - label_size.height * label_margin_factor_ * 1.15,
225  label_size.width * label_margin_factor_,
226  label_size.height * label_margin_factor_ * 1.3),
227  color, -1, CV_AA);
228  cv::putText(img, label,
229  cv::Point(orig_x + label_size.width * (label_margin_factor_ - 1.0) / 2.0,
230  orig_y - label_size.height * (label_margin_factor_ - 1.0) / 2.0),
232  label_size_,
233  cv::Scalar(text_color, text_color, text_color),
235  CV_AA);
236  }
237 
238  void DrawRects::randomColor(const int& label_num, const int& index, cv::Scalar& color)
239  {
240  static const float colors[6][3] = { {1,0,1}, {0,0,1},{0,1,1},{0,1,0},{1,1,0},{1,0,0} };
241  float ratio = ((float)(index * 123457 % label_num) / label_num) * 5;
242  int i = std::floor(ratio);
243  int j = std::ceil(ratio);
244  ratio -= i;
245  for (int c = 0; c < 3; ++c)
246  color[c] = (int)(((1-ratio) * colors[i][c] + ratio * colors[j][c]) * 255);
247  }
248 }
249 
sensor_msgs::image_encodings
jsk_perception::DrawRects
Definition: draw_rects.h:101
jsk_perception::DrawRects::null_class_
message_filters::PassThrough< jsk_recognition_msgs::ClassificationResult > null_class_
Definition: draw_rects.h:174
jsk_perception::DrawRects::srv_
boost::shared_ptr< dynamic_reconfigure::Server< Config > > srv_
Definition: draw_rects.h:170
ssd_train_dataset.float
float
Definition: ssd_train_dataset.py:180
boost::shared_ptr< CvImage >
i
int i
cv_bridge::CvImage::toImageMsg
sensor_msgs::ImagePtr toImageMsg() const
jsk_perception::DrawRects::sub_image_
message_filters::Subscriber< sensor_msgs::Image > sub_image_
Definition: draw_rects.h:175
jsk_perception::DrawRects::unsubscribe
virtual void unsubscribe()
Definition: draw_rects.cpp:136
jsk_perception::DrawRects::onMessage
virtual void onMessage(const sensor_msgs::Image::ConstPtr &image, const jsk_recognition_msgs::RectArray::ConstPtr &rects, const jsk_recognition_msgs::ClassificationResult::ConstPtr &classes)
Definition: draw_rects.cpp:187
_1
boost::arg< 1 > _1
jsk_perception::DrawRects::use_async_
bool use_async_
Definition: draw_rects.h:179
jsk_perception::DrawRects::rect_boldness_
int rect_boldness_
Definition: draw_rects.h:183
jsk_perception::DrawRects::label_font_
int label_font_
Definition: draw_rects.h:186
cv_bridge::Exception
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
message_filters::Subscriber::unsubscribe
void unsubscribe()
_3
boost::arg< 3 > _3
img
img
class_list_macros.h
jsk_perception::DrawRects::label_boldness_
int label_boldness_
Definition: draw_rects.h:185
jsk_perception
Definition: add_mask_image.h:48
jsk_perception::DrawRects::interpolation_method_
int interpolation_method_
Definition: draw_rects.h:189
jsk_perception::DrawRects::async_
boost::shared_ptr< message_filters::Synchronizer< AsyncPolicy > > async_
Definition: draw_rects.h:172
cv_bridge::toCvCopy
CvImagePtr toCvCopy(const sensor_msgs::CompressedImage &source, const std::string &encoding=std::string())
NODELET_ERROR_STREAM
#define NODELET_ERROR_STREAM(...)
jsk_perception::DrawRects::use_classification_result_
bool use_classification_result_
Definition: draw_rects.h:180
jsk_perception::DrawRects::drawLabel
virtual void drawLabel(cv::Mat &img, const jsk_recognition_msgs::Rect &rect, const cv::Scalar &color, const std::string &label)
Definition: draw_rects.cpp:241
jsk_perception::DrawRects::pub_image_
ros::Publisher pub_image_
Definition: draw_rects.h:173
jsk_perception::DrawRects::isDarkColor
virtual bool isDarkColor(const cv::Scalar &color)
Definition: draw_rects.h:165
jsk_perception::DrawRects::resolution_factor_
double resolution_factor_
Definition: draw_rects.h:188
jsk_perception::DrawRects::show_proba_
bool show_proba_
Definition: draw_rects.h:181
_2
boost::arg< 2 > _2
jsk_perception::DrawRects::~DrawRects
virtual ~DrawRects()
Definition: draw_rects.cpp:96
jsk_perception::DrawRects::mutex_
boost::mutex mutex_
Definition: draw_rects.h:169
jsk_perception::DrawRects::queue_size_
int queue_size_
Definition: draw_rects.h:182
jsk_perception::DrawRects::drawRect
virtual void drawRect(cv::Mat &img, const jsk_recognition_msgs::Rect &rect, const cv::Scalar &color)
Definition: draw_rects.cpp:231
message_filters::SimpleFilter::registerCallback
Connection registerCallback(const boost::function< void(P)> &callback)
message_filters::PassThrough::add
void add(const EventType &evt)
lock
mutex_t * lock
draw_rects.h
ratio
message_filters::Subscriber::subscribe
void subscribe()
jsk_perception::DrawRects::fillEmptyClasses
virtual void fillEmptyClasses(const jsk_recognition_msgs::RectArray::ConstPtr &rects)
Definition: draw_rects.cpp:178
f
f
jsk_perception::DrawRects::label_margin_factor_
double label_margin_factor_
Definition: draw_rects.h:187
jsk_perception::DrawRects::onInit
virtual void onInit()
Definition: draw_rects.cpp:82
nodelet::Nodelet
jsk_perception::DrawRects::subscribe
virtual void subscribe()
Definition: draw_rects.cpp:108
cv_bridge::CvImage
jsk_perception::DrawRects::configCallback
virtual void configCallback(Config &config, uint32_t level)
Definition: draw_rects.cpp:144
jsk_perception::DrawRects::label_size_
double label_size_
Definition: draw_rects.h:184
PLUGINLIB_EXPORT_CLASS
PLUGINLIB_EXPORT_CLASS(jsk_perception::DrawRects, nodelet::Nodelet)
config
config
jsk_perception::DrawRects::randomColor
virtual void randomColor(const int &label_num, const int &index, cv::Scalar &color)
Definition: draw_rects.cpp:270
jsk_perception::DrawRects::sync_
boost::shared_ptr< message_filters::Synchronizer< SyncPolicy > > sync_
Definition: draw_rects.h:171
jsk_perception::DrawRects::sub_class_
message_filters::Subscriber< jsk_recognition_msgs::ClassificationResult > sub_class_
Definition: draw_rects.h:177
jsk_perception::DrawRects::sub_rects_
message_filters::Subscriber< jsk_recognition_msgs::RectArray > sub_rects_
Definition: draw_rects.h:176


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