RGB与YUV

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RGB与YUV相关的知识,希望对你有一定的参考价值。

参考技术A 每个像素用1个bit表示,可表示的颜色范围为双色,即最传统的黑和白。1个bit只能表示0,1两种值。需要调色板,不过调色板只包含两种颜色。

每个像素用4个bit表示,4个bit所能够表示的索引范围是0-15,共16个。也就是可以表示16种颜色。即调色板中包含16中颜色。

每个像素用8个bit表示。8个bit所能够表示的索引范围是0-255,共256个。也就是可以表示256中颜色。即调色板中包含256中颜色。

RGB像素格式中的bit存储的是每一个像素点的R,G,B值

一个像素用16个bit = 2个byte表示 ,R=5 G=6 B=5

为什么绿色为6位?

一个像素用16个bit = 2个byte,但是最高位不用,R=5 G=5 B=5

RGB24图像每个像素用8个bit,共24个位表示,共3个字节,注意:在内存中RGB各分量的排列顺序为:BGR

RGB32图像每个像素用32个bit表示,占4个byte,R,G,B分量分别用8个bit表示,存储顺序为B,G,R,最后8个字节保留。注意:在内存中RGB各分量的排列顺序为:BGR

RGB32图像每个像素用32个bit表示,占4个字节,R,G,B分量分别用8个bit表示,存储顺序为B,G,R,最后8个为透明像素。注意:在内存中RGB各分量的排列顺序为:BGRA

注意:java默认使用大端字节序,c/c++默认使用小端字节序,android平台下Bitmap.config.ARGB_8888的Bitmap默认是大端字节序,当需要把这个图片内存数据给小端语言使用的时候,就需要把大端字节序转换为小端字节序。例如:java层的ARGB_565传递给jni层使用时,需要把java层的ARGB_565的内存数据转换为BGRA565。
详细验证请看: Android Bitmap像素排列与JNI操作

YUV有很多变种,我们常说的YUV指的是YCbCr,YUV三个字母中,其中”Y”表示明亮度(Lumina nce或Luma),也就是灰阶值;而”U”和”V”表示的则是色度(Chrominance或Chroma)作用是描述影像色彩及饱和度,用于指定像素的颜色。Cb指蓝色色度分量,而Cr指红色色度分量,是标准 YUV 的一个翻版(还有YPbPr等),此文中,我们就用 YUV 指代 YCbCr 了。

首先,YUV按照数据大小分为三个格式,YUV420,YUV422,YUV444。由于人眼对Y的敏感度远超于对U和V的敏感,所以可以多个Y分量共用一组UV,这样既可以极大的节省空间,又可以不太损失质量。

按照多个 Y 分量共用一个 UV 的方式,我们可以把 YUV 分为 420,422,444 三种类型,而在这三种类型之下,我们又可以按照 YUV 的排列储存顺序,将其细分为好多种格式,这些格式数量繁多,又不好记忆,这为我们学习过程中造成了不少困难。下面我就为大家一一介绍。

首先,我们将可以按照 YUV 的排列方式,再次将 YUV 分成三个大类,Planar,Semi-Planar 和 Packed。

Planar YUV 三个分量分开存放
Semi-Planar Y 分量单独存放,UV 分量交错存放
Packed YUV 三个分量全部交错存放
按照这三种方式,我们就可以将 YUV 格式进行比较细致的分类了。
YUV的所有格式列表

一张从上到下分别为原图、Y、U 和 V:

YUV 4:4:4 采样,意味着 Y、U、V 三个分量的采样比例相同,因此在生成的图像里,每个像素的三个分量信息完整,都是 8 bit,也就是一个字节。

如下图所示:

其中,Y 分量用叉表示,UV 分量用圆圈表示。

举个例子 :
假如图像像素为:[Y0 U0 V0]、[Y1 U1 V1]、[Y2 U2 V2]、[Y3 U3 V3]
那么采样的码流为:Y0 U0 V0 Y1 U1 V1 Y2 U2 V2 Y3 U3 V3
最后映射出的像素点依旧为 [Y0 U0 V0]、[Y1 U1 V1]、[Y2 U2 V2]、[Y3 U3 V3]

