tabletop_color_difference_likelihood.cpp
Go to the documentation of this file.
1 // -*- mode: c++ -*-
2 /*********************************************************************
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2015, 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 
36 #define BOOST_PARAMETER_MAX_ARITY 7
37 #include <Eigen/Geometry>
38 #include <boost/assign.hpp>
41 #include <cv_bridge/cv_bridge.h>
49 #include <sstream>
50 
51 namespace jsk_perception
52 {
54  {
55  DiagnosticNodelet::onInit();
56  pnh_->param("tf_queue_size", tf_queue_size_, 10);
57  pnh_->param("cyclic_value", cyclic_value_, true);
58  srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> > (*pnh_);
59  dynamic_reconfigure::Server<Config>::CallbackType f =
60  boost::bind (
62  srv_->setCallback (f);
64  pub_ = advertise<sensor_msgs::Image>(*pnh_, "output", 1);
65  pub_debug_histogram_image_ = advertise<sensor_msgs::Image>(*pnh_, "debug/histogram_image", 1);
66  pub_debug_polygon_ = advertise<sensor_msgs::Image>(*pnh_, "debug/polygon_image", 1);
68  }
69 
71  {
72  sub_info_ = pnh_->subscribe("input/camera_info", 1,
74  sub_polygons_ = pnh_->subscribe("input/polygons", 1,
76  sub_image_.subscribe(*pnh_, "input", 1);
77  ros::V_string names = boost::assign::list_of("~input")("~input/camera_info")("~input/polygons");
79  }
80 
82  {
86  }
87 
88  void TabletopColorDifferenceLikelihood::infoCallback(const sensor_msgs::CameraInfo::ConstPtr& msg)
89  {
90  boost::mutex::scoped_lock lock(mutex_);
91  latest_info_msg_ = msg;
92  }
93 
94  void TabletopColorDifferenceLikelihood::polygonCallback(const jsk_recognition_msgs::PolygonArray::ConstPtr& msg)
95  {
96  boost::mutex::scoped_lock lock(mutex_);
97  latest_polygon_msg_ = msg;
98  if (!tf_filter_) {
99  // If tf_filter_ is not initialized yet,
100  // we initialize tf_filter_ with frame_id
101  // of the message.
103  *tf_listener_,
104  msg->header.frame_id,
105  tf_queue_size_));
106  tf_filter_->registerCallback(boost::bind(&TabletopColorDifferenceLikelihood::imageCallback, this, _1));
107  }
108  }
109 
111  cv::Mat& image,
113  size_t pi) const
114  {
115  polygon->drawLineToImage(model, image,
117  if (polygon->centroid()[2] > 0) {
118  std::stringstream ss;
119  ss << pi;
120  cv::putText(image, ss.str(),
122  cv::FONT_HERSHEY_SIMPLEX,
123  0.5,
125  }
126  }
127 
128  void TabletopColorDifferenceLikelihood::imageCallback(const sensor_msgs::Image::ConstPtr& msg)
129  {
130  boost::mutex::scoped_lock lock(mutex_);
131  // check camera info and polygon is available
132  if (!latest_info_msg_) {
133  ROS_WARN("no camera info is available yet");
134  return;
135  }
136  if (!latest_polygon_msg_) {
137  ROS_WARN("no polygon is available yet");
138  return;
139  }
140 
141  // try-catch for tf exception
142  try
143  {
144  cv_bridge::CvImagePtr input_cv_image
146  cv::Mat input_image = input_cv_image->image;
147  // Transform PolygonArray to the frame of image
149  tf_listener_->lookupTransform(msg->header.frame_id,
150  latest_polygon_msg_->header.frame_id,
151  msg->header.stamp,
152  transform);
153  Eigen::Affine3f polygon_transform;
154  tf::transformTFToEigen(transform, polygon_transform);
155 
156  // convert to polygon
157  std::vector<jsk_recognition_utils::Polygon::Ptr> polygons
161  cv::Mat image = model.image(CV_8UC1);
162  // debug_polygon_image is an image for debug.
163  cv::Mat debug_polygon_image = model.image(CV_8UC3);
164  // prepare for histogram image
165  cv::Mat histogram_image;
166  for (size_t pi = 0; pi < polygons.size(); pi++) {
167  jsk_recognition_utils::Polygon::Ptr polygon = polygons[pi];
168  cv::Mat mask_image;
169  polygon->maskImage(model, mask_image);
170  debugPolygonImage(model, debug_polygon_image, polygon, pi);
171  // compute histogram of input with mask_image
172  cv::MatND hist = jsk_recognition_utils::computeHistogram(input_image, bin_size_,
174  mask_image);
175  std::vector<jsk_recognition_msgs::HistogramWithRangeBin> histogram_bins
178  std::vector<jsk_recognition_msgs::HistogramWithRangeBin> top_n_histogram_bins
180  cv::Mat one_histogram_image = cv::Mat(30, 180, CV_8UC3);
181  one_histogram_image = cv::Scalar::all(255);
182  for (size_t j = 0; j < histogram_bins.size(); j++) {
184  histogram_bins[j],
187  top_n_histogram_bins[0].count,
188  cv::Scalar(0, 0, 0));
189  }
190  for (size_t j = 0; j < top_n_histogram_bins.size(); j++) {
192  top_n_histogram_bins[j],
195  top_n_histogram_bins[0].count,
196  cv::Scalar(255, 0, 0));
197  }
198  if (histogram_image.empty()) {
199  histogram_image = one_histogram_image;
200  }
201  else {
202  cv::vconcat(histogram_image, one_histogram_image, histogram_image);
203  }
204  const cv::Scalar center_color = cv::mean(input_image, mask_image);
205  for (size_t j = 0; j < model.height(); j++) {
206  for (size_t i = 0; i < model.width(); i++) {
207  if (mask_image.at<unsigned char>(j, i) != 0) {
208  const unsigned char current_value = image.at<unsigned char>(j, i);
209  // const unsigned char new_value = computePixelDistance(input_image.at<unsigned char>(j, i),
210  // center_color[0]);
211  const unsigned char new_value = computePixelHistogramDistance(input_image.at<unsigned char>(j, i),
212  top_n_histogram_bins);
213  if (current_value > new_value || current_value == 0) {
214  image.at<unsigned char>(j, i) = new_value;
215  }
216  }
217  }
218  }
219  }
220  pub_.publish(cv_bridge::CvImage(msg->header,
222  image).toImageMsg());
225  debug_polygon_image).toImageMsg());
228  histogram_image).toImageMsg());
229  }
230  catch (...)
231  {
232  NODELET_ERROR("Failed to resolve tf");
233  }
234  }
235 
237  {
238  boost::mutex::scoped_lock lock(mutex_);
239  bin_size_ = config.bin_size;
240  pixel_min_value_ = config.pixel_min_value;
241  pixel_max_value_ = config.pixel_max_value;
242  histogram_top_n_ratio_ = config.histogram_top_n_ratio;
243  }
244 }
245 
f
#define NODELET_ERROR(...)
virtual void polygonCallback(const jsk_recognition_msgs::PolygonArray::ConstPtr &msg)
void publish(const boost::shared_ptr< M > &message) const
void transformTFToEigen(const tf::Transform &t, Eigen::Affine3d &e)
virtual void infoCallback(const sensor_msgs::CameraInfo::ConstPtr &msg)
virtual void imageCallback(const sensor_msgs::Image::ConstPtr &msg)
cv::MatND computeHistogram(const cv::Mat &input_image, int bin_size, float min_value, float max_value, const cv::Mat &mask_image)
boost::shared_ptr< tf::MessageFilter< sensor_msgs::Image > > tf_filter_
virtual cv::Mat image(const int type) const
static Polygon fromROSMsg(const geometry_msgs::Polygon &polygon)
PLUGINLIB_EXPORT_CLASS(jsk_perception::TabletopColorDifferenceLikelihood, nodelet::Nodelet)
virtual image_geometry::PinholeCameraModel getPinholeCameraModel() const
#define ROS_WARN(...)
cv::Point project3DPointToPixel(const image_geometry::PinholeCameraModel &model, const Eigen::Vector3f &p)
hist
std::vector< jsk_recognition_msgs::HistogramWithRangeBin > cvMatNDToHistogramWithRangeBinArray(const cv::MatND &cv_hist, float min_value, float max_value)
message_filters::Subscriber< sensor_msgs::Image > sub_image_
std::vector< jsk_recognition_msgs::HistogramWithRangeBin > topNHistogramWithRangeBins(const std::vector< jsk_recognition_msgs::HistogramWithRangeBin > &bins, double top_n_rate)
std::vector< std::string > V_string
void sortHistogramWithRangeBinArray(std::vector< jsk_recognition_msgs::HistogramWithRangeBin > &bins)
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())
cv::Scalar colorROSToCVRGB(const std_msgs::ColorRGBA &ros_color)
virtual unsigned char computePixelHistogramDistance(const unsigned char from, const std::vector< jsk_recognition_msgs::HistogramWithRangeBin > &bins)
void lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, StampedTransform &transform) const
mutex_t * lock
std_msgs::ColorRGBA colorCategory20(int i)
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)
int current_value
int count
void drawHistogramWithRangeBin(cv::Mat &image, const jsk_recognition_msgs::HistogramWithRangeBin &bin, float min_width_value, float max_width_value, float max_height_value, cv::Scalar color)
virtual void debugPolygonImage(const jsk_recognition_utils::CameraDepthSensor &model, cv::Mat &image, jsk_recognition_utils::Polygon::Ptr polygon, size_t pi) const
static tf::TransformListener * getInstance()
boost::shared_ptr< dynamic_reconfigure::Server< Config > > srv_
jsk_recognition_msgs::PolygonArray::ConstPtr latest_polygon_msg_
sensor_msgs::ImagePtr toImageMsg() const
virtual void setCameraInfo(const sensor_msgs::CameraInfo &info)


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