现在的位置: 首页 > 技术文章 > 正文

YUV422与RGB互相转换

2015年07月11日 技术文章 ⁄ 共 4410字 ⁄ 字号 评论 1 条 ⁄ 阅读 240 次

转自: http://m.blog.csdn.net/blog/guo8113/25333837#

 

前一段时间在DM8168中进行颜色空间的转换,在网上找了些程序,自己也根据网上的改了下,由于能力问题,实在是不好意思说做了好几天才弄出来,主要是因为YUV<—>RGB有各种各样的转换公式。在多次的实验修改后,终于找到了对的公式,共享出来,以便需要的人选择。

在监控系统中大多采用YUV的颜色空间,原因不说了,网上搜YUV转RGB各种介绍。

在TI的视频英语达芬奇系列中(这里只测试了DVR、IPNC),

采用如下公式:

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)

转换效果图如下

YUV----RGB

YUV----RGB

第一幅是原图YUV,第二幅是转为RGB后存为bmp,反转是因为BMP图像是从最下面一行开始存取的原因,最下面一副是转回YUV的图像。

代码如下,代码中YUV采用YUYVYUYV的格式,RGB为RGBRGBRGB.....

</p>
#ifndef _RGB2YUV__
#define _RGB2YUV__
#include <iostream>
using namespace std;

#define TUNE(r) ( r < 0 ? 0 : (r > 255 ? 255 : r) )

static int RGB_Y[256];
static int RGBR_V[256];
static int RGBG_U[256];
static int RGBG_V[256];
static int RGBB_U[256];
static int YUVY_R[256];
static int YUVY_G[256];
static int YUVY_B[256];

static int YUVU_R[256];
static int YUVU_G[256];
static int YUVU_B[256];

static int YUVV_R[256];
static int YUVV_G[256];
static int YUVV_B[256];

static int coff_rv[256];
static int coff_gu[256];
static int coff_gv[256];
static int coff_bu[256];

//直接采用公式浮点计算方式
//仅RGB2YUV采用了查表法,所以有一部分表是没有用到的
void InitTable()
{
int i;
for(i = 0;i<256;i++)
{
//初始化表,放大256倍
RGB_Y[i] = 298 * (i - 16);
RGBR_V[i] = 408 * (i - 128);
RGBG_U[i] = 100 * (128- i);
RGBG_V[i]= 208*(128-i);
RGBB_U[i] =517 * (i - 128);
//y=0.257*r+0.504*g+0.098*b+16
//u = -0.148*r - 0.291*g + 0.439*b + 128
//0.439*r - 0.368*g - 0.071*b + 128
YUVY_R[i]=66*i;
YUVY_G[i]=129*i;
YUVY_B[i]=25*i;
YUVU_R[i]=-38*i;
YUVU_G[i]=-74*i;
YUVU_B[i]=112*i;
YUVV_R[i]=112*i;
YUVV_G[i]=-94*i;
YUVV_B[i]=-18*i;
/*所用公式(此公式不适用)
*pRGB = (unsigned char)(1.0*y + 8 + 1.402*(v-128)); pRGB++; // r
*pRGB = (unsigned char)(1.0*y - 0.34413*(u-128) - 0.71414*(v-128)); pRGB++; // g
*pRGB = (unsigned char)(1.0*y + 1.772*(u-128) + 0); pRGB++ ;
*/
coff_rv[i] = (8+1.402*(i-128))*256;
coff_gu[i] = -0.34413*(i-128)*256;
coff_gv[i] = -0.71414*(i-128)*256;
coff_bu[i] = 1.772*(i-128)*256;

/*应该使用如下公式:
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)
*/
}
}