假如图像像素为:[Y0 U0 V0]、[Y1 U1 V1]、[Y2 U2 V2]、[Y3 U3 V3]
那么采样的码流为:Y0 U0 V0 Y1 U1 V1 Y2 U2 V2 Y3 U3 V3
最后映射出的像素点依旧为 [Y0 U0 V0]、[Y1 U1 V1]、[Y2 U2 V2]、[Y3 U3 V3]

可以看到这种采样方式的图像和 RGB 颜色模型的图像大小是一样,并没有达到节省带宽的目的,当将 RGB 图像转换为 YUV 图像时,也是先转换为 YUV 4:4:4 采样的图像。

YUV 4:2:2 采样,意味着 UV 分量是 Y 分量采样的一半,Y 分量和 UV 分量按照 2 : 1 的比例采样。如果水平方向有 10 个像素点,那么采样了 10 个 Y 分量,而只采样了 5 个 UV 分量。

如下图所示:

举个例子 :
假如图像像素为:[Y0 U0 V0]、[Y1 U1 V1]、[Y2 U2 V2]、[Y3 U3 V3] 那么采样的码流为:Y0 U0 Y1 V1 Y2 U2 Y3 V3
其中,每采样过一个像素点,都会采样其 Y 分量,而 U、V 分量就会间隔一个采集一个。
最后映射出的像素点为 [Y0 U0 V1]、[Y1 U0 V1]、[Y2 U2 V3]、[Y3 U2 V3]

假如图像像素为:[Y0 U0 V0]、[Y1 U1 V1]、[Y2 U2 V2]、[Y3 U3 V3]
那么采样的码流为:Y0 U0 Y1 V1 Y2 U2 Y3 V3 其中,每采样过一个像素点,都会采样其 Y 分量,而 U、V 分量就会间隔一个采集一个。
最后映射出的像素点为 [Y0 U0 V1]、[Y1 U0 V1]、[Y2 U2 V3]、[Y3 U2 V3]

采样的码流映射为像素点,还是要满足每个像素点有 Y、U、V 三个分量。但是可以看到,第一和第二像素点公用了 U0、V1 分量,第三和第四个像素点公用了 U2、V3 分量,这样就节省了图像空间。

一张 1280 * 720 大小的图片,在 YUV 4:2:2 采样时的大小为:

可以看到 YUV 4:2:2 采样的图像比 RGB 模型图像节省了三分之一的存储空间,在传输时占用的带宽也会随之减少。

YUV 4:2:0 采样,并不是指只采样 U 分量而不采样 V 分量。而是指,在每一行扫描时,只扫描一种色度分量(U 或者 V),和 Y 分量按照 2 : 1 的方式采样。比如,第一行扫描时,YU 按照 2 : 1 的方式采样,那么第二行扫描时,YV 分量按照 2:1 的方式采样。对于每个色度分量来说,它的水平方向和竖直方向的采样和 Y 分量相比都是 2:1 。

如下图所示:

假设第一行扫描了 U 分量,第二行扫描了 V 分量,那么需要扫描两行才能够组成完整的 UV 分量。

举个例子 :
假设图像像素为:[Y0 U0 V0]、[Y1 U1 V1]、 [Y2 U2 V2]、 [Y3 U3 V3][Y5 U5 V5]、[Y6 U6 V6]、 [Y7 U7 V7] 、[Y8 U8 V8]
那么采样的码流为:Y0 U0 Y1 Y2 U2 Y3 Y5 V5 Y6 Y7 V7 Y8其中,每采样过一个像素点,都会采样其 Y 分量,而 U、V 分量就会间隔一行按照 2 : 1 进行采样。
最后映射出的像素点为:[Y0 U0 V5]、[Y1 U0 V5]、[Y2 U2 V7]、[Y3 U2 V7][Y5 U0 V5]、[Y6 U0 V5]、[Y7 U2 V7]、[Y8 U2 V7]

