Camera 数据格式全解:Raw、YUV、RGB 与色彩空间转换
一、数据流水线总览
传感器 → Raw Bayer → ISP 处理 → RGB → 色彩空间转换 → YUV
↓ ↓
直接输出 编码/显示
Camera 系统中的图像数据经历三个阶段:
- Sensor 输出 Raw Bayer — 每像素单通道原始数据
- ISP 处理得到 RGB — demosaic + 图像增强
- 色彩空间转换得到 YUV — 为编码和显示优化
二、Raw 数据格式
Raw 是图像传感器直接输出的未经处理的原始数据。每个像素只记录一个颜色通道的值(通过 Bayer 滤镜阵列)。
2.1 Bayer 排列模式
传感器上的 Bayer 滤镜有 4 种排列方式(指 2x2 单元的起始顺序):
RGGB: BGGR: GRBG: GBRG:
┌───┬───┐ ┌───┬───┐ ┌───┬───┐ ┌───┬───┐
│ R │ G │ │ B │ G │ │ G │ R │ │ G │ B │
├───┼───┤ ├───┼───┤ ├───┼───┤ ├───┼───┤
│ G │ B │ │ G │ R │ │ B │ G │ │ R │ G │
└───┴───┘ └───┴───┘ └───┴───┘ └───┴───┘
| 模式 | V4L2 格式前缀 | 典型 Sensor |
|---|---|---|
| RGGB | SRGGB |
IMX477 |
| BGGR | SBGGR |
IMX219 |
| GRBG | SGRBG |
AR0234 |
| GBRG | SGBRG |
OV5647 |
2.2 位深度变体
| 位深 | 值范围 | V4L2 示例 | 存储方式 |
|---|---|---|---|
| 8-bit | 0-255 | V4L2_PIX_FMT_SRGGB8 |
每像素 1 字节,紧凑排列 |
| 10-bit | 0-1023 | V4L2_PIX_FMT_SRGGB10 |
16-bit 容器,高位或低位对齐 |
| 10-bit packed | 0-1023 | V4L2_PIX_FMT_SRGGB10P |
每 4 像素占 5 字节 |
| 12-bit | 0-4095 | V4L2_PIX_FMT_SRGGB12 |
16-bit 容器 |
| 12-bit packed | 0-4095 | V4L2_PIX_FMT_SRGGB12P |
每 2 像素占 3 字节 |
| 14-bit | 0-16383 | V4L2_PIX_FMT_SRGGB14 |
16-bit 容器 |
| 16-bit | 0-65535 | V4L2_PIX_FMT_SRGGB16 |
原生 16-bit |
2.3 Packed vs Unpacked 存储
10-bit Packed(每 4 像素 = 5 字节):
字节0: [P0 高8位]
字节1: [P1 高8位]
字节2: [P2 高8位]
字节3: [P3 高8位]
字节4: [P0低2 | P1低2 | P2低2 | P3低2]
文件大小 = width × height × 10 / 8
10-bit Unpacked(每像素 = 2 字节):
字节0-1: P0 (uint16, 高6位补零或左移)
字节2-3: P1 (uint16)
...
文件大小 = width × height × 2
Packed 省空间(节省 25%),Unpacked 方便处理(直接当 uint16 数组读取)。
三、YUV 数据格式
YUV 将亮度(Y)和色度(U/V,也称 Cb/Cr)分离。人眼对亮度更敏感,因此色度可以降采样以节省带宽。
3.1 色度采样方式
4:4:4 — 每个像素都有完整的 Y、U、V(无压缩)
4:2:2 — 水平方向每 2 个像素共享一组 UV(色度水平减半)
4:2:0 — 每 2x2 像素块共享一组 UV(色度水平和垂直都减半)
4:1:1 — 水平方向每 4 个像素共享一组 UV(较少使用)
视觉对比:
原始像素: ● ● ● ●
● ● ● ●
4:4:4 色度: ◆ ◆ ◆ ◆ 每个像素都有独立 UV
◆ ◆ ◆ ◆
4:2:2 色度: ◆ ◆ 水平每 2 像素共享
◆ ◆
4:2:0 色度: ◆ ◆ 2x2 块共享一个 UV
3.2 Packed 格式(交织存储)
Y 和 UV 数据交织在同一平面中,每 2 个像素为一组:
| 格式 | 字节排列(每 2 像素) | 采样 | 每像素字节 |
|---|---|---|---|
| YUYV (YUY2) | Y0 U0 Y1 V0 | 4:2:2 | 2 |
| UYVY | U0 Y0 V0 Y1 | 4:2:2 | 2 |
| YVYU | Y0 V0 Y1 U0 | 4:2:2 | 2 |
| VYUY | V0 Y0 U0 Y1 | 4:2:2 | 2 |
YUYV 是 USB 摄像头(UVC)最常见的输出格式。
3.3 Semi-Planar 格式(半平面)
Y 单独一个平面,UV 交织在第二个平面:
| 格式 | 平面结构 | 采样 | 每像素字节 |
|---|---|---|---|
| NV12 | Plane0: YYYY… Plane1: UVUV… | 4:2:0 | 1.5 |
| NV21 | Plane0: YYYY… Plane1: VUVU… | 4:2:0 | 1.5 |
| NV16 | Plane0: YYYY… Plane1: UVUV… | 4:2:2 | 2 |
| NV61 | Plane0: YYYY… Plane1: VUVU… | 4:2:2 | 2 |
NV12 是硬件编解码器(H.264/H.265)的首选输入格式。
3.4 Planar 格式(全平面)
Y、U、V 各自独立存储在不同平面:
| 格式 | 平面结构 | 采样 | 每像素字节 |
|---|---|---|---|
| YU12 (I420) | Y / U / V | 4:2:0 | 1.5 |
| YV12 | Y / V / U | 4:2:0 | 1.5 |
| YUV422P | Y / U / V | 4:2:2 | 2 |
| YUV444P | Y / U / V | 4:4:4 | 3 |
I420 是软件编解码(FFmpeg/x264)常用格式。
3.5 内存布局示例(4x2 图像)
YUYV (4:2:2 packed):
字节流: Y00 U00 Y01 V00 | Y02 U02 Y03 V02
Y10 U10 Y11 V10 | Y12 U12 Y13 V12
总大小: 4 × 2 × 2 = 16 字节
NV12 (4:2:0 semi-planar):
Y 平面: Y00 Y01 Y02 Y03
Y10 Y11 Y12 Y13
UV 平面: U00 V00 U02 V02 ← 2x2 像素块共享一组 UV
总大小: (4×2) + (4×1) = 12 字节 = 4×2×1.5
I420 (4:2:0 planar):
Y 平面: Y00 Y01 Y02 Y03
Y10 Y11 Y12 Y13
U 平面: U00 U02 ← 宽高各减半
V 平面: V00 V02
总大小: 8 + 2 + 2 = 12 字节
四、RGB 数据格式
RGB 是 ISP demosaic 后的直接产物,每个像素包含完整的红、绿、蓝三通道值。
4.1 常见 RGB 格式
| 格式 | 每像素字节 | 位分配 | 典型用途 |
|---|---|---|---|
| RGB24 (RGB888) | 3 | R:8 G:8 B:8 | 通用图像处理 |
| BGR24 | 3 | B:8 G:8 R:8 | OpenCV 默认 |
| ARGB32 (RGB8888) | 4 | A:8 R:8 G:8 B:8 | 带透明度合成 |
| RGB565 | 2 | R:5 G:6 B:5 | 嵌入式 LCD 显示 |
| RGB444 | 2 | R:4 G:4 B:4 | 低端显示 |
4.2 为什么大多数 camera 输出 YUV 而不是 RGB
| 原因 | 说明 |
|---|---|
| 带宽小 | YUV 4:2:0 比 RGB24 节省 50% 数据量 |
| 编码友好 | H.264/H.265 编码器直接接受 YUV 输入 |
| 符合人眼特性 | 人眼对亮度敏感、对色度不敏感 |
| 视频标准 | 电视、监控历史上就是 YUV 体系 |
五、色彩空间转换(CSC)
5.1 转换公式
RGB → YUV(BT.601 标准):
Y = 0.299R + 0.587G + 0.114B
U = -0.169R - 0.331G + 0.500B + 128
V = 0.500R - 0.419G - 0.081B + 128
YUV → RGB(反向):
R = Y + 1.402(V - 128)
G = Y - 0.344(U - 128) - 0.714(V - 128)
B = Y + 1.772(U - 128)
硬件实现时用定点数矩阵运算,一个时钟周期完成。
5.2 谁来完成色彩空间转换
色彩空间转换可以在多个环节完成:
1. ISP 硬件(最常见)
大多数 SoC 的 ISP 内部集成了 CSC 模块,demosaic 得到 RGB 后直接在硬件流水线内转成 YUV 输出。零 CPU 开销,实时处理。
2. 专用硬件转换模块
有些 SoC 有独立于 ISP 的 CSC 硬件:
| 平台 | CSC 硬件模块 | 功能 |
|---|---|---|
| NXP i.MX | PXP (Pixel Pipeline) / GPU 2D | CSC + 缩放 + 旋转 |
| Rockchip (RK3588等) | RGA (Raster Graphic Acceleration) | CSC + 缩放 + 旋转 + 合成 |
| TI (AM62x/AM68x) | VPAC ISP + DSS | ISP 处理 + 显示 CSC |
| Allwinner (H616等) | G2D + DE (Display Engine) | 2D 加速 + 显示 CSC |
| Samsung (Exynos) | FIMC / M2M Scaler | CSC + 缩放 |
| MediaTek | MDP (Media Data Path) | CSC + 缩放 + 旋转 |
| Intel (x86) | GPU EU + 显示引擎 | 通用计算 + 显示 CSC |
3. 显示控制器内部 CSC
显示时需要将 YUV 转回 RGB 送屏幕,由显示控制器硬件完成:
ISP 输出 NV12 → 显示控制器(CSC) → RGB → LCD/HDMI
4. GPU(shader)
通过 OpenGL ES shader 做矩阵运算,适合相机预览渲染。
5. CPU 软件
用库函数做转换(FFmpeg libswscale、OpenCV cvtColor、libyuv)。灵活但吃 CPU,仅用于调试或低帧率场景。
5.3 典型数据流
摄像头 Sensor → Raw Bayer
↓
ISP (demosaic → RGB → CSC) → NV12
↓ ↓
H.264 编码器 显示控制器 (CSC: YUV→RGB) → HDMI/LCD
六、树莓派的 CSC 硬件
树莓派 (Broadcom BCM2835/2837/2711/2712) 有多个硬件模块可以做色彩空间转换:
6.1 VideoCore ISP
VideoCore GPU 内置 ISP,通过 V4L2 M2M 设备节点暴露(/dev/video12、/dev/video13 等):
- Demosaic(Raw → RGB)
- RGB ↔ YUV 转换
- 缩放、裁剪、降噪
在 libcamera 框架下,应用把 Raw Bayer 送进去,拿到 YUV/RGB 输出。
6.2 HVS(Hardware Video Scaler)
显示流水线中的硬件模块:
- YUV → RGB 转换(送显示器前)
- 缩放、合成多个图层
6.3 H.264/H.265 编解码器
编码器前端自带格式转换,接受特定 YUV 格式输入。
6.4 树莓派实际数据流
摄像头 Sensor → Raw Bayer
↓
VideoCore ISP (M2M) → NV12
↓ ↓
H.264 编码器 HVS (YUV→RGB) → HDMI/DSI 显示
整条流水线都是硬件完成,CPU 基本不参与像素处理。
七、数据量对比(1920x1080)
| 格式 | 计算 | 大小 |
|---|---|---|
| Raw 8-bit | 1920×1080×1 | 2.0 MB |
| Raw 10-bit packed | 1920×1080×10/8 | 2.5 MB |
| Raw 10-bit unpacked | 1920×1080×2 | 4.1 MB |
| YUV 4:2:0 (NV12) | 1920×1080×1.5 | 3.1 MB |
| YUV 4:2:2 (YUYV) | 1920×1080×2 | 4.1 MB |
| YUV 4:4:4 | 1920×1080×3 | 6.2 MB |
| RGB24 | 1920×1080×3 | 6.2 MB |
| ARGB32 | 1920×1080×4 | 8.3 MB |
八、实际使用场景总结
| 格式 | 典型场景 |
|---|---|
| Raw Bayer | ISP 输入、专业摄影后期、需要最大灵活性 |
| NV12/NV21 | 硬件编解码器输入、Android Camera HAL 默认输出 |
| YUYV | USB 摄像头(UVC)最常见输出 |
| I420 | 软件编解码(FFmpeg/x264) |
| RGB24/BGR24 | 图像处理、OpenCV、神经网络推理输入 |
| RGB565 | 嵌入式 LCD 直接显示 |
九、V4L2 中查看和设置格式
# 查看设备支持的格式
v4l2-ctl -d /dev/video0 --list-formats-ext
# 设置捕获格式为 NV12
v4l2-ctl -d /dev/video0 --set-fmt-video=width=1920,height=1080,pixelformat=NV12
# 设置捕获格式为 YUYV
v4l2-ctl -d /dev/video0 --set-fmt-video=width=640,height=480,pixelformat=YUYV
# Media Controller 中设置 media bus format
media-ctl -d /dev/media0 -V '"sensor":0 [fmt:SRGGB10_1X10/1920x1080]'
media-ctl -d /dev/media0 -V '"isp":1 [fmt:UYVY8_1X16/1920x1080]'
Date: