librealsense 与 PCL 深度集成实战:基于 RealSense SDK 的点云采集、过滤与可视化指南
2026/9/16 13:35:44 网站建设 项目流程

librealsense 与 PCL 深度集成实战:基于 RealSense SDK 的点云采集、过滤与可视化指南

【免费下载链接】librealsenseRealSense SDK项目地址: https://gitcode.com/GitHub_Trending/li/librealsense

导读

本指南围绕 wrappers/pcl/readme.md 展开,系统讲解如何在 RealSense(librealsense SDK)之上接入PCL(Point Cloud Library,点云库),实现从深度相机原始帧到pcl::PointCloud对象、再到过滤与可视化的完整链路。读完本文,你将掌握两个可直接运行的官方示例(rs-pclrs-pcl-color)的 Windows/Linux 构建方法、核心源码的数据流原理,以及将 RGB 纹理映射到点云、导出.pcd文件的完整实现细节,可直接迁移到自己的点云处理项目中。

一、为什么要在 librealsense 中使用 PCL

librealsense 本身提供了强大的点云生成能力(rs2::pointcloud::calculate()),但点云的后续处理——滤波、分割、特征提取、配准——属于计算机视觉中的通用问题。PCL 恰好是开源生态中最成熟、最常用的点云处理库,两者结合可以复用 PCL 丰富的算法栈,避免重复造轮子。

wrappers/pcl/readme.md 明确指出,该目录下的示例旨在补充现有的 SDK examples,演示 RealSense 相机如何与 PCL 协同工作。仓库为此提供了两个示例,均位于 wrappers/pcl 下:

示例源码位置核心能力
PCL(rs-pcl)wrappers/pcl/pcl/rs-pcl.cpp最小点云查看器,包含 PCL 处理(直通滤波),无颜色
PCL-COLOR(rs-pcl-color)wrappers/pcl/pcl-color/rs-pcl-color.cpp点云查看器,包含 RGB 颜色映射、PCD 文件保存

从源码结构看,两者共享同一套构建体系:wrappers/pcl/CMakeLists.txt 作为父级 CMake 文件,通过add_subdirectory(pcl)add_subdirectory(pcl-color)聚合两个子示例;而该目录是否参与构建,由顶层的BUILD_PCL_EXAMPLES选项控制(见后文构建章节)。

二、Windows 安装与构建

原文档提供了 Windows 下的完整构建流程,这里完整继承并补充关键说明。需要强调:本节并非 PCL 的全面入门教程,而是帮助你快速进入可运行状态。

2.1 安装前置依赖

  1. 从 cmake.org/download 下载并安装CMake(建议使用与 Visual Studio 匹配的新版本)。
  2. 下载 PCL 预编译二进制包。官方渠道包括 pointclouds.org 的 Windows 下载页与 GitHub 的 PCL Releases 页面;针对 Visual Studio 2015/2017 也有社区维护的 PCL 1.8.1 安装包。请务必选择与你的 Visual Studio 版本对应的构建。
  3. 按安装向导完成 PCL 安装,勾选将 PCL 加入系统环境变量:

2.2 配置环境变量

打开命令提示符(Command Prompt),根据安装位宽执行:

:: 32 位版本 set PCL_ROOT="C:\Program Files (x86)\PCL 1.8.1" set PATH=%PATH%;%PCL_ROOT%\bin;%OPENNI2_REDIST%
:: 64 位版本 set PCL_ROOT="C:\Program Files\PCL 1.8.1" set PATH=%PATH%;%PCL_ROOT%\bin;%OPENNI2_REDIST64%

注意OPENNI2_REDIST(或 64 位对应的OPENNI2_REDIST64)是 PCL 自带 OpenNI2 运行库的环境变量,PCL 的点云采集与显示依赖其运行时 DLL。

若 Visual Studio 已经打开,请重启 Visual Studio,确保新的环境变量生效(步骤 5)。

2.3 获取源码并配置 CMake

  1. 将 librealsense 源码克隆或下载到本地目录,例如C:/git/librealsense
  2. 运行cmake-gui,分别填入源代码目录(如C:/git/librealsense)与二进制输出目录,点击Configure
  3. 确认勾选BUILD_SHARED_LIBS。这是关键一步:以静态库方式链接 librealsense 会导致与 PCL 的链接问题(因为 PCL 预编译包按动态链接 /MD 运行时构建,见 CMake/lrs_options.cmake 中该选项的定义)。
  4. 勾选BUILD_PCL_EXAMPLES选项后再次点击Configure