假设图像像素为:[Y0 U0 V0]、[Y1 U1 V1]、 [Y2 U2 V2]、 [Y3 U3 V3][Y5 U5 V5]、[Y6 U6 V6]、 [Y7 U7 V7] 、[Y8 U8 V8]
那么采样的码流为:Y0 U0 Y1 Y2 U2 Y3 Y5 V5 Y6 Y7 V7 Y8其中,每采样过一个像素点,都会采样其 Y 分量,而 U、V 分量就会间隔一行按照 2 : 1 进行采样。
最后映射出的像素点为:[Y0 U0 V5]、[Y1 U0 V5]、[Y2 U2 V7]、[Y3 U2 V7][Y5 U0 V5]、[Y6 U0 V5]、[Y7 U2 V7]、[Y8 U2 V7]

从映射出的像素点中可以看到,四个 Y 分量是共用了一套 UV 分量,而且是按照 2*2 的小方格的形式分布的,相比 YUV 4:2:2 采样中两个 Y 分量共用一套 UV 分量,这样更能够节省空间。

一张 1280 * 720 大小的图片,在 YUV 4:2:0 采样时的大小为:

可以看到 YUV 4:2:0 采样的图像比 RGB 模型图像节省了一半的存储空间,因此它也是比较主流的采样方式。

YUV 的存储格式,有两种:

YUYV 格式是采用打包格式进行存储的,指每个像素点都采用 Y 分量,但是每隔一个像素采样它的 UV 分量,排列顺序如下:

UYVY 格式也是采用打包格式进行存储,它的顺序和 YUYV 相反,先采用 U 分量再采样 Y 分量,排列顺序如下:

YUV 422P 格式,又叫做 I422,采用的是平面格式进行存储,先存储所有的 Y 分量,再存储所有的 U 分量,再存储所有的 V 分量。

基于 YUV 4:2:0 采样的格式主要有 YUV 420P 和 YUV 420SP 两种类型,每个类型又对应其他具体格式。

I420 的单帧结构示意图如下(Planar 方式)

这幅图的上面一幅可以看出 Y1、Y2、Y7、Y8 共用 U1 和 V1。后面的线性数组为其存储顺序,可以看出 Y、U 和 V 都是顺序存储的,往外写的时候,先按顺序将 Y 分量写出,然后再根据 U、V 分别将它们依次写出即可。

NV12的单帧结构示意图如下(Planar 方式)

可以看出与 YV12 不同的时,它的 Y 虽然也是顺序存储,但 U、V 却是交错存储的,这种方式存储在往外写出时则先直接顺序写出 Y,然后对 UV 分别依次写出。

PS:Android的Camera Preview默认图像格式为NV21。

把RGB和YUV的范围都缩放到[0,255]
YUV转RGB

RGB转YUV

参考资料:
图片RGB数据格式
一文读懂 YUV 的采样与格式
视音频数据处理入门:RGB、YUV像素数据处理
Android Bitmap像素排列与JNI操作
YUV420_SVG

RGB与YUV转换以及存储格式

RGB与YUV

色彩空间(Color Space)[1]:is a specific organization of colors. In combination with physical device profiling, it allows for reproducible representations of color, in both analog and digital representations. A color space may be arbitrary, with particular colors assigned to a set of physical color swatches and corresponding assigned color names or numbers such as with the Pantone collection, or structured mathematically as with the NCS System, Adobe RGB and sRGB.

