YUV数据格式解疑

来源:互联网 发布:手机备份软件应用数据 编辑:程序博客网 时间:2024/05/16 12:55

 一般我们在YUV格式上进行画面的数据进行分析,比如一些视频分析算法。对此,为了对以后该方面的算法做一些知识储备,先总结对自己了解到的相关YUV知识进行总结,认识。
 同样,首先贴出该篇文章的参考连接,如果大家有需要更深入了解的,可以点击进这里的链接:
 图文详解YUV420数据格式
 YUV(二)-YUV格式转换缩放
 YUV格式说明
 YUV采样格式与存储格式
 好了,话不多说,接下来YUV的总结。

初识YUV

 首先了解下什么是yuv。
 yuv是一种颜色编码方法,即对摄像头采集到的颜色数据进行编码。
 其中Y代表亮度(灰度值),UV代表色度与浓度(影像色彩饱和度)。

YUV与RGB

 YUV与RGB一样,都可以用于图像的存储,传输(由于这两种格式的数据量对于传输来说还是太大,所以一般不这么做),但YUV比RGB的优势是在哪里呢?
 在于用YUV方式传送占用极少的频宽,因为 一般来说,直接采集到的视频数据是RGB24的格式,RGB24一帧的大小size=width×heigth×3 byte,RGB32的size=width×heigth×4,如果是I420(即YUV的一种标准格式4:2:0)的数据量是 size=width×heigth×1.5 byte。
 由此看出YUV方式传输时能减少大量的数据量传递,但上面又说YUV一般不作为图像传输格式,那这个YUV除了能数据量小点外是不是就跟RGB一样了呢?其实在真正主要使用在YUV格式一般使用在图像处理方面。

YUV的存储格式

 YUV的存储格式分为紧缩格式(packed)平面模式(planar)
紧缩模式(packed):将Y、U、V值储存成Macro Pixels阵列,和RGB的存放方式类似,每个像素点的Y,U,V是连续交错存储的。
平面模式(planar):将Y、U、V的三个分量分别存放在不同的矩阵中,即先连续存储所有像素点的Y,紧接着存储所有像素点的U,随后是所有像素点的V。

YUV的采样方式与存储方式

 说完了yuv的存储格式,接下来对于我们理解yuv的几种不同的采样方式就容易得多了,以下分别简述yuv的三种通用的采样方式:
 同时不管是否理解,应该先知道的是以下几句话,相信带着这几句话去阅读以下的几种采样方式能更方便掌握。

1、YUV 4:4:4采样,每一个Y对应一组UV分量。
2、YUV 4:2:2采样,每两个Y共用一组UV分量。
3、YUV 4:2:0采样,每四个Y共用一组UV分量。

YUV4:4:4

采样方式

 yuv444方式采样即每采样一个Y分量就采样一个UV分量,如下两张图所示,该两张图描述同一个意思,即一个Y对应一组UV。
这里写图片描述
这里写图片描述

存储方式

 内存中为:YYYYYYYY UUUUUUUU VVVVVVVV

YUV4:2:2

采样方式

 yuv422是每两个y对应一组uv值。同样这里也引用两张图片进行直观的说明:
这里写图片描述
这里写图片描述

存储方式

 同时yuv422又可以分为YUYV,UYVY,YUV422P三种存储模式。下面就来简要地说明这三种模式的区别。
 这里需要说明的是其始终遵循2个y对应一组uv,变的只是在一个单元中这三个分量元素的排列顺序。
YUYV(属于yuv422,紧缩模式):
 与其命名表现出来的意思一样,yuyv的排列方式即为y,u,y,v。下面用一张图来更直观地说明该模式中yuv的排列方式。
这里写图片描述
 这里的Cb可以认为是u,这里的Cr可以认为是v。所以从图中可以看出YUYV的排列方式为y,u,y,v,对于像素点Y’00、Y’01 而言,其Cb、Cr的值均为 Cb00、Cr00,其他的像素点的YUV取值依次类推。
