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/auto.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_)
240 n3d.
compute (*normals_filtered_cloud);
244 extractEuclideanClustersSmooth (*normals_filtered_cloud,
245 *normals_filtered_cloud,
249 eps_angle_threshold_,
250 static_cast<unsigned int> (min_points_));
255 vfh.setInputCloud (surface_);
256 vfh.setInputNormals (normals_);
257 vfh.setIndices(indices_);
258 vfh.setSearchMethod (this->tree_);
259 vfh.setUseGivenNormal (
true);
260 vfh.setUseGivenCentroid (
true);
261 vfh.setNormalizeBins (normalize_bins_);
262 vfh.setNormalizeDistance (
true);
263 vfh.setFillSizeComponent (
true);
267 if (!clusters.empty ())
270 for (
const auto &cluster : clusters)
272 Eigen::Vector4f avg_normal = Eigen::Vector4f::Zero ();
273 Eigen::Vector4f avg_centroid = Eigen::Vector4f::Zero ();
275 for (
const auto &index : cluster.indices)
277 avg_normal += (*normals_filtered_cloud)[index].getNormalVector4fMap ();
278 avg_centroid += (*normals_filtered_cloud)[index].getVector4fMap ();
281 avg_normal /=
static_cast<float> (cluster.indices.size ());
282 avg_centroid /=
static_cast<float> (cluster.indices.size ());
284 Eigen::Vector4f centroid_test;
286 avg_normal.normalize ();
288 Eigen::Vector3f avg_norm (avg_normal[0], avg_normal[1], avg_normal[2]);
289 Eigen::Vector3f avg_dominant_centroid (avg_centroid[0], avg_centroid[1], avg_centroid[2]);
292 dominant_normals_.push_back (avg_norm);
293 centroids_dominant_orientations_.push_back (avg_dominant_centroid);
297 output.resize (dominant_normals_.size ());
298 output.width = dominant_normals_.size ();
300 for (std::size_t i = 0; i < dominant_normals_.size (); ++i)
303 vfh.setNormalToUse (dominant_normals_[i]);
304 vfh.setCentroidToUse (centroids_dominant_orientations_[i]);
306 vfh.compute (vfh_signature);
307 output[i] = vfh_signature[0];
312 Eigen::Vector4f avg_centroid;
314 Eigen::Vector3f cloud_centroid (avg_centroid[0], avg_centroid[1], avg_centroid[2]);
315 centroids_dominant_orientations_.push_back (cloud_centroid);
318 vfh.setCentroidToUse (cloud_centroid);
319 vfh.setUseGivenNormal (
false);
322 vfh.compute (vfh_signature);
327 output[0] = vfh_signature[0];
331 #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 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
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.
@ radius_search
The search method will mainly be used for radiusSearch.
IndicesAllocator<> Indices
Type used for indices in PCL.