点云降采样

1 概述

三维点云往往包含大量冗余数据,直接处理计算量大,消耗时间长,因此对其进行降采样是十分必要的。降采样同时也是点云预处理过程中的关键环节。

2 常用方法

2.1 体素网格下采样

2.1.1 原理

体素(Voxel):将三维空间划分成一个个立体的方格,每个方格就叫一个体素。

在每个体素中可能存在几个点,也可能没有点。降采样的思路为:检查每个体素中是否有点存在,若有,则用一个点代替体素内的点集,通常,这个采样点可以是体素中所有点坐标的平均值(质心),也可以是中心点或者离中心点最近的点。

2.1.2 流程

  1. 计算点云的包围盒,将包围盒离散成小体素。体素的长宽高尺寸可以通过用户设定,也可以指定三个方向上的体素个数;
  2. 获取落在每个体素中的点集,在每个体素中取一个采样点代替原来的点集。

2.1.3 特点

  • 效率高
  • 采样点分布比较均匀
  • 可以通过控制体素大小间接控制采样点的距离(采样后点云的稀疏程度)
  • 采集到的点云数量不可控

2.2 均匀下采样

2.2.1 原理

均匀下采样有多种不同的采样方式。

类似体素网格采样,同样需要将点云空间划分,不同的是,在均匀采样中是以半径为r的球体。选取距离球体中心最近的点作为采样点替代落在球体中的点集,此时,采样点的坐标为源点云中一点的坐标,不同于体素下采样中使用质心进行替代而产生新的点坐标。可以修改球体半径r,实现对采样点云稀疏程度的控制。

常用三维点云采样方法总结 - 知乎 (zhihu.com)

均匀采样是指每隔固定的点数采样一次。样本按点的顺序执行,始终选择从第 1 个点开始,而不是随机选择。显然点存储的顺序不同,得到的结果也会不一样。从这个角度来看,这种方法比较适合有序点云的降采样。这种方法适合均匀采集到的点云,如果点云本身不均匀,那么以固定点数采样很有可能造成某一部分的点云没被采样到。相比于体素的采样方法,点云均匀采样后的点数是固定可控的,而体素采样后的点云数量是不可控的。

三种点云下采样方法(二)— open3d python_Coding的叶子的博客-CSDN博客_点云下采样

最远点采样是较为简单的一种,首先需要选取一个种子点,并设置一个内点集合,每次从点云中不属于内点的集合找出一点距离内点最远的点,如下图,这里的距离计算方式为该点至内点所有点的最小距离。这种方式的下采样点云分布均匀,但是算法复杂度较高效率低。

Python点云数据处理(四)点云下采样 - 知乎 (zhihu.com)

2.2.2 特点

  • 分布很均匀
  • 不会移动源点云,准确度较高
  • 时间复杂度偏高。可以采用分治的方法提高效率

2.3 几何采样(曲率下采样)

2.3.1 原理

以点云的几何特征作为采样依据,以曲率为例。在点云中任意一点都存在某曲面,曲率示意图如下所示(密切圆半径r的倒数为曲率),曲率越大,弧的弯曲程度越大,表示该地方的特征点越多,故在点云曲率越大的地方,采样点数越多。

2.3.2 流程

1)首先计算每个点的K领域,然后计算点到领域点的法线夹角值,以此来近似达到曲率的效果并提高计算效率,因为曲率越大的地方,夹角值越大。

2)设置一个角度阈值,当点的领域夹角值大于阈值时被认为是特征明显的区域,其余区域为不明显区域。

3)对明显和不明显区域进行均匀采样,采样数分别为U(1−V)U(1-V)U(1−V)和$UV $, $ U$是目标采样数,V是均匀采样性。

2.3.3特点

  • 几何特征越明显的区域,采样个数分布越多(曲率越大,采样点数越多)
  • 效率高
  • 采样点局部均匀分布
  • 稳定性高:通过几何特征区域的划分,使得采样结果抗噪性更强

2.4 随机下采样

原理简单,顾名思义,指定采样点个数,进行随机点去除进行采样操作。

2.4.1 特点

  • 能控制采样点个数
  • 随机性太强

3 PCL 下采样实践

3.1 体素网格下采样

在PCL库中,我们可以使用pcl::VoxelGrid<pcl::PointXYZ>将空间点云体素化,得到对应的体素网格,再进行体素下采样。

关键代码:

pcl::VoxelGrid<pcl::PointXYZ> sor;     // 体素化网格
sor.setInputCloud(cloud);
sor.setLeafSize(0.01f, 0.01f, 0.01f);   // 设置体素栅格的大小为 1x1x1cm
sor.filter(*cloud_filtered);

测试代码如下:

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/filters/statistical_outlier_removal.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/visualization/pcl_visualizer.h>int main(int argc, char** argv)
{//pcl::PCLPointCloud2::Ptr cloud(new pcl::PCLPointCloud2());pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);//pcl::PCLPointCloud2::Ptr cloud_filtered(new pcl::PCLPointCloud2());pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);// Fill in the cloud datapcl::PCDReader reader;// Replace the path below with the path where you saved your filereader.read("table_scene_lms400.pcd", *cloud); // Remember to download the file first!std::cerr << "PointCloud before filtering: " << cloud->width * cloud->height<< " data points (" << pcl::getFieldsList(*cloud) << ").";// Create the filtering objectpcl::VoxelGrid<pcl::PointXYZ> sor;sor.setInputCloud(cloud);sor.setLeafSize(0.01f, 0.01f, 0.01f);sor.filter(*cloud_filtered);std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height<< " data points (" << pcl::getFieldsList(*cloud_filtered) << ").";//pcl::PCDWriter writer;//writer.write("table_scene_lms400_downsampled.pcd", *cloud_filtered,//Eigen::Vector4f::Zero(), Eigen::Quaternionf::Identity(), false);pcl::visualization::PCLVisualizer viewer("demo");int v1(0);int v2(1);viewer.createViewPort(0.0, 0.0, 0.5, 1.0, v1); viewer.createViewPort(0.5, 0.0, 1.0, 1.0, v2);// The color we will be usingfloat bckgr_gray_level = 0.0;  // Blackfloat txt_gray_lvl = 1.0 - bckgr_gray_level;// Original point cloud is whitepcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_in_color_h(cloud, (int)255 * txt_gray_lvl, (int)255 * txt_gray_lvl, (int)255 * txt_gray_lvl);viewer.addPointCloud(cloud, cloud_in_color_h, "cloud_in_v1", v1);       //viewer.addPointCloud(cloud_in, cloud_in_color_h, "cloud_in_v2", v2);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_out_green(cloud_filtered, 20, 180, 20);viewer.addPointCloud(cloud_filtered, cloud_out_green, "cloud_out", v2); viewer.setBackgroundColor(bckgr_gray_level, bckgr_gray_level, bckgr_gray_level, v2);     viewer.setSize(1280, 1024);  // Visualiser window size//viewer.showCloud(cloud_out);while (!viewer.wasStopped()){viewer.spinOnce();}return (0);
}

将官方源码中的pcl::PCLPointCloud2::Ptr替换成pcl::PointCloud<pcl::PointXYZ>::Ptr,更加方便点云的图形显示。

测试结果如下:

setLeafSize(0.01f, 0.01f, 0.01f)

[460400-->41049]

setLeafSize(0.1f, 0.1f, 0.1f)

[460400-->629]

3.2 均匀下采样

对点云数据创建一个三维体素栅格,然后取每个体素中最接近体素中心的点,代替体素中所有点。

关键代码:

// Uniform sampling object
pcl::UniformSampling<pcl::PointXYZ> filter;       // 创建均匀采样对象
filter.setInputCloud(cloud);                    // 设置待采样点云
filter.setRadiusSearch(0.01f);                  // 设置采样半径
filter.filter(*cloud_filtered);                 // 执行均匀采样,结果保存在cloud_filtered中

测试结果:

参考

[1] https://blog.csdn.net/suiyingy/article/details/124368059
[2] https://zhuanlan.zhihu.com/p/353761080
[3] https://blog.csdn.net/yanfeng1022/article/details/109322887
[4] https://blog.csdn.net/u013351270/article/details/68945056

