基于PCL库的C++ K-Means点云聚类,从已知点开始

本文将介绍如何使用PCL库进行以已知点为起点的K-Means点云聚类,并提供完整的C++代码示例。

1. 简介

K-Means算法是一种常用的聚类算法,它可以将数据集划分到不同的簇中。在点云处理中,K-Means算法可以用于分割不同的物体或识别点云中的不同区域。

本文将介绍如何使用PCL库中的K-Means算法实现点云聚类,并以一个已知点作为聚类起点。

2. 代码示例cpp#include #include <pcl/io/pcd_io.h>#include <pcl/point_types.h>#include <pcl/features/normal_3d.h>#include <pcl/kdtree/kdtree_flann.h>#include <pcl/segmentation/extract_clusters.h>#include <pcl/visualization/cloud_viewer.h>

int main(int argc, char** argv){ // 加载点云数据 pcl::PointCloudpcl::PointXYZ::Ptr cloud(new pcl::PointCloudpcl::PointXYZ); pcl::PCDReader reader; reader.readpcl::PointXYZ('input_cloud.pcd', *cloud);

// 创建法线估计对象    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;    ne.setInputCloud(cloud);

// 创建一个空的kdtree对象,并把它传递给法线估计对象    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());    ne.setSearchMethod(tree);

// 容器存储输出的法线    pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);

// 估计法线    ne.setKSearch(10); // 设置k近邻搜索的数量    ne.compute(*cloud_normals);

// 创建一个空的kd树对象,并把它传递给聚类对象    pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree(new pcl::search::KdTree<pcl::PointXYZ>());

// 创建一个向量存储点云索引    std::vector<pcl::PointIndices> cluster_indices;

// 创建欧氏聚类对象    pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;    ec.setClusterTolerance(0.02); // 设置聚类的容差    ec.setMinClusterSize(100); // 设置聚类的最小点数    ec.setMaxClusterSize(25000); // 设置聚类的最大点数    ec.setSearchMethod(kdtree);    ec.setInputCloud(cloud);    ec.setIndices(cloud_normals);

// **设置已知点作为聚类起点**    pcl::PointXYZ known_point(0.0, 0.0, 0.0); // 设置已知点的坐标    std::vector<int> nearest_indices;    std::vector<float> nearest_distances;    kdtree->nearestKSearch(known_point, 1, nearest_indices, nearest_distances);    int start_index = nearest_indices[0];    ec.setClusterStartIndices({start_index}); // 将已知点的索引作为聚类起点

// 执行聚类    ec.extract(cluster_indices);

// 创建可视化对象    pcl::visualization::PCLVisualizer viewer('Cluster viewer');

// 设置背景颜色    viewer.setBackgroundColor(0, 0, 0);

// 设置点云颜色    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color(cloud, 0, 255, 0);    viewer.addPointCloud<pcl::PointXYZ>(cloud, single_color, 'input_cloud');

// 遍历所有聚类    int cluster_id = 0;    for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin(); it != cluster_indices.end(); ++it)    {        // 创建一个新的点云数据对象,用于存储当前聚类的点云数据        pcl::PointCloud<pcl::PointXYZ>::Ptr cluster_cloud(new pcl::PointCloud<pcl::PointXYZ>);

    // 遍历当前聚类的所有点        for (std::vector<int>::const_iterator pit = it->indices.begin(); pit != it->indices.end(); ++pit)        {            // 将当前点添加到聚类点云数据对象中            cluster_cloud->points.push_back(cloud->points[*pit]);        }

    // 设置聚类点云数据对象的属性        cluster_cloud->width = cluster_cloud->points.size();        cluster_cloud->height = 1;        cluster_cloud->is_dense = true;

    // 设置聚类点云数据对象的颜色        pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cluster_color(cluster_cloud, rand() % 255, rand() % 255, rand() % 255);        std::string cluster_name = 'cluster_' + std::to_string(cluster_id);        viewer.addPointCloud<pcl::PointXYZ>(cluster_cloud, cluster_color, cluster_name);

    // 显示当前聚类的点云数据对象        viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, cluster_name);

    // 增加聚类ID        cluster_id++;    }

// 显示点云数据    while (!viewer.wasStopped())    {        viewer.spinOnce();    }

return 0;}

3. 代码解释

  • 首先,代码加载点云数据并进行法线估计。法线信息可以帮助提高聚类效果。- 然后,代码创建了一个 pcl::EuclideanClusterExtraction 对象,并设置了聚类参数,包括容差、最小点数、最大点数等。- 为了以已知点作为聚类起点,代码使用 kdtree->nearestKSearch 函数找到距离已知点最近的点的索引,并将该索引作为聚类起点传递给 ec.setClusterStartIndices 函数。- 最后,代码执行聚类并将结果可视化。

4. 总结

本文介绍了如何使用PCL库进行以已知点为起点的K-Means点云聚类,并提供了完整的C++代码示例。您可以根据自己的需求修改代码中的参数,以获得最佳的聚类效果。

希望这篇文章对您有所帮助!

基于PCL库的C++ K-Means点云聚类,从已知点开始

原文地址: https://www.cveoy.top/t/topic/fC5M 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录