Point Cloud Library (PCL) 1.15.1-dev
Loading...
Searching...
No Matches
sample_consensus_prerejective.h
1/*
2 * Software License Agreement (BSD License)
3 *
4 * Point Cloud Library (PCL) - www.pointclouds.org
5 * Copyright (c) 2010-2012, Willow Garage, Inc.
6 * Copyright (c) 2012-, Open Perception, Inc.
7 *
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * * Redistributions in binary form must reproduce the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer in the documentation and/or other materials provided
19 * with the distribution.
20 * * Neither the name of the copyright holder(s) nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 *
37 * $Id$
38 *
39 */
40
41#pragma once
42
43#include <pcl/registration/correspondence_rejection_poly.h>
44#include <pcl/registration/registration.h>
45#include <pcl/registration/transformation_estimation_svd.h>
46#include <pcl/registration/transformation_validation.h>
47
48#ifdef _OPENMP
49#include <omp.h>
50#endif
51
52namespace pcl {
53/** \brief Pose estimation and alignment class using a prerejective RANSAC routine.
54 *
55 * This class inserts a simple, yet effective "prerejection" step into the standard
56 * RANSAC pose estimation loop in order to avoid verification of pose hypotheses
57 * that are likely to be wrong. This is achieved by local pose-invariant geometric
58 * constraints, as also implemented in the class
59 * \ref registration::CorrespondenceRejectorPoly "CorrespondenceRejectorPoly".
60 *
61 * In order to robustly align partial/occluded models, this routine performs
62 * fit error evaluation using only inliers, i.e. points closer than a
63 * Euclidean threshold, which is specifiable using \ref setInlierFraction().
64 *
65 * The amount of prerejection or "greedyness" of the algorithm can be specified
66 * using \ref setSimilarityThreshold() in [0,1[, where a value of 0 means disabled,
67 * and 1 is maximally rejective.
68 *
69 * If you use this in academic work, please cite:
70 *
71 * A. G. Buch, D. Kraft, J.-K. Kämäräinen, H. G. Petersen and N. Krüger.
72 * Pose Estimation using Local Structure-Specific Shape and Appearance Context.
73 * International Conference on Robotics and Automation (ICRA), 2013.
74 *
75 * \author Anders Glent Buch (andersgb1@gmail.com)
76 * \ingroup registration
77 */
78template <typename PointSource, typename PointTarget, typename FeatureT>
79class SampleConsensusPrerejective : public Registration<PointSource, PointTarget> {
80public:
82
83 using Registration<PointSource, PointTarget>::reg_name_;
84 using Registration<PointSource, PointTarget>::getClassName;
85 using Registration<PointSource, PointTarget>::input_;
86 using Registration<PointSource, PointTarget>::target_;
87 using Registration<PointSource, PointTarget>::tree_;
88 using Registration<PointSource, PointTarget>::max_iterations_;
89 using Registration<PointSource, PointTarget>::corr_dist_threshold_;
90 using Registration<PointSource, PointTarget>::transformation_;
91 using Registration<PointSource, PointTarget>::final_transformation_;
92 using Registration<PointSource, PointTarget>::transformation_estimation_;
93 using Registration<PointSource, PointTarget>::getFitnessScore;
94 using Registration<PointSource, PointTarget>::converged_;
95
98 using PointCloudSourcePtr = typename PointCloudSource::Ptr;
99 using PointCloudSourceConstPtr = typename PointCloudSource::ConstPtr;
100
103
106
110
111 using Ptr =
112 shared_ptr<SampleConsensusPrerejective<PointSource, PointTarget, FeatureT>>;
113 using ConstPtr =
114 shared_ptr<const SampleConsensusPrerejective<PointSource, PointTarget, FeatureT>>;
115
117
123
124 /** \brief Constructor */
137
138 /** \brief Destructor */
139 ~SampleConsensusPrerejective() override = default;
140
141 /** \brief Provide a boost shared pointer to the source point cloud's feature
142 * descriptors \param features the source point cloud's features
143 */
144 void
146
147 /** \brief Get a pointer to the source point cloud's features */
148 inline const FeatureCloudConstPtr
150 {
151 return (input_features_);
152 }
153
154 /** \brief Provide a boost shared pointer to the target point cloud's feature
155 * descriptors \param features the target point cloud's features
156 */
157 void
159
160 /** \brief Get a pointer to the target point cloud's features */
161 inline const FeatureCloudConstPtr
163 {
164 return (target_features_);
165 }
166
167 /** \brief Set the number of samples to use during each iteration
168 * \param nr_samples the number of samples to use during each iteration
169 */
170 inline void
171 setNumberOfSamples(int nr_samples)
172 {
173 nr_samples_ = nr_samples;
174 }
175
176 /** \brief Get the number of samples to use during each iteration, as set by the user
177 */
178 inline int
180 {
181 return (nr_samples_);
182 }
183
184 /** \brief Set the number of neighbors to use when selecting a random feature
185 * correspondence. A higher value will add more randomness to the feature matching.
186 * \param k the number of neighbors to use when selecting a random feature
187 * correspondence.
188 */
189 inline void
194
195 /** \brief Get the number of neighbors used when selecting a random feature
196 * correspondence, as set by the user */
197 inline int
199 {
200 return (k_correspondences_);
201 }
202
203 /** \brief Set the similarity threshold in [0,1[ between edge lengths of the
204 * underlying polygonal correspondence rejector object, where 1 is a perfect match
205 * \param similarity_threshold edge length similarity threshold
206 */
207 inline void
208 setSimilarityThreshold(float similarity_threshold)
209 {
210 correspondence_rejector_poly_->setSimilarityThreshold(similarity_threshold);
211 }
212
213 /** \brief Get the similarity threshold between edge lengths of the underlying
214 * polygonal correspondence rejector object, \return edge length similarity threshold
215 */
216 inline float
218 {
219 return correspondence_rejector_poly_->getSimilarityThreshold();
220 }
221
222 /** \brief Set the required inlier fraction (of the input)
223 * \param inlier_fraction required inlier fraction, must be in [0,1]
224 */
225 inline void
226 setInlierFraction(float inlier_fraction)
227 {
228 inlier_fraction_ = inlier_fraction;
229 }
230
231 /** \brief Get the required inlier fraction
232 * \return required inlier fraction in [0,1]
233 */
234 inline float
236 {
237 return inlier_fraction_;
238 }
239
240 /** \brief Get the inlier indices of the source point cloud under the final
241 * transformation
242 * @return inlier indices
243 */
244 inline const pcl::Indices&
246 {
247 return inliers_;
248 }
249
250 /** \brief Initialize the scheduler and set the number of threads to use.
251 * \param nr_threads the number of hardware threads to use (0 sets the value back to
252 * automatic)
253 */
254 void
255 setNumberOfThreads(unsigned int nr_threads = 0)
256 {
257#ifdef _OPENMP
258 if (nr_threads == 0)
259 num_threads_ = omp_get_num_procs();
260 else
261 num_threads_ = nr_threads;
262 PCL_DEBUG("[pcl::SampleConsensusPrerejective::setNumberOfThreads] Setting number "
263 "of threads to %u.\n",
265#else
266 num_threads_ = 1;
267 if (nr_threads != 1)
268 PCL_WARN("[pcl::SampleConsensusPrerejective::setNumberOfThreads] Parallelization "
269 "is requested, but OpenMP is not available! Continuing without "
270 "parallelization.\n");
271#endif // _OPENMP
272 }
273
274protected:
275 /** \brief Choose a random index between 0 and n-1
276 * \param n the number of possible indices to choose from
277 */
278 inline int
279 getRandomIndex(int n) const
280 {
281 return (static_cast<int>(n * (rand() / (RAND_MAX + 1.0))));
282 };
283
284 /** \brief Select \a nr_samples sample points from cloud while making sure that their
285 * pairwise distances are greater than a user-defined minimum distance, \a
286 * min_sample_distance. \param cloud the input point cloud \param nr_samples the
287 * number of samples to select \param sample_indices the resulting sample indices
288 */
289 void
290 selectSamples(const PointCloudSource& cloud,
291 int nr_samples,
292 pcl::Indices& sample_indices);
293
294 /** \brief For each of the sample points, find a list of points in the target cloud
295 * whose features are similar to the sample points' features. From these, select one
296 * randomly which will be considered that sample point's correspondence. \param
297 * sample_indices the indices of each sample point \param similar_features
298 * correspondence cache, which is used to read/write already computed correspondences
299 * \param corresponding_indices the resulting indices of each sample's corresponding
300 * point in the target cloud
301 */
302 void
303 findSimilarFeatures(const pcl::Indices& sample_indices,
304 std::vector<pcl::Indices>& similar_features,
305 pcl::Indices& corresponding_indices);
306
307 /** \brief Rigid transformation computation method.
308 * \param output the transformed input point cloud dataset using the rigid
309 * transformation found \param guess The computed transformation
310 */
311 void
313 const Eigen::Matrix4f& guess) override;
314
315 /** \brief Obtain the fitness of a transformation
316 * The following metrics are calculated, based on
317 * \b final_transformation_ and \b corr_dist_threshold_:
318 * - Inliers: the number of transformed points which are closer than threshold to NN
319 * - Error score: the MSE of the inliers
320 * \param inliers indices of source point cloud inliers
321 * \param fitness_score output fitness score as RMSE
322 */
323 void
324 getFitness(pcl::Indices& inliers, float& fitness_score);
325
326 /** \brief The source point cloud's feature descriptors. */
328
329 /** \brief The target point cloud's feature descriptors. */
331
332 /** \brief The number of samples to use during each iteration. */
334
335 /** \brief The number of neighbors to use when selecting a random feature
336 * correspondence. */
338
339 /** \brief The KdTree used to compare feature descriptors. */
341
342 /** \brief The polygonal correspondence rejector used for prerejection */
344
345 /** \brief The fraction [0,1] of inlier points required for accepting a transformation
346 */
347 float inlier_fraction_{0.0f};
348
349 /** \brief Inlier points of final transformation as indices into source */
351
352 /** \brief The number of threads the scheduler should use. */
353 unsigned int num_threads_{1};
354};
355} // namespace pcl
356
357#include <pcl/registration/impl/sample_consensus_prerejective.hpp>
PointCloudConstPtr input_
The input point cloud dataset.
Definition pcl_base.h:147
shared_ptr< PointCloud< FeatureT > > Ptr
shared_ptr< const PointCloud< FeatureT > > ConstPtr
Registration represents the base registration class for general purpose, ICP-like methods.
Matrix4 final_transformation_
The final transformation matrix estimated by the registration method after N iterations.
double corr_dist_threshold_
The maximum distance threshold between two correspondent points in source <-> target.
std::string reg_name_
The registration method name.
Matrix4 transformation_
The transformation matrix estimated by the registration method.
KdTreePtr tree_
A pointer to the spatial search object.
bool converged_
Holds internal convergence state, given user parameters.
Eigen::Matrix< Scalar, 4, 4 > Matrix4
TransformationEstimationPtr transformation_estimation_
A TransformationEstimation object, used to calculate the 4x4 rigid transformation.
int max_iterations_
The maximum number of iterations the internal optimization should run for.
double getFitnessScore(double max_range=std::numeric_limits< double >::max(), bool use_indices=false)
Obtain the Euclidean fitness score (e.g., mean of squared distances from the source to the target)
PointCloudTargetConstPtr target_
The input point cloud dataset target.
const std::string & getClassName() const
Abstract class get name method.
Pose estimation and alignment class using a prerejective RANSAC routine.
float getSimilarityThreshold() const
Get the similarity threshold between edge lengths of the underlying polygonal correspondence rejector...
shared_ptr< SampleConsensusPrerejective< PointSource, PointTarget, FeatureT > > Ptr
typename Registration< PointSource, PointTarget >::PointCloudTarget PointCloudTarget
float inlier_fraction_
The fraction [0,1] of inlier points required for accepting a transformation.
typename PointCloudSource::ConstPtr PointCloudSourceConstPtr
void setNumberOfThreads(unsigned int nr_threads=0)
Initialize the scheduler and set the number of threads to use.
unsigned int num_threads_
The number of threads the scheduler should use.
pcl::Indices inliers_
Inlier points of final transformation as indices into source.
float getInlierFraction() const
Get the required inlier fraction.
void setCorrespondenceRandomness(int k)
Set the number of neighbors to use when selecting a random feature correspondence.
const FeatureCloudConstPtr getSourceFeatures() const
Get a pointer to the source point cloud's features.
FeatureCloudConstPtr input_features_
The source point cloud's feature descriptors.
FeatureKdTreePtr feature_tree_
The KdTree used to compare feature descriptors.
void setTargetFeatures(const FeatureCloudConstPtr &features)
Provide a boost shared pointer to the target point cloud's feature descriptors.
void setInlierFraction(float inlier_fraction)
Set the required inlier fraction (of the input)
CorrespondenceRejectorPolyPtr correspondence_rejector_poly_
The polygonal correspondence rejector used for prerejection.
void computeTransformation(PointCloudSource &output, const Eigen::Matrix4f &guess) override
Rigid transformation computation method.
int getCorrespondenceRandomness() const
Get the number of neighbors used when selecting a random feature correspondence, as set by the user.
typename CorrespondenceRejectorPoly::ConstPtr CorrespondenceRejectorPolyConstPtr
const FeatureCloudConstPtr getTargetFeatures() const
Get a pointer to the target point cloud's features.
typename Registration< PointSource, PointTarget >::PointCloudSource PointCloudSource
typename FeatureCloud::ConstPtr FeatureCloudConstPtr
typename PointCloudSource::Ptr PointCloudSourcePtr
void setSimilarityThreshold(float similarity_threshold)
Set the similarity threshold in [0,1[ between edge lengths of the underlying polygonal correspondence...
void findSimilarFeatures(const pcl::Indices &sample_indices, std::vector< pcl::Indices > &similar_features, pcl::Indices &corresponding_indices)
For each of the sample points, find a list of points in the target cloud whose features are similar t...
void setSourceFeatures(const FeatureCloudConstPtr &features)
Provide a boost shared pointer to the source point cloud's feature descriptors.
FeatureCloudConstPtr target_features_
The target point cloud's feature descriptors.
void setNumberOfSamples(int nr_samples)
Set the number of samples to use during each iteration.
int getNumberOfSamples() const
Get the number of samples to use during each iteration, as set by the user.
typename pcl::search::Search< FeatureT >::Ptr FeatureKdTreePtr
~SampleConsensusPrerejective() override=default
Destructor.
void selectSamples(const PointCloudSource &cloud, int nr_samples, pcl::Indices &sample_indices)
Select nr_samples sample points from cloud while making sure that their pairwise distances are greate...
int getRandomIndex(int n) const
Choose a random index between 0 and n-1.
const pcl::Indices & getInliers() const
Get the inlier indices of the source point cloud under the final transformation.
int nr_samples_
The number of samples to use during each iteration.
typename Registration< PointSource, PointTarget >::Matrix4 Matrix4
typename CorrespondenceRejectorPoly::Ptr CorrespondenceRejectorPolyPtr
shared_ptr< const SampleConsensusPrerejective< PointSource, PointTarget, FeatureT > > ConstPtr
int k_correspondences_
The number of neighbors to use when selecting a random feature correspondence.
void getFitness(pcl::Indices &inliers, float &fitness_score)
Obtain the fitness of a transformation The following metrics are calculated, based on final_transform...
CorrespondenceRejectorPoly implements a correspondence rejection method that exploits low-level and p...
shared_ptr< const CorrespondenceRejectorPoly< SourceT, TargetT > > ConstPtr
shared_ptr< CorrespondenceRejectorPoly< SourceT, TargetT > > Ptr
TransformationEstimationSVD implements SVD-based estimation of the transformation aligning the given ...
shared_ptr< pcl::search::Search< PointT > > Ptr
Definition search.h:81
IndicesAllocator<> Indices
Type used for indices in PCL.
Definition types.h:133
shared_ptr< ::pcl::PointIndices > Ptr
shared_ptr< const ::pcl::PointIndices > ConstPtr