irpas技术客

PCL:基于区域生长的点云分割原理与实现_孙 悟 空_点云区域生长

网络 2204

文章目录 1 基本思想2 算法流程3 代码实现4 区域生长结果展示

1 基本思想

区域生长的基本思想是将具有相似性质的点集合起来构成区域。首先对每个需要分割的区域找出一个种子作为生长的起点,然后将种子周围邻域中与种子有相同或相似性质的点(根据事先确定的生长或相似准则来确定,多为法向量、曲率)归并到种子所在的区域中。而新的点继续做种子向四周生长,直到再没有满足条件的点可以包括进来,一个区域就生长而成了。

基于曲率的区域生长,其结果是一个或多个聚类集合,每个聚类集合被认为是同一光滑表面的一部分。首先依据点的曲率对点进行排序,初始种子点所在区域为最平滑的区域,这样可以减少分割区域的总数。pcl::RegionGrowing 类就是采用的这种方法。

2 算法流程 设置一个空的种子点序列和一个空的聚类数组,选择种子点(曲率最小的点)并将其加入到种子点序列中;搜索当前种子点的邻域点,计算邻域点的法线与当前种子点的法线之间的夹角,小于平滑阈值的邻域点加入到当前区域;检查每一个邻域点的曲率,小于曲率阈值的邻域点加入到种子点序列中,并删除当前种子点,以新的种子点继续生长。重复进行以上生长过程,直到种子点序列被清空。此时,一个区域生长完成,并将其加入到聚类数组中;对剩余点重复进行以上步骤,直到遍历完所有点。

伪代码:

3 代码实现

代码:

#include <pcl/io/pcd_io.h> #include <pcl/search/search.h> #include <pcl/search/kdtree.h> #include <pcl/features/normal_3d.h> #include <pcl/visualization/cloud_viewer.h> #include <pcl/segmentation/region_growing.h> using namespace std; int main() { //------------------------------- 加载点云 ------------------------------- cout << "->正在加载点云..." << endl; pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); if (pcl::io::loadPCDFile<pcl::PointXYZ>("road.pcd", *cloud) < 0) { PCL_ERROR("\a点云文件不存在!\n"); system("pause"); return (-1); } cout << "->加载点的个数:" << cloud->points.size() << endl; //======================================================================== //------------------------------- 法线估计 ------------------------------- cout << "->正在估计点云法线..." << endl; pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne; //创建法线估计对象ne pcl::search::Search<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>); //设置搜索方法 pcl::PointCloud <pcl::Normal>::Ptr normals(new pcl::PointCloud <pcl::Normal>); //存放法线 ne.setSearchMethod(tree); ne.setInputCloud(cloud); ne.setKSearch(20); ne.compute(*normals); //======================================================================== //------------------------------- 区域生长 ------------------------------- cout << "->正在进行区域生长..." << endl; pcl::RegionGrowing<pcl::PointXYZ, pcl::Normal> rg; //创建区域生长分割对象 rg.setMinClusterSize(50); //设置满足聚类的最小点数 rg.setMaxClusterSize(99999999); //设置满足聚类的最大点数 rg.setSearchMethod(tree); //设置搜索方法 rg.setNumberOfNeighbours(30); //设置邻域搜索的点数 rg.setInputCloud(cloud); //设置输入点云 rg.setInputNormals(normals); //设置输入点云的法向量 rg.setSmoothnessThreshold(3.0 / 180.0 * M_PI); //设置平滑阈值,弧度,用于提取同一区域的点 rg.setCurvatureThreshold(1.0); //设置曲率阈值,如果两个点的法线偏差很小,则测试其曲率之间的差异。如果该值小于曲率阈值,则该算法将使用新添加的点继续簇的增长 vector<pcl::PointIndices> clusters; //聚类索引向量 rg.extract(clusters); //获取聚类结果,并保存到索引向量中 cout << "->聚类个数为" << clusters.size() << endl; //======================================================================== //---------------------- 为聚类点云添加颜色,并可视化 ---------------------- pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = rg.getColoredCloud(); pcl::visualization::CloudViewer viewer("区域生长结果"); viewer.showCloud(colored_cloud); while (!viewer.wasStopped()) { } //======================================================================== return (0); }

输出结果:

->正在加载点云... ->加载点的个数:200293 ->正在估计点云法线... ->正在进行区域生长... ->聚类个数为31 4 区域生长结果展示


相关链接:

PCL点云数据处理基础??????目录

https://pcl.readthedocs.io/projects/tutorials/en/latest/region_growing_segmentation.html#region-growing-segmentation

测试数据下载:https://download.csdn.net/download/weixin_46098577/76513961


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #点云区域生长