[done, 417.125 ms : 307200 points]
Available dimensions: x y z rgba
源点云milk_cartoon_all_small_clorox.pcd
> Loading point cloud...
> Extracting supervoxels!
Found 423 supervoxels
> Getting supervoxel adjacency
这段代码主要是使用PCL(Point Cloud Library)库来执行超体聚类(supervoxel clustering),并将结果显示在3D可视化工具中。现在我分步解释代码中的具体逻辑:
包含必要的头文件,这些文件用于点云处理和可视化。
定义使用的点云类型,例如pcl::PointXYZRGBA和pcl::PointNormal。
声明一个函数addSupervoxelConnectionsToViewer用于在视图中添加超体聚类的连接。
在main函数中,代码执行如下步骤:
a. 检查命令行参数,确保提供了点云数据文件。
b. 读取点云数据文件,将点云数据载入到PointCloudT类型的智能指针中。
c. 解析命令行参数,根据用户输入设置超体聚类的参数,如体素分辨率、种子分辨率、颜色重要性等。
d. 使用pcl::SupervoxelClustering类型创建超体聚类对象,并配置聚类参数。
e. 调用extract方法进行聚类操作,并将聚类结果存储到一个map容器中。
f. 创建一个PCLVisualizer对象用于3D数据的可视化。
g. 将超体聚类的结果添加到可视化对象中,包括体素中心点云和标记的体素云。
h. 计算超体的邻接性,并通过vtkPolyLine来创建和添加显示超体之间连接关系的可视化元素。
i. 启动可视化循环,直到用户关闭3D视图。
最后addSupervoxelConnectionsToViewer函数负责给每一对超体中心和其邻接超体中心之间添加连线,进而在3D视图中形成超体聚类的可视化图。
总结来说,这段代码是一个完整的PCL应用程序,用于执行超体聚类并可视化点云数据及其聚类结果。它可以让用户通过命令行参数来指定不同的聚类参数,并且能够显示每个聚类体素的中心,以及聚类体素之间的连接情况。
#include <pcl/console/parse.h> // 导入PCL库的console模块,用于解析命令行参数
#include <pcl/point_cloud.h> // 导入PCL库的点云处理模块
#include <pcl/point_types.h> // 导入PCL库的点类型定义
#include <pcl/io/pcd_io.h> // 导入PCL库的PCD文件输入输出模块
#include <pcl/visualization/pcl_visualizer.h> // 导入PCL库的可视化模块
#include <pcl/segmentation/supervoxel_clustering.h> // 导入PCL库的SuperVoxel聚类模块//VTK include needed for drawing graph lines
#include <vtkPolyLine.h> // 导入VTK库的PolyLine模块,用于绘制图形线条// Types
typedef pcl::PointXYZRGBA PointT; // 定义PointT为pcl::PointXYZRGBA类型
typedef pcl::PointCloud<PointT> PointCloudT; // 定义PointCloudT为PointT类型的点云
typedef pcl::PointNormal PointNT; // 定义PointNT为点的法线类型
typedef pcl::PointCloud<PointNT> PointNCloudT; // 定义PointNCloudT为PointNT类型的点云
typedef pcl::PointXYZL PointLT; // 定义PointLT为带标签的点类型
typedef pcl::PointCloud<PointLT> PointLCloudT; // 定义PointLCloudT为PointLT类型的点云void addSupervoxelConnectionsToViewer (PointT &supervoxel_center,PointCloudT &adjacent_supervoxel_centers,std::string supervoxel_name,pcl::visualization::PCLVisualizer::Ptr & viewer); // 声明函数addSupervoxelConnectionsToViewer,用于向可视化视图中添加超体连接int
main (int argc, char ** argv) // 主函数
{if (argc < 2) // 检查命令行参数数量是否小于2{pcl::console::print_error ("Syntax is: %s <pcd-file> \n ""--NT Disables the single cloud transform \n""-v <voxel resolution>\n-s <seed resolution>\n""-c <color weight> \n-z <spatial weight> \n""-n <normal_weight>\n", argv[0]); // 打印错误信息和使用说明return (1); // 返回错误代码}PointCloudT::Ptr cloud (new PointCloudT); // 创建一个PointCloudT类型的智能指针pcl::console::print_highlight ("Loading point cloud...\n"); // 打印加载点云的提示信息if (pcl::io::loadPCDFile<PointT> (argv[1], *cloud)) // 加载PCD文件{pcl::console::print_error ("Error loading cloud file!\n"); // 打印加载文件错误信息return (1); // 返回错误代码}bool disable_transform = pcl::console::find_switch (argc, argv, "--NT"); // 查找命令行参数中的`--NT`选项float voxel_resolution = 0.008f; // 设置体素分辨率的默认值bool voxel_res_specified = pcl::console::find_switch (argc, argv, "-v"); // 查找命令行参数中的`-v`选项if (voxel_res_specified) // 如果指定了体素分辨率pcl::console::parse (argc, argv, "-v", voxel_resolution); // 解析体素分辨率的值float seed_resolution = 0.1f; // 设置种子分辨率的默认值bool seed_res_specified = pcl::console::find_switch (argc, argv, "-s"); // 查找命令行参数中的`-s`选项if (seed_res_specified) // 如果指定了种子分辨率pcl::console::parse (argc, argv, "-s", seed_resolution); // 解析种子分辨率的值float color_importance = 0.2f; // 设置颜色重要性的默认值if (pcl::console::find_switch (argc, argv, "-c")) // 查找命令行参数中的`-c`选项pcl::console::parse (argc, argv, "-c", color_importance); // 解析颜色重要性的值float spatial_importance = 0.4f; // 设置空间重要性的默认值if (pcl::console::find_switch (argc, argv, "-z")) // 查找命令行参数中的`-z`选项pcl::console::parse (argc, argv, "-z", spatial_importance); // 解析空间重要性的值float normal_importance = 1.0f; // 设置法线重要性的默认值if (pcl::console::find_switch (argc, argv, "-n")) // 查找命令行参数中的`-n`选项pcl::console::parse (argc, argv, "-n", normal_importance); // 解析法线重要性的值// 以下是使用SuperVoxels的示例代码pcl::SupervoxelClustering<PointT> super (voxel_resolution, seed_resolution); // 创建一个SupervoxelClustering对象if (disable_transform) // 检查是否禁用了单一视角变换super.setUseSingleCameraTransform (false); // 禁用单一视角变换super.setInputCloud (cloud); // 设置输入的点云super.setColorImportance (color_importance); // 设置颜色重要性super.setSpatialImportance (spatial_importance); // 设置空间重要性super.setNormalImportance (normal_importance); // 设置法线重要性std::map <std::uint32_t, pcl::Supervoxel<PointT>::Ptr > supervoxel_clusters; // 创建一个map,用于存储超体聚类的结果pcl::console::print_highlight ("Extracting supervoxels!\n"); // 打印提取超体的提示信息super.extract (supervoxel_clusters); // 提取超体聚类pcl::console::print_info ("Found %d supervoxels\n", supervoxel_clusters.size ()); // 打印找到的超体数量pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer ("3D Viewer")); // 创建一个3D可视化视图viewer->setBackgroundColor (0, 0, 0); // 设置背景颜色为黑色PointCloudT::Ptr voxel_centroid_cloud = super.getVoxelCentroidCloud (); // 获取体素中心点云viewer->addPointCloud (voxel_centroid_cloud, "voxel centroids"); // 将体素中心点云添加到可视化视图中viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE,2.0, "voxel centroids"); // 设置点云的点大小viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY,0.95, "voxel centroids"); // 设置点云的透明度PointLCloudT::Ptr labeled_voxel_cloud = super.getLabeledVoxelCloud (); // 获取带标签的体素点云viewer->addPointCloud (labeled_voxel_cloud, "labeled voxels"); // 将带标签的体素点云添加到可视化视图中viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY,0.8, "labeled voxels"); // 设置点云的透明度PointNCloudT::Ptr sv_normal_cloud = super.makeSupervoxelNormalCloud (supervoxel_clusters); // 生成超体法线点云// 下面的代码行被注释掉了,如果需要查看超体法线,请取消注释//viewer->addPointCloudNormals<PointNormal> (sv_normal_cloud,1,0.05f, "supervoxel_normals");pcl::console::print_highlight ("Getting supervoxel adjacency\n"); // 打印获取超体邻接信息的提示信息std::multimap<std::uint32_t, std::uint32_t> supervoxel_adjacency; // 创建一个multimap,用于存储超体邻接信息super.getSupervoxelAdjacency (supervoxel_adjacency); // 获取超体邻接信息// 为了生成超体邻接图,需要遍历超体邻接信息的multimapfor (auto label_itr = supervoxel_adjacency.cbegin (); label_itr != supervoxel_adjacency.cend (); ) // 遍历超体邻接信息{// 首先获取标签std::uint32_t supervoxel_label = label_itr->first;// 然后获取对应标签的超体pcl::Supervoxel<PointT>::Ptr supervoxel = supervoxel_clusters.at (supervoxel_label);// 现在需要遍历邻接的超体,并且创建他们的中心点云PointCloudT adjacent_supervoxel_centers;for (auto adjacent_itr = supervoxel_adjacency.equal_range (supervoxel_label).first; adjacent_itr!=supervoxel_adjacency.equal_range (supervoxel_label).second; ++adjacent_itr) // 遍历邻接的超体{pcl::Supervoxel<PointT>::Ptr neighbor_supervoxel = supervoxel_clusters.at (adjacent_itr->second);adjacent_supervoxel_centers.push_back (neighbor_supervoxel->centroid_); // 将邻接超体的中心点添加到点云中}// 现在为这个多边形创建一个名称std::stringstream ss;ss << "supervoxel_" << supervoxel_label;// 下面的函数在本教程的范围之外,基本上它只是从给定的点生成一个“星型”多边形网格addSupervoxelConnectionsToViewer (supervoxel->centroid_, adjacent_supervoxel_centers, ss.str (), viewer); // 向可视化视图中添加超体连接// 将迭代器向前移动到下一个标签label_itr = supervoxel_adjacency.upper_bound (supervoxel_label);}while (!viewer->wasStopped ()) // 当可视化视图没有被关闭时{viewer->spinOnce (100); // 每100毫秒旋转一次可视化视图}return (0); // 正常退出
}void
addSupervoxelConnectionsToViewer (PointT &supervoxel_center,PointCloudT &adjacent_supervoxel_centers,std::string supervoxel_name,pcl::visualization::PCLVisualizer::Ptr & viewer) // addSupervoxelConnectionsToViewer函数定义
{vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New (); // 创建一个vtkPoints对象vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New (); // 创建一个vtkCellArray对象vtkSmartPointer<vtkPolyLine> polyLine = vtkSmartPointer<vtkPolyLine>::New (); // 创建一个vtkPolyLine对象// 遍历所有邻接点,添加一个中心点到邻接点对for (auto adjacent_itr = adjacent_supervoxel_centers.begin (); adjacent_itr != adjacent_supervoxel_centers.end (); ++adjacent_itr) // 遍历邻接的超体中心点{points->InsertNextPoint (supervoxel_center.data); // 插入中心点points->InsertNextPoint (adjacent_itr->data); // 插入邻接点}// 创建一个polydata来存储一切vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New ();// 将点添加到数据集中polyData->SetPoints (points);polyLine->GetPointIds ()->SetNumberOfIds(points->GetNumberOfPoints ()); // 设置polyLine的点ID数量for(unsigned int i = 0; i < points->GetNumberOfPoints (); i++)polyLine->GetPointIds ()->SetId (i,i); // 为polyLine的每个点设置IDcells->InsertNextCell (polyLine); // 将polyLine添加到cells中// 将线添加到数据集中polyData->SetLines (cells);viewer->addModelFromPolyData (polyData,supervoxel_name); // 将模型从PolyData添加到可视化视图中
}
此代码主要演示了如何使用PCL库进行点云数据的读取、处理和超体聚类分析,以及如何使用VTK库进行可视化展示。代码主要包括点云数据的加载、超体聚类参数设置、超体聚类结果提取和显示,以及超体邻接关系的可视化展示。
pcl::SupervoxelClustering<PointT>super(voxel_resolution, seed_resolution);
PointCloudT::Ptr voxel_centroid_cloud =super.getVoxelCentroidCloud();
PointLCloudT::Ptr labeled_voxel_cloud =super.getLabeledVoxelCloud();
PointNCloudT::Ptr sv_normal_cloud =super.makeSupervoxelNormalCloud(supervoxel_clusters);
super.getSupervoxelAdjacency(supervoxel_adjacency);
超体聚类(supervoxel clustering)