Point Cloud Library (PCL)  1.8.1
cpc_segmentation.h
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_CPC_SEGMENTATION_H_
39 #define PCL_SEGMENTATION_CPC_SEGMENTATION_H_
40 
41 // common includes
42 #include <pcl/pcl_base.h>
43 #include <pcl/point_types.h>
44 #include <pcl/point_cloud.h>
45 
46 // segmentation and sample consensus includes
47 #include <pcl/segmentation/supervoxel_clustering.h>
48 #include <pcl/segmentation/lccp_segmentation.h>
49 #include <pcl/sample_consensus/sac.h>
50 
51 #include <pcl/sample_consensus/sac_model_plane.h>
52 #include <pcl/segmentation/extract_clusters.h>
53 
54 #define PCL_INSTANTIATE_CPCSegmentation(T) template class PCL_EXPORTS pcl::CPCSegmentation<T>;
55 
56 namespace pcl
57 {
58  /** \brief A segmentation algorithm partitioning a supervoxel graph. It uses planar cuts induced by local concavities for the recursive segmentation. Cuts are estimated using locally constrained directed RANSAC.
59  * \note If you use this in a scientific work please cite the following paper:
60  * M. Schoeler, J. Papon, F. Woergoetter
61  * Constrained Planar Cuts - Object Partitioning for Point Clouds
62  * In Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition (CVPR) 2015
63  * Inherits most of its functionality from \ref LCCPSegmentation
64  * \author Markus Schoeler (mschoeler@web.de)
65  * \ingroup segmentation
66  */
67  template <typename PointT>
68  class CPCSegmentation : public LCCPSegmentation<PointT>
69  {
72  // LCCP typedefs
73  typedef typename LCCP::EdgeID EdgeID;
74  typedef typename LCCP::EdgeIterator EdgeIterator;
75  // LCCP methods
78  using LCCP::doGrouping;
80  // LCCP variables
82  using LCCP::k_factor_;
89 
90  public:
91  CPCSegmentation ();
92  virtual
94 
95  /** \brief Merge supervoxels using cuts through local convexities. The input parameters are generated by using the \ref SupervoxelClustering class. To retrieve the output use the \ref relabelCloud method.
96  * \note There are three ways to retrieve the segmentation afterwards (inherited from \ref LCCPSegmentation): \ref relabelCloud, \ref getSegmentSupervoxelMap and \ref getSupervoxelSegmentMap*/
97  void
98  segment ();
99 
100  /** \brief Determines if we want to use cutting planes
101  * \param[in] max_cuts Maximum number of cuts
102  * \param[in] cutting_min_segments Minimum segment size for cutting
103  * \param[in] cutting_min_score Minimum score a proposed cut has to achieve for being performed
104  * \param[in] locally_constrained Decide if we constrain our cuts locally
105  * \param[in] directed_cutting Decide if we prefer cuts perpendicular to the edge-direction
106  * \param[in] clean_cutting Decide if we cut only edges with supervoxels on opposite sides of the plane (clean) or all edges within the seed_resolution_ distance to the plane (not clean). The later was used in the paper.
107  */
108  inline void
109  setCutting (const uint32_t max_cuts = 20,
110  const uint32_t cutting_min_segments = 0,
111  const float cutting_min_score = 0.16,
112  const bool locally_constrained = true,
113  const bool directed_cutting = true,
114  const bool clean_cutting = false)
115  {
116  max_cuts_ = max_cuts;
117  min_segment_size_for_cutting_ = cutting_min_segments;
118  min_cut_score_ = cutting_min_score;
119  use_local_constrains_ = locally_constrained;
120  use_directed_weights_ = directed_cutting;
121  use_clean_cutting_ = clean_cutting;
122  }
123 
124  /** \brief Set the number of iterations for the weighted RANSAC step (best cut estimations)
125  * \param[in] ransac_iterations The number of iterations */
126  inline void
127  setRANSACIterations (const uint32_t ransac_iterations)
128  {
129  ransac_itrs_ = ransac_iterations;
130  }
131 
132  private:
133 
134  /** \brief Used in for CPC to find and fit cutting planes to the pointcloud.
135  * \note Is used recursively
136  * \param[in] depth_levels_left When first calling the function set this parameter to the maximum levels you want to cut down */
137  void
138  applyCuttingPlane (uint32_t depth_levels_left);
139 
140  /// *** Parameters *** ///
141 
142  /** \brief Maximum number of cuts */
143  uint32_t max_cuts_;
144 
145  /** \brief Minimum segment size for cutting */
146  uint32_t min_segment_size_for_cutting_;
147 
148  /** \brief Cut_score threshold */
149  float min_cut_score_;
150 
151  /** \brief Use local constrains for cutting */
152  bool use_local_constrains_;
153 
154  /** \brief Use directed weights for the cutting */
155  bool use_directed_weights_;
156 
157  /** \brief Use clean cutting */
158  bool use_clean_cutting_;
159 
160  /** \brief Interations for RANSAC */
161  uint32_t ransac_itrs_;
162 
163 
164 /******************************************* Directional weighted RANSAC declarations ******************************************************************/
165  /** \brief @b WeightedRandomSampleConsensus represents an implementation of the Directionally Weighted RANSAC algorithm, as described in: "Constrained Planar Cuts - Part Segmentation for Point Clouds", CVPR 2015, M. Schoeler, J. Papon, F. Wörgötter.
166  * \note It only uses points with a weight > 0 for the model calculation, but uses all points for the evaluation (scoring of the model)
167  * Only use in conjunction with sac_model_plane
168  * If you use this in a scientific work please cite the following paper:
169  * M. Schoeler, J. Papon, F. Woergoetter
170  * Constrained Planar Cuts - Object Partitioning for Point Clouds
171  * In Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition (CVPR) 2015
172  * \author Markus Schoeler (mschoeler@web.de)
173  * \ingroup segmentation
174  */
175 
176  class WeightedRandomSampleConsensus : public SampleConsensus<WeightSACPointType>
177  {
178  typedef typename SampleConsensusModel<WeightSACPointType>::Ptr SampleConsensusModelPtr;
179 
180  public:
181  typedef boost::shared_ptr<WeightedRandomSampleConsensus> Ptr;
182  typedef boost::shared_ptr<const WeightedRandomSampleConsensus> ConstPtr;
183 
184  /** \brief WeightedRandomSampleConsensus (Weighted RAndom SAmple Consensus) main constructor
185  * \param[in] model a Sample Consensus model
186  * \param[in] random if true set the random seed to the current time, else set to 12345 (default: false)
187  */
188  WeightedRandomSampleConsensus (const SampleConsensusModelPtr &model,
189  bool random = false)
190  : SampleConsensus<WeightSACPointType> (model, random)
191  {
192  initialize ();
193  }
194 
195  /** \brief WeightedRandomSampleConsensus (Weighted RAndom SAmple Consensus) main constructor
196  * \param[in] model a Sample Consensus model
197  * \param[in] threshold distance to model threshold
198  * \param[in] random if true set the random seed to the current time, else set to 12345 (default: false)
199  */
200  WeightedRandomSampleConsensus (const SampleConsensusModelPtr &model,
201  double threshold,
202  bool random = false)
203  : SampleConsensus<WeightSACPointType> (model, threshold, random)
204  {
205  initialize ();
206  }
207 
208  /** \brief Compute the actual model and find the inliers
209  * \param[in] debug_verbosity_level enable/disable on-screen debug information and set the verbosity level
210  */
211  bool
212  computeModel (int debug_verbosity_level = 0);
213 
214  /** \brief Set the weights for the input points
215  * \param[in] weights Weights for input samples. Negative weights are counted as penalty.
216  */
217  void
218  setWeights (const std::vector<double> &weights,
219  const bool directed_weights = false)
220  {
221  if (weights.size () != full_cloud_pt_indices_->size ())
222  {
223  PCL_ERROR ("[pcl::WeightedRandomSampleConsensus::setWeights] Cannot assign weights. Weight vector needs to have the same length as the input pointcloud\n");
224  return;
225  }
226  weights_ = weights;
227  model_pt_indices_->clear ();
228  for (size_t i = 0; i < weights.size (); ++i)
229  {
230  if (weights[i] > std::numeric_limits<double>::epsilon ())
231  model_pt_indices_->push_back (i);
232  }
233  use_directed_weights_ = directed_weights;
234  }
235 
236  /** \brief Get the best score
237  * \returns The best score found.
238  */
239  double
240  getBestScore () const
241  {
242  return (best_score_);
243  }
244 
245  protected:
246  /** \brief Initialize the model parameters. Called by the constructors. */
247  void
248  initialize ()
249  {
250  // Maximum number of trials before we give up.
251  max_iterations_ = 10000;
252  use_directed_weights_ = false;
253  model_pt_indices_ = boost::shared_ptr<std::vector<int> > (new std::vector<int> ());
254  full_cloud_pt_indices_.reset (new std::vector<int> (* (sac_model_->getIndices ())));
255  point_cloud_ptr_ = sac_model_->getInputCloud ();
256  }
257 
258  /** \brief weight each positive weight point by the inner product between the normal and the plane normal */
259  bool use_directed_weights_;
260 
261  /** \brief vector of weights assigned to points. Set by the setWeights-method */
262  std::vector<double> weights_;
263 
264  /** \brief The indices used for estimating the RANSAC model. Only those whose weight is > 0 */
265  boost::shared_ptr<std::vector<int> > model_pt_indices_;
266 
267  /** \brief The complete list of indices used for the model evaluation */
268  boost::shared_ptr<std::vector<int> > full_cloud_pt_indices_;
269 
270  /** \brief Pointer to the input PointCloud */
271  boost::shared_ptr<const pcl::PointCloud<WeightSACPointType> > point_cloud_ptr_;
272 
273  /** \brief Highest score found so far */
274  double best_score_;
275  };
276 
277  };
278 }
279 
280 #ifdef PCL_NO_PRECOMPILE
281  #include <pcl/segmentation/impl/cpc_segmentation.hpp>
282 #elif defined(PCL_ONLY_CORE_POINT_TYPES)
283  //pcl::PointXYZINormal is not a core point type (so we cannot use the precompiled classes here)
284  #include <pcl/sample_consensus/impl/sac_model_plane.hpp>
285  #include <pcl/segmentation/impl/extract_clusters.hpp>
286 #endif // PCL_NO_PRECOMPILE / PCL_ONLY_CORE_POINT_TYPES
287 
288 #endif // PCL_SEGMENTATION_CPC_SEGMENTATION_H_
A simple segmentation algorithm partitioning a supervoxel graph into groups of locally convex connect...
void doGrouping()
Perform depth search on the graph and recursively group all supervoxels with convex connections...
void segment()
Merge supervoxels using cuts through local convexities.
A segmentation algorithm partitioning a supervoxel graph.
void setRANSACIterations(const uint32_t ransac_iterations)
Set the number of iterations for the weighted RANSAC step (best cut estimations)
uint32_t k_factor_
Factor used for k-convexity.
std::map< uint32_t, typename pcl::Supervoxel< PointT >::Ptr > sv_label_to_supervoxel_map_
map from the supervoxel labels to the supervoxel objects
SampleConsensusModel represents the base model class.
Definition: sac_model.h:66
float seed_resolution_
Seed resolution of the supervoxels (used only for smoothness check)
Defines all the PCL implemented PointT point type structures.
A point structure representing Euclidean xyz coordinates, intensity, together with normal coordinates...
boost::graph_traits< SupervoxelAdjacencyList >::edge_iterator EdgeIterator
bool supervoxels_set_
Marks if supervoxels have been set by calling setInputSupervoxels.
void mergeSmallSegments()
Segments smaller than min_segment_size_ are merged to the label of largest neighbor.
boost::graph_traits< SupervoxelAdjacencyList >::edge_descriptor EdgeID
void setCutting(const uint32_t max_cuts=20, const uint32_t cutting_min_segments=0, const float cutting_min_score=0.16, const bool locally_constrained=true, const bool directed_cutting=true, const bool clean_cutting=false)
Determines if we want to use cutting planes.
std::map< uint32_t, uint32_t > sv_label_to_seg_label_map_
Storing relation between original SuperVoxel Labels and new segmantion labels.
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 avaiable...
SampleConsensus represents the base class.
Definition: sac.h:56
SupervoxelAdjacencyList sv_adjacency_list_
Adjacency graph with the supervoxel labels as nodes and edges between adjacent supervoxels.