iOS-FFmpeg音视频开发音视频,多媒体,编解码

音视频结构:带你深入理解YUV

2019-07-04  本文已影响2人  码农叔叔

前言

在音视频开发中,RGB和YUV这些颜色空间估计大家都不会陌生。相对来说RGB比较容易理解,但是YUV的一些概念可能会比较抽象,所以这篇文章就主要来介绍YUV这个颜色空间的一些知识。

什么是YUV

要理清YUV的本质,那么必须从其Y、U、V这三个维度着手,从网上抄来的对于此的介绍大体如下:

但是,对于没有多少美工基础的同学,着实是不好理解,所以接下来开始看图理解教学。

先来欣赏一张小可爱的图片:


原图

然后我们通过技术手段(万能的代码),将UV置为默认值(默认值是多少后面解释),然后得出如下这张图:


去除UV后的图

从这里可得出很明显的结论,如果只保留Y通道的话,我们可以获得一张灰度图妹子图,也就是说Y维度其实保留得是图片的轮廓。

那么UV具体是什么样子呢,这里假设三个维度的取值都是[0.0, 1.0],当我们Y取中间值0.5,那么可以得出如下一张映射图,看到这里大家估计就知道UV是怎么表示颜色了吧:

image.png

看完了UV,那么Y呢?
下面是Y分别取0.00.51.0的时候,在UV的各个组合的映射图,请观察如下三张图:

Y=0 Y=0.5 Y=1.0

很明显可以看出,随着Y维度数值的增大,图片她开始发亮了!

PS:额外说一点,做音视频小伙伴经常会遇到画面绿屏现象的现在,麻烦翻上去观察每个映射图的左上角,是不是一大坨绿色?醒醒,赶紧去检查你的byte数组是不是忘记赋值,全部是0。

看起来YUV很简单嘛,这里麻烦请停下你想吹牛逼说已经理解YUV的冲动想法,因为接下来才是开始划重点。

YUV与RGB的转换关系

在业务开发过程中,免不了需要进行YUV与RGB之间进行颜色转换,那么请翻开《XX入门指南》的10086页,找到如下两个矩阵计算公式:

RGB转YUV计算矩阵


RGB转YUV计算矩阵

YUV转RGB计算矩阵


YUV转RGB计算矩阵

什么?你忘了矩阵的计算方法?
算了算了,跳过看下面的直接计算公式好了。

由于我们经常用byte (8bit)来保持YUV,所以这里以[0, 255]作为取值范围计算。

①、YUV转RGB计算公式:

R = Y + 1.402 (V-128)
G = Y - 0.34414 (U-128) - 0.71414 (V-128)
B = Y + 1.772 (U-128)

②、RGB转YUV计算公式:

Y = 0.299 R + 0.587 G + 0.114 B
U = - 0.1687 R - 0.3313 G + 0.5 B + 128
V = 0.5 R - 0.4187 G - 0.0813 B + 128

下面开始记录知识点:

YUV的采样格式

接下来就得了解一下YUV的采样格式,例如大名鼎鼎的YUV420。
曾经的萌新小朋友一度以为YUV420就是Y:U:V=4:2:0,额,就没发现V被你吃了么?


心情复杂

有疑惑就得找解答,没钱请老师就得多翻翻问谷哥度娘,终于我发现了如下几条真理:

如果你懒得琢磨上面的真理的话,那么一张图可能更适合你:


总结如下:

PS:在计算机领域,YCbCr 与 YUV 基本可以认为是等同的。

接着进入没奖问答环节:

1、你能再分析出YUV422和YUV440的采样分布吗?
2、如果以byte(8bit)作为Y、U、V的精度来存储,在得知width/height的情况下,请计算出相应内存占用。

YUV的存储格式

当我们辛辛苦苦分析那么多YUV采样格式,理解了采样规律;但是面对一个存放byte数组的YUV数据,震惊是不是漏了一件很重要的事情,它这个鬼究竟是怎么在内存里面存放的?!

额,反正很多人都这么告诉我,YUV的存储格式大概可以分为planar(平面)semi planar(半平面)packed(打包)三个大类别,那么具体每个类别有什么特性呢?

常用的YUV格式

对于任何一个格式的分析,一般需要从以下几个维度进行区分:

1、分析采样格式,确认其属于YUV420、YUV444、YUV422等等的哪一个采样格式。
2、确定好采样格式后,接下来分析其打包格式,例如是否是平面、半平面、或者打包格式。
3、在确定打包格式的情况下,对于半平面/平面格式,我们需要关注UV的排序规则,对于打包格式就需要注意采样点个数和YUV的储存顺序。

通过上面三个步骤基本就可以确定一个具体的YUV格式,下面提供一些常用的格式进行分析。

I420格式

I420数据模型图如下:


I420(属于YUV420P) 按照数组存储如下所示: 数组存储排序

基本都是以一块4x2像素进行分析,也就是上图中红色部分,Y1/Y2/Y9/Y10共用同一个U1/V1色度对,介绍上文的知识点可以判断出其属于YUV420采样格式。
然后从平面上面看,U和V的分量分别存储在两个平面,其也就是属于平面格式YUV420P。
对于任何平面格式,首个平面都是存储Y分量;对于第二个平面存储U以及最后一个平面存储V,那么可以推断出其就是I420格式。

NV12格式

NV12数据模型图如下:


nv12(属于YUV420SP)

同样的,取一块4x2的像素区域来分析,Y1/Y2/Y9/Y10共用同一个U1/V1对,所以其属于YUV420采样格式。
这种格式的数据存在两个平面,也就是传说中的半平面(semi planar)格式,山寨点的可以表示为YUV420SP。
接下来我们需要关注第二个平面的内容,因为先U后V,按照U1V1U2V2这样排列存储,推断格式就是NV12格式。

YUY2格式

YUY2数据模型图如下:


YUY2(属于YUV422 packed)

继续对一块4x2的像素区域进行分析,我们发现Y1/Y2共用同一个U1/V1色度对,Y5/Y6共用U3/V3这另外一个色度对,所以可以得出属于YUV422格式。
由于其仅存在一个平面,毫无意外就是打包(packed)格式,可以表示为YUV422 packed。
接下来可以通过分析Y/U/V的排序规则来得出其子格式,其是以n=2两个像素为一组,按照Y1/U1/Y2/V1来排序,按照YUV标准其应该是YUY2格式。

I444格式

I444数据模型图如下:


I444(属于YUV444P)

按照惯例,一块4x2的像素区域是我们所需要关注的,很容易发现任意一个Y都对应单独的一个U/V色度对,这也是YUV444的采样情况。
由于其存在三个平面,也就是YUV444P格式,根据在ffmpeg源码的分析,YUV444P有且只有这一种格式,也就是第二个平面存放所有U分量,第三个平面存放所有V分量,这种格式也叫做I444格式。

由于YUV的格式太多不方便全部列出来分析,但是只要掌握:采样格式、储存平面、UV排序规则,基本就是掌握绝大部分的YUV格式的。

更多格式可以参考下面资料:
http://www.fourcc.org/yuv.php
https://github.com/FFmpeg/FFmpeg
https://wiki.videolan.org/YUV

对齐问题和取值范围

接下来说一下两个比较偏的知识点。

对齐问题
不知道大家有没有想过,YUV中的J我们一般都是取4,那么问题来了,对于采样的单个范围就是4x2像素区域,例如当图片的宽度为7个像素时(换句话说就是非4对齐),那么有问题如下:

对齐问题

我们会发现最后一个黄色区域凑不齐4x2的采样单元区域。

一般来说,当以8bit存储精度来存放分量时,我们需要对其进行16bit或者32bit对齐,补齐的位置以0为初始值,如果不对齐呢?可能你的编码器、渲染器就莫名其妙的不能正常工作了。

当然这个在我们对YUV计算合适存储缓存区大小时也需要关注对齐问题。

取值范围
做过iOS采集的同学可能会发现,在iOS平台利用Camera采集YUV有ITU601和ITU709两种标准,而ITU601还细分两种Rang,一种取值范围是[0, 255],另外一种取值范围是[16, 235],当然这里所需要关注的关键点其实是GRB颜色空间转换的矩阵其实是不同的,具体矩阵这里就不列出来了。

结语

这篇文章从YUV的成像原理、与RGB的转换关系、采样规律、存储方式等方面进行深度解析,如果看完这篇文章还不懂YUV的话,麻烦拿刀来请教我啊。

本文发布于简书

End!

上一篇 下一篇

猜你喜欢

热点阅读