Point Cloud Library (PCL)  1.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
rift.hpp
Go to the documentation of this file.
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  *
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 Willow Garage, Inc. 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  * $Id: rift.hpp 5036 2012-03-12 08:54:15Z rusu $
37  *
38  */
39 
40 #ifndef PCL_FEATURES_IMPL_RIFT_H_
41 #define PCL_FEATURES_IMPL_RIFT_H_
42 
43 #include <pcl/features/rift.h>
44 
46 template <typename PointInT, typename GradientT, typename PointOutT> void
48  const PointCloudIn &cloud, const PointCloudGradient &gradient,
49  int p_idx, float radius, const std::vector<int> &indices,
50  const std::vector<float> &sqr_distances, Eigen::MatrixXf &rift_descriptor)
51 {
52  if (indices.empty ())
53  {
54  PCL_ERROR ("[pcl::RIFTEstimation] Null indices points passed!\n");
55  return;
56  }
57 
58  // Determine the number of bins to use based on the size of rift_descriptor
59  int nr_distance_bins = static_cast<int> (rift_descriptor.rows ());
60  int nr_gradient_bins = static_cast<int> (rift_descriptor.cols ());
61 
62  // Get the center point
63  pcl::Vector3fMapConst p0 = cloud.points[p_idx].getVector3fMap ();
64 
65  // Compute the RIFT descriptor
66  rift_descriptor.setZero ();
67  for (size_t idx = 0; idx < indices.size (); ++idx)
68  {
69  // Compute the gradient magnitude and orientation (relative to the center point)
70  pcl::Vector3fMapConst point = cloud.points[indices[idx]].getVector3fMap ();
71  Eigen::Map<const Eigen::Vector3f> gradient_vector (& (gradient.points[indices[idx]].gradient[0]));
72 
73  float gradient_magnitude = gradient_vector.norm ();
74  float gradient_angle_from_center = acosf (gradient_vector.dot ((point - p0).normalized ()) / gradient_magnitude);
75  if (!pcl_isfinite (gradient_angle_from_center))
76  gradient_angle_from_center = 0.0;
77 
78  // Normalize distance and angle values to: 0.0 <= d,g < nr_distances_bins,nr_gradient_bins
79  const float eps = std::numeric_limits<float>::epsilon ();
80  float d = static_cast<float> (nr_distance_bins) * sqrtf (sqr_distances[idx]) / (radius + eps);
81  float g = static_cast<float> (nr_gradient_bins) * gradient_angle_from_center / (static_cast<float> (M_PI) + eps);
82 
83  // Compute the bin indices that need to be updated
84  int d_idx_min = (std::max)(static_cast<int> (ceil (d - 1)), 0);
85  int d_idx_max = (std::min)(static_cast<int> (floor (d + 1)), nr_distance_bins - 1);
86  int g_idx_min = static_cast<int> (ceil (g - 1));
87  int g_idx_max = static_cast<int> (floor (g + 1));
88 
89  // Update the appropriate bins of the histogram
90  for (int g_idx = g_idx_min; g_idx <= g_idx_max; ++g_idx)
91  {
92  // Because gradient orientation is cyclical, out-of-bounds values must wrap around
93  int g_idx_wrapped = ((g_idx + nr_gradient_bins) % nr_gradient_bins);
94 
95  for (int d_idx = d_idx_min; d_idx <= d_idx_max; ++d_idx)
96  {
97  // To avoid boundary effects, use linear interpolation when updating each bin
98  float w = (1.0f - fabsf (d - static_cast<float> (d_idx))) * (1.0f - fabsf (g - static_cast<float> (g_idx)));
99 
100  rift_descriptor (d_idx, g_idx_wrapped) += w * gradient_magnitude;
101  }
102  }
103  }
104 
105  // Normalize the RIFT descriptor to unit magnitude
106  rift_descriptor.normalize ();
107 }
108 
109 
111 template <typename PointInT, typename GradientT, typename PointOutT> void
113 {
114  // Make sure a search radius is set
115  if (search_radius_ == 0.0)
116  {
117  PCL_ERROR ("[pcl::%s::computeFeature] The search radius must be set before computing the feature!\n",
118  getClassName ().c_str ());
119  output.width = output.height = 0;
120  output.points.clear ();
121  return;
122  }
123 
124  // Make sure the RIFT descriptor has valid dimensions
125  if (nr_gradient_bins_ <= 0)
126  {
127  PCL_ERROR ("[pcl::%s::computeFeature] The number of gradient bins must be greater than zero!\n",
128  getClassName ().c_str ());
129  output.width = output.height = 0;
130  output.points.clear ();
131  return;
132  }
133  if (nr_distance_bins_ <= 0)
134  {
135  PCL_ERROR ("[pcl::%s::computeFeature] The number of distance bins must be greater than zero!\n",
136  getClassName ().c_str ());
137  output.width = output.height = 0;
138  output.points.clear ();
139  return;
140  }
141 
142  // Check for valid input gradient
143  if (!gradient_)
144  {
145  PCL_ERROR ("[pcl::%s::computeFeature] No input gradient was given!\n", getClassName ().c_str ());
146  output.width = output.height = 0;
147  output.points.clear ();
148  return;
149  }
150  if (gradient_->points.size () != surface_->points.size ())
151  {
152  PCL_ERROR ("[pcl::%s::computeFeature] ", getClassName ().c_str ());
153  PCL_ERROR ("The number of points in the input dataset differs from the number of points in the gradient!\n");
154  output.width = output.height = 0;
155  output.points.clear ();
156  return;
157  }
158 
159  Eigen::MatrixXf rift_descriptor (nr_distance_bins_, nr_gradient_bins_);
160  std::vector<int> nn_indices;
161  std::vector<float> nn_dist_sqr;
162 
163  // Iterating over the entire index vector
164  for (size_t idx = 0; idx < indices_->size (); ++idx)
165  {
166  // Find neighbors within the search radius
167  tree_->radiusSearch ((*indices_)[idx], search_radius_, nn_indices, nn_dist_sqr);
168 
169  // Compute the RIFT descriptor
170  computeRIFT (*surface_, *gradient_, (*indices_)[idx], static_cast<float> (search_radius_), nn_indices, nn_dist_sqr, rift_descriptor);
171 
172  // Copy into the resultant cloud
173  int bin = 0;
174  for (int g_bin = 0; g_bin < rift_descriptor.cols (); ++g_bin)
175  for (int d_bin = 0; d_bin < rift_descriptor.rows (); ++d_bin)
176  output.points[idx].histogram[bin++] = rift_descriptor (d_bin, g_bin);
177  }
178 }
179 
181 template <typename PointInT, typename GradientT> void
183 {
184  // These should be moved into initCompute ()
185  {
186  // Make sure a search radius is set
187  if (search_radius_ == 0.0)
188  {
189  PCL_ERROR ("[pcl::%s::computeFeature] The search radius must be set before computing the feature!\n",
190  getClassName ().c_str ());
191  output.width = output.height = 0;
192  output.points.resize (0, 0);
193  return;
194  }
195 
196  // Make sure the RIFT descriptor has valid dimensions
197  if (nr_gradient_bins_ <= 0)
198  {
199  PCL_ERROR ("[pcl::%s::computeFeature] The number of gradient bins must be greater than zero!\n",
200  getClassName ().c_str ());
201  output.width = output.height = 0;
202  output.points.resize (0, 0);
203  return;
204  }
205  if (nr_distance_bins_ <= 0)
206  {
207  PCL_ERROR ("[pcl::%s::computeFeature] The number of distance bins must be greater than zero!\n",
208  getClassName ().c_str ());
209  output.width = output.height = 0;
210  output.points.resize (0, 0);
211  return;
212  }
213 
214  // Check for valid input gradient
215  if (!gradient_)
216  {
217  PCL_ERROR ("[pcl::%s::computeFeature] No input gradient was given!\n", getClassName ().c_str ());
218  output.width = output.height = 0;
219  output.points.resize (0, 0);
220  return;
221  }
222  if (gradient_->points.size () != surface_->points.size ())
223  {
224  PCL_ERROR ("[pcl::%s::computeFeature] ", getClassName ().c_str ());
225  PCL_ERROR ("The number of points in the input dataset differs from the number of points in the gradient!\n");
226  output.width = output.height = 0;
227  output.points.resize (0, 0);
228  return;
229  }
230  }
231 
232  output.points.resize (indices_->size (), nr_gradient_bins_ * nr_distance_bins_);
233  Eigen::MatrixXf rift_descriptor (nr_distance_bins_, nr_gradient_bins_);
234  std::vector<int> nn_indices;
235  std::vector<float> nn_dist_sqr;
236 
237  output.is_dense = true;
238  // Iterating over the entire index vector
239  for (size_t idx = 0; idx < indices_->size (); ++idx)
240  {
241  // Find neighbors within the search radius
242  if (tree_->radiusSearch ((*indices_)[idx], search_radius_, nn_indices, nn_dist_sqr) == 0)
243  {
244  output.points.row (idx).setConstant (std::numeric_limits<float>::quiet_NaN ());
245  output.is_dense = false;
246  continue;
247  }
248 
249  // Compute the RIFT descriptor
250  this->computeRIFT (*surface_, *gradient_, (*indices_)[idx], static_cast<float> (search_radius_), nn_indices, nn_dist_sqr,
251  rift_descriptor);
252 
253  // Copy into the resultant cloud
254  int bin = 0;
255  for (int g_bin = 0; g_bin < rift_descriptor.cols (); ++g_bin)
256  for (int d_bin = 0; d_bin < rift_descriptor.rows (); ++d_bin)
257  output.points (idx, bin++) = rift_descriptor (d_bin, g_bin);
258 
259  }
260 }
261 
262 #define PCL_INSTANTIATE_RIFTEstimation(T,NT,OutT) template class PCL_EXPORTS pcl::RIFTEstimation<T,NT,OutT>;
263 
264 #endif // PCL_FEATURES_IMPL_RIFT_H_
265