41 #ifndef PCL_FEATURES_IMPL_CVFH_H_
42 #define PCL_FEATURES_IMPL_CVFH_H_
48 template<
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT>
void
65 computeFeature (output);
71 template<
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT>
void
77 std::vector<pcl::PointIndices> &clusters,
79 unsigned int min_pts_per_cluster,
80 unsigned int max_pts_per_cluster)
84 PCL_ERROR (
"[pcl::extractEuclideanClusters] Tree built for a different point cloud dataset (%zu) than the input cloud (%zu)!\n", tree->
getInputCloud ()->points.size (), cloud.
points.size ());
89 PCL_ERROR (
"[pcl::extractEuclideanClusters] Number of points in the input point cloud (%zu) different than normals (%zu)!\n", cloud.
points.size (), normals.
points.size ());
94 std::vector<bool> processed (cloud.
points.size (),
false);
96 std::vector<int> nn_indices;
97 std::vector<float> nn_distances;
99 for (
int i = 0; i < static_cast<int> (cloud.
points.size ()); ++i)
104 std::vector<unsigned int> seed_queue;
106 seed_queue.push_back (i);
110 while (sq_idx < static_cast<int> (seed_queue.size ()))
113 if (!tree->
radiusSearch (seed_queue[sq_idx], tolerance, nn_indices, nn_distances))
119 for (
size_t j = 1; j < nn_indices.size (); ++j)
121 if (processed[nn_indices[j]])
127 double dot_p = normals.
points[seed_queue[sq_idx]].normal[0] * normals.
points[nn_indices[j]].normal[0]
128 + normals.
points[seed_queue[sq_idx]].normal[1] * normals.
points[nn_indices[j]].normal[1]
129 + normals.
points[seed_queue[sq_idx]].normal[2] * normals.
points[nn_indices[j]].normal[2];
131 if (fabs (acos (dot_p)) < eps_angle)
133 processed[nn_indices[j]] =
true;
134 seed_queue.push_back (nn_indices[j]);
142 if (seed_queue.size () >= min_pts_per_cluster && seed_queue.size () <= max_pts_per_cluster)
145 r.
indices.resize (seed_queue.size ());
146 for (
size_t j = 0; j < seed_queue.size (); ++j)
153 clusters.push_back (r);
159 template<
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT>
void
162 std::vector<int> &indices_to_use,
163 std::vector<int> &indices_out,
164 std::vector<int> &indices_in,
167 indices_out.resize (cloud.
points.size ());
168 indices_in.resize (cloud.
points.size ());
173 for (
int i = 0; i < static_cast<int> (indices_to_use.size ()); i++)
175 if (cloud.
points[indices_to_use[i]].curvature > threshold)
177 indices_out[out] = indices_to_use[i];
182 indices_in[in] = indices_to_use[i];
187 indices_out.resize (out);
188 indices_in.resize (in);
192 template<
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT>
void
198 PCL_ERROR (
"[pcl::%s::computeFeature] No input dataset containing normals was given!\n", getClassName ().c_str ());
199 output.width = output.height = 0;
200 output.points.clear ();
203 if (normals_->points.size () != surface_->points.size ())
205 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 ());
206 output.width = output.height = 0;
207 output.points.clear ();
211 centroids_dominant_orientations_.clear ();
214 std::vector<int> indices_out;
215 std::vector<int> indices_in;
216 filterNormalsWithHighCurvature (*normals_, *indices_, indices_out, indices_in, curv_threshold_);
219 normals_filtered_cloud->width =
static_cast<uint32_t
> (indices_in.size ());
220 normals_filtered_cloud->height = 1;
221 normals_filtered_cloud->points.resize (normals_filtered_cloud->width);
223 for (
size_t i = 0; i < indices_in.size (); ++i)
225 normals_filtered_cloud->points[i].x = surface_->points[indices_in[i]].x;
226 normals_filtered_cloud->points[i].y = surface_->points[indices_in[i]].y;
227 normals_filtered_cloud->points[i].z = surface_->points[indices_in[i]].z;
230 std::vector<pcl::PointIndices> clusters;
232 if(normals_filtered_cloud->points.size() >= min_points_)
236 normals_tree_filtered->setInputCloud (normals_filtered_cloud);
239 n3d.setRadiusSearch (radius_normals_);
240 n3d.setSearchMethod (normals_tree_filtered);
241 n3d.setInputCloud (normals_filtered_cloud);
242 n3d.compute (*normals_filtered_cloud);
245 normals_tree->setInputCloud (normals_filtered_cloud);
247 extractEuclideanClustersSmooth (*normals_filtered_cloud,
248 *normals_filtered_cloud,
252 eps_angle_threshold_,
253 static_cast<unsigned int> (min_points_));
258 vfh.setInputCloud (surface_);
259 vfh.setInputNormals (normals_);
260 vfh.setIndices(indices_);
261 vfh.setSearchMethod (this->tree_);
262 vfh.setUseGivenNormal (
true);
263 vfh.setUseGivenCentroid (
true);
264 vfh.setNormalizeBins (normalize_bins_);
265 vfh.setNormalizeDistance (
true);
266 vfh.setFillSizeComponent (
true);
270 if (clusters.size () > 0)
273 for (
size_t i = 0; i < clusters.size (); ++i)
275 Eigen::Vector4f avg_normal = Eigen::Vector4f::Zero ();
276 Eigen::Vector4f avg_centroid = Eigen::Vector4f::Zero ();
278 for (
size_t j = 0; j < clusters[i].indices.size (); j++)
280 avg_normal += normals_filtered_cloud->points[clusters[i].indices[j]].getNormalVector4fMap ();
281 avg_centroid += normals_filtered_cloud->points[clusters[i].indices[j]].getVector4fMap ();
284 avg_normal /=
static_cast<float> (clusters[i].indices.size ());
285 avg_centroid /=
static_cast<float> (clusters[i].indices.size ());
287 Eigen::Vector4f centroid_test;
289 avg_normal.normalize ();
291 Eigen::Vector3f avg_norm (avg_normal[0], avg_normal[1], avg_normal[2]);
292 Eigen::Vector3f avg_dominant_centroid (avg_centroid[0], avg_centroid[1], avg_centroid[2]);
295 dominant_normals_.push_back (avg_norm);
296 centroids_dominant_orientations_.push_back (avg_dominant_centroid);
300 output.points.resize (dominant_normals_.size ());
301 output.width =
static_cast<uint32_t
> (dominant_normals_.size ());
303 for (
size_t i = 0; i < dominant_normals_.size (); ++i)
306 vfh.setNormalToUse (dominant_normals_[i]);
307 vfh.setCentroidToUse (centroids_dominant_orientations_[i]);
309 vfh.compute (vfh_signature);
315 Eigen::Vector4f avg_centroid;
317 Eigen::Vector3f cloud_centroid (avg_centroid[0], avg_centroid[1], avg_centroid[2]);
318 centroids_dominant_orientations_.push_back (cloud_centroid);
321 vfh.setCentroidToUse (cloud_centroid);
322 vfh.setUseGivenNormal (
false);
325 vfh.compute (vfh_signature);
330 output.points[0] = vfh_signature.
points[0];
334 #define PCL_INSTANTIATE_CVFHEstimation(T,NT,OutT) template class PCL_EXPORTS pcl::CVFHEstimation<T,NT,OutT>;
336 #endif // PCL_FEATURES_IMPL_VFH_H_