41 #ifndef PCL_FEATURES_IMPL_CVFH_H_
42 #define PCL_FEATURES_IMPL_CVFH_H_
44 #include <pcl/features/cvfh.h>
45 #include <pcl/features/normal_3d.h>
47 #include <pcl/search/kdtree.h>
50 template<
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT>
void
55 output.width = output.height = 0;
63 output.width = output.height = 1;
67 computeFeature (output);
73 template<
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT>
void
79 std::vector<pcl::PointIndices> &clusters,
81 unsigned int min_pts_per_cluster,
82 unsigned int max_pts_per_cluster)
86 PCL_ERROR(
"[pcl::extractEuclideanClusters] Tree built for a different point cloud "
87 "dataset (%zu) than the input cloud (%zu)!\n",
89 static_cast<std::size_t
>(cloud.
size()));
92 if (cloud.
size () != normals.
size ())
94 PCL_ERROR(
"[pcl::extractEuclideanClusters] Number of points in the input point "
95 "cloud (%zu) different than normals (%zu)!\n",
96 static_cast<std::size_t
>(cloud.
size()),
97 static_cast<std::size_t
>(normals.
size()));
104 std::vector<bool> processed (cloud.
size (),
false);
107 std::vector<float> nn_distances;
109 for (std::size_t i = 0; i < cloud.
size (); ++i)
119 seed_queue.push_back (i);
122 for (std::size_t idx = 0; idx != seed_queue.size (); ++idx)
125 if (!tree->
radiusSearch (seed_queue[idx], tolerance, nn_indices, nn_distances))
130 for (std::size_t j = nn_start_idx; j < nn_indices.size (); ++j)
132 if (processed[nn_indices[j]])
137 const double dot_p = normals[seed_queue[idx]].getNormalVector3fMap().dot(
138 normals[nn_indices[j]].getNormalVector3fMap());
140 if (std::acos (dot_p) < eps_angle)
142 processed[nn_indices[j]] =
true;
149 if (seed_queue.size () >= min_pts_per_cluster && seed_queue.size () <= max_pts_per_cluster)
155 clusters.emplace_back (std::move(r));
161 template<
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT>
void
169 indices_out.resize (cloud.
size ());
170 indices_in.resize (cloud.
size ());
175 for (
const auto &index : indices_to_use)
177 if (cloud[index].curvature > threshold)
179 indices_out[out] = index;
184 indices_in[in] = index;
189 indices_out.resize (out);
190 indices_in.resize (in);
194 template<
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT>
void
200 PCL_ERROR (
"[pcl::%s::computeFeature] No input dataset containing normals was given!\n", getClassName ().c_str ());
201 output.width = output.height = 0;
205 if (normals_->size () != surface_->size ())
207 PCL_ERROR (
"[pcl::%s::computeFeature] The number of points in the input dataset differs from the number of points in the dataset containing the normals!\n", getClassName ().c_str ());
208 output.width = output.height = 0;
213 centroids_dominant_orientations_.clear ();
218 filterNormalsWithHighCurvature (*normals_, *indices_, indices_out, indices_in, curv_threshold_);
221 normals_filtered_cloud->width = indices_in.size ();
222 normals_filtered_cloud->height = 1;
223 normals_filtered_cloud->points.resize (normals_filtered_cloud->width);
225 for (std::size_t i = 0; i < indices_in.size (); ++i)
227 (*normals_filtered_cloud)[i].x = (*surface_)[indices_in[i]].x;
228 (*normals_filtered_cloud)[i].y = (*surface_)[indices_in[i]].y;
229 (*normals_filtered_cloud)[i].z = (*surface_)[indices_in[i]].z;
232 std::vector<pcl::PointIndices> clusters;
234 if(normals_filtered_cloud->size() >= min_points_)
238 normals_tree_filtered->setInputCloud (normals_filtered_cloud);
245 n3d.
compute (*normals_filtered_cloud);
248 normals_tree->setInputCloud (normals_filtered_cloud);
250 extractEuclideanClustersSmooth (*normals_filtered_cloud,
251 *normals_filtered_cloud,
255 eps_angle_threshold_,
256 static_cast<unsigned int> (min_points_));
261 vfh.setInputCloud (surface_);
262 vfh.setInputNormals (normals_);
263 vfh.setIndices(indices_);
264 vfh.setSearchMethod (this->tree_);
265 vfh.setUseGivenNormal (
true);
266 vfh.setUseGivenCentroid (
true);
267 vfh.setNormalizeBins (normalize_bins_);
268 vfh.setNormalizeDistance (
true);
269 vfh.setFillSizeComponent (
true);
273 if (!clusters.empty ())
276 for (
const auto &cluster : clusters)
278 Eigen::Vector4f avg_normal = Eigen::Vector4f::Zero ();
279 Eigen::Vector4f avg_centroid = Eigen::Vector4f::Zero ();
281 for (
const auto &index : cluster.indices)
283 avg_normal += (*normals_filtered_cloud)[index].getNormalVector4fMap ();
284 avg_centroid += (*normals_filtered_cloud)[index].getVector4fMap ();
287 avg_normal /=
static_cast<float> (cluster.indices.size ());
288 avg_centroid /=
static_cast<float> (cluster.indices.size ());
290 Eigen::Vector4f centroid_test;
292 avg_normal.normalize ();
294 Eigen::Vector3f avg_norm (avg_normal[0], avg_normal[1], avg_normal[2]);
295 Eigen::Vector3f avg_dominant_centroid (avg_centroid[0], avg_centroid[1], avg_centroid[2]);
298 dominant_normals_.push_back (avg_norm);
299 centroids_dominant_orientations_.push_back (avg_dominant_centroid);
303 output.resize (dominant_normals_.size ());
304 output.width = dominant_normals_.size ();
306 for (std::size_t i = 0; i < dominant_normals_.size (); ++i)
309 vfh.setNormalToUse (dominant_normals_[i]);
310 vfh.setCentroidToUse (centroids_dominant_orientations_[i]);
312 vfh.compute (vfh_signature);
313 output[i] = vfh_signature[0];
318 Eigen::Vector4f avg_centroid;
320 Eigen::Vector3f cloud_centroid (avg_centroid[0], avg_centroid[1], avg_centroid[2]);
321 centroids_dominant_orientations_.push_back (cloud_centroid);
324 vfh.setCentroidToUse (cloud_centroid);
325 vfh.setUseGivenNormal (
false);
328 vfh.compute (vfh_signature);
333 output[0] = vfh_signature[0];
337 #define PCL_INSTANTIATE_CVFHEstimation(T,NT,OutT) template class PCL_EXPORTS pcl::CVFHEstimation<T,NT,OutT>;
Define methods for centroid estimation and covariance matrix calculus.
CVFHEstimation estimates the Clustered Viewpoint Feature Histogram (CVFH) descriptor for a given poin...
typename Feature< PointInT, PointOutT >::PointCloudOut PointCloudOut
void filterNormalsWithHighCurvature(const pcl::PointCloud< PointNT > &cloud, pcl::Indices &indices_to_use, pcl::Indices &indices_out, pcl::Indices &indices_in, float threshold)
Removes normals with high curvature caused by real edges or noisy data.
void compute(PointCloudOut &output)
Overloaded computed method from pcl::Feature.
Feature represents the base feature class.
void setRadiusSearch(double radius)
Set the sphere radius that is to be used for determining the nearest neighbors used for the feature e...
void setSearchMethod(const KdTreePtr &tree)
Provide a pointer to the search object.
void compute(PointCloudOut &output)
Base method for feature estimation for all points given in <setInputCloud (), setIndices ()> using th...
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.
void resize(std::size_t count)
Resizes the container to contain count elements.
reference emplace_back(Args &&...args)
Emplace a new point in the cloud, at the end of the container.
pcl::PCLHeader header
The point cloud header.
shared_ptr< PointCloud< PointT > > Ptr
search::KdTree is a wrapper class which inherits the pcl::KdTree class for performing search function...
virtual bool getSortedResults()
Gets whether the results should be sorted (ascending in the distance) or not Otherwise the results ma...
shared_ptr< pcl::search::Search< PointT > > Ptr
virtual PointCloudConstPtr getInputCloud() const
Get a pointer to the input point cloud dataset.
virtual int radiusSearch(const PointT &point, double radius, Indices &k_indices, std::vector< float > &k_sqr_distances, unsigned int max_nn=0) const =0
Search for all the nearest neighbors of the query point in a given radius.
unsigned int compute3DCentroid(ConstCloudIterator< PointT > &cloud_iterator, Eigen::Matrix< Scalar, 4, 1 > ¢roid)
Compute the 3D (X-Y-Z) centroid of a set of points and return it as a 3D vector.
IndicesAllocator<> Indices
Type used for indices in PCL.