RealSense D435i 与 librealsense SDK:从测距到深度滤波的实践手册
【免费下载链接】librealsenseRealSense SDK项目地址: https://gitcode.com/GitHub_Trending/li/librealsense
librealsense 是 Intel RealSense 深度相机的官方 SDK,D435i 是其带 6 轴 IMU 的立体深度机型。它把深度流、RGB 流与惯性数据统一在一套 pipeline API 下,适合要写机器人避障、三维测量、SLAM 前置模块的 C/C++ 开发者。
能力速览
| 项 | 内容 |
|---|---|
| 深度流 | 立体双目 + 红外投影,典型工作距离 0.3 m 至 6 m,最高 1280×720@90fps |
| RGB 流 | 独立彩色摄像头,可与深度对齐到同一视口 |
| IMU | 加速度计 + 陀螺仪,每个样本携带深度传感器硬件时钟时间戳,天然可与深度帧对齐 |
| 后处理 | 降采样、空间、时间、空洞填充等独立滤镜块,可任意串联 |
| 录制回放 | 内建 recorder / playback 设备,采集一次可离线复现 |
| 不适合 | 纯 2D 视觉检测场景(直接用彩色摄像头即可);超长距离激光级测距;虚拟机内使用(官方不支持 USB 3.0 透传) |
三步装好 SDK 并跑通第一帧
Ubuntu 20/22/24 LTS 的流程是:装依赖、补 udev 规则、打内核补丁、cmake 构建。内核补丁必须做,否则深度流不稳定。
git clone https://gitcode.com/GitHub_Trending/li/librealsense cd librealsense ./scripts/setup_udev_rules.sh ./scripts/patch-realsense-ubuntu-lts-hwe.sh mkdir build && cd build cmake .. -DBUILD_EXAMPLES=true -DCMAKE_BUILD_TYPE=Release && make -j$(nproc) && sudo make install装完用rs-enumerate-devices确认设备在列。最小程序 10 行以内就能读距离,仓库内完整示例在 examples/hello-realsense/:
#include <librealsense2/rs.hpp> rs2::pipeline pipe; rs2::config cfg; cfg.enable_stream(RS2_STREAM_DEPTH); pipe.start(cfg); while (true) { auto depth = pipe.wait_for_frames().get_depth_frame(); // 单位米;无效像素返回 0 std::cout << depth.get_distance(depth.get_width() / 2, depth.get_height() / 2) << " m\n"; }wait_for_frames()阻塞到帧到齐,get_distance(x, y)已把单位换算好,返回米。要拿原始毫米值就自己读get_data()并乘以RS2_OPTION_DEPTH_UNITS。
核心用法
测距与两点距离
单点距离用get_distance即可。两点间的真实三维距离要先反投影到 3D 再算欧氏距离,仓库里的 examples/measure/ 做了完整的可拖拽标尺实现,关键就三步:
rs2_intrinsics intr = depth.get_profile() .as<rs2::video_stream_profile>().get_intrinsics(); float px[2], p3d[3]; rs2_deproject_pixel_to_point(p3d, &intr, px, dist); // 两个像素各做一次,再对 p3d 求欧氏距离深度滤波参数怎么调
官方推荐链路与各滤镜参数如下,完整可交互示例在 examples/post-processing/,说明文档见 doc/post-processing-filters.md:
| 滤镜 | 作用 | 关键选项 | 取值 / 默认 |
|---|---|---|---|
| decimation | 降采样,顺手补小洞 | RS2_OPTION_FILTER_MAGNITUDE | 2–8,默认 2 |
| disparity_transform | 转视差域再滤波,远处噪声更均匀 | 构造参数true/false | — |
| spatial | 保边平滑 | RS2_OPTION_FILTER_SMOOTH_ALPHA/RS2_OPTION_FILTER_SMOOTH_DELTA | 0.25–1 默认 0.5;1–50 默认 20 |
| temporal | 时间降噪,依赖历史帧,动态场景会拖影 | RS2_OPTION_FILTER_SMOOTH_ALPHA/RS2_OPTION_FILTER_SMOOTH_DELTA | 默认 0.4 / 20 |
| hole_filling | 用四邻补无效像素 | RS2_OPTION_HOLE_FILLING | 0–2,默认 1(取最远邻) |
rs2::decimation_filter dec; rs2::spatial_filter spat; rs2::temporal_filter temp; spat.set_option(RS2_OPTION_FILTER_SMOOTH_DELTA, 20); rs2::frame out = depth; out = dec.process(out); out = spat.process(out); out = temp.process(out);注意:滤镜对象在多线程间共享状态,每台设备维护一条滤镜链;temporal 换帧源会丢失历史,效果直接失效。
多流同步:深度加 IMU
深度、RGB 由 pipeline 自动打包进同一个frameset;IMU 帧率远高于视频,走单帧通道。用first_or_default按流类型取帧即可:
rs2::config cfg; cfg.enable_stream(RS2_STREAM_GYRO); cfg.enable_stream(RS2_STREAM_ACCEL); pipe.start(cfg); while (true) { auto set = pipe.wait_for_frames(); if (auto g = set.first_or_default(RS2_STREAM_GYRO)) rs2_vector v = g.get_motion_data(); // 角速度 rad/s if (auto a = set.first_or_default(RS2_STREAM_ACCEL)) // a.get_motion_data() 静止时 y 分量约 -9.8 }IMU 样本时间戳与深度帧同一时钟,取frame.get_timestamp()相减就是真实时间差,做运动补偿不需要校时。需要自定义多流合流规则时用rs2::syncer构造回调,把pipe.start(syncer)的回调接到队列上;低延迟场景整体换成回调模式,参考 examples/callback/。
生成点云
rs2::pointcloud pc; pc.map_to(color); // 贴彩色纹理 auto points = pc.calculate(depth); // points.get_vertices() 每 3 个 float 一个点完整渲染版在 examples/pointcloud/。生成点云前先对齐,rs2::align的构造是重操作,放在主循环外:
rs2::align align_to_depth(RS2_STREAM_DEPTH); rs2::frameset out = align_to_depth.process(set);对齐是合成视口,会引入采样和遮挡伪影,examples/align/ 有双向对齐的可视化对比。
调优与进阶
按这个顺序调,收益从高到低:
- 分辨率与帧率。CPU 不够就降深度分辨率或帧率,别先加滤镜——滤镜是 CPU 开销大户。
- 滤镜链路。CPU 吃紧时只开 decimation + spatial;追求平面平滑度再叠 temporal;边缘毛刺多就把 spatial 的
RS2_OPTION_FILTER_SMOOTH_DELTA调大(默认 20,上限 50),空洞多再上 hole_filling。 - 视觉预设。D400 系列支持
RS2_OPTION_VISUAL_PRESET,测距场景直接切高精度档:
auto sensor = pipe.get_active_profile().get_device() .first<rs2::depth_sensor>(); sensor.set_option(RS2_OPTION_VISUAL_PRESET, RS2_RS400_VISUAL_PRESET_HIGH_ACCURACY);- 高级模式。
rs400::advanced_mode暴露约百个硬件参数,可save_json/load_json序列化整套配置。改坏能退出高级模式恢复默认,但深度质量与帧率不再保证。参数面板长这样:
- 深度质量工具。tools/depth-quality/ 内置 Z / Zi / ZPi 三类误差统计,用它做参数调优的量化验收,比肉眼判断可靠。
实战场景
场景一:桌面式尺寸测量
目标:相机固定,量取画面中两点间距离。
步骤:
- 参考 examples/measure/ 起 pipeline,深度 + RGBA 彩色双流;
- 设
RS2_RS400_VISUAL_PRESET_HIGH_ACCURACY; - 滤镜链用 decimation(2) → spatial(开
RS2_OPTION_HOLES_FILL)→ temporal,避免标尺路径从洞里穿过去; - 对鼠标两点反投影求 3D 距离。
验证:放一根已知长度的钢尺正对相机,读数偏差应在 1–2 cm 内;偏差大先检查相机是否水平,再看 Z 误差统计。
场景二:录制一次、离线调参
目标:现场采集困难,把数据带回办公室反复试验。
步骤:
- 用 tools/recorder/ 或 recorder 设备录
.bag,IMU 流一并包含; - 本地用 playback 设备打开 bag,pipeline 代码不用改,
device.as<rs2::playback>()判一下即可; - 在回放数据上迭代滤镜参数与高级 JSON 配置。
验证:回放帧的时间戳、分辨率、数据与原始采集逐位一致,rs-replay可直接复放。完整 GUI 示例见 examples/record-playback/。
排障速查
| 现象 | 可能原因 | 处理 |
|---|---|---|
rs-enumerate-devices列不出设备 | udev 规则未装 / 内核补丁未生效 | 重跑./scripts/setup_udev_rules.sh与patch-realsense-ubuntu-lts-hwe.sh,sudo dmesg | tail -n 50查新 uvcvideo 驱动是否注册 |
| 深度大面积空洞或全 0 | 距离超量程 / 红外被强光压制 / 镜片脏 | 拉近到 6 m 内;遮避阳光直射;用RS2_OPTION_LASER_POWER提功率 |
| IMU 静止时角速度非零、重力不等于 9.80665 | BMI055 出厂无内参校准 | 跑 tools/rs-imu-calibration/,结果写入设备 NVRAM,SDK 自动读取 |
| 帧率上不去 | 总线带宽或 CPU 瓶颈 | 降分辨率/帧率;确认 USB 3.0 直连、未走虚拟机 |
wait_for_frames报 profile 不匹配 | 设备不支持该组合 | 用rs-enumerate-devices核对可用流与帧率 |
资源索引
常用工具(安装后即可全局调用):
| 工具 | 用途 |
|---|---|
rs-enumerate-devices | 列出设备与全部可用流 |
realsense-viewer | 交互式查看器,可视化 IMU 与深度 |
rs-capture/rs-replay | 命令行抓帧 / 回放 bag |
rs-imu-calibration | IMU 内参校准 |
| 深度质量工具 | tools/depth-quality/ 误差统计 |
关键文档与示例:
- 坐标系与 IMU 集成:doc/d435i.md
- 滤镜说明:doc/post-processing-filters.md
- 高级模式:doc/rs400/rs400_advanced_mode.md
- 安装:doc/installation.md
- 录制回放:doc/record-and-playback.md
- 示例总目录:examples/
D435i 加上 librealsense,深度、RGB、IMU 三路数据的时间对齐和坐标统一都已处理,开发者剩下的工作集中在滤波链与业务逻辑上。建议从rs-enumerate-devices和 hello-realsense 起步,再按本文的调优顺序逐步加滤镜。延伸阅读:doc/stepbystep/getting_started_with_openCV.md 和 examples/sensor-control/ 中的传感器选项参考。
【免费下载链接】librealsenseRealSense SDK项目地址: https://gitcode.com/GitHub_Trending/li/librealsense
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考