3. 点云可视化:让数据“看得见”
点云可视化,说白了就是给你的激光雷达数据“拍张照”。
我刚开始做点云处理时,总觉得算法调好了就行,可视化可有可无。结果有一次调试滤波参数,死活看不出效果差异,折腾了两天才发现是参数写反了。嗯,从那以后,我再也不敢跳过可视化这一步。
这一节,我们聊聊三个最常用的可视化工具:PCL 的 pcl_viewer、Open3D 的 draw_geometries,以及点云渲染的几种实用技巧。
3.1 PCL 可视化工具:pcl_viewer
PCL 自带一个轻量级可视化工具,叫 pcl_viewer。它是个命令行工具,不需要写代码就能看点云。
用法很简单:
pcl_viewer point_cloud.pcd
窗口弹出来,你就能看到点云了。鼠标左键旋转,右键平移,滚轮缩放。这些操作和大多数 3D 软件差不多,上手很快。
我个人习惯用 pcl_viewer 做快速预览。比如刚采集完数据,先看一眼点云长什么样,有没有明显噪点,地面是不是平的。这些信息几秒钟就能判断出来。
pcl_viewer original.pcd filtered.pcd
两个点云会叠加显示,用不同颜色区分。
如果你想在代码里用 PCL 的可视化功能,那就得用 pcl::visualization::PCLVisualizer 类。下面是个简单例子:
#include <pcl/visualization/pcl_visualizer.h>
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("点云显示"));
viewer->addPointCloud(cloud, "cloud");
viewer->spin();
这段代码会创建一个窗口,显示你的点云。注意 spin() 会阻塞程序,直到你关闭窗口。如果你不想阻塞,可以用 spinOnce()。
3.2 Open3D 可视化:draw_geometries
Open3D 的可视化接口更 Pythonic,用起来很舒服。核心函数就一个:draw_geometries。
import open3d as o3d
pcd = o3d.io.read_point_cloud("point_cloud.pcd")
o3d.visualization.draw_geometries([pcd])
就这么三行,点云就出来了。Open3D 的交互方式和 PCL 类似,但界面更现代,操作更流畅。
我记得有一次做项目,需要同时显示点云和对应的轨迹。用 Open3D 很容易实现:
# 显示点云和轨迹
lines = o3d.geometry.LineSet()
lines.points = o3d.utility.Vector3dVector(trajectory_points)
lines.lines = o3d.utility.Vector2iVector(line_indices)
o3d.visualization.draw_geometries([pcd, lines])
你想想看,点云和轨迹叠在一起,数据关系一目了然。这种直观性,是看数字永远比不了的。
3.3 点云渲染:颜色映射、强度渲染、高度渲染
点云默认是白色的,但我们可以给它上色,让信息更丰富。常用的渲染方式有三种。
3.3.1 颜色映射
如果点云本身带有 RGB 信息(比如用相机采集的),直接显示颜色就行。PCL 和 Open3D 都支持:
# Open3D 显示彩色点云
pcd = o3d.io.read_point_cloud("colored.pcd")
o3d.visualization.draw_geometries([pcd])
但很多时候,点云没有颜色。这时候我们可以根据某个属性(比如强度、高度)来映射颜色。
3.3.2 强度渲染
激光雷达每个点都有强度值,反映的是目标反射的激光能量。强度高的点(比如路牌、白线)会更亮,强度低的点(比如黑色路面)会更暗。
在 PCL 中,强度渲染可以这样设置:
pcl::visualization::PCLVisualizer viewer;
viewer.addPointCloud(cloud, "cloud");
viewer.setPointCloudRenderingProperties(
pcl::visualization::PCL_VISUALIZER_COLOR, 1.0, 0.0, 0.0, "cloud");
不过更常见的做法是用强度值直接控制颜色。Open3D 里可以这样:
# 强度渲染
intensities = np.asarray(pcd.points)[:, 0] # 假设强度存在第一个通道
colors = plt.cm.jet(intensities / intensities.max())[:, :3]
pcd.colors = o3d.utility.Vector3dVector(colors)
o3d.visualization.draw_geometries([pcd])
3.3.3 高度渲染
高度渲染是最直观的。把点的高度(Z 值)映射成颜色,低处用蓝色,高处用红色。这样一眼就能看出地形起伏。
我曾经用高度渲染做过一个项目,需要快速识别道路上的障碍物。高度渲染一开,路面上凸起的物体(比如路肩、石块)立刻变成红色,非常显眼。
Open3D 实现高度渲染:
# 高度渲染
points = np.asarray(pcd.points)
z = points[:, 2]
z_min, z_max = z.min(), z.max()
colors = plt.cm.viridis((z - z_min) / (z_max - z_min))[:, :3]
pcd.colors = o3d.utility.Vector3dVector(colors)
o3d.visualization.draw_geometries([pcd])
这里用了 viridis 色图,它是感知均匀的,不会误导视觉判断。我个人推荐用 viridis 或 plasma,比 jet 更科学。
3.4 交互式可视化:旋转、缩放、选择
可视化不只是“看”,还要“交互”。
旋转和缩放是基本功。PCL 和 Open3D 都支持鼠标拖拽旋转、滚轮缩放。但有个细节要注意:
- PCL: 左键旋转,中键缩放,右键平移。按住 Shift 可以切换旋转中心。
- Open3D: 左键旋转,滚轮缩放,Ctrl+左键平移。按 R 键重置视角。
选择功能更高级。比如你想选中点云中的某个区域,提取出来做分析。Open3D 提供了矩形选择工具:
# 交互式选择
vis = o3d.visualization.VisualizerWithEditing()
vis.create_window()
vis.add_geometry(pcd)
vis.run() # 用户交互选择
picked_points = vis.get_picked_points() # 获取选中的点索引
运行这段代码后,按住 Ctrl 键,用鼠标框选点云区域,选中的点会变红。关闭窗口后,picked_points 就是选中点的索引列表。
PCL 也有类似的选择功能,用 pcl::visualization::PointPickingEvent 实现。不过接口比 Open3D 复杂一些,适合有 C++ 基础的同学。
3.5 小结
可视化是点云处理的“眼睛”。没有它,你就是在盲调参数。
我个人建议:
- 快速预览用 pcl_viewer 命令行
- 算法调试用 Open3D 的 draw_geometries
- 信息展示用高度渲染或强度渲染
- 数据提取用交互式选择工具
下一节,我们聊聊点云滤波。你会发现,可视化在滤波调试中同样不可或缺。
公众号:蓝海资料掘金营,微信deep3321