UYUV(属于yuv422,紧缩模式):
 同样是字面意思的u,y,v,y的排列方式,与yuyv的不同仅仅在于排列方式。下面出图:
这里写图片描述
 同样,这里的Cb为u,Cr为v。图中的排列方式为u,y,v,y,对于像素点同样是Y’00、Y’01对应Cb00、Cr00,即遵循两个Y一组uv。
YUV422P(属于yuv422,平面模式):
 与前面两种方式不同,并不仅仅是一个元素的y与u,y与v的先后问题。yuv422P的存储格式为平面模式,即不是前面两种的yuv在同一个矩阵且互相交错,而是先存完Y分量,再存U分量,最后存V分量。同样一张图看清其排列:
这里写图片描述
 虽然存储模式不一样,但既然属于yuv422,那么其yuv的对应关系是不会改变的,所以同样的对于像素点Y’00、Y’01 而言,其Cb、Cr的值均为 Cb00、Cr00。
 该平面模式中所有 Y 样例都会作为不带正负号的char值组成的数组首先显示在内存中。此数组后面紧接着所有 U (Cb) 样例。U 平面的跨距为 Y 平面跨距的一半,V 平面包含的行为 Y 平面包含行的一半。U平面后面紧接着所有 V(Cr) 样例,它的跨距和行数与 U 平面相同。

YUV4:2:0

采样方式

 其采样方式为4个y,一组uv,引用如下两张图所示:
这里写图片描述
这里写图片描述

存储方式

 yuv420的采样方式是比较常见和常用的,yuv420中也分不同的存储方式,如YV12,I420,NV12,NV21。其中YV12与I420都可以称为yuv420P,两者是同样的平面模式,只是u和v的顺序不同;而NV12与NV21也都可以称为yuv420SP,共同表现的是Y为平面模式,uv为紧缩模式,同样NV12与NV21两者区别为u与v的排列方式。
 再这里再啰嗦一下,yuv420存储格式下虽然分出这些排列模式,但其根本不会变,即4个y对应一组uv。下面开始一 一介绍。
YV12(属于yuv420,yuv420P,平面模式):
 YV12的yuv排列方式为,先排列完y分量,再排列v分量,最后排列u分量,直观展现如下图所示。图中,Y’00、Y’01、Y’10、Y’11共用Cr00、Cb00(需要注意清楚的是哪几个y对应哪几个uv),其他依次类推:
这里写图片描述
 该平面模式中,在内存中的排列为:
 YYYYYYYY VV UU =>YUV420P。
 具体如下图所示:
这里写图片描述
I420(属于yuv420,yuv420P,平面模式):
 与YV12基本类似,唯一不同的是Y后面U和V的先后顺序,I420是U紧随其后。
 YYYYYYYY UU VV =>YUV420P
 下面直接上图,就不过多说明了。
这里写图片描述
NV12(yuv420,yuv420SP,双平面模式):
&esmp;NV12的排列方式有些特殊,他是先将y分量排完,然后剩下的uv分量交错着排列,通常我们会将uv看成一个整体,那么NV12的排列方式就是two-plane模式,即双平面模式。NV12的uv平面中,uv的先后顺序为先u后v。
 下面是其排列顺序的图片:
这里写图片描述
 对应关系为Y’00、Y’01、Y’10、Y’11共用Cr00、Cb00。
 内存中为:YYYYYYYY UVUV =>YUV420SP (dxva 输出 NV12)
 所有 Y 样例都会作为由不带正负号的char值组成的数组首先显示在内存中,并且行数为偶数。Y 平面后面紧接着一个由不带正负号的char值组成的数组,其中包含了打包的 U (Cb) 和 V (Cr) 样例,如图 所示。
