#include\x3ciostream\x3e\n#include\x3cpcl/io/ply_io.h\x3e\n#include\x3cpcl/point_types.h\x3e\n#include\x3cpcl/features/normal_3d.h\x3e\n#include\x3cpcl/surface/mls.h\x3e\n#include\x3cpcl/kdtree/kdtree_flann.h\x3e\n\nint main() {\n\t// 输入文件路径\n\tstd::string input_file = "D:\DIANYUNWENJIANJIA\kruskal_ply.ply";\n\n\t// 加载点云数据\n\tpcl::PointCloudpcl::PointXYZ::Ptr cloud(new pcl::PointCloudpcl::PointXYZ);\n\tif (pcl::io::loadPLYFile(input_file, *cloud) == -1) {\n\t std::cerr << "Failed to load input file!" << std::endl;\n\t return -1;\n\t}\n\n\t// 手动计算法线\n\tpcl::PointCloudpcl::Normal::Ptr normals(new pcl::PointCloudpcl::Normal);\n\tpcl::search::KdTreepcl::PointXYZ::Ptr tree(new pcl::search::KdTreepcl::PointXYZ);\n\ttree->setInputCloud(cloud);\n\n\t// 设置计算法线的K值\n\tint k = 10;\n\n\t// 遍历每个点,计算其法线\n\tfor (size_t i = 0; i < cloud->size(); i++) {\n\t pcl::Normal normal;\n\t std::vector k_indices(k);\n\t std::vector k_distances(k);\n\t tree->nearestKSearch(cloud->points[i], k, k_indices, k_distances);\n\n\t // 计算协方差矩阵\n\t Eigen::Matrix3f covariance_matrix;\n\t Eigen::Vector4f centroid;\n\t pcl::computeMeanAndCovarianceMatrix(*cloud, k_indices, covariance_matrix, centroid);\n\n\t // 使用特征值分解计算法线\n\t Eigen::SelfAdjointEigenSolverEigen::Matrix3f eigen_solver(covariance_matrix, Eigen::ComputeEigenvectors);\n\t Eigen::Vector3f normal_vector = eigen_solver.eigenvectors().col(0);\n\n\t normal.normal_x = normal_vector[0];\n\t normal.normal_y = normal_vector[1];\n\t normal.normal_z = normal_vector[2];\n\t normals->push_back(normal);\n\t}\n\n\t// 阈值α\n\tfloat alpha = 3.0;\n\n\t// 骨架修建和节点分类\n\tpcl::PointCloudpcl::PointXYZ::Ptr skeleton(new pcl::PointCloudpcl::PointXYZ);\n\tstd::vector labels(cloud->size(), -1);\n\tfor (size_t i = 0; i < cloud->size(); i++) {\n\t int neighbor_count = 0;\n\t std::vector k_indices(5);\n\t std::vector k_distances(5);\n\t tree->nearestKSearch(cloud->points[i], 5, k_indices, k_distances);\n\n\t for (int j = 0; j < k_indices.size(); j++) {\n\t int neighbor_index = k_indices[j];\n\t if (cloud->points[i].x < cloud->points[neighbor_index].x) {\n\t neighbor_count++;\n\t }\n\t }\n\n\t if (neighbor_count < alpha) {\n\t labels[i] = 3; // 丢弃的分支\n\t } else if (neighbor_count == 1) {\n\t labels[i] = 0; // 叶尖\n\t } else if (neighbor_count == 2) {\n\t labels[i] = 1; // 内部节点\n\t } else if (neighbor_count >= 3) {\n\t labels[i] = 2; // 结点\n\t skeleton->push_back(cloud->points[i]);\n\t }\n\t}\n\n\t// 保存输出点云数据\n\tstd::string output_file = "D:\DIANYUNWENJIANJIA\gujiaxiujianhejiedianfenlei_ply.ply";\n\tpcl::PointCloudpcl::PointXYZRGB colored_cloud;\n\tcolored_cloud.width = cloud->size();\n\tcolored_cloud.height = 1;\n\tcolored_cloud.is_dense = false;\n\tcolored_cloud.points.resize(colored_cloud.width * colored_cloud.height);\n\tfor (size_t i = 0; i < colored_cloud.points.size(); i++) {\n\t colored_cloud.points[i].x = cloud->points[i].x;\n\t colored_cloud.points[i].y = cloud->points[i].y;\n\t colored_cloud.points[i].z = cloud->points[i].z;\n\t if (labels[i] == 0) {\n\t colored_cloud.points[i].r = 255;\n\t colored_cloud.points[i].g = 0;\n\t colored_cloud.points[i].b = 0;\n\t } else if (labels[i] == 1) {\n\t colored_cloud.points[i].r = 0;\n\t colored_cloud.points[i].g = 255;\n\t colored_cloud.points[i].b = 0;\n\t } else if (labels[i] == 2) {\n\t colored_cloud.points[i].r = 0;\n\t colored_cloud.points[i].g = 0;\n\t colored_cloud.points[i].b = 255;\n\t } else if (labels[i] == 3) {\n\t colored_cloud.points[i].r = 255;\n\t colored_cloud.points[i].g = 255;\n\t colored_cloud.points[i].b = 255;\n\t }\n\t}\n\tpcl::io::savePLYFile(output_file, colored_cloud);\n\n\t// 输出信息\n\tstd::cout << "骨架修建和节点分类已完成,结果保存在文件:" << output_file << std::endl;\n\n\treturn 0;\n}\n\n#include\x3cpcl/visualization/pcl_visualizer.h\x3e\n\nint main() {\n\t// 加载输出文件\n\tpcl::PointCloudpcl::PointXYZRGB::Ptr colored_cloud(new pcl::PointCloudpcl::PointXYZRGB);\n\tif (pcl::io::loadPLYFilepcl::PointXYZRGB("D:\DIANYUNWENJIANJIA\gujiaxiujianhejiedianfenlei_ply.ply", *colored_cloud) == -1) {\n\t std::cerr << "Failed to load output file!" << std::endl;\n\t return -1;\n\t}\n\n\t// 创建可视化窗口\n\tpcl::visualization::PCLVisualizer viewer("Skeleton and Node Classification");\n\n\t// 设置背景颜色\n\tviewer.setBackgroundColor(0, 0, 0);\n\n\t// 设置点云颜色\n\tpcl::visualization::PointCloudColorHandlerRGBFieldpcl::PointXYZRGB rgb(colored_cloud);\n\tviewer.addPointCloudpcl::PointXYZRGB(colored_cloud, rgb, "colored_cloud");\n\n\t// 设置点云大小\n\tviewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "colored_cloud");\n\n\t// 显示点云\n\twhile (!viewer.wasStopped()) {\n\t viewer.spinOnce();\n\t}\n\n\treturn 0;\n