基于PCL库的K-Means单点聚类C++实现
基于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;
}
代码说明
- 设置起始点 P: 代码首先定义了起始点
searchPoint,并设置其 x、y、z 坐标。 - 查找最近点: 使用
tree->nearestKSearch()函数在 Kd 树中查找距离searchPoint最近的点,并将结果存储在pointIdxNKNSearch中。 - 获取最近点索引: 从
pointIdxNKNSearch中获取最近点的索引值。 - 执行聚类: 使用欧式聚类算法对点云进行分割,并将结果存储在
clusterIndices中。 - 查找目标聚类: 遍历
clusterIndices中的所有聚类,查找包含起始点searchPoint的聚类,并将该聚类的索引存储在targetClusterIndex中。 - 输出目标聚类结果: 如果找到了包含起始点
searchPoint的聚类,则输出该聚类中所有点的坐标信息。
注意
- 该代码假设您已经有一个名为
input_cloud.pcd的输入点云文件,其中包含您的点云数据。您需要将文件路径更改为实际的点云文件路径。 - 此代码中的
setClusterTolerance、setMinClusterSize和setMaxClusterSize函数用于设置聚类的距离阈值、最小点数和最大点数。您可以根据需要进行调整。 - 此代码还使用了
NormalEstimation类来估计点云的法线。如果您的输入点云已经包含法线信息,则可以跳过此步骤。 - 该代码实现了以距离起始点P最近的点为中心的单点聚类。如果您需要实现以起始点P本身为中心的单点聚类,需要将
nearestPointIndex替换为起始点P在点云中的索引。
希望这个代码示例对您有所帮助!
原文地址: https://www.cveoy.top/t/topic/fC5O 著作权归作者所有。请勿转载和采集!