一、RGB 的物理含义
RGB 是加色模型:三种颜色的光叠加在一起,越叠越亮。
红 (R)
/ \
/ \
黄 洋红
| |
绿 ──── 白 ──── 蓝
| |
青 蓝 (B)
\ /
\ /
绿 (G)
显示器的工作原理:每个像素由三个子像素(红/绿/蓝 LED)组成,通过控制亮度百分比混合出各种颜色。
在内存中的排列(C++ 处理时直接面对):
// RGB24:每个像素 3 字节,R/G/B 各 8 bit
struct RGBPixel {
uint8_t r, g, b; // 内存顺序取决于平台
};
// OpenCV 是 BGR 顺序
struct BGRPixel {
uint8_t b, g, r; // 注意:蓝在前,红在后
};
// RGBA:每个像素 4 字节,多一个 Alpha(透明度)
struct RGBAPixel {
uint8_t r, g, b, a;
};
// 一行 1920×1080 RGB 图片的内存布局
// [R][G][B][R][G][B][R][G][B]......[R][G][B]
// \___________ 1920 × 3 = 5760 字节 ___________/
// 然后下一行
二、RGB 为什么不适合视频编码?
你提到的这个问题确实是很多初学者容易困惑的地方。简单说:RGB 把宝贵的带宽浪费在了人眼不敏感的信息上,而且三个通道之间有大量重复信息。
下面我用更直观的方式再解释一下,配合具体数字和比喻,应该能帮你彻底理解。
🧠 核心问题一:人眼的敏感度差异
人眼对 亮度(Luma) 非常敏感,但对 颜色(Chroma) 的敏感度低很多。
用一张图来感受:
- 一张黑白照片(只有亮度):你能看清所有细节、边缘、纹理。
- 一张只有颜色涂抹的照片(没有亮度):你根本看不清内容,只看到模糊的色块。
RGB 编码时,每个像素的 R/G/B 都保存了全部信息(亮度+颜色混在一起),相当于把颜色信息和亮度信息用同等精度存储。但人眼根本不需要那么精细的颜色细节——这就等于浪费了 2/3 的带宽(因为颜色信息可以大幅压缩)。
比喻:
你买了一套菜谱,里面每道菜都附了三张照片:一张是菜的全貌(亮度),一张专门拍红色调料(颜色细节),一张专门拍绿色蔬菜(颜色细节)。你其实只需要看全貌就知道怎么做菜了,那两张颜色特写只有在你纠结调料放多少时才需要——平时根本用不上。RGB 就是把那两张颜色特写也一直带着,平白占地方。
🔗 核心问题二:三个分量高度相关
想象一张蓝天白云的图片:
- R 分量:天空部分接近 100~150,白云部分接近 255
- G 分量:天空部分接近 150~200,白云部分接近 255
- B 分量:天空部分接近 200~255,白云部分接近 255
三个分量的数值在同一个区域里总是同步变化(要么都高,要么都低)。编码器要分别描述 R、G、B 三个通道,就等于 “用三句话描述同一件事”——比如“天空的 R 是 150,G 是 180,B 是 220”,但其实这三句话说到底都是在描述“蓝色的天空”这一件事。
而 YUV 把亮度(Y)和颜色(UV)分开后:
- Y 通道描述“天空有多亮”(从亮到暗的变化)——这是人眼最在意的。
- U、V 通道只描述“偏蓝还是偏红”——数值变化很小,而且 U/V 之间相关性很低,可以用更少的数据表示。
比喻:
你拍了一张风景照,你想发给朋友看。你可以这样描述:
“这张照片的上半部分是蓝色(RGB 三通道都高),下半部分是绿色(RGB 三通道都低)。”
但如果你用 YUV 描述:
“上面的亮度很高,颜色偏蓝;下面的亮度中等,颜色偏绿。”
后者只需要记录“亮度 + 颜色偏差”,数据量自然就小了。
📉 数字对比:为什么 RGB 效率低
以一张 1920×1080 的图片为例:
| 格式 | 每像素数据量 | 总大小(未压缩) | 特点 |
|---|---|---|---|
| RGB24 | 3 字节 | 1920×1080×3 = 6.2 MB | 全部保留 |
| YUV 4:4:4 | 3 字节 | 6.2 MB(没省) | 亮度/颜色分离,但未压缩 |
| YUV 4:2:0 | 1.5 字节 | 3.1 MB | 压缩后省 50%,人眼几乎看不出区别 |
重点:
RGB 没有利用“人眼对颜色不敏感”的特性,所以即使压缩到极限(比如 JPEG 压缩),也是先转成 YUV 再压缩才能高效。几乎所有视频编码标准(H.264/H.265/AV1)内部都是基于 YUV 处理的,而不是 RGB。
🛠 实际编码中的影响
如果你直接拿 RGB 做视频编码:
- 码率浪费:同样画质下,RGB 编码需要的码率大约是 YUV 4:2:0 的 2~3 倍。
- 压缩效率低:因为 RGB 三个通道相关性太强,编码器很难像处理 YUV 那样用“色度下采样”来省带宽。
- 兼容性差:绝大多数硬件编码器(如 NVENC、QuickSync、VideoToolbox)只支持 YUV 输入,你必须先转格式。
✅ 总结一句话
RGB 不适合视频编码,因为它的三个分量对人眼同等重要(浪费了颜色冗余),且分量之间高度相关(重复描述天空的颜色)。而 YUV 把亮度单独拿出来精细保存,颜色降低分辨率,省了一半带宽且画质无损。
如果你还有具体哪一点不清楚(比如 U/V 到底怎么省带宽的、或者转换公式),可以继续问,我会用更具体的代码或图示帮你理解。