PCL分割——区域生长聚簇

基于法向量夹角的区域生长聚簇

通过比较点之间法向量的夹角大小来判断点之间是否处于同一曲面,从而判断点之间是否聚簇。

算法流程

1️⃣ 初始化种子点
选中的点被加入一个称为 seeds(种子点集) 的集合,同时该点也被加入当前区域(Region)。
2️⃣ 遍历种子点
从 seeds 中取出一个种子点,查找该点的所有邻域点(通过 kNN 或半径搜索)。
3️⃣ 法向量角度判断(平滑性约束)
对于每一个邻域点,计算其法向量与当前种子点法向量之间的夹角。
若夹角 小于给定阈值,则认为该邻域点与种子点处于同一平滑表面,将该邻域点加入当前区域。
4️⃣ 曲率判断(是否继续生长)
若该邻域点的曲率 小于曲率阈值,说明该点位于较平坦区域,可作为新的生长起点,将该邻域点加入 seeds(种子点集)。
5️⃣ 更新种子点集并结束条件
当前种子点处理完成后,将其从 seeds 中移除;当 seeds 为空时,说明当前区域已生长完成。


为了减少点云分割得到的区域数量,该算法会优先选择具有较小曲率的点加入seed进行区域划分。

使用示例
  pcl::search::Search<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
  pcl::PointCloud <pcl::Normal>::Ptr normals (new pcl::PointCloud <pcl::Normal>);
  pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
  normal_estimator.setSearchMethod (tree);
  normal_estimator.setInputCloud (cloud);
  normal_estimator.setKSearch (50);
  normal_estimator.compute (*normals);

  pcl::IndicesPtr indices (new std::vector <int>);
  pcl::removeNaNFromPointCloud(*cloud, *indices);

  pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> reg;
  reg.setMinClusterSize (50);
  reg.setMaxClusterSize (1000000);
  reg.setSearchMethod (tree);
  reg.setNumberOfNeighbours (30);
  reg.setInputCloud (cloud);
  reg.setIndices (indices);
  reg.setInputNormals (normals);
  reg.setSmoothnessThreshold (3.0 / 180.0 * M_PI);
  reg.setCurvatureThreshold (1.0);

  std::vector <pcl::PointIndices> clusters;
  //生成的clusters是一个pcl::PointIndices的集合。存储每个类别对应的点索引。
  reg.extract (clusters);
  //reg.getColoredCloud()此方法可以返回一份着色的点云 用于渲染

reg.setSmoothnessThreshold (3.0 / 180.0 * M_PI); reg.setCurvatureThreshold (1.0);这两句代码实际上是添加了两个合并条件。当平滑度不满足合并要求时会继续通过曲率判断是否合并。

基于颜色的区域生长聚簇

该算法在思想上与上面那个一样。只不过合并两点的依据从发向量夹角变成了RGB颜色值的相似性。

算法流程

1️⃣ 初始化与种子选择
从点云中选取初始种子点,基于点之间的邻域关系(如 KNN 或半径搜索)准备区域生长所需的数据结构。
2️⃣ 基于颜色的区域生长
以种子点为起始,遍历其邻域点,比较邻域点与当前区域中点的颜色差异;若颜色差异小于给定阈值,则将该邻域点加入当前区域,并作为新的种子继续生长。
3️⃣ 颜色相近区域的合并(第一阶段合并)
初始分割完成后,对相邻的区域进行检查;若两个区域的平均颜色差异较小,则将这两个区域合并,以减少过分割现象。
4️⃣ 小区域合并(第二阶段合并)
检查每个区域所包含的点数;若某个区域的点数小于用户设定的最小阈值,则将该区域与最近的相邻区域合并,以避免产生过小或噪声区域。

使用实例
  pcl::IndicesPtr indices (new std::vector <int>);
  pcl::removeNaNFromPointCloud (*cloud, *indices);

  pcl::RegionGrowingRGB<pcl::PointXYZRGB> reg;
  reg.setInputCloud (cloud);
  reg.setIndices (indices);
  reg.setSearchMethod (tree);
  reg.setDistanceThreshold (10);
  reg.setPointColorThreshold (6);
  reg.setRegionColorThreshold (5);
  reg.setMinClusterSize (600);
  std::vector <pcl::PointIndices> clusters;
  reg.extract (clusters);

该算法支持使用reg.setInputNormals添加法向量信息进行检测,但此处只使用了RGB数据。

posted @ 2025-12-14 20:44  Ytytyty  阅读(62)  评论(0)    收藏  举报