在接触了pcl库三天后,根据一篇博客https://blog.csdn.net/ys578676728/article/details/104657262实现了自己的分离出人体的点云。参考的博客中,实现将一个人的点云信息分割出来。在今天参考该博客的流程,实现对场景中的五个人的点云图进行分割。这个流程可以作为pcl基础学习的一个流程。
每次看别人的博客都喜欢看别人实现了什么效果,总是拉到页面最下面,所以先把效果贴出来,提起兴趣再看流程和代码,图会比较多,耐心看。
左图为拿到的原图,右图为分割出来的五个人
对于人物来说,同样可以单独的分割出每个人:下图中每个人都可以单独的分离出,当然最后一个是两个人聚类时,连在了一起,忽略这细节,感受其中的牛X(大佬勿喷),请让小白骄傲一会。
看完了效果,将实现该效果的流程先在这里说一下,后面具体到每个流程:
首先,对于小白想要复现,有个头疼的问题,不知道你们有没有,反正我有,为了解决和我有一样头疼地方的人,先说一下,不知道引入那个头文件的问题,哈哈哈哈。
#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);
小白再问,怎么都是代码也没个注释和讲解,水平有限,后续会把我的学习过程分享一样。这里姑且先跑一跑流程,装一下。
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就可以下载了,不要币的。