YUV是一种颜色空间。
- 什么是RGB? ——RGB是红绿蓝三原色的意思,R=Red、G=Green、B=Blue。
- 什么是YUV/YCbCr/YPbPr?—— 亮度信号经常被称作Y,色度信号是由两个互相独立的信号组成。视颜色系统和格式不同,两种色度信号经常被称作U和V或Pb和Pr或Cb和Cr。这些都是由不同的编码格式所产生的,但是实际上,他们的概念基本相同。在DVD中,色度信号被存储成Cb和Cr(C代表颜色,b代表蓝色,r代表红色)。
YUV格式
-
planar:平面模式,先存储所有的Y,再存所有的U,然后V。比如 Y0Y1....Yn U0U1...Um V0V1..Vm。
这种模式有利于编解码的输入输出。(个人觉得区分开三个通道,从算法复杂度上,有利于帧内编码压缩和帧间压缩等)
-
packed:打包模式,交替存储每一个像素的Y/U/V三个通道。比如 Y0U0V0 + Y1U1V1 + ... + YnUnVn。
这种模式有利于视频数据采集输入和显示输出。(大概是因为自然界每一个像素都是多个通道混合在一起的吧,交替存储消耗的运算量少)
YUV采样和存储
原理
——由于人眼中视网膜杆细胞(用于识别亮度)比视网膜锥细胞(用于识别色度)要多,因此人眼对亮度(Y)的敏感程度要高于色度(U、V),所以在采样和存储、传输过程中,可以保持完整的亮度信息,而减少色度信息。
如上图,黑色实心点代表Y分量,空心圆圈代表UV分量。 转载一个分析各类存储方式的文章: YUV存储格式解析- 4:4:4:每4点Y采样,就有相对应的4点Cb和4点Cr。换句话说,在这种格式中,色度信号的分辨率和亮度信号的分辨率是相同的。这种格式主要应用在视频处理设备内部,避免画面质量在处理过程中降低。
- 4:2:2:每4点Y采样,就有2点Cb和2点Cr。在这种格式中,色度信号的扫描线数量和亮度信号一样多,但是每条扫描线上的色度采样点 数却只有亮度信号的一半。当4:2:2信号被解码的时候,“缺失”的色度采样,通常由一定的内插补点算法通过它两侧的色度信息运算补充。
- 4:2:0:并不是指只有Y和U分量,4:2:0的意思是,色度采样在每条横向扫描线上只有亮度采样的一半,扫描线的条数上,也只有亮度的一半。每四个Y公用一个UV分量。每一条扫描线的色度信息,都是由其上一条横向扫描色度信息的一半,与下一条色度信息的一半计算还原。
不同存储格式的特点和应用
格式 | 模式 | 通道 | bits | 示例应用 |
---|---|---|---|---|
GRAY | Planar | 1 | 8 | 400.Y0Y1...Y15,黑白 |
I420 | Planar | 3 | 12 | 420. Y0Y1...Y15 U0U1...U3 V0V1...V3,比较常用,理解为YU12 |
IYUV | Planar | 3 | 12 | 同I420 |
YUV420P | Planar | 3 | 12 | 同I420 |
YUVJ420P | Planar | 3 | 12 | 同I420,不同的是色彩转换公式,YUVJ使用 JPEG 公式, 输出数据范围[0..255], I420的范围是 [16-240] |
YV12 | Planar | 3 | 12 | 420. Y0Y1..Y15 V0V1V2V3 U0U1U2U3 * 常用,很多编解码器都用这个格式输入输出 |
YVU420P | Planar | 3 | 12 | 同YV12 |
NV12 | Planar | 2 | 12 | 420. Y0Y1..Y15 U0V0U1V1.....U3V3常用,Android采集,X264编码 |
NV21 | Planar | 2 | 12 | 420. Y0Y1..Y15 V0U0V1U1.....V3U3,Android采集后需要转换格式才能编码 |
YV16 | Planar | 3 | 16 | 422. Y0Y1..Y15 V0V1..V7 U0U1..U7 |
YUV422P | Planar | 3 | 16 | 同YV16 |
I422 | Planar | 3 | 16 | 同YV16 |
UYVY | Packed | 1 | 16 | 422. U0Y0V0Y1 U1Y2V1Y3... |
Y422 | Packed | 1 | 16 | 同UYVY |
YUY2 | Packed | 1 | 16 | 422. Y0U0Y1V0 Y2U1Y3V1...很多摄像机的输出格式 |
YUV422 | Packed | 1 | 16 | 同YUY2 |
YUYV | Packed | 1 | 16 | 同YUY2 |
YVYU | Packed | 1 | 16 | 422. Y0V0Y1U0 Y2V1Y3U1... |
YU16 | Planar | 3 | 16 | 422. Y0Y1..Y15 U0U1..U7 V0V1..V7 |
NV16 | Planar | 2 | 16 | 422. Y0Y1..Y15 U0V0U1V1..U7V7 |
YV24 | Planar | 3 | 24 | 444. Y0Y1..Y15 V0V1..V15 U0U1..U15 |
I444 | Planar | 3 | 24 | 同YV24 |
IYU2 | Packed | 1 | 24 | 444. U0Y0V0 U1Y1V1... |
- NV12和NV21属于YUV420格式,是一种two-planar模式,即Y和UV分为两个Planar,但是UV(CbCr)为交错存储,而不是分为三个plane。其提取方式与上一种类似,即Y'00、Y'01、Y'10、Y'11共用Cr00、Cb00
- 4:2:0的存储格式中,又有420P和420SP的区别。420SP是指先存放Y,然后UV交替存放【也是two-planar】如NV12和NV21就是420SP,其他都是420P。
- I420和YV12都是420P的格式,区别在于存储时UV的顺序不同。
转换
-
NV21和NV12转换
Y不变,就互换一下UV顺序
-
NV21换成I420
Y不变,UV进行一定逻辑变更
int i, j;
int y_size = width * height;
unsigned char* y = yuv420sp;
unsigned char* uv = yuv420sp + y_size;
unsigned char* y_tmp = yuv420p;
unsigned char* u_tmp = yuv420p + y_size;
unsigned char* v_tmp = yuv420p + y_size * 5 / 4;
// y
memcpy(y_tmp, y, y_size);
// u
for (j = 0, i = 0; j < y_size/2; j+=2, i++)
{
u_tmp[i] = uv[j];
v_tmp[i] = uv[j+1];
}
复制代码
RGB和YUV的转换
-
根据三基色原理,任意一种色光F都可以用不同分量的R、G、B三色相加混合而成。F = r [ R ] + g [ G ] + b [ B ]其中,r、g、b分别为三基色参与混合的系数。
-
使用YUV颜色空间是为了分离亮度和色度
-
转换公式如下:
- Y = 0.299R + 0.587G + 0.114B
- U = -0.147R - 0.289G + 0.436B(+128)
- V = 0.615R - 0.515G - 0.100B(+128)
- R = Y + 1.14V
- G = Y - 0.39U - 0.58V
- B = Y + 2.03U
-
一般,直接采集的视频数据是RGB24的格式,每一帧大小为weight * height * 3. RGB32的每一帧大小为weight * height * 4.