YUV 与RGB之间的变换
YUV422到RGB24的转换
YUV422_to_RGB24转换算法最近做摄像头的测试,读取出来的数据为YUV422(YUYV)格式,若要在LCD上面显示,需要先做格式转换,但在网上搜了一遍,只有YUV420转RGB的算法,无奈自己做了一个函数,实现到RGB24的格式转换,转成RGB24(即RGB888)之后,就可以根据自己的LCD格式再做其他转换,例如我的LCD显示格式为RGB565,可以再做一个RGB24到RGB565的转换即可,类似转换比较简单,相关例程网上也比较多,就不多做描述了,下面给出YUV422到RGB24的转换函数:typedef unsigned char uint8_t;static void yuv422_to_rgb24(unsigned char *yuv422,unsigned char *rgb24, int width, int height){int x,y;uint8_t *yuv444;yuv444 = (uint8_t *) malloc(sizeof(uint8_t) * WIDTH * HEIGHT * 3);for(x = 0,y = 0;x < width*height*2,y < width*height*3;x+=4,y+=6){yuv444[y] = yuv422[x];yuv444[y+1] = yuv422[x+1];yuv444[y+2] = yuv422[x+3];yuv444[y+3] = yuv422[x+2];yuv444[y+4] = yuv422[x+1];yuv444[y+5] = yuv422[x+3];}for(x = 0;x < width*height*3;x+=3){rgb24[x+2] = yuv444[x] + 1.402*(yuv444[x+2] - 128);rgb24[x+1] = yuv444[x]-0.34414*(yuv444[x+1]-128)-0.71414*(yuv444[x+2]-128);rgb24[x] = yuv444[x] + 1.772*(yuv444[x+1] - 128);if (rgb24[x]>255)rgb24[x]=255;if (rgb24[x]<0)rgb24[x]=0;if (rgb24[x+1]>255)rgb24[x+1]=255;if (rgb24[x+1]<0)rgb24[x+1]=0;if (rgb24[x+2]>255)rgb24[x+2]=255;if (rgb24[x+2]<0)rgb24[x+2]=0;}free(yuv444);}该函数的转换思想是先进行YUV422到YUV444的转化,再进行YUV444到RGB24的转化,利用一个YUV422像素点得到两个YUV444像素点,其中YUV444[0]由Y[0]、U[0]、V[0]得到,YUV444[1]由Y[1] 、U[0]、V[0]得到,可见UV分量被重复利用。
关于YUV和RGB之间的转换公式
关于YUV和RGB之间的转换公式总结了一下网上关于YUV的一些东西先区分一下YUV和YCbCrYUV色彩模型来源于RGB模型,该模型的特点是将亮度和色度分离开,从而适合于图像处理领域。
应用:模拟领域Y'= 0.299*R' + 0.587*G' + 0.114*B'U'= -0.147*R' - 0.289*G' + 0.436*B' = 0.492*(B'- Y')V'= 0.615*R' - 0.515*G' - 0.100*B' = 0.877*(R'- Y')R' = Y' + 1.140*V'G' = Y' - 0.394*U' - 0.581*V'B' = Y' + 2.032*U'YCbCr模型来源于YUV模型。
YCbCr是YUV 颜色空间的偏移版本.应用:数字视频,ITU-R BT.601建议Y’ = 0.257*R' + 0.504*G' + 0.098*B' + 16Cb' = -0.148*R' - 0.291*G' + 0.439*B' + 128Cr' = 0.439*R' - 0.368*G' - 0.071*B' + 128R' = 1.164*(Y’-16) + 1.596*(Cr'-128)G' = 1.164*(Y’-16) - 0.813*(Cr'-128) - 0.392*(Cb'-128)B' = 1.164*(Y’-16) + 2.017*(Cb'-128)PS: 上面各个符号都带了一撇,表示该符号在原值基础上进行了伽马校正,伽马校正有助于弥补在抗锯齿的过程中,线性分配伽马值所带来的细节损失,使图像细节更加丰富。
色彩空间变换算法
色彩空间变换算法
RGB色彩空间是由红、绿、蓝三个基色按照一定比例混合而成的,它是最常见的颜色空间。
但在一些特定的应用中,比如图像处理、计算机视觉等,RGB色彩空间可能无法满足需求,因此需要将图像转换到其他色彩空间。
1.线性变换算法:
-RGB到YUV变换:YUV色彩空间是将RGB色彩空间进行线性变换得到的,其中Y分量表示亮度,而U和V分量表示色度。
变换公式如下:Y=0.299*R+0.587*G+0.114*B
U=0.492*(B-Y)
V=0.877*(R-Y)
-RGB到XYZ变换:XYZ色彩空间是一种绝对色彩空间,其与RGB空间的转换是线性的,并且是一种无损转换。
变换公式如下:
2.非线性变换算法:
-RGB到HSV变换:HSV色彩空间是一种更接近人眼感知的色彩空间,其中H表示色调,S表示饱和度,V表示明度。
变换公式如下:V = max(R, G, B)
S = (V-min(R, G, B))/V
H=
if V = R, then 60 * (G-B)/(V-min(R, G, B))
if V = G, then 120 + 60 * (B-R)/(V-min(R, G, B))
if V = B, then 240 + 60 * (R-G)/(V-min(R, G, B))
- RGB到Lab变换:Lab色彩空间是一种非线性的色彩空间,其中L 表示明度,a表示从红色到绿色的范围,b表示从黄色到蓝色的范围。
变换公式需要进行归一化处理,如下:
L=116*f(Y/Yn)-16
a=500*(f(X/Xn)-f(Y/Yn))
b=200*(f(Y/Yn)-f(Z/Zn))。
YYCbCr与RGB之间的转换关系
YYCbCr与RGB之间的转换关系1YUV空间简介YUV为亮度-色差形式的色彩空间格式,Y表示亮度,U, V表示色差。
YUV色彩空间中,主要有三种格式:YUV, YIQ和YCbCr。
YCbCr特指CCITT601 (CCITT后改名为ITU-T)规定的数字化后的色彩空间格式。
YUV特指JPEG图像压缩标准中规定的色彩空间格式。
YUV和YIQ的区别在于它们在色度矢量图中的位置不同而已,多了一个33度角的旋转。
YcbCr则为MPEG和H.26X标准所采纳。
注意,凡是标明符合ITU-T 601 或ITU-T 656接口标准的视频采集器/视频输入端口,其采集到的视频数据均为YCbCr格式,即使有关文档里用的是YUV字样,但实际上是YCbCr格式(U相当于Cb,V相当于Cr)。
比如:我们的PHILIPS 1300的VI,1500的AI, SAA7113等,均为YCbCr格式。
2YIQ和RGB之间的转换关系RGB到YIQ的转换关系如下式:Y = 0299 R + 0.587 G + 0.144 BI = 0.596R – 0.274G – 0.322 B (式1)Q = 0. 211R – 0.522 G + 0.311 BYIQ到RGB的转换关系为:R = Y + 0.956 I + 0.623 QG = Y – 0.272 I – 0.648 Q (式2)B = Y – 1.105 I + 0.705 Q3YUV和RGB之间的转换关系注意,这里的YUV特指JPEG图像压缩标准中规定的色彩空间格式。
在JPEG图像信息压缩标准中,规定R,G,B的范围为0~255,转换后的Y取值范围为0~255,U, V的取值范围为0 ~ 128。
RGB到YUV 的转换关系如下式:Y = 0.299 R + 0.587 G + 0.144 B ;U = -0.1678 R - 0.3313 G+ 0.5 B; (式3)V = 0.5 R - 0.4187 G - 0.0813 B;YCbCr到RGB的转换关系如下式:R = Y + 1.1402 VG = Y – 0.34414 U – 0.71414 V (式4)B = Y + 1.1772 U4YCbCr和RGB之间的转换关系注意,这里的YCbCr特指CCITT601规定的数字化后的色彩空间格式CCITT601,对R,G,B和Y,Cb,Cr之间的转换关系做了规定:亮度值Y的范围为16 ~235,色度值Cb,Cr的范围为16 ~240,YCbCr和RGB之间的转换关系可以由上面的(式3)和(式4)做如下转换才能得到正确的结果:Y = 219/255 * Y + 16 (等式左边的Y指的是YcbCr中的Y分量)Cb = 224/255 * U + 128Cr = 224/255 * V + 128即:Y = 0.2568 R + 0.504 G + 0.1237 B + 16Cb = -0.1474 R - 0.291 G+ 0.4392 B + 128 (式4)Cr = 0.4392 R - 0.3678 G - 0.0714 B + 128YCbCr到RGB之间的转换关系为:R = 1.16438 Y + 1.596 Cr – 222.92G = 1.16438 Y – 0.3917 Cb – 0.81297 Cr + 135.576 (式5)B = 1.16438 Y + 2.016Cb – 190.1655附录1:Converting Between YUV and RGB(From MS)It is frequently necessary to convert between YUV pixel formats (used by the JPEG and MPEG co mpression methods) and RGB format (used by many hardware manufacturers.) The following for mulas show how to compute a pixel's value in one format from the pixel value in the other format.YUV format allows for higher compression rates without a proportionately high loss of data, as the U and V portions can be highly compressed and computed from the non- or lowly-compr essed Y portion.Computer RGB888, or full-scale RGB, uses 8 bits each for the red, green, and blue channels. Blac k is represented by R = G = B = 0, and white is represented by R = G = B = 255. The 4:4:4 YUV f ormat uses 8 bits each for the Y, U, and V channels.************************************************************Converting RGB888 to YUV************************************************************The following formulas define the conversion from RGB to YUV:Y = ( ( 66 * R + 129 * G + 25 * B + 128) >> 8) + 16U = ( ( -38 * R - 74 * G + 112 * B + 128) >> 8) + 128V = ( ( 112 * R - 94 * G - 18 * B + 128) >> 8) + 128These formulas produce 8-bit results using coefficients that require no more than 8 bits of (unsign ed) precision. Intermediate results require up to 16 bits of precision.************************************************************Converting 8-bit YUV to RGB888************************************************************The following coefficients are used in conversion process:C = Y - 16D = U - 128E = V - 128Using the previous coefficients and noting that clip() denotes clipping a value to the range of 0 to 255, the following formulas provide the conversion from YUV to RGB:R = clip(( 298 * C + 409 * E + 128) >> 8)G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)B = clip(( 298 *C + 516 *D + 128) >> 8)These formulas use some coefficients that require more than 8 bits of precision to produce each 8-bit result, and intermediate results require more than 16 bits of precision.Note All units range from 0 (zero) to 1.0 (one). In DirectDraw, they range from 0 to 255. Overflo w and underflow can (and does) occur, and the results must be saturated.To convert 4:2:0 or 4:2:2 YUV to RGB, convert the YUV data to 4:4:4 YUV, and then convert fro m 4:4:4 YUV to RGB.。
yuv 和颜色对应关系
yuv 和颜色对应关系YUV和颜色对应关系YUV是一种表示颜色的方式,常用于数字影像、视频压缩及传输等领域。
它是由亮度(Y)和两个色度(U和V)组成的,与RGB(红绿蓝)颜色空间相比,YUV能更好地适应人眼的感知特性,具有更好的压缩效果和更小的数据量。
YUV和颜色之间的对应关系可以通过以下方式进行描述:1. Y分量Y分量代表图像的亮度信息,取值范围为0到255,数值越大,表示亮度越高。
在RGB颜色空间中,亮度的计算方法为: Y = 0.299R + 0.587G + 0.114B。
在YUV颜色空间中,Y分量就是该计算公式的结果。
2. U分量U分量代表图像的色度(色彩饱和度)信息,取值范围为-128到127,数值越大,表示颜色越饱和、色彩越鲜艳。
在RGB颜色空间中,U分量的计算方法为:U = -0.169R - 0.331G + 0.5B。
在YUV颜色空间中,U分量的计算方法为:U = (B-Y) x 0.493。
3. V分量V分量同样代表图像的色度信息,取值范围为-128到127,数值越大,表示颜色越饱和、色彩越鲜艳。
在RGB颜色空间中,V分量的计算方法为:V = 0.5R - 0.419G - 0.081B。
在YUV颜色空间中,V 分量的计算方法为:V = (R-Y) x 0.877。
通过以上公式,我们可以计算出任意一个RGB颜色值对应的YUV值,并且可以相互转换。
在数字影像和视频领域中,常常使用YUV颜色空间来进行压缩和传输,以获得更好的压缩效果和更小的数据量。
总结:YUV是一种表示颜色的方式,可以更好地适应人眼的感知特性,并具有更好的压缩效果和更小的数据量。
YUV和颜色之间的对应关系可以通过Y、U、V三个分量来描述,其中Y分量代表亮度信息,U 和V分量代表色度信息。
通过计算公式,可以将任意一个RGB颜色值转换为对应的YUV值。
【总结】关于YUV-RGB格式转换的一些个人理解
【总结】关于YUV-RGB格式转换的⼀些个⼈理解 这段时间⼀直在研究YUV的格式问题例如YUV422、YUV420,在⽹上搜索了很多这⽅⾯的资料,发现很多资料讲的东西是重复的,没有⽐较深⼊的讲解,所以看了之后印象不是很深,过了⼀段时间之后⼜对它们有了困惑。
所以就有了⼀个想法,打算⾃⼰写⼀个c语⾔⼩程序,通过对BMP⽂件的RGB数据读取,然后将得到的RGB数据转换成为YUV格式的⽂件,然后⽤YUV的播放器打开,查看是否解析正确。
(在这⾥,BMP⽂件我选择了24bpp的格式,为了⽅便。
)通过这样的⽅式,正向和逆向学习来加深YUV⽂件的认识。
经过了2天的努⼒,从想法到实践,终于完成了YUV422和YUV420的⽣成,基本上对YUV的⼏种常见格式有了⼀些深⼊的看法,由于本⼈的⽔平有限,如果理解有出⼊,还请各位⽹友能够指出。
⼀、基本思路先附上主要程序的流程图:在正式讲解代码前,我们先来了解YUV的分类:packed: 打包模式,即Y、U、V数据是连续排布的planar: 平⾯模式,即Y、U、V是各⾃分开存放的semi-planar: 半平⾯模式,即Y单独存放, UV⼀起存放上⾯的3种是主要内存排布的分类,⾄于详细的排布如下(主要是YUV422、YUV420):(我们使⽤⼀张分辨率为 height*width的图⽚为例⼦)YUV422 planar:整个YUV⽂件中,Y、U、V是⼀个⼤数组,⽽其中我们可以看成是三个⼩数组,分别是Y数组(长度为Height*Width)、U数组(长度为Height*Width/2)、V数组(长度为Height*Width/2)。
YUV422 Semi planar:YUV420 planar :整个YUV⽂件中,Y、U、V是⼀个⼤数组,⽽其中我们可以看成是三个⼩数组,分别是Y数组(长度为Height*Width)、U数组(长度为Height*Width/4)、V数组(长度为Height*Width/4)。
RGB与YUV(正式版)
将RGB三个通道的像素值分别乘以相应的权重系数,然后相加得到Y通道的像素 值。
第二步
计算U和V通道的像素值,U通道的像素值可以通过从R通道像素值中减去Y通道 像素值得到,V通道的像素值可以通过从B通道像素值中减去Y通道像素值得到。
YUV转RGB的算法
第一步
将Y通道的像素值作为RGB三个通道 的像素值。
主要用于电视广播和视频压缩。Y分量表示亮度信息,而U和V分量表示
色度信息。
03
总结
RGB和YUV色彩空间的主要区别在于它们处理颜色的方式。RGB基于加
色模型,而YUV基于减色模型。
信号传输的差异
RGB信号传输
RGB信号直接传输红、绿、蓝三个通道的亮度信息,需要 传输更多的数据,尤其是在高清视频中。
第二步
将U和V通道的像素值分别加上相应的 偏移量,然后分别分配给R、G、B三 个通道。
转换过程中的失真问题
01
02
03
色彩失真
由于RGB和YUV颜色空间 在色彩表示上的差异,直 接进行转换可能导致色彩 失真。
亮度失真
在转换过程中,如果对 RGB像素值进行线性变换, 可能会影响图像的亮度信 息,导致亮度失真。
YUV图像质量
YUV主要用于电视广播和视频压缩,通过减少色度通道的数据量来实现高效的压缩。在适 当的压缩和解码条件下,YUV图像质量可以非常接近RGB图像质量。
总结
在图像质量方面,RGB通常提供更真实的颜色再现,而YUV通过高效的压缩实现适合电视 广播和视频应用的效果。
04 RGB与YUV的转换
RGB转YUV的算法
RGB的应用
RGB色彩模式在计算机图形学中广泛应用,用于 创建和编辑图像。
yuv rgb 互转 公式 及算法
1 前言自然界的颜色千变万化,为了给颜色一个量化的衡量标准,就需要建立色彩空间模型来描述各种各样的颜色,由于人对色彩的感知是一个复杂的生理和心理联合作用的过程,所以在不同的应用领域中为了更好更准确的满足各自的需求,就出现了各种各样的色彩空间模型来量化的描述颜色。
我们比较常接触到的就包括RGB / CMYK / YIQ / YUV / HSI等等。
对于数字电子多媒体领域来说,我们经常接触到的色彩空间的概念,主要是RGB , YUV 这两种(实际上,这两种体系包含了许多种具体的颜色表达方式和模型,如sRGB, Adobe RGB, YUV422, YUV420 …), RGB是按三基色加光系统的原理来描述颜色,而YUV则是按照亮度,色差的原理来描述颜色。
即使只是RGB YUV这两大类色彩空间,所涉及到的知识也是十分丰富复杂的,自知不具备足够的相关专业知识,所以本文主要针对工程领域的应用及算法进行讨论。
2 YUV相关色彩空间模型对于YUV模型,实际上很多时候,我们是把它和YIQ / YCrCb模型混为一谈的。
实际上,YUV模型用于PAL制式的电视系统,Y表示亮度,UV并非任何单词的缩写。
YIQ模型与YUV模型类似,用于NTSC制式的电视系统。
YIQ颜色空间中的I和Q分量相当于将YUV空间中的UV分量做了一个33度的旋转。
YCbCr颜色空间是由YUV颜色空间派生的一种颜色空间,主要用于数字电视系统中。
从RGB到YCbCr的转换中,输入、输出都是8位二进制格式。
三者与RGB的转换方程如下:RGB -> YUV:实际上也就是:Y=0.30R+0.59G+0.11B ,U=0.493(B-Y) ,V=0.877(R-Y)RGB -> YIQ:RGB -> YCrCb:从公式中,我们关键要理解的一点是,UV / CbCr信号实际上就是蓝色差信号和红色差信号,进而言之,实际上一定程度上间接的代表了蓝色和红色的强度,理解这一点对于我们理解各种颜色变换处理的过程会有很大的帮助。
YUV与RGB
RGB 格式是将色彩分成红绿蓝3个分量,没有红绿蓝时为黑色,红绿蓝3色都最亮时为白色。
常见的RGB格式有16 bit(高彩)和24bit(真彩),16 bit的RGB格式实际上还包含15 bit RGB和真16 bit RGB, 这两种格式都将红和蓝分成32等级,但是15bitRGB(也称为5-5-5 RGB)将绿色分成32等级,而16 bit RGB则将绿色分成64等级(所谓5-6-5 RGB),不过这两者占据的空间是相同的。
24 bit GRB(8-8-8 RGB)是将3个色道都分成256等级。
所有RGB24就是RGB888YUV和YCrCb(亮度/色度)格式,这两种格式非常相似,它是将色彩分成一个Y值(亮度)和两个U值和V值(定义颜色),这种格式实际上是利用了人眼的视觉特性,对亮度比较敏感,而对颜色相对较迟钝。
也由于这个原因,有些YUV格式采用了色度抽样,即U/V 值是针对一个象素组合来确定的,而不是一个单个象素,于是便出现了YUV9,YUV12等不同的格式,最普遍的是YUV12,常用于MPEG视频解码后的输出,每个象素都有自己的Y值,但是U/V值则包括了2x2象素组,或者说每个2x2象素组只有一个U/V值,相当于每个象素用了12 bit来编码,所以叫YUV12。
YUV9与YUV12类似,不同的是YUV9中的U/V值包含了4x4个象素组,因此在YUV9里面,每个象素由9 bit来编码。
关于RGB-YUV转换,这在视频编码里面是一个常见的预处理步骤。
对电脑产生的图形进行编码时,要特别小心YUV转换,因为色度抽样很容易导致图像中的颜色产生色渗透。
代码typedef struct YUVTRIPLE_FAST{BYTE V;BYTE U;BYTE Y;} YUVTRIPLE;inline RGBTRIPLE YUV2RGB(YUVTRIPLE yuv){int r, g, b;RGBTRIPLE rgb;r = (298*(yuv.Y-16) + 409*(yuv.V - 128) + 128) > > 8;g = (298*(yuv.Y-16) - 100*(yuv.U - 128) - 208*(yuv.V - 128) + 128)> > 8;b = (298*(yuv.Y-16) + 516*(yuv.U - 128) +128) > > 8;if(r > 255) r = 255;else if(r < 0) r = 0;if(g > 255) g = 255;else if(g < 0) g = 0;if(b > 255) b = 255;else if(b < 0) b = 0;rgb.rgbtRed = r;rgb.rgbtGreen = g;rgb.rgbtBlue = b;return rgb;}inline YUVTRIPLE RGB2YUV(RGBTRIPLE rgb){YUVTRIPLE yuv;yuv.Y = ((66*rgb.rgbtRed + 129*rgb.rgbtGreen + 25*rgb.rgbtBlue + 128) > > 8) + 16;yuv.U = ((-38*rgb.rgbtRed - 74*rgb.rgbtGreen + 112*rgb.rgbtBlue + 128) > > 8) + 128;yuv.V = ((112*rgb.rgbtRed - 94*rgb.rgbtGreen - 18*rgb.rgbtBlue + 128) > > 8) + 128;return yuv;}/china/MSDN/library/enterprisedevelopment/softwaredev/VideoRende8 BitYUV.mspx?mfr=trueorConvertYuvToRGB24Bstream(LPBYTE pY,LPBYTE pCb,LPBYTE pCr,LPBYTE hpOutput,int imWidth,int imHeight){//WTYPE *pY, *pCr, *pCb;LPBYTE cbuf;long x, y;short int r,g,b;cbuf = hpOutput;for (y=0; y <imHeight; y++ ){cbuf = hpOutput + ((imWidth*3)*(imHeight-y-1));for (x=0; x <imWidth/2; x++){YUV2RGB(pY[0],pCb[0],pCr[0],r,g,b);cbuf[0] = (unsigned char)b;//TRIM(b);// cbuf[1] = (unsigned char)g;//TRIM(g);// cbuf[2] = (unsigned char)r;//TRIM(r);// YUV2RGB(pY[1],pCb[0],pCr[0],r,g,b);cbuf[3] = (unsigned char)b;//TRIM(b);// cbuf[4] = (unsigned char)g;//TRIM(g);// cbuf[5] = (unsigned char)r;//TRIM(r);// cbuf += 6;pY += 2;pCr++;pCb++;}}}。
yuv420与RGB888之间相互转换
1.//rgb转yuv4202.//////////////////////////////////////////////////////////////////////////3.bool RGB2YUV(LPBYTE RgbBuf,UINT nWidth,UINT nHeight,LPBYTE yuvBuf,unsigned long*len)4.{5.int i,j;6.unsigned char*bufY,*bufU,*bufV,*bufRGB,*bufYuv;7.memset(yuvBuf,0,(unsigned int)*len);8.bufY=yuvBuf;9.bufV=yuvBuf+nWidth*nHeight;10.bufU=bufV+(nWidth*nHeight*1/4);11.*len=0;12.unsigned char y,u,v,r,g,b,testu,testv;13.unsigned int ylen=nWidth*nHeight;14.unsigned int ulen=(nWidth*nHeight)/4;15.unsigned int vlen=(nWidth*nHeight)/4;16.for(j=0;j<nHeight;j++)17.{18.bufRGB=RgbBuf+nWidth*(nHeight-1-j)*3;19.for(i=0;i<nWidth;i++)20.{21.int pos=nWidth*i+j;22.r=*(bufRGB++);23.g=*(bufRGB++);24.b=*(bufRGB++);25.y=(unsigned char)((66*r+129*g+25*b+128)>>8)+16;26.u=(unsigned char)((-38*r-74*g+112*b+128)>>8)+128;27.v=(unsigned char)((112*r-94*g-18*b+128)>>8)+128;28.*(bufY++)=max(0,min(y,255));29.if(j%2==0&&i%2==0)30.{31.if(u>255)32.{33.u=255;34.}35.if(u<0)36.{37.u=0;38.}39.*(bufU++)=u;40.//存u分量41.}42.else43.{44.//存v分量45.if(i%2==0)46.{47.if(v>255)48.{49.v=255;50.}51.if(v<0)52.{53.v=0;54.}55.*(bufV++)=v;56.}57.}58.}59.}60.*len=nWidth*nHeight+(nWidth*nHeight)/2;61.return true;62.}63.//////////////////////////////////////////////////////////////////////////64.//yuv420转rgb65.//////////////////////////////////////////////////////////////////////////66.bool YUV2RGB(LPBYTE yuvBuf,UINT nWidth,UINT nHeight,LPBYTE pRgbBuf,unsigned long*len)67.{68.#define PIXELSIZE nWidth*nHeight69.const int Table_fv1[256]={-180,-179,-177,-176,-174,-173,-172,-170,-169,-167,-166,-165,-163,-162,-160,-159,-158,-156,-155,-153,-152,-151,-149,-148,-146,-145,-144,-142,-141,-139,-138,-137,-135,-134,-132,-131,-130,-128,-127,-125,-124,-123,-121,-120,-118,-117,-115,-114,-113,-111,-110,-108,-107,-106,-104,-103,-101,-100,-99,-97,-96,-94,-93,-92,-90,-89,-87,-86,-85,-83,-82,-80,-79,-78,-76,-75,-73,-72,-71,-69,-68,-66,-65,-64,-62,-61,-59,-58,-57,-55,-54,-52,-51,-50,-48,-47,-45,-44,-43,-41,-40,-38,-37,-36,-34,-33,-31,-30,-29,-27,-26,-24,-23,-22,-20,-19,-17,-16,-15,-13,-12,-10,-9,-8,-6,-5,-3,-2,0,1,2,4,5,7,8,9,11,12,14,15,16,18,19,21,22,23,25,26,28,29,30,32,33,35, 36,37,39,40,42,43,44,46,47,49,50,51,53,54,56,57,58,60,61,63,64,65,67,68, 70,71,72,74,75,77,78,79,81,82,84,85,86,88,89,91,92,93,95,96,98,99,100,10 2,103,105,106,107,109,110,112,113,114,116,117,119,120,122,123,124,126,12 7,129,130,131,133,134,136,137,138,140,141,143,144,145,147,148,150,151,15 2,154,155,157,158,159,161,162,164,165,166,168,169,171,172,173,175,176,17 8};70.const int Table_fv2[256]={-92,-91,-91,-90,-89,-88,-88,-87,-86,-86,-85,-84,-83,-83,-82,-81,-81,-80,-79,-78,-78,-77,-76,-76,-75,-74,-73,-73,-72,-71,-71,-70,-69,-68,-68,-67,-66,-66,-65,-64,-63,-63,-62,-61,-61,-60,-59,-58,-58,-57,-56,-56,-55,-54,-53,-53,-52,-51,-51,-50,-49,-48,-48,-47,-46,-46,-45,-44,-43,-43,-42,-41,-41,-40,-39,-38,-38,-37,-36,-36,-35,-34,-33,-33,-32,-31,-31,-30,-29,-28,-28,-27,-26,-26,-25,-24,-23,-23,-22,-21,-21,-20,-19,-18,-18,-17,-16,-16,-15,-14,-13,-13,-12,-11,-11,-10,-9,-8,-8,-7,-6,-6,-5,-4,-3,-3,-2,-1,0,0,1,2,2,3,4,5,5,6,7,7,8,9,10,10,11,12,12,13,14,15,15,16,17,17,18,19,2 0,20,21,22,22,23,24,25,25,26,27,27,28,29,30,30,31,32,32,33,34,35,35,36,3 7,37,38,39,40,40,41,42,42,43,44,45,45,46,47,47,48,49,50,50,51,52,52,53,5 4,55,55,56,57,57,58,59,60,60,61,62,62,63,64,65,65,66,67,67,68,69,70,70,7 1,72,72,73,74,75,75,76,77,77,78,79,80,80,81,82,82,83,84,85,85,86,87,87,8 8,89,90,90};71.const int Table_fu1[256]={-44,-44,-44,-43,-43,-43,-42,-42,-42,-41,-41,-41,-40,-40,-40,-39,-39,-39,-38,-38,-38,-37,-37,-37,-36,-36,-36,-35,-35,-35,-34,-34,-33,-33,-33,-32,-32,-32,-31,-31,-31,-30,-30,-30,-29,-29,-29,-28,-28,-28,-27,-27,-27,-26,-26,-26,-25,-25,-25,-24,-24,-24,-23,-23,-22,-22,-22,-21,-21,-21,-20,-20,-20,-19,-19,-19,-18,-18,-18,-17,-17,-17,-16,-16,-16,-15,-15,-15,-14,-14,-14,-13,-13,-13,-12,-12,-11,-11,-11,-10,-10,-10,-9,-9,-9,-8,-8,-8,-7,-7,-7,-6,-6,-6,-5,-5,-5,-4,-4,-4,-3,-3,-3,-2,-2,-2,-1,-1,0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,9,10,10,11,11 ,11,12,12,12,13,13,13,14,14,14,15,15,15,16,16,16,17,17,17,18,18,18,19,19, 19,20,20,20,21,21,22,22,22,23,23,23,24,24,24,25,25,25,26,26,26,27,27,27, 28,28,28,29,29,29,30,30,30,31,31,31,32,32,33,33,33,34,34,34,35,35,35,36, 36,36,37,37,37,38,38,38,39,39,39,40,40,40,41,41,41,42,42,42,43,43};72.const int Table_fu2[256]={-227,-226,-224,-222,-220,-219,-217,-215,-213,-212,-210,-208,-206,-204,-203,-201,-199,-197,-196,-194,-192,-190,-188,-187,-185,-183,-181,-180,-178,-176,-174,-173,-171,-169,-167,-165,-164,-162,-160,-158,-157,-155,-153,-151,-149,-148,-146,-144,-142,-141,-139,-137,-135,-134,-132,-130,-128,-126,-125,-123,-121,-119,-118,-116,-114,-112,-110,-109,-107,-105,-103,-102,-100,-98,-96,-94,-93,-91,-89,-87,-86,-84,-82,-80,-79,-77,-75,-73,-71,-70,-68,-66,-64,-63,-61,-59,-57,-55,-54,-52,-50,-48,-47,-45,-43,-41,-40,-38,-36,-34,-32,-31,-29,-27,-25,-24,-22,-20,-18,-16,-15,-13,-11,-9,-8,-6,-4,-2,0,1,3,5,7,8,10,12,14,15,17,19,21,23,24,26,28,30,31,33,35,37,39,40,42,4 4,46,47,49,51,53,54,56,58,60,62,63,65,67,69,70,72,74,76,78,79,81,83,85,8 6,88,90,92,93,95,97,99,101,102,104,106,108,109,111,113,115,117,118,120,1 22,124,125,127,129,131,133,134,136,138,140,141,143,145,147,148,150,152,1 54,156,157,159,161,163,164,166,168,170,172,173,175,177,179,180,182,184,1 86,187,189,191,193,195,196,198,200,202,203,205,207,209,211,212,214,216,2 18,219,221,223,225};73.*len=3*nWidth*nHeight;74.if(!yuvBuf||!pRgbBuf)75.return false;76.const long nYLen=long(PIXELSIZE);77.const int nHfWidth=(nWidth>>1);78.if(nYLen<1||nHfWidth<1)79.return false;80.//Y data81.unsigned char*yData=yuvBuf;82.//v data83.unsigned char*vData=&yData[nYLen];84.//u data85.unsigned char*uData=&vData[nYLen>>2];86.if(!uData||!vData)87.return false;88.int rgb[3];89.int i,j,m,n,x,y,pu,pv,py,rdif,invgdif,bdif;90.m=-nWidth;91.n=-nHfWidth;92.bool addhalf=true;93.for(y=0;y<nHeight;y++){94.m+=nWidth;95.if(addhalf){96.n+=nHfWidth;97.addhalf=false;98.}else{99.addhalf=true;100.}101.for(x=0;x<nWidth;x++){102.i=m+x;103.j=n+(x>>1);104.py=yData[i];105.//search tables to get rdif invgdif and bidif106.rdif=Table_fv1[vData[j]];//fv1107.invgdif=Table_fu1[uData[j]]+Table_fv2[vData[j]];//fu1+fv2 108.bdif=Table_fu2[uData[j]];//fu2109.rgb[0]=py+rdif;//R110.rgb[1]=py-invgdif;//G111.rgb[2]=py+bdif;//B112.j=nYLen-nWidth-m+x;113.i=(j<<1)+j;114.//copy this pixel to rgb data115.for(j=0;j<3;j++)116.{117.if(rgb[j]>=0&&rgb[j]<=255){118.pRgbBuf[i+j]=rgb[j];119.}120.else{121.pRgbBuf[i+j]=(rgb[j]<0)?0:255;122.}123.}124.} 125.}126.return true; 127.}。
(转)RGB、YUY2、YUYV、YVYU、UYVY、AYUV格式详解
(转)RGB、YUY2、YUYV、YVYU、UYVY、AYUV格式详解YUY2经常⽤于电视制式以及许多摄像头的输出格式.⽽我们在处理时经常需要将其转化为RGB进⾏处理,这⾥简单介绍下YUY2(YUV)与RGB 之间相互转化的关系:YUY2(YUV) To RGB:C = Y - 16D = U - 128E = V - 128R = clip(( 298 * C + 409 * E + 128) >> 8) G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8) B = clip(( 298 * C + 516 * D + 128) >> 8)其中 clip()为限制函数,将其取值限制在0-255之间.RGB To YUY2(YUV):Y = ( ( 66 * R + 129 * G + 25 * B + 128) >> 8) + 16U = ( ( -38 * R - 74 * G + 112 * B + 128) >> 8) + 128V = ( ( 112 * R - 94 * G - 18 * B + 128) >> 8) + 128上述两个公式在代码中的int YUV2RGB(void* pYUV, void* pRGB, int width, int height, bool alphaYUV, bool alphaRGB);int RGB2YUV(void* pRGB, void* pYUVX, int width, int height, bool alphaYUV, bool alphaRGB);函数中转换。
在诸如摄像头的数据获取中,我们往往需要直接在YUY2(YUV)空间上进⾏⼀些图象处理,我们希望能够在YUY2 (YUV)进⾏⼀些RGB上可以做到的处理。
这⾥已blending为例,将两张带有透明度的YUY2(YUV)图⽚进⾏叠加,以达到在RGB空间进⾏图像合成的效果。
深入探索视频帧中的颜色空间——RGB和YUV
深⼊探索视频帧中的颜⾊空间——RGB和YUV接触前端⾳视频之后,需要掌握⼤量⾳视频和多媒体相关的基础知识。
在使⽤ FFmpeg + WASM 进⾏视频帧提取时,涉及到视频帧和颜⾊编码等相关概念。
本⽂将对视频帧中的颜⾊空间进⾏介绍。
视频帧对于视频,我们都知道是由⼀系列的画⾯在⼀个较短的时间内(通常是 1/24 或 1/30 秒)不停地下⼀个画⾯替换上⼀个画⾯形成连贯的画⾯变化。
这些画⾯称之为视频帧。
对于视频帧,在现代视频技术⾥⾯,通常都是⽤ RGB 颜⾊空间或者 YUV 颜⾊空间的像素矩阵来表⽰。
在 ffmpeg ⾥⾯,我们可以看到源码中定义了⼀系列像素格式,绝⼤部分都是 RGB 和 YUV 颜⾊空间类型的。
enum AVPixelFormat {// ... 省略部分不怎么重要的类型///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)AV_PIX_FMT_YUV420P,///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 CrAV_PIX_FMT_YUYV422,///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)AV_PIX_FMT_YUV422P,///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1AV_PIX_FMT_UYVY422,///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)AV_PIX_FMT_YUV444P,///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)AV_PIX_FMT_YUV440P,///< packed RGB 8:8:8, 24bpp, RGBRGB...AV_PIX_FMT_RGB24,///< packed RGB 8:8:8, 24bpp, BGRBGR...AV_PIX_FMT_BGR24,///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB...AV_PIX_FMT_ARGB,///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA...AV_PIX_FMT_RGBA,///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR...AV_PIX_FMT_ABGR,///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA...AV_PIX_FMT_BGRA,///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endianAV_PIX_FMT_RGB565BE,///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endianAV_PIX_FMT_RGB565LE,///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefinedAV_PIX_FMT_RGB555BE,///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefinedAV_PIX_FMT_RGB555LE,///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endianAV_PIX_FMT_BGR565BE,///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endianAV_PIX_FMT_BGR565LE,///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian , X=unused/undefinedAV_PIX_FMT_BGR555BE,///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefinedAV_PIX_FMT_BGR555LE,}复制代码每个类型的注释开头要么是packed要么是planar,YUV 类型后跟着三个数字 4:2:0、4:2:2、4:4:4 等等,这些都表⽰什么?带着这些疑问,开始搜索资料研究学习 RGB 和 YUV 颜⾊空间相关和像素格式的概念。
RGB-YCrCb
颜色空间是一个三维坐标系统,每一种颜色由一个点表示。
在RGB 颜色空间中,红,绿,蓝是基本元素。
RGB 格式是显示器通常使用的格式。
在YUV 空间中,每一个颜色有一个亮度信号Y,和两个色度信号U 和V。
亮度信号是强度的感觉,它和色度信号断开,这样的话强度就可以在不影响颜色的情况下改变。
YUV 格式通常用于PAL制,即欧洲的电视传输标准,而且缺省情况下是图像和视频压缩的标准。
YUV 使用RGB的信息,但它从全彩色图像中产生一个黑白图像,然后提取出三个主要的颜色变成两个额外的信号来描述颜色。
把这三个信号组合回来就可以产生一个全彩色图像。
YUV 使用红,绿,蓝的点阵组合来减少信号中的信息量。
Y 通道描述Luma 信号,它与亮度信号有一点点不同,值的范围介于亮和暗之间。
Luma 是黑白电视可以看到的信号。
U (Cb) 和V (Cr) 通道从红(U) 和蓝(V) 中提取亮度值来减少颜色信息量。
这些值可以从新组合来决定红,绿和蓝的混合信号。
YUV和RGB的转换: ★这里是不是不是yuv而是Y Cb Cr???★Y = 0.299 R + 0.587 G + 0.114 BU = -0.1687 R - 0.3313 G + 0.5 B + 128V = 0.5 R - 0.4187 G - 0.0813 B + 128R = Y + 1.402 (V-128)G = Y - 0.34414 (U-128) - 0.71414 (V-128)B = Y + 1.772 (U-128)以前,一直没明白yuv和YcbCr之间的差异,想必有些朋友也会有同样的疑惑。
所以,我看完之后就记载下来了。
一、和rgb之间换算公式的差异yuv<-->rgbY'= 0.299*R' + 0.587*G' + 0.114*B'U'= -0.147*R' - 0.289*G' + 0.436*B' = 0.492*(B'- Y')V'= 0.615*R' - 0.515*G' - 0.100*B' = 0.877*(R'- Y')R' = Y' + 1.140*V'G' = Y' - 0.394*U' - 0.581*V'B' = Y' + 2.032*U'yCbCr<-->rgbY’ = 0.257*R' + 0.504*G' + 0.098*B' + 16Cb' = -0.148*R' - 0.291*G' + 0.439*B' + 128Cr' = 0.439*R' - 0.368*G' - 0.071*B' + 128R' = 1.164*(Y’-16) + 1.596*(Cr'-128)G' = 1.164*(Y’-16) - 0.813*(Cr'-128) - 0.392*(Cb'-128)B' = 1.164*(Y’-16) + 2.017*(Cb'-128)Note: 上面各个符号都带了一撇,表示该符号在原值基础上进行了gamma correction二、来源上的差异yuv色彩模型来源于rgb模型,该模型的特点是将亮度和色度分离开,从而适合于图像处理领域。
RGB 转换至 YCbCr (YUV) 的计算公式
RGB 转换至 YCbCr (YUV) 的计算公式文章分类:行业应用对于每个取样点的 R,G,B 值, 在转换到 YUV colour space 时, 首先定义画面的平均亮度值(Luminance), Y, 其计算公式为:Y = kr*R + kg*G + kb*Bkr, kg, kb 为 weighting factors (加权因数), kr + kg + kb = 1 恒定. (其中, ITU-R BT.601 定义 kb = 0.114 和 kr = 0.299)然后定义 Cr, Cg, Cb 为颜色强度 (colour intensity) 与这个 luminance 的差值:Cb = B − YCr = R − YCg = G − Y这时对于一个取样点, 完整的信息被保存于 Y, Cb, Cr, Cg 四个变量里, 此时相对于 RGB colour space 的三个变量值, 这样的计算公式还没有优势.但由于 Cb + Cr + Cg 是个常数, 我们可以用其中两个变量来表达原来所需的三个, 并且在数据的贮存和传输中也只需使用其中的两个变量. 这样, 就完成了定义 YCbCr colour space 中的三个变量了: Y, Cb, Cr.一个在 RGB colour space 中取样值的三个变量 R, G, B 在转换为 YCbCr 的公式于是重新定义/转化为:Y = kr*R + (1 − kb − kr )*G + kb*B (1)Cb = 0.5(1 − kb) / (B − Y )Cr = 0.5(1 − kr) / (R − Y )然后再用公式 (1) 代换 Y, 得到仅含 R,G,B 的 Cb, Cr 函数 (kr,kb 视为常数)作简单的代数也可以求出从 YCbCr 转换至 RGB 的公式:R = Y + (1 - kr)*Cr/0.5G = Y - [kb*(1 - kb)*Cb]/ [0.5*(1 - kb - kr)] - [kr*(1 - kr)*Cr]/ [0.5*(1 - kb - kr)]B = Y + (1 - kb)*Cb/0.5代入 ITU-R BT.601 定义的 kb = 0.114 和 kr = 0.299那么 RGB ---> YCbCr 的公式为:Y = 0.299R + 0.587G + 0.114B (2)Cb = 0.564(B − Y )Cr = 0.713(R − Y )同样地, 然后再用公式 (2) 代换 Y, 得到仅含 R,G,B 的 Cb, Cr 函数 (kr,kb 视为常数)YCbCr ---> RGB 的公式为:R = Y + 1.402CrG = Y − 0.344Cb − 0.714CrB = Y + 1.772Cb。
RGB YUV的来历及其相互转换
RGB,YUV的来历及其相互转换在视频等相关的应用中,YUV是一个经常出现的格式。
本文主要以图解的资料的形式详细描述YUV和RGB格式的来由,相互关系以及转换方式,并对C 语言实现的YUV转为RGB程序进行介绍。
人类眼睛的色觉,具有特殊的特性,早在上世纪初,Young(1809)和Helmholtz(1824)就提出了视觉的三原色学说,即:视网膜存在三种视锥细胞,分别含有对红、绿、蓝三种光线敏感的视色素,当一定波长的光线作用于视网膜时,以一定的比例使三种视锥细胞分别产生不同程度的兴奋,这样的信息传至中枢,就产生某一种颜色的感觉。
70年代以来,由于实验技术的进步,关于视网膜中有三种对不同波长光线特别敏感的视锥细胞的假说,已经被许多出色的实验所证实。
例如:①有人用不超过单个视锥直径的细小单色光束,逐个检查并绘制在体(最初实验是在金鱼和蝾螈等动物进行,以后是人)视锥细胞的光谱吸收曲线,发现所有绘制出来的曲线不外三种类型,分别代表了三类光谱吸收特性不同的视锥细胞,一类的吸收峰值在420nm处,一类在534nm处,一类在564nm处,差不多正好相当于蓝、绿、红三色光的波长。
与上述视觉三原色学说的假设相符。
②用微电极记录单个视锥细胞感受器电位的方法,也得到了类似的结果,即不同单色光所引起的不同视锥细胞的超极化型感受器电位的大小也不同,峰值出现的情况符合于三原色学说。
于是,在彩色显示器还没有发明的时候,人类已经懂得使用三原色光调配出所有颜色的光。
并不是说三原色混合后产生了新的频率的光,而是给人眼睛的感觉是这样。
在显示器发明之后,从黑白显示器发展到彩色显示器,人们开始使用发出不同颜色的光的荧光粉(CRT,等离子体显示器),或者不同颜色的滤色片(LCD),或者不同颜色的半导体发光器件(OLED和LED大型全彩显示牌)来形成色彩,无一例外的选择了Red,Green,Blue这3种颜色的发光体作为基本的发光单元。
通过控制他们发光强度,组合出了人眼睛能够感受到的大多数的自然色彩。
RGB与YUV,HSB,HSL,HSV等的转换算法
RGB与YUV,HSB,HSL,HSV等的转换算法void rgb2ycbcr(int r, int g, int b, int[] ycbcr) {int y = (int)( 0.299 * r + 0.587 * g + 0.114 * b);int cb = (int)(-0.16874 * r - 0.33126 * g + 0.50000 * b);int cr = (int)( 0.50000 * r - 0.41869 * g - 0.08131 * b);ycbcr[0] = y;ycbcr[1] = cb;ycbcr[2] = cr;}RGB to YUV void rgb2yuv(int r,int g, int b, int[] yuv,) {int y = (int)(0.299 * r + 0.587 * g + 0.114 * b);int u = (int)((b - y) * 0.492f);int v = (int)((r - y) * 0.877f);yuv[0]= y;yuv[1]= u;yuv[2]= v;} RGB to HSB void rgb2hsb(int r, int g, int b, int[] hsb) {float [] hsbvals = new float[3];Color.RGBtoHSB(r, g, b, hsbvals);} RGB to HMMD void rgb2hmmd(int r, int g, int b, int[] hmmd) {float max = (int)Math.max(Math.max(r,g), Math.max(g,b));float min = (int)Math.min(Math.min(r,g), Math.min(g,b));float diff = (max - min);float sum = (float) ((max + min)/2.);float hue = 0;if (diff == 0)hue = 0;else if (r == max && (g - b) > 0)hue = 60*(g-b)/(max-min);else if (r == max && (g - b) <= 0)hue = 60*(g-b)/(max-min) + 360;else if (g == max)hue = (float) (60*(2.+(b-r)/(max-min)));else if (b == max)hue = (float) (60*(4.+(r-g)/(max-min)));hmmd[0] = (int)(hue);hmmd[1] = (int)(max);hmmd[2] = (int)(min);hmmd[3] = (int)(diff);} RGB to HSL private void rgb2hsl(int r, int g, int b, int hsl[]) {float var_R = ( r / 255f );float var_G = ( g / 255f );float var_B = ( b / 255f );float var_Min; //Min. value of RGBfloat var_Max; //Max. value of RGBfloat del_Max; //Delta RGB valueif (var_R > var_G){ var_Min = var_G; var_Max = var_R; }else{ var_Min = var_R; var_Max = var_G; }if (var_B > var_Max) var_Max = var_B;if (var_B < var_Min) var_Min = var_B;del_Max = var_Max - var_Min;float H = 0, S, L;L = ( var_Max + var_Min ) / 2f;if ( del_Max == 0 ) { H = 0; S = 0; } // grayelse { //Chromaif ( L < 0.5 )S = del_Max / ( var_Max + var_Min );elseS = del_Max / ( 2 - var_Max - var_Min );float del_R = ( ( ( var_Max - var_R ) / 6f ) + ( del_Max / 2f ) ) / del_Max; float del_G = ( ( ( var_Max - var_G ) / 6f ) + ( del_Max / 2f ) ) / del_Max; float del_B = ( ( ( var_Max - var_B ) / 6f ) + ( del_Max / 2f ) ) / del_Max;if ( var_R == var_Max )H = del_B - del_G;else if ( var_G == var_Max )H = ( 1 / 3f ) + del_R - del_B;else if ( var_B == var_Max )H = ( 2 / 3f ) + del_G - del_R;if ( H < 0 ) H += 1;if ( H > 1 ) H -= 1;}hsl[0] = (int)(360*H);hsl[1] = (int)(S*100);hsl[2] = (int)(L*100);} RGB to HSV private void rgb2hsv(int r, int g, int b, int hsv[]) {int min; //Min. value of RGBint max; //Max. value of RGBint delMax; //Delta RGB valueif (r > g) { min = g; max = r; }else { min = r; max = g; }if (b > max) max = b;if (b < min) min = b;delMax = max - min;float H = 0, S;float V = max;if ( delMax == 0 ) { H = 0; S = 0; }else {S = delMax/255f;if ( r == max )H = ( (g - b)/(float)delMax)*60;else if ( g == max )H = ( 2 + (b - r)/(float)delMax)*60;else if ( b == max )H = ( 4 + (r - g)/(float)delMax)*60;}hsv[0] = (int)(H);hsv[1] = (int)(S*100);hsv[2] = (int)(V*100);} RGB to xyY public void rgb2xyY(int R, int G, int B, int []xyy) { //float rf, gf, bf;float r, g, b, X, Y, Z;// RGB to XYZr = R/255.f; //R 0..1g = G/255.f; //G 0..1b = B/255.f; //B 0..1if (r <= 0.04045)r = r/12;elser = (float) Math.pow((r+0.055)/1.055,2.4);if (g <= 0.04045)g = g/12;elseg = (float) Math.pow((g+0.055)/1.055,2.4);if (b <= 0.04045)b = b/12;elseb = (float) Math.pow((b+0.055)/1.055,2.4);X = 0.436052025f*r + 0.385081593f*g + 0.143087414f *b; Y = 0.222491598f*r + 0.71688606f *g + 0.060621486f *b; Z = 0.013929122f*r + 0.097097002f*g + 0.71418547f *b;float x;float y;float sum = X + Y + Z;if (sum != 0) {x = X / sum;y = Y / sum;}else {float Xr = 0.964221f; // reference whitefloat Yr = 1.0f;float Zr = 0.825211f;x = Xr / (Xr + Yr + Zr);y = Yr / (Xr + Yr + Zr);}xyy[0] = (int) (255*x + .5);xyy[1] = (int) (255*y + .5);xyy[2] = (int) (255*Y + .5);} RGB to XYZ public void rgb2xyz(int R, int G, int B, int []xyz) { float rf, gf, bf;float r, g, b, X, Y, Z;r = R/255.f; //R 0..1g = G/255.f; //G 0..1b = B/255.f; //B 0..1if (r <= 0.04045)r = r/12;elser = (float) Math.pow((r+0.055)/1.055,2.4);if (g <= 0.04045)g = g/12;elseg = (float) Math.pow((g+0.055)/1.055,2.4);if (b <= 0.04045)b = b/12;elseb = (float) Math.pow((b+0.055)/1.055,2.4);X = 0.436052025f*r + 0.385081593f*g + 0.143087414f *b;Y = 0.222491598f*r + 0.71688606f *g + 0.060621486f *b;Z = 0.013929122f*r + 0.097097002f*g + 0.71418547f *b;xyz[1] = (int) (255*Y + .5);xyz[0] = (int) (255*X + .5);xyz[2] = (int) (255*Z + .5);} RGB to LAB public void rgb2lab(int R, int G, int B, int []lab) { //float r, g, b, X, Y, Z, fx, fy, fz, xr, yr, zr;float Ls, as, bs;float eps = 216.f/24389.f;float k = 24389.f/27.f;float Xr = 0.964221f; // reference white D50float Yr = 1.0f;float Zr = 0.825211f;// RGB to XYZr = R/255.f; //R 0..1g = G/255.f; //G 0..1b = B/255.f; //B 0..1// assuming sRGB (D65)if (r <= 0.04045)r = r/12;elser = (float) Math.pow((r+0.055)/1.055,2.4);if (g <= 0.04045)g = g/12;elseg = (float) Math.pow((g+0.055)/1.055,2.4);if (b <= 0.04045)b = b/12;elseb = (float) Math.pow((b+0.055)/1.055,2.4);X = 0.436052025f*r + 0.385081593f*g + 0.143087414f *b; Y = 0.222491598f*r + 0.71688606f *g + 0.060621486f *b; Z = 0.013929122f*r + 0.097097002f*g + 0.71418547f *b;// XYZ to Labxr = X/Xr;yr = Y/Yr;zr = Z/Zr;if ( xr > eps )fx = (float) Math.pow(xr, 1/3.);elsefx = (float) ((k * xr + 16.) / 116.);if ( yr > eps )fy = (float) Math.pow(yr, 1/3.);elsefy = (float) ((k * yr + 16.) / 116.);if ( zr > eps )fz = (float) Math.pow(zr, 1/3.);elsefz = (float) ((k * zr + 16.) / 116);Ls = ( 116 * fy ) - 16;as = 500*(fx-fy);bs = 200*(fy-fz);lab[0] = (int) (2.55*Ls + .5);lab[1] = (int) (as + .5);lab[2] = (int) (bs + .5);} RGB to LUV public void rgb2luv(int R, int G, int B, int []luv) { //float rf, gf, bf;float r, g, b, X_, Y_, Z_, X, Y, Z, fx, fy, fz, xr, yr, zr;float L;float eps = 216.f/24389.f;float k = 24389.f/27.f;float Xr = 0.964221f; // reference white D50float Yr = 1.0f;float Zr = 0.825211f;// RGB to XYZr = R/255.f; //R 0..1g = G/255.f; //G 0..1b = B/255.f; //B 0..1// assuming sRGB (D65)if (r <= 0.04045)r = r/12;elser = (float) Math.pow((r+0.055)/1.055,2.4);if (g <= 0.04045)g = g/12;elseg = (float) Math.pow((g+0.055)/1.055,2.4);if (b <= 0.04045)b = b/12;elseb = (float) Math.pow((b+0.055)/1.055,2.4);X = 0.436052025f*r + 0.385081593f*g + 0.143087414f *b;Y = 0.222491598f*r + 0.71688606f *g + 0.060621486f *b; Z = 0.013929122f*r + 0.097097002f*g + 0.71418547f *b;// XYZ to Luvfloat u, v, u_, v_, ur_, vr_;u_ = 4*X / (X + 15*Y + 3*Z);v_ = 9*Y / (X + 15*Y + 3*Z);ur_ = 4*Xr / (Xr + 15*Yr + 3*Zr);vr_ = 9*Yr / (Xr + 15*Yr + 3*Zr);yr = Y/Yr;if ( yr > eps )L = (float) (116*Math.pow(yr, 1/3.) - 16);elseL = k * yr;u = 13*L*(u_ -ur_);v = 13*L*(v_ -vr_);luv[0] = (int) (2.55*L + .5);luv[1] = (int) (u + .5);luv[2] = (int) (v + .5);}。
yuv转RGB
我们从CMOS摄像头采集到的数据一般是YUV2格式的,YUV2是YUYV,YVYU,VYUY,UYVY,四种格式的统称,在源代码中,采用YUYV格式的数据转换为RGB24格式的数据,当然,通过修改某些参数,YUV2所有格式的数据都可以转换成RGB24即RGB888格式的数据。
首先,我们采集到的数据是以Y0,V0,Y1,U0, Y2,V2,Y3,U2 …的格式存放在内存中,这里,我是通过串口将该块内存中的数据打印到文件中,并将数据稍作编辑,即可作为带转换的YUV2数据。
YUV与RGB的转换关系可以看到,Y0,V0…都是8位数据,占1个字节,但每个16进制数以字符存放在内存中,那么Y,U,V就是占2个字节,Y0,V0,Y1,U0,共32位,包含两个像素,转换为RGB24时,关系如下:RGB0=(Y0,V0,U0),RGB1=(Y1,V0,U0),依次类推,可以看到每个YUV2占32位,转换为2个RGB时,占48位,所有,字符长度增加了0.5倍。
从文件中读取数据,并分配内存大小,YUV的数据大小为WIDTH*HEIGHT*2,而RGB数据大小为WIDTH*HEIGHT*3;具体转换算法:图片中,是网上常用的两种转换算法,(注释部分是一种,在*号之间的部分是目前在使用的一种)存在问题:核心部分就是从文件中读取数据,分配内存,并将数据进行转换,然后放回文件中。
但我们从文件中读取到的数据均为字符型,而在转换关系中,用到的数据均为数值型,所以需要对数据进行转换处理,算法如下:以上部分是将字符型数据转换成数值型,另一方面,存入文件中,还应当将数值型数据转换成字符型,即上图转换算法的逆算法如下:到此,整个转换算法分析完毕。
BYTE *YUV422_to_RGB24(VIDEO_FRAME_S * pVBuf,LONG *pwidth, LONG *pheight,FILE *pfd,BYTE *rgb24){LONG width=*pwidth;LONG height=*pheight;HI_S32 s32Ret = HI_SUCCESS;BYTE *pVBufVirt_Y;BYTE *pVBufVirt_C;BYTE *pMemContent;HI_U32 phy_addr[2],size;HI_CHAR *pUserPageAddr[2];PIXEL_FORMAT_E enPixelFormat = pVBuf->enPixelFormat;HI_U32 u32UvHeight;if (PIXEL_FORMAT_YUV_SEMIPLANAR_420 == enPixelFormat){size = (pVBuf->u32Stride[0])*(pVBuf->u32Height)*3/2;u32UvHeight = pVBuf->u32Height/2;}else{size = (pVBuf->u32Stride[0])*(pVBuf->u32Height);u32UvHeight = pVBuf->u32Height;}phy_addr[0] = pVBuf->u32PhyAddr[0];phy_addr[1] = pVBuf->u32PhyAddr[1];//printf("phy_addr:%x, size:%d\n", phy_addr, size);pUserPageAddr[0] = (BYTE *) HI_MPI_SYS_Mmap(phy_addr[0], size);if (NULL == pUserPageAddr[0])return HI_FAILURE;}pUserPageAddr[1] = (BYTE *) HI_MPI_SYS_Mmap(phy_addr[1], size);if (NULL == pUserPageAddr[0]){return HI_FAILURE;}// printf("stride: %d,%d\n",pVBuf->u32Stride[0],pVBuf->u32Stride[1] );pVBufVirt_Y = pUserPageAddr[0];pVBufVirt_C = pUserPageAddr[1];BYTE *yuv422[3];yuv422[0]=pVBufVirt_Y;yuv422[1]=pVBufVirt_C;yuv422[2]=pVBufVirt_C;/*****************************************************************************/ BITMAPFILEHEADER bmfh;BITMAPINFOHEADER bmih;DWORD Linebytes=width*3;DWORD SizeImage = Linebytes*height;bmfh.bfType=0x4D42;bmfh.bfSize=SizeImage+54;bmfh.bfReserved1 = 0;bmfh.bfReserved2 = 0;bmfh.bfOffBits =54;bmih.biSize =40;bmih.biWidth = width;bmih.biHeight = height;bmih.biPlanes = 1;bmih.biBitCount = 24;bmih.biCompression = 0;bmih.biSizeImage =width*height*3;bmih.biXPelsPerMeter = 0;bmih.biYPelsPerMeter = 0;bmih.biClrUsed = 0;bmih.biClrImportant = 0;saveBmpFileHeader(pfd,&bmfh);saveBmpInfoHeader(pfd,&bmih);rgb24=(BYTE *)malloc(Linebytes*height);int R,G,B;BYTE Y,U,V;int x,x1,y;x1=0;for (y=0;y<height;y++)for (x=0;x<width;x++){x1=x;Y = *(yuv422[0] + y*width + x);if(x==0){U = *(yuv422[1] + y*width + 0);V = *(yuv422[2] + y*width + 1);}else if((x>0)&&(x%2==0)){U = *(yuv422[1] + y*width + x);V = *(yuv422[2] + y*width + x+1);}else{U = *(yuv422[1] + y*width + x-1);V = *(yuv422[2] + y*width + x);}R = Y + 1.402*(V-128);//method 1:G = Y - 0.34414*(U-128) - 0.71414*(V-128);B = Y + 1.772*(U-128);// R=1.164*(Y-16)+1.596*(V-128);//method 2:// G=1.164*(Y-16)+0.813*(V-128)-0.391*(U-128); // B=1.164*(Y-16)+2.018*(U-128);//阒叉 瓒婄晫if(R>255)R=255;if(R<0)R=0;if(G>255)G=255;if(G<0)G=0;if(B>255)B=255;if(B<0)B=0;rgb24[((height-y-1)*width + x)*3] = (BYTE)R;rgb24[((height-y-1)*width + x)*3 + 1] = (BYTE)G;rgb24[((height-y-1)*width + x)*3 + 2] = (BYTE)B;}}fwrite(rgb24,Linebytes*height,1,pfd);fclose(pfd);printf("YUV2BMP %d success ok\n",gs_s32SnapCntbmp);HI_MPI_SYS_Munmap(pUserPageAddr[0],size);HI_MPI_SYS_Munmap(pUserPageAddr[1],size);return rgb24;}。
RGB与YUV图像视频格式的相互转换
RGB与YUV图像视频格式的相互转换我们知道普通彩色CRT显示器内部有三支电子枪,电子枪去激活显示器屏幕的荧光粉,三种荧光粉发射出的光生成一个像素位置的颜色点,这就是我们人眼能看到的一个像素。
每个像素对应红、绿、蓝(R、G、B)三个强度等级,每个像素占用24位,可以显示近1700 万种颜色,这就是我们所说的真彩色。
普通彩色CRT显示器是基于电视技术的光栅扫描,电子束一次扫描一行,从顶到底依次扫描,整个屏幕扫描一次(我们称它为1帧),电子束扫描完一帧后回到最初位置进行下一次扫描。
电视图像显示概述:电视显示原理与CRT相似,不过采用的是隔行扫描,我国的广播电视采用的是625行隔行扫描方式。
隔行扫描是将一帧图像分两次(场)扫描。
第一场先扫出1、3、5、7…等奇数行光栅,第二场扫出2、4、6、8…等偶数行光栅。
通常将扫奇数行的场叫奇数场(也称上场),扫偶数行的场叫偶数场(也称下场)。
为什么电视会选择隔行扫描,这是因为会使显示运动图像更平滑。
下面两图为一帧图像的上场和下场的扫描过程。
(图1 上场扫描)(图2 下场扫描)常见的电视的制式有三种:NTSC、PAL、SECAM,我国的广播电视采用PAL制式,我国电视制式的帧频只有50HZ和我们日常使用的电流频率一样,PAL帧频为25fps,在文章后面我会以一张720x576的图像转换为720x 576 PAL隔行扫描的电视场视频格式作详细描述。
RGB介绍:在记录计算机图像时,最常见的是采用RGB(红、绿,蓝)颜色分量来保存颜色信息,例如非压缩的24位的BMP图像就采用RGB空间来保存图像。
一个像素24位,每8位保存一种颜色强度(0-255),例如红色保存为 0xFF0000。
YUV介绍:YUV是被欧洲电视系统所采用的一种颜色编码方法,我国广播电视也普遍采用这类方法。
其中“Y”表示明亮度(Luminance或Luma),也就是灰阶值;而“U”和“V”表示的则是色度(Chrominance或Chroma)。
709yuv转换公式
709yuv转换公式
YUV颜色空间是一种将亮度(Y)和色度(U、V)分离的编码方式,常用于视频压缩和显示。
Y表示亮度,而U和V表示色度。
YUV
转换的公式可以通过以下方式来计算:
假设R、G、B分别是RGB颜色空间中的红色、绿色和蓝色分量,而Y、U、V是对应的YUV分量,转换公式如下:
Y = 0.299 R + 0.587 G + 0.114 B.
U = -0.147 R 0.289 G + 0.436 B.
V = 0.615 R 0.515 G 0.100 B.
这些转换公式是根据国际电报电话咨询委员会(CCIR)制定的
标准推导出来的,它们可以将RGB颜色空间中的颜色值转换为对应
的YUV分量。
这种转换可以帮助我们对图像进行压缩和编解码,从
而节省存储空间和传输带宽。
需要注意的是,这些转换公式是理论推导的结果,实际应用中
可能会根据具体的需求和标准进行微调和优化。
另外,在实际的图
像处理中,还会涉及到颜色空间的转换、采样率、量化等其他因素,这些都需要综合考虑和处理。
总之,YUV转换公式是通过对RGB颜色空间中的颜色分量进行
加权求和得到对应的YUV分量,这种转换在视频编解码和处理中具
有重要的作用。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
YUV 与RGB之间的变换
颜色空间是一个三维坐标系统,每一种颜色由一个点表示。
在 RGB 颜色空间中,红,绿,蓝是基本元素。
RGB 格式是显示器通常使用的格式。
在 YUV 空间中,每一个颜色有一个亮度信号 Y,和两个色度信号 U 和 V。
亮度信号是强度的感觉,它和色度信号断开,这样的话强度就可以在不影响颜色的情况下改变。
YUV 格式通常用于 PAL制,即欧洲的电视传输标准,而且缺省情况下是图像和视频压缩的标准。
大多数的计算机图形工作者熟悉 RGB,而大多数的具有图像背景的则熟悉 YUV。
RGB可以认为是三个分别表示红,绿,蓝颜色的灰度图像。
把它们组合在一起就可以产生各种各样的颜色。
YUV 使用RGB的信息,但它从全彩色图像中产生一个黑白图像,然后提取出三个主要的颜色变成两个额外的信号来描述颜色。
把这三个信号组合回来就可以产生一个全彩色图像。
那么 YUV 是怎么产生的呢?当时,工程师们需要找到一种办法来使彩色电视广播可以兼容黑白电视。
他们使用的彩色信号也需要保全带宽因为 RGB 数据不能适合信号空间的限制。
通过合并颜色信息,YUV 使用比 RGB 更小的带宽,并且与黑白电视兼容。
YUV 使用红,绿,蓝的点阵组合来减少信号中的信息量。
Y 通道描述 Luma 信号,它与亮度信号有一点点不同,值的范围介于亮和暗之间。
Luma 是黑白电视可以看到的信号。
U (Cb) 和 V (Cr) 通道从红 (U) 和蓝 (V) 中提取亮度值来减少颜色信息量。
这些值可以从新组合来决定红,绿和蓝的混合信号。
一些对 YUV 的较深的研究揭示了当从视频图像中提取时,为什么蓝色总是看起来不很舒服的两个原因。
U 通道的范围是从红到黄,V 通道的范围是从蓝到黄。
因为黄色其实是红和绿,红色基本上被传输三次, 绿色是两次而蓝色只有一次。
重建亮度部份揭示了另外一个原因,蓝色通道只有11%的亮度。
下图显示了在亮度混合信号中每一个通道的比重。
Luma = 30% 红 + 59% 绿 + 11% 蓝
下面简介一下YUV和RGB的转换。
VGA卡通过设置红,蓝,绿三色的强度来显示颜色。
这三种颜色形成笛卡尔坐标系统的轴线。
如下图1。
任何一种颜色都是这个颜色空间的一点。
你不需要使用这个坐标来定义颜色空间的一点。
一个灰度图像只使用颜色空间中那些有着相同红,蓝,绿强度的点。
我们可以作一个坐标,其中红,蓝,绿是相等的。
如图2。
这个坐标叫做亮度坐标。
我们还可以通过从亮度中提取红和蓝部份作两个新的坐标。
新的坐标是红和蓝的色度值,用于添加颜色到图像中。
亮度坐标标识为 Y,蓝的色度坐标标识为 U,红的色度坐标标识为 V。
如图3。
我们建立的这三个新坐标形成了JPEG图像中使用的三个部份。
以下的公式用于在这两个坐标系统之间互相转换。
Y = 0.299 R + 0.587 G + 0.114 B
U = -0.1687 R - 0.3313 G + 0.5 B + 128
V = 0.5 R - 0.4187 G - 0.0813 B + 128
R = Y + 1.402 (V-128) G
= Y - 0.34414 (U-128) - 0.71414 (V-128) B
= Y + 1.772 (U-128)
需要注意的是我们只使用RGB颜色空间中三个坐标都为正的象限。
当我们从YUV 转换到RGB时,我们必须确保坐标不是负数而且它们没有超过允许的最大值。
那么为什么我们要使用YUV颜色空间呢?那时因为人的眼睛对亮度的敏感高于对色度的敏感。
通常 JPEG 在进行其它任何压缩前会丢掉 3/
的色度信息。
这可以减
4。
如果三个部份全部存储的话,4 pixels就需要3 x 4 少图像所要存储信息的1/
2
= 12个值。
如果两个部份的 3/
的信息可以丢掉不要的话,我们就只需要 1 x 4
4
+ 2 x 1 = 6 个值。