Point Cloud Library (PCL) 1.13.1
Loading...
Searching...
No Matches
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
54namespace 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:
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
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...