4. 点云可视化
点云可视化,说白了就是给你的激光雷达数据装上一双「眼睛」。
你想想看,我们做滤波、做配准、做分割,每一步处理完,数据到底变成啥样了?光看数字和坐标,脑袋里很难形成直观印象。我个人的习惯是:每做一步处理,必须看一眼可视化结果。这就像炒菜时尝一口咸淡,少了这一步,后面可能全白干。
4.1 为什么需要可视化?
我在项目中遇到过不少同学,算法跑得飞起,结果一可视化发现点云全是噪点。嗯,这种情况其实很常见。可视化能帮你快速发现三个核心问题:
- 数据是否完整:雷达有没有丢帧?视野有没有遮挡?
- 滤波效果是否合理:地面点有没有被误删?离群点有没有被保留?
- 参数是否调对:体素大小、半径阈值,这些参数调完到底长啥样?
说白了,可视化就是你的调试「照妖镜」。
4.2 PCL Visualizer 实战
PCL 自带的可视化工具,我用了好多年。它轻量、直接,适合快速查看点云。
4.2.1 基础可视化代码
先来个最简单的例子,把一帧点云显示出来:
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/io/pcd_io.h>
int main() {
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile("input.pcd", *cloud);
pcl::visualization::CloudViewer viewer("Simple Cloud Viewer");
viewer.showCloud(cloud);
while (!viewer.wasStopped()) {
// 保持窗口打开
}
return 0;
}
这段代码很简单,但有个坑——窗口会一闪而过。我曾经第一次跑的时候,以为代码写错了,查了半天才发现是没加 while 循环。嗯,这里要注意。
4.2.2 更灵活的方式:PCLVisualizer
如果你需要更精细的控制,比如添加坐标轴、调整颜色、多视角对比,那就用 pcl::visualization::PCLVisualizer:
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
viewer->setBackgroundColor(0, 0, 0); // 黑色背景
// 添加点云,并设置颜色
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> color_handler(cloud, 255, 0, 0);
viewer->addPointCloud(cloud, color_handler, "cloud");
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cloud");
// 添加坐标轴
viewer->addCoordinateSystem(1.0);
while (!viewer->wasStopped()) {
viewer->spinOnce(100);
}
我个人习惯把点云大小设为 2 或 3,太小了看不清,太大了又显得粗糙。这个值你可以根据数据密度灵活调整。
viewer->createViewPort() 就能实现。
4.3 Open3D 可视化实战
Open3D 是后来才火起来的工具,但说实话,它的可视化体验比 PCL 好不少。交互更流畅,鼠标拖拽、缩放都很顺滑。
4.3.1 基础可视化
import open3d as o3d
# 读取点云
pcd = o3d.io.read_point_cloud("input.pcd")
print(pcd)
# 可视化
o3d.visualization.draw_geometries([pcd], window_name="Open3D Viewer",
width=800, height=600,
point_show_normal=False)
就这么几行,点云就出来了。你想想看,PCL 里要写几十行才能达到同样的交互效果。Open3D 默认就支持鼠标旋转、缩放、平移,非常方便。
4.3.2 高级可视化技巧
我在项目中经常需要同时显示多帧点云,或者叠加显示滤波前后的结果。Open3D 的 draw_geometries 支持传入列表:
# 读取原始点云和滤波后的点云
pcd_raw = o3d.io.read_point_cloud("raw.pcd")
pcd_filtered = o3d.io.read_point_cloud("filtered.pcd")
# 给滤波后的点云上色(红色)
pcd_filtered.paint_uniform_color([1, 0, 0])
# 同时显示
o3d.visualization.draw_geometries([pcd_raw, pcd_filtered])
这里有个细节:原始点云默认是白色,滤波后的点云我涂成红色。这样一眼就能看出哪些点被保留了,哪些被去掉了。我曾经用这个技巧快速定位了一个参数调错的问题——当时体素滤波的叶子大小设成了 1 米,结果点云几乎被滤光了,可视化一看就发现问题了。
draw_geometries 是阻塞函数,会卡住程序直到你关闭窗口。如果你需要在循环中实时更新点云,请使用 draw_geometries_with_animation_callback 或 draw_geometries_with_key_callbacks。
4.4 两种工具对比
我整理了一个表格,方便你快速选择:
| 特性 | PCL Visualizer | Open3D |
|---|---|---|
| 语言 | C++ | Python / C++ |
| 交互流畅度 | 一般 | 优秀 |
| 代码量 | 较多 | 较少 |
| 自定义能力 | 强(可深度定制) | 中等(够用) |
| 适合场景 | 工业级、嵌入式 | 快速原型、科研 |
我个人建议:做算法验证和调试时用 Open3D,效率高;做最终产品集成时用 PCL,因为 C++ 性能更好,且与 ROS 等框架集成更紧密。
4.5 可视化避坑指南
最后分享几个我踩过的坑:
- 点云太大导致卡死:我曾经加载一个 1 亿点的 PCD 文件,Open3D 直接崩了。解决办法是先下采样,或者只显示部分点。
- 颜色显示异常:PCL 默认的颜色范围是 0-255,Open3D 是 0-1。如果你混用两个库,颜色值一定要转换。
- 窗口无法关闭:PCL 的
spinOnce如果没加延时,CPU 会跑满,窗口也关不掉。加个std::this_thread::sleep_for就能解决。
这张图概括了可视化的核心流程:从原始点云出发,根据你的需求选择 PCL 或 Open3D,最终得到可视化结果用于调试和验证。记住,工具只是手段,目的是让你「看见」数据。
好了,这一章的内容就到这里。可视化是点云处理的基本功,也是你后续学习滤波、配准、分割等算法的重要辅助工具。多练、多看、多对比,慢慢你就能「一眼看出问题」了。
可可精品资料库