news 2026/9/17 8:50:49

用 Rerun 实时可视化 Intel RealSense 深度传感器:RGB 与深度流式管线实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用 Rerun 实时可视化 Intel RealSense 深度传感器:RGB 与深度流式管线实战

用 Rerun 实时可视化 Intel RealSense 深度传感器:RGB 与深度流式管线实战

【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun

本篇技术指南基于 Rerun 仓库中的live_depth_sensor官方示例(examples/python/live_depth_sensor/README.md),讲解如何把 Intel RealSense 深度传感器实时流式采集的 RGB 彩色帧与深度帧接入 Rerun 3D 视图,并借助针孔相机(Pinhole)模型实现 RGB 相机、深度相机与三维空间的坐标对齐。读完本文,你将掌握PinholeTransform3DImageDepthImage等 Rerun 核心 archetype 的组合用法、meter深度单位换算的关键细节,以及如何运行、自定义这套实时传感器可视化方案。

示例概览:把 RealSense 实时流接入 Rerun 3D 视图

该示例的功能非常聚焦:从一台已连接的 Intel RealSense 深度传感器上持续读取彩色(RGB)与深度(Depth)两种数据流,并逐帧送入 Rerun 进行可视化。最终在 Rerun Viewer 中看到的不只是两张并排的图像,而是一个带针孔相机模型的 3D 场景——RGB 相机与深度相机都被标定在正确的位置,深度图在 3D 视图中被自动反投影为点云。

硬件要求:此示例需要一台真实连接(USB)的 Intel RealSense 深度传感器才能运行,例如 D400 系列。正因为依赖硬件,示例在 pyproject.toml 中通过[tool.rerun-example] skip = true # requires hardware标记为跳过 CI 自动化执行。

示例使用到的 Rerun 核心类型(archetype)共 4 种:

Archetype作用
Pinhole描述相机透视投影(内参),负责图像坐标与相机坐标的映射
Transform3D描述相机外参,用于把 RGB 相机摆放到相对深度相机的正确位置
Image记录 RGB 彩色图像
DepthImage记录深度图像,并携带深度单位(meter)信息

运行环境与依赖

按照示例文档,你需要先准备好最新版 Rerun SDK 并检出仓库代码:

pip install --upgrade rerun-sdk # 安装最新版 Rerun SDK git clone https://gitcode.com/GitHub_Trending/re/rerun.git # 检出仓库 cd rerun git checkout latest # 检出与最新 SDK 发布版本匹配的提交

然后安装该示例所需的依赖库:

pip install -e examples/python/live_depth_sensor

依赖声明见 examples/python/live_depth_sensor/pyproject.toml,核心依赖只有三个:

  • numpy:用于把 RealSense 原始帧数据转为 NumPy 数组;
  • pyrealsense2(macOS 上为pyrealsense2-mac):Intel RealSense 官方 Python SDK,提供rs.pipeline()get_intrinsics()get_extrinsics_to()等接口;
  • rerun-sdk:Rerun 日志 SDK。

示例同时声明了命令行入口脚本:live_depth_sensor = "live_depth_sensor:main"

运行示例主脚本:

python -m live_depth_sensor # 运行示例

如果想自定义行为、探索更多功能或保存数据,用--help查看全部 CLI 选项:

python -m live_depth_sensor --help

代码结构总览

示例主体是一个约 100 行的单文件脚本 examples/python/live_depth_sensor/live_depth_sensor.py,流程可以概括为四个阶段:

  1. 声明坐标系:把整个realsense空间声明为 RDF(右、下、前)坐标约定;
  2. 标定相机(静态):分别记录深度相机与 RGB 相机的内参(Pinhole)以及两者之间的外参(Transform3D),全部使用static=True只记录一次;
  3. 循环取流:通过rs.pipeline()阻塞等待帧,逐帧把深度图与彩色图 log 到对应实体路径;
  4. 清理退出finally中调用pipe.stop()释放 RealSense 管线。

其中关键的相机标定与坐标约定逻辑如下。

相机模型与坐标约定:Pinhole + Transform3D + ViewCoordinates

坐标约定:RDF

RealSense 的坐标系约定为RDF(X 向右、Y 向下、Z 向前),这与 Rerun 深度相机的默认坐标约定一致。示例在第一行就把它声明为静态属性:

rr.log("realsense", rr.ViewCoordinates.RDF, static=True) # Visualize the data as RDF

从 rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py 的实现说明看,[Right, Down, Forward]表示+X指向右、+Y指向下、+Z指向前。RDF 是图像类数据(所有图像都使用 RDF 像素坐标约定)最自然的空间表示。

