点云分割的过程主要分为以下几个步骤:
1. 法线估计 (Normal Estimation)
在分割之前,首先需要计算每个点的法线。法线是与点云表面垂直的向量,在点云处理中通常用于描述点的局部表面特征。
pcl::NormalEstimation<pcl::PointXYZI, pcl::Normal> norm_est;
pcl::search::KdTree<pcl::PointXYZI>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZI>()); norm_est.setSearchMethod(tree);
norm_est.setKSearch(40);
norm_est.setInputCloud(cloud);
norm_est.compute(*normals);
法线估计通过NormalEstimation
类实现,并使用了KD-Tree(快速最近邻搜索)来查找每个点的邻域。setKSearch(40)
表示为每个点考虑它周围40个最近的邻居来估计法线。
2. 平面分割 (Plane Segmentation)
平面分割是点云分割中常用的一部分,用于提取平面部分,例如地面、墙壁等。
pcl::SACSegmentationFromNormals<pcl::PointXYZI, pcl::Normal> seg;
seg.setOptimizeCoefficients(true);
seg.setModelType(pcl::SACMODEL_NORMAL_PLANE);
seg.setNormalDistanceWeight(0.2);
seg.setMethodType(pcl::SAC_RANSAC);
seg.setMaxIterations(3000);
seg.setDistanceThreshold(0.2);
seg.setInputCloud(cloud);
seg.setInputNormals(normals);
seg.segment(*indices_plane, *coefficients);
- 模型类型:选择了法线平面模型 (
SACMODEL_NORMAL_PLANE
)。 - 分割方法:使用了RANSAC(随机采样一致性算法)来找到最大的一致平面。
- 参数设置:例如
NormalDistanceWeight
用于控制法线距离在平面分割中的权重,DistanceThreshold
设置了点到平面距离的阈值,用于确定点是否属于该平面。
分割完成后,会继续分割剩下的点,直到找到所有满足条件的平面或没有足够大的平面为止。
3. 欧几里得聚类 (Euclidean Cluster Extraction)
在去除了平面部分后,剩下的点通常进行欧几里得聚类,这个过程用于将彼此靠近的点群分割为独立的部分(如不同的物体)。
pcl::EuclideanClusterExtraction<pcl::PointXYZI> ec;
ec.setClusterTolerance(params_.cluster_tolerance);
ec.setMaxClusterSize(10000);
ec.setMinClusterSize(50);
ec.setSearchMethod(tree);
ec.setInputCloud(cloud);
ec.setIndices(indices_notplane);
ec.extract(eu_cluster_indices);
- 聚类容差 (Cluster Tolerance):决定了点与点之间的最大距离,超过这个距离的点被认为属于不同的簇。
- 最大和最小簇大小:限制了每个簇的大小,以过滤掉过大或过小的噪声。
聚类后,每个簇代表一个独立的物体或区域。
4. 结果整合
最终,将分割的平面部分和聚类的结果整合在一起,并将这些分割结果用于后续处理或分析。
seg_indices.insert(seg_indices.end(), eu_cluster_indices.begin(), eu_cluster_indices.end());
这些步骤构成了完整的点云分割流程。通过法线估计、平面分割和欧几里得聚类,能够将点云数据分割成不同的部分,为进一步的处理和分析奠定基础。