Point Cloud Library (PCL)  1.9.0-dev
lccp_segmentation.hpp
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2014-, Open Perception, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of the copyright holder(s) nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37 
38 #ifndef PCL_SEGMENTATION_IMPL_LCCP_SEGMENTATION_HPP_
39 #define PCL_SEGMENTATION_IMPL_LCCP_SEGMENTATION_HPP_
40 
41 #include <pcl/segmentation/lccp_segmentation.h>
42 #include <pcl/common/common.h>
43 
44 
45 //////////////////////////////////////////////////////////
46 //////////////////////////////////////////////////////////
47 /////////////////// Public Functions /////////////////////
48 //////////////////////////////////////////////////////////
49 //////////////////////////////////////////////////////////
50 
51 
52 
53 template <typename PointT>
55  concavity_tolerance_threshold_ (10),
56  grouping_data_valid_ (false),
57  supervoxels_set_ (false),
58  use_smoothness_check_ (false),
59  smoothness_threshold_ (0.1),
60  use_sanity_check_ (false),
61  seed_resolution_ (0),
62  voxel_resolution_ (0),
63  k_factor_ (0),
64  min_segment_size_ (0)
65 {
66 }
67 
68 template <typename PointT>
70 {
71 }
72 
73 template <typename PointT> void
75 {
76  sv_adjacency_list_.clear ();
77  processed_.clear ();
82  grouping_data_valid_ = false;
83  supervoxels_set_ = false;
84 }
85 
86 template <typename PointT> void
88 {
89  if (supervoxels_set_)
90  {
91  // Calculate for every Edge if the connection is convex or invalid
92  // This effectively performs the segmentation.
94 
95  // Correct edge relations using extended convexity definition if k>0
97 
98  // group supervoxels
99  doGrouping ();
100 
101  grouping_data_valid_ = true;
102 
103  // merge small segments
105  }
106  else
107  PCL_WARN ("[pcl::LCCPSegmentation::segment] WARNING: Call function setInputSupervoxels first. Nothing has been done. \n");
108 }
109 
110 
111 template <typename PointT> void
113 {
115  {
116  // Relabel all Points in cloud with new labels
117  typename pcl::PointCloud<pcl::PointXYZL>::iterator voxel_itr = labeled_cloud_arg.begin ();
118  for (; voxel_itr != labeled_cloud_arg.end (); ++voxel_itr)
119  {
120  voxel_itr->label = sv_label_to_seg_label_map_[voxel_itr->label];
121  }
122  }
123  else
124  {
125  PCL_WARN ("[pcl::LCCPSegmentation::relabelCloud] WARNING: Call function segment first. Nothing has been done. \n");
126  }
127 }
128 
129 
130 
131 //////////////////////////////////////////////////////////
132 //////////////////////////////////////////////////////////
133 /////////////////// Protected Functions //////////////////
134 //////////////////////////////////////////////////////////
135 //////////////////////////////////////////////////////////
136 
137 template <typename PointT> void
139 {
141 
142  //The vertices in the supervoxel adjacency list are the supervoxel centroids
143  std::pair<VertexIterator, VertexIterator> vertex_iterator_range;
144  vertex_iterator_range = boost::vertices (sv_adjacency_list_);
145 
146  uint32_t current_segLabel;
147  uint32_t neigh_segLabel;
148 
149  // For every Supervoxel..
150  for (VertexIterator sv_itr = vertex_iterator_range.first; sv_itr != vertex_iterator_range.second; ++sv_itr) // For all supervoxels
151  {
152  const uint32_t& sv_label = sv_adjacency_list_[*sv_itr];
153  current_segLabel = sv_label_to_seg_label_map_[sv_label];
154 
155  // ..look at all neighbors and insert their labels into the neighbor set
156  std::pair<AdjacencyIterator, AdjacencyIterator> neighbors = boost::adjacent_vertices (*sv_itr, sv_adjacency_list_);
157  for (AdjacencyIterator itr_neighbor = neighbors.first; itr_neighbor != neighbors.second; ++itr_neighbor)
158  {
159  const uint32_t& neigh_label = sv_adjacency_list_[*itr_neighbor];
160  neigh_segLabel = sv_label_to_seg_label_map_[neigh_label];
161 
162  if (current_segLabel != neigh_segLabel)
163  {
164  seg_label_to_neighbor_set_map_[current_segLabel].insert (neigh_segLabel);
165  }
166  }
167  }
168 }
169 
170 template <typename PointT> void
172 {
173  if (min_segment_size_ == 0)
174  return;
175 
177 
178  std::set<uint32_t> filteredSegLabels;
179 
180  uint32_t largest_neigh_size = 0;
181  uint32_t largest_neigh_seg_label = 0;
182  uint32_t current_seg_label;
183 
184  std::pair<VertexIterator, VertexIterator> vertex_iterator_range;
185  vertex_iterator_range = boost::vertices (sv_adjacency_list_);
186 
187  bool continue_filtering = true;
188 
189  while (continue_filtering)
190  {
191  continue_filtering = false;
192  unsigned int nr_filtered = 0;
193 
194  // Iterate through all supervoxels, check if they are in a "small" segment -> change label to largest neighborID
195  for (VertexIterator sv_itr = vertex_iterator_range.first; sv_itr != vertex_iterator_range.second; ++sv_itr) // For all supervoxels
196  {
197  const uint32_t& sv_label = sv_adjacency_list_[*sv_itr];
198  current_seg_label = sv_label_to_seg_label_map_[sv_label];
199  largest_neigh_seg_label = current_seg_label;
200  largest_neigh_size = seg_label_to_sv_list_map_[current_seg_label].size ();
201 
202  const uint32_t& nr_neighbors = seg_label_to_neighbor_set_map_[current_seg_label].size ();
203  if (nr_neighbors == 0)
204  continue;
205 
206  if (seg_label_to_sv_list_map_[current_seg_label].size () <= min_segment_size_)
207  {
208  continue_filtering = true;
209  nr_filtered++;
210 
211  // Find largest neighbor
212  std::set<uint32_t>::const_iterator neighbors_itr = seg_label_to_neighbor_set_map_[current_seg_label].begin ();
213  for (; neighbors_itr != seg_label_to_neighbor_set_map_[current_seg_label].end (); ++neighbors_itr)
214  {
215  if (seg_label_to_sv_list_map_[*neighbors_itr].size () >= largest_neigh_size)
216  {
217  largest_neigh_seg_label = *neighbors_itr;
218  largest_neigh_size = seg_label_to_sv_list_map_[*neighbors_itr].size ();
219  }
220  }
221 
222  // Add to largest neighbor
223  if (largest_neigh_seg_label != current_seg_label)
224  {
225  if (filteredSegLabels.count (largest_neigh_seg_label) > 0)
226  continue; // If neighbor was already assigned to someone else
227 
228  sv_label_to_seg_label_map_[sv_label] = largest_neigh_seg_label;
229  filteredSegLabels.insert (current_seg_label);
230 
231  // Assign supervoxel labels of filtered segment to new owner
232  std::set<uint32_t>::iterator sv_ID_itr = seg_label_to_sv_list_map_[current_seg_label].begin ();
233  sv_ID_itr = seg_label_to_sv_list_map_[current_seg_label].begin ();
234  for (; sv_ID_itr != seg_label_to_sv_list_map_[current_seg_label].end (); ++sv_ID_itr)
235  {
236  seg_label_to_sv_list_map_[largest_neigh_seg_label].insert (*sv_ID_itr);
237  }
238  }
239  }
240  }
241 
242  // Erase filtered Segments from segment map
243  std::set<uint32_t>::iterator filtered_ID_itr = filteredSegLabels.begin ();
244  for (; filtered_ID_itr != filteredSegLabels.end (); ++filtered_ID_itr)
245  {
246  seg_label_to_sv_list_map_.erase (*filtered_ID_itr);
247  }
248 
249  // After filtered Segments are deleted, compute completely new adjacency map
250  // NOTE Recomputing the adjacency of every segment in every iteration is an easy but inefficient solution.
251  // Because the number of segments in an average scene is usually well below 1000, the time spend for noise filtering is still negligible in most cases
253  } // End while (Filtering)
254 }
255 
256 template <typename PointT> void
257 pcl::LCCPSegmentation<PointT>::prepareSegmentation (const std::map<uint32_t, typename pcl::Supervoxel<PointT>::Ptr>& supervoxel_clusters_arg,
258  const std::multimap<uint32_t, uint32_t>& label_adjaceny_arg)
259 {
260  // Clear internal data
261  reset ();
262 
263  // Copy map with supervoxel pointers
264  sv_label_to_supervoxel_map_ = supervoxel_clusters_arg;
265 
266  // Build a boost adjacency list from the adjacency multimap
267  std::map<uint32_t, VertexID> label_ID_map;
268 
269  // Add all supervoxel labels as vertices
270  for (typename std::map<uint32_t, typename pcl::Supervoxel<PointT>::Ptr>::iterator svlabel_itr = sv_label_to_supervoxel_map_.begin ();
271  svlabel_itr != sv_label_to_supervoxel_map_.end (); ++svlabel_itr)
272  {
273  const uint32_t& sv_label = svlabel_itr->first;
274  VertexID node_id = boost::add_vertex (sv_adjacency_list_);
275  sv_adjacency_list_[node_id] = sv_label;
276  label_ID_map[sv_label] = node_id;
277  }
278 
279  // Add all edges
280  for (std::multimap<uint32_t, uint32_t>::const_iterator sv_neighbors_itr = label_adjaceny_arg.begin (); sv_neighbors_itr != label_adjaceny_arg.end ();
281  ++sv_neighbors_itr)
282  {
283  const uint32_t& sv_label = sv_neighbors_itr->first;
284  const uint32_t& neighbor_label = sv_neighbors_itr->second;
285 
286  VertexID u = label_ID_map[sv_label];
287  VertexID v = label_ID_map[neighbor_label];
288 
289  boost::add_edge (u, v, sv_adjacency_list_);
290  }
291 
292  // Initialization
293  // clear the processed_ map
294  seg_label_to_sv_list_map_.clear ();
295  for (typename std::map<uint32_t, typename pcl::Supervoxel<PointT>::Ptr>::iterator svlabel_itr = sv_label_to_supervoxel_map_.begin ();
296  svlabel_itr != sv_label_to_supervoxel_map_.end (); ++svlabel_itr)
297  {
298  const uint32_t& sv_label = svlabel_itr->first;
299  processed_[sv_label] = false;
300  sv_label_to_seg_label_map_[sv_label] = 0;
301  }
302 }
303 
304 
305 
306 
307 template <typename PointT> void
309 {
310  // clear the processed_ map
311  seg_label_to_sv_list_map_.clear ();
312  for (typename std::map<uint32_t, typename pcl::Supervoxel<PointT>::Ptr>::iterator svlabel_itr = sv_label_to_supervoxel_map_.begin ();
313  svlabel_itr != sv_label_to_supervoxel_map_.end (); ++svlabel_itr)
314  {
315  const uint32_t& sv_label = svlabel_itr->first;
316  processed_[sv_label] = false;
317  sv_label_to_seg_label_map_[sv_label] = 0;
318  }
319 
320  // Perform depth search on the graph and recursively group all supervoxels with convex connections
321  //The vertices in the supervoxel adjacency list are the supervoxel centroids
322  std::pair< VertexIterator, VertexIterator> vertex_iterator_range;
323  vertex_iterator_range = boost::vertices (sv_adjacency_list_);
324 
325  // Note: *sv_itr is of type " boost::graph_traits<VoxelAdjacencyList>::vertex_descriptor " which it nothing but a typedef of size_t..
326  unsigned int segment_label = 1; // This starts at 1, because 0 is reserved for errors
327  for (VertexIterator sv_itr = vertex_iterator_range.first; sv_itr != vertex_iterator_range.second; ++sv_itr) // For all supervoxels
328  {
329  const VertexID sv_vertex_id = *sv_itr;
330  const uint32_t& sv_label = sv_adjacency_list_[sv_vertex_id];
331  if (!processed_[sv_label])
332  {
333  // Add neighbors (and their neighbors etc.) to group if similarity constraint is met
334  recursiveSegmentGrowing (sv_vertex_id, segment_label);
335  ++segment_label; // After recursive grouping ended (no more neighbors to consider) -> go to next group
336  }
337  }
338 }
339 
340 template <typename PointT> void
342  const unsigned int segment_label)
343 {
344  const uint32_t& sv_label = sv_adjacency_list_[query_point_id];
345 
346  processed_[sv_label] = true;
347 
348  // The next two lines add the supervoxel to the segment
349  sv_label_to_seg_label_map_[sv_label] = segment_label;
350  seg_label_to_sv_list_map_[segment_label].insert (sv_label);
351 
352  // Iterate through all neighbors of this supervoxel and check whether they should be merged with the current supervoxel
353  std::pair<OutEdgeIterator, OutEdgeIterator> out_edge_iterator_range;
354  out_edge_iterator_range = boost::out_edges (query_point_id, sv_adjacency_list_); // adjacent vertices to node (*itr) in graph sv_adjacency_list_
355  for (OutEdgeIterator out_Edge_itr = out_edge_iterator_range.first; out_Edge_itr != out_edge_iterator_range.second; ++out_Edge_itr)
356  {
357  const VertexID neighbor_ID = boost::target (*out_Edge_itr, sv_adjacency_list_);
358  const uint32_t& neighbor_label = sv_adjacency_list_[neighbor_ID];
359 
360  if (!processed_[neighbor_label]) // If neighbor was not already processed
361  {
362  if (sv_adjacency_list_[*out_Edge_itr].is_valid)
363  {
364  recursiveSegmentGrowing (neighbor_ID, segment_label);
365  }
366  }
367  } // End neighbor loop
368 }
369 
370 template <typename PointT> void
372 {
373  if (k_arg == 0)
374  return;
375 
376  bool is_convex;
377  unsigned int kcount = 0;
378 
379  EdgeIterator edge_itr, edge_itr_end, next_edge;
380  boost::tie (edge_itr, edge_itr_end) = boost::edges (sv_adjacency_list_);
381 
382  std::pair<OutEdgeIterator, OutEdgeIterator> source_neighbors_range;
383  std::pair<OutEdgeIterator, OutEdgeIterator> target_neighbors_range;
384 
385  // Check all edges in the graph for k-convexity
386  for (next_edge = edge_itr; edge_itr != edge_itr_end; edge_itr = next_edge)
387  {
388  next_edge++; // next_edge iterator is necessary, because removing an edge invalidates the iterator to the current edge
389 
390  is_convex = sv_adjacency_list_[*edge_itr].is_convex;
391 
392  if (is_convex) // If edge is (0-)convex
393  {
394  kcount = 0;
395 
396  const VertexID source = boost::source (*edge_itr, sv_adjacency_list_);
397  const VertexID target = boost::target (*edge_itr, sv_adjacency_list_);
398 
399  source_neighbors_range = boost::out_edges (source, sv_adjacency_list_);
400  target_neighbors_range = boost::out_edges (target, sv_adjacency_list_);
401 
402  // Find common neighbors, check their connection
403  for (OutEdgeIterator source_neighbors_itr = source_neighbors_range.first; source_neighbors_itr != source_neighbors_range.second; ++source_neighbors_itr) // For all supervoxels
404  {
405  VertexID source_neighbor_ID = boost::target (*source_neighbors_itr, sv_adjacency_list_);
406 
407  for (OutEdgeIterator target_neighbors_itr = target_neighbors_range.first; target_neighbors_itr != target_neighbors_range.second; ++target_neighbors_itr) // For all supervoxels
408  {
409  VertexID target_neighbor_ID = boost::target (*target_neighbors_itr, sv_adjacency_list_);
410  if (source_neighbor_ID == target_neighbor_ID) // Common neighbor
411  {
412  EdgeID src_edge = boost::edge (source, source_neighbor_ID, sv_adjacency_list_).first;
413  EdgeID tar_edge = boost::edge (target, source_neighbor_ID, sv_adjacency_list_).first;
414 
415  bool src_is_convex = (sv_adjacency_list_)[src_edge].is_convex;
416  bool tar_is_convex = (sv_adjacency_list_)[tar_edge].is_convex;
417 
418  if (src_is_convex && tar_is_convex)
419  ++kcount;
420 
421  break;
422  }
423  }
424 
425  if (kcount >= k_arg) // Connection is k-convex, stop search
426  break;
427  }
428 
429  // Check k convexity
430  if (kcount < k_arg)
431  (sv_adjacency_list_)[*edge_itr].is_valid = false;
432  }
433  }
434 }
435 
436 template <typename PointT> void
438 {
439  bool is_convex;
440 
441  EdgeIterator edge_itr, edge_itr_end, next_edge;
442  boost::tie (edge_itr, edge_itr_end) = boost::edges (adjacency_list_arg);
443 
444  for (next_edge = edge_itr; edge_itr != edge_itr_end; edge_itr = next_edge)
445  {
446  next_edge++; // next_edge iterator is necessary, because removing an edge invalidates the iterator to the current edge
447 
448  uint32_t source_sv_label = adjacency_list_arg[boost::source (*edge_itr, adjacency_list_arg)];
449  uint32_t target_sv_label = adjacency_list_arg[boost::target (*edge_itr, adjacency_list_arg)];
450 
451  float normal_difference;
452  is_convex = connIsConvex (source_sv_label, target_sv_label, normal_difference);
453  adjacency_list_arg[*edge_itr].is_convex = is_convex;
454  adjacency_list_arg[*edge_itr].is_valid = is_convex;
455  adjacency_list_arg[*edge_itr].normal_difference = normal_difference;
456  }
457 }
458 
459 template <typename PointT> bool
460 pcl::LCCPSegmentation<PointT>::connIsConvex (const uint32_t source_label_arg,
461  const uint32_t target_label_arg,
462  float &normal_angle)
463 {
464  typename pcl::Supervoxel<PointT>::Ptr& sv_source = sv_label_to_supervoxel_map_[source_label_arg];
465  typename pcl::Supervoxel<PointT>::Ptr& sv_target = sv_label_to_supervoxel_map_[target_label_arg];
466 
467  const Eigen::Vector3f& source_centroid = sv_source->centroid_.getVector3fMap ();
468  const Eigen::Vector3f& target_centroid = sv_target->centroid_.getVector3fMap ();
469 
470  const Eigen::Vector3f& source_normal = sv_source->normal_.getNormalVector3fMap (). normalized ();
471  const Eigen::Vector3f& target_normal = sv_target->normal_.getNormalVector3fMap (). normalized ();
472 
473  //NOTE For angles below 0 nothing will be merged
475  {
476  return (false);
477  }
478 
479  bool is_convex = true;
480  bool is_smooth = true;
481 
482  normal_angle = getAngle3D (source_normal, target_normal, true);
483  // Geometric comparisons
484  Eigen::Vector3f vec_t_to_s, vec_s_to_t;
485 
486  vec_t_to_s = source_centroid - target_centroid;
487  vec_s_to_t = -vec_t_to_s;
488 
489  Eigen::Vector3f ncross;
490  ncross = source_normal.cross (target_normal);
491 
492  // Smoothness Check: Check if there is a step between adjacent patches
494  {
495  float expected_distance = ncross.norm () * seed_resolution_;
496  float dot_p_1 = vec_t_to_s.dot (source_normal);
497  float dot_p_2 = vec_s_to_t.dot (target_normal);
498  float point_dist = (std::fabs (dot_p_1) < std::fabs (dot_p_2)) ? std::fabs (dot_p_1) : std::fabs (dot_p_2);
499  const float dist_smoothing = smoothness_threshold_ * voxel_resolution_; // This is a slacking variable especially important for patches with very similar normals
500 
501  if (point_dist > (expected_distance + dist_smoothing))
502  {
503  is_smooth &= false;
504  }
505  }
506  // ----------------
507 
508  // Sanity Criterion: Check if definition convexity/concavity makes sense for connection of given patches
509  float intersection_angle = getAngle3D (ncross, vec_t_to_s, true);
510  float min_intersect_angle = (intersection_angle < 90.) ? intersection_angle : 180. - intersection_angle;
511 
512  float intersect_thresh = 60. * 1. / (1. + exp (-0.25 * (normal_angle - 25.)));
513  if (min_intersect_angle < intersect_thresh && use_sanity_check_)
514  {
515  // std::cout << "Concave/Convex not defined for given case!" << std::endl;
516  is_convex &= false;
517  }
518 
519 
520  // vec_t_to_s is the reference direction for angle measurements
521  // Convexity Criterion: Check if connection of patches is convex. If this is the case the two supervoxels should be merged.
522  if ((getAngle3D (vec_t_to_s, source_normal) - getAngle3D (vec_t_to_s, target_normal)) <= 0)
523  {
524  is_convex &= true; // connection convex
525  }
526  else
527  {
528  is_convex &= (normal_angle < concavity_tolerance_threshold_); // concave connections will be accepted if difference of normals is small
529  }
530  return (is_convex && is_smooth);
531 }
532 
533 #endif // PCL_SEGMENTATION_IMPL_LCCP_SEGMENTATION_HPP_
std::map< uint32_t, bool > processed_
Stores which supervoxel labels were already visited during recursive grouping.
bool use_smoothness_check_
Determines if the smoothness check is used during segmentation.
std::map< uint32_t, std::set< uint32_t > > seg_label_to_neighbor_set_map_
map < SegmentID, std::set< Neighboring segment labels> >
void doGrouping()
Perform depth search on the graph and recursively group all supervoxels with convex connections...
void computeSegmentAdjacency()
Compute the adjacency of the segments.
void relabelCloud(pcl::PointCloud< pcl::PointXYZL > &labeled_cloud_arg)
Relabels cloud with supervoxel labels with the computed segment labels.
double getAngle3D(const Eigen::Vector4f &v1, const Eigen::Vector4f &v2, const bool in_degree=false)
Compute the smallest angle between two 3D vectors in radians (default) or degree. ...
Definition: common.hpp:46
bool use_sanity_check_
Determines if we use the sanity check which tries to find and invalidate singular connected patches...
boost::graph_traits< SupervoxelAdjacencyList >::vertex_iterator VertexIterator
pcl::PointXYZRGBA centroid_
The centroid of the supervoxel - average voxel.
iterator end()
Definition: point_cloud.h:443
pcl::Normal normal_
The normal calculated for the voxels contained in the supervoxel.
float voxel_resolution_
Voxel resolution used to build the supervoxels (used only for smoothness check)
uint32_t min_segment_size_
Minimum segment size.
VectorType::iterator iterator
Definition: point_cloud.h:440
uint32_t k_factor_
Factor used for k-convexity.
std::map< uint32_t, std::set< uint32_t > > seg_label_to_sv_list_map_
map <Segment Label, std::set <SuperVoxel labels>=""> >
std::map< uint32_t, typename pcl::Supervoxel< PointT >::Ptr > sv_label_to_supervoxel_map_
map from the supervoxel labels to the supervoxel objects
void prepareSegmentation(const std::map< uint32_t, typename pcl::Supervoxel< PointT >::Ptr > &supervoxel_clusters_arg, const std::multimap< uint32_t, uint32_t > &label_adjacency_arg)
Is called within setInputSupervoxels mainly to reserve required memory.
float seed_resolution_
Seed resolution of the supervoxels (used only for smoothness check)
boost::adjacency_list< boost::setS, boost::setS, boost::undirectedS, uint32_t, EdgeProperties > SupervoxelAdjacencyList
boost::graph_traits< SupervoxelAdjacencyList >::edge_iterator EdgeIterator
float smoothness_threshold_
Two supervoxels are unsmooth if their plane-to-plane distance DIST > (expected_distance + smoothness_...
void reset()
Reset internal memory.
boost::graph_traits< SupervoxelAdjacencyList >::adjacency_iterator AdjacencyIterator
bool supervoxels_set_
Marks if supervoxels have been set by calling setInputSupervoxels.
boost::graph_traits< SupervoxelAdjacencyList >::vertex_descriptor VertexID
void mergeSmallSegments()
Segments smaller than min_segment_size_ are merged to the label of largest neighbor.
PointCloud represents the base class in PCL for storing collections of 3D points. ...
boost::graph_traits< SupervoxelAdjacencyList >::edge_descriptor EdgeID
void segment()
Merge supervoxels using local convexity.
void recursiveSegmentGrowing(const VertexID &queryPointID, const unsigned int group_label)
Assigns neighbors of the query point to the same group as the query point.
iterator begin()
Definition: point_cloud.h:442
boost::graph_traits< SupervoxelAdjacencyList >::out_edge_iterator OutEdgeIterator
std::map< uint32_t, uint32_t > sv_label_to_seg_label_map_
Storing relation between original SuperVoxel Labels and new segmantion labels.
boost::shared_ptr< Supervoxel< PointT > > Ptr
float concavity_tolerance_threshold_
*** Parameters *** ///
void calculateConvexConnections(SupervoxelAdjacencyList &adjacency_list_arg)
Calculates convexity of edges and saves this to the adjacency graph.
void applyKconvexity(const unsigned int k_arg)
Connections are only convex if this is true for at least k_arg common neighbors of the two patches...
bool grouping_data_valid_
Marks if valid grouping data (sv_adjacency_list_, sv_label_to_seg_label_map_, processed_) is availabl...
SupervoxelAdjacencyList sv_adjacency_list_
Adjacency graph with the supervoxel labels as nodes and edges between adjacent supervoxels.
bool connIsConvex(const uint32_t source_label_arg, const uint32_t target_label_arg, float &normal_angle)
Returns true if the connection between source and target is convex.