深度相机内参

示例把深度相机的坐标系原点直接当作世界原点——realsense/depth保持为单位变换(Identity),因此无需为深度相机记录外参。只记录深度相机的针孔内参:

rr.log( "realsense/depth/image", rr.Pinhole( resolution=[depth_intr.width, depth_intr.height], focal_length=[depth_intr.fx, depth_intr.fy], principal_point=[depth_intr.ppx, depth_intr.ppy], ), static=True, )

三个参数分别对应 RealSense 内参结构(depth_intr)中的分辨率、焦距(fx/fy)与主点(ppx/ppy),来源是profile.get_stream(rs.stream.depth).as_video_stream_profile().get_intrinsics()

RGB 相机外参与内参

RGB 相机与深度相机通常不在同一物理位置,需要外参把 RGB 相机摆放到正确位姿。示例用get_extrinsics_to获取深度相机到 RGB 相机的变换,并记录为Transform3D

rgb_from_depth = depth_profile.get_extrinsics_to(rgb_profile) rr.log( "realsense/rgb", rr.Transform3D( translation=rgb_from_depth.translation, mat3x3=np.reshape(rgb_from_depth.rotation, (3, 3)), relation=rr.TransformRelation.ChildFromParent, ), static=True, )

这里的relation=rr.TransformRelation.ChildFromParent表示该变换描述子实体(RGB 相机)相对父实体(深度相机坐标系)的姿态。之后 RGB 相机同样记录自己的针孔内参:

rr.log( "realsense/rgb/image", rr.Pinhole( resolution=[rgb_intr.width, rgb_intr.height], focal_length=[rgb_intr.fx, rgb_intr.fy], principal_point=[rgb_intr.ppx, rgb_intr.ppy], ), static=True, )

从 rerun_py/rerun_sdk/rerun/archetypes/pinhole.py 的源码注释可以进一步理解Pinhole的语义:它是一个相机透视投影 archetype("Camera perspective projection (a.k.a. intrinsics)"),resolution是子图像空间的像素分辨率(宽、高),image_from_camera投影到(0,0)resolution - 1的范围内。当同一实体下记录了Transform3D时,它表示相机外参并优先于Pinhole被用于空间定位;而当DepthImage记录在Pinhole之下时,深度图会沿相机朝向被自动反投影成 3D 点云——这正是本示例在 3D 视图中看到点云的原理。

Pinhole还支持更多可选字段:camera_xyz(默认即RDF)、image_plane_distance(仅影响 3D 可视化中相机平截头体的显示距离)、colorline_width(相机线框的样式)等,均可按需扩展。

记录 RGB 图像:Image

相机标定完成后,进入主循环。每取到一帧,先递增帧号并用rr.set_time把它写入时间轴,再记录彩色图:

rr.set_time("frame_nr", sequence=frame_nr) rr.log("realsense/rgb/image", rr.Image(color_image))

color_imagenp.asanyarray(color_frame.get_data())转换而来,即 RealSense 原始彩色帧数据(BGR/RGB 排列的 H×W×C 数组)。由于实体路径与之前Pinhole记录的路径一致(realsense/rgb/image),图像会自动与相机内参关联,从而在 3D 视图中拥有正确的位置与投影。

记录深度图像:DepthImage 与 meter 单位换算

深度图与彩色图同样逐帧记录,但多了关键的meter参数:

rr.log( "realsense/depth/image", rr.Pinhole( resolution=[depth_intr.width, depth_intr.height], focal_length=[depth_intr.fx, depth_intr.fy], principal_point=[depth_intr.ppx, depth_intr.ppy], ), static=True, )
rr.set_time("frame_nr", sequence=frame_nr) rr.log("realsense/depth/image", rr.DepthImage(depth_image, meter=1.0 / depth_units))

depth_units来自depth_frame.get_units(),是 RealSense 深度值对应的物理长度(单位为米)。例如depth_units = 0.001表示每个深度单位是 1 毫米,此时meter = 1.0 / 0.001 = 1000,即 1 米对应 1000 个原生深度单位。

根据 rerun_py/rerun_sdk/rerun/archetypes/depth_image.py 的字段文档,meter的含义是"原生深度单位中一米有多长"。它对 2D 视图的影响仅是悬停时显示的物理深度值;在 3D 视图中则直接决定点云中每个点的空间位置,单位错误会导致点云被整体缩放或拉伸。若省略meter,Viewer 会默认浮点深度格式取1.0、整数格式取1000.0(毫米)。

DepthImage还提供其它可视化相关字段,可按需组合:

