1. 点云数据基础

大家好,我是老张。今天咱们聊聊点云数据的基础。说实话,我刚入行那会儿,对点云的理解也就停留在「一堆点嘛」的层面。直到第一次处理激光雷达数据,才发现这里面的门道比想象中多得多。

1.1 激光雷达工作原理

激光雷达,英文叫 LiDAR(Light Detection And Ranging)。说白了,就是「用激光来测距」。它的核心原理其实很简单:发射一束激光,打到目标物体上,反射回来,接收器捕捉到回波信号。通过计算发射和接收的时间差,就能知道目标有多远。

嗯,这里要注意一个关键点:激光雷达不是拍照片,它是「逐点扫描」的。每个激光脉冲对应一个点,成千上万个点拼在一起,才形成我们看到的点云。

核心公式:

距离 = (光速 × 飞行时间) / 2

为什么除以2?因为激光走了「去程 + 回程」两趟路。

我在项目中遇到过一件事:有次调试一个16线激光雷达,发现点云数据总是有奇怪的「鬼影」。排查了半天,原来是地面反射太强,产生了多路径效应。从那以后,我每次做数据采集都会先观察环境,避免强反射面。

激光雷达按扫描方式分,主要有这么几类:

  • 机械旋转式:通过电机带动激光器旋转,实现360°扫描。Velodyne的HDL-64就是典型代表。优点是视野广,缺点是机械结构容易磨损。
  • 固态式:没有旋转部件,靠光学相控阵或微镜阵列实现扫描。体积小、寿命长,但视场角有限。
  • MEMS式:微机电系统,用微型镜面反射激光。算是机械式和固态式的折中方案。

你想想看,不同的扫描方式,产生的点云特性也完全不同。机械式的点云分布均匀,固态式的边缘区域点密度会下降。这些细节,在做压缩算法时都得考虑进去。

1.2 点云数据格式

点云数据怎么存?市面上常见的格式有三种:PCD、PLY、BIN。我个人的习惯是:做原型验证用PCD,做可视化用PLY,做工程部署用BIN。

PCD格式

PCD是Point Cloud Data的缩写,由Point Cloud Library(PCL)推广。它的特点是「自描述」——文件头里包含了点云的所有元信息。

# .PCD v0.7 - Point Cloud Data file format
VERSION 0.7
FIELDS x y z intensity
SIZE 4 4 4 4
TYPE F F F F
COUNT 1 1 1 1
WIDTH 1000
HEIGHT 1
VIEWPOINT 0 0 0 1 0 0 0
POINTS 1000
DATA ascii
1.0 2.0 3.0 128
2.0 3.0 4.0 255
...

你看,文件头里明确写了每个字段的名称、类型、大小。这种格式的好处是「可读性强」,坏处是「文件体积大」。我记得有次处理一个1亿点的PCD文件,光解析文件头就花了半秒钟。

小技巧:如果你只是临时查看点云数据,用PCD的ASCII格式很方便。但正式处理时,一定要转成二进制格式,体积能缩小3-5倍。

PLY格式

PLY(Polygon File Format)是斯坦福大学搞出来的,最初是为了保存三维扫描的网格数据。它比PCD多了一个能力:可以存储多边形面片信息。

PLY也分ASCII和二进制两种。我个人觉得,PLY的二进制格式比PCD更紧凑,因为它支持「按属性打包」——比如把所有点的x坐标连续存储,y坐标连续存储,这样压缩效率更高。

BIN格式

BIN格式,说白了就是「裸数据」。没有文件头,没有元信息,就是一堆二进制数。KITTI数据集用的就是这种格式。

// 读取KITTI点云数据的C++代码片段
std::ifstream file("000000.bin", std::ios::binary);
std::vector<float> data(4 * num_points);
file.read(reinterpret_cast<char*>(data.data()), 4 * num_points * sizeof(float));

为什么KITTI要用BIN格式?因为效率。在自动驾驶场景中,每秒要处理几十帧点云,每帧几十万个点。如果用PCD或PLY,光解析文件头就够受的。BIN格式直接读入内存,零开销。

避坑指南:我曾经因为BIN格式的字节序问题吃过亏。不同平台的字节序(大端/小端)可能不同,跨平台传输时一定要确认字节序。建议统一使用小端序(Little Endian)。

1.3 点云特性

点云和图像不一样。图像是规整的网格,每个像素都有值。点云呢?它有三个让我又爱又恨的特性。

稀疏性

点云是稀疏的。什么意思?你想想看,一个64线激光雷达,每秒也就产生200万个点。这些点散布在三维空间中,大部分区域其实是「空的」。这和图像完全不同——一张1080p的图像有200万个像素,每个像素都有颜色值。

稀疏性带来的挑战是:你不能用处理图像的方法来处理点云。图像可以用卷积神经网络,因为数据是密集的、有规律的。点云不行,你得用PointNet、PointNet++这类专门设计的网络。

无序性

点云是无序的。同样一组点,你换个顺序存储,它还是同一个点云。这听起来简单,但做起来很麻烦。

举个例子:假设你有一个点云,包含三个点A、B、C。你把它存成[A, B, C]和[C, A, B],在数学上是等价的。但如果你用全连接网络处理,网络会把顺序当成特征来学习——这就出问题了。

我在做点云压缩时,就遇到过这个问题。传统的图像压缩算法(比如JPEG)依赖像素的排列顺序。点云不行,你得设计「置换不变」的编码方式。后来我用了基于八叉树的方法,才解决了这个问题。

密度不均

点云的密度不是均匀的。离激光雷达近的地方,点很密;远的地方,点很稀疏。为什么?因为激光束是发散的,距离越远,光束覆盖的面积越大,单位面积上的点就越少。

密度不均带来的问题是:你不能用统一的量化步长。近处的点需要高精度,远处的点可以适当降低精度。我在做自适应量化时,就是根据距离动态调整量化参数,效果还不错。

总结一下点云的三大特性:

  • 稀疏性:大部分区域是空的,需要特殊的数据结构(如八叉树、KD树)来存储。
  • 无序性:点的排列顺序不影响点云的几何意义,需要设计置换不变的算法。
  • 密度不均:近密远疏,需要自适应处理策略。

知识体系总览

下面这张图,是我自己画的点云数据基础的知识结构。你可以把它当作本章的「地图」。

点云数据基础 - 知识体系 点云数据基础 激光雷达工作原理 TOF测距原理 扫描方式分类 多路径效应 点云数据格式 PCD格式 PLY格式 BIN格式 点云三大特性 稀疏性 无序性 密度不均 核心挑战:如何高效表示和压缩非结构化三维数据

这张图把本章的三个核心内容串起来了。左边是工作原理,中间是数据格式,右边是点云特性。这三者不是孤立的——你理解了工作原理,才能明白为什么点云有这些特性;你掌握了数据格式,才能选择合适的存储和传输方案。

好了,关于点云数据基础,我就讲这么多。记住一句话:点云不是图像,别用图像思维去理解它。下一章,我们会深入讨论点云压缩的核心技术——八叉树编码。到时候见。


公众号:蓝海资料掘金营,微信deep3321