十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Rerun PixelFormat 全解析:YUV 色度采样、取值范围与图像随机访问编码

Rerun PixelFormat 全解析:YUV 色度采样、取值范围与图像随机访问编码 Rerun PixelFormat 全解析YUV 色度采样、取值范围与图像随机访问编码【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun本文以 Rerun 可视化 SDK 中的encodings.PixelFormat枚举官方类型参考为核心系统讲解其在多模态机器人数据可视化中处理 YUV/灰度图像的职责如何描述色度下采样chroma subsampling、每通道位深差异与 limited/full range 取值并结合仓库源码与示例说明各变体的内存布局、随机访问解码原理及在rr.Image/ImageFormat中的实际用法。读完本文你将能够为 Rerun 的Image组件正确指定像素格式、理解ImageFormat字段的优先级关系并掌握decode_rgb_at、GPU 端yuv_converter.wgsl等底层实现的原理与边界。一、PixelFormat 是什么为什么需要它PixelFormat是 Rerun 数据模型re_types中用于描述archetypes.Image特定存储格式的枚举类型。大多数图像可以仅用两个枚举描述清楚色彩模型encodings.ColorModel如L、RGB、RGBA加上通道数据类型encodings.ChannelDatatype如U8、F16。但当图像格式存在两类特殊性质时仅靠这两个枚举就不够了色度下采样chroma subsampling为了压缩带宽YUV 类格式常让色度通道U/V的分辨率低于亮度通道Y如 4:2:0、4:2:2。每通道位数差异与取值范围部分格式使用 limited range YUV8bit 下 Y 有效区间 [16, 235]、U/V 有效区间 [16, 240]而另一些使用 full range0~255。这正是PixelFormat存在的原因。在官方文档中明确写到所有这些格式都支持随机访问random access——即可以不经过整帧解码直接按坐标取出任意像素。对于更压缩的编码格式JPEG/PNG 等Rerun 则使用archetypes.EncodedImage二者是互补关系。补充说明Rerun 仓库代码中常以YUV/YCbCr/YPbPr混用称呼这一色彩空间。在 yuv_converter.rs 的注释中给出了严格定义YUV是模拟信号YCbCr是数字信号中经过缩放与偏移的版本即本文所说的 limited range YUVYPbPr是传输YCbCr的物理分量线缆。实际业界用法比较混乱例如 OpenCV 在讨论全范围时使用YCbCr讨论下采样时使用YUV。二、全部 10 个变体逐一详解PixelFormat共定义 10 个变体对应的 Rust 定义位于 pixel_format.rs以下数值即其在 Arrow 数据中的原始枚举值#[repr(u8)]。2.1 4:2:0 平面planar格式变体数值别名rangeY_U_V12_LimitedRange20I420limitedY_U_V12_FullRange44I420fullNV1226Y_UV12limitedYUY227YUYV、YUYV16、NV21limitedY_U_V12_LimitedRange20即I420YUV 4:2:0 全平面fully planar格式无交错。整个图像先以 Y 单独占一个平面随后是 U 平面与 V 平面U/V 平面的宽高都只有 Y 平面的一半。使用 limited range YUV。Y_U_V12_FullRange44与上面相同的I420平面布局但改用 full range0~255与NV12的 limited range 形成对照。NV1226又名Y_UV12YUV 4:2:0 下采样、12 bits/pixel、8 bits/channel 的半平面semi-planar格式也是该枚举的默认变体在 Rust 定义中以#[default]标注见 pixel_format.rs。内存布局为先是整幅图像的 Y 平面随后是一个交错平面顺序为U0, V0, U1, V1, …。使用 limited range YUV。这是摄像头/视频采集中最常见的格式之一仓库示例 examples/python/nv12/nv12.py 即演示了如何把 webcam 帧转成 NV12 后流式送入 Rerun。YUY227别名YUYV、YUYV16、NV21YUV 4:2:2 下采样、16 bits/pixel、8 bits/channel 的**单平面交错interleaved**格式。像素序列为Y0, U0, Y1, V0全部位于同一平面。使用 limited range YUV。注意仓库文档特别提醒YUY2常被误称为NV21两者命名虽有混淆但YUY2在 Rerun 中即指 4:2:2 交错格式。2.2 4:4:4 平面格式变体数值别名rangeY_U_V24_LimitedRange39I444limitedY_U_V24_FullRange40I444fullY_U_V24_LimitedRange39/Y_U_V24_FullRange40Y_U_V24是 YUV 4:4:4 全平面格式无任何色度下采样别名I444。内存布局为先是完整 Y 平面随后是 U 平面、V 平面各平面尺寸相同。区别仅在于前者使用 limited rangeY ∈ [16,235]U/V ∈ [16,240]后者使用 full range0~255。2.3 4:2:2 平面格式变体数值别名rangeY_U_V16_LimitedRange49I422limitedY_U_V16_FullRange50I422fullY_U_V16_LimitedRange49/Y_U_V16_FullRange50Y_U_V16是 YUV 4:2:2 全平面格式别名I422。布局为 Y 平面后跟 U、V 平面U/V 平面只有 Y 平面水平分辨率的一半垂直分辨率相同。两者仅在 YUV range 上不同。2.4 灰度monochrome格式变体数值别名rangeY8_FullRange30gray / I400fullY8_LimitedRange41gray / I400limitedY8_FullRange30只有 Y 平面、无任何色度的单色格式本质上等价于 YUV 4:0:0 平面格式也常被直接称为 gray。它与 8bit 亮度/灰度ColorModel几乎完全一致使用 full rangeY ∈ [0, 255]。Y8_LimitedRange41同样只有 Y 平面的单色 gray 格式但使用 limited rangeY ∈ [16, 235]。除该范围限制/重映射外与 8bit 亮度/灰度几乎一致。2.5 变体速查总表变体数值采样结构位/像素平面数YUV range别名Y_U_V12_LimitedRange204:2:0 planar123limitedI420NV12默认264:2:0 semi-planar122limitedY_UV12YUY2274:2:2 interleaved161limitedYUYV/YUYV16/NV21Y8_FullRange304:0:0单色81fullgrayY_U_V24_LimitedRange394:4:4 planar243limitedI444Y_U_V24_FullRange404:4:4 planar243fullI444Y8_LimitedRange414:0:0单色81limitedgrayY_U_V12_FullRange444:2:0 planar123fullI420Y_U_V16_LimitedRange494:2:2 planar163limitedI422Y_U_V16_FullRange504:2:2 planar163fullI422位/像素 与 平面数 依据 pixel_format_ext.rs 中num_bytes与decode_yuv_at的实现归纳三、与 ImageFormat 的关系字段优先级PixelFormat本身不单独出现而是作为ImageFormat结构体中的一个字段使用。ImageFormat是描述components.ImageBuffer内容的元数据共 5 个字段字段Arrow 类型含义width非空UInt32图像宽度像素height非空UInt32图像高度像素pixel_formatUInt8像素格式主要用于色度下采样与每通道位深差异的格式color_modelUInt8色彩模型L、RGB、RGBA…channel_datatypeUInt8每个通道的数据类型U8、F16…关键优先级规则务必牢记一旦指定了pixel_format它优先于color_model与channel_datatype后两者将被忽略见 image_format.md 的原文说明。反过来如果只提供color_modelchannel_datatype则必须二者齐备才能完整定义像素格式。在 Rust 实现中PixelFormat的 Arrow 数据类型为UInt8见 pixel_format.rs枚举值直接以u8存储非法值在反序列化时会被拒绝missing_union_arm错误。四、随机访问解码从原始字节到 RGB官方文档强调所有PixelFormat均支持随机访问。这一能力由 pixel_format_ext.rs 中的扩展实现提供decode_yuv_at(buf, [w, h], [x, y]) - Option[u8; 3]按坐标直接取出该像素的[Y, U, V]三元组越界返回Nonedecode_rgb_at(...)在其上调用rgb_from_yuv(y, u, v, is_limited_yuv_range(), yuv_matrix_coefficients())得到[R, G, B]num_bytes([w, h])计算该格式下整幅图像的字节数见上文总表has_alpha()全部 10 个变体均返回false无 alpha 通道is_float()全部返回false均为 8bit 整型datatype()全部解码为ChannelDatatype::U8color_model()全部映射为ColorModel::RGB。4.1 各格式的坐标寻址逻辑decode_yuv_at的实现pixel_format_ext.rs清晰展示了各布局的寻址方式4:2:0 平面Y_U_V12_*Y 平面大小w*hU/V 平面大小为w*h/4水平、垂直各减半。Y 坐标y*w xU 坐标y*w/4 x/2偏移到 Y 平面之后V 坐标再偏移一个 U 平面大小。4:2:2 平面Y_U_V16_*U/V 平面大小为w*h/2仅水平减半UV 坐标(y*w x)/2。4:4:4 平面Y_U_V24_*三个平面大小相同均为w*h直接依次偏移。NV12Y 平面后接 UV 交错平面U 在w*h (y/2)*w xV 紧随其后 1。YUY2单平面交错像素偏移(y*w x)*2偶数 x 取[Y, U, V] [i, i1, i3]奇数 x 取[i, i-1, i1]。Y8_*单色直接y*w x取 YU/V 固定为128中性色度。4.2 YUV→RGB 转换矩阵与 rangedecode_rgb_at依赖两个属性pixel_format_ext.rsis_limited_yuv_range()10 个变体中所有*_LimitedRange、NV12、YUY2返回true其余返回falseyuv_matrix_coefficients()Y_U_V12/16/24_*与Y8_*使用BT.709系数而NV12与YUY2使用BT.601系数。这与 GPU 侧的着色器枚举一一对应。在 yuv_converter.rs 中YuvMatrixCoefficients定义了Identity把 YUV 当作 GBR、Bt601SDTV/Rec.601、Bt709HDTV/Rec.709三种矩阵并注明 BT.2020 尚不支持。注释解释了为什么只关心矩阵差异BT.709 与 sRGB 的原色primaries几乎一致、BT.601 PAL 与 BT.709 原色相同、BT.709 与 sRGB 的传递函数差异常被忽略因此非 HDR 内容在转换后无需额外处理。五、在 Python / Rust / C SDK 中的用法5.1 Python 示例以rr.Image指定pixel_format仓库代码片段 docs/snippets/all/archetypes/image_formats.py 演示了完整的用法import numpy as np import rerun as rr rr.init(rerun_example_image_formats, spawnTrue) # 普通 RGB 图像 image np.array( [[[x, min(255, x y), y] for x in range(256)] for y in range(256)], dtypenp.uint8, ) rr.log(image_rgb, rr.Image(image)) # 灰度只取一个通道 color_modell rr.log(image_green_only, rr.Image(image[:, :, 1], color_modell)) # 4:2:2 平面格式Y、U、V 三个平面按序拼成一个 bytes y bytes([128 for y in range(256) for x in range(256)]) u bytes([x * 2 for y in range(256) for x in range(128)]) # 水平减半 v bytes([y for y in range(256) for x in range(128)]) rr.log( image_yuv422, rr.Image( bytesy u v, width256, height256, pixel_formatrr.PixelFormat.Y_U_V16_FullRange, ), )要点传入bytes原始缓冲区时必须同时给出width、heightpixel_format一经指定color_model/channel_datatype即被忽略见第三节优先级规则Y/U/V 三个平面的长度必须与num_bytes推算一致否则后续随机访问解码会越界返回None。5.2 实战摄像头 NV12 流式可视化examples/python/nv12/nv12.py 演示了从 OpenCV 采集视频帧并转为 NV12 后实时送入 Rerunimport cv2 import numpy as np import rerun as rr def bgr2nv12(bgr: cv2.typing.MatLike) - cv2.typing.MatLike: yuv cv2.cvtColor(bgr, cv2.COLOR_BGR2YUV_I420) uv_row_cnt yuv.shape[0] // 3 uv_plane np.transpose(yuv[uv_row_cnt * 2 :].reshape(2, -1), [1, 0]) yuv[uv_row_cnt * 2 :] uv_plane.reshape(uv_row_cnt, -1) return yuv # 主循环中每帧 rr.log( NV12, rr.Image( bytesbytes(bgr2nv12(frame)), widthframe.shape[1], heightframe.shape[0], pixel_formatrr.PixelFormat.NV12, ), )这段代码把 BGR 帧先转成 I420三个平面再把 UV 两个平面重排成交错的U0,V0,U1,V1,…序列正是NV12变体期望的字节布局。运行该示例需要本机摄像头依赖pip install rerun-sdk与 OpenCV。5.3 Rust / C API 对照Rustrerun::encodings::PixelFormat枚举定义于 pixel_format.rs#[repr(u8)]保证与 ArrowUInt8存储一致扩展方法num_bytes、decode_rgb_at等见 pixel_format_ext.rs。Crerun::encodings::PixelFormat头文件位于 rerun_cpp/src/rerun通过生成的 API 与 Python/Rust 对齐。六、GPU 侧YUV 下采样格式如何被渲染PixelFormat在数据层负责描述与解码而真正的渲染转换由 GPU 完成。渲染器 yuv_converter.rs 中定义了与PixelFormat对应的YuvPixelLayout索引需与 yuv_converter.wgsl 保持同步YuvPixelLayout含义对应PixelFormat族Y_U_V4444:4:4 三平面I444Y_U_V24_*Y_U_V4224:2:2 三平面I422Y_U_V16_*Y_U_V4204:2:0 三平面I420Y_U_V12_*Y_UV4204:2:0 半平面NV12NV12YUYV4224:2:2 单平面交错YUY2Y4004:0:0 单色I400Y8_*实现要点输入数据统一以R8Uint数据纹理上传yuv_converter.rs通过data_texture_width_height把解码尺寸换算为数据纹理尺寸例如 4:2:0 为[w, h h/2]YUY2为[w*2, h]输出为Rgba8UnormsRGB 编码的 8bit 纹理yuv_converter.rsYuvRange枚举Limited/Full与YuvMatrixCoefficientsBT.601/BT.709/Identity通过 uniform buffer 传给片段着色器完成色度上采样与 YUV→RGB 矩阵换算。七、常见问题与注意事项NV12是默认变体在 Rust 定义中以#[default]标注pixel_format.rs若场景未明确指定且需要 YUV 下采样格式默认即 NV12limited range BT.601。limited vs full range 影响色彩还原同为 4:2:0 平面布局Y_U_V12_LimitedRange20与Y_U_V12_FullRange44只是取值范围不同decode_rgb_at会依据is_limited_yuv_range()选择不同的缩放/偏移路径选错会导致画面发灰或对比度异常。平面长度必须匹配num_bytes([w, h])可用于校验4:4:4 为w*h*3扩展实现为num_pixels*4含 RGB 对齐4:2:2 为16*w*h/84:2:0 为12*w*h/8灰度Y8为w*h。缓冲区过短时decode_yuv_at返回None过长的多余字节被忽略。不要混淆YUY2与NV21文档明确列出YUY2的别名包括YUYV、YUYV16与NV21业界命名混乱在 Rerun 中该变体专指 4:2:2 单平面交错格式。更压缩的格式请走EncodedImagePixelFormat面向的是支持随机访问的平面/半平面/交错 YUV 与灰度格式JPEG/PNG 等需要整帧解码的压缩图像应使用archetypes.EncodedImage。八、延伸阅读类型定义与生成说明pixel_format.def.rsre_types_builder 的元定义源解码/工具扩展方法pixel_format_ext.rsImageFormat字段与优先级image_format.mdGPU 渲染转换器yuv_converter.rs 与 yuv_converter.wgsl完整 Python 示例image_formats.py、nv12.py【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表