Point Cloud Library (PCL)  1.14.0-dev
correspondence_rejection.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2010-2011, 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/console/print.h>
44 #include <pcl/registration/correspondence_sorting.h>
45 #include <pcl/registration/correspondence_types.h>
46 #include <pcl/search/kdtree.h>
47 #include <pcl/point_cloud.h>
48 
49 namespace pcl {
50 namespace registration {
51 /** @b CorrespondenceRejector represents the base class for correspondence rejection
52  * methods \author Dirk Holz \ingroup registration
53  */
55 public:
56  using Ptr = shared_ptr<CorrespondenceRejector>;
57  using ConstPtr = shared_ptr<const CorrespondenceRejector>;
58 
59  /** \brief Empty constructor. */
61 
62  /** \brief Empty destructor. */
63  virtual ~CorrespondenceRejector() = default;
64 
65  /** \brief Provide a pointer to the vector of the input correspondences.
66  * \param[in] correspondences the const shared pointer to a correspondence vector
67  */
68  virtual inline void
70  {
71  input_correspondences_ = correspondences;
72  };
73 
74  /** \brief Get a pointer to the vector of the input correspondences.
75  * \return correspondences the const shared pointer to a correspondence vector
76  */
79  {
81  };
82 
83  /** \brief Run correspondence rejection
84  * \param[out] correspondences Vector of correspondences that have not been rejected.
85  */
86  inline void
88  {
90  return;
91 
92  applyRejection(correspondences);
93  }
94 
95  /** \brief Get a list of valid correspondences after rejection from the original set
96  * of correspondences. Pure virtual. Compared to \a getCorrespondences this function
97  * is stateless, i.e., input correspondences do not need to be provided beforehand,
98  * but are directly provided in the function call.
99  * \param[in] original_correspondences the set of initial correspondences given
100  * \param[out] remaining_correspondences the resultant filtered set of remaining
101  * correspondences
102  */
103  virtual inline void
104  getRemainingCorrespondences(const pcl::Correspondences& original_correspondences,
105  pcl::Correspondences& remaining_correspondences) = 0;
106 
107  /** \brief Determine the indices of query points of
108  * correspondences that have been rejected, i.e., the difference
109  * between the input correspondences (set via \a setInputCorrespondences)
110  * and the given correspondence vector.
111  * \param[in] correspondences Vector of correspondences after rejection
112  * \param[out] indices Vector of query point indices of those correspondences
113  * that have been rejected.
114  */
115  inline void
117  pcl::Indices& indices)
118  {
120  PCL_WARN("[pcl::registration::%s::getRejectedQueryIndices] Input correspondences "
121  "not set (lookup of rejected correspondences _not_ possible).\n",
122  getClassName().c_str());
123  return;
124  }
125 
126  pcl::getRejectedQueryIndices(*input_correspondences_, correspondences, indices);
127  }
128 
129  /** \brief Get a string representation of the name of this class. */
130  inline const std::string&
131  getClassName() const
132  {
133  return (rejection_name_);
134  }
135 
136  /** \brief See if this rejector requires source points */
137  virtual bool
139  {
140  return (false);
141  }
142 
143  /** \brief Abstract method for setting the source cloud */
144  virtual void
146  {
147  PCL_WARN("[pcl::registration::%s::setSourcePoints] This class does not require an "
148  "input source cloud\n",
149  getClassName().c_str());
150  }
151 
152  /** \brief See if this rejector requires source normals */
153  virtual bool
155  {
156  return (false);
157  }
158 
159  /** \brief Abstract method for setting the source normals */
160  virtual void
162  {
163  PCL_WARN("[pcl::registration::%s::setSourceNormals] This class does not require "
164  "input source normals\n",
165  getClassName().c_str());
166  }
167  /** \brief See if this rejector requires a target cloud */
168  virtual bool
170  {
171  return (false);
172  }
173 
174  /** \brief Abstract method for setting the target cloud */
175  virtual void
177  {
178  PCL_WARN("[pcl::registration::%s::setTargetPoints] This class does not require an "
179  "input target cloud\n",
180  getClassName().c_str());
181  }
182 
183  /** \brief See if this rejector requires target normals */
184  virtual bool
186  {
187  return (false);
188  }
189 
190  /** \brief Abstract method for setting the target normals */
191  virtual void
193  {
194  PCL_WARN("[pcl::registration::%s::setTargetNormals] This class does not require "
195  "input target normals\n",
196  getClassName().c_str());
197  }
198 
199 protected:
200  /** \brief The name of the rejection method. */
201  std::string rejection_name_{};
202 
203  /** \brief The input correspondences. */
205 
206  /** \brief Abstract rejection method. */
207  virtual void
208  applyRejection(Correspondences& correspondences) = 0;
209 };
210 
211 /** @b DataContainerInterface provides a generic interface for computing correspondence
212  * scores between correspondent points in the input and target clouds
213  * \ingroup registration
214  */
216 public:
217  using Ptr = shared_ptr<DataContainerInterface>;
218  using ConstPtr = shared_ptr<const DataContainerInterface>;
219 
220  virtual ~DataContainerInterface() = default;
221  virtual double
222  getCorrespondenceScore(int index) = 0;
223  virtual double
225  virtual double
227 };
228 
229 /** @b DataContainer is a container for the input and target point clouds and implements
230  * the interface to compute correspondence scores between correspondent points in the
231  * input and target clouds \ingroup registration
232  */
233 template <typename PointT, typename NormalT = pcl::PointNormal>
236  using PointCloudPtr = typename PointCloud::Ptr;
237  using PointCloudConstPtr = typename PointCloud::ConstPtr;
238 
239  using KdTreePtr = typename pcl::search::KdTree<PointT>::Ptr;
240 
242  using NormalsPtr = typename Normals::Ptr;
243  using NormalsConstPtr = typename Normals::ConstPtr;
244 
245 public:
246  /** \brief Empty constructor. */
247  DataContainer(bool needs_normals = false)
248  : input_()
249  , input_transformed_()
250  , target_()
251  , input_normals_()
252  , input_normals_transformed_()
253  , target_normals_()
254  , tree_(new pcl::search::KdTree<PointT>)
255  , class_name_("DataContainer")
256  , needs_normals_(needs_normals)
257  {}
258 
259  /** \brief Empty destructor */
260  ~DataContainer() override = default;
261 
262  /** \brief Provide a source point cloud dataset (must contain XYZ
263  * data!), used to compute the correspondence distance.
264  * \param[in] cloud a cloud containing XYZ data
265  */
266  inline void
267  setInputSource(const PointCloudConstPtr& cloud)
268  {
269  input_ = cloud;
270  }
271 
272  /** \brief Get a pointer to the input point cloud dataset target. */
273  inline PointCloudConstPtr const
275  {
276  return (input_);
277  }
278 
279  /** \brief Provide a target point cloud dataset (must contain XYZ
280  * data!), used to compute the correspondence distance.
281  * \param[in] target a cloud containing XYZ data
282  */
283  inline void
284  setInputTarget(const PointCloudConstPtr& target)
285  {
286  target_ = target;
287  target_cloud_updated_ = true;
288  }
289 
290  /** \brief Get a pointer to the input point cloud dataset target. */
291  inline PointCloudConstPtr const
293  {
294  return (target_);
295  }
296 
297  /** \brief Provide a pointer to the search object used to find correspondences in
298  * the target cloud.
299  * \param[in] tree a pointer to the spatial search object.
300  * \param[in] force_no_recompute If set to true, this tree will NEVER be
301  * recomputed, regardless of calls to setInputTarget. Only use if you are
302  * confident that the tree will be set correctly.
303  */
304  inline void
305  setSearchMethodTarget(const KdTreePtr& tree, bool force_no_recompute = false)
306  {
307  tree_ = tree;
308  force_no_recompute_ = force_no_recompute;
309  target_cloud_updated_ = true;
310  }
311 
312  /** \brief Set the normals computed on the input point cloud
313  * \param[in] normals the normals computed for the input cloud
314  */
315  inline void
316  setInputNormals(const NormalsConstPtr& normals)
317  {
318  input_normals_ = normals;
319  }
320 
321  /** \brief Get the normals computed on the input point cloud */
322  inline NormalsConstPtr
324  {
325  return (input_normals_);
326  }
327 
328  /** \brief Set the normals computed on the target point cloud
329  * \param[in] normals the normals computed for the input cloud
330  */
331  inline void
332  setTargetNormals(const NormalsConstPtr& normals)
333  {
334  target_normals_ = normals;
335  }
336 
337  /** \brief Get the normals computed on the target point cloud */
338  inline NormalsConstPtr
340  {
341  return (target_normals_);
342  }
343 
344  /** \brief Get the correspondence score for a point in the input cloud
345  * \param[in] index index of the point in the input cloud
346  */
347  inline double
348  getCorrespondenceScore(int index) override
349  {
350  if (target_cloud_updated_ && !force_no_recompute_) {
351  tree_->setInputCloud(target_);
352  }
353  pcl::Indices indices(1);
354  std::vector<float> distances(1);
355  if (tree_->nearestKSearch((*input_)[index], 1, indices, distances))
356  return (distances[0]);
357  return (std::numeric_limits<double>::max());
358  }
359 
360  /** \brief Get the correspondence score for a given pair of correspondent points
361  * \param[in] corr Correspondent points
362  */
363  inline double
365  {
366  // Get the source and the target feature from the list
367  const PointT& src = (*input_)[corr.index_query];
368  const PointT& tgt = (*target_)[corr.index_match];
369 
370  return ((src.getVector4fMap() - tgt.getVector4fMap()).squaredNorm());
371  }
372 
373  /** \brief Get the correspondence score for a given pair of correspondent points based
374  * on the angle between the normals. The normmals for the in put and target clouds
375  * must be set before using this function \param[in] corr Correspondent points
376  */
377  inline double
379  {
380  // assert ( (input_normals_->size () != 0) && (target_normals_->size () != 0) &&
381  // "Normals are not set for the input and target point clouds");
382  assert(input_normals_ && target_normals_ &&
383  "Normals are not set for the input and target point clouds");
384  const NormalT& src = (*input_normals_)[corr.index_query];
385  const NormalT& tgt = (*target_normals_)[corr.index_match];
386  return (static_cast<double>((src.normal[0] * tgt.normal[0]) +
387  (src.normal[1] * tgt.normal[1]) +
388  (src.normal[2] * tgt.normal[2])));
389  }
390 
391 private:
392  /** \brief The input point cloud dataset */
393  PointCloudConstPtr input_;
394 
395  /** \brief The input transformed point cloud dataset */
396  PointCloudPtr input_transformed_;
397 
398  /** \brief The target point cloud dataset. */
399  PointCloudConstPtr target_;
400 
401  /** \brief Normals to the input point cloud */
402  NormalsConstPtr input_normals_;
403 
404  /** \brief Normals to the input point cloud */
405  NormalsPtr input_normals_transformed_;
406 
407  /** \brief Normals to the target point cloud */
408  NormalsConstPtr target_normals_;
409 
410  /** \brief A pointer to the spatial search object. */
411  KdTreePtr tree_;
412 
413  /** \brief The name of the rejection method. */
414  std::string class_name_;
415 
416  /** \brief Should the current data container use normals? */
417  bool needs_normals_;
418 
419  /** \brief Variable that stores whether we have a new target cloud, meaning we need to
420  * pre-process it again. This way, we avoid rebuilding the kd-tree */
421  bool target_cloud_updated_{true};
422 
423  /** \brief A flag which, if set, means the tree operating on the target cloud
424  * will never be recomputed*/
425  bool force_no_recompute_{false};
426 
427  /** \brief Get a string representation of the name of this class. */
428  inline const std::string&
429  getClassName() const
430  {
431  return (class_name_);
432  }
433 };
434 } // namespace registration
435 } // namespace pcl
KdTree represents the base spatial locator class for kd-tree implementations.
Definition: kdtree.h:56
PointCloud represents the base class in PCL for storing collections of 3D points.
Definition: point_cloud.h:173
shared_ptr< PointCloud< PointT > > Ptr
Definition: point_cloud.h:413
shared_ptr< const PointCloud< PointT > > ConstPtr
Definition: point_cloud.h:414
CorrespondenceRejector represents the base class for correspondence rejection methods
virtual bool requiresSourceNormals() const
See if this rejector requires source normals.
CorrespondenceRejector()=default
Empty constructor.
virtual void setSourceNormals(pcl::PCLPointCloud2::ConstPtr)
Abstract method for setting the source normals.
virtual void getRemainingCorrespondences(const pcl::Correspondences &original_correspondences, pcl::Correspondences &remaining_correspondences)=0
Get a list of valid correspondences after rejection from the original set of correspondences.
virtual void setSourcePoints(pcl::PCLPointCloud2::ConstPtr)
Abstract method for setting the source cloud.
virtual void setTargetNormals(pcl::PCLPointCloud2::ConstPtr)
Abstract method for setting the target normals.
shared_ptr< const CorrespondenceRejector > ConstPtr
virtual void applyRejection(Correspondences &correspondences)=0
Abstract rejection method.
void getCorrespondences(pcl::Correspondences &correspondences)
Run correspondence rejection.
virtual bool requiresSourcePoints() const
See if this rejector requires source points.
CorrespondencesConstPtr input_correspondences_
The input correspondences.
void getRejectedQueryIndices(const pcl::Correspondences &correspondences, pcl::Indices &indices)
Determine the indices of query points of correspondences that have been rejected, i....
const std::string & getClassName() const
Get a string representation of the name of this class.
shared_ptr< CorrespondenceRejector > Ptr
virtual bool requiresTargetPoints() const
See if this rejector requires a target cloud.
virtual bool requiresTargetNormals() const
See if this rejector requires target normals.
std::string rejection_name_
The name of the rejection method.
virtual ~CorrespondenceRejector()=default
Empty destructor.
CorrespondencesConstPtr getInputCorrespondences()
Get a pointer to the vector of the input correspondences.
virtual void setTargetPoints(pcl::PCLPointCloud2::ConstPtr)
Abstract method for setting the target cloud.
virtual void setInputCorrespondences(const CorrespondencesConstPtr &correspondences)
Provide a pointer to the vector of the input correspondences.
DataContainer is a container for the input and target point clouds and implements the interface to co...
NormalsConstPtr getTargetNormals()
Get the normals computed on the target point cloud.
void setInputTarget(const PointCloudConstPtr &target)
Provide a target point cloud dataset (must contain XYZ data!), used to compute the correspondence dis...
PointCloudConstPtr const getInputSource()
Get a pointer to the input point cloud dataset target.
double getCorrespondenceScore(int index) override
Get the correspondence score for a point in the input cloud.
double getCorrespondenceScore(const pcl::Correspondence &corr) override
Get the correspondence score for a given pair of correspondent points.
NormalsConstPtr getInputNormals()
Get the normals computed on the input point cloud.
void setInputSource(const PointCloudConstPtr &cloud)
Provide a source point cloud dataset (must contain XYZ data!), used to compute the correspondence dis...
void setTargetNormals(const NormalsConstPtr &normals)
Set the normals computed on the target point cloud.
double getCorrespondenceScoreFromNormals(const pcl::Correspondence &corr) override
Get the correspondence score for a given pair of correspondent points based on the angle between the ...
void setSearchMethodTarget(const KdTreePtr &tree, bool force_no_recompute=false)
Provide a pointer to the search object used to find correspondences in the target cloud.
DataContainer(bool needs_normals=false)
Empty constructor.
void setInputNormals(const NormalsConstPtr &normals)
Set the normals computed on the input point cloud.
PointCloudConstPtr const getInputTarget()
Get a pointer to the input point cloud dataset target.
~DataContainer() override=default
Empty destructor.
DataContainerInterface provides a generic interface for computing correspondence scores between corre...
virtual double getCorrespondenceScore(int index)=0
shared_ptr< const DataContainerInterface > ConstPtr
shared_ptr< DataContainerInterface > Ptr
virtual double getCorrespondenceScore(const pcl::Correspondence &)=0
virtual double getCorrespondenceScoreFromNormals(const pcl::Correspondence &)=0
shared_ptr< KdTree< PointT, Tree > > Ptr
Definition: kdtree.h:75
shared_ptr< const Correspondences > CorrespondencesConstPtr
std::vector< pcl::Correspondence, Eigen::aligned_allocator< pcl::Correspondence > > Correspondences
IndicesAllocator<> Indices
Type used for indices in PCL.
Definition: types.h:133
void getRejectedQueryIndices(const pcl::Correspondences &correspondences_before, const pcl::Correspondences &correspondences_after, Indices &indices, bool presorting_required=true)
Get the query points of correspondences that are present in one correspondence vector but not in the ...
Correspondence represents a match between two entities (e.g., points, descriptors,...
index_t index_query
Index of the query (source) point.
index_t index_match
Index of the matching (target) point.
A point structure representing normal coordinates and the surface curvature estimate.
shared_ptr< const ::pcl::PCLPointCloud2 > ConstPtr
A point structure representing Euclidean xyz coordinates, and the RGB color.