42#include <pcl/console/print.h>
43#include <pcl/pcl_base.h>
45#include <pcl/search/search.h>
47#include <pcl/kdtree/kdtree.h>
63 template <
typename Po
intT>
void
66 float tolerance, std::vector<PointIndices> &clusters,
67 unsigned int min_pts_per_cluster = 1,
unsigned int max_pts_per_cluster = (std::numeric_limits<int>::max) ());
81 template <
typename Po
intT>
void
85 unsigned int min_pts_per_cluster = 1,
unsigned int max_pts_per_cluster = (std::numeric_limits<int>::max) ());
105 template <
typename Po
intT,
typename Normal>
106 PCL_DEPRECATED(1, 19,
"use a search method inheriting from pcl::search::Search instead")
110 float tolerance, const typename KdTree<
PointT>::Ptr &tree,
111 std::vector<PointIndices> &clusters,
double eps_angle,
112 unsigned int min_pts_per_cluster = 1,
113 unsigned int max_pts_per_cluster = (std::numeric_limits<
int>::max) ())
115 if (tree->getInputCloud ()->size () != cloud.size ())
117 PCL_ERROR(
"[pcl::extractEuclideanClusters] Tree built for a different point "
118 "cloud dataset (%zu) than the input cloud (%zu)!\n",
119 static_cast<std::size_t
>(tree->getInputCloud()->size()),
120 static_cast<std::size_t
>(cloud.size()));
123 if (cloud.size () != normals.size ())
125 PCL_ERROR(
"[pcl::extractEuclideanClusters] Number of points in the input point "
126 "cloud (%zu) different than normals (%zu)!\n",
127 static_cast<std::size_t
>(cloud.size()),
128 static_cast<std::size_t
>(normals.size()));
132 const std::size_t nn_start_idx = tree->getSortedResults () ? 1 : 0;
133 const double cos_eps_angle = std::cos (eps_angle);
136 std::vector<bool> processed (cloud.size (),
false);
139 std::vector<float> nn_distances;
141 for (std::size_t i = 0; i < cloud.size (); ++i)
148 seed_queue.push_back (
static_cast<index_t> (i));
152 while (sq_idx <
static_cast<int> (seed_queue.size ()))
155 if (!tree->radiusSearch (seed_queue[sq_idx], tolerance, nn_indices, nn_distances))
161 for (std::size_t j = nn_start_idx; j < nn_indices.size (); ++j)
163 if (processed[nn_indices[j]])
168 double dot_p = normals[seed_queue[sq_idx]].normal[0] * normals[nn_indices[j]].normal[0] +
169 normals[seed_queue[sq_idx]].normal[1] * normals[nn_indices[j]].normal[1] +
170 normals[seed_queue[sq_idx]].normal[2] * normals[nn_indices[j]].normal[2];
171 if ( std::abs (dot_p) > cos_eps_angle )
173 processed[nn_indices[j]] =
true;
174 seed_queue.push_back (nn_indices[j]);
182 if (seed_queue.size () >= min_pts_per_cluster && seed_queue.size () <= max_pts_per_cluster)
185 r.
indices.resize (seed_queue.size ());
186 for (std::size_t j = 0; j < seed_queue.size (); ++j)
193 clusters.push_back (r);
197 PCL_DEBUG(
"[pcl::extractEuclideanClusters] This cluster has %zu points, which is not between %u and %u points, so it is not a final cluster\n",
198 seed_queue.size (), min_pts_per_cluster, max_pts_per_cluster);
222 template <
typename Po
intT,
typename Normal>
223 PCL_DEPRECATED(1, 19,
"use a search method inheriting from pcl::search::Search instead")
227 const
Indices &indices, const typename KdTree<
PointT>::Ptr &tree,
228 float tolerance, std::vector<PointIndices> &clusters,
double eps_angle,
229 unsigned int min_pts_per_cluster = 1,
230 unsigned int max_pts_per_cluster = (std::numeric_limits<
int>::max) ())
234 if (tree->getInputCloud()->size() != cloud.size()) {
235 PCL_ERROR(
"[pcl::extractEuclideanClusters] Tree built for a different point "
236 "cloud dataset (%zu) than the input cloud (%zu)!\n",
237 static_cast<std::size_t
>(tree->getInputCloud()->size()),
238 static_cast<std::size_t
>(cloud.size()));
241 if (tree->getIndices()->size() != indices.size()) {
242 PCL_ERROR(
"[pcl::extractEuclideanClusters] Tree built for a different set of "
243 "indices (%zu) than the input set (%zu)!\n",
244 static_cast<std::size_t
>(tree->getIndices()->size()),
248 if (cloud.size() != normals.size()) {
249 PCL_ERROR(
"[pcl::extractEuclideanClusters] Number of points in the input point "
250 "cloud (%zu) different than normals (%zu)!\n",
251 static_cast<std::size_t
>(cloud.size()),
252 static_cast<std::size_t
>(normals.size()));
256 const std::size_t nn_start_idx = tree->getSortedResults () ? 1 : 0;
257 const double cos_eps_angle = std::cos (eps_angle);
259 std::vector<bool> processed (cloud.size (),
false);
262 std::vector<float> nn_distances;
264 for (
const auto& point_idx : indices)
266 if (processed[point_idx])
271 seed_queue.push_back (point_idx);
273 processed[point_idx] =
true;
275 while (sq_idx <
static_cast<int> (seed_queue.size ()))
278 if (!tree->radiusSearch (cloud[seed_queue[sq_idx]], tolerance, nn_indices, nn_distances))
284 for (std::size_t j = nn_start_idx; j < nn_indices.size (); ++j)
286 if (processed[nn_indices[j]])
291 double dot_p = normals[seed_queue[sq_idx]].normal[0] * normals[nn_indices[j]].normal[0] +
292 normals[seed_queue[sq_idx]].normal[1] * normals[nn_indices[j]].normal[1] +
293 normals[seed_queue[sq_idx]].normal[2] * normals[nn_indices[j]].normal[2];
294 if ( std::abs (dot_p) > cos_eps_angle )
296 processed[nn_indices[j]] =
true;
297 seed_queue.push_back (nn_indices[j]);
305 if (seed_queue.size () >= min_pts_per_cluster && seed_queue.size () <= max_pts_per_cluster)
308 r.
indices.resize (seed_queue.size ());
309 for (std::size_t j = 0; j < seed_queue.size (); ++j)
316 clusters.push_back (r);
320 PCL_DEBUG(
"[pcl::extractEuclideanClusters] This cluster has %zu points, which is not between %u and %u points, so it is not a final cluster\n",
321 seed_queue.size (), min_pts_per_cluster, max_pts_per_cluster);
344 template <
typename Po
intT,
typename Normal>
349 std::vector<PointIndices> &clusters,
double eps_angle,
350 unsigned int min_pts_per_cluster = 1,
351 unsigned int max_pts_per_cluster = (std::numeric_limits<int>::max) ())
355 PCL_ERROR(
"[pcl::extractEuclideanClusters] Tree built for a different point "
356 "cloud dataset (%zu) than the input cloud (%zu)!\n",
358 static_cast<std::size_t
>(cloud.
size()));
361 if (cloud.
size () != normals.
size ())
363 PCL_ERROR(
"[pcl::extractEuclideanClusters] Number of points in the input point "
364 "cloud (%zu) different than normals (%zu)!\n",
365 static_cast<std::size_t
>(cloud.
size()),
366 static_cast<std::size_t
>(normals.
size()));
371 const double cos_eps_angle = std::cos (eps_angle);
374 std::vector<bool> processed (cloud.
size (),
false);
377 std::vector<float> nn_distances;
379 for (std::size_t i = 0; i < cloud.
size (); ++i)
386 seed_queue.push_back (
static_cast<index_t> (i));
390 while (sq_idx <
static_cast<int> (seed_queue.size ()))
393 if (!tree->
radiusSearch (cloud[seed_queue[sq_idx]], tolerance, nn_indices, nn_distances))
399 for (std::size_t j = nn_start_idx; j < nn_indices.size (); ++j)
401 if (processed[nn_indices[j]])
406 double dot_p = normals[seed_queue[sq_idx]].normal[0] * normals[nn_indices[j]].normal[0] +
407 normals[seed_queue[sq_idx]].normal[1] * normals[nn_indices[j]].normal[1] +
408 normals[seed_queue[sq_idx]].normal[2] * normals[nn_indices[j]].normal[2];
409 if ( std::abs (dot_p) > cos_eps_angle )
411 processed[nn_indices[j]] =
true;
420 if (seed_queue.size () >= min_pts_per_cluster && seed_queue.size () <= max_pts_per_cluster)
423 r.
indices.resize (seed_queue.size ());
424 for (std::size_t j = 0; j < seed_queue.size (); ++j)
431 clusters.push_back (r);
435 PCL_DEBUG(
"[pcl::extractEuclideanClusters] This cluster has %zu points, which is not between %u and %u points, so it is not a final cluster\n",
436 seed_queue.size (), min_pts_per_cluster, max_pts_per_cluster);
460 template <
typename Po
intT,
typename Normal>
465 float tolerance, std::vector<PointIndices> &clusters,
double eps_angle,
466 unsigned int min_pts_per_cluster = 1,
467 unsigned int max_pts_per_cluster = (std::numeric_limits<int>::max) ())
472 PCL_ERROR(
"[pcl::extractEuclideanClusters] Tree built for a different point "
473 "cloud dataset (%zu) than the input cloud (%zu)!\n",
475 static_cast<std::size_t
>(cloud.
size()));
480 PCL_ERROR(
"[pcl::extractEuclideanClusters] Tree was built without indices, but an indices set was provided!\n");
483 if (tree_indices->size() != indices.size()) {
484 PCL_ERROR(
"[pcl::extractEuclideanClusters] Tree built for a different set of "
485 "indices (%zu) than the input set (%zu)!\n",
486 static_cast<std::size_t
>(tree_indices->size()),
490 if (cloud.
size() != normals.
size()) {
491 PCL_ERROR(
"[pcl::extractEuclideanClusters] Number of points in the input point "
492 "cloud (%zu) different than normals (%zu)!\n",
493 static_cast<std::size_t
>(cloud.
size()),
494 static_cast<std::size_t
>(normals.
size()));
499 const double cos_eps_angle = std::cos (eps_angle);
501 std::vector<bool> processed (cloud.
size (),
false);
504 std::vector<float> nn_distances;
506 for (
const auto& point_idx : indices)
508 if (processed[point_idx])
513 seed_queue.push_back (point_idx);
515 processed[point_idx] =
true;
517 while (sq_idx <
static_cast<int> (seed_queue.size ()))
520 if (!tree->
radiusSearch (cloud[seed_queue[sq_idx]], tolerance, nn_indices, nn_distances))
526 for (std::size_t j = nn_start_idx; j < nn_indices.size (); ++j)
528 if (processed[nn_indices[j]])
533 double dot_p = normals[seed_queue[sq_idx]].normal[0] * normals[nn_indices[j]].normal[0] +
534 normals[seed_queue[sq_idx]].normal[1] * normals[nn_indices[j]].normal[1] +
535 normals[seed_queue[sq_idx]].normal[2] * normals[nn_indices[j]].normal[2];
536 if ( std::abs (dot_p) > cos_eps_angle )
538 processed[nn_indices[j]] =
true;
547 if (seed_queue.size () >= min_pts_per_cluster && seed_queue.size () <= max_pts_per_cluster)
550 r.
indices.resize (seed_queue.size ());
551 for (std::size_t j = 0; j < seed_queue.size (); ++j)
558 clusters.push_back (r);
562 PCL_DEBUG(
"[pcl::extractEuclideanClusters] This cluster has %zu points, which is not between %u and %u points, so it is not a final cluster\n",
563 seed_queue.size (), min_pts_per_cluster, max_pts_per_cluster);
575 template <
typename Po
intT>
665 extract (std::vector<PointIndices> &clusters);
687 virtual std::string
getClassName ()
const {
return (
"EuclideanClusterExtraction"); }
701#ifdef PCL_NO_PRECOMPILE
702#include <pcl/segmentation/impl/extract_clusters.hpp>
PointCloudConstPtr input_
The input point cloud dataset.
IndicesPtr indices_
A pointer to the vector of point indices to use.
bool initCompute()
This method should get called before starting the actual computation.
bool deinitCompute()
This method should get called after finishing the actual computation.
PointCloud represents the base class in PCL for storing collections of 3D points.
void push_back(const PointT &pt)
Insert a new point in the cloud, at the end of the container.
pcl::PCLHeader header
The point cloud header.
shared_ptr< PointCloud< PointT > > Ptr
shared_ptr< const PointCloud< PointT > > ConstPtr
virtual bool getSortedResults()
Gets whether the results should be sorted (ascending in the distance) or not Otherwise the results ma...
virtual IndicesConstPtr getIndices() const
Get a pointer to the vector of indices used.
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.
void extractEuclideanClusters(const PointCloud< PointT > &cloud, const typename search::Search< PointT >::Ptr &tree, float tolerance, std::vector< PointIndices > &clusters, unsigned int min_pts_per_cluster=1, unsigned int max_pts_per_cluster=(std::numeric_limits< int >::max)())
Decompose a region of space into clusters based on the Euclidean distance between points.
bool comparePointClusters(const pcl::PointIndices &a, const pcl::PointIndices &b)
Sort clusters method (for std::sort).
detail::int_type_t< detail::index_type_size, false > uindex_t
Type used for an unsigned index in PCL.
detail::int_type_t< detail::index_type_size, detail::index_type_signed > index_t
Type used for an index in PCL.
IndicesAllocator<> Indices
Type used for indices in PCL.
#define PCL_DEPRECATED(Major, Minor, Message)
macro for compatibility across compilers and help remove old deprecated items for the Major....
shared_ptr< ::pcl::PointIndices > Ptr
shared_ptr< const ::pcl::PointIndices > ConstPtr
A point structure representing Euclidean xyz coordinates, and the RGB color.