之前使用区域增长算法将点云文件聚类后,聚类的面通过索引就可以输出,但是想既要聚类的面,也要聚类剩余的点,搜遍了没有这方面的资料,国内网上聚类方面的资料都是抄抄PCL学习教程,都是输出聚类面就完事了。遂决定,自己写一个,输出聚类后剩余的点云。
主要方法是使用kd-tree来比较聚类完所有的聚类面与原点云文件,通过比较点距来判断是否是剩余点
第二种方法是使用八叉树来做,先写第一种方法,有时间更新八叉树。
话不多说,完成这个需要先将所有聚类的面整合在一起输出成一个pcd
//当聚类完后,提取聚类点的索引这一步相信都会关键代码:
pcl::聚类算法不同这里也不同<pcl::PointXYZ, pcl::Normal>YY;
std::vector<pcl::PointIndices>XX;
YY.extract(XX);//提取点索引
//输出所有聚类面
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudout(new pcl::PointCloud<pcl::PointXYZ>);//存在cloudout里
pcl::copyPointCloud(*cloud,XX,*cloudout);//copy函数用法自行百度
std::out<<"复制后"<<cloudout->points.size()<<std::endl;//查看所有聚类点数
pcl::io::savePCDFile("SS.pcd",*cloudout);//聚类所有面输出为SS.pcd
到这里第一步就完事了,下面是最重要的kd-tree部分:
//存放A,B点云的代码块
pcl::PointCloud<pcl::PointXYZ>::Ptr Acloud(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile<pcl::PointXYZ>("A.pcd", *Acloud) == -1)
{
PCL_ERROR("出错\n");
return(-1);
}
int Apoints = (int)Acloud->points.size();
int Bpoints = (int)Bcloud->points.size();
std::vector<int> LA(Apoints, 0);
std::vector<int> LB(Bpoints, 0);
std::vector<int> LA; LA.clear();
std::vector<int> LB; LB.clear();
for (int i = 0; i < Apoints; ++i)
{
if (kdtree.nearestKSearch(Acloud->points[i], K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0)
{
if (pointNKNSquaredDistance[0] == 0)
{
LA[i] = 1;
LB[pointIdxNKNSearch[0]] = 1;
}
}
}
这里是第一种方法,第一种方法实际上是便利判断两个点云的不同,试用场景较广,但是遍历,效率太低,如果仅想知道两个点云相比较多了那些点,使用八叉树更为迅速
点云库pcl教程,第6章八叉树
第131页