#include #include <pcl/io/ply_io.h> #include <pcl/point_types.h> #include <pcl/visualization/pcl_visualizer.h> #include <pcl/features/organized_edge_detection.h> #include <pcl/segmentation/supervoxel_clustering.h> #include <pcl/common/common.h>

typedef pcl::PointXYZ PointT; typedef pcl::PointCloud PointCloudT;

// 边结构体,存储两个点的索引和边的权值 struct Edge { int src; int dest; float weight; };

// 并查集结构体,用于判断两个点是否在同一个集合中 struct UnionFind { int *parent, *rank; int n;

UnionFind(int n)
{
    this->n = n;
    parent = new int[n];
    rank = new int[n];

    for (int i = 0; i < n; i++)
    {
        parent[i] = i;
        rank[i] = 0;
    }
}

int find(int x)
{
    if (x != parent[x])
        parent[x] = find(parent[x]);
    return parent[x];
}

void Union(int x, int y)
{
    int xroot = find(x);
    int yroot = find(y);

    if (rank[xroot] < rank[yroot])
        parent[xroot] = yroot;
    else if (rank[xroot] > rank[yroot])
        parent[yroot] = xroot;
    else
    {
        parent[yroot] = xroot;
        rank[xroot]++;
    }
}

};

// 比较函数,用于对边按照权值进行排序 bool compareEdges(const Edge &e1, const Edge &e2) { return e1.weight < e2.weight; }

// Kruskal最小生成树算法 void kruskalMST(PointCloudT::Ptr cloud, std::vector &edges) { int num_points = cloud->size(); std::vector result;

// 按照边的权值进行排序
std::sort(edges.begin(), edges.end(), compareEdges);

UnionFind uf(num_points);

for (int i = 0; i < edges.size(); i++)
{
    int src_root = uf.find(edges[i].src);
    int dest_root = uf.find(edges[i].dest);

    // 判断两个点是否在同一个集合中,如果不在则加入最小生成树中
    if (src_root != dest_root)
    {
        result.push_back(edges[i]);
        uf.Union(src_root, dest_root);
    }
}

// 可视化最小生成树
pcl::visualization::PCLVisualizer viewer('Minimum Spanning Tree');
viewer.setBackgroundColor(0.0, 0.0, 0.0);

// 将点云添加到可视化视窗中
pcl::visualization::PointCloudColorHandlerCustom<PointT> single_color(cloud, 0, 255, 0);
viewer.addPointCloud(cloud, single_color, 'cloud');

// 将最小生成树的边添加到可视化视窗中
for (int i = 0; i < result.size(); i++)
{
    PointT pt1 = cloud->at(result[i].src);
    PointT pt2 = cloud->at(result[i].dest);

    std::stringstream ss;
    ss << 'edge_' << i;
    viewer.addLine(pt1, pt2, 255, 0, 0, ss.str());
}

while (!viewer.wasStopped())
{
    viewer.spinOnce();
}

}

int main() { // 加载PLY文件 PointCloudT::Ptr cloud(new PointCloudT); pcl::io::loadPLYFile('input.ply', *cloud);

// 计算点云之间的边
std::vector<Edge> edges;
for (int i = 0; i < cloud->size(); i++)
{
    for (int j = i + 1; j < cloud->size(); j++)
    {
        Edge edge;
        edge.src = i;
        edge.dest = j;
        edge.weight = pcl::euclideanDistance(cloud->at(i), cloud->at(j));
        edges.push_back(edge);
    }
}

// 使用Kruskal算法构建最小生成树并可视化
kruskalMST(cloud, edges);

return 0;

}

// 请注意,此代码仅仅对点云中的点进行了连接,并没有考虑点云的拓扑结构。如果需要构建有意义的3D模型,可以考虑使用SuperVoxel算法对点云进行分割和分析。

基于PCL 1.8.1库的点云PLY文件最小生成树算法可视化C++代码

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

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