[点云分割] Clustering of Pointclouds into Supervoxels

介绍

“Clustering of Pointclouds into Supervoxels” 是一种点云数据聚类的方法,用于将点云数据分割成具有相似特征的超体素(supervoxel)。

超体素是一种在点云数据中表示连续区域的方法,类似于像素在图像中表示连续区域。超体素是点云数据的小块区域,具有相似的几何特征和颜色特征。通过将点云数据聚类成超体素,可以实现对点云数据的语义分割和对象识别。

“Clustering of Pointclouds into Supervoxels” 方法的主要步骤如下:

  1. 首先,对输入的点云数据进行预处理,包括点云滤波、法线估计等操作,以获取点云的几何和颜色特征。

  2. 然后,通过选择一个种子点(seed point)开始,使用一种聚类算法(如欧几里得聚类或基于图的聚类)将点云数据分割成超体素。聚类过程中,会考虑点云的几何和颜色特征,以确保超体素内的点具有相似的特征。

  3. 聚类过程中,可以根据一些准则(如紧密度、颜色一致性等)对超体素进行合并或分割,以进一步优化聚类结果。

  4. 最后,生成的超体素可以用于点云的语义分割、对象识别等应用。可以根据超体素的特征,将点云数据划分为不同的对象或区域。

“Clustering of Pointclouds into Supervoxels” 方法在点云处理和分析中具有广泛的应用,特别是在三维场景理解、目标检测和机器人导航等领域。通过将点云数据聚类为超体素,可以提取出具有语义信息的局部区域,为后续的处理和分析提供更准确和可靠的数据基础。

效果

代码

#include <pcl/console/parse.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/segmentation/supervoxel_clustering.h>

//VTK include needed for drawing graph lines
#include <vtkPolyLine.h>

// Types
typedef pcl::PointXYZRGBA PointT;
typedef pcl::PointCloud<PointT> PointCloudT;
typedef pcl::PointNormal PointNT;
typedef pcl::PointCloud<PointNT> PointNCloudT;
typedef pcl::PointXYZL PointLT;
typedef pcl::PointCloud<PointLT> PointLCloudT;

void addSupervoxelConnectionsToViewer (PointT &supervoxel_center,
                                PointCloudT &adjacent_supervoxel_centers,
                                std::string supervoxel_name,
                                pcl::visualization::PCLVisualizer::Ptr & viewer);


int main (int argc, char ** argv)
{
    if (argc < 2)
        {
            pcl::console::print_error ("Syntax is: %s <pcd-file> \n "
                                     "--NT Dsables 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);
    pcl::console::print_highlight ("Loading point cloud...\n");
    if (pcl::io::loadPCDFile<PointT> (argv[1], *cloud))
    {
        pcl::console::print_error ("Error loading cloud file!\n");
        return (1);
    }


    bool disable_transform = pcl::console::find_switch (argc, argv, "--NT");

    float voxel_resolution = 0.008f;// 用于体素化点云数据的分辨率
    bool voxel_res_specified = pcl::console::find_switch (argc, argv, "-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");
    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"))
        pcl::console::parse (argc, argv, "-c", color_importance);

    float spatial_importance = 0.4f;
    if (pcl::console::find_switch (argc, argv, "-z"))
        pcl::console::parse (argc, argv, "-z", spatial_importance);

    float normal_importance = 1.0f;
    if (pcl::console::find_switch (argc, argv, "-n"))
        pcl::console::parse (argc, argv, "-n", normal_importance);

    //  //
    // This is how to use supervoxels
    //  //

    pcl::SupervoxelClustering<PointT> super (voxel_resolution, seed_resolution);
    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;

    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"));
    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); //获取超体素的法线点云
    //We have this disabled so graph is easy to see, uncomment to see supervoxel normals
    //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;
    super.getSupervoxelAdjacency (supervoxel_adjacency); // 获取超体素的邻接关系
    //To make a graph of the supervoxel adjacency, we need to iterate through the supervoxel adjacency multimap
    or (auto label_itr = supervoxel_adjacency.cbegin (); label_itr != supervoxel_adjacency.cend (); )
    {
        //First get the label
        std::uint32_t supervoxel_label = label_itr->first;
        //Now get the supervoxel corresponding to the label
        pcl::Supervoxel<PointT>::Ptr supervoxel = supervoxel_clusters.at (supervoxel_label);

        //Now we need to iterate through the adjacent supervoxels and make a point cloud of them
        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_);
            }
        //Now we make a name for this polygon
            std::stringstream ss;
        ss << "supervoxel_" << supervoxel_label;
        //This function is shown below, but is beyond the scope of this tutorial - basically it just generates a "star" polygon mesh from the points given
            addSupervoxelConnectionsToViewer (supervoxel->centroid_, adjacent_supervoxel_centers, ss.str (), viewer);
        //Move iterator forward to next label
        label_itr = supervoxel_adjacency.upper_bound (supervoxel_label);
        }

        while (!viewer->wasStopped ())
        {
         viewer->spinOnce (100);
        }
    return (0);
    }

   void addSupervoxelConnectionsToViewer (PointT &supervoxel_center,
                                        PointCloudT &adjacent_supervoxel_centers,
                                        std::string supervoxel_name,
                                        pcl::visualization::PCLVisualizer::Ptr & viewer)
   {
    vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New ();
    vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New ();
    vtkSmartPointer<vtkPolyLine> polyLine = vtkSmartPointer<vtkPolyLine>::New ();

    //Iterate through all adjacent points, and add a center point to adjacent point pair
        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);
        }
    // Create a polydata to store everything in
        vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New ();
    // Add the points to the dataset
        polyData->SetPoints (points);
    polyLine->GetPointIds  ()->SetNumberOfIds(points->GetNumberOfPoints ());
    for(unsigned int i = 0; i < points->GetNumberOfPoints (); i++)
        polyLine->GetPointIds ()->SetId (i,i);
    cells->InsertNextCell (polyLine);
    // Add the lines to the dataset
        polyData->SetLines (cells);
    viewer->addModelFromPolyData (polyData,supervoxel_name);
    }

 

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

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

