【PCL】教程 supervoxel_clustering执行超体聚类并可视化点云数据及其聚类结果

news2024/11/23 11:38:51

283b84ee4b86bda667354bac4dc12739.png

[done, 417.125 ms : 307200 points]
Available dimensions: x y z rgba

源点云milk_cartoon_all_small_clorox.pcd

ec9bcf1d875d53a5d2b4874aaff95fef.png

> Loading point cloud...
> Extracting supervoxels!
Found 423 supervoxels
> Getting supervoxel adjacency

这段代码主要是使用PCL(Point Cloud Library)库来执行超体聚类(supervoxel clustering),并将结果显示在3D可视化工具中。现在我分步解释代码中的具体逻辑:

  1. 包含必要的头文件,这些文件用于点云处理和可视化。

  2. 定义使用的点云类型,例如pcl::PointXYZRGBA和pcl::PointNormal

  3. 声明一个函数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); // 获取超体邻接信息
  // 为了生成超体邻接图,需要遍历超体邻接信息的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库进行可视化展示。代码主要包括点云数据的加载、超体聚类参数设置、超体聚类结果提取和显示,以及超体邻接关系的可视化展示。

pcl::SupervoxelClustering<PointT>
    super(voxel_resolution, seed_resolution);

2309011e78408db58aa7464b33cd29e6.png

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);

8c1ef5d5855e0157909c1303e8175a79.png

超体聚类(supervoxel clustering)

cf39e232637593ad4a11524c6ac48faf.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1638875.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【如此简单!数据库入门系列】之数据库设计基础--函数依赖

文章目录 问题函数依赖函数依赖的作用函数依赖的性质重新理解主键总结系列文章 问题 考虑一个在线商店数据库&#xff0c;其中包含以下表&#xff1a; 【订单表】 Order_Num(订单号)Product_ID(产品ID)Count(数量)Price(单价)110210021011003203200 你觉得这张表是否存在问…

【C++】深入理解string类

一、熟悉string类 1.1 string类的由来&#xff1a; C语音中的字符串需要我们自己管理底层空间&#xff0c;容易内存泄露。而C是面向对象语音&#xff0c;所以它把字符串封装成一个string类。 C中对于string的定义为&#xff1a;typedef basic_string string; 也就是说C中的str…

负债56亿,购买理财产品遭违约,操纵虚假粉丝,流量在下滑,客户数量减少,汽车之家面临大量风险(九)

本文由猛兽财经历时5个多月完成。猛兽财经将通过以下二十二个章节、8万字以上的内容来全面、深度的分析汽车之家这家公司。 由于篇幅限制&#xff0c;全文分为&#xff08;一&#xff09;到&#xff08;十&#xff09;篇发布。 本文为全文的第二十二章。 目录 一、汽车之家公…

Transformers:它们如何转换您的数据?

一、说明 在快速发展的人工智能和机器学习领域&#xff0c;一项创新因其对我们处理、理解和生成数据的方式产生深远影响而脱颖而出&#xff1a;Transformers。Transformer 彻底改变了自然语言处理 &#xff08;NLP&#xff09; 及其他领域&#xff0c;为当今一些最先进的 AI 应…

代码随想录-二叉树(节点)

目录 104. 二叉树的最大深度 题目描述&#xff1a; 输入输出描述&#xff1a; 思路和想法&#xff1a; 111. 二叉树的最小深度 题目描述&#xff1a; 输入输出描述&#xff1a; 思路和想法&#xff1a; 222. 完全二叉树的节点个数 题目描述&#xff1a; ​输入输出描…

关于举办《Llama3关键技术深度解析与构建Responsible AI、算法及开发落地实战》线上高级研修讲座的通知

关于举办《Llama3关键技术深度解析与构建Responsible AI、算法及开发落地实战》线上高级研修讲座的通知

Mybatis逆向工程的2种方法,一键高效快速生成Pojo、Mapper、XML,摆脱大量重复开发

一、写在开头 最近一直在更新《Java成长计划》这个专栏&#xff0c;主要是Java全流程学习的一个记录&#xff0c;目前已经更新到Java并发多线程部分&#xff0c;后续会继续更新&#xff1b;而今天准备开设一个全新的专栏 《EfficientFarm》。 EfficientFarm&#xff1a;高效农…

Tomcat PUT方法任意写文件漏洞(CVE-2017-12615)

1 漏洞原理 在Apache Tomcat服务器中&#xff0c;PUT方法通常用于上传文件。攻击者可以通过发送PUT请求&#xff0c;将恶意文件上传到服务器。 当攻击者发送PUT请求时&#xff0c;Tomcat服务器会将请求中的数据写入指定的文件。如果攻击者能够控制文件路径&#xff0c;那么他们…

