PCL点云骨架提取和节点分类:基于Y坐标的实现
#include<iostream>\n#include<pcl/io/ply_io.h>\n#include<pcl/point_types.h>\n#include<pcl/features/normal_3d.h>\n#include<pcl/surface/mls.h>\n#include<pcl/kdtree/kdtree_flann.h>\n#include<pcl/visualization/pcl_visualizer.h>\n\nint\ main()\ {\n\t// 输入文件路径\n\tstd::string\ input_file\ =\ "D:\DIANYUNWENJIANJIA:\kruskal_ply.ply";\n\n\t// 加载点云数据\n\tpcl::PointCloud<pcl::PointXYZ>::Ptr\ cloud(new\ pcl::PointCloud<pcl::PointXYZ>);\n\tif(pcl::io::loadPLYFile(input_file,\ *cloud)\ ==\ -1)\ {\n\t\tstd::cerr\ <<\ "Failed\ to\ load\ input\ file!"\ <<\ std::endl;\n\t\treturn\ -1;\n\t}\n\n\t// 手动计算法线\n\tpcl::PointCloud<pcl::Normal>::Ptr\ normals(new\ pcl::PointCloud<pcl::Normal>);\n\tpcl::search::KdTree<pcl::PointXYZ>::Ptr\ tree(new\ pcl::search::KdTree<pcl::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\tpcl::Normal\ normal;\n\t\tstd::vector<int>\ k_indices(k);\n\t\tstd::vector<float>\ k_distances(k);\n\t\ttree->nearestKSearch(cloud->points[i],\ k,\ k_indices,\ k_distances);\n\n\t\t// 计算协方差矩阵\n\t\tEigen::Matrix3f\ covariance_matrix;\n\t\tEigen::Vector4f\ centroid;\n\t\tpcl::computeMeanAndCovarianceMatrix(*cloud,\ k_indices,\ covariance_matrix,\ centroid);\n\n\t\t// 使用特征值分解计算法线\n\t\tEigen::SelfAdjointEigenSolver<Eigen::Matrix3f>\ eigen_solver(covariance_matrix,\ Eigen::ComputeEigenvectors);\n\t\tEigen::Vector3f\ normal_vector\ =\ eigen_solver.eigenvectors().col(0);\n\n\t\tnormal.normal_x\ =\ normal_vector[0];\n\t\tnormal.normal_y\ =\ normal_vector[1];\n\t\tnormal.normal_z\ =\ normal_vector[2];\n\t\tnormals->push_back(normal);\n\t}\n\n\t// 阈值α\n\tfloat\ alpha\ =\ 3.0;\n\n\t// 骨架修减和节点分类\n\tpcl::PointCloud<pcl::PointXYZ>::Ptr\ skeleton(new\ pcl::PointCloud<pcl::PointXYZ>);\n\tstd::vector<int>\ labels(cloud->size(),\ -1);\n\tfor(size_t\ i\ =\ 0;\ i\ <\ cloud->size();\ i++)\ {\n\t\tint\ neighbor_count\ =\ 0;\n\t\tstd::vector<int>\ k_indices(5);\n\t\tstd::vector<float>\ k_distances(5);\n\t\ttree->nearestKSearch(cloud->points[i],\ 5,\ k_indices,\ k_distances);\n\n\t\tfor(int\ j\ =\ 0;\ j\ <\ k_indices.size();\ j++)\ {\n\t\t\tint\ neighbor_index\ =\ k_indices[j];\n\t\t\tif(cloud->points[i].y\ <\ cloud->points[neighbor_index].y)\ {\n\t\t\t\tneighbor_count++;\n\t\t\t}\n\t\t}\n\n\t\tif(neighbor_count\ <\ alpha)\ {\n\t\t\tlabels[i]\ =\ 3;\ // 丢弃的分支\n\t\t}\n\t\telse\ if(neighbor_count\ ==\ 1)\ {\n\t\t\tlabels[i]\ =\ 0;\ // 叶尖\n\t\t}\n\t\telse\ if(neighbor_count\ ==\ 2)\ {\n\t\t\tlabels[i]\ =\ 1;\ // 内部节点\n\t\t}\n\t\telse\ if(neighbor_count\ >=\ 3)\ {\n\t\t\tlabels[i]\ =\ 2;\ // 结点\n\t\t\tskeleton->push_back(cloud->points[i]);\n\t\t}\n\t}\n\n\t// 保存输出点云数据\n\tstd::string\ output_file\ =\ "D:\DIANYUNWENJIANJIA:\gujiaxiujianhejiedianfenlei_ply.ply";\n\tpcl::PointCloud<pcl::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\tcolored_cloud.points[i].x\ =\ cloud->points[i].x;\n\t\tcolored_cloud.points[i].y\ =\ cloud->points[i].y;\n\t\tcolored_cloud.points[i].z\ =\ cloud->points[i].z;\n\t\tif(labels[i]\ ==\ 0)\ {\n\t\t\tcolored_cloud.points[i].r\ =\ 255;\n\t\t\tcolored_cloud.points[i].g\ =\ 0;\n\t\t\tcolored_cloud.points[i].b\ =\ 0;\n\t\t}\n\t\telse\ if(labels[i]\ ==\ 1)\ {\n\t\t\tcolored_cloud.points[i].r\ =\ 0;\n\t\t\tcolored_cloud.points[i].g\ =\ 255;\n\t\t\tcolored_cloud.points[i].b\ =\ 0;\n\t\t}\n\t\telse\ if(labels[i]\ ==\ 2)\ {\n\t\t\tcolored_cloud.points[i].r\ =\ 0;\n\t\t\tcolored_cloud.points[i].g\ =\ 0;\n\t\t\tcolored_cloud.points[i].b\ =\ 255;\n\t\t}\n\t\telse\ if(labels[i]\ ==\ 3)\ {\n\t\t\tcolored_cloud.points[i].r\ =\ 255;\n\t\t\tcolored_cloud.points[i].g\ =\ 255;\n\t\t\tcolored_cloud.points[i].b\ =\ 255;\n\t\t}\n\t}\n\tpcl::io::savePLYFile(output_file,\ colored_cloud);\n\n\t// 可视化点云数据\n\tpcl::visualization::PCLVisualizer\ viewer("Point\ Cloud\ Viewer");\n\tviewer.setBackgroundColor(0,\ 0,\ 0);\n\tviewer.addPointCloud<pcl::PointXYZRGB>(colored_cloud.makeShared(),\ "colored_cloud");\n\tviewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,\ 1,\ "colored_cloud");\n\tviewer.spin();\n\n\t// 输出信息\n\tstd::cout\ <<\ "骨架修减和节点分类已完成,结果保存在文件:"\ <<\ output_file\ <<\ std::endl;\n\n\treturn\ 0;\n}\n
原文地址: http://www.cveoy.top/t/topic/pFoB 著作权归作者所有。请勿转载和采集!