使用RegionGrowing类实现区域生长分割,算法的输出是一个聚类集合。
算法的流程:
设立空的种子点序列、空的聚类数组 -> 初始种子点加入种子序列 -> 搜索邻域点 -> 若领域点法线与当前种子点法线的夹角小于阈值,则加入当前区域 -> 领域点曲率值小于曲率阈值,则加入种子点序列 -> 删除当前种子点,利用新种子点生长,直到种子序列点被清空。
利用曲率值从小到大排序,顺序选为种子点进行生长。
主要步骤:
(1)计算点法线;
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;//创建法线估计对象
normal_estimator.setSearchMethod(tree);//设置搜索方法
normal_estimator.setInputCloud(cloud);//设置法线估计对象输入点集
normal_estimator.setKSearch(KN_normal);// 设置用于法向量估计的k近邻数目
normal_estimator.compute(*normals);//计算并输出法向量
(2)实例化pcl::RegionGrowing,设置聚类参数;
// 区域生长算法的5个参数
pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;//创建区域生长分割对象
reg.setMinClusterSize(50);//设置一个聚类需要的最小点数
reg.setMaxClusterSize(1000000);//设置一个聚类需要的最大点数
reg.setSearchMethod(tree);//设置搜索方法
reg.setNumberOfNeighbours(30);//设置搜索的临近点数目
reg.setInputCloud(cloud);//设置输入点云
if (Bool_Cuting)reg.setIndices(indices);//通过输入参数设置,确定是否输入点云索引
reg.setInputNormals(normals);//设置输入点云的法向量
(3)其中两个主要参数设置;
reg.setSmoothnessThreshold(SmoothnessThreshold / 180.0 * M_PI);//设置平滑阈值
reg.setCurvatureThreshold(CurvatureThreshold);//设置曲率阈值
平滑阈值即两法线偏差允许范围,若小于该阈值则认为两点属于同一聚类;曲率阈值即两点曲率偏差允许范围,若满足前一条件并小于该阈值,则采用新增加点迭代进行区域生长。
(4)分割。
std::vector <pcl::PointIndices> clusters;
reg.extract(clusters);//获取聚类的结果,分割结果保存在点云索引的向量中。
运行结果:
同一聚类中的点集为同一颜色,分割结果间还存在大量红色点,这是因为该聚类点的数量不在初始设定的最大聚类数目和最小聚类数目之间,可以修改参数获取更好的分割结果。