4. 点云可视化基础
点云处理这行,有个很实在的道理——看不见,就调不对。你算法写得再漂亮,滤波参数设得再精细,不亲眼看看点云长什么样,心里始终没底。我刚开始做SLAM的时候,就吃过这个亏:跑完一帧匹配,觉得效果挺好,结果可视化一看,点云全飘到天上去了……嗯,从那以后,我再也不敢跳过可视化这一步。
这一章,咱们就扎扎实实地把Open3D可视化这块啃下来。说白了,就是学会怎么把点云“摆”在屏幕上,还能随心所欲地调颜色、调大小、换视角。你想想看,后面做滤波、做配准,每一步都要靠眼睛来验证,可视化就是你的“第二双眼睛”。
4.1 Open3D可视化窗口:从零搭建你的“点云观察站”
Open3D的可视化核心就一个函数:draw_geometries。但别小看它,参数调好了,能玩出花来。
先看最基础的用法:
import open3d as o3d
import numpy as np
# 生成一个简单的点云(1000个随机点)
points = np.random.rand(1000, 3)
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(points)
# 可视化
o3d.visualization.draw_geometries([pcd])
这段代码一跑,一个窗口就弹出来了。你可以用鼠标拖拽旋转、滚轮缩放、右键平移。操作很直觉,跟玩3D建模软件差不多。
但实际项目中,我们往往需要更精细的控制。比如窗口大小、窗口标题、背景颜色。这时候就要用draw_geometries的window_name和width/height参数:
o3d.visualization.draw_geometries(
[pcd],
window_name="我的第一个点云窗口",
width=1280,
height=720,
point_show_normal=False
)
4.2 点云颜色与大小:让数据“说话”
默认的点云是灰色的,大小是1个像素。说实话,看起来挺费劲的。尤其是当你要区分不同区域、不同高度或者不同类别的点时,颜色和大小就是你的“画笔”。
4.2.1 给点云上色
Open3D里给点云上色有三种方式:
| 方法 | 代码示例 | 适用场景 |
|---|---|---|
| 统一颜色 | pcd.paint_uniform_color([1, 0, 0]) |
区分不同物体或不同帧 |
| 按高度染色 | 根据z值映射颜色 | 地形、建筑物立面分析 |
| 按类别染色 | 根据标签分配颜色 | 语义分割结果展示 |
统一颜色最简单,直接传RGB值(范围0-1):
pcd.paint_uniform_color([0.2, 0.6, 1.0]) # 浅蓝色
按高度染色是我用得最多的。比如你有一片地面点云,想看看地形起伏,按z轴染色一目了然:
# 获取点的z坐标
points = np.asarray(pcd.points)
z = points[:, 2]
# 归一化到0-1
z_min, z_max = z.min(), z.max()
z_norm = (z - z_min) / (z_max - z_min)
# 使用colormap(这里用jet)
colors = plt.cm.jet(z_norm)[:, :3] # 去掉alpha通道
pcd.colors = o3d.utility.Vector3dVector(colors)
4.2.2 调整点的大小
点的大小在Open3D里不是直接设pcd的属性,而是通过可视化选项来调。有两种方式:
方式一:运行时按键盘
在可视化窗口打开后,按+和-键可以实时调整点的大小。这个技巧很实用,我经常在调试时一边看效果一边调。
方式二:代码中预设
用Visualizer类可以精确控制:
vis = o3d.visualization.Visualizer()
vis.create_window(window_name="点云大小测试", width=800, height=600)
vis.add_geometry(pcd)
# 获取渲染选项并设置点大小
opt = vis.get_render_option()
opt.point_size = 5.0 # 默认是1.0
vis.run()
vis.destroy_window()
点大小的取值范围一般是1.0到10.0。点云密度大时用小点(1-3),密度小时用大点(5-8)。我个人的经验是:激光雷达点云用2-3,深度相机点云用4-6。
4.3 多窗口与多视角可视化:同时看,才能对比
做点云处理,最怕的就是“盲人摸象”。只看一个视角,很容易漏掉关键信息。比如你滤波前和滤波后的点云,放在两个窗口里对比着看,效果立竿见影。
4.3.1 多窗口:各看各的
Open3D支持同时打开多个窗口。每个窗口独立控制视角、独立渲染。实现方式很简单——开多个Visualizer实例:
# 创建两个窗口
vis1 = o3d.visualization.Visualizer()
vis1.create_window(window_name="原始点云", width=640, height=480, left=50, top=50)
vis2 = o3d.visualization.Visualizer()
vis2.create_window(window_name="滤波后点云", width=640, height=480, left=700, top=50)
# 添加几何体
vis1.add_geometry(pcd_original)
vis2.add_geometry(pcd_filtered)
# 分别设置点大小
opt1 = vis1.get_render_option()
opt1.point_size = 3.0
opt2 = vis2.get_render_option()
opt2.point_size = 3.0
# 同时更新
while True:
vis1.poll_events()
vis1.update_renderer()
vis2.poll_events()
vis2.update_renderer()
poll_events()和update_renderer()必须放在循环里同时调用。如果只更新一个窗口,另一个会卡死。我刚开始写多窗口时,就因为这个bug折腾了半天。
4.3.2 多视角:一个窗口,多个角度
有时候我们不想开那么多窗口,而是希望在一个窗口里从不同角度观察同一个点云。Open3D的ViewControl可以帮我们实现:
vis = o3d.visualization.Visualizer()
vis.create_window()
vis.add_geometry(pcd)
# 获取视角控制
ctrl = vis.get_view_control()
# 设置前视图
ctrl.set_front([0, 0, -1]) # 从z轴负方向看
ctrl.set_up([0, -1, 0]) # 上方向为y轴负方向
ctrl.set_zoom(0.8)
# 运行
vis.run()
vis.destroy_window()
常用的视角预设:
| 视角 | front向量 | up向量 | 说明 |
|---|---|---|---|
| 俯视图 | [0, 0, -1] | [0, -1, 0] | 看地面分布 |
| 前视图 | [0, -1, 0] | [0, 0, 1] | 看立面结构 |
| 侧视图 | [1, 0, 0] | [0, 0, 1] | 看侧面轮廓 |
| 等轴测图 | [1, -1, -1] | [0, 0, 1] | 立体感最强 |
我个人习惯在调试时先切到俯视图,看看点云的整体分布是否合理。然后再切到等轴测图,观察细节结构。
4.4 本章知识体系
下面这张图把本章的核心内容串起来了,你可以对照着回顾一下:
可视化这件事,说难不难,说简单也不简单。关键是要养成习惯——每做一步处理,都打开窗口看一眼。你会发现,很多bug在可视化面前根本藏不住。
好了,这一章的内容就到这里。拿起你的点云数据,动手试试吧。记住,看得见,才能调得准。