[点云分割] Clustering of Pointclouds into Supervoxels

news2024/11/15 11:36:15

介绍

“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.coloradmin.cn/o/1244025.html

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

相关文章

SPASS-信度分析

信度分析概述 效度 效度指的是量表是否真正反映了我们希望测量的东西。一般来说&#xff0c;有4种类型的效度&#xff1a;内容效度、标准效度、结构效度和区分效度。内容效度是一种基于概念的评价指标&#xff0c;其他三种效度是基于经验的评价指标。如果一个量表实际上是有效…

练习七-在Verilog中使用任务task

在Verilog中使用任务task 1&#xff0c;任务目的2&#xff0c;RTL代码&#xff0c;交换3&#xff0c;测试代码4&#xff0c;波形显示 1&#xff0c;任务目的 &#xff08;1&#xff09;掌握任务在verilog模块设计中的应用&#xff1b; &#xff08;2&#xff09;学会在电平敏感…

使用pt-query-digest分析慢查询日志

介绍 pt-query-digest 属于 Percona Toolkit 工具集中较为常用的工具&#xff0c;用于分析 slow log&#xff0c;可以分析 MySQL 数据库的 binary log 、 general log 日志&#xff0c;同时也可以使用 show processlist 或从 tcpdump 抓取的 MySQL 协议数据来进行分析。 安装…

人工智能教程(一):基础知识

目录 前言 什么是人工智能&#xff1f; 教学环境搭建 向量和矩阵 前言 如果你是关注计算机领域最新趋势的学生或从业者&#xff0c;你应该听说过人工智能、数据科学、机器学习、深度学习等术语。作为人工智能系列文章的第一篇&#xff0c;本文将解释这些术语&#xff0c;并搭…

Python实现交易策略评价指标-收益率

1.收益率的定义 收益率几乎是所有投资者都会关注的一个指标&#xff0c;收益率的高低决定了投资策略的赚钱能力&#xff0c;常见关于收益率的指标如下&#xff1a; 持有期收益率 持有期收益率 期末投资权益 − 期初投资权益 期初投资权益 持有期收益率 \frac {期末投资权益…

王道p149 9.设树B是一棵采用链式结构存储的二叉树,编写一个把树 B中所有结点的左、右子树进行交换的函数。(c语言代码实现)

本题代码如下 void swap(tree* t) {if (*t){treenode* temp (*t)->lchild;(*t)->lchild (*t)->rchild;(*t)->rchild temp;swap(&(*t)->lchild);swap(&(*t)->rchild);} } 完整测试代码 #include<stdio.h> #include<stdlib.h> typed…

C++每日选择题—Day1

第一题 以下C代码会输出什么? #include <iostream> using namespace std; class A { public:A() {}~A() {} private:static int a; }; int main() {cout << sizeof(A) << endl;return 0; } A&#xff1a;0 B&#xff1a;1 C&#xff1a;4 D&#xff1a;8 答…

视频网关简介

在数字化时代&#xff0c;视频通信已经成为了人们日常生活和工作中的重要部分。为了满足不同设备和平台之间的视频通信需求&#xff0c;各种视频协议应运而生。然而&#xff0c;这些协议之间的差异使得相互通信变得复杂。因此&#xff0c;视频网关作为一种重要的网络设备&#…

初识Java 18-3 泛型

目录 边界 通配符 编译器的能力范畴 逆变性 无界通配符 捕获转换 本笔记参考自&#xff1a; 《On Java 中文版》 边界 在泛型中&#xff0c;边界的作用是&#xff1a;在参数类型上增加限制。这么做可以强制执行应用泛型的类型规则&#xff0c;但还有一个更重要的潜在效果…

IntelliJ IDEA 16创建Web项目

首先要理解一个概念&#xff1a;在IntelliJ IDEA中“new Project”相当于eclipse中的工作空间&#xff08;Workspace&#xff09;&#xff0c;而“new Module”相当于eclipse中的工程&#xff08;Project&#xff09;。以下均采用Intellij的说法&#xff0c;请自行对照转换理解…

Python---把函数的返回值作为另外一个函数的参数

def test1():return 50def test2(num):print(num)# 1. 保存函数test1的返回值 result test1()# 2.将函数返回值所在变量作为参数传递到test2函数 test2(result) # 50

PLC-Recorder文件存储设置的一些注意事项和技巧

存储是PLC-Recorder高速采集软件的三大基本功能之一&#xff08;另外两个是“采集”和“使用”&#xff09;。与内存访问相比&#xff0c;磁盘访问是一个很慢的过程&#xff0c;频繁的读写操作或多或少地会对采集造成影响&#xff0c;因此&#xff0c;也有一些可遵循的规则。 …

JavaScript编程基础 – 布尔值(Booleans)

JavaScript编程基础 – 布尔值(Booleans) Javascript Programming Essentials – Booleans 一个JavaScript布尔值包含两个值中的一个&#xff0c;即 true 或者 false。 本文简要介绍JavaScript布尔值的具体应用&#xff0c;以及可能作为对象的布尔值等。 1. 布尔值(Booleans)…

Claude 发布2.1 版本,重大升级更新来看看有什么新功能?

11 月 23 日消息&#xff0c;OpenAI 竞争对手 Anthropic 日前推出了 Claude 2.1 聊天机器人及对应同名 AI 模型Claude 2.1&#xff0c;本文将总结Claude 2.1的主要功能。 增强的处理能力 上下文处理量大幅提升&#xff1a;Claude 2.1 现在能处理高达 200K上下文标记&#xff…

AdaBoost提升分类器性能

目录 AdaBoost算法原理 AdaBoost工作详情 初始权重分配 第一轮 第二轮 后续轮次 最终模型 AdaBoost的API解释 AdaBoost 对房价进行预测 AdaBoost 与决策树模型的比较 结论 AdaBoost算法原理 在数据挖掘中&#xff0c;分类算法可以说是核心算法&#xff0c;其中 Ada…

计算机毕业设计 基于Hadoop的物品租赁系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

HTTP客户端警告:Going to buffer response body of large or unknown size

HTTP客户端警告&#xff1a;Going to buffer response body of large or unknown size 点关注不迷路&#xff0c;欢迎再访&#xff01; 精简博客内容&#xff0c;尽量已行业术语来分享。 努力做到对每一位认可自己的读者负责。 帮助别人的同时更是丰富自己的良机。 目录 HTTP客…

Unity机器学习 ML-Agents第一个例子

上一节我们安装了机器学习mlagents的开发环境&#xff0c;本节我们创建第一个例子&#xff0c;了解什么是机器学习。 我们的例子很简单&#xff0c;就是让机器人自主移动到目标位置&#xff0c;不能移动到地板范围外。 首先我们来简单的了解以下机器学习的过程。 机器学习的过…

EventLog Analyzer:强大的日志管理与分析工具

随着企业网络规模的扩大和信息系统的复杂化&#xff0c;安全日志管理和分析成为了至关重要的一环。在这个背景下&#xff0c;EventLog Analyzer崭露头角&#xff0c;成为一款备受推崇的日志管理与分析工具。本文将介绍EventLog Analyzer的主要特点、功能以及为企业带来的实际价…

github批量仓库克隆,git clone某个用户的所有仓库

利用github的api工具&#xff0c; 首先拿到用户名为kevin的所有仓库的url&#xff1a; curl "https://api.github.com/users/kevin/repos?per_page100&&page1" | grep -w clone_url >clone.txt过滤一下&#xff1a; grep -o https://[^"]* clone…