1.版本要求
版本: >PCL1.3
2.简介
欧式聚类是点云聚类的一种重要方法,利用点云中点与点之间的欧式距离进行聚类,当点与点之间的欧式距离小于设定的阈值则视为一类。欧式聚类是车辆前方障碍物检测的重要方法。
3.数据
本例中使用的点云数据(test.pcd)请见百度网盘分享。
链接:https://pan.baidu.com/s/1io3q_ESUbhdGT2vr6-NuVA
提取码:ias2
4.代码
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree.h>
#include <pcl/segmentation/extract_clusters.h>
#include <pcl/visualization/cloud_viewer.h>
int main(int argc, char** argv)
{
// 读取测试点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PCDReader reader;
reader.read("test.pcd", *cloud);
// 创建KdTreea对象用于点云搜索
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
tree->setInputCloud(cloud);
std::vector<pcl::PointIndices> cluster_indices; //创建索引对象向量,用于存储不同聚类结果的点云索引
pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec; //创建欧式聚类对象
ec.setClusterTolerance(0.13); // 设置距离阈值为13cm。点与点之间小于这个距离阈值视为一类
ec.setMinClusterSize(200); //设置聚类最少点数
ec.setMaxClusterSize(5000); //设置聚类最大点数
ec.setSearchMethod(tree); //输入点云搜索方法
ec.setInputCloud(cloud);
ec.extract(cluster_indices); //开始聚类
//将聚类结果合成一幅点云,方便后面对比显示
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster(new pcl::PointCloud<pcl::PointXYZ>);
for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin(); it != cluster_indices.end(); ++it) //循环一次就是一个聚类结果
{
for (std::vector<int>::const_iterator pit = it->indices.begin(); pit != it->indices.end(); ++pit)
cloud_cluster->push_back((*cloud)[*pit]); //每个聚类结果都装到cloud_cluster这幅点云里
}
cloud_cluster->width = cloud_cluster->size(); //点云尺寸的明确,存储点云前需要明确尺寸大小
cloud_cluster->height = 1;
cloud_cluster->is_dense = true;
//对比显示聚类结果
pcl::visualization::PCLVisualizer viewer("Cloud Viewer");
int v1(0); //创建左窗口显示原始点云
viewer.createViewPort(0, 0, 0.5, 1.0, v1); //左右窗口大小划分,1:1
viewer.setBackgroundColor(0, 0, 0, v1);
viewer.addText("Original Cloud", 2, 2, "Original Cloud", v1);
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> rgb1(cloud, "z");
viewer.addPointCloud<pcl::PointXYZ>(cloud, rgb1, "original cloud", v1);
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "original cloud", v1);
viewer.addCoordinateSystem(1.0, "original cloud", v1);
int v2(1); //创建右窗口显示聚类结果
viewer.createViewPort(0.5, 0, 1.0, 1.0, v2); //左右窗口大小划分,1:1
viewer.setBackgroundColor(0, 0, 0, v2);
viewer.addText("Clustered Cloud", 2, 2, "Clustered Cloud", v2);
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> rgb2(cloud_cluster, "z");
viewer.addPointCloud<pcl::PointXYZ>(cloud_cluster, rgb2, "clustered cloud", v2);
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "clustered cloud", v2);
viewer.addCoordinateSystem(1.0, "clustered cloud", v2);
viewer.spin(); //循环不断显示点云
return (0);
}
5.效果
左图为原始点云,右图为聚类结果。