从仓库源码看,BUILD_PCL_EXAMPLES在 CMake/lrs_options.cmake 中定义为option(BUILD_PCL_EXAMPLES "Build PCL examples" OFF),默认关闭;并在 wrappers/CMakeLists.txt 中通过if (BUILD_PCL_EXAMPLES) add_subdirectory(pcl) endif()决定是否编译 PCL 示例。

2.4 生成并运行

  1. 点击Generate生成 Visual Studio 工程,再点击Open Project打开。
  2. 在解决方案资源管理器中,PCL 示例位于Examples → PCL文件夹下(由 wrappers/pcl/pcl/CMakeLists.txt 的set_target_properties(... FOLDER "Examples/PCL")归类)。
  1. 右键任一示例,选择Set as StartUp Project
  2. F5编译并运行:

三、Linux 安装与构建

Linux 下的流程更为简洁:

3.1 安装 PCL

从 PCL 官方 PPA 安装:

sudo add-apt-repository ppa:v-launchpad-jochen-sprickerhof-de/pcl sudo apt-get update sudo apt-get install libpcl-all

3.2 构建 librealsense 并启用 PCL 示例

  1. 按照 doc/installation.md 的指引从源码构建 librealsense。
  2. 在 cmake 命令中添加 PCL 示例开关:
cmake .. -DBUILD_PCL_EXAMPLES=true
  1. 编译完成后,运行示例:
# 未执行 sudo make install 时,直接运行构建产物 ./wrappers/pcl/pcl/rs-pcl # 若已执行 sudo make install,产物已安装到系统 bin 目录 rs-pcl

Debug 配置下的段错误(Seg-Fault)提示:demo 在 Debug 配置下似乎会发生段错误,这是 PCL 的已知问题(与libpcl_surfaceboost::math::lanczos在 Debug 下的行为有关)。规避方法是在 cmake 命令中添加-DCMAKE_BUILD_TYPE=RelWithDebInfo

从源码看,Linux 下两个示例均要求链接 PCL、OpenGL 与 glfw:wrappers/pcl/CMakeLists.txt 中find_package(PCL REQUIRED)find_package(OpenGL),并在 Windows 链接glfw3、其他平台链接glfw。另外rs-pcl-color还额外要求 OpenCV(find_package(OpenCV REQUIRED),见 wrappers/pcl/pcl-color/CMakeLists.txt)。

四、源码剖析:rs-pcl —— 最小 PCL 点云查看器

rs-pcl.cpp 展示了 RealSense 深度帧到 PCL 点云的核心数据流,共分为四步:

4.1 建立 RealSense 数据管线

rs2::pointcloud pc; // 点云计算与纹理映射对象 rs2::points points; // 持久的点集对象,帧丢失时仍可显示上一帧 rs2::pipeline pipe; // 封装实际设备与传感器的管线 pipe.start(); // 使用默认推荐配置开始流

pipe.start()使用默认配置启动深度流,随后pipe.wait_for_frames()获取帧、frames.get_depth_frame()取深度帧,最后pc.calculate(depth)生成点云。

4.2 将 rs2::points 转换为 PCL 点云

核心转换函数points_to_pcl是连接两个库的关键桥接代码:

pcl_ptr points_to_pcl(const rs2::points& points) { pcl_ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); auto sp = points.get_profile().as<rs2::video_stream_profile>(); cloud->width = sp.width(); // 从视频流配置获取宽度 cloud->height = sp.height(); // 获取高度 cloud->is_dense = false; // 深度可能存在空洞,标记为稀疏 cloud->points.resize(points.size()); auto ptr = points.get_vertices(); // 获取顶点数组 for (auto& p : cloud->points) { p.x = ptr->x; p.y = ptr->y; p.z = ptr->z; ptr++; } return cloud; }

要点:points.get_profile()可取得与点云关联的视频流配置,从而获得width/heightpoints.get_vertices()返回原始 XYZ 顶点数组,逐点拷贝到pcl::PointXYZis_dense = false表示点云可能存在无效点(深度空洞),PCL 算法会据此处理。

4.3 应用 PCL 直通滤波(PassThrough)

示例接着用 PCL 的直通滤波器裁剪点云,仅保留 Z 方向 0~1 米的点:

pcl::PassThrough<pcl::PointXYZ> pass; pass.setInputCloud(pcl_points); pass.setFilterFieldName("z"); // 沿 Z 轴过滤 pass.setFilterLimits(0.0, 1.0); // 保留 0 ~ 1 米范围 pass.filter(*cloud_filtered);

