Point Cloud Library (PCL)  1.9.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 Iterations 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_
pcl::CPCSegmentation
A segmentation algorithm partitioning a supervoxel graph.
Definition: cpc_segmentation.h:68
pcl
This file defines compatibility wrappers for low level I/O functions.
Definition: convolution.h:45
point_types.h
pcl::LCCPSegmentation
A simple segmentation algorithm partitioning a supervoxel graph into groups of locally convex connect...
Definition: lccp_segmentation.h:59
pcl::LCCPSegmentation::EdgeIterator
boost::graph_traits< SupervoxelAdjacencyList >::edge_iterator EdgeIterator
Definition: lccp_segmentation.h:90
pcl::LCCPSegmentation::supervoxels_set_
bool supervoxels_set_
Marks if supervoxels have been set by calling setInputSupervoxels.
Definition: lccp_segmentation.h:308
pcl::LCCPSegmentation::EdgeID
boost::graph_traits< SupervoxelAdjacencyList >::edge_descriptor EdgeID
Definition: lccp_segmentation.h:92
pcl::LCCPSegmentation::mergeSmallSegments
void mergeSmallSegments()
Segments smaller than min_segment_size_ are merged to the label of largest neighbor.
Definition: lccp_segmentation.hpp:171
pcl::CPCSegmentation::~CPCSegmentation
virtual ~CPCSegmentation()
Definition: cpc_segmentation.hpp:55
pcl::PointXYZINormal
A point structure representing Euclidean xyz coordinates, intensity, together with normal coordinates...
Definition: point_types.hpp:981
pcl::LCCPSegmentation::concavity_tolerance_threshold_
float concavity_tolerance_threshold_
*** Parameters *** ///
Definition: lccp_segmentation.h:302
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:371
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:305
pcl::LCCPSegmentation::sv_label_to_seg_label_map_
std::map< uint32_t, uint32_t > sv_label_to_seg_label_map_
Storing relation between original SuperVoxel Labels and new segmantion labels.
Definition: lccp_segmentation.h:343
pcl::LCCPSegmentation::calculateConvexConnections
void calculateConvexConnections(SupervoxelAdjacencyList &adjacency_list_arg)
Calculates convexity of edges and saves this to the adjacency graph.
Definition: lccp_segmentation.hpp:437
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:336
pcl::LCCPSegmentation::doGrouping
void doGrouping()
Perform depth search on the graph and recursively group all supervoxels with convex connections.
Definition: lccp_segmentation.hpp:308
pcl::CPCSegmentation::setCutting
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.
Definition: cpc_segmentation.h:109
pcl::SampleConsensus< WeightSACPointType >::sac_model_
SampleConsensusModelPtr sac_model_
The underlying data model used (i.e.
Definition: sac.h:310
pcl::CPCSegmentation::setRANSACIterations
void setRANSACIterations(const uint32_t ransac_iterations)
Set the number of iterations for the weighted RANSAC step (best cut estimations)
Definition: cpc_segmentation.h:127
pcl::LCCPSegmentation::k_factor_
uint32_t k_factor_
Factor used for k-convexity.
Definition: lccp_segmentation.h:326
pcl::LCCPSegmentation::sv_label_to_supervoxel_map_
std::map< 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:339
pcl::SampleConsensusModel
SampleConsensusModel represents the base model class.
Definition: sac_model.h:66
pcl::SampleConsensus
SampleConsensus represents the base class.
Definition: sac.h:56
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:320
pcl::SampleConsensus< WeightSACPointType >::max_iterations_
int max_iterations_
Maximum number of iterations before giving up.
Definition: sac.h:331