注意:欧式聚类很常用。
1.欧式聚类原理:
(1)对点云建KD树。并选取点云中内某一初始点P。
(2)对P进行邻近搜索,获取其在用户设定的距离阈值内的所有点云点。加入集合Q。
(3)对集合Q内未进行临近搜索的所有点云点按照用户设定的距离阈值进行邻近搜索。
(4)不停迭代(2)(3),得到一簇符合距离阈值的点。
(5)重新设置未聚类的点云初始点P,再进行如上步骤,直到聚类得到所有点云。
如下图:
假设我们设置的初始点P在红色部分中,
1)我们首先通过距离阈值,不停摸完附近点云,直到摸无可摸,得到红色簇的点云簇。
2)更换初始点P的位置(红色簇已聚类,被剔除,因此只能在其他点云中得到初始点P)。假设更换后的初始点P在蓝色簇中,再进行1)的步骤,摸出蓝色簇。
3)如此反复,直到得到所有点云点。
2.使用场景
欧式聚类非常常用,在点云不连通的情况下,聚类效果较好,参数调整也较少。
3.关键函数
(1)设置邻近搜索的半径,也就是你摸点云时候的距离阈值
segmentation.setClusterTolerance(1.3);
(2)一簇点包含的最少点数(少于这个点数不当作点云簇)
segmentation.setMinClusterSize(50);
(3)一簇点包含的最大点数(大于这个点数不当作点云簇)
segmentation.setMaxClusterSize(10000);
(4)得到的结果为分簇之后的点云索引
std::vector<pcl::PointIndices> clusterIndices; // 聚类后点云
segmentation.extract(clusterIndices);
4.完整代码
#include <iostream>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/common/colors.h>
#include <pcl/kdtree/kdtree.h>
#include <pcl/segmentation/extract_clusters.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
int main()
{
/****************欧式聚类********************/
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); // 源点云
pcl::io::loadPCDFile("D:/code/csdn/data/kmeansTest.pcd", *cloud);
// 欧式聚类
pcl::EuclideanClusterExtraction<pcl::PointXYZ> segmentation; // 欧式聚类对象
segmentation.setClusterTolerance(1.3); // 近邻搜索的搜索半径为2cm(也即两个不同聚类团点之间的最小欧氏距离)
segmentation.setMinClusterSize(50); // 一簇点包含的最少点数
segmentation.setMaxClusterSize(10000); // 一簇点包含的最大点数
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
tree->setInputCloud(cloud);
segmentation.setSearchMethod(tree);
segmentation.setInputCloud(cloud);
std::vector<pcl::PointIndices> clusterIndices; // 聚类后点云
segmentation.extract(clusterIndices);
// 提取聚类后点云
std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr> clustreClouds;
for (size_t i = 0; i < clusterIndices.size(); i++)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudTemp(new pcl::PointCloud<pcl::PointXYZ>);
pcl::copyPointCloud(*cloud, clusterIndices[i], *cloudTemp);
clustreClouds.push_back(cloudTemp);
}
/****************展示********************/
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("EuclideanClusterExtraction"));
for (size_t i = 0; i < clustreClouds.size(); i++)
{
pcl::RGB rgb = pcl::getRandomColor(0, 255);
viewer->addPointCloud<pcl::PointXYZ>(clustreClouds.at(i), pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>(clustreClouds.at(i), rgb.r, rgb.g, rgb.b), "clustreClouds" + i);
}
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
return (0);
}