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