随后将原始点云与过滤后点云放入同一个layers向量,供渲染时叠加显示:

std::vector<pcl_ptr> layers; layers.push_back(pcl_points); layers.push_back(cloud_filtered);

4.4 OpenGL 渲染与交互

draw_pointcloud使用固定管线 OpenGL 将两层点云以不同颜色绘制(原始点为红色{0.8, 0.1, 0.3},过滤后为绿色{0.1, 0.9, 0.5}),仅在p.z非零(有效深度)时上传顶点:

for (int i = 0; i < pc->points.size(); i++) { auto&& p = pc->points[i]; if (p.z) { glVertex3f(p.x, p.y, p.z); // 只为有深度数据的点上传顶点 } }

register_glfw_callbacks注册了鼠标左键拖拽旋转(yaw 限幅 ±120°、pitch 限幅 ±80°)、滚轮缩放以及空格键复位视角的交互逻辑,演示了 PCL 点云在 GLFW 窗口中的典型查看交互。

五、源码剖析:rs-pcl-color —— RGB 彩色点云与 PCD 导出

rs-pcl-color.cpp 在上一示例基础上增加了颜色纹理映射PCD 文件保存能力,是 RGB-D 点云采集的完整参考实现。

5.1 彩色点云类型与管线配置

示例使用pcl::PointXYZRGB类型承载 XYZ + RGB 数据:

typedef pcl::PointXYZRGB RGB_Cloud; typedef pcl::PointCloud<RGB_Cloud> point_cloud;

管线显式启用颜色、红外与深度三条流,并获取深度传感器以控制激光发射器:

cfg.enable_stream(RS2_STREAM_COLOR); cfg.enable_stream(RS2_STREAM_INFRARED); cfg.enable_stream(RS2_STREAM_DEPTH); rs2::pipeline_profile selection = pipe.start(cfg); auto depth_sensor = selected_device.first<rs2::depth_sensor>();

5.2 发射器与激光功率控制

示例在采集前对深度传感器做了一次“预热-关闭”序列,以确保自动曝光稳定:

if (depth_sensor.supports(RS2_OPTION_EMITTER_ENABLED)) { depth_sensor.set_option(RS2_OPTION_EMITTER_ENABLED, 1.f); // 开启发射器 pipe.wait_for_frames(); depth_sensor.set_option(RS2_OPTION_EMITTER_ENABLED, 0.f); // 关闭发射器 } if (depth_sensor.supports(RS2_OPTION_LASER_POWER)) { auto range = depth_sensor.get_option_range(RS2_OPTION_LASER_POWER); depth_sensor.set_option(RS2_OPTION_LASER_POWER, range.max); // 最大激光功率 sleep(1); depth_sensor.set_option(RS2_OPTION_LASER_POWER, 0.f); // 关闭激光 }

get_option_range()可查询选项的取值范围,这里先拉满激光功率再归零,属于典型的硬件唤醒/曝光稳定手法。

5.3 RGB 纹理映射的核心算法

RGB_Texture函数完成「纹理坐标 → 像素索引 → RGB 值」的映射,是彩色点云的关键:

std::tuple<int, int, int> RGB_Texture(rs2::video_frame texture, rs2::texture_coordinate Texture_XY) { int width = texture.get_width(); int height = texture.get_height(); // 法线坐标转纹理坐标,并做边界裁剪 int x_value = min(max(int(Texture_XY.u * width + .5f), 0), width - 1); int y_value = min(max(int(Texture_XY.v * height + .5f), 0), height - 1); int bytes = x_value * texture.get_bytes_per_pixel(); // 像素字节偏移 int strides = y_value * texture.get_stride_in_bytes(); // 行字节偏移 int Text_Index = bytes + strides; const auto New_Texture = reinterpret_cast<const uint8_t*>(texture.get_data()); int NT1 = New_Texture[Text_Index]; // R int NT2 = New_Texture[Text_Index + 1]; // G int NT3 = New_Texture[Text_Index + 2]; // B return std::tuple<int, int, int>(NT1, NT2, NT3); }

RealSense 点云中每个顶点都带有一个归一化纹理坐标texture_coordinate(u、v ∈ [0,1]),将该坐标乘以帧宽高即可换算回像素位置,进而从get_data()的原始缓冲区中读取颜色字节。

PCL_Conversion则逐点组合 XYZ 与 RGB,并处理了相机的BGR 顺序

// 映射颜色(注意相机模型为 BGR 顺序) cloud->points[i].r = get<2>(RGB_Color); cloud->points[i].g = get<1>(RGB_Color); cloud->points[i].b = get<0>(RGB_Color);

同时将彩色帧通过pc.map_to(RGB)绑定给点云计算对象,pc.calculate(depth)后即可从points.get_texture_coordinates()取到逐点纹理坐标。

5.4 交互式采集与 PCD 保存

主循环等待用户输入y/Y(采集一帧并保存)或n/N(退出),采集前丢弃 30 帧以等待自动曝光稳定:

for (int i = 0; i < 30; i++) { auto frames = pipe.wait_for_frames(); // 丢弃若干帧等待自动曝光 }

过滤后点云(同样保留 Z 0~1 米)通过 ASCII 格式写入 PCD 文件:

cloudFile = "Captured_Frame" + to_string(i) + ".pcd"; pcl::io::savePCDFileASCII(cloudFile, *cloud);

之后Load_PCDFilepcl::io::loadPCDFile重新读回该文件,并交给pcl::visualization::PCLVisualizer(黑色背景、点大小 1)进行可视化,按Q键返回继续采集。每次保存的文件名带递增序号,形成Captured_Frame1.pcdCaptured_Frame2.pcd…… 的序列。

下图是该示例的典型输出(经直通滤波保留 1 米内点、导出为 PCD 后的彩色点云渲染结果):

六、CMake 构建体系与依赖解析

两个示例的 CMake 配置清晰反映了其依赖关系:

  • wrappers/pcl/CMakeLists.txt:父级文件,find_package(PCL REQUIRED)查找 PCL,find_package(OpenGL)校验 OpenGL,Windows 链接glfw3、其他平台链接glfw,并将realsense2与 PCL/OpenGL 库一起追加到DEPENDENCIES,最后聚合两个子目录。
  • wrappers/pcl/pcl/CMakeLists.txt:生成rs-pcl可执行文件,强制CXX_STANDARD 11,并做/MT → /MD的编译标志替换(保证与 PCL 预编译包的运行时一致);若未找到外部 glfw,则回退使用仓库自带 third-party/glfw 的头文件与构建产物。
  • wrappers/pcl/pcl-color/CMakeLists.txt:生成rs-pcl-color,额外find_package(OpenCV REQUIRED)并链接${OpenCV_LIBS},同时链接${PCL_COMMON_LIBRARIES}${PCL_IO_LIBRARIES}(用于 PCD 读写)。

顶层开关BUILD_PCL_EXAMPLES默认关闭(见 CMake/lrs_options.cmake),启用后由 wrappers/CMakeLists.txt 引入本目录。因此构建命令需要显式开启:

cmake .. -DBUILD_PCL_EXAMPLES=true -DCMAKE_BUILD_TYPE=RelWithDebInfo

七、常见问题与工程实践建议

  1. Debug 配置段错误:如原文档所述,Demo 在 Debug 构建下可能因 PCL 的已知问题段错误,推荐使用RelWithDebInfo构建类型。
  2. 静态链接冲突:务必保持BUILD_SHARED_LIBS=ON,静态链接 librealsense 会与 PCL 的链接方式冲突。
  3. OpenCV 缺失rs-pcl-color强依赖 OpenCV,编译前需确保find_package(OpenCV)可找到;若仅需纯点云查看,可只编译rs-pcl
  4. 过滤参数可调:两个示例的直通滤波均写死为 Z 0~1 米(rs-pcl.cpp、rs-pcl-color.cpp),实际项目中可依据场景调整setFilterLimits,或将过滤结果作为后续 PCL 分割、配准等算法的输入。
  5. PCD 导出savePCDFileASCII适合调试与互操作;数据量大时可改用二进制格式(savePCDFileBinary)以提升读写性能。

结语

本文以 wrappers/pcl/readme.md 为主线,完整还原了rs-pclrs-pcl-color两个示例的安装、构建与运行流程,并结合 rs-pcl.cpp 与 rs-pcl-color.cpp 的源码,剖析了从 RealSense 深度帧到 PCL 点云、再到颜色映射与 PCD 导出的完整数据链路。无论是快速验证硬件,还是作为自研点云处理管线的起点,这两个示例都提供了可直接复用的参考实现——你可以在其基础上替换 PCL 的滤波、分割、配准等算法,构建更完整的 RGB-D 处理系统。

【免费下载链接】librealsenseRealSense SDK项目地址: https://gitcode.com/GitHub_Trending/li/librealsense

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询