欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

pcl完整分割聚类流程

发布时间:2025/3/15 36 豆豆
生活随笔 收集整理的这篇文章主要介绍了 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就可以下载了,不要币的。

总结

以上是生活随笔为你收集整理的pcl完整分割聚类流程的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。