organized_edge_detector_nodelet.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 #include <pcl/features/organized_edge_detection.h>
40 #include <pcl/features/integral_image_normal.h>
42 #include <cv_bridge/cv_bridge.h>
44 #include <std_msgs/ColorRGBA.h>
46 
47 #include <opencv2/opencv.hpp>
48 #include <jsk_recognition_msgs/ClusterPointIndices.h>
49 
50 namespace jsk_pcl_ros
51 {
53  {
54  ConnectionBasedNodelet::onInit();
55 
57  // setup dynamic reconfigure
59  srv_ = boost::make_shared <dynamic_reconfigure::Server<Config> > (*pnh_);
60  dynamic_reconfigure::Server<Config>::CallbackType f =
61  boost::bind (&OrganizedEdgeDetector::configCallback, this, _1, _2);
62  srv_->setCallback (f);
64  // indices publishers
67  = advertise<PCLIndicesMsg>(*pnh_, "output_nan_boundary_edge_indices", 1);
69  = advertise<PCLIndicesMsg>(*pnh_, "output_occluding_edge_indices", 1);
71  = advertise<PCLIndicesMsg>(*pnh_, "output_occluded_edge_indices", 1);
73  = advertise<PCLIndicesMsg>(*pnh_, "output_curvature_edge_indices", 1);
75  = advertise<PCLIndicesMsg>(*pnh_, "output_rgb_edge_indices", 1);
77  = advertise<PCLIndicesMsg>(*pnh_, "output_indices", 1);
79  = advertise<jsk_recognition_msgs::ClusterPointIndices>(*pnh_,
80  "output_straight_edges_indices", 1);
82  // pointcloud publishers
84  pub_normal_ = advertise<sensor_msgs::PointCloud2>(*pnh_, "output_normal", 1);
86  = advertise<sensor_msgs::PointCloud2>(*pnh_, "output_nan_boundary_edge", 1);
88  = advertise<sensor_msgs::PointCloud2>(*pnh_, "output_occluding_edge", 1);
90  = advertise<sensor_msgs::PointCloud2>(*pnh_, "output_occluded_edge", 1);
92  = advertise<sensor_msgs::PointCloud2>(*pnh_, "output_curvature_edge", 1);
94  = advertise<sensor_msgs::PointCloud2>(*pnh_, "output_rgb_edge", 1);
96  = advertise<sensor_msgs::PointCloud2>(*pnh_, "output", 1);
98  // image publishers
101  pub_edge_image_ = it.advertise("edge_image", 1);
102  pub_hough_image_ = it.advertise("hough_image", 1);
104  }
105 
107  {
108  sub_ = pnh_->subscribe("input", 1, &OrganizedEdgeDetector::estimate, this);
109  }
110 
112  {
113  sub_.shutdown();
114  }
115 
117  const pcl::PointCloud<PointT>::Ptr& input,
118  pcl::PointCloud<pcl::Normal>::Ptr output,
119  const std_msgs::Header& header)
120  {
121  pcl::IntegralImageNormalEstimation<PointT, pcl::Normal> ne;
122  if (estimation_method_ == 0) {
123  ne.setNormalEstimationMethod (ne.AVERAGE_3D_GRADIENT);
124  }
125  else if (estimation_method_ == 1) {
126  ne.setNormalEstimationMethod (ne.COVARIANCE_MATRIX);
127  }
128  else if (estimation_method_ == 2) {
129  ne.setNormalEstimationMethod (ne.AVERAGE_DEPTH_CHANGE);
130  }
131  else {
132  NODELET_FATAL("unknown estimation method: %d", estimation_method_);
133  return;
134  }
135 
136  if (border_policy_ignore_) {
137  ne.setBorderPolicy(pcl::IntegralImageNormalEstimation<PointT, pcl::Normal>::BORDER_POLICY_IGNORE);
138  }
139  else {
140  ne.setBorderPolicy(pcl::IntegralImageNormalEstimation<PointT, pcl::Normal>::BORDER_POLICY_MIRROR);
141  }
142 
143  ne.setMaxDepthChangeFactor(max_depth_change_factor_);
144  ne.setNormalSmoothingSize(normal_smoothing_size_);
145  ne.setDepthDependentSmoothing(depth_dependent_smoothing_);
146  ne.setInputCloud(input);
147  ne.compute(*output);
148  if (publish_normal_) {
149  sensor_msgs::PointCloud2 ros_output;
150  pcl::toROSMsg(*output, ros_output);
151  ros_output.header = header;
152  pub_normal_.publish(ros_output);
153  }
154  }
155 
156  void OrganizedEdgeDetector::configCallback (Config &config, uint32_t level)
157  {
158  boost::mutex::scoped_lock lock(mutex_);
159  max_depth_change_factor_ = config.max_depth_change_factor;
160  normal_smoothing_size_ = config.normal_smoothing_size;
161  depth_dependent_smoothing_ = config.depth_dependent_smoothing;
162  estimation_method_ = config.estimation_method;
163  border_policy_ignore_ = config.border_policy_ignore;
164  max_search_neighbors_ = config.max_search_neighbors;
165  depth_discontinuation_threshold_ = config.depth_discontinuation_threshold;
166  publish_normal_ = config.publish_normal;
167  use_nan_boundary_ = config.use_nan_boundary;
168  use_occluding_ = config.use_occluding;
169  use_occluded_ = config.use_occluded;
170  use_curvature_ = config.use_curvature;
171  use_rgb_ = config.use_rgb;
172  use_straightline_detection_ = config.use_straightline_detection;
173  rho_ = config.rho;
174  theta_ = config.theta;
175  straightline_threshold_ = config.straightline_threshold;
176  min_line_length_ = config.min_line_length;
177  max_line_gap_ = config.max_line_gap;
178  publish_debug_image_ = config.publish_debug_image;
179  }
180 
182  const pcl::PointCloud<PointT>::Ptr& input,
183  const pcl::PointCloud<pcl::Normal>::Ptr& normal,
184  pcl::PointCloud<pcl::Label>::Ptr& output,
185  std::vector<pcl::PointIndices>& label_indices)
186  {
187  pcl::OrganizedEdgeFromRGBNormals<PointT, pcl::Normal, pcl::Label> oed;
188  oed.setDepthDisconThreshold (depth_discontinuation_threshold_);
189  oed.setMaxSearchNeighbors (max_search_neighbors_);
190  int flags = 0;
191  if (use_nan_boundary_) {
192  flags |= oed.EDGELABEL_NAN_BOUNDARY;
193  }
194  if (use_occluding_) {
195  flags |= oed.EDGELABEL_OCCLUDING;
196  }
197  if (use_occluded_) {
198  flags |= oed.EDGELABEL_OCCLUDED;
199  }
200  if (use_curvature_) {
201  flags |= oed.EDGELABEL_HIGH_CURVATURE;
202  }
203  if (use_rgb_) {
204  flags |= oed.EDGELABEL_RGB_CANNY;
205  }
206  oed.setEdgeType (flags);
207  oed.setInputNormals(normal);
208  oed.setInputCloud(input);
209  oed.compute(*output, label_indices);
210  }
211 
214  ros::Publisher& pub_indices,
215  const pcl::PointCloud<PointT>::Ptr& cloud,
216  const std::vector<int>& indices,
217  const std_msgs::Header& header)
218  {
220  // publish indices
223  msg.header = header;
224  msg.indices = indices;
225  pub_indices.publish(msg);
226 
228  // publish cloud
230  pcl::PointCloud<PointT>::Ptr output(new pcl::PointCloud<PointT>);
231  pcl::copyPointCloud(*cloud, indices, *output);
232  sensor_msgs::PointCloud2 ros_output;
233  pcl::toROSMsg(*output, ros_output);
234  ros_output.header = header;
235  pub.publish(ros_output);
236  }
237 
239  const pcl::PointCloud<PointT>::Ptr& cloud,
240  const std_msgs::Header& header,
241  const std::vector<std::vector<int> > indices)
242  {
243  // output as cluster indices
244  jsk_recognition_msgs::ClusterPointIndices ros_msg;
245  ros_msg.header = header;
246  ros_msg.cluster_indices.resize(indices.size());
247  for (size_t i = 0; i < indices.size(); i++) {
248  PCLIndicesMsg ros_indices;
249  ros_indices.header = header;
250  ros_indices.indices = indices[i];
251  ros_msg.cluster_indices[i] = ros_indices;
252  }
254  }
255 
257  const pcl::PointCloud<PointT>::Ptr& cloud,
258  const std::vector<int>& indices,
259  const std_msgs::Header& header,
260  std::vector<std::vector<int> >& output_indices)
261  {
262  // initialize all the value by 0
263  cv::Mat mat = cv::Mat(cloud->height, cloud->width, CV_8UC1) * 0;
264  for (size_t i = 0; i < indices.size(); i++) {
265  int index = indices[i];
266  int index_height = index / cloud->width;
267  int index_width = index % cloud->width;
268  mat.data[index_height * mat.step + index_width * mat.elemSize()] = 255;
269  }
270 
271  std::vector<cv::Vec4i> lines;
272  cv::HoughLinesP(mat, lines, rho_, theta_ * CV_PI/180,
274  output_indices.resize(lines.size());
275  std::set<int> all_indices_set(indices.begin(), indices.end());
276  for (size_t i_line = 0; i_line < lines.size(); i_line++) {
277  std::vector<int> pixels;
278  cv::LineIterator it(mat,
279  cv::Point(lines[i_line][0], lines[i_line][1]),
280  cv::Point(lines[i_line][2], lines[i_line][3]), 4);
281  for(int i_pixel = 0; i_pixel < it.count; i_pixel++, ++it) {
282  cv::Point point = it.pos();
283  int flatten_index = point.x + point.y * cloud->width;
284  // check if flatten_index is included in indices or not
285  if (all_indices_set.find(flatten_index) != all_indices_set.end()) {
286  pixels.push_back(flatten_index);
287  }
288  }
289  output_indices[i_line] = pixels;
290  }
291  if (publish_debug_image_) {
292  cv::Mat color_dst;
293  cv::cvtColor(mat, color_dst, CV_GRAY2BGR );
294  for( size_t i = 0; i < lines.size(); i++ )
295  {
296  std_msgs::ColorRGBA c = jsk_topic_tools::colorCategory20(i);
297  cv::line(color_dst,
298  cv::Point(lines[i][0], lines[i][1]),
299  cv::Point(lines[i][2], lines[i][3]),
300  cv::Scalar((uint8_t)(c.b * 255), (uint8_t)(c.g * 255), (uint8_t)(c.r * 255)), 3, 8);
301  }
302  sensor_msgs::Image::Ptr ros_edge_image
303  = cv_bridge::CvImage(header,
305  mat).toImageMsg();
306  pub_edge_image_.publish(ros_edge_image);
307  sensor_msgs::Image::Ptr ros_hough_image
308  = cv_bridge::CvImage(header,
310  color_dst).toImageMsg();
311  pub_hough_image_.publish(ros_hough_image);
312  }
313  }
314 
316  const sensor_msgs::PointCloud2::ConstPtr& msg)
317  {
318  boost::mutex::scoped_lock lock(mutex_);
319  if (msg->height == 1) {
320  NODELET_ERROR("[OrganizedEdgeDetector] organized pointcloud is required");
321  return;
322  }
323  pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);
324  pcl::PointCloud<pcl::Normal>::Ptr normal(new pcl::PointCloud<pcl::Normal>);
325  pcl::PointCloud<pcl::Label>::Ptr label(new pcl::PointCloud<pcl::Label>);
326  std::vector<pcl::PointIndices> label_indices;
327  pcl::fromROSMsg(*msg, *cloud);
328 
329  estimateNormal(cloud, normal, msg->header);
330  estimateEdge(cloud, normal, label, label_indices);
332  // build indices includes all the indices
334  std::vector<int> tmp1 = jsk_recognition_utils::addIndices(label_indices[0].indices,
335  label_indices[1].indices);
336  std::vector<int> tmp2 = jsk_recognition_utils::addIndices(tmp1,
337  label_indices[2].indices);
338  std::vector<int> tmp3 = jsk_recognition_utils::addIndices(tmp2,
339  label_indices[3].indices);
340  std::vector<int> all = jsk_recognition_utils::addIndices(tmp3,
341  label_indices[4].indices);
343  std::vector<std::vector<int> > straightline_indices;
344  estimateStraightEdges(cloud, all, msg->header, straightline_indices);
345  // publish the result
346  publishStraightEdges(cloud, msg->header, straightline_indices);
347  }
349  // publish result
352  cloud,
353  label_indices[0].indices, msg->header);
355  cloud,
356  label_indices[1].indices, msg->header);
358  cloud,
359  label_indices[2].indices, msg->header);
361  cloud,
362  label_indices[3].indices, msg->header);
364  cloud,
365  label_indices[4].indices, msg->header);
367  cloud,
368  all, msg->header);
369  }
370 }
371 
list lines
PLUGINLIB_EXPORT_CLASS(jsk_pcl_ros::OrganizedEdgeDetector, nodelet::Nodelet)
#define NODELET_ERROR(...)
label
void publish(const boost::shared_ptr< M > &message) const
image_transport::Publisher pub_hough_image_
virtual void estimateNormal(const pcl::PointCloud< PointT >::Ptr &input, pcl::PointCloud< pcl::Normal >::Ptr output, const std_msgs::Header &header)
image_transport::Publisher pub_edge_image_
void fromROSMsg(const sensor_msgs::PointCloud2 &cloud, pcl::PointCloud< T > &pcl_cloud)
unsigned int index
boost::shared_ptr< dynamic_reconfigure::Server< Config > > srv_
void output(int index, double value)
void publish(const sensor_msgs::Image &message) const
boost::shared_ptr< ros::NodeHandle > pnh_
virtual void estimateEdge(const pcl::PointCloud< PointT >::Ptr &input, const pcl::PointCloud< pcl::Normal >::Ptr &normal, pcl::PointCloud< pcl::Label >::Ptr &output, std::vector< pcl::PointIndices > &label_indices)
std::vector< int > addIndices(const std::vector< int > &a, const std::vector< int > &b)
virtual void configCallback(Config &config, uint32_t level)
void toROSMsg(const pcl::PointCloud< T > &pcl_cloud, sensor_msgs::PointCloud2 &cloud)
jsk_pcl_ros::OrganizedEdgeDetectorConfig Config
double x
std_msgs::ColorRGBA colorCategory20(int i)
c
#define NODELET_FATAL(...)
pcl::PointIndices PCLIndicesMsg
cloud
virtual void estimate(const sensor_msgs::PointCloud2::ConstPtr &msg)
virtual void publishStraightEdges(const pcl::PointCloud< PointT >::Ptr &cloud, const std_msgs::Header &header, const std::vector< std::vector< int > > indices)
virtual void publishIndices(ros::Publisher &pub, ros::Publisher &pub_indices, const pcl::PointCloud< PointT >::Ptr &cloud, const std::vector< int > &indices, const std_msgs::Header &header)
sensor_msgs::ImagePtr toImageMsg() const
virtual void estimateStraightEdges(const pcl::PointCloud< PointT >::Ptr &cloud, const std::vector< int > &indices, const std_msgs::Header &header, std::vector< std::vector< int > > &output_indices)


jsk_pcl_ros
Author(s): Yohei Kakiuchi
autogenerated on Mon May 3 2021 03:03:47