基于PCL库以已知点P为起点的K-Means单点聚类C++实现

本篇博客提供了一个使用 PCL 库实现以已知点 P 为起点的单点聚类的 C++ 代码示例。

代码示例

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d.h>
#include <pcl/segmentation/extract_clusters.h>

int main() {
    // 读取点云数据
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::io::loadPCDFile<pcl::PointXYZ>('input_cloud.pcd', *cloud);

    // 创建Kd树对象
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
    tree->setInputCloud(cloud);

    // 设置起始点P
    pcl::PointXYZ searchPoint;
    searchPoint.x = 0.0; // 设置起始点 P 的 x 坐标
    searchPoint.y = 0.0; // 设置起始点 P 的 y 坐标
    searchPoint.z = 0.0; // 设置起始点 P 的 z 坐标

    // 在Kd树中查找距离searchPoint最近的点
    int K = 1; // 只查找一个最近点
    std::vector<int> pointIdxNKNSearch(K);
    std::vector<float> pointNKNSquaredDistance(K);
    tree->nearestKSearch(searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance);

    // 获取最近点的索引
    int nearestPointIndex = pointIdxNKNSearch[0];

    // 估计法线
    pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normalEstimation;
    normalEstimation.setInputCloud(cloud);
    normalEstimation.setSearchMethod(tree);
    normalEstimation.setKSearch(10);
    normalEstimation.compute(*normals);

    // 创建分割对象
    pcl::EuclideanClusterExtraction<pcl::PointXYZ> euclideanCluster;
    euclideanCluster.setClusterTolerance(0.02); // 设置聚类的距离阈值
    euclideanCluster.setMinClusterSize(100); // 设置聚类的最小点数
    euclideanCluster.setMaxClusterSize(25000); // 设置聚类的最大点数
    euclideanCluster.setSearchMethod(tree);
    euclideanCluster.setInputCloud(cloud);
    euclideanCluster.setInputNormals(normals);

    // 执行聚类
    std::vector<pcl::PointIndices> clusterIndices;
    euclideanCluster.extract(clusterIndices);

    // 查找包含起始点P的聚类
    int targetClusterIndex = -1;
    for (size_t i = 0; i < clusterIndices.size(); ++i) {
        if (std::find(clusterIndices[i].indices.begin(), 
                      clusterIndices[i].indices.end(), 
                      nearestPointIndex) != clusterIndices[i].indices.end()) {
            targetClusterIndex = i;
            break;
        }
    }

    // 输出目标聚类结果
    if (targetClusterIndex != -1) {
        std::cout << '目标聚类点云:' << std::endl;
        for (int i : clusterIndices[targetClusterIndex].indices) {
            std::cout << 'Point: ' << cloud->points[i].x << ' ' 
                      << cloud->points[i].y << ' ' 
                      << cloud->points[i].z << std::endl;
        }
    } else {
        std::cout << '未找到包含起始点P的聚类' << std::endl;
    }

    return 0;
}

代码说明

  1. 设置起始点 P: 代码首先定义了起始点 searchPoint,并设置其 x、y、z 坐标。
  2. 查找最近点: 使用 tree->nearestKSearch() 函数在 Kd 树中查找距离 searchPoint 最近的点,并将结果存储在 pointIdxNKNSearch 中。
  3. 获取最近点索引:pointIdxNKNSearch 中获取最近点的索引值。
  4. 执行聚类: 使用欧式聚类算法对点云进行分割,并将结果存储在 clusterIndices 中。
  5. 查找目标聚类: 遍历 clusterIndices 中的所有聚类,查找包含起始点 searchPoint 的聚类,并将该聚类的索引存储在 targetClusterIndex 中。
  6. 输出目标聚类结果: 如果找到了包含起始点 searchPoint 的聚类,则输出该聚类中所有点的坐标信息。

注意

  • 该代码假设您已经有一个名为 input_cloud.pcd 的输入点云文件,其中包含您的点云数据。您需要将文件路径更改为实际的点云文件路径。
  • 此代码中的 setClusterTolerancesetMinClusterSizesetMaxClusterSize 函数用于设置聚类的距离阈值、最小点数和最大点数。您可以根据需要进行调整。
  • 此代码还使用了 NormalEstimation 类来估计点云的法线。如果您的输入点云已经包含法线信息,则可以跳过此步骤。
  • 该代码实现了以距离起始点P最近的点为中心的单点聚类。如果您需要实现以起始点P本身为中心的单点聚类,需要将nearestPointIndex替换为起始点P在点云中的索引。

希望这个代码示例对您有所帮助!

基于PCL库的K-Means单点聚类C++实现

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

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