- 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)
RGB取值范围均为0~255,Y=0~255,U=-122~+122,V=-157~+157
以下是经过简化的公式,运算量比上述公式要小一些。
- RGB转YUV
Y = 0.299R + 0.587G + 0.114B
U'= (BY)*0.565
V'= (RY)*0.713
- YUV转RGB
R = Y + 1.403V'
G = Y - 0.344U' - 0.714V'
B = Y + 1.770U'
- 什么是YCbCr?
- YCbCr表示隔行分量端子,是属于YUV经过缩放和偏移的翻版,常说的YUV也称 作YCbCr。其中Y与YUV 中的Y含义一致,Cb , Cr 同样都指色彩,,只是在表示方法上不同而已,Cb Cr 就是本来理论上的“分量/色差”的标识。C代表分量(是component的缩写)Cr、Cb分别对应r(红)、b(蓝)分量信号,Y除了g(绿)分量信 号,还叠加了亮度信号。
- 其中YCbCr是隔行信号,YPbPr是逐行信号。YCbCr 是在计算机系统中应用最多的一种信号,其应用领域很广泛,JPEG、MPEG均采用此格式。
- 什么是YPbPr?
- Y'CbCr 在模拟分量视频(analog component video)中也常被称为YPbPr,YPbPr是将模拟的Y、PB、PR信号分开,使用三条线缆来独立传输,保障了色彩还原的准确性,YPbPr表示逐 行扫描色差输出.YPbPr接口可以看做是S端子的扩展,与S端子相比,要多传输PB、PR两种信号,避免了两路色差混合解码并再次分离的过程,也保持了 色度通道的最大带宽,只需要经过反矩阵解码电路就可以还原为RGB三原色信号而成像,这就最大限度地缩短了视频源到显示器成像之间的视频信号通道,避免了 因繁琐的传输过程所带来的图像失真,保障了色彩还原的准确,目前几乎所有大屏幕电视都支持色差输入。
YUV,分为三个分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。
与我们熟知的RGB类似,YUV也是一种颜色编码方法,主要用于电视系统以及模拟视频领域,它将亮度信息(Y)与色彩信息(UV)分离,没有UV信息一样可以显示完整的图像,只不过是黑白的,这样的设计很好地解决了彩色电视机与黑白电视的兼容问题。并且,YUV不像RGB那样要求三个独立的视频信号同时传输,所以用YUV方式传送占用极少的频宽。
YUV码流的存储格式其实与其采样的方式密切相关,主流的采样方式有三种,YUV4:4:4,YUV4:2:2,YUV4:2:0,关于其详细原理,可以通过网上其它文章了解,这里我想强调的是如何根据其采样格式来从码流中还原每个像素点的YUV值,因为只有正确地还原了每个像素点的YUV值,才能通过YUV与RGB的转换公式提取出每个像素点的RGB值,然后显示出来。
用三个图来直观地表示采集的方式吧,以黑点表示采样该像素点的Y分量,以空心圆圈表示采用该像素点的UV分量。
先记住下面这段话,以后提取每个像素的YUV分量会用到。
- YUV 4:4:4采样,每一个Y对应一组UV分量。
- YUV 4:2:2采样,每两个Y共用一组UV分量。
- YUV 4:2:0采样,每四个Y共用一组UV分量。
2. 存储方式
下面我用图的形式给出常见的YUV码流的存储方式,并在存储方式后面附有取样每个像素点的YUV数据的方法,其中,Cb、Cr的含义等同于U、V。
(1) YUVY 格式 (属于YUV422)

(2) UYVY 格式 (属于YUV422)


YUV422P也属于YUV422的一种,它是一种Plane模式,即平面模式,并不是将YUV数据交错存储,而是先存放所有的Y分量,然后存储所有的U(Cb)分量,最后存储所有的V(Cr)分量,如上图所示。其每一个像素点的YUV值提取方法也是遵循YUV422格式的最基本提取方法,即两个Y共用一个UV。比如,对于像素点Y'00、Y'01 而言,其Cb、Cr的值均为 Cb00、Cr00。

