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