使用Kruskal最小生成树算法可视化连接点云PLY文件中的点
以下是基于PCL库使用Kruskal最小生成树处理点云PLY文件并将各个点按照生成树顺序连接可视化的C++代码:\n\ncpp\n#include \"iostream\"\n#include \"pcl/io/ply_io.h\"\n#include \"pcl/point_types.h\"\n#include \"pcl/visualization/pcl_visualizer.h\"\n#include \"pcl/common/common.h\"\n#include \"pcl/common/transforms.h\"\n#include \"pcl/segmentation/extract_clusters.h\"\n#include \"pcl/features/normal_3d.h\"\n#include \"pcl/registration/ia_ransac.h\"\n#include \"pcl/common/eigen.h\"\n#include \"pcl/segmentation/sac_segmentation.h\"\n#include \"pcl/filters/voxel_grid.h\"\n\ntypedef pcl::PointXYZRGB PointT;\ntypedef pcl::PointCloud<PointT> PointCloudT;\n\n// Structure to represent a weighted edge in graph\nstruct Edge {\n int src, dest;\n float weight;\n};\n\n// Structure to represent a connected, undirected and weighted graph\nstruct Graph {\n // V-> Number of vertices, E-> Number of edges\n int V, E;\n\n // graph is represented as an array of edges\n struct Edge* edge;\n};\n\n// Creates a graph with V vertices and E edges\nstruct Graph* createGraph(int V, int E)\n{\n struct Graph* graph = new Graph;\n graph->V = V;\n graph->E = E;\n graph->edge = new Edge[E];\n return graph;\n}\n\n// A structure to represent a subset for union-find\nstruct subset {\n int parent;\n int rank;\n};\n\n// A utility function to find set of an element i\n// (uses path compression technique)\nint find(struct subset subsets[], int i)\n{\n // find root and make root as parent of i \n // (path compression)\n if (subsets[i].parent != i)\n subsets[i].parent = find(subsets, subsets[i].parent);\n\n return subsets[i].parent;\n}\n\n// A function that does union of two sets of x and y\n// (uses union by rank)\nvoid Union(struct subset subsets[], int x, int y)\n{\n int xroot = find(subsets, x);\n int yroot = find(subsets, y);\n\n // Attach smaller rank tree under root of high rank tree\n // (Union by Rank)\n if (subsets[xroot].rank < subsets[yroot].rank)\n subsets[xroot].parent = yroot;\n else if (subsets[xroot].rank > subsets[yroot].rank)\n subsets[yroot].parent = xroot;\n\n // If ranks are same, then make one as root and increment\n // its rank by one\n else {\n subsets[yroot].parent = xroot;\n subsets[xroot].rank++;\n }\n}\n\n// Compare two edges according to their weights.\n// Used in qsort() for sorting an array of edges\nint myComp(const void* a, const void* b)\n{\n struct Edge* a1 = (struct Edge*)a;\n struct Edge* b1 = (struct Edge*)b;\n return a1->weight > b1->weight;\n}\n\n// The main function to construct MST using Kruskal's algorithm\nvoid kruskalMST(struct Graph* graph, PointCloudT::Ptr cloud)\n{\n int V = graph->V;\n struct Edge result[V]; // Tnis will store the resultant MST\n int e = 0; // An index variable, used for result[]\n int i = 0; // An index variable, used for sorted edges\n\n // Step 1: Sort all the edges in non-decreasing order of their weight\n // If we are not allowed to change the given graph, we can create a copy of\n // array of edges\n qsort(graph->edge, graph->E, sizeof(graph->edge[0]), myComp);\n\n // Allocate memory for creating V ssubsets\n struct subset* subsets = new subset[(V * sizeof(struct subset))];\n\n // Create V subsets with single elements\n for (int v = 0; v < V; ++v) {\n subsets[v].parent = v;\n subsets[v].rank = 0;\n }\n\n // Number of edges to be taken is equal to V-1\n while (e < V - 1 && i < graph->E) {\n // Step 2: Pick the smallest edge. And increment \n // the index for next iteration\n struct Edge next_edge = graph->edge[i++];\n\n int x = find(subsets, next_edge.src);\n int y = find(subsets, next_edge.dest);\n\n // If including this edge does't cause cycle, \n // include it in result and increment the index\n // of result for next edge\n if (x != y) {\n result[e++] = next_edge;\n Union(subsets, x, y);\n }\n // Else discard the next_edge\n }\n\n // print the contents of result[] to display the built MST\n pcl::visualization::PCLVisualizer viewer("Cloud Viewer");\n viewer.setBackgroundColor(0, 0, 0);\n\n for (i = 0; i < e; ++i) {\n int srcIdx = result[i].src;\n int destIdx = result[i].dest;\n\n PointT srcPt = cloud->points[srcIdx];\n PointT destPt = cloud->points[destIdx];\n\n pcl::PointXYZRGB srcPtRGB;\n srcPtRGB.x = srcPt.x;\n srcPtRGB.y = srcPt.y;\n srcPtRGB.z = srcPt.z;\n srcPtRGB.r = 255;\n srcPtRGB.g = 0;\n srcPtRGB.b = 0;\n\n pcl::PointXYZRGB destPtRGB;\n destPtRGB.x = destPt.x;\n destPtRGB.y = destPt.y;\n destPtRGB.z = destPt.z;\n destPtRGB.r = 255;\n destPtRGB.g = 0;\n destPtRGB.b = 0;\n\n std::string edgeId = "edge" + std::to_string(i);\n viewer.addLine(srcPtRGB, destPtRGB, edgeId);\n }\n\n while (!viewer.wasStopped()) {\n viewer.spinOnce(100);\n std::this_thread::sleep_for(std::chrono::milliseconds(100));\n }\n}\n\nint main(int argc, char** argv)\n{\n // Read input cloud from PLY file\n PointCloudT::Ptr cloud(new PointCloudT);\n pcl::PLYReader reader;\n reader.read("input_cloud.ply", *cloud);\n\n // Create a graph from the point cloud\n int V = cloud->size();\n int E = V * (V - 1) / 2;\n struct Graph* graph = createGraph(V, E);\n int edgeIndex = 0;\n\n for (int i = 0; i < cloud->size(); i++) {\n for (int j = i + 1; j < cloud->size(); j++) {\n PointT srcPt = cloud->points[i];\n PointT destPt = cloud->points[j];\n\n float distance = pcl::euclideanDistance(srcPt, destPt);\n\n graph->edge[edgeIndex].src = i;\n graph->edge[edgeIndex].dest = j;\n graph->edge[edgeIndex].weight = distance;\n edgeIndex++;\n }\n }\n\n // Find minimum spanning tree and visualize it\n kruskalMST(graph, cloud);\n\n return 0;\n}\n\n\n这段代码首先读取一个PLY文件作为输入点云,然后根据输入点云的坐标计算各个点之间的距离,并构建成一个加权无向图。接下来,使用Kruskal算法找到该图的最小生成树,并将最小生成树的边可视化。最后,使用PCL的可视化工具显示生成的点云和边。\n\n请注意,此代码假设输入的PLY文件包含点的XYZ坐标和RGB颜色信息。如果您的PLY文件不包含颜色信息,您可能需要进行相应的修改。
原文地址: https://www.cveoy.top/t/topic/pq4J 著作权归作者所有。请勿转载和采集!