Rerun 数据分析结果回传实战:从 Pandas 分析到 Viewer 实时可视化
2026/9/16 14:28:01 网站建设 项目流程

Rerun 数据分析结果回传实战:从 Pandas 分析到 Viewer 实时可视化

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

导读

本文是 Rerun「Getting started / Data out」系列教程的第三部分,讲解如何基于前一步导出的 Pandas 数据帧,对**面部追踪(face tracking)**录像中的jawOpen(嘴巴张开程度)信号做分析,提取二值化的「嘴巴张开状态」信号,并通过 Rerun SDK 将其回传给正在运行的 Viewer,实现实时可视化。读完本文,你将掌握rr.init+rr.connect_grpc的连接复用技巧、列式日志 APIrr.send_columns()的高效用法,以及如何同时以Scalar时间序列和Text标签两种形式呈现分析结果。

前置条件:从数据帧导出到分析

本教程建立在前面两节的基础上:

  • explore-as-dataframe.md:在 Viewer 的 dataframe 视图中探索面部追踪数据;
  • export-dataframe.md:通过 Rerun SDK 的数据帧 API,将face_tracking.rrd录制内容导出为 Pandas 数据帧。

在 export-dataframe.md 中,我们完成了两步关键预处理:

  1. dataset.filter_contents("/blendshapes/0/jawOpen").reader(index="frame_nr")创建视图并读取为 DataFusion 数据帧;
  2. explode()把组件列(每行是标量列表)展平成 float64 的jawOpen列,缺失帧用NaN表示。

本节的起点就是这份 Pandas 数据帧pd_df,它包含frame_nrjawOpen等列。

分析数据:阈值化提取二值信号

在之前的探索中我们已经确认:将jawOpen信号与阈值0.15比较,足以产生可靠的二值「嘴巴张开状态」信号。因此分析阶段只需要一行 Pandas 操作:

# compute the mouth state pd_df["jawOpenState"] = pd_df["jawOpen"] > 0.15

这段代码来自 docs/snippets/all/tutorials/data_out.py 中标记为filter_jaw的代码片段。jawOpenState是一个布尔列:

  • True表示嘴巴张开(OPEN);
  • False表示嘴巴闭合(CLOSE);
  • 原始信号缺失(NaN)的帧,比较结果为False,会被归类为闭合状态。

这样我们就得到了一个与frame_nr一一对应的状态信号,接下来需要把它送回 Viewer。

回传的第一步:连接到同一段录制

要把分析结果追加到我们刚分析的那段录制中,关键前提是复用完全相同的 application ID 与 recording ID。只有标识符一致,SDK 才会把新数据追加到既有录制;如果 Viewer 当前正打开该录制并监听新连接,新数据会实时出现在活动会话中。

读取原始录制的标识符

脚本首先从原始 RRD 文件中读取 application ID:

application_id = rr.chunk.RrdReader(example_rrd).recordings()[0].application_id

随后完成初始化和连接:

rr.init(application_id, recording_id=dataset.segment_ids()[0]) rr.connect_grpc()

从源码看,rr.init位于 rerun_py/rerun_sdk/rerun/init.py,其中recording_id参数默认会生成一个随机 UUIDv4;若两次init不显式指定 recording ID,它们会被视为同一段录制(该随机值在整个进程生命周期内保持不变)。这里我们显式传入dataset.segment_ids()[0],保证与查询到的录制段完全一致,从而把新数据追加进去。

rr.connect_grpc()的实现见 rerun_py/rerun_sdk/rerun/sinks.py 与 rerun_py/rerun_sdk/rerun/recording_stream.py:

  • 默认连接地址为rerun+http://127.0.0.1:9876/proxy(即本机 Viewer 的 gRPC 代理端口);
  • 也支持rerun://rerun+https://等 scheme,pathname 必须是/proxy
  • 该调用立即返回,不会阻塞主线程。

[!NOTE] 在自动化数据分析场景中,通常更推荐把结果写入独立的 RRD 文件(与源 RRD 相邻,通过rr.save()实现),此时依然可以使用相同的 application ID 和 recording ID。这样在 Viewer 中同时打开源文件与结果文件,两个文件的数据会在同一段录制下共同显示。

