1 /*
2  * Software License Agreement (BSD License)
3  *
4  *  Point Cloud Library (PCL) - www.pointclouds.org
5  *
6  *  All rights reserved.
7  *
8  *  Redistribution and use in source and binary forms, with or without
9  *  modification, are permitted provided that the following conditions
10  *  are met:
11  *
12  *   * Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *   * Redistributions in binary form must reproduce the above
15  *     copyright notice, this list of conditions and the following
16  *     disclaimer in the documentation and/or other materials provided
17  *     with the distribution.
18  *   * Neither the name of Willow Garage, Inc. nor the names of its
19  *     contributors may be used to endorse or promote products derived
20  *     from this software without specific prior written permission.
21  *
22  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  *  POSSIBILITY OF SUCH DAMAGE.
34  *
35  * Author : Sergey Ushakov
36  * Email  : sergey.s.ushakov@mail.ru
37  *
38  */
39 
40 #pragma once
41 
42 #include <pcl/memory.h>
43 #include <pcl/pcl_macros.h>
44 #include <pcl/Vertices.h> // for Vertices
45 #include <pcl/features/feature.h>
46 #include <set>
47 
48 namespace pcl
49 {
50   /** \brief
51     * This class implements the method for extracting RoPS features presented in the article
52     * "Rotational Projection Statistics for 3D Local Surface Description and Object Recognition" by
53     * Yulan Guo, Ferdous Sohel, Mohammed Bennamoun, Min Lu and Jianwei Wan.
54     */
55   template <typename PointInT, typename PointOutT>
56   class PCL_EXPORTS ROPSEstimation : public pcl::Feature <PointInT, PointOutT>
57   {
58     public:
59 
60       using Feature <PointInT, PointOutT>::input_;
61       using Feature <PointInT, PointOutT>::indices_;
62       using Feature <PointInT, PointOutT>::surface_;
63       using Feature <PointInT, PointOutT>::tree_;
64 
65       using PointCloudOut = typename pcl::Feature <PointInT, PointOutT>::PointCloudOut;
66       using PointCloudIn = typename pcl::Feature <PointInT, PointOutT>::PointCloudIn;
67 
68     public:
69 
70       /** \brief Simple constructor. */
71       ROPSEstimation ();
72 
73       /** \brief Virtual destructor. */
74 
75       ~ROPSEstimation ();
76 
77       /** \brief Allows to set the number of partition bins that is used for distribution matrix calculation.
78         * \param[in] number_of_bins number of partition bins
79         */
80       void
81       setNumberOfPartitionBins (unsigned int number_of_bins);
82 
83       /** \brief Returns the number of partition bins. */
84       unsigned int
85       getNumberOfPartitionBins () const;
86 
87       /** \brief This method sets the number of rotations.
88         * \param[in] number_of_rotations number of rotations
89         */
90       void
91       setNumberOfRotations (unsigned int number_of_rotations);
92 
93       /** \brief returns the number of rotations. */
94       unsigned int
95       getNumberOfRotations () const;
96 
97       /** \brief Allows to set the support radius that is used to crop the local surface of the point.
98         * \param[in] support_radius support radius
99         */
100       void
101       setSupportRadius (float support_radius);
102 
103       /** \brief Returns the support radius. */
104       float
105       getSupportRadius () const;
106 
107       /** \brief This method sets the triangles of the mesh.
108         * \param[in] triangles list of triangles of the mesh
109         */
110       void
111       setTriangles (const std::vector <pcl::Vertices>& triangles);
112 
113       /** \brief Returns the triangles of the mesh.
114         * \param[out] triangles triangles of the mesh
115         */
116       void
117       getTriangles (std::vector <pcl::Vertices>& triangles) const;
118 
119     private:
120 
121       /** \brief Abstract feature estimation method.
122         * \param[out] output the resultant features
123         */
124       void
125       computeFeature (PointCloudOut& output) override;
126 
127       /** \brief This method simply builds the list of triangles for every point.
128         * The list of triangles for each point consists of indices of triangles it belongs to.
129         * The only purpose of this method is to improve performance of the algorithm.
130         */
131       void
132       buildListOfPointsTriangles ();
133 
134       /** \brief This method crops all the triangles within the given radius of the given point.
135         * \param[in] point point for which the local surface is computed
136         * \param[out] local_triangles stores the indices of the triangles that belong to the local surface
137         * \param[out] local_points stores the indices of the points that belong to the local surface
138         */
139       void
140       getLocalSurface (const PointInT& point, std::set <unsigned int>& local_triangles, pcl::Indices& local_points) const;
141 
142       /** \brief This method computes LRF (Local Reference Frame) matrix for the given point.
143         * \param[in] point point for which the LRF is computed
144         * \param[in] local_triangles list of triangles that represents the local surface of the point
145         * \paran[out] lrf_matrix stores computed LRF matrix for the given point
146         */
147       void
148       computeLRF (const PointInT& point, const std::set <unsigned int>& local_triangles, Eigen::Matrix3f& lrf_matrix) const;
149 
150       /** \brief This method calculates the eigen values and eigen vectors
151         * for the given covariance matrix. Note that it returns normalized eigen
152         * vectors that always form the right-handed coordinate system.
153         * \param[in] matrix covariance matrix of the cloud
154         * \param[out] major_axis eigen vector which corresponds to a major eigen value
155         * \param[out] middle_axis eigen vector which corresponds to a middle eigen value
156         * \param[out] minor_axis eigen vector which corresponds to a minor eigen value
157         */
158       void
159       computeEigenVectors (const Eigen::Matrix3f& matrix, Eigen::Vector3f& major_axis, Eigen::Vector3f& middle_axis,
160                            Eigen::Vector3f& minor_axis) const;
161 
162       /** \brief This method translates the cloud so that the given point becomes the origin.
163         * After that the cloud is rotated with the help of the given matrix.
164         * \param[in] point point which stores the translation information
165         * \param[in] matrix rotation matrix
166         * \param[in] local_points point to transform
167         * \param[out] transformed_cloud stores the transformed cloud
168         */
169       void
170       transformCloud (const PointInT& point, const Eigen::Matrix3f& matrix, const pcl::Indices& local_points, PointCloudIn& transformed_cloud) const;
171 
172       /** \brief This method rotates the cloud around the given axis and computes AABB of the rotated cloud.
173         * \param[in] axis axis around which cloud must be rotated
174         * \param[in] angle angle in degrees
175         * \param[in] cloud cloud to rotate
176         * \param[out] rotated_cloud stores the rotated cloud
177         * \param[out] min stores the min point of the AABB
178         * \param[out] max stores the max point of the AABB
179         */
180       void
181       rotateCloud (const PointInT& axis, const float angle, const PointCloudIn& cloud, PointCloudIn& rotated_cloud,
182                    Eigen::Vector3f& min, Eigen::Vector3f& max) const;
183 
184       /** \brief This method projects the local surface onto the XY, XZ or YZ plane
185         * and computes the distribution matrix.
186         * \param[in] projection represents the case of projection. 1 - XY, 2 - XZ, 3 - YZ
187         * \param[in] min min point of the AABB
188         * \param[in] max max point of the AABB
189         * \param[in] cloud cloud containing the points of the local surface
190         * \param[out] matrix stores computed distribution matrix
191         */
192       void
193       getDistributionMatrix (const unsigned int projection, const Eigen::Vector3f& min, const Eigen::Vector3f& max, const PointCloudIn& cloud, Eigen::MatrixXf& matrix) const;
194 
195       /** \brief This method computes the set ofcentral moments for the given matrix.
196         * \param[in] matrix input matrix
197         * \param[out] moments set of computed moments
198         */
199       void
200       computeCentralMoments (const Eigen::MatrixXf& matrix, std::vector <float>& moments) const;
201 
202     private:
203 
204       /** \brief Stores the number of partition bins that is used for distribution matrix calculation. */
205       unsigned int number_of_bins_;
206 
207       /** \brief Stores number of rotations. Central moments are calculated for every rotation. */
208       unsigned int number_of_rotations_;
209 
210       /** \brief Support radius that is used to crop the local surface of the point. */
211       float support_radius_;
212 
213       /** \brief Stores the squared support radius. Used to improve performance. */
214       float sqr_support_radius_;
215 
216       /** \brief Stores the angle step. Step is calculated with respect to number of rotations. */
217       float step_;
218 
219       /** \brief Stores the set of triangles representing the mesh. */
220       std::vector <pcl::Vertices> triangles_;
221 
222       /** \brief Stores the set of triangles for each point. Its purpose is to improve performance. */
223       std::vector <std::vector <unsigned int> > triangles_of_the_point_;
224 
225     public:
226       PCL_MAKE_ALIGNED_OPERATOR_NEW
227   };
228 }
229 
230 #define PCL_INSTANTIATE_ROPSEstimation(InT, OutT) template class pcl::ROPSEstimation<InT, OutT>;
231 
232 #ifdef PCL_NO_PRECOMPILE
233 #include <pcl/features/impl/rops_estimation.hpp>
234 #endif
235