40 #ifndef PCL_SEGMENTATION_SUPERVOXEL_CLUSTERING_HPP_
41 #define PCL_SEGMENTATION_SUPERVOXEL_CLUSTERING_HPP_
43 #include <pcl/segmentation/supervoxel_clustering.h>
44 #include <pcl/common/io.h>
47 template <
typename Po
intT>
49 float seed_resolution)
50 : resolution_(voxel_resolution)
51 , seed_resolution_(seed_resolution)
53 , voxel_centroid_cloud_()
59 template <
typename Po
intT>
63 template <
typename Po
intT>
void
66 if ( cloud->
empty () )
68 PCL_ERROR (
"[pcl::SupervoxelClustering::setInputCloud] Empty cloud set, doing nothing \n");
73 adjacency_octree_->setInputCloud (cloud);
77 template <
typename Po
intT>
void
80 if ( normal_cloud->empty () )
82 PCL_ERROR (
"[pcl::SupervoxelClustering::setNormalCloud] Empty cloud set, doing nothing \n");
86 input_normals_ = normal_cloud;
90 template <
typename Po
intT>
void
96 bool segmentation_is_possible = initCompute ();
97 if ( !segmentation_is_possible )
104 segmentation_is_possible = prepareForSegmentation ();
105 if ( !segmentation_is_possible )
114 selectInitialSupervoxelSeeds (seed_indices);
116 createSupervoxelHelpers (seed_indices);
121 int max_depth =
static_cast<int> (1.8f*seed_resolution_/resolution_);
122 expandSupervoxels (max_depth);
126 makeSupervoxels (supervoxel_clusters);
142 template <
typename Po
intT>
void
145 if (supervoxel_helpers_.empty ())
147 PCL_ERROR (
"[pcl::SupervoxelClustering::refineVoxelNormals] Supervoxels not extracted, doing nothing - (Call extract first!) \n");
151 int max_depth =
static_cast<int> (1.8f*seed_resolution_/resolution_);
152 for (
int i = 0; i < num_itr; ++i)
154 for (
typename HelperListT::iterator sv_itr = supervoxel_helpers_.begin (); sv_itr != supervoxel_helpers_.end (); ++sv_itr)
156 sv_itr->refineNormals ();
159 reseedSupervoxels ();
160 expandSupervoxels (max_depth);
164 makeSupervoxels (supervoxel_clusters);
174 template <
typename Po
intT>
bool
179 if ( input_->points.empty () )
185 if ( (use_default_transform_behaviour_ && input_->isOrganized ())
186 || (!use_default_transform_behaviour_ && use_single_camera_transform_))
187 adjacency_octree_->setTransformFunction ([
this] (
PointT &p) { transformFunction (p); });
189 adjacency_octree_->addPointsFromInputCloud ();
202 template <
typename Po
intT>
void
206 voxel_centroid_cloud_->resize (adjacency_octree_->getLeafCount ());
207 auto leaf_itr = adjacency_octree_->begin ();
208 auto cent_cloud_itr = voxel_centroid_cloud_->begin ();
209 for (
int idx = 0 ; leaf_itr != adjacency_octree_->end (); ++leaf_itr, ++cent_cloud_itr, ++idx)
211 VoxelData& new_voxel_data = (*leaf_itr)->getData ();
213 new_voxel_data.getPoint (*cent_cloud_itr);
215 new_voxel_data.idx_ = idx;
222 assert (input_normals_->size () == input_->size ());
224 auto normal_itr = input_normals_->begin ();
225 for (
auto input_itr = input_->begin (); input_itr != input_->end (); ++input_itr, ++normal_itr)
228 if ( !pcl::isFinite<PointT> (*input_itr))
231 LeafContainerT* leaf = adjacency_octree_->getLeafContainerAtPoint (*input_itr);
234 VoxelData& voxel_data = leaf->getData ();
236 voxel_data.normal_ += normal_itr->getNormalVector4fMap ();
237 voxel_data.curvature_ += normal_itr->curvature;
240 for (leaf_itr = adjacency_octree_->begin (); leaf_itr != adjacency_octree_->end (); ++leaf_itr)
242 VoxelData& voxel_data = (*leaf_itr)->getData ();
243 voxel_data.normal_.normalize ();
244 voxel_data.owner_ =
nullptr;
245 voxel_data.distance_ = std::numeric_limits<float>::max ();
247 int num_points = (*leaf_itr)->getPointCounter ();
248 voxel_data.curvature_ /= num_points;
253 for (leaf_itr = adjacency_octree_->begin (); leaf_itr != adjacency_octree_->end (); ++leaf_itr)
255 VoxelData& new_voxel_data = (*leaf_itr)->getData ();
258 indices.reserve (81);
260 indices.push_back (new_voxel_data.idx_);
261 for (
auto neighb_itr=(*leaf_itr)->cbegin (); neighb_itr!=(*leaf_itr)->cend (); ++neighb_itr)
263 VoxelData& neighb_voxel_data = (*neighb_itr)->getData ();
265 indices.push_back (neighb_voxel_data.idx_);
267 for (
auto neighb_neighb_itr=(*neighb_itr)->cbegin (); neighb_neighb_itr!=(*neighb_itr)->cend (); ++neighb_neighb_itr)
269 VoxelData& neighb2_voxel_data = (*neighb_neighb_itr)->getData ();
270 indices.push_back (neighb2_voxel_data.idx_);
276 new_voxel_data.normal_[3] = 0.0f;
277 new_voxel_data.normal_.normalize ();
278 new_voxel_data.owner_ =
nullptr;
279 new_voxel_data.distance_ = std::numeric_limits<float>::max ();
287 template <
typename Po
intT>
void
292 for (
int i = 1; i < depth; ++i)
295 for (
typename HelperListT::iterator sv_itr = supervoxel_helpers_.begin (); sv_itr != supervoxel_helpers_.end (); ++sv_itr)
301 for (
typename HelperListT::iterator sv_itr = supervoxel_helpers_.begin (); sv_itr != supervoxel_helpers_.end (); )
303 if (sv_itr->size () == 0)
305 sv_itr = supervoxel_helpers_.erase (sv_itr);
309 sv_itr->updateCentroid ();
319 template <
typename Po
intT>
void
322 supervoxel_clusters.clear ();
323 for (
typename HelperListT::iterator sv_itr = supervoxel_helpers_.begin (); sv_itr != supervoxel_helpers_.end (); ++sv_itr)
325 std::uint32_t label = sv_itr->getLabel ();
326 supervoxel_clusters[label].reset (
new Supervoxel<PointT>);
327 sv_itr->getXYZ (supervoxel_clusters[label]->centroid_.x,supervoxel_clusters[label]->centroid_.y,supervoxel_clusters[label]->centroid_.z);
328 sv_itr->getRGB (supervoxel_clusters[label]->centroid_.rgba);
329 sv_itr->getNormal (supervoxel_clusters[label]->normal_);
330 sv_itr->getVoxels (supervoxel_clusters[label]->voxels_);
331 sv_itr->getNormals (supervoxel_clusters[label]->normals_);
337 template <
typename Po
intT>
void
341 supervoxel_helpers_.clear ();
342 for (std::size_t i = 0; i < seed_indices.size (); ++i)
344 supervoxel_helpers_.push_back (
new SupervoxelHelper(i+1,
this));
346 LeafContainerT* seed_leaf = adjacency_octree_->at(seed_indices[i]);
349 supervoxel_helpers_.back ().addLeaf (seed_leaf);
353 PCL_WARN (
"Could not find leaf in pcl::SupervoxelClustering<PointT>::createSupervoxelHelpers - supervoxel will be deleted \n");
359 template <
typename Po
intT>
void
368 seed_octree.setInputCloud (voxel_centroid_cloud_);
369 seed_octree.addPointsFromInputCloud ();
371 std::vector<PointT, Eigen::aligned_allocator<PointT> > voxel_centers;
372 int num_seeds = seed_octree.getOccupiedVoxelCenters(voxel_centers);
375 std::vector<int> seed_indices_orig;
376 seed_indices_orig.resize (num_seeds, 0);
377 seed_indices.clear ();
380 closest_index.resize(1,0);
385 voxel_kdtree_ ->setInputCloud (voxel_centroid_cloud_);
388 for (
int i = 0; i < num_seeds; ++i)
390 voxel_kdtree_->nearestKSearch (voxel_centers[i], 1, closest_index,
distance);
391 seed_indices_orig[i] = closest_index[0];
395 std::vector<float> sqr_distances;
396 seed_indices.reserve (seed_indices_orig.size ());
397 float search_radius = 0.5f*seed_resolution_;
400 float min_points = 0.05f * (search_radius)*(search_radius) * 3.1415926536f / (resolution_*resolution_);
401 for (
const auto &index_orig : seed_indices_orig)
403 int num = voxel_kdtree_->radiusSearch (index_orig, search_radius , neighbors, sqr_distances);
404 if ( num > min_points)
406 seed_indices.push_back (index_orig);
416 template <
typename Po
intT>
void
420 for (
typename HelperListT::iterator sv_itr = supervoxel_helpers_.begin (); sv_itr != supervoxel_helpers_.end (); ++sv_itr)
422 sv_itr->removeAllLeaves ();
428 for (
typename HelperListT::iterator sv_itr = supervoxel_helpers_.begin (); sv_itr != supervoxel_helpers_.end (); ++sv_itr)
431 sv_itr->getXYZ (point.x, point.y, point.z);
432 voxel_kdtree_->nearestKSearch (point, 1, closest_index,
distance);
434 LeafContainerT* seed_leaf = adjacency_octree_->at (closest_index[0]);
437 sv_itr->addLeaf (seed_leaf);
441 PCL_WARN (
"Could not find leaf in pcl::SupervoxelClustering<PointT>::reseedSupervoxels - supervoxel will be deleted \n");
448 template <
typename Po
intT>
void
453 p.z = std::log (p.z);
457 template <
typename Po
intT>
float
461 float spatial_dist = (v1.xyz_ - v2.xyz_).norm () / seed_resolution_;
462 float color_dist = (v1.rgb_ - v2.rgb_).norm () / 255.0f;
463 float cos_angle_normal = 1.0f - std::abs (v1.normal_.dot (v2.normal_));
465 return cos_angle_normal * normal_importance_ + color_dist * color_importance_+ spatial_dist * spatial_importance_;
476 template <
typename Po
intT>
void
479 adjacency_list_arg.clear ();
481 std::map <std::uint32_t, VoxelID> label_ID_map;
482 for (
typename HelperListT::const_iterator sv_itr = supervoxel_helpers_.cbegin (); sv_itr != supervoxel_helpers_.cend (); ++sv_itr)
484 VoxelID node_id = add_vertex (adjacency_list_arg);
485 adjacency_list_arg[node_id] = (sv_itr->getLabel ());
486 label_ID_map.insert (std::make_pair (sv_itr->getLabel (), node_id));
489 for (
typename HelperListT::const_iterator sv_itr = supervoxel_helpers_.cbegin (); sv_itr != supervoxel_helpers_.cend (); ++sv_itr)
491 std::uint32_t label = sv_itr->getLabel ();
492 std::set<std::uint32_t> neighbor_labels;
493 sv_itr->getNeighborLabels (neighbor_labels);
494 for (
const unsigned int &neighbor_label : neighbor_labels)
498 VoxelID u = (label_ID_map.find (label))->second;
499 VoxelID v = (label_ID_map.find (neighbor_label))->second;
500 boost::tie (edge, edge_added) = add_edge (u,v,adjacency_list_arg);
504 VoxelData centroid_data = (sv_itr)->getCentroid ();
508 for (
typename HelperListT::const_iterator neighb_itr = supervoxel_helpers_.cbegin (); neighb_itr != supervoxel_helpers_.cend (); ++neighb_itr)
510 if (neighb_itr->getLabel () == neighbor_label)
512 neighb_centroid_data = neighb_itr->getCentroid ();
517 float length = voxelDataDistance (centroid_data, neighb_centroid_data);
518 adjacency_list_arg[edge] = length;
527 template <
typename Po
intT>
void
530 label_adjacency.clear ();
531 for (
typename HelperListT::const_iterator sv_itr = supervoxel_helpers_.cbegin (); sv_itr != supervoxel_helpers_.cend (); ++sv_itr)
533 std::uint32_t label = sv_itr->getLabel ();
534 std::set<std::uint32_t> neighbor_labels;
535 sv_itr->getNeighborLabels (neighbor_labels);
536 for (
const unsigned int &neighbor_label : neighbor_labels)
537 label_adjacency.insert (std::pair<std::uint32_t,std::uint32_t> (label, neighbor_label) );
549 return centroid_copy;
557 for (
typename HelperListT::const_iterator sv_itr = supervoxel_helpers_.cbegin (); sv_itr != supervoxel_helpers_.cend (); ++sv_itr)
560 sv_itr->getVoxels (voxels);
564 auto xyzl_copy_itr = xyzl_copy.
begin ();
565 for ( ; xyzl_copy_itr != xyzl_copy.
end (); ++xyzl_copy_itr)
566 xyzl_copy_itr->label = sv_itr->getLabel ();
568 *labeled_voxel_cloud += xyzl_copy;
571 return labeled_voxel_cloud;
581 auto i_input = input_->begin ();
582 for (
auto i_labeled = labeled_cloud->
begin (); i_labeled != labeled_cloud->
end (); ++i_labeled,++i_input)
584 if ( !pcl::isFinite<PointT> (*i_input))
585 i_labeled->label = 0;
588 i_labeled->label = 0;
589 LeafContainerT *leaf = adjacency_octree_->getLeafContainerAtPoint (*i_input);
592 i_labeled->label = voxel_data.
owner_->getLabel ();
598 return (labeled_cloud);
606 normal_cloud->
resize (supervoxel_clusters.size ());
607 auto normal_cloud_itr = normal_cloud->
begin ();
608 for (
auto sv_itr = supervoxel_clusters.cbegin (), sv_itr_end = supervoxel_clusters.cend ();
609 sv_itr != sv_itr_end; ++sv_itr, ++normal_cloud_itr)
611 (sv_itr->second)->getCentroidPointNormal (*normal_cloud_itr);
617 template <
typename Po
intT>
float
620 return (resolution_);
624 template <
typename Po
intT>
void
627 resolution_ = resolution;
632 template <
typename Po
intT>
float
635 return (seed_resolution_);
639 template <
typename Po
intT>
void
642 seed_resolution_ = seed_resolution;
647 template <
typename Po
intT>
void
650 color_importance_ = val;
654 template <
typename Po
intT>
void
657 spatial_importance_ = val;
661 template <
typename Po
intT>
void
664 normal_importance_ = val;
668 template <
typename Po
intT>
void
671 use_default_transform_behaviour_ =
false;
672 use_single_camera_transform_ = val;
676 template <
typename Po
intT>
int
680 for (
typename HelperListT::const_iterator sv_itr = supervoxel_helpers_.cbegin (); sv_itr != supervoxel_helpers_.cend (); ++sv_itr)
682 int temp = sv_itr->getLabel ();
683 if (temp > max_label)
695 template <
typename Po
intT>
void
698 normal_arg.normal_x = normal_[0];
699 normal_arg.normal_y = normal_[1];
700 normal_arg.normal_z = normal_[2];
708 template <
typename Po
intT>
void
711 leaves_.insert (leaf_arg);
712 VoxelData& voxel_data = leaf_arg->getData ();
713 voxel_data.owner_ =
this;
717 template <
typename Po
intT>
void
720 leaves_.erase (leaf_arg);
724 template <
typename Po
intT>
void
727 for (
auto leaf_itr = leaves_.cbegin (); leaf_itr != leaves_.cend (); ++leaf_itr)
729 VoxelData& voxel = ((*leaf_itr)->getData ());
730 voxel.owner_ =
nullptr;
731 voxel.distance_ = std::numeric_limits<float>::max ();
737 template <
typename Po
intT>
void
742 std::vector<LeafContainerT*> new_owned;
743 new_owned.reserve (leaves_.size () * 9);
745 for (
auto leaf_itr = leaves_.cbegin (); leaf_itr != leaves_.cend (); ++leaf_itr)
748 for (
auto neighb_itr=(*leaf_itr)->cbegin (); neighb_itr!=(*leaf_itr)->cend (); ++neighb_itr)
751 VoxelData& neighbor_voxel = ((*neighb_itr)->getData ());
753 if(neighbor_voxel.owner_ ==
this)
756 float dist = parent_->voxelDataDistance (centroid_, neighbor_voxel);
759 if (dist < neighbor_voxel.distance_)
761 neighbor_voxel.distance_ = dist;
762 if (neighbor_voxel.owner_ !=
this)
764 if (neighbor_voxel.owner_)
765 (neighbor_voxel.owner_)->removeLeaf(*neighb_itr);
766 neighbor_voxel.owner_ =
this;
767 new_owned.push_back (*neighb_itr);
773 for (
auto new_owned_itr = new_owned.cbegin (); new_owned_itr != new_owned.cend (); ++new_owned_itr)
775 leaves_.insert (*new_owned_itr);
780 template <
typename Po
intT>
void
784 for (
auto leaf_itr = leaves_.cbegin (); leaf_itr != leaves_.cend (); ++leaf_itr)
786 VoxelData& voxel_data = (*leaf_itr)->getData ();
788 indices.reserve (81);
790 indices.push_back (voxel_data.idx_);
791 for (
auto neighb_itr=(*leaf_itr)->cbegin (); neighb_itr!=(*leaf_itr)->cend (); ++neighb_itr)
794 VoxelData& neighbor_voxel_data = ((*neighb_itr)->getData ());
796 if (neighbor_voxel_data.owner_ ==
this)
798 indices.push_back (neighbor_voxel_data.idx_);
800 for (
auto neighb_neighb_itr=(*neighb_itr)->cbegin (); neighb_neighb_itr!=(*neighb_itr)->cend (); ++neighb_neighb_itr)
802 VoxelData& neighb_neighb_voxel_data = (*neighb_neighb_itr)->getData ();
803 if (neighb_neighb_voxel_data.owner_ ==
this)
804 indices.push_back (neighb_neighb_voxel_data.idx_);
813 voxel_data.normal_[3] = 0.0f;
814 voxel_data.normal_.normalize ();
819 template <
typename Po
intT>
void
822 centroid_.normal_ = Eigen::Vector4f::Zero ();
823 centroid_.xyz_ = Eigen::Vector3f::Zero ();
824 centroid_.rgb_ = Eigen::Vector3f::Zero ();
825 for (
auto leaf_itr = leaves_.cbegin (); leaf_itr != leaves_.cend (); ++leaf_itr)
827 const VoxelData& leaf_data = (*leaf_itr)->getData ();
828 centroid_.normal_ += leaf_data.normal_;
829 centroid_.xyz_ += leaf_data.xyz_;
830 centroid_.rgb_ += leaf_data.rgb_;
832 centroid_.normal_.normalize ();
833 centroid_.xyz_ /=
static_cast<float> (leaves_.size ());
834 centroid_.rgb_ /=
static_cast<float> (leaves_.size ());
838 template <
typename Po
intT>
void
843 voxels->
resize (leaves_.size ());
844 auto voxel_itr = voxels->
begin ();
845 for (
auto leaf_itr = leaves_.cbegin (); leaf_itr != leaves_.cend (); ++leaf_itr, ++voxel_itr)
847 const VoxelData& leaf_data = (*leaf_itr)->getData ();
848 leaf_data.getPoint (*voxel_itr);
853 template <
typename Po
intT>
void
858 normals->
resize (leaves_.size ());
859 auto normal_itr = normals->
begin ();
860 for (
auto leaf_itr = leaves_.cbegin (); leaf_itr != leaves_.cend (); ++leaf_itr, ++normal_itr)
862 const VoxelData& leaf_data = (*leaf_itr)->getData ();
863 leaf_data.getNormal (*normal_itr);
868 template <
typename Po
intT>
void
871 neighbor_labels.clear ();
873 for (
auto leaf_itr = leaves_.cbegin (); leaf_itr != leaves_.cend (); ++leaf_itr)
876 for (
auto neighb_itr=(*leaf_itr)->cbegin (); neighb_itr!=(*leaf_itr)->cend (); ++neighb_itr)
879 VoxelData& neighbor_voxel = ((*neighb_itr)->getData ());
881 if (neighbor_voxel.owner_ !=
this && neighbor_voxel.owner_)
883 neighbor_labels.insert (neighbor_voxel.owner_->getLabel ());
PointCloud represents the base class in PCL for storing collections of 3D points.
void resize(std::size_t count)
Resizes the container to contain count elements.
void clear()
Removes all points in a cloud and sets the width and height to 0.
shared_ptr< PointCloud< PointT > > Ptr
iterator begin() noexcept
shared_ptr< const PointCloud< PointT > > ConstPtr
VoxelData is a structure used for storing data within a pcl::octree::OctreePointCloudAdjacencyContain...
SupervoxelHelper * owner_
void getNormal(Normal &normal_arg) const
Gets the data of in the form of a normal.
Implements a supervoxel algorithm based on voxel structure, normals, and rgb values.
static pcl::PointCloud< pcl::PointNormal >::Ptr makeSupervoxelNormalCloud(std::map< std::uint32_t, typename Supervoxel< PointT >::Ptr > &supervoxel_clusters)
Static helper function which returns a pointcloud of normals for the input supervoxels.
VoxelAdjacencyList::edge_descriptor EdgeID
int getMaxLabel() const
Returns the current maximum (highest) label.
virtual void refineSupervoxels(int num_itr, std::map< std::uint32_t, typename Supervoxel< PointT >::Ptr > &supervoxel_clusters)
This method refines the calculated supervoxels - may only be called after extract.
void setSpatialImportance(float val)
Set the importance of spatial distance for supervoxels.
float getVoxelResolution() const
Get the resolution of the octree voxels.
virtual void setNormalCloud(typename NormalCloudT::ConstPtr normal_cloud)
This method sets the normals to be used for supervoxels (should be same size as input cloud)
void setColorImportance(float val)
Set the importance of color for supervoxels.
pcl::PointCloud< pcl::PointXYZL >::Ptr getLabeledVoxelCloud() const
Returns labeled voxelized cloud Points that belong to the same supervoxel have the same label.
void setVoxelResolution(float resolution)
Set the resolution of the octree voxels.
void setInputCloud(const typename pcl::PointCloud< PointT >::ConstPtr &cloud) override
This method sets the cloud to be supervoxelized.
virtual void extract(std::map< std::uint32_t, typename Supervoxel< PointT >::Ptr > &supervoxel_clusters)
This method launches the segmentation algorithm and returns the supervoxels that were obtained during...
boost::adjacency_list< boost::setS, boost::setS, boost::undirectedS, std::uint32_t, float > VoxelAdjacencyList
pcl::octree::OctreePointCloudAdjacency< PointT, LeafContainerT > OctreeAdjacencyT
pcl::PointCloud< PointT >::Ptr getVoxelCentroidCloud() const
Returns a deep copy of the voxel centroid cloud.
void setSeedResolution(float seed_resolution)
Set the resolution of the octree seed voxels.
void getSupervoxelAdjacency(std::multimap< std::uint32_t, std::uint32_t > &label_adjacency) const
Get a multimap which gives supervoxel adjacency.
void setUseSingleCameraTransform(bool val)
Set whether or not to use the single camera transform.
SupervoxelClustering(float voxel_resolution, float seed_resolution)
Constructor that sets default values for member variables.
void getSupervoxelAdjacencyList(VoxelAdjacencyList &adjacency_list_arg) const
Gets the adjacency list (Boost Graph library) which gives connections between supervoxels.
VoxelAdjacencyList::vertex_descriptor VoxelID
~SupervoxelClustering() override
This destructor destroys the cloud, normals and search method used for finding neighbors.
float getSeedResolution() const
Get the resolution of the octree seed voxels.
void setNormalImportance(float val)
Set the importance of scalar normal product for supervoxels.
pcl::PointCloud< PointXYZL >::Ptr getLabeledCloud() const
Returns labeled cloud Points that belong to the same supervoxel have the same label.
shared_ptr< Supervoxel< PointT > > Ptr
Octree adjacency leaf container class- stores a list of pointers to neighbors, number of points added...
DataT & getData()
Returns a reference to the data member to access it without copying.
Octree pointcloud search class
search::KdTree is a wrapper class which inherits the pcl::KdTree class for performing search function...
void copyPointCloud(const pcl::PointCloud< PointInT > &cloud_in, pcl::PointCloud< PointOutT > &cloud_out)
Copy all the fields from a given point cloud into a new point cloud.
void flipNormalTowardsViewpoint(const PointT &point, float vp_x, float vp_y, float vp_z, Eigen::Matrix< Scalar, 4, 1 > &normal)
Flip (in place) the estimated normal of a point towards a given viewpoint.
bool computePointNormal(const pcl::PointCloud< PointT > &cloud, Eigen::Vector4f &plane_parameters, float &curvature)
Compute the Least-Squares plane fit for a given set of points, and return the estimated plane paramet...
float distance(const PointT &p1, const PointT &p2)
IndicesAllocator<> Indices
Type used for indices in PCL.
A point structure representing normal coordinates and the surface curvature estimate.
A point structure representing Euclidean xyz coordinates, and the RGB color.