这里写图片描述
NV21(yuv420,yuv420SP,双平面模式):
 与NV12基本一致,唯一不同的是在排列完y分量后,uv的先后顺序为先v后u。
 内存中为:YYYYYYYY VUVU =>YUV420SP (x264/ffmpeg 输入、输出 I420)
 引用图片如下图所示:
这里写图片描述

在内存中的yuv420

 引用上面借鉴博客中的一段话就能进行很好的描述。

YUV420 planar数据, 以720×480大小图象YUV420 planar为例,
其存储格式是: 共大小为(720×480×3>>1)字节,
分为三个部分:Y,U和V
Y分量: (720×480)个字节
U(Cb)分量:(720×480>>2)个字节
V(Cr)分量:(720×480>>2)个字节
三个部分内部均是行优先存储,三个部分之间是Y,U,V 顺序存储。
即YUV数据的0--720×480字节是Y分量值,
720×480--720×480×5/4字节是U分量
720×480×5/4 --720×480×3

 为什么内存所占大小是(720×480×3/2)字节,即width * hight * 3 / 2字节呢,原因就在于4个y对应一组uv。
 即Y部分所占大小为width * hight =Y(总和);U部分所占大小为 U = Y / 4 ;V部分所占大小为 V = Y / 4。将这三个量加起来就可以得到yuv420在内存中所占的大小为width * hight * 3 / 2。

yuv420P与yuv420SP区别

 最后为了收个尾,再引用两张图片说明yuv420P与yuv420SP的区别。
这里写图片描述

yuv的采集,理论上的传输和显示流程

 为什么是理论上的传输呢,因为一般不这么干,yuv还是太大了,一般采取再一次编码压缩(H264,H265等等)。
 OK,下面引用上面博客的一段话以及一张图片进行说明yuv的这一系列流程。

一般来说,直接采集到的视频数据是RGB24的格式,RGB24一帧的大小size=width×heigth×3 byte,RGB32的size=width×heigth×4,如果是I420(即YUV标准格式4:2:0)的数据量是 size=width×heigth×1.5 byte。在采集到RGB24数据后,需要对这个格式的数据进行第一次压缩。即将图像的颜色空间由RGB2YUV。因为,X264在进行编码的时候需要标准的YUV(4:2:0)。
经过第一次数据压缩后RGB24->YUV(I420)。这样,数据量将减少一半。同样,如果是RGB24->YUV(YV12),也是减少一半。但是,虽然都是一半,如果是YV12的话效果就有很大损失。然后,经过X264编码后,数据量将大大减少。将编码后的数据打包,通过RTP实时传送。到达目的地后,将数据取出,进行解码。完成解码后,数据仍然是YUV格式的,所以,还需要一次转换,这样windows的驱动才可以处理,就是YUV2RGB24。

关于yuv的代码计算

yuv420与yuv422的转换

 YUV4:2:2 —> YUV4:2:0 Y不变,将U和V信号值在行(垂直方向)在进行一次隔行抽样。 YUV4:2:0 —> YUV4:2:2 Y不变,将U和V信号值的每一行分别拷贝一份形成连续两行数据。

yuv420sp旋转90度的算法

public static void rotateYUV240SP(byte[] src,byte[] des,int width,int height){    int wh = width * height;    //旋转Y    int k = 0;    for(int i=0;i<width;i++) {        for(int j=0;j<height;j++)         {            des[k] = src[width*j + i];               k++;        }    }    for(int i=0;i<width;i+=2) {        for(int j=0;j<height/2;j++)         {             des[k] = src[wh+ width*j + i];             des[k+1]=src[wh + width*j + i+1];            k+=2;        }    } }

缩放扩大方法

 yuv缩放一般是进行倍数的缩放和扩大,这样才能尽可能地保持原有图像内容。
 对于缩放,则可以通过隔点采样的方式进行,即隔一个倍数点,采一个;对于扩大可以复制的方式进行。

0 0
原创粉丝点击