相关文章

vue + docxtemplater 导出 word 文档

一、痛点 word 导出 这种功能其实之前都是后端实现的&#xff0c;但最近有个项目没得后端。所以研究下前端导出。 ps&#xff1a; 前端还可以导出 pdf&#xff0c;但是其分页问题需要话精力去计算才可能实现&#xff0c;并且都不是很完善。可参考之前的文章&#xff1a;利用 h…

Peter算法小课堂—前缀和数组的应用

桶 相当于计数排序&#xff0c;看一个视频 桶排序 太戈编程1620题 算法解析 #include <bits/stdc.h> using namespace std; const int R11; int cnt[R];//cnt[t]代表第t天新增几人 int s[R];//s[]数组是cnt[]数组的前缀和数组 int n,t; int main(){cin>>n;for(…

意图交易:为用户思考,而不是让用户思考

意图叙事 在前不久&#xff0c;知名加密投资机构 Paradigm 的 CTO 、研究员 Georgios Konstantopoulos 曾在推特上对现有 ChainAsset 模式的糟糕且割裂的体验进行了吐槽&#xff0c;这也道出了很多链上用户的痛点。同时他也认为现有加密基建设施需要为用户思考&#xff0c;而不…

Nginx:简介、安装与部署

一、Nginx简介 Nginx是一个很好的高性能Web和反向大力服务器&#xff0c;它具有很多非常优越的特性&#xff1a;在高连接并发的情况下&#xff0c;Nginx是Apahe服务器的不错的替代品&#xff1a;Nginx在美国是虚拟主机生意选择的软件平台之一。能够支持50000个并发连接数的响应…

若依vue-修改标题和图标

因为我们拉下来的代码,图标和logo是若依的,这和我们需要做出来的效果有差别 这个时候就需要去对应的文件内去修改标题和图标 (主要就是这两个地方的图标和标题) 修改菜单里面的logo以及文字 修改文字 位置: src/layout/component/Sidebar/Logo.vue 此处的title文字是定义在…

plantUML学习与实战

背景 在日常工作或者生活中&#xff0c;使用交互图来描述想法&#xff0c;往往相对于文字来说&#xff0c;可读性更高&#xff0c;同时一定程度上可以提高沟通效率&#xff0c;但是苦于&#xff0c;不想对一堆控件拖拖拉拉&#xff0c;本人就是一个很讨厌画图&#xff0c;但是…

谈思生物医疗直播 | 利用类器官模型研究肺的发育与稳态

类器官是一种三维细胞培养物&#xff0c;其在细胞类型&#xff0c;空间结构及生理功能上能够模拟对应器官&#xff0c;从而提供一个高度生理相关的系统。自2009年小肠类器官首次建立至今&#xff0c;类器官研究已经延伸到多个组织系统&#xff0c;并成为当下生命科学领域最热门…

改善钢棒直线度检测可靠性 在线直线度测量仪替代人工检测

根据GB/T908-2019标准规定&#xff0c;钢棒的尺寸包括直径或边长、长度、弯曲度等。因此钢棒在生产中进行尺寸检测&#xff0c;保证成品符合规格&#xff0c;是降低废品率的重要一环。 有些钢棒的弯曲很明显&#xff0c;肉眼可看&#xff0c;但更有很多不明显的需要借助工具检测…

