Point Cloud Library (PCL)  1.11.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 
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
pcl::CPCSegmentation
A segmentation algorithm partitioning a supervoxel graph.
Definition: cpc_segmentation.h:66
pcl
Definition: convolution.h:46
point_types.h
pcl::IndicesPtr
shared_ptr< Indices > IndicesPtr
Definition: pcl_base.h:58
pcl::LCCPSegmentation::sv_label_to_seg_label_map_
std::map< std::uint32_t, std::uint32_t > sv_label_to_seg_label_map_
Storing relation between original SuperVoxel Labels and new segmantion labels.
Definition: lccp_segmentation.h:341
pcl::LCCPSegmentation
A simple segmentation algorithm partitioning a supervoxel graph into groups of locally convex connect...
Definition: lccp_segmentation.h:57
pcl::CPCSegmentation::setCutting
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.
Definition: cpc_segmentation.h:107
pcl::LCCPSegmentation::supervoxels_set_
bool supervoxels_set_
Marks if supervoxels have been set by calling setInputSupervoxels.
Definition: lccp_segmentation.h:306
pcl::LCCPSegmentation::mergeSmallSegments
void mergeSmallSegments()
Segments smaller than min_segment_size_ are merged to the label of largest neighbor.
Definition: lccp_segmentation.hpp:168
pcl::CPCSegmentation::~CPCSegmentation
~CPCSegmentation()
Definition: cpc_segmentation.hpp:56
pcl::PointXYZINormal
A point structure representing Euclidean xyz coordinates, intensity, together with normal coordinates...
Definition: point_types.hpp:1059
pcl::LCCPSegmentation::concavity_tolerance_threshold_
float concavity_tolerance_threshold_
*** Parameters *** ///
Definition: lccp_segmentation.h:300
pcl::LCCPSegmentation::applyKconvexity
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.
Definition: lccp_segmentation.hpp:355
pcl::LCCPSegmentation::grouping_data_valid_
bool grouping_data_valid_
Marks if valid grouping data (sv_adjacency_list_, sv_label_to_seg_label_map_, processed_) is availabl...
Definition: lccp_segmentation.h:303
pcl::CPCSegmentation::setRANSACIterations
void setRANSACIterations(const std::uint32_t ransac_iterations)
Set the number of iterations for the weighted RANSAC step (best cut estimations)
Definition: cpc_segmentation.h:125
pcl::LCCPSegmentation::calculateConvexConnections
void calculateConvexConnections(SupervoxelAdjacencyList &adjacency_list_arg)
Calculates convexity of edges and saves this to the adjacency graph.
Definition: lccp_segmentation.hpp:412
pcl::LCCPSegmentation::sv_adjacency_list_
SupervoxelAdjacencyList sv_adjacency_list_
Adjacency graph with the supervoxel labels as nodes and edges between adjacent supervoxels.
Definition: lccp_segmentation.h:334
pcl::LCCPSegmentation::doGrouping
void doGrouping()
Perform depth search on the graph and recursively group all supervoxels with convex connections.
Definition: lccp_segmentation.hpp:294
pcl::SampleConsensus< WeightSACPointType >::sac_model_
SampleConsensusModelPtr sac_model_
The underlying data model used (i.e.
Definition: sac.h:320
pcl::Indices
IndicesAllocator<> Indices
Type used for indices in PCL.
Definition: types.h:133
pcl::LCCPSegmentation::sv_label_to_supervoxel_map_
std::map< std::uint32_t, typename pcl::Supervoxel< PointT >::Ptr > sv_label_to_supervoxel_map_
map from the supervoxel labels to the supervoxel objects
Definition: lccp_segmentation.h:337
pcl::PointCloud::ConstPtr
shared_ptr< const PointCloud< PointT > > ConstPtr
Definition: point_cloud.h:408
pcl::LCCPSegmentation::k_factor_
std::uint32_t k_factor_
Factor used for k-convexity.
Definition: lccp_segmentation.h:324
pcl::SampleConsensusModel
SampleConsensusModel represents the base model class.
Definition: sac_model.h:69
pcl::SampleConsensus
SampleConsensus represents the base class.
Definition: sac.h:60
pcl::LCCPSegmentation::EdgeIterator
typename boost::graph_traits< SupervoxelAdjacencyList >::edge_iterator EdgeIterator
Definition: lccp_segmentation.h:88
pcl::CPCSegmentation::CPCSegmentation
CPCSegmentation()
Definition: cpc_segmentation.hpp:45
pcl::CPCSegmentation::segment
void segment()
Merge supervoxels using cuts through local convexities.
Definition: cpc_segmentation.hpp:61
pcl::LCCPSegmentation::seed_resolution_
float seed_resolution_
Seed resolution of the supervoxels (used only for smoothness check)
Definition: lccp_segmentation.h:318
pcl::SampleConsensus< WeightSACPointType >::max_iterations_
int max_iterations_
Maximum number of iterations before giving up.
Definition: sac.h:341
pcl::LCCPSegmentation::EdgeID
typename boost::graph_traits< SupervoxelAdjacencyList >::edge_descriptor EdgeID
Definition: lccp_segmentation.h:90