龙空技术网

YUV格式及分类规则简介

曹小满大人的快乐生活 197

前言:

此刻小伙伴们对“yuv叠加算法”可能比较关心,各位老铁们都需要分析一些“yuv叠加算法”的相关资讯。那么小编同时在网上收集了一些对于“yuv叠加算法””的相关文章,希望朋友们能喜欢,姐妹们一起来了解一下吧!

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协议排列方式有(仅仅是协议上的样子,可以暂定为理论上的样子,事实上数据怎么存的,跟这个协议有出入,取决于存储方式。不过尽管有出入,却可按照一定的规则还原成这个样子):

YUV444YUV422YUV420YUV411

按照数据格式的存储方式(这个是真真正正存储的样子,存储的样子可按照一定规则解析成协议的样子)

纯平铺(Planar,YUV三个分量全部平铺),紧凑(Packed,YUV三个交错存储)平铺+交错复合(SemiPlanar, Y是平铺,YU是交错存储)

按照每个通道数据占多少位

8位10位(这个10位怎么会是10位?)16位YUV各种排列方式

YUV排列方式就是我们上面提到的

YUV444YUV422YUV420YUV411

无论哪种排列方式,我们也有一点共性

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

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

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常见问题及原因总结编完播放的是绿的而且它成形状。

解:这种问题建议向YUV数据,与真实给的宽高不对这种问题上考虑。就是可能对齐方面是有问题的。

颜色不对

思考:这种颜色不对,根据上述YUV将的可以知道,Y数据应该是正确的(啊当然我们先别看这个方向问题,方向明显就是有问题,但是现在我们看的是颜色), UV它不对,Y是对的,这种原因大多数为,原始数据输出,中间加工的时候,编码格式有不一致的地方,会引发这种问题。例如原始数据我们存储格式为YUV420全部平铺,即 YUV在存储上全部是平铺的,但是初始化编码器的时候给的格式却不是这种格式,在另外一个播放器播放的时候,就容易出现这个问题。

主要是颜色格式不对引起的,这种问题其实还好了,是很简单的那种问题。

这块如果想了解更多,建议专门学学YUV这个格式。这块也是比较专业复杂的,建议有系统的看一下。就像图中的样子,我们可以看出来,灰度其实还是可以的,起码能看出来这是一个人,但是颜色不对,应该是UV数据不对。当然不对的原因有很多,我也在看,今天还在调这个问题。

只要有灰色就还好,起码Y好用哈哈哈哈。这个问题的解决思路在于 数据转换的环节,是怎么转换的。以我自己的工程,和碰见的问题为例

相机启动时候,绑定的是 I420格式,那么在Camera回调的时候,返回的也是I420格式,但是有一点是,Camera回调的数据是在ImageReader里面的,它记录数据是 Y U V分开记录的你拿到的这种数据,给出了 Y, U, V三个通道,严格的讲,只要你拿到了这些数据,按照一定算法转换,就能转换成各种YUV格式。就算是I420格式,这个格式还有4种排列方式。你要转成哪一种,这个要注意下!这个格式一定一定要记住。另外还有转方向问题,转方向的算法,是按照那种格式去计算的,一定要好好看看细节。我遇见的一个问题就是,转YUV的时候,转成的是YU12, 但是转方向代码,我是找的网上的,我找的那个算法,是按照NV21来转的。 诡异的是,他们的名字都叫I420+转换角度,坑死。于是就出现了上方的灰屏问题,也就是Y是转对了,但是UV乱套了,前者数据是UV平铺,但是后者计算的时候假定的是UV交错排列,可不出问题么。chatGPT在这里我不得不吐槽一下,它出的代码也是错的。我们做了这种动作之后,一般就是把数据喂给编码器去了,这个编码器在配置的时候,是需要一个颜色格式的,设置的一定要对!要不,其他的播放器在解码的时候,会解错,UV还是不对还是会灰。方向不对

那就转方向,YUV转方向的思路跟我们上方提到的是一样的。

这块建议别死磕,就是找网上的代码即可。如果有兴趣的话,可以看看那个转角度的数据赋值。但是一定要注意的是:

你找的方法,的入参,也就是那个byte数组,究竟是什么格式的。我查有网上的代码方法名直接叫 “rotateYUV420Degree270” 诸如此类。但是还是那句话, 即使是420,它也有4种排列方式,要看看算法是参考哪种格式排列的。这块如果转不对,也是容易出现灰屏的问题。算法肯定是经过验证的,搞对整条路,就会转对。

标签: #yuv叠加算法