点云检测--欧式聚类Euclidean Cluster

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.效果

左图为原始点云,右图为聚类结果。
在这里插入图片描述