第一章:点云数据读取与可视化
各位同学好,我是你们这门课的主讲。做了这么多年点云处理,我始终觉得——可视化是理解点云的第一步。你想想看,一堆三维坐标点,光看数字能看出什么名堂?只有把它渲染出来,你才能真正感知到数据的结构、噪声、密度分布。
这一章,我们就从最基础的操作开始:用Open3D读取点云文件,然后把它显示在屏幕上。嗯,别小看这一步,我见过不少新手在这上面栽跟头。
1.1 点云文件格式:PCD vs PLY
先聊聊文件格式。目前最常用的两种就是PCD和PLY。
| 特性 | PCD | PLY |
|---|---|---|
| 发明者 | Point Cloud Library (PCL) | Stanford Graphics Lab |
| 存储方式 | ASCII / 二进制 | ASCII / 二进制 |
| 支持颜色 | ✅ 支持 | ✅ 支持 |
| 支持法向量 | ✅ 支持 | ✅ 支持 |
| 文件大小 | 相对较小 | 相对较大 |
| 常见场景 | 机器人、SLAM | 计算机图形学、3D扫描 |
我个人习惯用PCD,因为PCL生态里它最顺手。但如果你做图形学相关的工作,PLY会更常见。其实Open3D对两者支持都很好,你不需要纠结太多。
1.2 用Open3D读取点云
代码其实就一行。但这一行背后,Open3D帮你做了很多事:文件格式检测、数据解析、内存分配。
import open3d as o3d
# 读取PCD文件
pcd = o3d.io.read_point_cloud("data/room.pcd")
# 读取PLY文件
pcd = o3d.io.read_point_cloud("data/bunny.ply")
print("点云加载完成")
我在项目中遇到过一个问题:读取一个几百兆的PCD文件,程序直接卡死了。后来发现是文件用了ASCII格式,数据量太大。所以如果你处理大文件,记得用二进制格式存储。
1.3 点云的基本属性
读取完点云,我们得看看它长什么样。说白了,就是查几个关键属性。
# 获取点数
num_points = len(pcd.points)
print(f"点数: {num_points}")
# 获取坐标范围
points = np.asarray(pcd.points)
x_min, x_max = points[:, 0].min(), points[:, 0].max()
y_min, y_max = points[:, 1].min(), points[:, 1].max()
z_min, z_max = points[:, 2].min(), points[:, 2].max()
print(f"X范围: [{x_min:.2f}, {x_max:.2f}]")
print(f"Y范围: [{y_min:.2f}, {y_max:.2f}]")
print(f"Z范围: [{z_min:.2f}, {z_max:.2f}]")
# 检查是否有颜色信息
if pcd.has_colors():
colors = np.asarray(pcd.colors)
print(f"颜色范围: R[{colors[:,0].min():.2f}, {colors[:,0].max():.2f}]")
else:
print("该点云没有颜色信息")
这里有个坑:Open3D的颜色值范围是0到1,不是0到255。如果你从别的工具导出的PLY文件颜色是0-255,记得归一化。我刚开始用的时候,显示出来的点云一片漆黑,还以为是代码写错了。
1.4 点云可视化基础
终于到了最激动人心的部分——把点云显示出来。
# 最简单的可视化
o3d.visualization.draw_geometries([pcd])
# 带窗口控制的可视化
vis = o3d.visualization.Visualizer()
vis.create_window(window_name="我的第一个点云", width=800, height=600)
vis.add_geometry(pcd)
# 设置渲染选项
opt = vis.get_render_option()
opt.background_color = np.array([0.1, 0.1, 0.1]) # 深灰色背景
opt.point_size = 2.0 # 点的大小
vis.run()
vis.destroy_window()
你运行这段代码,会看到一个3D窗口。鼠标操作很简单:左键旋转、滚轮缩放、右键平移。嗯,这里要注意,如果你用的是Mac的触摸板,可能需要调整一下鼠标设置。
1.5 颜色渲染:让点云更好看
默认情况下,Open3D会用一种统一的颜色渲染所有点。但很多时候,我们需要根据某些属性给点上色。
# 根据Z轴高度上色
points = np.asarray(pcd.points)
z_values = points[:, 2]
z_min, z_max = z_values.min(), z_values.max()
# 归一化到[0, 1]
z_norm = (z_values - z_min) / (z_max - z_min)
# 创建颜色:低处蓝色,高处红色
colors = np.zeros((len(points), 3))
colors[:, 0] = z_norm # 红色通道
colors[:, 2] = 1 - z_norm # 蓝色通道
pcd.colors = o3d.utility.Vector3dVector(colors)
o3d.visualization.draw_geometries([pcd])
这种高度着色法,我在做地形扫描数据时经常用。一眼就能看出哪里是高地、哪里是洼地,比看数字直观多了。
- Open3D的颜色范围是[0, 1],不是[0, 255]
- 可视化窗口支持鼠标交互:旋转、平移、缩放
- 可以通过修改render_option控制显示效果
- 颜色渲染是理解点云结构的重要手段
1.6 本章知识体系
下面这张图,是我梳理的本章核心逻辑。你跟着这个流程走,基本不会出错。
这张图把本章的知识点串起来了。你从文件格式开始,一路走到可视化,每一步都有对应的Open3D函数。我个人建议你按照这个流程,自己动手跑一遍代码。光看是学不会的,得亲手敲。
vis.run() 和 vis.destroy_window()。如果你也遇到这个问题,检查一下是不是少了这两行。
好了,第一章的内容就到这里。你学会了怎么读取点云、查看属性、可视化、做颜色渲染。这些是后续所有章节的基础,一定要练熟。
公众号:蓝海资料掘金营,微信deep3321