色彩模型(Color Model[1]is an abstract mathematical model describing the way colors can be represented as tuples of numbers (e.g. triples in RGB or quadruples in CMYK); however, a color model with no associated mapping function to an absolute color space is a more or less arbitrary color system with no connection to any globally understood system of color interpretation. Adding a specific mapping function between a color model and a reference color space establishes within the reference color space a definite "footprint", known as a gamut, and for a given color model this defines a color space.

不同色彩空间的比较

定义色彩空间时,通常使用 CIELAB 或者 CIEXYZ 色彩空间作为参考标准。这两个色彩空间在设计时便要求包含普通人眼可见的所有颜色。

由于“色彩空间”有着固定的色彩模型和映射函数组合,非正式场合下,这一词汇也被用来指代色彩模型。这样的用法严格意义上是错误的。

 

1.RGB

RGB色彩空间中的一种颜色是由红、绿、蓝光构成。由R、G、B三个分量组成。RGB颜色分量是跟设备相关的,不论是采集还是显示。在摄像头采集中,每个像素的颜色分量不仅取决于场景的颜色和光照,还取决于测量红、绿蓝分量的滤波器的光谱相应。在屏幕显示中,实际显示出来的颜色取决于显示器中红、绿、蓝光源的光谱。(所以,根据所使用的波长不同,可以有许多不同的RGB色彩空间。)

标准的RGB是24bit的,即每个分量8bit。考虑到带宽限制,也有16bit的RGB,R和B用5bit表示,G用6bit表示(因为人眼对绿色更敏感)。从16bit转到24bitRGB,不是添加0,而是添加2位(G)或3位(R、B)最高有效位。

为了克服RGB 的设备依赖性,人们又定义了一种不依赖上设备的sRGB,添加了光强与颜色分量数值之间的分线性γ映射。从RGB转换到sRGB,就是在色彩向量上乘以一个设备相关的红、绿、蓝光谱特性的3x3矩阵。这个变换由标定决定。

常见的RGB格式有RGB888,RGB565,RGB555,RGB24,RGB32(每个分量8比特,剩余8位空着),ARGB32(每个分量8比特,Alpha通道值8bit)等。

RGB的存储格式通常为BGRBGRBGR的顺序。

Bitmap就是在RGB像素数据上加上数据头形成的文件格式。

 

2. YUV

YUV is a color encoding system typically used as part of a color image pipeline. It encodes a color image or video taking human perception into account, allowing reduced bandwidth for chrominance components, thereby typically enabling transmission errors or compression artifacts to be more efficiently masked by the human perception than using a "direct" RGB-representation.[2]

Y′UV was invented when engineers wanted color television in a black-and-white infrastructure. They needed a signal transmission method that was compatible with black-and-white (B&W) TV while being able to add color. The luma component already existed as the black and white signal; they added the UV signal to this as a solution.

YUV是被欧洲电视系统所采用的一种颜色编码方法(属于PAL,Phase Alternation Line)。(YIQ用于NTSC彩色电视制式,YUV用于PAL制和SECAM彩色电视制式,而YCrCb用于计算机用的显示器。)

Y代表亮度(Luma,Luminance),UV代表色度(Chroma,Chrominance)。

YUV完全由RGB推到而来,亮度分量Y是RGB分量的组合,颜色分量由差分B-Y,R-Y提供。

二者的转化公式如下:

ITU-R BT.601定义了如下变量:

归一化之后的RGB(linear RGB, not gamma corrected RGB or sRGB)转换到YUV可以表示为:

此时Y、U、V的范围分别是[0, 1], [−Umax, Umax],[−Vmax, Vmax]。

 

YIQ将(U,V)旋转了33度,优点是减少了电视广播需要的带宽(因为与I分量相比人类对Q分量比较不敏感),缺点是需要9个乘法而不是上式中的5个。

 

严格来说,YUV是一种模拟表示,相应的数字表示为YCbCr。

YCrCb颜色空是由YUV颜色空间派生的一种颜色空间。YCbCr是在世界数字组织视频标准研制过程中作为ITU-R BT.601建议的一部分,其实是YUV经过缩放和偏移的翻版。YCrCb中的Y与YUV中的Y含义一致,Cb、Cr同样都指色彩,只是在表示方法上不同。在YUV家族中,YCbCr是在计算机系统中应用最多的成员,其应用领域很广泛,JPEG、MPEG均采用此格式。一般人们所讲的YUV大多是指YCbCr。

YCbCr的两种常用格式[3]:

1)ITU-R BT.601 conversion

缩放到具有上下动态裕量的8bit,平移后可以用无符号数表示。

2)JPEG conversion

使用完全的8bit输出表示每一个分量。

 

相比RGB,YUV或者YCbCr的优点是减少通道之间的相关性。可以方便的对色彩进行阈值处理;简化了彩色图像的增强,例如对比度增强只需要在图像的Y分量上执行;可以对亮度和色彩进行不同策略的噪声去除等。

缺点是转化是RGB坐标系的旋转,需要浮点或者定点乘法来执行;缩放系数的选择必须保证每个RGB组合具有一个有效的YCbCr表示,可是逆变换是非真的,有些YCbCr组合落在RGB的有效范围之外,如果需要计算逆变换,那么意味着YCbCr需要更多位表示。

 

