音视频系列9:BGRYUV420和YUV422编码格式
Posted IE06
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了音视频系列9:BGRYUV420和YUV422编码格式相关的知识,希望对你有一定的参考价值。
视频流转码的时候遇到了点麻烦,下面分析一下。
1 BGR vs YUV
BGR格式的shape为(width, height, 3),最后的3按照blue、green、red排列。
YUV格式中的Y、UV分别代表Luma、Chroma。UV分别描述色彩和饱和度。
YUV的好处是,将亮度与颜色分离,即使丢弃UV,仍然能够正常显示黑白图片。
下面是一个例子:
2. 各种YUV编码方式
YUV码流的存储格式有2个关键点:
1)Y与UV的采样,主流的采样方式有三种,YUV4:4:4,YUV4:2:2,YUV4:2:0。
YUV 4:4:4采样,每一个Y对应一组UV分量。YUV 4:2:2采样,每两个Y共用一组UV分量。 YUV 4:2:0采样,每四个Y共用一组UV分量。
2)Y与UV的编排。有两大类:planar和packed。
对于planar的YUV格式,先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V。
对于packed的YUV格式,每个像素点的Y,U,V是连续交*存储的。
这里先介绍两个项目中用到的:
2.1 I420
亮度(行×列) + U(行×列/4) + V(行×列/4)
2.2 nv12
NV12属于YUV420格式,是一种two-plane模式,即Y和UV分为两个Plane,但是UV(CbCr)为交错存储,而不是分为三个plane。其提取方式与上一种类似,即Y’00、Y’01、Y’10、Y’11共用Cr00、Cb00。python版本的代码如下:
# I420转为nv12
img_nv12 = list(img_I420[:w,:]) # Y
for wi in range(w//4):
d = []
for hi in range(h//2):
d.append(img_I420[w+wi,hi])
d.append(img_I420[w//4*5+wi,hi])
img_nv12.append(np.array(d))
d = []
for hi in range(h//2):
d.append(img_I420[w+wi,h//2+hi])
d.append(img_I420[w//4*5+wi,h//2+hi])
img_nv12.append(np.array(d))
img_nv12 = np.array(img_nv12)
io.imshow(img_nv12)
C++版本代码如下:
void swapYUV_I420toNV12(unsigned char* i420bytes, unsigned char* nv12bytes, int width, int height)
{
int nLenY = width * height;
int nLenU = nLenY / 4;
memcpy(nv12bytes, i420bytes, width * height);
for (int i = 0; i < nLenU; i++)
{
nv12bytes[nLenY + 2 * i] = i420bytes[nLenY + i]; // U
nv12bytes[nLenY + 2 * i + 1] = i420bytes[nLenY + nLenU + i]; // V
}
}
我们可以尝试恢复成BGR格式看一下:
和原图一模一样
以上是关于音视频系列9:BGRYUV420和YUV422编码格式的主要内容,如果未能解决你的问题,请参考以下文章
详解 YUV 格式(I420/YUV420/NV12/NV12/YUV422)