字段说明默认
colormap深度渲染使用的颜色映射Turbo 色图
depth_range期望的有效深度值范围,超出部分在映射色图时被截断(点云不受影响)自动从数据估计
point_fill_ratio缩放 3D 点云中点的半径1.0
draw_order2D 视图下的绘制顺序-20.0
magnification_filter2D 视图放大时的过滤方式(仅 2D 有效)

时间轴:用 frame_nr 串联连续帧

rr.set_time("frame_nr", sequence=frame_nr)

每一帧都调用一次rr.set_time,把序列时间点frame_nr写入 Rerun 时间轴。这样所有帧(无论 RGB 还是深度)都会被标记上同一帧号,Viewer 可以按时间轴播放、拖动、对比不同帧的数据。这也是 Rerun 处理流式时序数据(multimodal robotics data)的标准方式。

完整的帧循环

综合上述各环节,主循环在源码中的实现如下(来自 examples/python/live_depth_sensor/live_depth_sensor.py):

frame_nr = 0 try: while True: if num_frames and frame_nr >= num_frames: break rr.set_time("frame_nr", sequence=frame_nr) frame_nr += 1 frames = pipe.wait_for_frames() for _f in frames: depth_frame = frames.get_depth_frame() depth_units = depth_frame.get_units() depth_image = np.asanyarray(depth_frame.get_data()) rr.log("realsense/depth/image", rr.DepthImage(depth_image, meter=1.0 / depth_units)) color_frame = frames.get_color_frame() color_image = np.asanyarray(color_frame.get_data()) rr.log("realsense/rgb/image", rr.Image(color_image)) finally: pipe.stop()

num_frames--num-frames命令行参数控制,不传则无限流式运行,直到按Ctrl-C中断,此时finally块确保 RealSense 管线被正确关闭。

CLI 选项:script_add_args 带来的标准能力

示例的main()除了自定义的--num-frames外,还调用了rr.script_add_args(parser)rr.script_setup(args, "rerun_example_live_depth_sensor")。从 rerun_py/rerun_sdk/rerun/_script_helpers.py 的源码可以看到,这组辅助函数会为脚本注入一整套标准 Rerun 参数:

  • --headless:不弹出 GUI,只记录数据;
  • --connect [URL]:连接到一个外部运行的 Rerun Viewer(不指定 URL 时连接默认地址);
  • --serve:启动 gRPC 与 Web 服务器,并打开浏览器端的 Web Viewer;
  • --url:指定要连接的 Rerun URL;
  • --save <path>:把数据保存为.rrd文件;
  • --stdout:把数据写到标准输出,供管道重定向到 Rerun Viewer。

script_setup会根据这些参数自动完成rr.init与连接建立,script_teardown负责收尾(如在--serve模式下阻塞等待)。因此本示例天然支持"离线保存为 rrd 文件"或"无头模式采集"等扩展用法,无需修改任何业务代码。

小结

live_depth_sensor示例展示了 Rerun 处理实时多模态传感器数据的标准范式:先以static=True一次性记录坐标系约定(ViewCoordinates.RDF)、相机内参(Pinhole)与外参(Transform3D),建立 3D 空间的标定骨架;再逐帧用rr.set_time标记时间戳,并通过ImageDepthImage(配合meter单位换算)持续记录数据流。这套模式可以直接迁移到任何深度相机、双目相机或 RGB-D 机器人感知管线上,是理解 Rerun 相机模型与流式日志机制的最小可运行范本。

【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 8:49:08

ROS1机器人导航闭环系统:SLAM建图、AMCL定位与底盘控制实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 8:47:27

5G SA室分QoS Flow建立成功率异常排查完全指南

简介&#xff1a;一份专注5G SA室分网络优化实战的案例文档&#xff0c;面向网络优化工程师、基站运维及5G性能管理人员。内容围绕A小区QoS Flow建立成功率异常偏低&#xff08;最低56.32%&#xff09;的完整排查过程&#xff0c;从告警排查、设计图纸核对、信令跟踪&#xff0…

作者头像 李华
网站建设 2026/9/17 8:47:09

开关二极管本质:载流子寿命决定的高频硬开关能力

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/17 8:46:47

D* Lite算法与横向避障在无人驾驶路径规划中的Matlab实现

1. 项目背景与核心挑战无人驾驶地面车辆的路径规划一直是自动驾驶领域的核心问题之一。在实际应用中&#xff0c;车辆不仅需要从起点到终点生成一条全局路径&#xff0c;还需要具备动态避障和实时调整路径的能力。这正是D* Lite算法与横向避障算法结合的价值所在。D* Lite算法是…

作者头像 李华