bash
[done, 417.125 ms : 307200 points]
Available dimensions: x y z rgba
源点云milk_cartoon_all_small_clorox.pcd
shell
> 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应用程序,用于执行超体聚类并可视化点云数据及其聚类结果。它可以让用户通过命令行参数来指定不同的聚类参数,并且能够显示每个聚类体素的中心,以及聚类体素之间的连接情况。
php
#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); // 获取超体邻接信息
// 为了生成超体邻接图,需要遍历超体邻接信息的multimap
for (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的每个点设置ID
cells->InsertNextCell (polyLine); // 将polyLine添加到cells中
// 将线添加到数据集中
polyData->SetLines (cells);
viewer->addModelFromPolyData (polyData,supervoxel_name); // 将模型从PolyData添加到可视化视图中
}
此代码主要演示了如何使用PCL库进行点云数据的读取、处理和超体聚类分析,以及如何使用VTK库进行可视化展示。代码主要包括点云数据的加载、超体聚类参数设置、超体聚类结果提取和显示,以及超体邻接关系的可视化展示。
ruby
pcl::SupervoxelClustering<PointT>
super(voxel_resolution, seed_resolution);
ruby
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)