Rerun EncodedDepthImage 详解:在 Rerun 中记录并可视化 RVL/PNG/TIFF 编码深度图像
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
导读
本文聚焦 Rerun 类型体系中的EncodedDepthImage原型(Archetype),讲解如何将已经过 RVL、PNG 或 TIFF 等编解码器压缩的深度图像直接作为字节流记录进 Rerun,并在 Viewer 中完成解码、着色与 2D/3D 投影展示。读完本文,你将掌握该类型的全部 8 个字段(1 必选 + 2 推荐 + 5 可选)的含义与取值、Python/Rust/C++ 三端完整可运行的示例代码、from_file/from_file_contents等便捷构造方法,以及 Viewer 端解码管线的底层实现路径,并了解它与未压缩DepthImage原型的适用边界。
本文基于 docs/content/reference/types/archetypes/encoded_depth_image.md 展开,并配合仓库内类型定义、三端 SDK 生成代码、Viewer 可视化器与测试用例作纵深佐证。
EncodedDepthImage 是什么
EncodedDepthImage是 Rerun 中用于可视化已编码压缩深度图像的原型(Archetype)。它不接收像素矩阵,而是接收一个包含完整图片文件的字节流(Blob),由 Viewer 在渲染时按需解码。这样做的直接收益是:记录带宽与磁盘占用大幅下降——深度图这类高分辨率 16 位数据用 RVL 这类专用编解码器压缩后体积通常远小于原始像素。
官方类型定义明确给出了它的定位:
A depth image encoded with a codec (e.g. RVL, PNG, or TIFF). Rerun also supports uncompressed depth images with the
archetypes.DepthImage.
也就是说,它与未压缩的 DepthImage 原型互为补充:前者面向已编码文件,后者面向原始像素数组。
不稳定标记
该类型在类型定义源 crates/build/re_type_definitions/rerun/archetypes/encoded_depth_image.def.rs 中带有#[rerun(state = "unstable")]标记,文档中也明确警告:
⚠️This type isunstableand may change significantly in a way that the data won't be backwards compatible.
使用它记录的.rrd数据在后续版本中可能无法向后兼容,适合实验性/内部数据管线,若追求长期存档稳定性应优先考虑稳定的未压缩DepthImage。
字段详解(8 个组件)
EncodedDepthImage共由 8 个字段构成,它们在类型定义中的组织结构(必选 1 + 推荐 2 + 可选 5)与生成的 Rust SDK 代码(见 crates/store/re_sdk_types/src/archetypes/encoded_depth_image.rs 中的REQUIRED_COMPONENTS/RECOMMENDED_COMPONENTS/OPTIONAL_COMPONENTS)完全一致。
必选字段
| 字段 | 组件类型 | 说明 |
|---|---|---|
blob | Blob | 编码后的深度图像完整文件字节。定义中标注了no_ui_edit(不可在 UI 中手工编辑),因为它是原始字节负载 |
在 Python SDK 中它是唯一的必选位置参数(rerun_py/rerun_sdk/rerun/archetypes/encoded_depth_image.py),其余字段均为关键字参数。
推荐字段
| 字段 | 组件类型 | 说明 |
|---|---|---|
media_type | MediaType | blob 的媒体类型,取值:application/rvl(RVL 压缩 16 位)、image/png、image/tiff |
meter | DepthMeter | 深度图原生单位到米的换算系数,如毫米对应0.001 |
media_type是 Viewer 选择解码器的依据(详见下文可视化器源码)。meter的默认行为在 SDK 文档与类型定义中均有明确说明:省略时,Viewer 对浮点深度格式默认取1.0,对整数格式默认取1000.0(即毫米)。
DepthMeter组件本身的语义在 crates/build/re_type_definitions/rerun/components/depth_meter.def.rs 中有更精确的定义:
The world->depth map scaling factor. This measures how many depth map units are in a world unit. For instance, if a depth map uses millimeters and the world uses meters, this value would be
1000.
它在 2D 视图与 3D 视图中的作用不同:2D 视图中仅影响鼠标悬停时显示的物理深度数值;3D 视图中则直接决定点云投影时每个点的空间位置。
可选字段
| 字段 | 组件类型 | 说明 |
|---|---|---|
colormap | Colormap | 解码后深度值映射到颜色所用的色图 |
depth_range | ValueRange | 深度值的可视化范围(用于色图映射的上下界) |
point_fill_ratio | FillRatio | 点云投影时的点填充率 |
draw_order | DrawOrder | 2D 绘制顺序 |
magnification_filter | MagnificationFilter | 2D 视图中纹素放大时的过滤方式;在 3D 视图中无效 |
magnification_filter还有一个值得注意的实现细节(见 Rust 生成代码注释):过滤器作用于标量深度值、在经色图映射为颜色之前,且只在 2D 视图中生效。
Colormap组件(crates/build/re_type_definitions/rerun/components/colormap.def.rs)是 12 个枚举值构成的稳定类型,含Grayscale、Inferno、Magma、Plasma、默认值Turbo、Viridis、CyanToYellow、Spectral、Twilight,以及面向 SLAM 栅格地图的RvizMap、RvizCostmap和Costmap。
完整可运行的示例
文档核心示例在仓库中有 Python / Rust / C++ 三个版本,下面完整给出。三者逻辑一致:读取命令行参数指定的.png或.rvl深度文件 → 按扩展名选择media_type→ 以meter=0.001记录到depth/encoded实体。
Python 示例
源码见 docs/snippets/all/archetypes/encoded_depth_image.py:
"""Log an encoded depth image stored as a 16-bit PNG or RVL file.""" import sys from pathlib import Path import rerun as rr if len(sys.argv) < 2: print( f"Usage: {sys.argv[0]} <path_to_depth_image.[png|rvl]>", file=sys.stderr ) sys.exit(1) depth_path = Path(sys.argv[1]) rr.init("rerun_example_encoded_depth_image", spawn=True) depth_png = depth_path.read_bytes() if depth_path.suffix.lower() == ".png": media_type = rr.components.MediaType.PNG else: media_type = rr.components.MediaType.RVL rr.log( "depth/encoded", rr.EncodedDepthImage( blob=depth_png, media_type=media_type, meter=0.001, ), )Python 侧EncodedDepthImage的构造签名(来自 rerun_py/rerun_sdk/rerun/archetypes/encoded_depth_image.py)为:
EncodedDepthImage( blob: BlobLike, # 必选:编码后图片的字节 *, media_type: Utf8Like | None = None, meter: Float32Like | None = None, colormap: ColormapLike | None = None, depth_range: Range1DLike | None = None, point_fill_ratio: Float32Like | None = None, draw_order: Float32Like | None = None, magnification_filter: MagnificationFilterLike | None = None, )所有可选参数默认None,即交给 Viewer 端回退(fallback)逻辑决定默认值。
Rust 示例
源码见 docs/snippets/all/archetypes/encoded_depth_image.rs:
//! Log an encoded depth image stored as a 16-bit PNG or RVL file use rerun::external::anyhow; fn main() -> anyhow::Result<()> { let args = _args; let Some(path) = args.get(1) else { anyhow::bail!("Usage: {} <path_to_depth_image.[png|rvl]>", args[0]); }; let rec = rerun::RecordingStreamBuilder::new("rerun_example_encoded_depth_image") .spawn()?; let is_png = std::path::Path::new(path) .extension() .is_some_and(|ext| ext.eq_ignore_ascii_case("png")); let depth_blob = std::fs::read(path)?; let encoded_depth = rerun::EncodedDepthImage::new(depth_blob) .with_media_type(if is_png { rerun::components::MediaType::PNG } else { rerun::components::MediaType::RVL }) .with_meter(0.001_f32); rec.log("depth/encoded", &encoded_depth)?; Ok(()) }Rust 生成代码为每个字段都提供了.with_xxx(...)与.with_many_xxx(...)两种构造方法(见 crates/store/re_sdk_types/src/archetypes/encoded_depth_image.rs):前者用于单行数据,后者配合columns()/columns_of_unit_batches()用于RecordingStream::send_columns列式批量发送场景。
C++ 示例
源码见 docs/snippets/all/archetypes/encoded_depth_image.cpp:
//! Log an encoded depth image stored as a 16-bit PNG or RVL file #include <rerun.hpp> #include <filesystem> #include <fstream> #include <iostream> #include <vector> namespace fs = std::filesystem; int main(int argc, char* argv[]) { if (argc < 2) { std::cerr << "Usage: " << argv[0] << " <path_to_depth_image.[png|rvl]>" << std::endl; return 1; } const auto rec = rerun::RecordingStream("rerun_example_encoded_depth_image"); rec.spawn().exit_on_failure(); const auto depth_path = fs::path(argv[1]); std::ifstream file(depth_path, std::ios::binary); if (!file) { std::cerr << "Failed to open encoded depth image: " << depth_path << std::endl; return 1; } std::vector<uint8_t> bytes{ std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>() }; // Determine media type based on file extension rerun::MediaType media_type; if (depth_path.extension() == ".png") { media_type = rerun::MediaType::png(); } else { media_type = rerun::MediaType::rvl(); } rec.log( "depth/encoded", rerun::archetypes::EncodedDepthImage() .with_blob(rerun::components::Blob( rerun::Collection<uint8_t>::take_ownership(std::move(bytes)) )) .with_media_type(media_type) .with_meter(0.001f) ); }C++ 头文件 rerun_cpp/src/rerun/archetypes/encoded_depth_image.hpp 与 Rust 端对称地提供了with_blob、with_media_type、with_meter等构建器方法。
便捷构造:from_file与from_file_contents
除了手工指定media_type,Rust SDK 还提供了自动推断媒体类型的便捷构造,实现在 crates/store/re_sdk_types/src/archetypes/encoded_depth_image_ext.rs:
pub fn from_file(filepath: impl AsRef<std::path::Path>) -> std::io::Result<Self> { let filepath = filepath.as_ref(); let contents = std::fs::read(filepath)?; Ok(Self::from_file_contents(contents)) } pub fn from_file_contents(bytes: Vec<u8>) -> Self { #[cfg(feature = "image")] { if let Some(media_type) = image::guess_format(&bytes) .ok() .map(|format| crate::components::MediaType::from(format.to_mime_type())) { return Self::new(bytes).with_media_type(media_type); } } Self::new(bytes) }两个方法的行为与适用场景:
from_file(path):直接读取文件路径,内部复用from_file_contents;非 wasm32 目标可用(#[cfg(not(target_arch = "wasm32"))]),因为它依赖std::fs文件系统访问;from_file_contents(bytes):对给定字节调用image::guess_format从文件头魔数推断媒体类型并自动写入media_type;推断失败(例如 RVL 字节流无法被imagecrate 识别)时回退为不设置media_type,此时需依赖 Viewer 端对未知媒体类型的处理或手动补充。
注意该推断路径依赖imagefeature;即便推断失败,EncodedDepthImage::new(bytes)也能正常构造,仅media_type为空。
Viewer 端解码与渲染管线
可视化器与支持视图
根据文档,EncodedDepthImage可在以下视图中显示:
- Spatial2DView(始终可用)
- Spatial3DView(需在投影(projection)下记录)
- DataframeView
对应地,Viewer 端可视化器为 crates/views/re_view_spatial/src/visualizers/video/encoded_depth_image.rs,其affinity()声明与SpatialView2D绑定,visualizer_query_info()声明以Blob为唯一必需组件进行查询。
解码与着色配置
从可视化器实现可以看出整个渲染链路的关键设计:
- 解码器选择:
get_codec回调读取media_type组件,将其转换为re_video::VideoCodec::ImageSequence(codec),即把编码深度图作为"图像序列"经由统一的视频流式管线(execute_video_stream_like)解码渲染; - 深度配置:
get_depth_config回调一次性读取colormap、depth_range、meter(DepthMeter)与point_fill_ratio(FillRatio)四个组件,组合成DepthTextureConfig交给渲染后端;其中colormap通过colormap_to_re_renderer转换为渲染器色图,value_range从ValueRange解包为[f32; 2]; - 回退机制:
colormap、depth_range、depth_meter均通过typed_fallback_for提供缺省值,fill_ratio缺省为Default::default()——这正是各可选/推荐字段可以省略的原因。
测试用例佐证
仓库中的集成测试 crates/views/re_view_spatial/tests/encoded_depth_image.rs 验证了 TIFF 路径的端到端行为:测试用tiff::encoder生成一张 64×48 的 Gray32Float 灰度斜坡图(0 到 4 米水平深度渐变),以EncodedDepthImage::new(...).with_media_type(MediaType::tiff()).with_meter(1.0)记录到depth实体,在SpatialView2D中渲染并与基线快照比对(encoded_depth_image_tiff)。对应快照文件位于 crates/views/re_view_spatial/tests/snapshots/encoded_depth_image_tiff.png,测试注释还特别说明解码发生在独立线程、渲染存在软硬件光栅化差异(CI 的 llvmpipe 与 Metal 之间最多约 920 像素位移)。
此外,仓库测试资产 tests/assets/encoded_depth_image.rvl 提供了一份可直接使用的 RVL 编码深度样例文件,可用于快速跑通上述三个语言版本的示例脚本。
数据支持格式小结
综合类型定义(encoded_depth_image.def.rs)与 SDK 文档注释,blob目前支持:
| 格式 | media_type | 说明 |
|---|---|---|
| PNG | image/png | 单通道(single channel)PNG |
| TIFF | image/tiff | 单通道 TIFF,样本类型支持U8、U16、F32 |
| RVL | application/rvl | RVL 压缩 16 位深度,可携带 ROS2 元数据(参见 ROS2 image_transport_plugins) |
其中 RVL 常用于 ROS2 生态深度图像传输,这也是该项目在机器人多模态数据可视化场景下优先支持该格式的重要原因。
常见使用模式与注意事项
- 最小可用记录:仅传
blob即可记录;不传media_type时 Viewer 按未知媒体类型处理,建议总是显式给出以命中正确解码器; - 单位换算务必正确:
meter直接决定 3D 点云的空间尺度。毫米图省略该字段时 Viewer 默认按1000.0处理、浮点图默认按1.0处理,与你设备实际单位不符时会出现深度被放大/缩小千倍的投影错误; - 2D/3D 差异:
magnification_filter只影响 2D 放大显示效果;meter在 2D 仅影响悬停读数,在 3D 影响点云几何; - 不稳定 API:该类型带 unstable 标记,升级 SDK 版本后旧记录可能无法读取,长期存档请评估使用稳定的
DepthImage原型; - 查看方式:记录后可先在 Spatial2DView 中直接观察解码着色结果;需要 3D 点时云请将实体置于投影关系之下,再以 Spatial3DView 呈现。
延伸阅读
- 未压缩深度图原型:docs/content/reference/types/archetypes/depth_image.md
- 类型定义源(Rust DSL):crates/build/re_type_definitions/rerun/archetypes/encoded_depth_image.def.rs
- Rust 生成 API:crates/store/re_sdk_types/src/archetypes/encoded_depth_image.rs 与便捷构造扩展 encoded_depth_image_ext.rs
- Python 生成 API:rerun_py/rerun_sdk/rerun/archetypes/encoded_depth_image.py
- C++ 头文件:rerun_cpp/src/rerun/archetypes/encoded_depth_image.hpp
- Viewer 可视化器实现:crates/views/re_view_spatial/src/visualizers/video/encoded_depth_image.rs
- 集成测试与快照:crates/views/re_view_spatial/tests/encoded_depth_image.rs、encoded_depth_image_tiff.png
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考