YU12和YV12属于YUV420格式,也是一种Plane模式,将Y、U、V分量分别打包,依次存储。其每一个像素点的YUV数据提取遵循YUV420格式的提取方式,即4个Y分量共用一组UV。注意,上图中,Y'00、Y'01、Y'10、Y'11共用Cr00、Cb00,其他依次类推。
(5)NV12、NV21(属于YUV420)

NV12和NV21属于YUV420格式,是一种two-plane模式,即Y和UV分为两个Plane,但是UV(CbCr)为交错存储,而不是分为三个plane。其提取方式与上一种类似,即Y'00、Y'01、Y'10、Y'11共用Cr00、Cb00
YUV420 planar数据, 以720×488大小图象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/2字节是V分量。
4 :2: 2 和4:2:0 转换:
最简单的方式:
YUV4:2:2 ---> YUV4:2:0 Y不变,将U和V信号值在行(垂直方向)在进行一次隔行抽样。 YUV4:2:0 ---> YUV4:2:2 Y不变,将U和V信号值的每一行分别拷贝一份形成连续两行数据。
width * hight =Y(总和) U = Y / 4 V = Y / 4
所以YUV420 数据在内存中的长度是 width * hight * 3 / 2,
假设一个分辨率为8X4的YUV图像,它们的格式如下图:
YUV420sp格式如下图
YUV420p数据格式如下图
旋转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;
}
}
}
YV12和I420的区别 一般来说,直接采集到的视频数据是RGB24的格式,RGB24一帧的大小size=width×heigth×3 Bit,RGB32的size=width×heigth×4,如果是I420(即YUV标准格式4:2:0)的数据量是 size=width×heigth×1.5 Bit。 在采集到RGB24数据后,需要对这个格式的数据进行第一次压缩。即将图像的颜色空间由RGB2YUV。因为,X264在进行编码的时候需要标准的YUV(4:2:0)。但是这里需要注意的是,虽然YV12也是(4:2:0),但是YV12和I420的却是不同的,在存储空间上面有些区别。如下: YV12 : 亮度(行×列) + U(行×列/4) + V(行×列/4)
I420 : 亮度(行×列) + V(行×列/4) + U(行×列/4)
可以看出,YV12和I420基本上是一样的,就是UV的顺序不同。
继续我们的话题,经过第一次数据压缩后RGB24->YUV(I420)。这样,数据量将减少一半,为什么呢?呵呵,这个就太基础了,我就不多写了。同样,如果是RGB24->YUV(YV12),也是减少一半。但是,虽然都是一半,如果是YV12的话效果就有很大损失。然后,经过X264编码后,数据量将大大减少。将编码后的数据打包,通过RTP实时传送。到达目的地后,将数据取出,进行解码。完成解码后,数据仍然是YUV格式的,所以,还需要一次转换,这样windows的驱动才可以处理,就是YUV2RGB24。
YUY2 是 4:2:2 [Y0 U0 Y1 V0]
Four CC 码
V4L2 采用编码
Positive biHeight implies top-down image (top line first)
YUY2(和YUYV)格式为像素保留 Y,而 UV 在水平空间上相隔二个像素采样一次。YVYU, UYVY格式跟YUY2类似,只是排列顺序有所不同。Y211格式是Y每2个像素采样一次,而UV每4个像素采样一次。AYUV格 式则有一 Alpha通道。
YV12格式与IYUV类似,每个像素都提取Y,在UV提取时,将图像2 x 2的矩阵,每个元素中提取一个U和一个V。YV12格式和I420格式的不同处在V平面和U平面的位置不同。在I420格式中,U平面紧跟在Y平面之后, 然后才是V平面(即:YUV);但YV12则是相反(即:YVU)。NV12与YV12类似,效果一样,YV12中 U 和 V 是连续排列的,而在NV12中,U 和 V 就交错排列的。
YUV 与 RGB 的转换公式:
U 和 V 元件可以被表示成原始的 R、 G,和 B:
如一般顺序,转移元件的范围可得到:
在逆转关系上,从 YUV 到 RGB,可得
取而代之,以矩阵表示法(matrix representation),可得到公式:
function RGB* YUV444toRGB888(Y, U, V);将 YUV format 移转成简单的 RGB format 并可以用浮点运算实作:
大多数 YUV 格式平均使用的每像素位数都少于24位元。YUV444是最逼真的格式,一格不删(24 bits),即每4个Y,配上4个 U,还有4个 V;YUV422则是在UV格式上减半,即每4个Y,配2个U,2个V ;YUV420则是在UV上减1/4之格式,即每4个Y,配1个U,再配1个V。
这些公式是基于 NTSC standard;
在早期的非SIMD(non-SIMD)构造中,floating point arithmetic 会比 fixed-point arithmetic 稍慢,所以有一替代公式如下:
- C= Y' - 16
- D= U- 128
- E= V- 128
使用前面的系数并且用 clip() 注明切割的值域是 0 至 255,如下的公式是从 Y'UV 到 RGB (NTSC version):
注意:上述的公式多暗示为 YCbCr. 虽然称为 YUV,但应该严格区分 YUV 和 YCbCr 这两个专有名词有时并非完全相同。
ITU-R 版本的公式差异:
ITU-R 标准 YCbCr(每一通道8位元)至 RGB888:
Cr = Cr - 128; Cb = Cb - 128;
- R= Y+ Cr+ Cr> > 2 + Cr> > 3 + Cr> > 5
- G= Y? (Cb> > 2 + Cb> > 4 + Cb> > 5) ? (Cr> > 1 + Cr> > 3 + Cr> > 4 + Cr> > 5)
- B= Y+ Cb+ Cb> > 1 + Cb> > 2 + Cb> > 6
- Input:读取 Y'UV 的4bytes(u, y1, v, y2 )
- Output:写入 RGB的6bytes (R, G, B, R, G, B)
u = yuv[0]; y1 = yuv[1]; v = yuv[2]; y2 = yuv[3];
以此一资讯可以剖析出 regular Y'UV444 格式而成为 2 RGB pixels info:
rgb1 = Y'UV444toRGB888(y1, u, v); rgb2 = Y'UV444toRGB888(y2, u, v);
Y'UV422 可被表达成 Y'UY'2 FourCC 格式码。意思是 2 pixels 将被定义成 each macropixel (four bytes) treated in the image.
// Extract YUV components u = yuv[0]; y1 = yuv[1]; y2 = yuv[2]; v = yuv[3]; y3 = yuv[4]; y4 = yuv[5];
rgb1 = Y'UV444toRGB888(y1, u, v); rgb2 = Y'UV444toRGB888(y2, u, v); rgb3 = Y'UV444toRGB888(y3, u, v); rgb4 = Y'UV444toRGB888(y4, u, v);
所以结果会得到 4 RGB 像素的值 (4*3 bytes) from 6 bytes. This means reducing size of transferred data to half and with quite good loss of quality.
The Y'V12 的格式相当类似 Y'UV420p,但 U 与 V 资料反转:Y' 跟随着 V, U 殿后。Y'UV420p 与 Y'V12 使用相同算法。许多重要的编码器都采用YV12空间存储视频:MPEG-4(x264,XviD,DivX),DVD- Video存储格式MPEG-2,MPEG-1以及MJPEG。
将Y'UV420p 转换成 RGB
Height = 16; Width = 16; Y'ArraySize = Height × Width; // (256) Y' = Array[7 × Width + 5]; U = Array[(7/2) × (Width/2) + 5/2 + Y'ArraySize]; V = Array[(7/2) × (Width/2) + 5/2 + Y'ArraySize + Y'ArraySize/4]; RGB = Y'UV444toRGB888(Y', U, V);
参考:
到此这篇yuv444和rgb888区别(yuv422和rgb的区别)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/rfx/34588.html