void YUV2RGB422(unsigned char *pRGB, unsigned char *pYUV,int size)
{
unsigned char y, u, v,y1;
int r,g,b;
unsigned int i=0;
unsigned int loop = size>>1;
while(loop-- >0)
{

y = *pYUV; pYUV++;
u = *pYUV; pYUV++;
y1 = *pYUV;pYUV++;
v = *pYUV; pYUV++;

r = 1.164*(y-16) + 1.596*(v-128);
g = 1.164*(y-16) - 0.813*(v-128) - 0.392*(u-128);
b = 1.164*(y-16) + 2.017*(u-128);

*pRGB = TUNE(r);pRGB++;
*pRGB = TUNE(g);pRGB++;
*pRGB = TUNE(b);pRGB++;

r = 1.164*(y1-16) + 1.596*(v-128);
g = 1.164*(y1-16) - 0.813*(v-128) - 0.392*(u-128);
b = 1.164*(y1-16) + 2.017*(u-128);
*pRGB = TUNE(r);pRGB++;
*pRGB = TUNE(g);pRGB++;
*pRGB = TUNE(b);pRGB++;
}

}
//size 为图片的大小
void RGB2YUV422(unsigned char *pRGB, unsigned char *pYUV,int size)
{
unsigned char r,g,b,u,v,u1,v1,r1,g1,b1;
//unsigned char *YUVBuff;
//unsigned char* p;
//p = YUVBuff;//
int loop = size/2;
int i;
for( i=0;i<loop;i++)
{
r = *pRGB; pRGB++;
g = *pRGB; pRGB++;
b = *pRGB; pRGB++;
r1 = *pRGB; pRGB++;
g1 = *pRGB; pRGB++;
b1 = *pRGB; pRGB++;

//new method --- right
int y = ((YUVY_R[r] + YUVY_G[g] + YUVY_B[b] + 128) >> 8) +16;
u = ((YUVU_R[r] + YUVU_G[g] + YUVU_B[b] + 128) >> 8) + 128;
v = ((YUVV_R[r] + YUVV_G[g] + YUVV_B[b] + 128) >> 8) + 128;
int y1 = ((YUVY_R[r1] + YUVY_G[g1] + YUVY_B[b1] + 128) >> 8)+16;
u1 = ((YUVU_R[r1] + YUVU_G[g1] + YUVU_B[b1] + 128) >> 8) + 128;
v1 = ((YUVV_R[r1] + YUVV_G[g1] + YUVV_B[b1] + 128) >> 8) + 128;

*pYUV++ = TUNE(y);
*pYUV++ =(TUNE(u)+TUNE(u1))>>1;
*pYUV++ = TUNE(y1);
*pYUV++ = TUNE(v);
}

}

void inline Yuv2RgbPixel(unsigned char y,unsigned char u,unsigned char v,
unsigned char* rgbPixel)
{
int r = (RGB_Y[y] + RGBR_V[v] + 128) >> 8;
int g = ((RGB_Y[y] + RGBG_V[v] +RGBG_U[u]+ 128)>>8 );
int b = ((RGB_Y[y] + RGBB_U[u]+128 )>>8);
*rgbPixel=TUNE(r);rgbPixel++;
*rgbPixel=TUNE(g);rgbPixel++;
*rgbPixel=TUNE(b);
}
void YUV2RGB(unsigned char *pRGB, unsigned char *pYUV,int size)//444
{
unsigned char y, u, v;

for(int i=0;i<size;i++)
{
y = *pYUV; pYUV++;
u = *pYUV; pYUV++;
v = *pYUV; pYUV++;

Yuv2RgbPixel(y,u,v,pRGB);
pRGB += 3;
}

}
void inline Rgb2YuvPiexl(unsigned char r,unsigned char g,unsigned char b,unsigned char* pYUV)
{
int y = ((YUVY_R[r] + YUVY_G[g] + YUVY_B[b] + 128) >> 8) + 16;
int u = ((YUVU_R[r] + YUVU_G[g] + YUVU_B[b] + 128) >> 8) + 128;
int v = ((YUVV_R[r] + YUVV_G[g] + YUVV_B[b] + 128) >> 8) + 128;
*pYUV = TUNEY(y);pYUV++;
//*pYUV = u < 0 ? 0 : (u > 255 ? 255 : u);pYUV++;
*pYUV =TUNE(u);pYUV++;
*pYUV = TUNE(v);
}
void RGB2YUV(unsigned char *pRGB, unsigned char *pYUV,int size)
{
unsigned char r,g,b,y,u,v;
for(int i=0;i<size;i++)
{
r = *pRGB; pRGB++;
g = *pRGB; pRGB++;
b = *pRGB; pRGB++;
Rgb2YuvPiexl(r,g,b,pYUV);
pYUV +=3;

}
}
#endif
<p align="left">

代码下载

文件下载

目前有 1 条留言    访客:1 条, 博主:0 条

  1. 扫路车 2015年09月13日 下午8:35  @回复  Δ-49楼 回复

    下载学习了,谢谢分享!

给我留言

留言无头像?



×