你知道RGB,那你知道什么是YUV么?-腾讯云开发者社区-腾讯云
RGB/YUV的来历及其相互转换_51CTO博客_yuv转rgb
摄像头工程师说 Camera - 数据格式 YUV 详解(2)_yuv数据大小-CSDN博客
YUV图像里面的stride和plane的解释-腾讯云开发者社区-腾讯云
http://dougkerr.net/Pumpkin/articles/Subsampling.pdf
音视频工程师 YUV 和 RGB 详解_yuv 音频工程师-CSDN博客
YUV和RGB的区别(以及YUV444 YUV422 YUV411 YUV420的介绍)_444 422 420 411-CSDN博客
YUV是什么
先来句废话YUV首先是一种格式。
YUV是一种亮度参数和色度参量分开表示的一种像素格式。其中Y代表的是明亮度,也就是灰度值。而UV代表的是色度。作用是用来描述色彩和饱和度。用于指定像素的颜色。
Y:亮度分量,表示物理线性空间亮度
U:蓝色偏移程度
V:红色偏移程度
YUV同RGB类似,也是一种颜色编码方法,主要用于电视系统以及模拟视频领域。它讲亮度信息Y,与色彩信息UV进行分离,只用Y数据就可以播放出完整的影像,只不过图像是黑白色的。YUV不像RGB那样需要三个独立的视频信号**同时传输,**另外YUV格式可以在UV这种色彩信息进行压缩,所以它占用的空间会小一些。
历史
首先说一下YUV的优点,原因之后会有解释。
- YUV更省空间
- YUV它也可以表示图像。
- RGB可以与YUV可以互转
YUV的发明是由于彩色电视与黑白电视的过度时期。黑白的电视仅仅需要Y数据,也就是灰阶值,就可以表示出来图像。而对于YUV、YIQ来处理色彩的电视,可以把UV看做表示彩色。剩下的Y讯号就和黑白电视的电视讯号相同,就可以解决兼容问题。同时YUV最大的优点在于,只需要占用极少的带宽。
那有YUV这么好为什么还用RGB?
原因很简单,因为我们的液晶显示器的色彩原理,运用的就是红绿蓝颜色模型。就是依据这个来进行硬件设计的。仔细拿放大镜看看我们的手机屏幕,可以看到红绿蓝三个条条的。硬件就是这样,硬件识别的值,也是参考红绿蓝模型的值,这对于硬件设计而言是理所应当的。用比较拟人的说法就是,你们最终干活的打工人,除了RGB不认别的。那你跟他沟通的时候,不得也用RGB么。所以就产生了一个规则,无论数据如何兜兜转转,最终的结果一定要是显示屏硬件能识别的数据。也就是 RGB。
那这样的话直接用RGB不就得了?为什么还要有YUV?
我们最前面提到的,YUV它可以解决兼容问题,也曾经解决过,但是,这不是它被广泛使用的核心原因,核心原因就是YUV它占得容量小,节省带宽。在多媒体的世界里,带宽是能省则省的。因为涉及网络传输,数据量太大,耗流量而且慢,对于实时音视频而言,哪一个都要是力保的。所以YUV会得到广泛的使用。
在实践中,我们肯定既要数据最终是RGB,给显示器,又要数据省空间的,那么这样的话,一般就是出现以下现象:
- 数据生产端可能最初的数据也是RGB,也可能是其他,但是网络传输前被转为YUV。(转这块的耗时相比于网络传输,是很少的)
- 携带YUV的数据可能会经过网络传输(网络传输这里是很耗时的,转YUV一定程度上加快了速度)
- 数据消费端拿到数据,将YUV转回RGB,显示。(转这块的耗时相比于网络传输,是很少的)
这种方案的话,就满足了既要又要的要求。
下图是网上找的图,有个步骤就是生生硬转成了YUV。