点云降采样(DownSampling)相关推荐

  1. 基于体素化方法的点云降采样

    前两天做了一个点云降采样的项目,用pcl自带的降采样方法出来的结果不是很理想,于是就自己写了一个.为了使代码执行效率高点就采用了基于点云索引的方式. 本文使用的方法为:首先,计算点云群的Boundin ...

  2. NormalSpaceSampling 基于法向空间的点云降采样

    随着工业自动化.智能化的不断推进,机器视觉(2D/3D)在工业领域的应用和重要程度也同步激增(识别.定位.抓取.测量,缺陷检测等),而针对不同作业场景进行解决方案设计时,通常会借助PCL.OpenCV ...

  3. 我们成功给OpenCV添加了三维点云降采样算法!

    作者:阮业淳,钟万里,张昌圳(本科生) 指导教师:于仕琪 南方科技大学计算机科学与工程系 知名开源计算机视觉库OpenCV(Open Source Computer Vision Library)在其 ...

  4. 点云降采样--ApproximateVoxelGrid点云降采样

    1.版本要求 版本: >PCL1.0 2.简介 ApproximateVoxelGrid体素降采样是PCL开源库中非常有效的点云降采样手段.ApproximateVoxelGrid对点云进行体素 ...

  5. matlab 降采样代码,matlab 点云降采样 pcdownsample()

    ** 点云数据降采样 pcdownsample() ** pcdownsample降采样减少点云数据量: 一.语法: ptCloudOut = pcdownsample(ptCloudIn, 'ran ...

  6. 三维点云学习(1)下-点云体素降采样

    三维点云学习(1)下 点云体素降采样(Voxel Filter Downsampling) 代码参考网址秦乐乐CSDN博客 理论参考知乎博主:WALL-E 1.方法 Centroid 均值采样 Ran ...

  7. Down-Sampling 降采样(Verilog)

    简介 在图像处理领域中,降采样是一个非常常用的图像处理方法,目的是为了在大体上不改变图片的情况下,缩小图像,降低分辨率,减少数据的计算量,生成对应图像的降采样图.本质就是抽取图像数据来降低特征的维度进 ...

  8. 可观测|时序数据降采样在Prometheus实践复盘

    作者:智真 基于 Prometheus 的监控实践中,尤其是在规模较大时,时序数据的存储与查询是其中非常关键,而且问题点较多的一环.如何应对大数据量下的长周期查询,原生的 Prometheus 体系并 ...

  9. 可观测|时序数据降采样在 Prometheus 实践复盘

    基于 Prometheus 的监控实践中,尤其是在规模较大时,时序数据的存储与查询是其中非常关键,而且问题点较多的一环.如何应对大数据量下的长周期查询,原生的 Prometheus 体系并未能给出一个 ...

最新文章

  1. Java程序员从笨鸟到菜鸟之(十二)java异常处理机制
  2. 机器人弧焊焊钳型号_Delmia机器人仿真编程 第4节 创建资源库
  3. Google地图的trip plan是旅行规划的好帮手!
  4. Linux IPC / 分类
  5. C#实现软键盘的几个关键技术实现方法
  6. 张正友相机标定Opencv实现以及标定流程标定结果评价图像矫正流程解析(附标定程序和棋盘图)
  7. 功能对等四个原则_强直患者功能锻炼十分重要
  8. 根据父类id查询所有的父级_031、组函数和子查询
  9. Atitit mybatis返回多个数据集总结 目录 1.1. 配置handleResult接受,但是只有第一个select语句的结果 1 2. 配置resultMap ok 1 2.1. 调
  10. Oracle 11g数据库基础教程(第2版)-课后习题-第六章
  11. 网银打印回单显示服务器不能创建对象,打开应用弹出提示“Activex部件不能创建对象”的解决方法...
  12. 电气工程及其自动化走Java_电气工程及其自动化专业项目经验范文
  13. 时间序列预测方法最全总结!
  14. 软件界面原型设计工具(Web):Axure RP
  15. 关于Optical Zoom
  16. 小何的第一篇博客+GitHub的基本设置
  17. 2017年团建心得、总结、建议
  18. 【STM32F429的DSP教程】第6章 ARM DSP源码和库移植方法(MDK5的AC5和AC6)
  19. 浅谈导航数据中POI搜索技术原理
  20. 根据具体日期计算是一年的第几周和当月的第几周

热门文章

  1. 2_IPC进程间通信机制
  2. 2011年9月全国计算机等级考试四级网络工程师 试卷+题解
  3. mpython掌控板_用mpython x玩转掌控板——音乐律动
  4. 杂项-公司-百科:伯克希尔·哈撒韦-un
  5. VirtualBox虚拟网络环境配置【两台虚拟机互通】
  6. c++客户端 grpc_gRPC应用C++
  7. 石子合并(区间dp)
  8. 说不得大师与手游《我叫MT》:在崩盘之前逆袭
  9. 【易购管理系统】商品列表
  10. MySQL5.6数据库多种安装方法及企业级安装实践