Point Cloud Library (PCL)  1.12.1-dev
spin_image.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 #pragma once
41 
42 #include <pcl/point_types.h>
43 #include <pcl/features/feature.h>
44 
45 namespace pcl
46 {
47  /** \brief Estimates spin-image descriptors in the given input points.
48  *
49  * This class represents spin image descriptor. Spin image is
50  * a histogram of point locations summed along the bins of the image.
51  * A 2D accumulator indexed by <VAR>a</VAR> and <VAR>b</VAR> is created. Next,
52  * the coordinates (<VAR>a</VAR>, <VAR>b</VAR>) are computed for a vertex in
53  * the surface mesh that is within the support of the spin image
54  * (explained below). The bin indexed by (<VAR>a</VAR>, <VAR>b</VAR>) in
55  * the accumulator is then incremented; bilinear interpolation is used
56  * to smooth the contribution of the vertex. This procedure is repeated
57  * for all vertices within the support of the spin image.
58  * The resulting accumulator can be thought of as an image;
59  * dark areas in the image correspond to bins that contain many projected points.
60  * As long as the size of the bins in the accumulator is greater
61  * than the median distance between vertices in the mesh
62  * (the definition of mesh resolution), the position of individual
63  * vertices will be averaged out during spin image generation.
64  *
65  * \attention The input normals given by \ref setInputNormals have to match
66  * the input point cloud given by \ref setInputCloud. This behavior is
67  * different than feature estimation methods that extend \ref
68  * FeatureFromNormals, which match the normals with the search surface.
69  *
70  * With the default parameters, pcl::Histogram<153> is a good choice for PointOutT.
71  * Of course the dimension of this descriptor must change to match the number
72  * of bins set by the parameters.
73  *
74  * For further information please see:
75  *
76  * - Johnson, A. E., & Hebert, M. (1998). Surface Matching for Object
77  * Recognition in Complex 3D Scenes. Image and Vision Computing, 16,
78  * 635-651.
79  *
80  * The class also implements radial spin images and spin-images in angular domain
81  * (or both).
82  *
83  * \author Roman Shapovalov, Alexander Velizhev
84  * \ingroup features
85  */
86  template <typename PointInT, typename PointNT, typename PointOutT>
87  class SpinImageEstimation : public Feature<PointInT, PointOutT>
88  {
89  public:
90  using Ptr = shared_ptr<SpinImageEstimation<PointInT, PointNT, PointOutT> >;
91  using ConstPtr = shared_ptr<const SpinImageEstimation<PointInT, PointNT, PointOutT> >;
100 
102 
106 
110 
111  /** \brief Constructs empty spin image estimator.
112  *
113  * \param[in] image_width spin-image resolution, number of bins along one dimension
114  * \param[in] support_angle_cos minimal allowed cosine of the angle between
115  * the normals of input point and search surface point for the point
116  * to be retained in the support
117  * \param[in] min_pts_neighb min number of points in the support to correctly estimate
118  * spin-image. If at some point the support contains less points, exception is thrown
119  */
120  SpinImageEstimation (unsigned int image_width = 8,
121  double support_angle_cos = 0.0, // when 0, this is bogus, so not applied
122  unsigned int min_pts_neighb = 0);
123 
124  /** \brief Empty destructor */
125  ~SpinImageEstimation () override = default;
126 
127  /** \brief Sets spin-image resolution.
128  *
129  * \param[in] bin_count spin-image resolution, number of bins along one dimension
130  */
131  void
132  setImageWidth (unsigned int bin_count)
133  {
134  image_width_ = bin_count;
135  }
136 
137  /** \brief Sets the maximum angle for the point normal to get to support region.
138  *
139  * \param[in] support_angle_cos minimal allowed cosine of the angle between
140  * the normals of input point and search surface point for the point
141  * to be retained in the support
142  */
143  void
144  setSupportAngle (double support_angle_cos)
145  {
146  if (0.0 > support_angle_cos || support_angle_cos > 1.0) // may be permit negative cosine?
147  {
148  throw PCLException ("Cosine of support angle should be between 0 and 1",
149  "spin_image.h", "setSupportAngle");
150  }
151 
152  support_angle_cos_ = support_angle_cos;
153  }
154 
155  /** \brief Sets minimal points count for spin image computation.
156  *
157  * \param[in] min_pts_neighb min number of points in the support to correctly estimate
158  * spin-image. If at some point the support contains less points, exception is thrown
159  */
160  void
161  setMinPointCountInNeighbourhood (unsigned int min_pts_neighb)
162  {
163  min_pts_neighb_ = min_pts_neighb;
164  }
165 
166  /** \brief Provide a pointer to the input dataset that contains the point normals of
167  * the input XYZ dataset given by \ref setInputCloud
168  *
169  * \attention The input normals given by \ref setInputNormals have to match
170  * the input point cloud given by \ref setInputCloud. This behavior is
171  * different than feature estimation methods that extend \ref
172  * FeatureFromNormals, which match the normals with the search surface.
173  * \param[in] normals the const boost shared pointer to a PointCloud of normals.
174  * By convention, L2 norm of each normal should be 1.
175  */
176  inline void
178  {
179  input_normals_ = normals;
180  }
181 
182  /** \brief Sets single vector a rotation axis for all input points.
183  *
184  * It could be useful e.g. when the vertical axis is known.
185  * \param[in] axis unit-length vector that serves as rotation axis for reference frame
186  */
187  void
188  setRotationAxis (const PointNT& axis)
189  {
190  rotation_axis_ = axis;
191  use_custom_axis_ = true;
192  use_custom_axes_cloud_ = false;
193  }
194 
195  /** \brief Sets array of vectors as rotation axes for input points.
196  *
197  * Useful e.g. when one wants to use tangents instead of normals as rotation axes
198  * \param[in] axes unit-length vectors that serves as rotation axes for
199  * the corresponding input points' reference frames
200  */
201  void
203  {
204  rotation_axes_cloud_ = axes;
205 
206  use_custom_axes_cloud_ = true;
207  use_custom_axis_ = false;
208  }
209 
210  /** \brief Sets input normals as rotation axes (default setting). */
211  void
213  {
214  use_custom_axis_ = false;
215  use_custom_axes_cloud_ = false;
216  }
217 
218  /** \brief Sets/unsets flag for angular spin-image domain.
219  *
220  * Angular spin-image differs from the vanilla one in the way that not
221  * the points are collected in the bins but the angles between their
222  * normals and the normal to the reference point. For further
223  * information please see
224  * Endres, F., Plagemann, C., Stachniss, C., & Burgard, W. (2009).
225  * Unsupervised Discovery of Object Classes from Range Data using Latent Dirichlet Allocation.
226  * In Robotics: Science and Systems. Seattle, USA.
227  * \param[in] is_angular true for angular domain, false for point domain
228  */
229  void
230  setAngularDomain (bool is_angular = true) { is_angular_ = is_angular; }
231 
232  /** \brief Sets/unsets flag for radial spin-image structure.
233  *
234  * Instead of rectangular coordinate system for reference frame
235  * polar coordinates are used. Binning is done depending on the distance and
236  * inclination angle from the reference point
237  * \param[in] is_radial true for radial spin-image structure, false for rectangular
238  */
239  void
240  setRadialStructure (bool is_radial = true) { is_radial_ = is_radial; }
241 
242  protected:
243  /** \brief Estimate the Spin Image descriptors at a set of points given by
244  * setInputWithNormals() using the surface in setSearchSurfaceWithNormals() and the spatial locator
245  * \param[out] output the resultant point cloud that contains the Spin Image feature estimates
246  */
247  void
248  computeFeature (PointCloudOut &output) override;
249 
250  /** \brief initializes computations specific to spin-image.
251  *
252  * \return true iff input data and initialization are correct
253  */
254  bool
255  initCompute () override;
256 
257  /** \brief Computes a spin-image for the point of the scan.
258  * \param[in] index the index of the reference point in the input cloud
259  * \return estimated spin-image (or its variant) as a matrix
260  */
261  Eigen::ArrayXXd
262  computeSiForPoint (int index) const;
263 
264  private:
265  PointCloudNConstPtr input_normals_;
266  PointCloudNConstPtr rotation_axes_cloud_;
267 
268  bool is_angular_;
269 
270  PointNT rotation_axis_;
271  bool use_custom_axis_;
272  bool use_custom_axes_cloud_;
273 
274  bool is_radial_;
275 
276  unsigned int image_width_;
277  double support_angle_cos_;
278  unsigned int min_pts_neighb_;
279  };
280 }
281 
282 #ifdef PCL_NO_PRECOMPILE
283 #include <pcl/features/impl/spin_image.hpp>
284 #endif
Feature represents the base feature class.
Definition: feature.h:107
typename PointCloudIn::Ptr PointCloudInPtr
Definition: feature.h:121
shared_ptr< Feature< PointInT, PointOutT > > Ptr
Definition: feature.h:114
shared_ptr< const Feature< PointInT, PointOutT > > ConstPtr
Definition: feature.h:115
typename PointCloudIn::ConstPtr PointCloudInConstPtr
Definition: feature.h:122
PCL base class.
Definition: pcl_base.h:70
A base class for all pcl exceptions which inherits from std::runtime_error.
Definition: exceptions.h:64
shared_ptr< PointCloud< PointNT > > Ptr
Definition: point_cloud.h:413
shared_ptr< const PointCloud< PointNT > > ConstPtr
Definition: point_cloud.h:414
Estimates spin-image descriptors in the given input points.
Definition: spin_image.h:88
void setRotationAxis(const PointNT &axis)
Sets single vector a rotation axis for all input points.
Definition: spin_image.h:188
typename Feature< PointInT, PointOutT >::PointCloudOut PointCloudOut
Definition: spin_image.h:101
Eigen::ArrayXXd computeSiForPoint(int index) const
Computes a spin-image for the point of the scan.
Definition: spin_image.hpp:67
void useNormalsAsRotationAxis()
Sets input normals as rotation axes (default setting).
Definition: spin_image.h:212
void setRadialStructure(bool is_radial=true)
Sets/unsets flag for radial spin-image structure.
Definition: spin_image.h:240
void setAngularDomain(bool is_angular=true)
Sets/unsets flag for angular spin-image domain.
Definition: spin_image.h:230
~SpinImageEstimation() override=default
Empty destructor.
typename PointCloudN::Ptr PointCloudNPtr
Definition: spin_image.h:104
void setImageWidth(unsigned int bin_count)
Sets spin-image resolution.
Definition: spin_image.h:132
void setMinPointCountInNeighbourhood(unsigned int min_pts_neighb)
Sets minimal points count for spin image computation.
Definition: spin_image.h:161
void setInputNormals(const PointCloudNConstPtr &normals)
Provide a pointer to the input dataset that contains the point normals of the input XYZ dataset given...
Definition: spin_image.h:177
typename PointCloudN::ConstPtr PointCloudNConstPtr
Definition: spin_image.h:105
SpinImageEstimation(unsigned int image_width=8, double support_angle_cos=0.0, unsigned int min_pts_neighb=0)
Constructs empty spin image estimator.
Definition: spin_image.hpp:52
bool initCompute() override
initializes computations specific to spin-image.
Definition: spin_image.hpp:237
void setSupportAngle(double support_angle_cos)
Sets the maximum angle for the point normal to get to support region.
Definition: spin_image.h:144
void computeFeature(PointCloudOut &output) override
Estimate the Spin Image descriptors at a set of points given by setInputWithNormals() using the surfa...
Definition: spin_image.hpp:322
void setInputRotationAxes(const PointCloudNConstPtr &axes)
Sets array of vectors as rotation axes for input points.
Definition: spin_image.h:202
Defines all the PCL implemented PointT point type structures.