仅凭这三点,足以在音视频传输中考虑这种替代方案。因为可以实现,因为可以省空间省带宽省钱。如果你是设计者,我想也会调研考虑的。
谈谈RGB
相对于YUV而言,它是不省空间的。RGB为什么大, 我们解释一下,YUV为什么相对于RGB小,这个看下面一节就可以了。
RGB的原理有点类似于我们的三原色原理,只不过画画中的三原色和光色它有一些区别。光的三原色是 红绿蓝。 红黄蓝集一块是白色,(美术中的是红黄蓝,红黄蓝颜色集一块是黑色)。
RGB格式目前主要分为两类
- 像素格式:是我们比较常用的一种格式,RGB分别分开,用N个位来进行表示。例如RGB24格式,代表 R, G, B 每一个分别占8位,合起来是24位。 这种格式可以代表256 * 256 * 256种颜色,即16777216种颜色。但是有个缺点是占用的空间比较大。 另外还有一种带透明度的颜色格式,这个是 32位的。更大。
- 索引格式:这个格式是比较省空间的,但是是一个老格式,而且代表的颜色并不是那么丰富的。目前基本被弃用状态。其原理是,一个值对应的是一个指定的颜色。嗯,索引嘛。去映射找就是了。就比如,01这个值代表的是红色,就去找。对应的索引内容就是红色。索引格式也有几种。
-
- RGB1: 每个像素用一个比特表示,可以表示黑白。
- RGB4: 表示16种颜色。
- RGB8:表示256种颜色。
- 现在基本不用了。只是我不是很熟,就多写几句。
YUV色彩原理
人眼
人眼视网膜是处理光,和色彩刺激的。 有两大种类细胞组成,视杆细胞,和视锥细胞。视杆细胞是识别亮度的,视锥细胞是识别色度的。 但是有个事实是,视网膜中的视杆细胞比视锥细胞多,也就意味着,人眼对阴暗的分辨,要比色彩敏感。YUV的思路参考了这种生物学原理,把图像拆分成了灰度(明亮),以及颜色。其中描述灰度的数据,很全,但是色彩的数据,由于人眼特征,是可以考虑优化掉一部分数据的。
如果我们查YUV的排列格式,你会发现有 YUV444, YUV422, YUV411, YUV420。 Android手机常用420。这些不同格式尽管乍一听有点晕,都是采用了保留Y,UV酌情优化的策略。简而言之就是,保核心,砍枝叶。就像职场。。。
YUV分类及规则
YUV种类可多了,而且,每个种类也有细分,有区别。但是有规律
按照YUV协议排列方式有(仅仅是协议上的样子,可以暂定为理论上的样子,事实上数据怎么存的,跟这个协议有出入,取决于存储方式。不过尽管有出入,却可按照一定的规则还原成这个样子):
- YUV444
- YUV422
- YUV420
- YUV411
按照数据格式的存储方式(这个是真真正正存储的样子,存储的样子可按照一定规则解析成协议的样子)
- 纯平铺(Planar,YUV三个分量全部平铺),
- 紧凑(Packed,YUV三个交错存储)
- 平铺+交错复合(SemiPlanar, Y是平铺,YU是交错存储)
按照每个通道数据占多少位
- 8位
- 10位(这个10位怎么会是10位?)
- 16位
YUV各种排列方式
YUV排列方式就是我们上面提到的
- YUV444
- YUV422
- YUV420
- YUV411
无论哪种排列方式,我们也有一点共性
- Y分量数据,永远是全的!
- 444,422, 420, 411 数字来源为, **以一行四个像素看,注意是一行, YUV占比。**记住这个套路我们接下来看细分
YUV444

YUV444,代表每4个Y采样,就有对应的4个U和4个V。
但是这种格式,是可以很完美的呈现出来画面亮度和色彩,1:1:1的比例,画面肯定是会表现的比较好的,但是,这个数据量比较大,基本和RGB都是1:1:1保持一种比例。是不怎么省空间的。
YUV422

Y分量同样是保证全量,记住,无论那种,Y一定是全量。
YUV422 就很明显,把UV的量给减少了,相比于444,它只保留了一半。隔一个保留一份全的。
形式上也是那种套路,每四个Y采样点,有两个U,两个V
YUV420
http://dougkerr.net/Pumpkin/articles/Subsampling.pdf
YUV和RGB的区别(以及YUV444 YUV422 YUV411 YUV420的介绍)_444 422 420 411-CSDN博客
PS:420, 和 411 是两个令我迷惑的格式。因为明明总量YUV比例都是 4:1:1,但为什么一个叫420,一个叫411
上面我们看见了YUV444 和 YUV422, 可以看出来 422是把UV分量砍了一半,排列出来的样子。
但是仍旧有优化空间,那就是,可不可以再砍点数据呢?
思路如图所示首先看图二
图二是思路,可以考虑黑圈中四个Y共用一个U一个V,这样也是可以的,又省了一部分空间
那究竟怎么排布呢?看图一
也就是第一排隔列记录UV的其中一个, 第二行隔列记录UV中第一行没有被记录的另外一个。错开记。
这样下来,按照四个像素一行来数的话, YUV比例要么是: 4:2:0 要么是 4:0:2
420排布参考图三

YUV 411
有了420的思路实际上411已经可以反推出来应该怎么排布了。当然总容量依然是YUV比例4:1:1,但是按照我们之前的规则的话,很明显,应该是一行四个像素,其中有一个四个Y, 一个U, 一个V

