Rerun Boxes2D Archetype 完全指南:2D 包围盒的字段、构造与可视化原理
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
本文以 Rerun 开源仓库中的Boxes2D类型定义与 API 参考文档为骨架,深入讲解这一 2D 包围盒数据类型的字段体系、三种语言(Python / Rust / C++)的构造方式、底层类型生成机制,以及它在 Spatial2D 视图中的渲染原理。读完本文,你将掌握如何用Boxes2D记录目标检测框、ROI 区域、平面尺寸标注等常见二维几何数据,并能理解"半边长(half-extent)"这一核心概念如何在 Rerun 的 Arrow 数据模型中落地。
Boxes2D 是什么
Boxes2D是 Rerun 提供的一种archetype(原型类型),用于描述一组2D 轴对齐包围盒(axis-aligned bounding boxes)。在官方类型定义 boxes2d.def.rs 中,它的定位是:
"2D boxes with half-extents and optional center, colors etc."(带半边长、可选中心点、颜色等的 2D 盒子)
它归属于"Spatial 2D"类别,状态为stable(稳定),由Boxes2D视觉化器(visualizer)负责渲染,在类型定义中声明为#[docs(category = "Spatial 2D")]与#[rerun(visualizer = "Boxes2D")]。
核心概念:半边长(half-extent)
Boxes2D的尺寸字段在底层是HalfSize2D,即"2D 盒子的半径"。根据 HalfSize2D 组件文档 的说明:
- 半边长在盒子的局部坐标系中度量;
- 盒子沿每个坐标轴在正、负两个方向同时延伸(即以中心为原点向两侧对称展开);
- 负的尺寸表示盒子沿对应轴发生了翻转,但这不影响显示效果;
- 其 Rerun 编码为
Vec2D,底层 Arrow 数据类型为FixedSizeList(2 x non-null Float32),即两个f32构成的定长列表。
这种"半边长 + 中心点"的表示方式,与计算机视觉领域常见的[x_center, y_center, width/2, height/2](即XCYCW2H2)格式天然对应,因此非常便于与检测模型输出直接对接。
字段体系:Required / Recommended / Optional
Boxes2D共由8 个组件字段组成(见 boxes2d.rs 中的NUM_COMPONENTS: usize = 8),按类型定义中的#[rerun(required)]、#[rerun(recommended)]、#[rerun(optional)]标记分为三档:
| 类别 | 字段 | 组件类型 | 说明 |
|---|---|---|---|
| Required(必填) | half_sizes | HalfSize2D | 整批盒子的半边长,构成盒子的"尺寸" |
| Recommended(推荐) | centers | Position2D | 盒子中心位置;缺省时以局部原点为中心 |
| Recommended(推荐) | colors | Color | 盒子颜色 |
| Optional(可选) | radii | Radius | 构成盒子的描边线的半径(线宽) |
| Optional(可选) | labels | Text | 文本标签;若只有一个标签则放在实体中心,否则每个实例各有一个标签 |
| Optional(可选) | show_labels | ShowLabels | 是否显示标签;未设置时,当实体恰好只有一个标签或实例数低于阈值时自动显示 |
| Optional(可选) | draw_order | DrawOrder | 2D 绘制顺序,值越大越靠上层绘制,默认10.0 |
| Optional(可选) | class_ids | ClassId | 类别 ID;通过 AnnotationContext 提供颜色与标签,未显式指定颜色/标签时生效 |
字段语义要点
half_sizes是唯一必填字段:类型定义源码boxes2d.def.rs中仅它标记为#[rerun(required)],其余字段均为可选。生成代码中的REQUIRED_COMPONENTS数组也只有Boxes2D:half_sizes一项。centers决定摆放位置:不提供中心时,所有盒子以局部坐标原点为中心排列。labels的分布规则:生成代码中明确注释——"If there's a single label present, it will be placed at the center of the entity. Otherwise, each instance will have its own label."(若只提供一个标签,则放置在实体中心;否则每个实例各取一个标签)。draw_order控制 2D 层叠:值越大越靠上,未设置时默认10.0。这在叠加多个实体(例如先画底图、再画框)时非常有用。class_ids提供"语义化配色":配合 AnnotationContext,可以让同一类别的盒子自动获得统一颜色与标签,无需逐框指定颜色。
可显示的视图(Views)
根据文档,Boxes2D数据可以在以下视图中展示:
- Spatial2DView:标准的 2D 空间视图,
Boxes2D是它直接可视化的 archetype 之一(见其 "Visualized archetypes" 列表); - Spatial3DView:当盒子被记录在某个投影(如针孔相机 Pinhole)之下时,可以作为 2D 覆盖层叠加显示在 3D 场景中;
- DataframeView:以表格形式查看组件数据。
从源码结构看,Boxes2D的渲染逻辑位于 re_view_spatial/src/visualizers/boxes2d.rs,它属于 Spatial 视图的视觉化器集合,负责把half_sizes、centers、colors等组件批次转换为屏幕上的矩形图元。
快速上手:三语言"简单 2D 盒子"示例
官方示例boxes2d_simple在仓库中提供了 Python、Rust、C++ 三套等价实现,分别位于 docs/snippets/all/archetypes/boxes2d_simple.py、boxes2d_simple.rs 与 boxes2d_simple.cpp。
Python
"""Log a simple 2D Box.""" import rerun as rr rr.init("rerun_example_box2d", spawn=True) rr.log("simple", rr.Boxes2D(mins=[-1, -1], sizes=[2, 2]))mins=[-1, -1]指定盒子的最小角点,sizes=[2, 2]指定完整边长,SDK 会自动换算为"中心 + 半边长"。
Rust
//! Log some very simple 2D boxes. fn main() -> Result<(), Box<dyn std::error::Error>> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_box2d").spawn()?; rec.log( "simple", &rerun::Boxes2D::from_mins_and_sizes([(-1., -1.)], [(2., 2.)]), )?; Ok(()) }C++
// Log some simple 2D boxes. #include <rerun.hpp> int main(int argc, char* argv[]) { const auto rec = rerun::RecordingStream("rerun_example_box2d"); rec.spawn().exit_on_failure(); rec.log( "simple", rerun::Boxes2D::from_mins_and_sizes({{-1.f, -1.f}}, {{2.f, 2.f}}) ); }三份代码完全等价:都在实体"simple"下记录一个左下角为(-1, -1)、尺寸为2×2的正方形盒子。运行后会在弹出的 Rerun Viewer 的 Spatial2D 视图中看到该盒子。仓库中还预置了该示例的录制文件 tests/assets/rrd/snippets/archetypes/boxes2d_simple.rrd,可直接用 viewer 打开查看。
构造方式的完整矩阵
Boxes2D的价值在于它提供了丰富的"语义化构造器",让你不用手动换算半边长。Rust 侧的实现集中在 boxes2d_ext.rs:
| 构造函数 | 输入 | 语义 |
|---|---|---|
from_half_sizes | 半边长集合 | 盒子以局部原点为中心 |
from_centers_and_half_sizes | 中心 + 半边长 | 最直接的完整定义 |
from_sizes | 完整尺寸 | 内部执行HalfSize2D::new(w/2.0, h/2.0)换算 |
from_centers_and_sizes | 中心 + 完整尺寸 | 尺寸自动折半 |
from_mins_and_sizes | 最小角点 + 完整尺寸 | 按center = min + half_size反推中心 |
其中from_mins_and_sizes的实现值得注意(源码 boxes2d_ext.rs):
- 若提供的
sizes少于mins,最后一个半边长会被自动重复使用(std::iter::repeat(last_half_size)),用于补齐剩余的盒子; - 若完全没有提供 size,则记录一条
re_log::warn_once!("Must provide at least one size to create boxes.")警告,且盒子列表为空。
注意:
from_sizes与from_centers_and_sizes在源码中带有TODO(#3285)注释,说明它们目前"并不按原样保存数据,而是从输入数据中生成半边长"——即输入尺寸会被除以 2 后存储,这是当前版本(基于该仓库实现)的既定行为。
Python 扩展:Box2DFormat 六种输入格式
Python 侧在 boxes2d_ext.py 中额外提供了array+array_format参数,可以直接传入原始检测框数组,由 SDK 自动换算为half_sizes与centers。Box2DFormat枚举定义了六种解释方式:
| 枚举值 | 格式 | 含义 |
|---|---|---|
XYWH | [x, y, w, h] | x, y为左上角 |
YXHW | [y, x, h, w] | x, y为左上角,坐标交换 |
XYXY | [x0, y0, x1, y1] | 左上角 + 右下角 |
YXYX | [y0, x0, y1, x1] | 坐标交换的角点形式 |
XCYCWH | [x_center, y_center, width, height] | 中心 + 完整尺寸 |
XCYCW2H2 | [x_center, y_center, width/2, height/2] | 中心 + 半边长(与内部表示一致) |
例如,把 YOLO 风格的归一化检测结果[cx, cy, w, h]直接可视化:
import numpy as np import rerun as rr from rerun.archetypes import Box2DFormat rr.init("rerun_example_box2d", spawn=True) boxes = np.array([[0.5, 0.5, 0.2, 0.4], [0.8, 0.3, 0.1, 0.1]], dtype=np.float32) rr.log("detections", rr.Boxes2D(array=boxes, array_format=Box2DFormat.XCYCWH))array模式的使用约束(源码中通过ValueError强制校验):
- 使用
array时必须同时指定array_format; array与sizes、half_sizes、mins、centers互斥,不能同时传入;- 空数组会被归一化为形状
(0, 4)的float32数组; - 一维数组会自动扩展为单行(
np.expand_dims),便于传入单个框。
此外 Python 构造器对sizes/mins/half_sizes/centers的互斥关系也有完整校验:sizes与half_sizes不能同时指定,mins与centers不能同时指定,mins必须搭配sizes或half_sizes使用(否则报错 "Cannot specifyminswithoutsizesorhalf_sizes")。传入sizes时内部会执行half_sizes = sizes / 2.0,传入mins时执行centers = mins + half_sizes。
底层原理:类型定义驱动的代码生成
Boxes2D在三种语言中的实现并不是手写的三份独立代码,而是由一份类型定义统一生成:
- 定义源头:boxes2d.def.rs 用
#[rerun::rerun_type]等宏声明了字段、必填/推荐/可选标记、状态与视觉化器;该文件顶部注明"这是 Rerun 的类型定义,而非可执行代码,由re_types_builder解析以生成 Rust、Python、C++ 绑定"。 - 代码生成器:
crates/build/re_types_builder/src/codegen/下的rust/api.rs、python/mod.rs等模块根据定义生成各语言 API。生成的 Rust 文件 boxes2d.rs 顶部同样注明"DO NOT EDIT! This file was auto-generated"。 - 生成结果:Rust 侧实现了
Archetypetrait,包括required_components()/recommended_components()/optional_components()/all_components()四组ComponentDescriptor常量数组(分别为 1 / 2 / 5 / 8 个),以及from_arrow_components反序列化、as_serialized_batches序列化等 Arrow 数据通路。
也就是说,你在文档 boxes2d.md 中看到的字段分类表、可显示视图列表,与各语言生成的 docstring 完全同源,均来自boxes2d.def.rs的#[docs(...)]声明——这正是 Rerun"单一定义、多端一致"设计哲学的体现。
关于 2D 旋转的预留位
在类型定义boxes2d.def.rs中,centers与colors之间有一段被注释掉的字段:
// TODO(#3247): Add 2D rotation. // Optional rotations of the boxes. //#[rerun(recommended)] //pub rotations: Option<Vec<rerun::components::Rotation2D>>,从源码可以推断:2D 旋转目前尚未作为正式字段加入Boxes2D(当前版本只支持轴对齐盒子),但已在类型定义层预留了设计位置,未来可能以Rotation2D组件形式扩展。
列式发送与批量更新
除了逐行log,生成代码还提供了面向时序数据的列式(columnar)发送能力:
- Rust:
Boxes2D::columns(lengths)将各SerializedComponentBatch通过partitioned拆分为SerializedComponentColumn,配合RecordingStream::send_columns使用;columns_of_unit_batches()则是把每个元素拆成独立子批次的便捷版本。 - Python:
Boxes2D.columns(...)返回ComponentColumnList,配合rr.send_columns可一次写入多帧数据。源码中针对FixedSizeList(如half_sizes的 Vec2D)与原始类型(如colors的 uint32)分别推导了分区大小。
生成代码中还提供了update_fields()/from_fields()(只更新部分字段)与clear_fields()/cleared()(清空全部字段,写入各组件空数组)两个方向的 API,便于在长运行任务中增量维护一个实体的盒子集合。
小结
Boxes2D是 Rerun 生态中记录二维轴对齐包围盒的标准入口,其设计要点可归纳为:
- 单一必填字段
half_sizes,配合推荐的centers、colors与可选的标签、线宽、绘制顺序、类别 ID,覆盖从检测框到带语义标注的 ROI 的绝大多数 2D 场景; - 多套语义化构造器(min+size、center+size、center+half-size,以及 Python 的六种
array_format)让你无需手动换算; - 稳定、生成的类型体系:一份
boxes2d.def.rs定义同时驱动 Rust / Python / C++ 三端 API 与本文档,保证多语言行为完全一致; - 在 Spatial2DView 中直接可视化,也可在投影下作为 2D 覆盖层显示于 3D 视图,还可通过 DataframeView 做数据检视。
若需继续深入,可阅读类型定义 boxes2d.def.rs、生成实现 boxes2d.rs 与扩展实现 boxes2d_ext.rs、Python 扩展 boxes2d_ext.py、C++ 头文件 boxes2d.hpp,以及渲染侧 re_view_spatial/src/visualizers/boxes2d.rs。
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考