亿级流量架构服务降级

什么是服务降级 如果看过我前面对服务限流的分析,理解服务降级就很容易了,对于一个景区,平时随便进出,但是一到春节或者十一国庆这种情况客流量激增,那么景区会限制同时进去的人数,这叫限流,那么什么是服务降级呢? 简单来说就是,将一些不太重要的景区项目砍掉,平时就那么三五…

[PTQ]均匀量化和非均匀量化

均匀量化和非均匀量化 基本概念 量化出发点&#xff1a;使用整型数据类型代替浮点数据&#xff0c;从而节省存储空间同时加快推理速度。量化基本形式 均匀量化&#xff1a;浮点线性映射到定点整型上&#xff0c;可以根据scale/offset完成量化/反量化操作。非均匀量化 PowersO…

CentOS 7 使用cJSON 库

什么是JSON JSON是一种轻量级的数据交换格式&#xff0c;可读性强、编写简单。键值对组合编写规则&#xff0c;键名使用双引号包裹&#xff0c;冒号&#xff1a;分隔符后面紧跟着数值&#xff0c;有两种常用的数据类型是对象和数组。 对象&#xff1a;使用花括号{}包裹起来的…

怎么用 AI 来智能审核 PDF合同?5步搞定!

大家都知道审合同是一个比较耗费精力的过程,有没有更好的办法来智能审核PDF合同呢,今天就教大家一招,用AI来智能审核PDF合同。 在开始之前呢,我们要找到一款带AI功能的工具,我试用过擎盾智能合同审查、幂律智能等工具,感觉都不太理想,经过一段时间的摸索,我找到了一款比较适合…

【Linux】关系运算符、shell判断脚本执行时是否有传参、判断文件/文件夹是否存在、判断字符串是否相等、判断上个命令执行是否正常、判断字符串是否为空

&#x1f984; 个人主页——&#x1f390;个人主页 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341; 感谢点赞和关注 &#xff0c;每天进步一点点&#xff01;加油&#xff01;&…

无损压缩技巧:减小PDF文件尺寸的有效方法

我们在制作pdf文档的时候&#xff0c;会加入许多内容&#xff0c;文字、图片等等&#xff0c;素材添加的过多之后就会导致pdf文档特别大&#xff0c;在上传或者储存时&#xff0c;就会特别不方便&#xff0c;所以今天就告诉大家一个pdf压缩的方法&#xff0c;使用pdf在线压缩工…

【C++】:STL中的string类的增删查改的底层模拟实现

本篇博客仅仅实现存储字符(串)的string 同时由于Cstring库设计的不合理&#xff0c;我仅实现一些最常见的增删查改接口 接下来给出的接口都是基于以下框架&#xff1a; private:char* _str;//思考如何不用constsize_t _size;size_t _capacity;//这样写可以const static size_t…

csdn最新最全的Selenium教程:定位frame框架中的元素

定位frame框架中的元素 在web应用中经常会出现frame嵌套的应用&#xff0c;假设页面上有A,B两个frame,其中B在A内&#xff0c;那么定位B中的内容则需要先到A&#xff0c;再到B。 switch_to.frame方法可以把当前定位的主题切换到frame里&#xff0c;在frame里实际是嵌套了另外一…

Android Studio xml文件id爆红但是项目可以运行

这种原因是你的R文件太大了&#xff08;超过了Android Studio的上限25.6M了&#xff09; 解决办法如下&#xff1a; Help -> Edit Custom Properties -> create custom properties?(yes) ->添加 idea.max.intellisense.filesize5000 最后需要重启Android Studio

【double check 读写锁】

使用double check 读写锁 读多写少场景 记录下 //来源 jdbc 中的查询连接信息 //public abstract class ConnectionUrl implements DatabaseUrlContainer public static ConnectionUrl getConnectionUrlInstance(String connString, Properties info) {if (connString null…

算法刷题-动态规划2(继续)

算法刷题-动态规划2 珠宝的最高价值下降路径最小和 珠宝的最高价值 题目 大佬思路 多开一行使得代码更加的简洁 移动到右侧和下侧 dp[ i ][ j ]有两种情况&#xff1a; 第一种是从上面来的礼物最大价值&#xff1a;dp[ i ][ j ] dp[ i - 1 ][ j ] g[ i ][ j ] 第二种是从左…

【MySQL】宝塔面板结合内网穿透实现公网远程访问

文章目录 前言1.Mysql服务安装2.创建数据库3.安装cpolar3.2 创建HTTP隧道4.远程连接5.固定TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 宝塔面板的简易操作性,使得运维难度降低,简化了Linux命令行进行繁琐的配置,下面简单几步,通过宝塔面板cpo…
最新文章