YUV存储方式
YUV的主要存储方式分为两种
- Planar: 平面模式,是将Y信号与UV信号分开来进行存储,首先将Y信号进行存储,然后再按照一定的规则来存储UV信号。
- Packed: YUV信号不进行分开,而是YUV就是进行这种排列来进行存储。就是交叉存储。不过这样存储的话,看着明白,但是解析的时候,有些费劲。因为是交叉的,解析的时候还得考虑交叉。

Planar模式
上方讲了,Planar是平铺模式。但是就算是平铺它也有很多不同。Y都知道拍一块,但是UV怎么排。也是有不一样的:

嗯,从上面我们也可以看出来,这个planar模式实际上应该是用的比较广泛,但是"花样百出"的。原因是它的排列方式也是比较多样化的!
从大的分类上讲, 有的多了个 S, 你看这个 YUV_420_P 和 YUV_420_SP, 这里面就多了个"S", S 代表的是,UV是否混搭。那么这样的话我们进行理解一下
- YUV_420_P(YU12), 首先,不是混搭,也就是U和V也是平铺排列的,而YU12 代表Y排第一,U排第二,剩余那个肯定是V,嗯,连名字都很符合YUV的设计思想。见左上角,看看Y是排第一个,U是排第二个,V是第三个吧。
- YUV_420_P(YV12),首先,不是混搭的,也就是也是U V都是平铺开来的,但是 YV12 则代表 Y排第一个,V排第二个,剩余的肯定是U,排第三个。就是右上角的那张
- YUV_420_SP(NV12), 首先,UV是混搭的,"S"可看出,然后,后面的NV12, 这个NV示意是Non-interleaved 非交错,但我只能向Y非混搭方面解释了,这块我没法理解, 但是 12 这个顺序如果便于理解的话,那就是 UV, 本来U就应该是第一个
- YUV_420_SP(NV21), 首先,UV是混搭的,"S"可看出,然后,后面的NV21,但是 21 这个顺序如果便于理解的话,那就是 UV 反过来,就是 VU。
YUV转方向
YUV转方向这块是视频录制绕不开的话题,原因是,安卓手机上的摄像头,是转了方向的,安卓的Camera API,我用的事Camera2,返回的图像数据尽管是我们指定好的格式,大多是YUV 420 。但是它的方向不是正常的方向。关于为什么方向不对,画个饼,也会单独出一个文章写这个,总之就是不对。
因为方向不对,所以我们需要转方向。所以才谈到了这个方向问题。当然,本篇要是要讲的思路是转YUV数据的方向。
通常我们转数据的情况下,是希望这样转的,就是生转。。。拍脑袋一般是这个结果。

但是如果生转的话,我们看转成的结果,它都不符合YUV的排列了。实际上是不行的。
正确的思路是: 把YUV拆开,分别转90度,然后再拼接。原因简单啊,Y U V 数据,实际上内容展现的都是一整张图片的颜色分量。分开转方向,实际上就是将Y分量全转,U分量全转, V分量全转。都转对了,就是一个可以看的图片,转错了,勉强能看出是啥。但是图片不正常。
这是我挺佩服YUV这种思想的一点。因为他们有解耦的属性,以Y为主,离了谁都还可以。就像人生。。。
正确的思路为:

YUV转RGB
VideoTech 第1期:为什么受损的视频数据通常显示为绿色? - 微帧科技
YUV转RGB遵循公式的。这个公式我认为非算法,没有必要太钻研,但是,有一点仍值得开发注意。就是我们在开发中遇到过的绿屏问题。。为什么是绿屏而不是红瓶蓝屏?为什么是绿色?这个是从公式上可以得到解释的。
RGB 转换成 YUV
Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16
Cr = V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128
Cb = U = -( 0.148 * R) - (0.291 * G) + (0.439 * B) + 128
YUV 转换成 RGB
B = 1.164(Y - 16) + 2.018(U - 128)
G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
R = 1.164(Y - 16) + 1.596(V - 128)
如果YUV数据都为0的情况下,按照这种, B, G, R 这三个值是恒定不变的,三者组一下,就是一样的色彩
-14.836 -258.304 = -223.092 = R
-14.836 + 127.187 + 50.048 = 162.399 = G
-14.836 - 126.404 = -141.24 = B

嗯,就酱,所以是绿色
YUV常见问题及原因总结
我记录在了另外一篇文章中,Android视频编解码 这片文章的后几段,着重写了下YUV相关大的问题,但因为是和编码器结合的所以就写在了另外一篇文章中。