38#ifndef PCL_ISS_KEYPOINT3D_IMPL_H_
39#define PCL_ISS_KEYPOINT3D_IMPL_H_
41#include <Eigen/Eigenvalues>
42#include <pcl/features/boundary.h>
43#include <pcl/features/normal_3d.h>
44#include <pcl/features/integral_image_normal.h>
46#include <pcl/keypoints/iss_3d.h>
49template<
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
56template<
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
63template<
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
70template<
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
77template<
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
84template<
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
91template<
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
98template<
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
105template<
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
119template<
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
bool*
122 bool* edge_points =
new bool [input.size ()];
124 Eigen::Vector4f u = Eigen::Vector4f::Zero ();
125 Eigen::Vector4f v = Eigen::Vector4f::Zero ();
130#pragma omp parallel for \
132 shared(angle_threshold, boundary_estimator, border_radius, edge_points, input) \
134 num_threads(threads_)
135 for (
int index = 0; index < static_cast<int>(input.size ()); index++)
137 edge_points[index] =
false;
138 PointInT current_point = input[index];
143 std::vector<float> nn_distances;
148 n_neighbors =
static_cast<int> (nn_indices.size ());
154 if (boundary_estimator.
isBoundaryPoint (input,
static_cast<int> (index), nn_indices, u, v, angle_threshold))
155 edge_points[index] =
true;
160 return (edge_points);
164template<
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
167 const PointInT& current_point = (*input_)[current_index];
169 double central_point[3]{};
171 central_point[0] = current_point.x;
172 central_point[1] = current_point.y;
173 central_point[2] = current_point.z;
175 cov_m = Eigen::Matrix3d::Zero ();
178 std::vector<float> nn_distances;
183 n_neighbors =
static_cast<int> (nn_indices.size ());
190 for (
const auto& n_idx : nn_indices)
192 const PointInT& n_point = (*input_)[n_idx];
194 double neigh_point[3]{};
196 neigh_point[0] = n_point.x;
197 neigh_point[1] = n_point.y;
198 neigh_point[2] = n_point.z;
200 for (
int i = 0; i < 3; i++)
201 for (
int j = 0; j < 3; j++)
202 cov[i * 3 + j] += (neigh_point[i] - central_point[i]) * (neigh_point[j] - central_point[j]);
205 cov_m << cov[0], cov[1], cov[2],
206 cov[3], cov[4], cov[5],
207 cov[6], cov[7], cov[8];
211template<
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
bool
216 PCL_ERROR (
"[pcl::%s::initCompute] init failed!\n",
name_.c_str ());
221 PCL_ERROR (
"[pcl::%s::initCompute] : the salient radius (%f) must be strict positive!\n",
227 PCL_ERROR (
"[pcl::%s::initCompute] : the non maxima radius (%f) must be strict positive!\n",
233 PCL_ERROR (
"[pcl::%s::initCompute] : the threshold on the ratio between the 2nd and the 1rst eigenvalue (%f) must be strict positive!\n",
239 PCL_ERROR (
"[pcl::%s::initCompute] : the threshold on the ratio between the 3rd and the 2nd eigenvalue (%f) must be strict positive!\n",
245 PCL_ERROR (
"[pcl::%s::initCompute] : the minimum number of neighbors (%f) must be strict positive!\n",
262 PCL_ERROR (
"[pcl::%s::initCompute] : the radius used to estimate surface normals (%f) must be positive!\n",
273 normal_estimation.
compute (*normal_ptr);
281 normal_estimation.
compute (*normal_ptr);
287 PCL_ERROR (
"[pcl::%s::initCompute] normals given, but the number of normals does not match the number of input points!\n",
name_.c_str ());
293 PCL_ERROR (
"[pcl::%s::initCompute] : the border radius used to estimate boundary points (%f) must be positive!\n",
302template<
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
311 bool* borders =
new bool [
input_->size()];
313#pragma omp parallel for \
316 num_threads(threads_)
317 for (
int index = 0; index < static_cast<int>(
input_->size ()); index++)
319 borders[index] =
false;
320 PointInT current_point = (*input_)[index];
325 std::vector<float> nn_distances;
329 for (
const auto &nn_index : nn_indices)
333 borders[index] =
true;
341 auto *omp_mem =
new Eigen::Vector3d[
threads_];
343 for (std::size_t i = 0; i <
threads_; i++)
344 omp_mem[i].setZero (3);
346 auto *omp_mem =
new Eigen::Vector3d[1];
348 omp_mem[0].setZero (3);
351 double *prg_local_mem =
new double[
input_->size () * 3];
352 double **prg_mem =
new double * [
input_->size ()];
354 for (std::size_t i = 0; i <
input_->size (); i++)
355 prg_mem[i] = prg_local_mem + 3 * i;
357#pragma omp parallel for \
359 shared(borders, omp_mem, prg_mem) \
360 num_threads(threads_)
361 for (
int index = 0; index < static_cast<int> (
input_->size ()); index++)
364 int tid = omp_get_thread_num ();
368 PointInT current_point = (*input_)[index];
373 Eigen::Matrix3d cov_m = Eigen::Matrix3d::Zero ();
376 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> solver (cov_m);
378 const double& e1c = solver.eigenvalues ()[2];
379 const double& e2c = solver.eigenvalues ()[1];
380 const double& e3c = solver.eigenvalues ()[0];
382 if (!std::isfinite (e1c) || !std::isfinite (e2c) || !std::isfinite (e3c))
387 PCL_WARN (
"[pcl::%s::detectKeypoints] : The third eigenvalue is negative! Skipping the point with index %i.\n",
388 name_.c_str (), index);
392 omp_mem[tid][0] = e2c / e1c;
393 omp_mem[tid][1] = e3c / e2c;
394 omp_mem[tid][2] = e3c;
397 for (Eigen::Index d = 0; d < omp_mem[tid].size (); d++)
398 prg_mem[index][d] = omp_mem[tid][d];
401 for (
int index = 0; index < static_cast<int>(
input_->size ()); index++)
410 bool* feat_max =
new bool [
input_->size()];
412#pragma omp parallel for \
415 num_threads(threads_)
416 for (
int index = 0; index < static_cast<int>(
input_->size ()); index++)
418 feat_max [index] =
false;
419 PointInT current_point = (*input_)[index];
424 std::vector<float> nn_distances;
429 n_neighbors =
static_cast<int> (nn_indices.size ());
435 for (
const auto& j : nn_indices)
439 feat_max[index] =
true;
444#pragma omp parallel for \
446 shared(feat_max, output) \
447 num_threads(threads_)
448 for (
int index = 0; index < static_cast<int>(
input_->size ()); index++)
454 p.getVector3fMap () = (*input_)[index].getVector3fMap ();
460 output.header =
input_->header;
461 output.width = output.size ();
470 delete[] prg_local_mem;
475#define PCL_INSTANTIATE_ISSKeypoint3D(T,U,N) template class PCL_EXPORTS pcl::ISSKeypoint3D<T,U,N>;
BoundaryEstimation estimates whether a set of points is lying on surface boundaries using an angle cr...
void getCoordinateSystemOnPlane(const PointNT &p_coeff, Eigen::Vector4f &u, Eigen::Vector4f &v)
Get a u-v-n coordinate system that lies on a plane defined by its normal.
bool isBoundaryPoint(const pcl::PointCloud< PointInT > &cloud, int q_idx, const pcl::Indices &indices, const Eigen::Vector4f &u, const Eigen::Vector4f &v, const float angle_threshold)
Check whether a point is a boundary point in a planar patch of projected points given by indices.
void setRadiusSearch(double radius)
Set the sphere radius that is to be used for determining the nearest neighbors used for the feature e...
void compute(PointCloudOut &output)
Base method for feature estimation for all points given in <setInputCloud (), setIndices ()> using th...
pcl::PointCloud< NormalT > PointCloudN
double * third_eigen_value_
Store the third eigen value associated to each point in the input cloud.
typename PointCloudN::ConstPtr PointCloudNConstPtr
void setNumberOfThreads(unsigned int nr_threads=0)
Initialize the scheduler and set the number of threads to use.
typename Keypoint< PointInT, PointOutT >::PointCloudIn PointCloudIn
void setNormals(const PointCloudNConstPtr &normals)
Set the normals if pre-calculated normals are available.
double gamma_32_
The upper bound on the ratio between the third and the second eigenvalue returned by the EVD.
void setBorderRadius(double border_radius)
Set the radius used for the estimation of the boundary points.
void setSalientRadius(double salient_radius)
Set the radius of the spherical neighborhood used to compute the scatter matrix.
void getScatterMatrix(const int ¤t_index, Eigen::Matrix3d &cov_m)
Compute the scatter matrix for a point index.
double salient_radius_
The radius of the spherical neighborhood used to compute the scatter matrix.
bool * edge_points_
Store the information about the boundary points of the input cloud.
void setThreshold21(double gamma_21)
Set the upper bound on the ratio between the second and the first eigenvalue.
void setMinNeighbors(int min_neighbors)
Set the minimum number of neighbors that has to be found while applying the non maxima suppression al...
double gamma_21_
The upper bound on the ratio between the second and the first eigenvalue returned by the EVD.
void setNormalRadius(double normal_radius)
Set the radius used for the estimation of the surface normals of the input cloud.
double non_max_radius_
The non maxima suppression radius.
void setThreshold32(double gamma_32)
Set the upper bound on the ratio between the third and the second eigenvalue.
PointCloudNConstPtr normals_
The cloud of normals related to the input surface.
unsigned int threads_
The number of threads that has to be used by the scheduler.
float angle_threshold_
The decision boundary (angle threshold) that marks points as boundary or regular.
bool initCompute() override
Perform the initial checks before computing the keypoints.
double normal_radius_
The radius used to compute the normals of the input cloud.
double border_radius_
The radius used to compute the boundary points of the input cloud.
typename PointCloudN::Ptr PointCloudNPtr
void setNonMaxRadius(double non_max_radius)
Set the radius for the application of the non maxima suppression algorithm.
int min_neighbors_
Minimum number of neighbors that has to be found while applying the non maxima suppression algorithm.
bool * getBoundaryPoints(PointCloudIn &input, double border_radius, float angle_threshold)
Compute the boundary points for the given input cloud.
void detectKeypoints(PointCloudOut &output) override
Detect the keypoints by performing the EVD of the scatter matrix.
typename Keypoint< PointInT, PointOutT >::PointCloudOut PointCloudOut
Surface normal estimation on organized data using integral images.
void setNormalEstimationMethod(NormalEstimationMethod normal_estimation_method)
Set the normal estimation method.
void setInputCloud(const typename PointCloudIn::ConstPtr &cloud) override
Provide a pointer to the input dataset (overwrites the PCLBase::setInputCloud method)
void setNormalSmoothingSize(float normal_smoothing_size)
Set the normal smoothing size.
virtual bool initCompute()
pcl::PointIndicesPtr keypoints_indices_
PointCloudInConstPtr surface_
int searchForNeighbors(pcl::index_t index, double parameter, pcl::Indices &indices, std::vector< float > &distances) const
NormalEstimation estimates local surface properties (surface normals and curvatures)at each 3D point.
void setInputCloud(const PointCloudConstPtr &cloud) override
Provide a pointer to the input dataset.
PointCloudConstPtr input_
virtual void setInputCloud(const PointCloudConstPtr &cloud)
Provide a pointer to the input dataset.
PointCloud represents the base class in PCL for storing collections of 3D points.
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...
IndicesAllocator<> Indices
Type used for indices in PCL.