在图像处理过程中,很多场合需要对RGB图像进行YUV格式转换。主要由于YUV色彩空间的图像容易实现目标图像与阴影的分割(阴影的YUV数据存在跟目标图像的YUV数据存在明显的差异),另一种原因是YUV420格式的图片数据缩小了图片的大小,在大量的图片处理过程中,降低了内存的消耗,提高运行效率。
由于RGB和YUV图像数据都不是灰度图像,它们都由三种色彩组成。所以存储一张RGB和YUV格式的图像数据所需要的字节数都为图像的宽width*图像的高hight*3。
一、RGB
RGB图像数据也有很多种,具体根据r、g、b三种色彩排列形式而分列。假设有一张分辨率为352*288的RGB图像,并把其对应的352列288行的二维像素矩阵转化为352*288列的一维像素阵。把按照
r1、g1、b1,r2、g2、b2,…,r352、g352、b352,…,r352*288、g352*288、b352*288
这样排列的RGB图像数据归列为[rgb]。像有些通过OPencv得到的RGB图像,它的排列方式就不是这样,它排列的方式为
[gbr]: g1、b1、r1,g2、b2、r2,…,g352、b352、r352,…,g352*288、b352*288、r352*288
所以在转化RGB图像之前先弄明白它的r、b、g是怎样排列的。
二、YUV
YUV图像数据也一样,它的排列方式更多,所以有很多种YUV格式的数据
[yuv]: y1、u1、v1,y2、u2、v2,…,y352、u352、v352,…,y352*288、u352*288、v352*288
[y][u][v]:
y1、y2、y3、y4、…、y352*288,u1、u2、u3、……、u352*288/4,v1、v2、v3、…、v352*288/4
第二种[y][u][v]排列方式就是YUV420数据格式,它是按照Y:U:V=4:1:1的数据量排列,所以它的字节数变为图像的宽width*图像的高hight*3/2,并且排列的方式为首先排列完所有的Y团块,其次是U团块,最后是V团块。
三、RGB[rbg] to YUV420([y][u][v])
#include <string.h>
int RGB2YUV_YR[256], RGB2YUV_YG[256], RGB2YUV_YB[256];
int RGB2YUV_UR[256], RGB2YUV_UG[256], RGB2YUV_UBVR[256];
int RGB2YUV_VG[256], RGB2YUV_VB[256];
// Table used for RGB to YUV420 conversion
void InitLookupTable()
{ int i;
for (i = 0; i < 256; i++) RGB2YUV_YR[i] = (float)65.481 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_YG[i] = (float)128.553 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_YB[i] = (float)24.966 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_UR[i] = (float)37.797 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_UG[i] = (float)74.203 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_VG[i] = (float)93.786 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_VB[i] = (float)18.214 * (i<<8);
for (i = 0; i < 256; i++) RGB2YUV_UBVR[i] = (float)112 * (i<<8);
}
// Convert from RGB24 to YUV420
unsigned int uu0[352*288], vv0[352*288];
int ConvertRGB2YUV(int w,int h,unsigned char *bmp,unsigned char *yuv)
{ unsigned int *uu,*vv;
unsigned int *pu1,*pu2,*pu3,*pu4;
unsigned int *pv1,*pv2,*pv3,*pv4;
unsigned char *r,*g,*b,*y,*u,*v; int i,j; uu=uu0; vv=vv0;
if(uu==NULL || vv==NULL)
return 0;
y=yuv;
r=bmp; g=bmp+1; b=bmp+2;
for(i=0;i
{
for(j=0;j
{ *y++=( RGB2YUV_YR[*r] +RGB2YUV_YG[*g]+RGB2YUV_YB[*b]+1048576)>>16;
*uu++=(-RGB2YUV_UR[*r] -RGB2YUV_UG[*g]+RGB2YUV_UBVR[*b]+8388608)>>16;
*vv++=( RGB2YUV_UBVR[*r]-RGB2YUV_VG[*g]-RGB2YUV_VB[*b]+8388608)>>16;
r+=3; g+=3; b+=3;
}
}
u=yuv+w*h; v=u+(w*h)/4;
pu1=uu0; pu2=pu1+1; pu3=pu1+w; pu4=pu3+1;
pv1=vv0; pv2=pv1+1; pv3=pv1+w; pv4=pv3+1;
for(i=0;i
{
for(j=0;j
{
*u++=(*pu1+*pu2+*pu3+*pu4)>>2;
*v++=(*pv1+*pv2+*pv3+*pv4)>>2;
pu1+=2; pu2+=2; pu3+=2; pu4+=2;
pv1+=2; pv2+=2; pv3+=2; pv4+=2;
}
pu1+=w; pu2+=w; pu3+=w; pu4+=w;
pv1+=w; pv2+=w; pv3+=w; pv4+=w;
}
return 1;
)
四、查看YUV420图片数据
查看是否RGB转YUV420数据成功,可以将YUV420数据以二进制的方式保存为文本文件形式,通过YUVVIEWER软件读取文本文件进行查看。