点云降采样(DownSampling)

article/2025/9/25 0:06:55

点云降采样

1 概述

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

2 常用方法

2.1 体素网格下采样

2.1.1 原理

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

img

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

2.1.2 流程

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

2.1.3 特点

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

2.2 均匀下采样

2.2.1 原理

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

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

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

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

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

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

img

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(1V)和$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]

image-20220726083856610
setLeafSize(0.1f, 0.1f, 0.1f)

[460400-->629]

image-20220726085053058

3.2 均匀下采样

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

关键代码:

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

测试结果:

image-20220726091522437

参考

[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


http://chatgpt.dhexx.cn/article/ctPoiV0p.shtml

相关文章

对信号做降采样处理时,需要先滤波,后抽取(降采样);升采样操作与之相反

一、对信号做降采样处理时&#xff0c;需要先滤波&#xff0c;后抽取&#xff08;降采样&#xff09;的原因解释&#xff1a; 一句话就能概括&#xff0c;如果抽取时不先做滤波&#xff0c;就会导致信号混叠&#xff0c;这里的滤波器是抗混叠滤波器。 1、如果不滤波&#xff…

数字图像处理--六、图像压缩

目录 1.基本概念 1.1 图像压缩概念及其分类 1.2 数据冗余 1.3 图像信息的度量 1.4 图像保真度准则 (Fidelity Criteria) 1.5 图像压缩模型 2.图像压缩方法 2.1Huffman编码 消除编码冗余 2.2算术编码 (Arithmetic Coding) 消除编码冗余 2.3LZW编码 (Lempel-Ziv-Welch …

图像压缩之算术编码

JPEG中使用了量化、哈夫曼编码等&#xff0c;极大的压缩了图片占用的空间&#xff0c;那么是否可以进一步压缩呢&#xff1f; 从技术角度讲&#xff0c;是可以的。如DropBox开源的lepton&#xff0c;在目前的JPEG压缩基础上&#xff0c;可以再节省22%左右的空间。 lepton中使用…

数字图像处理——JPEG图像压缩

该文章的代码为数字图像的JPEG压缩模型。最后是我得到的结果。 import numpy as np import matplotlib.pyplot as plt from skimage import ioDC_Y {0: 00,1: 010,2: 011,3: 100,4: 101,5: 110,6: 1110,7: 11110,8: 111110,9: 1111110,10: 11111110,11: 111111110} AC_Y {(0…

JPEG图像压缩

转载自&#xff1a; https://blog.csdn.net/shelldon/article/details/54234433 www.thecodeway.com http://www.ibm.com/developerworks/cn/linux/l-cn-jpeg/ 一、图像分割 JPEG算法的第一步&#xff0c;图像被分割成大小为8X8的小块&#xff0c;这些小块在整个压缩过程中…

JPEG2000图像压缩算法学习

压缩算法——JPEG2000 编解码原理 JPEG2000-Matlab源码实现 JPEG和JPEG2000 JPEG2000和JEPG都是静止图像压缩标准&#xff0c;最大区别是在空间域至频域转换。JPEG是基于离散余弦变换&#xff08;DCT&#xff09;&#xff0c; 而JEPG2000是基于离散小波变换&#xff08;DWT&a…

图像处理(六)——图像压缩

图像压缩模型图像数据中的冗余 三种数据冗余&#xff1a;编码冗余、像素冗余、视觉心理冗余 如果一个图像的灰度级编码&#xff0c;使用了多于实际需要的编码符号&#xff0c;就称该图像包含了编码冗余。 图像压缩中的信息论观点 字典压缩 有…

图片压缩算法

有损算法&#xff1a; JPEG&#xff0c;我们最为常用的算法。他是通过离散余弦变换&#xff0c;对图片质量尽量小的时候进行有损压缩&#xff0c;改算法对高中波特率下效果很好&#xff0c;但是对低波特率下&#xff0c;就会出现方格之类的&#xff0c;比如100多MB的MPEG电影&…

算法设计与分析——图像的压缩

一、基本概念&#xff1a; 像素灰度值为0-255&#xff0c;需要8位二进制数来存储。若一灰度序列为{p1,p2,p3…pn}&#xff0c;pi为第i个像素点的灰度值。则所需的空间为8n。 二、问题提出&#xff1a; 若图像中有一大部分的颜色的相同的或是相近的&#xff0c;能不能有更好的…

JPEG图像压缩算法的python实现

摘要 文章在研究JPEG压缩编码对图像数据压缩的基本原理的基础上&#xff0c;设计了JPEG图像压缩算法程序实现流程&#xff0c;利用 Python语言对程序进行了编写&#xff0c;并实现了对压缩质量进行控制&#xff0c;验证了JPEG压缩编码对图像数据压缩的可行性。 用 JPEG压缩软件…

基于深度学习的图像压缩

近年来&#xff0c;深度学习在计算机视觉领域已经占据主导地位&#xff0c;不论是在图像识别还是超分辨重现上&#xff0c;深度学习已成为图片研究的重要技术&#xff0c;但它们的能力并不仅限于这些任务&#xff1b;现在深度学习技术已进入图片压缩领域。下面就说说神经网络在…

JPEG压缩算法步骤原理

目录 JPEG压缩算法解密 步骤一&#xff1a;图像分割 步骤二&#xff1a;颜色空间转换RGB->YCbCr 步骤三&#xff1a;离散余弦变换 步骤四&#xff1a;数据量化 步骤五&#xff1a;哈弗曼编码 JPEG压缩算法解密 by jinchao 图片压缩有多重要&#xff0c;可能很多人可能…

影像算法解析——JPEG 压缩算法

由于视频是由一帧帧图像构成的&#xff0c;研究视频编码首先先要研究图像编码。这篇文章就详细说一下 JPEG 是如何压缩一个图像的。 先简单介绍一下 JPEG&#xff08;Joint Photographic Experts Group&#xff0c;联合图像专家小组&#xff09;&#xff1a;此团队创立于1986年…

数字图像处理(七)图像压缩-无损编码/压缩算法+matlab

要求&#xff1a; 无损编码/压缩算法&#xff1a; 问题1: 实现行程编码压缩, 肉眼观察压缩效果&#xff0c;并计算原图和压缩以后的尺寸&#xff0c;计算压缩率并比较分析&#xff1b;问题2: 实现哈夫曼压缩, 肉眼观察压缩效果&#xff0c;并计算原图和压缩以后的尺寸&#x…

图像压缩原理-JPEG

搬来一个基础啊 给自己看~~ 非技术指正勿扰 图像的格式有很多种&#xff0c;比如PNG&#xff0c;JPEG等等&#xff0c;但当我们把一张图用工具变成各种其他格式时&#xff0c;其在计算机文件系统显示的文件大小各不一样&#xff0c;但是当你打开显示时&#xff0c;从视觉角度…

图像压缩算法简介

理论基础 香农的信息论&#xff0c;在不产生任何失真的前提下&#xff0c;通过合理的编码&#xff0c;对于每个信源符号分配不等长的码字&#xff0c;平均码长可以任意接近于信源的熵。在这个理论框架下产生了几种不同的无失真的信源编码方法&#xff1a;哈夫曼编码&#xff0c…

图像压缩原理

原文网址&#xff1a;http://blog.csdn.net/newchenxf/article/details/51693753 转载请注明出处。 1 图像可压缩的原因 一张原始图像(1920x1080)&#xff0c;如果每个像素32bit表示&#xff08;RGBA&#xff09;&#xff0c;那么&#xff0c;图像需要的内存大小 1920x1080x…

JPEG图像压缩算法详解

转载自 http://www.ibm.com/developerworks/cn/linux/l-cn-jpeg/ JPEG压缩算法之前已有很多前辈详细讲解过&#xff0c;我就不在这里画蛇添足了&#xff08;主要是我懒。。&#xff09;&#xff0c;转载两篇JPEG压缩算法介绍&#xff0c;拼为一篇。侵删。 JPEG图像压缩算法详解…

图片压缩知识

一、图片压缩算法 有损算法&#xff1a; JPEG&#xff0c;我们最为常用的算法。他是通过离散余弦变换&#xff0c;对图片质量尽量小的时候进行有损压缩&#xff0c;该算法对高中波特率下效果很好&#xff0c;但是对低波特率下&#xff0c;就会出现方格之类的&#xff0c;比如1…

imadjust函数分析一

声明&#xff1a;本文涉及到的行数皆指本文提供的附件imadjust.m的代码中行数 本文只讨论imadjust函数是一种用法&#xff0c;即 J IMADJUST(I,[LOW_IN; HIGH_IN],[LOW_OUT; HIGH_OUT],GAMMA) 处理效果如下图 图像矩阵I要求数据类型uint8、uint16、double、single和int16&…