YUV到RGB颜色空间转换
来源:互联网 发布:客车票订票软件 编辑:程序博客网 时间:2024/05/16 16:21
三种颜色空间简介:
YUV:是欧洲电视系统采用的一种颜色编码格式,Y表示亮度值(Luminance或Luma),U和V表示色彩及饱和度(Chrominance或Chroma)。
YUV主要格式有:YUV444、YUV 422、YUV 411和YUV 420。YUV对原始数据以每4个像素为单元进行压缩处理,处理的方式就是对U和V分量进行降采样,如YUV444就是每4个像素YUV都会被采样4次数据无压缩,YUV422就是每4个像素YUV采样次数分别为422,数据减小了1/3,同理YUV411数据就减小了一半。但是根据奈奎斯特采样定理可以知道,采样后的数据信息损失量很小,不会造成图像的视觉效果变差。
假设有四个YUV空间的像素点{Y0,U0,V0},{Y1,U1,V1},{Y2,U2,V2},{Y3,U3,V3}
(1)YUV444
存储格式为:{Y0,U0,V0},{Y1,U1,V1},{Y2,U2,V2},{Y3,U3,V3}
像素表示为:{Y0,U0,V0},{Y1,U1,V1},{Y2,U2,V2},{Y3,U3,V3}
没有压缩。
(2) YUV422
存储格式为:{Y0,U0},{Y1,V1},{Y2,U2},{Y3,V3}
像素表示为:{Y0,U0,V1}, {Y1,U0,V1},{Y2,U2,V3}, {Y3,U2,V3}
可以看出四个像素点Y分量全部采样,U保留了偶数,V保留了奇数,四个像素点每两个像素点共用同一个U和V分量,数据压缩了1/3。
(3)YUV411
存储格式为:{Y0,U0,Y1},{Y2,V2,Y3}
像素表示为:{Y0,U0,V2}, {Y1,U0,V2},{Y2,U0,V2}, {Y3,U0,V2}
可以看出四个像素点Y分量全部采样,U和V只采样了U0和V2两个值,然后四个像素点的UV分离都是U0和V2,数据压缩了1/2。
(3)YUV420
这个有点特殊,上面的几种每4个像素点中的YUV三个分量都有采样,而YUV420则是第一次四个像素点中只采样Y和U分量,第二次四个像素点总只采用Y和V分量,然后依次交替进行。
存储格式为:{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,V5}, {Y1,U0,V5},{Y2,U2,V7}, {Y3,U2,V7},{Y5,U0,V5}, {Y6,U0,V5},{Y7,U2,V7}, {Y8,U2,V7}
数据压缩了1/2。
YcbCr:是经过伽马修正(gamma correction)编码处理后的YUV版本,Y'为颜色的亮度(luma)成分、而cb和Cr则为蓝色和红色的浓度偏移量成份。
RGB:是现在运用最广的颜色系统之一,通过红绿蓝三个分量的变化叠加来得到其他颜色。
BGR:把RGB的红色分量和蓝色交换即BGR。
颜色空间转换格式:
YUV<==>RGB
Y = (B * 1868 + G * 9617 + R * 4899 +8192)/16384;
U = ((B - Y)* 9241 + 8192)/16384 + 128;
V = ((R - Y)*11682 + 8192)/16384 + 128;
R = Y + 1.14V
G = Y - 0.39U - 0.58V
B = Y + 2.03U
YcbCr<==>RGB
Y’ = 0.257*R' + 0.504*G' + 0.098*B' + 16
Cb' = -0.148*R' - 0.291*G' + 0.439*B' + 128
Cr' = 0.439*R' - 0.368*G' - 0.071*B' + 128
R' = 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)
颜色空间转换代码:
在opencv中可以用cvtColor();函数来进行颜色空间的转换,同样我们也可以自己写函数来实现。
(1)自定义颜色空间转换函数
下面这个函数是根据上面的公式实现的YcbCr2BGR的函数,经过本人调试成功,不过出来最后的图像上下颠倒了,可以自己改一下,也可以根据YUV2RGB公式稍微改一下便可以进行YUV到RGB的转换。其中YcbCr为422格式,RGB为888格式。
int YcbCr2RGB(void* pYUV, void* pRGB, int width, int height, bool alphaYUV, bool alphaRGB){ if (NULL == pYUV) { return -1; } unsigned char* pYUVData = (unsigned char *)pYUV; unsigned char* pRGBData = (unsigned char *)pRGB; int Y1, U1, V1, Y2, alpha1, alpha2, R1, G1, B1, R2, G2, B2; int C1, D1, E1, C2; if (alphaRGB) { if (alphaYUV) { for (int i=0; i<height; ++i) { for (int j=0; j<width/2; ++j) { Y1 = *(pYUVData+i*width*3+j*6); //i*width*3 = i*(width/2)*6 U1 = *(pYUVData+i*width*3+j*6+1); Y2 = *(pYUVData+i*width*3+j*6+2); V1 = *(pYUVData+i*width*3+j*6+3); alpha1 = *(pYUVData+i*width*3+j*6+4); alpha2 = *(pYUVData+i*width*3+j*6+5); C1 = Y1-16; C2 = Y2-16; D1 = U1-128; E1 = V1-128; R1 = ((298*C1 + 409*E1 + 128)>>8>255 ? 255 : (298*C1 + 409*E1 + 128)>>8); G1 = ((298*C1 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C1 - 100*D1 - 208*E1 + 128)>>8); B1 = ((298*C1+516*D1 +128)>>8>255 ? 255 : (298*C1+516*D1 +128)>>8); R2 = ((298*C2 + 409*E1 + 128)>>8>255 ? 255 : (298*C2 + 409*E1 + 128)>>8); G2 = ((298*C2 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C2 - 100*D1 - 208*E1 + 128)>>8); B2 = ((298*C2 + 516*D1 +128)>>8>255 ? 255 : (298*C2 + 516*D1 +128)>>8); *(pRGBData+(height-i-1)*width*4+j*8+2) = R1<0 ? 0 : R1; *(pRGBData+(height-i-1)*width*4+j*8+1) = G1<0 ? 0 : G1; *(pRGBData+(height-i-1)*width*4+j*8) = B1<0 ? 0 : B1; *(pRGBData+(height-i-1)*width*4+j*8+3) = alpha1; *(pRGBData+(height-i-1)*width*4+j*8+6) = R2<0 ? 0 : R2; *(pRGBData+(height-i-1)*width*4+j*8+5) = G2<0 ? 0 : G2; *(pRGBData+(height-i-1)*width*4+j*8+4) = B2<0 ? 0 : B2; *(pRGBData+(height-i-1)*width*4+j*8+7) = alpha2; } } } else { int alpha = 255; for (int i=0; i<height; ++i) { for (int j=0; j<width/2; ++j) { Y1 = *(pYUVData+i*width*2+j*4); U1 = *(pYUVData+i*width*2+j*4+1); Y2 = *(pYUVData+i*width*2+j*4+2); V1 = *(pYUVData+i*width*2+j*4+3); C1 = Y1-16; C2 = Y2-16; D1 = U1-128; E1 = V1-128; R1 = ((298*C1 + 409*E1 + 128)>>8>255 ? 255 : (298*C1 + 409*E1 + 128)>>8); G1 = ((298*C1 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C1 - 100*D1 - 208*E1 + 128)>>8); B1 = ((298*C1+516*D1 +128)>>8>255 ? 255 : (298*C1+516*D1 +128)>>8); R2 = ((298*C2 + 409*E1 + 128)>>8>255 ? 255 : (298*C2 + 409*E1 + 128)>>8); G2 = ((298*C2 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C2 - 100*D1 - 208*E1 + 128)>>8); B2 = ((298*C2 + 516*D1 +128)>>8>255 ? 255 : (298*C2 + 516*D1 +128)>>8); *(pRGBData+(height-i-1)*width*4+j*8+2) = R1<0 ? 0 : R1; *(pRGBData+(height-i-1)*width*4+j*8+1) = G1<0 ? 0 : G1; *(pRGBData+(height-i-1)*width*4+j*8) = B1<0 ? 0 : B1; *(pRGBData+(height-i-1)*width*4+j*8+3) = alpha; *(pRGBData+(height-i-1)*width*4+j*8+6) = R2<0 ? 0 : R2; *(pRGBData+(height-i-1)*width*4+j*8+5) = G2<0 ? 0 : G2; *(pRGBData+(height-i-1)*width*4+j*8+4) = B2<0 ? 0 : B2; *(pRGBData+(height-i-1)*width*4+j*8+7) = alpha; } } } } else { if (alphaYUV) { for (int i=0; i<height; ++i) { for (int j=0; j<width/2; ++j) { Y1 = *(pYUVData+i*width*3+j*4); U1 = *(pYUVData+i*width*3+j*4+1); Y2 = *(pYUVData+i*width*3+j*4+2); V1 = *(pYUVData+i*width*3+j*4+3); C1 = Y1-16; C2 = Y2-16; D1 = U1-128; E1 = V1-128; R1 = ((298*C1 + 409*E1 + 128)>>8>255 ? 255 : (298*C1 + 409*E1 + 128)>>8); G1 = ((298*C1 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C1 - 100*D1 - 208*E1 + 128)>>8); B1 = ((298*C1+516*D1 +128)>>8>255 ? 255 : (298*C1+516*D1 +128)>>8); R2 = ((298*C2 + 409*E1 + 128)>>8>255 ? 255 : (298*C2 + 409*E1 + 128)>>8); G2 = ((298*C2 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C2 - 100*D1 - 208*E1 + 128)>>8); B2 = ((298*C2 + 516*D1 +128)>>8>255 ? 255 : (298*C2 + 516*D1 +128)>>8); *(pRGBData+(height-i-1)*width*3+j*6+2) = R1<0 ? 0 : R1; *(pRGBData+(height-i-1)*width*3+j*6+1) = G1<0 ? 0 : G1; *(pRGBData+(height-i-1)*width*3+j*6) = B1<0 ? 0 : B1; *(pRGBData+(height-i-1)*width*3+j*6+5) = R2<0 ? 0 : R2; *(pRGBData+(height-i-1)*width*3+j*6+4) = G2<0 ? 0 : G2; *(pRGBData+(height-i-1)*width*3+j*6+3) = B2<0 ? 0 : B2; } } } else { for (int i=0; i<height; ++i) { for (int j=0; j<width/2; ++j) { Y1 = *(pYUVData+i*width*2+j*4); U1 = *(pYUVData+i*width*2+j*4+1); Y2 = *(pYUVData+i*width*2+j*4+2); V1 = *(pYUVData+i*width*2+j*4+3); C1 = Y1-16; C2 = Y2-16; D1 = U1-128; E1 = V1-128; R1 = ((298*C1 + 409*E1 + 128)>>8>255 ? 255 : (298*C1 + 409*E1 + 128)>>8); G1 = ((298*C1 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C1 - 100*D1 - 208*E1 + 128)>>8); B1 = ((298*C1+516*D1 +128)>>8>255 ? 255 : (298*C1+516*D1 +128)>>8); R2 = ((298*C2 + 409*E1 + 128)>>8>255 ? 255 : (298*C2 + 409*E1 + 128)>>8); G2 = ((298*C2 - 100*D1 - 208*E1 + 128)>>8>255 ? 255 : (298*C2 - 100*D1 - 208*E1 + 128)>>8); B2 = ((298*C2 + 516*D1 +128)>>8>255 ? 255 : (298*C2 + 516*D1 +128)>>8); *(pRGBData+(height-i-1)*width*3+j*6+2) = R1<0 ? 0 : R1; *(pRGBData+(height-i-1)*width*3+j*6+1) = G1<0 ? 0 : G1; *(pRGBData+(height-i-1)*width*3+j*6) = B1<0 ? 0 : B1; *(pRGBData+(height-i-1)*width*3+j*6+5) = R2<0 ? 0 : R2; *(pRGBData+(height-i-1)*width*3+j*6+4) = G2<0 ? 0 : G2; *(pRGBData+(height-i-1)*width*3+j*6+3) = B2<0 ? 0 : B2; } } } } return 0;}
(2)使用opencv进行颜色空间转换
下面的代码主要调用了cvtColor();函数来实现YUV2BGR,把CV_YUV2BGR改成CV_ YcbCr2RGB即可把YcbCr转换成RGB。其中YUV为422格式,RGB为888格式。
(下面的代码运行效率较低,需要优化!)
void YUV2RGB (unsigned char *inbuf,Mat&bgrimg, int width, int height){ vector<Mat> yuvchs; unsigned char ybuf[width*height]; unsigned char ubuf[width*height/2]; unsigned char vbuf[width*height/2]; int cnt=0,y=0,u=0,v=0; for(int i=0;i<width*height*2;i++){ if(i%2){ if(cnt==0){ ubuf[u++]=inbuf[i]; cnt=1; } else{ vbuf[v++]=inbuf[i]; cnt=0; } } else{ ybuf[y++]=inbuf[i]; } } Mat umat0(1,width*height/2,CV_8UC1,ubuf); Mat vmat0(1,width*height/2,CV_8UC1,vbuf); Mat ymat1(1,width*height,CV_8UC1,ybuf); Mat umat1(1,width*height,CV_8UC1); Mat vmat1(1,width*height,CV_8UC1); resize(umat0,umat1,umat1.size()); resize(vmat0,vmat1,vmat1.size()); Mat yimg=ymat1.reshape(1,height); Mat uimg=umat1.reshape(1,height); Mat vimg=vmat1.reshape(1,height); yuvchs.push_back(yimg); yuvchs.push_back(uimg); yuvchs.push_back(vimg); Mat yuvimg; merge(yuvchs,yuvimg); cvtColor(yuvimg,bgrimg,CV_YUV2BGR);}
- YUV到RGB颜色空间转换
- YUV到RGB颜色空间转换源码
- 颜色空间转换(YUV,RGB)
- 颜色空间转换(YUV,RGB)
- RGB颜色空间到HSV和YUV的转换关系(含VC代码)
- YUV和RGB颜色空间转换,Alpha Blending
- YUV颜色空间及其与RGB的转换
- RGB与YUV颜色空间
- RGB,YUV颜色空间简介
- YUV到RGB转换
- RGB转换到HSV颜色空间
- RGB到HSV颜色空间的转换
- RGB到HSV颜色空间的转换
- RGB颜色空间与YUV等颜色空间之间的转换单元
- RGB到YUV的转换
- 颜色空间表示方式YUV,RGB
- RGB/HSV/YUV颜色空间模型总结
- RGB/HSV/YUV颜色空间模型总结
- uva507
- 【数据结构】顺序栈的基本操作
- UVa 10976 Fractions Again?!(分数拆分)
- 155,纯代码创建标签和按钮,并关联点击事件
- java程序员工作三年的修行之路
- YUV到RGB颜色空间转换
- freemarker中参数及java片段的使用方法
- 我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。
- 双目视觉算法简介
- 队列简单操作
- 几种定位方式的总结
- 2015年总结和2016年的规划
- Mahout In Action-第一章:初识Mahout
- Swift 之别具一格的 Struct 和 Class