【点云处理】基于欧式聚类的点云分割

对于范围较广的点云来说,一开始先使用基于模型的点云分割方法将类似于平面这样的点云块提出来,然后在对留下的小部分点云进行像欧式聚类这样的后续分割处理。

原始点云:

代码,对代码的理解都注释上了,以便于以后复习~注释真的很重要~~~:

#include <pcl/ModelCoefficients.h> //模型参数头文件
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/extract_indices.h> //索引提取头文件
#include <pcl/filters/voxel_grid.h> //体素分割头文件
#include <pcl/features/normal_3d.h> 
#include <pcl/kdtree/kdtree.h>  
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/sample_consensus/method_types.h>
#include <pcl/sample_consensus/model_types.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/segmentation/extract_clusters.h>

using namespace std;
int main()
{
	//读入点云文件
	pcl::PCDReader read;
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_f(new pcl::PointCloud<pcl::PointXYZ>);
	read.read("table_scene_lms400.pcd",*cloud);
	cout << "初始点云数量为 : " << cloud->points.size() << endl;

	//体素滤波精简点云 
	pcl::VoxelGrid<pcl::PointXYZ> vg; //创建体素滤波对象
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
	vg.setInputCloud(cloud);
	vg.setLeafSize(0.01f,0.01f,0.01f);
	vg.filter(*cloud_filtered);
	cout << "体素下采样后的点云数量为 : " << cloud_filtered->points.size() << endl;

	//分割
	pcl::SACSegmentation<pcl::PointXYZ> seg;
	pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
	pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_plane(new pcl::PointCloud<pcl::PointXYZ>());
	pcl::PCDWriter writer;

	seg.setOptimizeCoefficients(true); //选择 模型参数是否需要优化
	seg.setModelType(pcl::SACMODEL_PLANE); //定义为平面模型
	seg.setMethodType(pcl::SAC_RANSAC); //定义分割方法
	seg.setMaxIterations(100); //定义最大迭代次数
	seg.setDistanceThreshold(0.02); //定义内点到模型内允许的最大值

	int i = 0;
	int nr_points = (int)cloud_filtered->points.size();
	//提取点云中的所有的平面
	while( cloud_filtered->points.size() > 0.3*nr_points)
	{
		seg.setInputCloud(cloud_filtered); //第一步 将整个简化的的点云进行分割
		seg.segment(*inliers, *coefficients); //分割结果索引保存 系数保存
		if (inliers->indices.size() == 0)
		{
			std::cout << "Could not estimate a planar model for the given dataset." << std::endl;
		}

		pcl::ExtractIndices<pcl::PointXYZ> extract;
		extract.setInputCloud(cloud_filtered);
		extract.setIndices(inliers);
		extract.setNegative(false); //如果设为true,可以提取指定index之外的点云,即除了平面之外的点云 
		extract.filter(*cloud_plane);
		cout<<"平面的点的数量为: "<<cloud_plane->points.size()<<endl;
		std::cout << "PointCloud representing the planar component: " << cloud_plane->points.size() << " data points." << std::endl;

		extract.setNegative(true);
		extract.filter(*cloud_f); //去除平面之后的点云
		cloud_filtered = cloud_f;
	}
	//当while循环结束之后,所有的平面将被剔除出去,
	//cloud_filtered之中 只剩下除了平面的所有的点云数据

	//创建kdtree
	pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
	tree->setInputCloud(cloud_filtered);//cloud_filtered 中只有除了平面的点云数据

	std::vector<pcl::PointIndices> cluster_indices;  //创建聚类索引点集
	pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec; //创建聚类对象
	ec.setClusterTolerance(0.02);  //设置近邻距离的搜索半径为0.02
	ec.setMinClusterSize(100); //聚类需要最少100个点云
	ec.setMaxClusterSize(25000); //聚类最多2500个点云
	ec.setSearchMethod(tree);
	ec.setInputCloud(cloud_filtered);
	ec.extract(cluster_indices);  //从点云中提取聚类,并将点云索引保存在 cluster_indices 之中

	//从点云聚类中分割出每一块点云,必须迭代访问点云索引,每次访问一次,就会创建一个新的点云文件,并且将当前聚类的所有的放到点云数据集之中
	int j = 0;
	//遍历整个索引集合cluster_indices 
	for (vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin(); it != cluster_indices.end(); ++it)
	{
		pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster(new pcl::PointCloud<pcl::PointXYZ>); //创建空的点云集
		//遍历每个索引集合中的每个点,将每个点存入创建的空的点云集合中
		for (vector<int>::const_iterator pit = it->indices.begin(); pit != it->indices.end(); pit++) //为空的点云集中逐个赋对象
		{
			cloud_cluster->points.push_back(cloud_filtered->points[*pit]);
		}
		cloud_cluster->width = cloud_cluster->points.size();
		cloud_cluster->height = 1;
		cloud_cluster->is_dense = true;
		cout<<"该聚类点云中点云的点的数量为 : "<< cloud_cluster->points.size()<<endl;
		std::stringstream ss;
		ss << "cloud_cluster_" << j << ".pcd";
		writer.write<pcl::PointXYZ>(ss.str(), *cloud_cluster, false);
		j++;
	}
	cerr<<"程序结束"<<endl;
	system("pause");
	return 0;
}

 分割结果:

 虽然大论文任务有点重,但是在学习中,总结真的很重要~~~希望写博客的习惯自己可以坚持下来~~~

PCL点云库中的欧式聚类分割是一种通过计算点云中点之间的欧氏距离来将点云分割成不同的聚类的方法。在这种方法中,首先对点云进行预处理,包括去除离群点和平面模型分割。然后,使用pcl::EuclideanClusterExtraction类对点云进行欧式聚类分割。该类通过设置聚类的最小和最大尺寸,以及聚类的距离阈值来提取聚类。 在使用欧式聚类分割的过程中,首先对点云进行预处理,包括去除离群点和平面模型分割。然后,根据设定的距离阈值,将点云中的点分成不同的聚类聚类的最小和最大尺寸可以用来控制聚类的大小。最后,可以通过获取每个聚类中的点的数量,进一步分析和处理聚类。 通过使用PCL点云库中的欧式聚类分割方法,可以对点云数据进行有效的分割和聚类,从而实现对点云数据的进一步分析和应用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [PCL点云库-欧式聚类分割-麦粒](https://download.csdn.net/download/fei_12138/87570560)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [PCL教程-点云分割欧式聚类分割](https://blog.csdn.net/luolaihua2018/article/details/120184539)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值