YUV的常见采样格式

YUV444无压缩,YUV三个信道的采样率相同,三个分量信息完整(通常为8bit)。每个Y独享一对UV分量。每个像素3字节。

原始像素:[Y0 U0 V0][ Y1 U1 V1][ Y2 U2 V2]

码流:Y0 U0 V0 Y1 U1 V1 Y2 U2 V2 Y3 U3 V3

YUV4222:1的水平取样,垂直完全采样。每两个Y共用一组UV分量。每个像素2字节。

原始像素:[Y0 U0 V0][ Y1 U1 V1][ Y2 U2 V2]

码流:Y0 U0 Y1 V1 Y2 U2 Y3 V3

得到的像素:[Y0 U0 V1] [Y1 U0 V1] [Y2 U2 V3] [Y3 U2 V3]

YUV4114:1的水平取样,垂直完全采样。每四个Y共用一组UV分量。每个像素

8+(8/4)+(8/4)=12bits,1.5个字节。

原始像素:[Y0 U0 V0][ Y1 U1 V1][ Y2 U2 V2]

码流:Y0 U0 Y1 Y2 V2 Y3

得到的像素:[Y0 U0 V2] [Y1 U0 V2] [Y2 U0 V2] [Y3 U0 V2]

YUV4202:1的水平取样,垂直2:1采样。每四个Y共用一组UV分量。每个像素12bit,采样方式不一样了。

原始像素:[Y0 U0 V0][ Y1 U1 V1][ Y2 U2 V2] [Y3 U3 V3]

                 [Y5 U5 V5] [Y6 U6 V6] [Y7 U7 V7] [Y8 U8 V8]

码流:Y0 U0 Y1 Y2 U2 Y3

           Y5 V5 Y6 Y7 V7 Y8

得到的像素:[Y0 U0 V5] [Y1 U0 V5] [Y2 U2 V7] [Y3 U2 V7]

                     [Y5 U0 V5] [Y6 U0 V5] [Y7U2 V7] [Y8 U2 V7]

 

 

下图中,以黑点表示采样该像素点的Y分量,以空心圆圈表示采样该像素点的UV分量


YUV420比较常用。

U = Y / 4   V = Y / 4

所以YUV420 数据在内存中的长度是 width * height * 3 / 2

 

YUV存储格式

紧缩格式(packed formats):将YUV分量存放在同一个数组中,通常是几个相邻的像素组成一个宏像素(macro-pixel),和RGB的存放方式类似,在这种格式下每个像素点的YUV数据混合放在一个矩阵中。

平面格式(planar formats):使用三个数组分开存放YUV三个分量,就像是一个三维平面一样。其中Y为width*height,而U、V合占Y的一半。

 

YUV420中,一些特殊的存储格式:

YUV420p,planer模式,Y、U、V分别位于不同平面。按U、V存储顺序不同,可以分为

YV12:YYYYVVVUUU

YU12:YYYYUUUVVV,又叫I420

YUV420p的YU12存储格式如下:

 

YUV420sp,bi-planer或者two-planer双平面,Y在一个平面,UV在同一个平面交叉存储。

NV12:YYYYUVUVUV

NV21YYYYVUVUVU,安卓相机标准图片格式

YUV420sp的NV12存储格式如下:

 

OpenCV 中,RGB与YUV的互相转换:

使用cvtColor函数,在imgproc模块的types_c.h中查看转换代码:

RGB与YUV444互转:

RGB转YUV420p的YU12:


RGB转YUV420p的YV12:

 

YUV420p转RGB:

YUV420sp转RGB:

OpenCV没有RGB直接转YUV420sp的函数。

 

 

    1. https://en.wikipedia.org/wiki/Color_space
    2. https://en.wikipedia.org/wiki/YUV
    3. https://en.wikipedia.org/wiki/YCbCr

以上是关于RGB与YUV的主要内容,如果未能解决你的问题,请参考以下文章

YUV与RGB

RGB888与RGB565互相转换原理

YUV格式与RGB格式

图像RGB2YUV与YUV2RGB格式互转介绍

RGB与YUV

RGB与HSV之间的转换公式及颜色表