1、点云数据基础:什么是点云、点云数据格式(.pcd/.las/.ply)、点云可视化基础(Open3D/PCL)

好,咱们直接进入正题。点云是什么?说白了,就是一堆三维空间里的点。每个点带着自己的坐标 (x, y, z),有时候还带着颜色、强度之类的附加信息。你想想看,激光雷达扫一圈,打出去几百万束激光,每束光碰到物体弹回来,我们就记录下一个点的位置。几百万个点凑在一起,就成了点云。

我个人习惯把点云理解成「三维世界的照片底片」。照片是二维的,点云是三维的。你拿着相机拍一张照片,得到的是像素矩阵;激光雷达扫一圈,得到的就是点云矩阵。只不过这个矩阵里的每个元素,不是 RGB 值,而是空间坐标。

核心概念:点云 = 三维坐标系下的离散点集合。每个点至少包含 (x, y, z) 三个维度。

1.1 点云数据格式:.pcd / .las / .ply

做点云处理,绕不开文件格式。我刚开始接触的时候,被各种后缀名搞得头晕。其实常用的就三种:.pcd.las.ply。咱们一个一个说。

.pcd 格式(Point Cloud Data)

这是 PCL 库的亲儿子格式。PCL 是啥?Point Cloud Library,点云库,后面会细讲。.pcd 格式最大的优点是简单、清晰、好解析。文件头部用纯文本写明了点云的基本信息,比如点数、维度、数据类型。头部之后就是纯数据。

我给大家看一个典型的 .pcd 文件头:

# .PCD v0.7 - Point Cloud Data file format
VERSION 0.7
FIELDS x y z rgb
SIZE 4 4 4 4
TYPE F F F F
COUNT 1 1 1 1
WIDTH 640
HEIGHT 480
VIEWPOINT 0 0 0 1 0 0 0
POINTS 307200
DATA ascii
0.123 0.456 0.789 0.5
0.234 0.567 0.890 0.6
...

嗯,这里要注意:WIDTHHEIGHT 不一定代表图像尺寸。对于无序点云,HEIGHT 固定为 1,WIDTH 等于点数。对于有序点云(比如从深度相机来的),WIDTHHEIGHT 才对应行列数。我曾经在这个坑里栽过跟头,解析一个 .pcd 文件时死活读不对点数,后来才发现是没区分有序和无序。

我的建议:做原型验证时,优先用 .pcd 格式。它简单、跨平台、PCL 和 Open3D 都原生支持。别折腾其他格式,除非有特殊需求。

.las 格式(LASer)

.las 是测绘和遥感领域的标准格式。它比 .pcd 复杂得多,支持更多的附加信息:回波次数、回波强度、分类标签(地面、建筑、植被等)、GPS 时间戳等等。说白了,.las 是为「专业测绘」设计的,.pcd 是为「通用点云处理」设计的。

如果你做的是车载激光雷达、机器人导航这类项目,大概率用 .pcd 就够了。但如果你做的是无人机测绘、地形建模、林业调查,那 .las 是绕不开的。我记得有一次做城市三维重建项目,甲方给的数据全是 .las 格式,里面每个点都带了分类标签,省了我不少标注的功夫。

特性 .pcd .las .ply
主要用途 通用点云处理 测绘、遥感 三维模型、网格
支持颜色
支持强度
支持分类标签
文件大小 中等 较大 中等
解析复杂度

.ply 格式(Polygon File Format)

.ply 原本是为三维网格(Mesh)设计的,但也可以存储点云。它的特点是支持顶点 + 面片的结构。如果你做的是三维重建,从点云生成网格后,通常保存为 .ply 格式。

我个人觉得,纯点云处理用 .ply 有点「杀鸡用牛刀」的感觉。但如果你需要同时保存点云和三角面片,那 .ply 是首选。Open3D 对 .ply 的支持非常好,读写都很方便。

避坑指南:我曾经遇到过一个 .ply 文件,用 Open3D 读进来全是 NaN 值。查了半天才发现,那个文件是用二进制格式写的,但头部声明了 ASCII。嗯,格式声明和实际编码不一致,这种坑在网上下载的数据集里很常见。遇到这种问题,先用文本编辑器打开看看头部,确认一下格式。

1.2 点云可视化基础:Open3D 与 PCL

做点云处理,可视化是刚需。你总不能对着几百万个数字发呆吧?得看到点云长什么样,才能判断算法效果好不好。常用的可视化工具有两个:Open3DPCL

Open3D:现代、轻量、Python 友好

Open3D 是我现在的主力工具。为什么?因为它太方便了。几行 Python 代码就能把点云显示出来,而且交互体验很好——旋转、缩放、平移都很流畅。

来看一个最简单的例子:

import open3d as o3d

# 读取点云
pcd = o3d.io.read_point_cloud("example.pcd")

# 可视化
o3d.visualization.draw_geometries([pcd])

就这三行,点云就出来了。你想想看,如果用 C++ 的 PCL,得写多少行?至少得配置 CMake、包含头文件、创建窗口、绑定鼠标事件……Open3D 把这些都封装好了。

我个人习惯在 Jupyter Notebook 里用 Open3D 做快速验证。写一段算法,跑一下,看一眼结果,不满意就改。这种「写-跑-看」的循环,Open3D 支持得非常好。

小技巧:Open3D 的 draw_geometries 函数支持传入多个几何体。你可以把原始点云和分割后的点云一起显示,用不同颜色区分。这样对比效果一目了然。

PCL:工业级、功能全面、C++ 生态

PCL 是点云处理的老牌库,功能极其全面。从滤波、分割、配准到识别,几乎你能想到的点云算法,PCL 都有实现。但它的学习曲线比较陡,而且配置环境是个体力活。

用 PCL 可视化点云,大概是这样:

#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>

int main() {
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::io::loadPCDFile("example.pcd", *cloud);

    pcl::visualization::PCLVisualizer viewer("Point Cloud Viewer");
    viewer.addPointCloud(cloud, "cloud");
    
    while (!viewer.wasStopped()) {
        viewer.spinOnce();
    }
    return 0;
}

嗯,代码量明显多了。但 PCL 的优势在于深度和广度。比如你要做点云配准,PCL 提供了 ICP、NDT 等多种算法,而且参数可调范围很大。Open3D 虽然也有这些算法,但参数没那么多,灵活性稍差。

我记得有一次做工业检测项目,客户要求点云处理速度必须达到 30Hz。Open3D 的 Python 接口跑不满,后来用 PCL 的 C++ 实现,优化了一下参数,稳稳地跑到了 35Hz。所以我的建议是:快速原型用 Open3D,产品落地用 PCL

怎么选?

其实不用纠结。我个人的工作流是这样的:

  • 学习阶段:用 Open3D + Python。上手快,反馈及时,适合理解算法原理。
  • 项目阶段:先用 Open3D 验证算法可行性,再用 PCL 做性能优化和工程化。
  • 特殊需求:如果要做三维重建、网格处理,Open3D 更合适;如果要做点云配准、特征提取,PCL 更强大。

一句话总结:点云就是三维世界的「像素」,.pcd 适合通用处理,.las 适合测绘,.ply 适合网格。可视化工具,Open3D 图方便,PCL 图深度。两个都学,不吃亏。

好,这一章就到这里。下一章咱们聊聊点云的预处理——滤波和降采样。这可是点云处理的「洗菜」环节,菜洗不干净,后面炒菜再厉害也白搭。