pcl完整分割聚类流程

前言

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

效果

每次看别人的博客都喜欢看别人实现了什么效果,总是拉到页面最下面,所以先把效果贴出来,提起兴趣再看流程和代码,图会比较多,耐心看。
左图为拿到的原图,右图为分割出来的五个人
原始点云在这里插入图片描述

对于人物来说,同样可以单独的分割出每个人:下图中每个人都可以单独的分离出,当然最后一个是两个人聚类时,连在了一起,忽略这细节,感受其中的牛X(大佬勿喷),请让小白骄傲一会。
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

流程

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

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

详细步骤

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

引入头文件
#include <iostream>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/approximate_voxel_grid.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/common/transforms.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/search/kdtree.h>
#include <pcl/segmentation/extract_clusters.h>
读入文件
//读取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<pcl::PointXYZ> 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就可以下载了,不要币的。

  • 20
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值