用 send_columns 批量回传结果

我们将以两种形式发送嘴巴状态数据:

  1. 作为独立的Scalar组件,保存原始状态数据,用于时间序列展示;
  2. 作为Text组件,挂在既有的边界框实体上,在可视化中得到文字化的状态描述。

形式一:发送 Scalar 时间序列

rr.send_columns( "/jaw_open_state", indexes=[rr.TimeColumn("frame_nr", sequence=pd_df["frame_nr"])], columns=rr.Scalars.columns(scalars=pd_df["jawOpenState"]), )

我们使用rr.send_columns()API 一次性批量发送整列数据。这与行导向的rr.log()有本质区别:

  • send_columns列导向的:一次调用即可更新实体在多个时间点上的状态;
  • 绕过时间上下文与 micro-batcher:不会自动注入log_timelog_tick等内建时间轴,也不会带上任何用户时间轴,只有显式传入的indexes(此处为frame_nr序列)会被写入;
  • 所有列的长度必须一致,共享同一索引的行相当于一次独立的rr.log()调用。

底层实现位于 rerun_py/rerun_sdk/rerun/_send_columns.py:send_columns内部将indexescolumns组装为参数后,直接调用绑定层bindings.send_arrow_chunk(),以 Arrow 数据块(Chunk)的形式发送。这也是它高效的原因——整列数据打包成单个 Arrow Chunk,而不是逐行发送。

形式二:发送 Text 标签到边界框实体

target_entity = "/video/detector/faces/0/bbox" rr.log(target_entity, rr.Boxes2D.from_fields(show_labels=True), static=True) rr.send_columns( target_entity, indexes=[rr.TimeColumn("frame_nr", sequence=pd_df["frame_nr"])], columns=rr.Boxes2D.columns( labels=np.where(pd_df["jawOpenState"], "OPEN", "CLOSE") ), )

这里有两个要点:

  1. 静态启用标签显示:先通过rr.log(..., static=True)ShowLabels组件以静态(static)方式写入target_entity。静态组件不依赖时间轴、只保存一份,用于控制该实体是否显示标签。这正是ShowLabels组件的设计初衷——它独立于标签本体存在,便于在 Viewer 和蓝图中按需隐藏/显示。

  2. 批量生成文本标签:再次使用rr.send_columns(),借助np.where(pd_df["jawOpenState"], "OPEN", "CLOSE")为每一帧生成对应的文字标签(True"OPEN"False"CLOSE")。Boxes2D.columns(labels=...)构建的是针对边界框实体的组件列,因此每个时间点的 OPEN/CLOSE 文本都会与对应的边界框对齐。

最终结果

对 Viewer 蓝图稍作调整后,效果为:

  • 2D 视图中,边界框旁显示OPEN/CLOSE标签;
  • /jaw_open_state信号同时出现在time series(时间序列)视图dataframe 视图中,True/False状态随时间可见。

完整脚本

本指南的完整脚本(加载数据 → 分析 → 回传结果)见 docs/snippets/all/tutorials/data_out.py,其核心流程可以概括为四步:

  1. 加载:启动rr.server.Server并挂载face_tracking.rrd,通过rr.catalog.CatalogClient查询录制;
  2. 导出filter_contents(...).reader(index="frame_nr")读取数据帧,to_pandas()转成 Pandas;
  3. 分析pd_df["jawOpen"] > 0.15生成布尔状态列;
  4. 回传rr.init+rr.connect_grpc()复用录制标识符,rr.send_columns()分别发送标量与文本标签。

需要说明的是,该教程的完整示例目前仅以 Python 实现(见 docs/snippets/snippets.toml 中tutorials/data_out的配置,C++ 与 Rust 标注为未实现);Rust 与 C++ 用户可参考对应的send_columns列式 API 迁移相同思路。建议按以下步骤复现:先按 export-dataframe.md 准备数据帧,确保 Viewer 打开同一段录制(默认端口 9876),再依次运行分析、连接、回传代码,即可在时间序列视图与 2D 视图中实时看到分析结果。

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

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

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

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

立即咨询