4、点云可视化入门:使用Open3D读取并显示点云、调整视角与颜色、保存截图
点云可视化,说白了就是让那些密密麻麻的坐标点“活”起来。你想想看,一个激光雷达扫出来的几十万个点,光看数字谁能看出个门道?我刚开始做感知的时候,就对着纯文本数据发过呆——完全想象不出场景长什么样。后来学会了可视化,才真正跟数据“对上话”。
这一节,我们就用Open3D这个库,把点云数据变成能看、能转、能截图的3D画面。嗯,这是你搭建标注数据集的第一步,也是最重要的一步。
4.1 为什么是Open3D?
市面上点云可视化的工具不少,比如PCL、Mayavi、CloudCompare。但我个人习惯用Open3D,原因很简单:
- 轻量:安装简单,pip一行搞定
- 现代:API设计得很Pythonic,上手快
- 交互友好:鼠标拖拽旋转、滚轮缩放,跟玩3D游戏一样
- 标注扩展性强:后面做标注工具,Open3D也能撑得住
我在项目中遇到过用PCL做可视化,编译半天还报错的情况。换成Open3D后,十分钟就把数据看明白了。所以,咱们就用它。
4.2 安装与第一个可视化程序
先装库,打开终端:
pip install open3d
装好之后,写个最简单的脚本试试:
import open3d as o3d
import numpy as np
# 生成一些随机点云数据(模拟激光雷达扫描结果)
points = np.random.rand(1000, 3) # 1000个点,每个点有x,y,z坐标
# 创建点云对象
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(points)
# 可视化
o3d.visualization.draw_geometries([pcd])
运行后,你会看到一个3D窗口,里面飘着一团随机点。你可以用鼠标左键旋转视角,滚轮缩放,右键平移。是不是很直观?
4.3 读取真实的点云文件
实际项目中,点云数据通常存在文件里。最常见的格式是PCD(Point Cloud Data)和PLY。Open3D直接支持读取:
# 读取PCD文件
pcd = o3d.io.read_point_cloud("your_data.pcd")
# 读取PLY文件
pcd = o3d.io.read_point_cloud("your_data.ply")
# 看看有多少个点
print(f"点云包含 {len(pcd.points)} 个点")
# 显示
o3d.visualization.draw_geometries([pcd])
如果你手头没有现成的点云文件,可以用Open3D自带的数据集:
# 加载示例数据(一个客厅场景的片段)
pcd = o3d.data.PCDPointCloud()
pcd = o3d.io.read_point_cloud(pcd.path)
o3d.visualization.draw_geometries([pcd])
4.4 调整视角——让点云“站”对位置
默认视角不一定好看。比如你加载一个道路场景,可能看到的是俯视图,而不是你想要的平视效果。这时候就需要手动调整视角。
Open3D提供了两种方式:
4.4.1 交互式调整
在可视化窗口中,按 H 键可以查看所有快捷键。常用的有:
Ctrl + 左键:旋转Shift + 左键:平移滚轮:缩放
4.4.2 代码控制视角
如果你想让每次打开都看到同一个角度,可以用代码设置:
# 创建可视化窗口
vis = o3d.visualization.Visualizer()
vis.create_window()
# 添加点云
vis.add_geometry(pcd)
# 设置视角参数(前、上、右方向向量)
view_control = vis.get_view_control()
view_control.set_front([0, 0, -1]) # 看向Z轴负方向
view_control.set_up([0, -1, 0]) # 上方是Y轴负方向
view_control.set_zoom(0.8) # 缩放比例
# 运行可视化
vis.run()
vis.destroy_window()
我个人习惯先交互式调整到满意的视角,然后通过 vis.get_view_control().convert_to_pinhole_camera_parameters() 把当前视角参数打印出来,再写进代码里。这样最省事。
4.5 颜色设置——让点云“说话”
默认的点云是灰色的,看起来有点单调。给点云上色,可以让你一眼看出不同区域或不同类别的点。
4.5.1 统一颜色
# 把所有点设为蓝色
pcd.paint_uniform_color([0, 0, 1]) # RGB值范围0~1
4.5.2 按高度着色
这是最常用的方式。比如地面附近的点用绿色,高处的点用红色:
import numpy as np
# 获取所有点的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)
# 创建颜色数组:低处蓝色,中间绿色,高处红色
colors = np.zeros((len(points), 3))
colors[:, 0] = z_norm # 红色通道
colors[:, 2] = 1 - z_norm # 蓝色通道
pcd.colors = o3d.utility.Vector3dVector(colors)
4.5.3 按类别着色
如果你已经做了标注,可以给不同类别分配不同颜色:
# 假设labels是一个数组,0表示地面,1表示车辆,2表示行人
labels = np.random.randint(0, 3, len(points))
# 定义颜色映射
color_map = {
0: [0.5, 0.5, 0.5], # 地面:灰色
1: [1, 0, 0], # 车辆:红色
2: [0, 1, 0] # 行人:绿色
}
colors = np.array([color_map[l] for l in labels])
pcd.colors = o3d.utility.Vector3dVector(colors)
4.6 保存截图——记录你的“作品”
可视化之后,你可能想把当前画面保存下来,用于报告、论文或者团队分享。Open3D支持直接保存截图:
# 方法一:在交互窗口中按 Ctrl + S
# 会弹出保存对话框,选择路径即可
# 方法二:代码自动保存
vis = o3d.visualization.Visualizer()
vis.create_window(visible=False) # 不显示窗口,后台渲染
vis.add_geometry(pcd)
# 设置视角(同上)
view_control = vis.get_view_control()
view_control.set_front([0, 0, -1])
view_control.set_up([0, -1, 0])
view_control.set_zoom(0.8)
# 更新渲染
vis.poll_events()
vis.update_renderer()
# 保存截图
vis.capture_screen_image("pointcloud_screenshot.png")
vis.destroy_window()
注意,capture_screen_image 保存的是当前窗口的截图,分辨率取决于窗口大小。如果你想要高清大图,可以先把窗口设大一点:
vis.create_window(width=1920, height=1080)
4.7 本章知识体系
下面这张图,帮你理清这一节的核心逻辑:
4.8 避坑指南
最后,分享几个我踩过的坑:
- 点云显示不全:检查一下点云的范围,如果坐标值特别大(比如几万米),Open3D的默认视角可能看不到。可以用
pcd.get_axis_aligned_bounding_box()查看范围,然后调整zoom。 - 颜色显示不对:Open3D的RGB值范围是0~1,不是0~255。如果你从别的工具导入了0~255的颜色值,记得除以255。
- 截图黑屏:在无头服务器(没有显示器的Linux系统)上,Open3D默认无法渲染。需要安装虚拟显示器,比如
xvfb,或者用headless模式。
好了,这一节的内容就到这里。你现在已经能用Open3D把点云数据“看”明白了。下一节,我们会在这个基础上,开始做标注——给点云里的每个点贴上标签。