#include #include <pcl/io/ply_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> #include <pcl/common/distances.h> #include <pcl/search/search.h> #include <pcl/search/kdtree.h>

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;

}

PCL 点云聚类:基于 K-Means 算法的改进方法

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

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