Point Cloud Library (PCL)  1.9.1-dev
harris_3d.hpp
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  */
37 
38 #ifndef PCL_HARRIS_KEYPOINT_3D_IMPL_H_
39 #define PCL_HARRIS_KEYPOINT_3D_IMPL_H_
40 
41 #include <pcl/keypoints/harris_3d.h>
42 #include <pcl/common/io.h>
43 #include <pcl/filters/passthrough.h>
44 #include <pcl/filters/extract_indices.h>
45 #include <pcl/features/normal_3d.h>
46 #include <pcl/features/integral_image_normal.h>
47 #include <pcl/common/time.h>
48 #include <pcl/common/centroid.h>
49 #ifdef __SSE__
50 #include <xmmintrin.h>
51 #endif
52 
53 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
54 template <typename PointInT, typename PointOutT, typename NormalT> void
56 {
57  if (normals_ && input_ && (cloud != input_))
58  normals_.reset ();
59  input_ = cloud;
60 }
61 
62 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
63 template <typename PointInT, typename PointOutT, typename NormalT> void
65 {
66  method_ = method;
67 }
68 
69 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
70 template <typename PointInT, typename PointOutT, typename NormalT> void
72 {
73  threshold_= threshold;
74 }
75 
76 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
77 template <typename PointInT, typename PointOutT, typename NormalT> void
79 {
80  search_radius_ = radius;
81 }
82 
83 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
84 template <typename PointInT, typename PointOutT, typename NormalT> void
86 {
87  refine_ = do_refine;
88 }
89 
90 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
91 template <typename PointInT, typename PointOutT, typename NormalT> void
93 {
94  nonmax_ = nonmax;
95 }
96 
97 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
98 template <typename PointInT, typename PointOutT, typename NormalT> void
100 {
101  normals_ = normals;
102 }
103 
104 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
105 template <typename PointInT, typename PointOutT, typename NormalT> void
106 pcl::HarrisKeypoint3D<PointInT, PointOutT, NormalT>::calculateNormalCovar (const std::vector<int>& neighbors, float* coefficients) const
107 {
108  unsigned count = 0;
109  // indices 0 1 2 3 4 5 6 7
110  // coefficients: xx xy xz ?? yx yy yz ??
111 #ifdef __SSE__
112  // accumulator for xx, xy, xz
113  __m128 vec1 = _mm_setzero_ps();
114  // accumulator for yy, yz, zz
115  __m128 vec2 = _mm_setzero_ps();
116 
117  __m128 norm1;
118 
119  __m128 norm2;
120 
121  float zz = 0;
122 
123  for (const int &neighbor : neighbors)
124  {
125  if (std::isfinite (normals_->points[neighbor].normal_x))
126  {
127  // nx, ny, nz, h
128  norm1 = _mm_load_ps (&(normals_->points[neighbor].normal_x));
129 
130  // nx, nx, nx, nx
131  norm2 = _mm_set1_ps (normals_->points[neighbor].normal_x);
132 
133  // nx * nx, nx * ny, nx * nz, nx * h
134  norm2 = _mm_mul_ps (norm1, norm2);
135 
136  // accumulate
137  vec1 = _mm_add_ps (vec1, norm2);
138 
139  // ny, ny, ny, ny
140  norm2 = _mm_set1_ps (normals_->points[neighbor].normal_y);
141 
142  // ny * nx, ny * ny, ny * nz, ny * h
143  norm2 = _mm_mul_ps (norm1, norm2);
144 
145  // accumulate
146  vec2 = _mm_add_ps (vec2, norm2);
147 
148  zz += normals_->points[neighbor].normal_z * normals_->points[neighbor].normal_z;
149  ++count;
150  }
151  }
152  if (count > 0)
153  {
154  norm2 = _mm_set1_ps (float(count));
155  vec1 = _mm_div_ps (vec1, norm2);
156  vec2 = _mm_div_ps (vec2, norm2);
157  _mm_store_ps (coefficients, vec1);
158  _mm_store_ps (coefficients + 4, vec2);
159  coefficients [7] = zz / float(count);
160  }
161  else
162  memset (coefficients, 0, sizeof (float) * 8);
163 #else
164  memset (coefficients, 0, sizeof (float) * 8);
165  for (std::vector<int>::const_iterator iIt = neighbors.begin(); iIt != neighbors.end(); ++iIt)
166  {
167  if (std::isfinite (normals_->points[*iIt].normal_x))
168  {
169  coefficients[0] += normals_->points[*iIt].normal_x * normals_->points[*iIt].normal_x;
170  coefficients[1] += normals_->points[*iIt].normal_x * normals_->points[*iIt].normal_y;
171  coefficients[2] += normals_->points[*iIt].normal_x * normals_->points[*iIt].normal_z;
172 
173  coefficients[5] += normals_->points[*iIt].normal_y * normals_->points[*iIt].normal_y;
174  coefficients[6] += normals_->points[*iIt].normal_y * normals_->points[*iIt].normal_z;
175  coefficients[7] += normals_->points[*iIt].normal_z * normals_->points[*iIt].normal_z;
176 
177  ++count;
178  }
179  }
180  if (count > 0)
181  {
182  float norm = 1.0 / float (count);
183  coefficients[0] *= norm;
184  coefficients[1] *= norm;
185  coefficients[2] *= norm;
186  coefficients[5] *= norm;
187  coefficients[6] *= norm;
188  coefficients[7] *= norm;
189  }
190 #endif
191 }
192 
193 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
194 template <typename PointInT, typename PointOutT, typename NormalT> bool
196 {
198  {
199  PCL_ERROR ("[pcl::%s::initCompute] init failed!\n", name_.c_str ());
200  return (false);
201  }
202 
203  if (method_ < 1 || method_ > 5)
204  {
205  PCL_ERROR ("[pcl::%s::initCompute] method (%d) must be in [1..5]!\n", name_.c_str (), method_);
206  return (false);
207  }
208 
209  if (!normals_)
210  {
211  PointCloudNPtr normals (new PointCloudN ());
212  normals->reserve (normals->size ());
213  if (!surface_->isOrganized ())
214  {
216  normal_estimation.setInputCloud (surface_);
217  normal_estimation.setRadiusSearch (search_radius_);
218  normal_estimation.compute (*normals);
219  }
220  else
221  {
224  normal_estimation.setInputCloud (surface_);
225  normal_estimation.setNormalSmoothingSize (5.0);
226  normal_estimation.compute (*normals);
227  }
228  normals_ = normals;
229  }
230  if (normals_->size () != surface_->size ())
231  {
232  PCL_ERROR ("[pcl::%s::initCompute] normals given, but the number of normals does not match the number of input points!\n", name_.c_str (), method_);
233  return (false);
234  }
235 
236  return (true);
237 }
238 
239 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
240 template <typename PointInT, typename PointOutT, typename NormalT> void
242 {
244 
245  response->points.reserve (input_->points.size());
246 
247  switch (method_)
248  {
249  case HARRIS:
250  responseHarris(*response);
251  break;
252  case NOBLE:
253  responseNoble(*response);
254  break;
255  case LOWE:
256  responseLowe(*response);
257  break;
258  case CURVATURE:
259  responseCurvature(*response);
260  break;
261  case TOMASI:
262  responseTomasi(*response);
263  break;
264  }
265 
266  if (!nonmax_)
267  {
268  output = *response;
269  // we do not change the denseness in this case
270  output.is_dense = input_->is_dense;
271  for (size_t i = 0; i < response->size (); ++i)
272  keypoints_indices_->indices.push_back (i);
273  }
274  else
275  {
276  output.points.clear ();
277  output.points.reserve (response->points.size());
278 
279 #ifdef _OPENMP
280 #pragma omp parallel for shared (output) num_threads(threads_)
281 #endif
282  for (int idx = 0; idx < static_cast<int> (response->points.size ()); ++idx)
283  {
284  if (!isFinite (response->points[idx]) ||
285  !std::isfinite (response->points[idx].intensity) ||
286  response->points[idx].intensity < threshold_)
287  continue;
288 
289  std::vector<int> nn_indices;
290  std::vector<float> nn_dists;
291  tree_->radiusSearch (idx, search_radius_, nn_indices, nn_dists);
292  bool is_maxima = true;
293  for (std::vector<int>::const_iterator iIt = nn_indices.begin(); iIt != nn_indices.end(); ++iIt)
294  {
295  if (response->points[idx].intensity < response->points[*iIt].intensity)
296  {
297  is_maxima = false;
298  break;
299  }
300  }
301  if (is_maxima)
302 #ifdef _OPENMP
303 #pragma omp critical
304 #endif
305  {
306  output.points.push_back (response->points[idx]);
307  keypoints_indices_->indices.push_back (idx);
308  }
309  }
310 
311  if (refine_)
312  refineCorners (output);
313 
314  output.height = 1;
315  output.width = static_cast<uint32_t> (output.points.size());
316  output.is_dense = true;
317  }
318 }
319 
320 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
321 template <typename PointInT, typename PointOutT, typename NormalT> void
323 {
324  PCL_ALIGN (16) float covar [8];
325  output.resize (input_->size ());
326 #ifdef _OPENMP
327  #pragma omp parallel for shared (output) private (covar) num_threads(threads_)
328 #endif
329  for (int pIdx = 0; pIdx < static_cast<int> (input_->size ()); ++pIdx)
330  {
331  const PointInT& pointIn = input_->points [pIdx];
332  output [pIdx].intensity = 0.0; //std::numeric_limits<float>::quiet_NaN ();
333  if (isFinite (pointIn))
334  {
335  std::vector<int> nn_indices;
336  std::vector<float> nn_dists;
337  tree_->radiusSearch (pointIn, search_radius_, nn_indices, nn_dists);
338  calculateNormalCovar (nn_indices, covar);
339 
340  float trace = covar [0] + covar [5] + covar [7];
341  if (trace != 0)
342  {
343  float det = covar [0] * covar [5] * covar [7] + 2.0f * covar [1] * covar [2] * covar [6]
344  - covar [2] * covar [2] * covar [5]
345  - covar [1] * covar [1] * covar [7]
346  - covar [6] * covar [6] * covar [0];
347 
348  output [pIdx].intensity = 0.04f + det - 0.04f * trace * trace;
349  }
350  }
351  output [pIdx].x = pointIn.x;
352  output [pIdx].y = pointIn.y;
353  output [pIdx].z = pointIn.z;
354  }
355  output.height = input_->height;
356  output.width = input_->width;
357 }
358 
359 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
360 template <typename PointInT, typename PointOutT, typename NormalT> void
362 {
363  PCL_ALIGN (16) float covar [8];
364  output.resize (input_->size ());
365 #ifdef _OPENMP
366  #pragma omp parallel for shared (output) private (covar) num_threads(threads_)
367 #endif
368  for (int pIdx = 0; pIdx < static_cast<int> (input_->size ()); ++pIdx)
369  {
370  const PointInT& pointIn = input_->points [pIdx];
371  output [pIdx].intensity = 0.0;
372  if (isFinite (pointIn))
373  {
374  std::vector<int> nn_indices;
375  std::vector<float> nn_dists;
376  tree_->radiusSearch (pointIn, search_radius_, nn_indices, nn_dists);
377  calculateNormalCovar (nn_indices, covar);
378  float trace = covar [0] + covar [5] + covar [7];
379  if (trace != 0)
380  {
381  float det = covar [0] * covar [5] * covar [7] + 2.0f * covar [1] * covar [2] * covar [6]
382  - covar [2] * covar [2] * covar [5]
383  - covar [1] * covar [1] * covar [7]
384  - covar [6] * covar [6] * covar [0];
385 
386  output [pIdx].intensity = det / trace;
387  }
388  }
389  output [pIdx].x = pointIn.x;
390  output [pIdx].y = pointIn.y;
391  output [pIdx].z = pointIn.z;
392  }
393  output.height = input_->height;
394  output.width = input_->width;
395 }
396 
397 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
398 template <typename PointInT, typename PointOutT, typename NormalT> void
400 {
401  PCL_ALIGN (16) float covar [8];
402  output.resize (input_->size ());
403 #ifdef _OPENMP
404  #pragma omp parallel for shared (output) private (covar) num_threads(threads_)
405 #endif
406  for (int pIdx = 0; pIdx < static_cast<int> (input_->size ()); ++pIdx)
407  {
408  const PointInT& pointIn = input_->points [pIdx];
409  output [pIdx].intensity = 0.0;
410  if (isFinite (pointIn))
411  {
412  std::vector<int> nn_indices;
413  std::vector<float> nn_dists;
414  tree_->radiusSearch (pointIn, search_radius_, nn_indices, nn_dists);
415  calculateNormalCovar (nn_indices, covar);
416  float trace = covar [0] + covar [5] + covar [7];
417  if (trace != 0)
418  {
419  float det = covar [0] * covar [5] * covar [7] + 2.0f * covar [1] * covar [2] * covar [6]
420  - covar [2] * covar [2] * covar [5]
421  - covar [1] * covar [1] * covar [7]
422  - covar [6] * covar [6] * covar [0];
423 
424  output [pIdx].intensity = det / (trace * trace);
425  }
426  }
427  output [pIdx].x = pointIn.x;
428  output [pIdx].y = pointIn.y;
429  output [pIdx].z = pointIn.z;
430  }
431  output.height = input_->height;
432  output.width = input_->width;
433 }
434 
435 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
436 template <typename PointInT, typename PointOutT, typename NormalT> void
438 {
439  PointOutT point;
440  for (size_t idx = 0; idx < input_->points.size(); ++idx)
441  {
442  point.x = input_->points[idx].x;
443  point.y = input_->points[idx].y;
444  point.z = input_->points[idx].z;
445  point.intensity = normals_->points[idx].curvature;
446  output.points.push_back(point);
447  }
448  // does not change the order
449  output.height = input_->height;
450  output.width = input_->width;
451 }
452 
453 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
454 template <typename PointInT, typename PointOutT, typename NormalT> void
456 {
457  PCL_ALIGN (16) float covar [8];
458  Eigen::Matrix3f covariance_matrix;
459  output.resize (input_->size ());
460 #ifdef _OPENMP
461  #pragma omp parallel for shared (output) private (covar, covariance_matrix) num_threads(threads_)
462 #endif
463  for (int pIdx = 0; pIdx < static_cast<int> (input_->size ()); ++pIdx)
464  {
465  const PointInT& pointIn = input_->points [pIdx];
466  output [pIdx].intensity = 0.0;
467  if (isFinite (pointIn))
468  {
469  std::vector<int> nn_indices;
470  std::vector<float> nn_dists;
471  tree_->radiusSearch (pointIn, search_radius_, nn_indices, nn_dists);
472  calculateNormalCovar (nn_indices, covar);
473  float trace = covar [0] + covar [5] + covar [7];
474  if (trace != 0)
475  {
476  covariance_matrix.coeffRef (0) = covar [0];
477  covariance_matrix.coeffRef (1) = covariance_matrix.coeffRef (3) = covar [1];
478  covariance_matrix.coeffRef (2) = covariance_matrix.coeffRef (6) = covar [2];
479  covariance_matrix.coeffRef (4) = covar [5];
480  covariance_matrix.coeffRef (5) = covariance_matrix.coeffRef (7) = covar [6];
481  covariance_matrix.coeffRef (8) = covar [7];
482 
483  EIGEN_ALIGN16 Eigen::Vector3f eigen_values;
484  pcl::eigen33(covariance_matrix, eigen_values);
485  output [pIdx].intensity = eigen_values[0];
486  }
487  }
488  output [pIdx].x = pointIn.x;
489  output [pIdx].y = pointIn.y;
490  output [pIdx].z = pointIn.z;
491  }
492  output.height = input_->height;
493  output.width = input_->width;
494 }
495 
496 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
497 template <typename PointInT, typename PointOutT, typename NormalT> void
499 {
500  Eigen::Matrix3f nnT;
501  Eigen::Matrix3f NNT;
502  Eigen::Matrix3f NNTInv;
503  Eigen::Vector3f NNTp;
504  float diff;
505  const unsigned max_iterations = 10;
506 #ifdef _OPENMP
507  #pragma omp parallel for shared (corners) private (nnT, NNT, NNTInv, NNTp, diff) num_threads(threads_)
508 #endif
509  for (int cIdx = 0; cIdx < static_cast<int> (corners.size ()); ++cIdx)
510  {
511  unsigned iterations = 0;
512  do {
513  NNT.setZero();
514  NNTp.setZero();
515  PointInT corner;
516  corner.x = corners[cIdx].x;
517  corner.y = corners[cIdx].y;
518  corner.z = corners[cIdx].z;
519  std::vector<int> nn_indices;
520  std::vector<float> nn_dists;
521  tree_->radiusSearch (corner, search_radius_, nn_indices, nn_dists);
522  for (std::vector<int>::const_iterator iIt = nn_indices.begin(); iIt != nn_indices.end(); ++iIt)
523  {
524  if (!std::isfinite (normals_->points[*iIt].normal_x))
525  continue;
526 
527  nnT = normals_->points[*iIt].getNormalVector3fMap () * normals_->points[*iIt].getNormalVector3fMap ().transpose();
528  NNT += nnT;
529  NNTp += nnT * surface_->points[*iIt].getVector3fMap ();
530  }
531  if (invert3x3SymMatrix (NNT, NNTInv) != 0)
532  corners[cIdx].getVector3fMap () = NNTInv * NNTp;
533 
534  diff = (corners[cIdx].getVector3fMap () - corner.getVector3fMap()).squaredNorm ();
535  } while (diff > 1e-6 && ++iterations < max_iterations);
536  }
537 }
538 
539 #define PCL_INSTANTIATE_HarrisKeypoint3D(T,U,N) template class PCL_EXPORTS pcl::HarrisKeypoint3D<T,U,N>;
540 #endif // #ifndef PCL_HARRIS_KEYPOINT_3D_IMPL_H_
541 
void refineCorners(PointCloudOut &corners) const
Definition: harris_3d.hpp:498
void setRadius(float radius)
Set the radius for normal estimation and non maxima supression.
Definition: harris_3d.hpp:78
bool isFinite(const PointT &pt)
Tests if the 3D components of a point are all finite param[in] pt point to be tested return true if f...
Definition: point_tests.h:53
size_t size() const
Definition: point_cloud.h:447
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
Definition: point_cloud.h:409
void setNormals(const PointCloudNConstPtr &normals)
Set normals if precalculated normals are available.
Definition: harris_3d.hpp:99
struct pcl::PointXYZIEdge EIGEN_ALIGN16
void calculateNormalCovar(const std::vector< int > &neighbors, float *coefficients) const
calculates the upper triangular part of unnormalized covariance matrix over the normals given by the ...
Definition: harris_3d.hpp:106
void setRadiusSearch(double radius)
Set the sphere radius that is to be used for determining the nearest neighbors used for the feature e...
Definition: feature.h:199
NormalEstimation estimates local surface properties (surface normals and curvatures)at each 3D point...
Definition: normal_3d.h:241
void setThreshold(float threshold)
Set the threshold value for detecting corners.
Definition: harris_3d.hpp:71
uint32_t height
The point cloud height (if organized as an image-structure).
Definition: point_cloud.h:414
void setInputCloud(const PointCloudInConstPtr &cloud) override
Provide a pointer to the input dataset.
Definition: harris_3d.hpp:55
boost::shared_ptr< PointCloud< PointT > > Ptr
Definition: point_cloud.h:427
Keypoint represents the base class for key points.
Definition: keypoint.h:48
uint32_t width
The point cloud width (if organized as an image-structure).
Definition: point_cloud.h:412
PointCloudN::ConstPtr PointCloudNConstPtr
Definition: harris_3d.h:64
Surface normal estimation on organized data using integral images.
bool initCompute() override
Definition: harris_3d.hpp:195
void setRefine(bool do_refine)
Whether the detected key points should be refined or not.
Definition: harris_3d.hpp:85
void setNormalEstimationMethod(NormalEstimationMethod normal_estimation_method)
Set the normal estimation method.
void eigen33(const Matrix &mat, typename Matrix::Scalar &eigenvalue, Vector &eigenvector)
determines the eigenvector and eigenvalue of the smallest eigenvalue of the symmetric positive semi d...
Definition: eigen.hpp:251
void responseTomasi(PointCloudOut &output) const
Definition: harris_3d.hpp:455
void setInputCloud(const typename PointCloudIn::ConstPtr &cloud) override
Provide a pointer to the input dataset (overwrites the PCLBase::setInputCloud method) ...
void responseHarris(PointCloudOut &output) const
gets the corner response for valid input points
Definition: harris_3d.hpp:322
PointCloudIn::ConstPtr PointCloudInConstPtr
Definition: harris_3d.h:60
Matrix::Scalar invert3x3SymMatrix(const Matrix &matrix, Matrix &inverse)
Calculate the inverse of a 3x3 symmetric matrix.
Definition: eigen.hpp:504
void detectKeypoints(PointCloudOut &output) override
Abstract key point detection method.
Definition: harris_3d.hpp:241
void setNonMaxSupression(bool=false)
Whether non maxima suppression should be applied or the response for each point should be returned...
Definition: harris_3d.hpp:92
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields)...
Definition: point_cloud.h:417
void setMethod(ResponseMethod type)
Set the method of the response to be calculated.
Definition: harris_3d.hpp:64
void resize(size_t n)
Resize the cloud.
Definition: point_cloud.h:454
void compute(PointCloudOut &output)
Base method for feature estimation for all points given in <setInputCloud (), setIndices ()> using th...
Definition: feature.hpp:189
PointCloudN::Ptr PointCloudNPtr
Definition: harris_3d.h:63
void setInputCloud(const PointCloudConstPtr &cloud) override
Provide a pointer to the input dataset.
Definition: normal_3d.h:330
void responseCurvature(PointCloudOut &output) const
Definition: harris_3d.hpp:437
void setNormalSmoothingSize(float normal_smoothing_size)
Set the normal smoothing size.
void responseLowe(PointCloudOut &output) const
Definition: harris_3d.hpp:399
void responseNoble(PointCloudOut &output) const
Definition: harris_3d.hpp:361