PCL 点云聚类:基于 K-Means 算法的改进方法
#include
int main() { // 读取点云数据 pcl::PointCloudpcl::PointXYZ::Ptr cloud(new pcl::PointCloudpcl::PointXYZ); pcl::io::loadPLYFilepcl::PointXYZ('D:\DIANYUNWENJIANJIA\kruskal_ply.ply', *cloud);
// 设置参数
int maxIterations = 100; // 最大迭代次数
double distanceThreshold = 0.01; // 聚类中心之间的距离阈值
double clusterTolerance = 0.1; // 聚类的容差
int minClusterSize = 100; // 最小聚类大小
int maxClusterSize = 25000; // 最大聚类大小
// 初始化聚类中心
std::vector<pcl::PointXYZ> clusterCenters;
for (const auto& point : cloud->points)
{
clusterCenters.push_back(point);
}
// 迭代聚类
for (int i = 0; i < maxIterations; i++)
{
// 分配点到最近的聚类中心
std::vector<std::vector<int>> clusters(clusterCenters.size());
pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
kdtree.setInputCloud(cloud);
for (int j = 0; j < cloud->size(); j++)
{
pcl::PointXYZ point = cloud->points[j];
int nearestCluster = 0;
double minDistance = std::numeric_limits<double>::max();
for (int k = 0; k < clusterCenters.size(); k++)
{
double distance = pcl::euclideanDistance(clusterCenters[k], point);
if (distance < minDistance)
{
minDistance = distance;
nearestCluster = k;
}
}
clusters[nearestCluster].push_back(j);
}
// 计算新的聚类中心
std::vector<pcl::PointXYZ> newClusterCenters;
for (const auto& cluster : clusters)
{
pcl::PointXYZ newCenter;
for (const auto& index : cluster)
{
newCenter.x += cloud->points[index].x;
newCenter.y += cloud->points[index].y;
newCenter.z += cloud->points[index].z;
}
newCenter.x /= cluster.size();
newCenter.y /= cluster.size();
newCenter.z /= cluster.size();
newClusterCenters.push_back(newCenter);
}
// 检查聚类中心是否发生变化
bool centersChanged = false;
for (int j = 0; j < clusterCenters.size(); j++)
{
if (pcl::euclideanDistance(clusterCenters[j], newClusterCenters[j]) > distanceThreshold)
{
centersChanged = true;
break;
}
}
if (!centersChanged)
{
break;
}
clusterCenters = newClusterCenters;
}
// 构建kd树
pcl::search::Search<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
tree->setInputCloud(cloud);
// 分割聚类
std::vector<pcl::PointIndices> clusterIndices;
pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
ec.setClusterTolerance(clusterTolerance);
ec.setMinClusterSize(minClusterSize);
ec.setMaxClusterSize(maxClusterSize);
ec.setSearchMethod(tree);
ec.setInputCloud(cloud);
ec.extract(clusterIndices);
// 输出聚类结果
pcl::PointCloud<pcl::PointXYZRGB>::Ptr coloredCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
int colorIndex = 0;
for (const auto& indices : clusterIndices)
{
pcl::PointXYZRGB color;
color.r = colorIndex % 256;
color.g = (colorIndex / 256) % 256;
color.b = (colorIndex / 256 / 256) % 256;
for (const auto& index : indices.indices)
{
pcl::PointXYZRGB point;
point.x = cloud->points[index].x;
point.y = cloud->points[index].y;
point.z = cloud->points[index].z;
point.r = color.r;
point.g = color.g;
point.b = color.b;
coloredCloud->points.push_back(point);
}
colorIndex++;
}
coloredCloud->width = coloredCloud->points.size();
coloredCloud->height = 1;
coloredCloud->is_dense = true;
// 保存结果
pcl::io::savePLYFileBinary('D:\DIANYUNWENJIANJIA\2MEANS_ply.ply', *coloredCloud);
return 0;
}
原文地址: https://www.cveoy.top/t/topic/pyqN 著作权归作者所有。请勿转载和采集!