Mac brew安装Redis之后更新配置文件的方法

安装命令 brew install redis 查看安装位置命令 brew list redis #查看redis安装的位置 % brew list redis /usr/local/Cellar/redis/6.2.5/.bottle/etc/ (2 files) /usr/local/Cellar/redis/6.2.5/bin/redis-benchmark /usr/local/Cellar/redis/6.2.5/bin/redis-check-ao…

跨平台桌面客户端开发框架

跨平台桌面客户端开发框架允许开发者创建能够在多个操作系统上运行的桌面应用程序。以下是一些流行的跨平台桌面客户端开发框架。这些框架各有优势&#xff0c;选择哪个框架取决于项目需求、团队的技术栈以及对特定特性的偏好。 1.Electron &#xff1a; 使用JavaScript, HTML…

Java IO流(三)

1. 字符流 1.1 什么是字符流 在Java中&#xff0c;字符流是指提供了基于字符的I/O能力的API。 Java 1.0中提供的基于字节的I/O流API只能支持8位字节流&#xff0c;无法妥善地处理16位Unicode字符。由于需要支持Unicode处理国际化字符&#xff0c;因此Java 1.1 对基础流式I/O库…

vue3+ts 原生 js drag drop 实现

vue3ts 原生 js drag drop 实现 一直以来没有涉及的一个领域就是 drag drop 拖动操作&#xff0c;研究了下&#xff0c;实现了&#xff0c;所以写个教程。 官方说明页面及实例&#xff1a;https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API 最终效果&…

SpringCloud整合Gateway结合Nacos

目录 一、引入依赖 二、开启两个测试项目 2.1 order service ​编辑 2.2 user service 三、gateway项目 3.1 新建一个bootstrap.yml文件 3.2 将我们的的网关配置写道nacos里的配置里 3.3 测试&#xff1a;看能够根据网关路由到两个测试的项目 四、 优化 4.1 将项目打包…

数据库(MySQL)—— DQL语句(聚合,分组,排序,分页)

数据库&#xff08;MySQL&#xff09;—— DQL语句&#xff08;聚合&#xff0c;分组&#xff0c;排序&#xff0c;分页&#xff09; 聚合函数常见的聚合函数语法 分组查询语法 排序查询语法 分页查询语法 DQL的执行顺序 我们今天来继续学习MySQL的DQL语句的聚合和分组查询&…

【面试经典 150 | 数组】接雨水

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;预处理方法二&#xff1a;单调栈方法三&#xff1a;双指针 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff…

【大模型学习】Transformer(学习笔记)

Transformer介绍 word2vec Word2Vec是一种用于将词语映射到连续向量空间的技术&#xff0c;它是由Google的Tomas Mikolov等人开发的。Word2Vec模型通过学习大量文本数据中的词语上下文信息&#xff0c;将每个词语表示为高维空间中的向量。在这个向量空间中&#xff0c;具有相似…

【C++】学习笔记——string_2

文章目录 六、string类2. 反向迭代器const迭代器 string类对象的容量操作&#xff08;补&#xff09;size() 3. string类的元素访问4. string类的修改 未完待续 结合文档食用~ 六、string类 2. 反向迭代器 一般来说&#xff0c;迭代器都是正向的遍历容器&#xff0c;虽然可以…

LuaJIT源码分析(三)字符串

LuaJIT源码分析&#xff08;三&#xff09;字符串 要表示一个字符串&#xff0c;核心就是需要知道字符串的长度&#xff0c;以及存放字符串具体数据的地址。lua的字符串是内化不可变的&#xff0c;也就是lua字符串变量存放的不是字符串的拷贝&#xff0c;而是字符串的引用。那么…

C语言⼆级指针如何操作字符串数组(指针数组)?

一、问题 对于字符串数组该如何操作&#xff08;⽽且是使⽤指针数组存储&#xff09;&#xff1f; 二、解答 使⽤指针的指针实现对字符串数组中字符串的输出。指向指针的指针即是指向指针数据的指针变量。这⾥创建⼀个指针数组 strings&#xff0c;它的每个数组元素相当于⼀个…

springcloud自定义全局异常

自行创建一个实体类 /*** 全局异常处理类**/ ControllerAdvice public class GlobalExceptionHandler {ExceptionHandler(Exception.class) ResponseBody public Result error(Exception e){e.printStackTrace(); return Result.fail();}/*** 自定义异常处理方法* param e * re…