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

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.mfbz.cn/a/588668.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux进程——进程的创建(fork的原理)

前言&#xff1a;在上一篇文章中&#xff0c;我们已经会使用getpid/getppid函数来查看pid和ppid,本篇文章会介绍第二种查看进程的方法&#xff0c;以及如何创建子进程&#xff01; 本篇主要内容&#xff1a; 查看进程的第二种方法创建子进程系统调用函数fork 在开始前&#xff…

【华为】路由综合实验(基础)

【华为】路由综合实验 实验需求拓扑配置AR1AR2AR3AR4AR5PC1PC2 查看通信OSPF邻居OSPF路由表 BGPBGP邻居BGP 路由表 配置文档 实验需求 ① 自行规划IP地址 ② 在区域1里面 启用OSPF ③ 在区域1和区域2 启用BGP&#xff0c;使AR4和AR3成为eBGP&#xff0c;AR4和AR5成为iBGP对等体…

buuctf-misc-22.神秘龙卷风1

22.神秘龙卷风1 题目&#xff1a;暴力破解-翻译Brainfuck计算机语言 根据提示是4位密码&#xff0c;直接破解密码即可 解压后发现是这样一个文档 我们尝试使用网站翻译这个 内容由“”、“.”、“>”三种符号组成&#xff0c;我刚开始认为这是一种密文&#xff0c;经过搜索…

thinkpad电脑文件隐藏了怎么恢复?教你几招

在使用ThinkPad电脑时&#xff0c;有时我们可能会发现一些文件或文件夹突然“消失”了&#xff0c;这通常是因为它们被隐藏了。本文将为您介绍几招恢复ThinkPad电脑上隐藏文件的方法&#xff0c;帮助您轻松找回丢失的文件。 图片来源于网络&#xff0c;如有侵权请告知 一、了解…

【实时数仓架构】方法论

笔者不是专业的实时数仓架构&#xff0c;这是笔者从其他人经验和网上资料整理而来&#xff0c;仅供参考。写此文章意义&#xff0c;加深对实时数仓理解。 一、实时数仓架构技术演进 1.1 四种架构演进 1&#xff09;离线大数据架构 一种批处理离线数据分析架构&#xff0c;…

when to create a ViewRootImpl

when to create a ViewRootImpl when method setView is called: when method dispatchDetachedFromWindow is called:

预训练模型介绍

一、什么是GPT GPT 是由人工智能研究实验室 OpenAI 在2022年11月30日发布的全新聊天机器人模型, 一款人工智能技术驱动的自然语言处理工具 它能够通过学习和理解人类的语言来进行对话, 还能根据聊天的上下文进行互动,能完成撰写邮件、视频脚本、文案、翻译、代码等任务 二、 为…

TypeScript学习笔记:迈向更安全的JavaScript编程

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Linux专栏05:Linux基本指令之目录处理指令

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Linux专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Linux基本指令之目录处理指令 编号&#xff1a;05 文章目录 Linux基…

STM32之HAL开发——电容按键

电容按键原理 电容器 (简称为电容) 就是可以容纳电荷的器件&#xff0c;两个金属块中间隔一层绝缘体就可以构成一个最简单的电容。如图 32_1 (俯视图)&#xff0c;有两个金属片&#xff0c;之间有一个绝缘介质&#xff0c;这样就构成了一个电容。这样一个电容在电路板上非常容…

线程同步与条件变量

再论生产消费者问题 问题 如果缓冲池为空&#xff0c;如何定义消费者的行为? 一种可能的解决方案 这种方案是可行的&#xff0c;但是如果生产者一直不生产&#xff0c;那么消费者会反复查看产品的数量为 0 并休眠&#xff0c;这样会浪费 cpu 的资源&#xff0c;并且生产者生产…

MWCNTs微纳米纤维膜的制备

MWCNTs微纳米纤维膜是一种由多壁碳纳米管&#xff08;MWCNTs&#xff09;与聚合物纤维复合而成的纳米纤维膜。这种材料结合了MWCNTs的良好性能和纳米纤维膜的高比表面积、高通量等特点&#xff0c;具有广泛的应用前景。 在制备过程中&#xff0c;首先需要对MWCNTs进行酸化处理和…

基于SpringBoot的私人健身与教练预约管理系统设计与实现

一、引言 私人健身与教练预约管理系统&#xff0c;可以摆脱传统手写记录的管理模式。利用计算机系统&#xff0c;进行用户信息、管理员信息的管理&#xff0c;其中包含首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;教练管理&#xff0c;健身项目管理&#xff0c;项…

Agent AI智能体:如何借助机器学习引领科技新潮流

文章目录 &#x1f4d1;前言一、Agent AI智能体的基本概念二、Agent AI智能体的技术进步2.1 机器学习技术2.2 自适应技术2.3 分布式计算与云计算 三、Agent AI智能体的知识积累3.1 知识图谱3.2 迁移学习 四、Agent AI智能体的挑战与机遇4.1 挑战4.2 机遇 小结 &#x1f4d1;前言…

Linux下安装snaphu

1、官网下载安装包 2、解压&#xff0c;移动文件夹到/usr/local/下 3、在/usr/local/下创建man&#xff0c;在man下创建man1文件夹 4、进入到snaphu的src文件夹里&#xff0c;执行sudo make&#xff0c;如果报错 在这个 Makefile 中&#xff0c;-arch x86_64 是 macOS 特定的…

小区服务|基于SprinBoot+vue的小区服务管理系统(源码+数据库+文档)

目录 基于SprinBootvue的小区服务管理系统 一、前言 二、系统设计 三、系统功能设计 1管理员登录 2 客服聊天管理、反馈管理管理 3 公告信息管理 4公告类型管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博…

图论之最短路算法模板总结

来个大致的分类&#xff1a; 朴素的迪杰斯特拉&#xff1a; 实现&#xff1a; 我们让s表示当前已经确定的最短距离的点&#xff0c;我们找到一个不在s中的距离最近的点t&#xff0c;并用t来更新其他的点。 下面是AC代码&#xff1a; #include<bits/stdc.h> using nam…

《Spring-MVC》系列文章目录

简介 Spring MVC是一种基于Java的实现MVC设计模式的请求驱动类型的轻量级Web框架&#xff0c;它通过把Model&#xff08;模型&#xff09;、View&#xff08;视图&#xff09;、Controller&#xff08;控制器&#xff09;分离&#xff0c;将web层进行职责解耦&#xff0c;把复杂…

Getting started - 英文版 - English Version

&#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace This pa…

在不同操作系统上自动生成Protocol Buffers的Java语言包的方法

各语言的Protocol Buffers文件都需要通过protoc来生成&#xff0c;这个动作往往需要手动输入命令完成。本文介绍的方法&#xff0c;将借助Maven来实现自动化生成工作。这样开发者只要专注于proto的定义&#xff0c;且不用将生成的文件上传到代码仓库&#xff0c;从而降低开发的…
最新文章