pcl完整分割聚类流程

前言

在接触了pcl库三天后,根据一篇博客https://blog.csdn.net/ys578676728/article/details/104657262实现了自己的分离出人体的点云。参考的博客中,实现将一个人的点云信息分割出来。在今天参考该博客的流程,实现对场景中的五个人的点云图进行分割。这个流程可以作为pcl基础学习的一个流程。

效果

每次看别人的博客都喜欢看别人实现了什么效果,总是拉到页面最下面,所以先把效果贴出来,提起兴趣再看流程和代码,图会比较多,耐心看。
左图为拿到的原图,右图为分割出来的五个人
pcl完整分割聚类流程_第1张图片pcl完整分割聚类流程_第2张图片

对于人物来说,同样可以单独的分割出每个人:下图中每个人都可以单独的分离出,当然最后一个是两个人聚类时,连在了一起,忽略这细节,感受其中的牛X(大佬勿喷),请让小白骄傲一会。
pcl完整分割聚类流程_第3张图片pcl完整分割聚类流程_第4张图片pcl完整分割聚类流程_第5张图片pcl完整分割聚类流程_第6张图片pcl完整分割聚类流程_第7张图片

流程

看完了效果,将实现该效果的流程先在这里说一下,后面具体到每个流程:

  • 读入pcd点云;
    • 搜一搜,应该比较容易
  • 滤波操作
    • 这里用的是体素滤波器,具体原因,你懂得,作为一下小白怎么可能知道
  • 利用SAC分割算法
    • 利用该算法,将点云中的平面,比如地面等,给去除;这一步中可以得到去除的平面和剩余的点云
  • 采用欧式聚类分割算法,实现最终的效果
    • 同样的我也不知道原理,今天只是跑通一个流程。

详细步骤

首先,对于小白想要复现,有个头疼的问题,不知道你们有没有,反正我有,为了解决和我有一样头疼地方的人,先说一下,不知道引入那个头文件的问题,哈哈哈哈。

引入头文件

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

读入文件

//读取pcd文件
	string pcdPath = "F:/3dDataSets/pcdFiles/five_people.pcd";
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PCDWriter writer;
	if (pcl::io::loadPCDFile(pcdPath.c_str(), *cloud) < 0)
	{
		cout << "load PCD failure" << endl;
	}

体素滤波器实现降采样

小白再问怎么还有transform啊!我这对降采样的点云的进行一个平移,这样在显示时效果比较直观。

	//采用体素滤波器来实现降采样
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloudFilterVoxelGrid(new pcl::PointCloud<pcl::PointXYZ>);
	
	//pcl::ApproximateVoxelGrid sor;
	pcl::VoxelGrid<pcl::PointXYZ> sor;
	sor.setInputCloud(cloud);
	sor.setLeafSize(0.05f,0.05f,0.05f);
	sor.filter(*cloudFilterVoxelGrid);

	Eigen::Affine3f transformM = Eigen::Affine3f::Identity();
	transformM.translation() << 5.0, 0.0, 0.0;
	transformM.rotate(Eigen::AngleAxisf(0.0,Eigen::Vector3f::UnitZ()));


	pcl::PointCloud<pcl::PointXYZ>::Ptr pingyi(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::transformPointCloud(*cloudFilterVoxelGrid,*pingyi,transformM);

SAC分割点云,去除平面

小白再问,怎么都是代码也没个注释和讲解,水平有限,后续会把我的学习过程分享一样。这里姑且先跑一跑流程,装一下。

pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
	pcl::PointIndices::Ptr inliners(new pcl::PointIndices);
	
	pcl::SACSegmentation<pcl::PointXYZ> sac;
	sac.setOptimizeCoefficients(true);
	sac.setModelType(pcl::SACMODEL_PLANE);
	sac.setMethodType(pcl::SAC_RANSAC);
	sac.setDistanceThreshold(0.1);
	sac.setMaxIterations(500);
	int i = 0, nr_points = (int)pingyi->points.size();
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloudPlane(new pcl::PointCloud<pcl::PointXYZ>), cloudT(new pcl::PointCloud<pcl::PointXYZ>);
	while(pingyi->points.size() > 0.7 * nr_points)
	{
		sac.setInputCloud(pingyi);
		sac.segment(*inliners, *coefficients);
		if (inliners->indices.size() == 0)
		{
			cout << "could not remove " << endl;
			break;
		}

		pcl::ExtractIndices<pcl::PointXYZ> extract;
		extract.setInputCloud(pingyi);
		extract.setIndices(inliners);
		extract.setNegative(false);
		extract.filter(*cloudPlane);

		
		extract.setNegative(true);
		extract.filter(*cloudT);
		writer.write<pcl::PointXYZ>("./temp/cloudPlane" + to_string(i) + ".pcd", *cloudPlane, false);
		writer.write<pcl::PointXYZ>("./temp/cloudfilter" + to_string(i) + ".pcd", *cloudT, false);
		i++;
		*pingyi = *cloudT;
	}

欧式距离聚类分割

pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
	tree->setInputCloud(pingyi);
	std::vector<pcl::PointIndices> clusterIndices;
	pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
	ec.setClusterTolerance(0.1);
	ec.setMinClusterSize(100);
	ec.setMaxClusterSize(25000);
	ec.setSearchMethod(tree);
	ec.setInputCloud(pingyi);
	ec.extract(clusterIndices);

	int j = 0;
	for (std::vector<pcl::PointIndices>::const_iterator it = clusterIndices.begin();it!=clusterIndices.end();++it)
	{
		pcl::PointCloud<pcl::PointXYZ>::Ptr cloudCluster(new pcl::PointCloud<pcl::PointXYZ>);
		for (std::vector<int>::const_iterator pit = it->indices.begin();pit != it->indices.end();++pit)
		{
			cloudCluster->points.push_back(pingyi->points[*pit]);
		}
		cloudCluster->width = cloudCluster->points.size();
		cloudCluster->height = 1;
		cloudCluster->is_dense = true;
		writer.write<pcl::PointXYZ>("cluster"+to_string(j++)+".pcd",*cloudCluster,false);
	}

复现

对3d点云感兴趣,想跑一跑的,肯定就会本小白,“您好,那个点云文件你可以发一下”或者“您好,有源代码文件文件吗?”。这里把点云的文件放在资源中,至于源代码,上述的源码是完全衔接的,没有漏裁。
点云:https://download.csdn.net/download/qq_25105061/21018535,在csdn直接搜索five_people.pcd就可以下载了,不要币的。

你可能感兴趣的:(pcl,点云)