在 PCL 点云库中,PCLVisualizer
是建立在 VTK(Visualization Toolkit) 之上的 3D 可视化引擎,这也就是Qt+VTK+PCL联合的底层逻辑。PCL点云库通过 PCLVisualizer
提供的封装接口,用户可以实现基于事件的 交互操作、拾取响应、视角控制 等高级可视化需求(如展示点云、几何图形、标注文本等,并且支持与用户交互)。同时,它也允许直接使用底层 VTK 对象来自定义交互样式与行为。PCLVisualizer
是PCL点云可视化和交互的核心类之一,可以用于 3D 渲染、点云的颜色设置、缩放、旋转等操作。下面先对PCLVisualizer
的基本应用进行讲解。
1、PCLVisualizer 基本功能概述
- 点云显示:可以通过
PCLVisualizer
显示点云数据,支持不同的显示样式(如球体、点、平面等)。
viewer->addPointCloud<pcl::PointXYZ>(cloud, "cloud_id");
点云更新(动态刷新)
viewer->updatePointCloud(cloud, "cloud_id");
- 支持多种几何体渲染:除了点云,还可以渲染其他几何体,如线条、平面、立方体、轴等。
用于可视化辅助线、坐标轴等结构,如下表。
图元 | 示例函数 |
---|---|
坐标轴 | addCoordinateSystem() |
线段 | addLine() |
球体 | addSphere() |
平面 | addPlane() |
多边形 | addPolygon() |
- 交互支持:允许用户通过鼠标操作进行旋转、缩放、平移等交互。
- 鼠标点选:
registerPointPickingCallback
- 框选:
registerAreaPickingCallback
- 键盘事件:
registerKeyboardCallback
- 鼠标移动/点击事件:通过 VTK 扩展实现(需继承
vtkInteractorStyle
) - 摄像机视角控制
viewer->setCameraPosition(
0, 0, -3, // 相机位置
0, 0, 0, // 视点中心
0, -1, 0); // 相机“上”方向
- 点选拾取(交互功能)
viewer->registerPointPickingCallback(
[](const pcl::visualization::PointPickingEvent& event, void*) {
float x, y, z;
event.getPoint(x, y, z);
std::cout << "Picked point: " << x << ", " << y << ", " << z << std::endl;
});
- 支持颜色和样式设置:可以设置点云的颜色、大小以及其它可视化样式。设置点云渲染属性示例如下:
viewer->setPointCloudRenderingProperties(
pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "cloud_id");
viewer->setPointCloudRenderingProperties(
pcl::visualization::PCL_VISUALIZER_COLOR, 1.0, 0.0, 0.0, "cloud_id"); // RGB
- 多窗口支持:
PCLVisualizer
可以在同一个窗口中显示多个视图(例如多个视角)。
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1);
viewer->createViewPort(0.5, 0.0, 1.0, 1.0, v2);
viewer->addPointCloud(cloud1, "cloud1", v1);
viewer->addPointCloud(cloud2, "cloud2", v2);
- 保存截图
viewer->saveScreenshot("screenshot.png");
2、 PCLVisualizer 主要方法介绍
1. 初始化和设置
- 构造函数:
PCLVisualizer
构造函数用于创建一个可视化器实例。pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer ("PCL Viewer"));
2. 添加点云
-
addPointCloud
:将点云数据添加到可视化器。viewer->addPointCloud(cloud, "cloud");
- 第一个参数是点云数据(例如
pcl::PointCloud<pcl::PointXYZ>::Ptr
)。 - 第二个参数是点云的标识符,用于在可视化器中区分不同的点云。
- 第一个参数是点云数据(例如
-
setPointCloudRenderingProperties
:设置点云的渲染属性(例如点的大小、颜色等)。viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "cloud"); viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 1.0, 0.0, "cloud"); // 设置颜色为绿色
3. 添加几何体
-
addLine
:添加一条直线。viewer->addLine<pcl::PointXYZ>(start_point, end_point, "line");
-
addCube
:添加一个立方体。viewer->addCube(min_point, max_point, "cube");
-
addText
:添加文本标注。viewer->addText("Point Cloud", 10, 10, "text");
4. 交互功能
-
spin
:启动可视化器并开始交互模式,用户可以使用鼠标进行旋转、缩放等操作。viewer->spin();
-
spinOnce
:在没有用户交互时更新可视化器,这通常用于需要不断更新显示内容的应用场景。viewer->spinOnce();
5. 视角设置
-
resetCamera
:重置视角,使得点云能够自适应显示。viewer->resetCamera();
-
setCameraPosition
:设置视角的位置、方向和上下方向。viewer->setCameraPosition(0, 0, -10, 0, -1, 0);
6. 窗口管理
createViewPort
:创建一个新的视口,支持多个视图窗口。int vp1, vp2; viewer->createViewPort(0.0, 0.0, 0.5, 1.0, vp1); // 第一个视口 viewer->createViewPort(0.5, 0.0, 1.0, 1.0, vp2); // 第二个视口
示例代码:使用 PCLVisualizer 显示点云综合示例
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <iostream>
// 点云类型定义
using PointT = pcl::PointXYZ;
using PointCloudT = pcl::PointCloud<PointT>;
int main(int argc, char** argv) {
// 创建指针和点云实例
PointCloudT::Ptr cloud(new PointCloudT);
// 读取点云文件(PCD格式)
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " <pcd-file>" << std::endl;
return -1;
}
if (pcl::io::loadPCDFile<PointT>(argv[1], *cloud) == -1) {
PCL_ERROR("Couldn't read PCD file\n");
return -1;
}
std::cout << "Loaded " << cloud->size() << " points from " << argv[1] << std::endl;
// 创建PCLVisualizer指针,窗口标题为"3D Viewer"
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
// 设置背景颜色(黑色)
viewer->setBackgroundColor(0, 0, 0);
// 添加点云到视图,点云标识符为"sample cloud"
viewer->addPointCloud<PointT>(cloud, "sample cloud");
// 设置点云渲染属性:点大小为2
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "sample cloud");
// 添加坐标系,坐标系大小为1.0
viewer->addCoordinateSystem(1.0);
// 初始化相机参数
viewer->initCameraParameters();
// 注册键盘事件回调,按下 'q' 键时关闭窗口
viewer->registerKeyboardCallback(
[&](const pcl::visualization::KeyboardEvent& event, void*) {
if (event.keyDown() && event.getKeySym() == "q") {
std::cout << "Q pressed. Exiting..." << std::endl;
viewer->close();
}
});
// 注册点选拾取回调,点击点云打印坐标
viewer->registerPointPickingCallback(
[&](const pcl::visualization::PointPickingEvent& event, void*) {
float x, y, z;
if (event.getPoint(x, y, z)) {
std::cout << "Picked point coordinates: (" << x << ", " << y << ", " << z << ")" << std::endl;
}
});
// 主渲染循环,直到关闭窗口
while (!viewer->wasStopped()) {
viewer->spinOnce(100);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
return 0;
}
结果展示:
代码解析:
- 创建一个点云对象
cloud
,并给它填充一些简单的点。 - 使用
PCLVisualizer
创建一个可视化器实例。 - 使用
addPointCloud
将点云添加到可视化器中,显示的点云标识符是"cloud"
。 - 使用
setPointCloudRenderingProperties
设置点云的点大小和颜色。 - 使用
spin
启动可视化,并允许用户进行交互。
常见问题和注意事项
- 性能问题:当点云非常大时,渲染速度可能会受到影响,尤其是在处理数百万点时。可以通过简化点云或使用点云下采样技术来提高性能。
- 多个视口:可以使用
createViewPort
来创建多个视口,并在同一个窗口中显示不同的点云视图。 - 交互功能:
spin
是一个阻塞函数,会一直等待用户的交互。如果需要非阻塞模式,可以使用spinOnce
来轮询更新可视化。 - 颜色和样式设置:除了
setPointCloudRenderingProperties
,还可以为其他几何对象(如线条、立方体)设置样式,具体取决于应用需求。
3、PCLVisualizer 类中与 **VTK 交互器(Interactor)的成员函数和变量
在 PCLVisualizer
类中,与 VTK 交互器(Interactor) 相关的成员函数和变量主要用于实现 交互控制,比如点云的旋转、缩放、拾取等操作。这些接口是 PCL 点云库封装了 VTK 的关键部分,但是PCL点云库允许开发者使用 VTK 直接操作底层,这部分内容我们会在Qt+PCL+VTK联合开发中就会应用到,因此了解此部分相关内容是非常有必要。
1、关键背景
在 PCL 中,PCLVisualizer
是基于 VTK 封装的 3D 可视化类,其背后使用了:
vtkRenderWindow
:显示渲染图像。vtkRenderWindowInteractor
:处理用户输入(鼠标/键盘)。vtkInteractorStyle
/PCLVisualizerInteractorStyle
:定义用户交互行为,如旋转/拾取等。
2、成员函数详解(与 Interactor 相关)
1. createInteractor()
void createInteractor();
- 作用:内部创建一个
vtkRenderWindowInteractor
实例(智能指针interactor_
)。 - 调用时机:初始化或用户未手动指定交互器时自动调用。
2. setupInteractor(vtkRenderWindowInteractor*, vtkRenderWindow*)
void setupInteractor(vtkRenderWindowInteractor* iren,
vtkRenderWindow* win);
- 作用:为
iren
设置默认的 PCL 交互样式PCLVisualizerInteractorStyle
并绑定win
。 - 使用场景:快速搭建 PCL 默认交互系统。
3. setupInteractor(vtkRenderWindowInteractor*, vtkRenderWindow*, vtkInteractorStyle*)
void setupInteractor(vtkRenderWindowInteractor* iren,
vtkRenderWindow* win,
vtkInteractorStyle* style);
- 作用:允许用户传入自定义的交互样式
style
。 - 用途:高级用户自定义操作(如拾取、框选、特殊事件)。
4. getInteractorStyle()
inline vtkSmartPointer<PCLVisualizerInteractorStyle> getInteractorStyle();
- 作用:获取当前使用的交互样式。
- 常用场景:手动修改交互行为,例如绑定快捷键、扩展事件处理。
3、成员变量详解
1. interactor_
vtkSmartPointer<vtkRenderWindowInteractor> interactor_;
- 说明:内部交互器对象,驱动渲染和用户交互。
- 用途:自动处理用户事件,触发交互样式。
2. style_
vtkSmartPointer<PCLVisualizerInteractorStyle> style_;
-
说明:PCL 定义的自定义交互样式类,继承自
vtkInteractorStyleTrackballCamera
。 -
功能扩展:
- 点云拾取事件处理。
- 快捷键响应(如 ‘r’ 重置视图)。
- 鼠标拖动、滚轮等行为定义。
4、常见使用流程(伪代码示意)
pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
// 使用默认交互器
viewer->createInteractor(); // 创建 interactor_
viewer->setupInteractor(viewer->getInteractor(), viewer->getRenderWindow());
// 获取交互样式,自定义行为
auto style = viewer->getInteractorStyle();
style->setKeyboardCallback(...);
5、实战建议
使用目标 | 推荐接口 |
---|---|
使用默认交互控制 | createInteractor() + setupInteractor(...) |
自定义鼠标/键盘事件响应 | getInteractorStyle() 并设置回调 |
替换为自定义交互风格 | setupInteractor(..., custom_style) |
手动集成 Qt + VTK 控件 | 使用 getRenderWindow() + getInteractor() 绑定到 Qt 容器 |
4、总结
pcl::visualization::PCLVisualizer
是 PCL 提供的功能强大的点云可视化工具,适用于各种 3D 点云数据展示和交互。它支持点云、几何体的渲染和自定义视角设置,且能够实现交互式操作,非常适合用于科研和开发中对点云数据的展示和分析。
至此完成第11讲的内容,欢迎喜欢朋友的关注订阅!