4、点云可视化:使用 PCL Visualizer 和 Open3D 可视化原始点云数据

点云可视化,说白了就是给你的激光雷达数据装上一双「眼睛」。

你想想看,我们做滤波、做配准、做分割,每一步处理完,数据到底变成啥样了?光看数字和坐标,脑袋里很难形成直观印象。我个人的习惯是:每做一步处理,必须看一眼可视化结果。这就像炒菜时尝一口咸淡,少了这一步,后面可能全白干。

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,太小了看不清,太大了又显得粗糙。这个值你可以根据数据密度灵活调整。

小技巧:如果你要对比滤波前后的效果,可以创建两个视口(viewport),左右分屏显示。代码里用 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 米,结果点云几乎被滤光了,可视化一看就发现问题了。

注意:Open3D 的 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 Visualizer C++ / 工业级 Open3D Python / 快速原型 可视化结果(交互窗口) 调试 / 验证 / 展示

这张图概括了可视化的核心流程:从原始点云出发,根据你的需求选择 PCL 或 Open3D,最终得到可视化结果用于调试和验证。记住,工具只是手段,目的是让你「看见」数据。

我的建议:刚开始学的时候,两种工具都试试。PCL 让你理解底层渲染逻辑,Open3D 让你快速出效果。等你有经验了,自然知道什么时候该用哪个。

好了,这一章的内容就到这里。可视化是点云处理的基本功,也是你后续学习滤波、配准、分割等算法的重要辅助工具。多练、多看、多对比,慢慢你就能「一眼看出问题」了。

可可精品资料库