数据压缩原理与应用之彩色空间转换 实验报告1

1、实验基本原理

(1)YUV 与 RGB 空间的相互转换
Y=0.2990R+0.5870G+0.1140B

R-Y=0.7010R -0.5870G -0.1140B

B-Y=-0.2990R -0.5870G+0.8860B

归一 化后的色差信号为:
U=-0.1684R -0.3316G+0.5B
V=0.5R -0.4187G -0.0813B

为将两个色差信号电平控制在-0.5~0.5,零电平对应128的码电平 :
U=-0.1684R -0.3316G+0.5B +128 
V=0.5R -0.4187G -0.0813B +128 
结合以上得 
R = Y + 1.4075 *(V-128) 
G = Y – 0.3455 (U –128) – 0.7169 (V –128) 
B = Y + 1.779 *(U – 128)

2、实验流程

1.程序初始化(打开两个文件、定义变量和缓冲区等)
2.读取YUV文件,抽取YUV数据写入缓冲区
3.调用YUV2RGB的函数实现YUV到RGB数据的转换
4.写RGB文件
5.程序收尾工作(关闭文件,释放缓冲区)

3、关键代码及其分析

 yuv2rgb.cpp部分代码

int RGB2YUV (int x_dim, int y_dim, void *bmp, void *y_in, void *u_in, void *v_in, int flip)

{  static int init_done = 0;

 long i, j, size;  unsigned char *r, *g, *b;  unsigned char *y, *u, *v;  unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv;  unsigned char *y_buffer, *u_buffer, *v_buffer;  unsigned char *sub_u_buf, *sub_v_buf;  float b1,r1,g1;//设置中间变量,防止溢出

 if (init_done == 0)  {   InitLookupTable();   init_done = 1;  }

 // check to see if x_dim and y_dim are divisible by 2  if ((x_dim % 2) || (y_dim % 2)) return 1;  size = x_dim * y_dim;

 // allocate memory

    y_buffer = (unsigned char *)y_in;     sub_u_buf = (unsigned char *)u_in;     sub_v_buf = (unsigned char *)v_in;     u_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));     v_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));  if (!(u_buffer && v_buffer))  {   if (u_buffer) free(u_buffer);   if (v_buffer) free(v_buffer);   return 2;  }

 b = (unsigned char *)bmp;  y = y_buffer;  u = u_buffer;  v = v_buffer;

 //上采样  for (j = 0; j < y_dim/2; j ++)  {   psu = sub_u_buf + j * x_dim / 2;   psv = sub_v_buf + j * x_dim / 2;   pu1 = u_buffer + 2 * j * x_dim;   pu2 = u_buffer + (2 * j + 1) * x_dim;   pv1 = v_buffer + 2 * j * x_dim;   pv2 = v_buffer + (2 * j + 1) * x_dim;   for (i = 0; i < x_dim/2; i ++)   {    *pu1 = *psu;    *(pu1 + 1) = *psu;    *pu2 = *psu;    *(pu2 + 1) = *psu;    *pv1 = *psv;    *(pv1 + 1) = *psv;    *pv2 = *psv;    *(pv2 + 1) = *psv;

   psu ++;    psv ++;    pu1 += 2;    pu2 += 2;    pv1 += 2;    pv2 += 2;   }  }

 // convert YUV to RGB  if (!flip) {   //暂时不用  } else {   for (i = 0; i < size; i++)   {    g = b + 1;//RGB格式文件储存按照BGR的顺序    r = b + 2;    b1 = (*y) + YUVRGB1779[*u];    g1 = (*y) - YUVRGB03455[*u] - YUVRGB07169[*v];    r1 = (*y) + YUVRGB14075[*v];    if(b1>0&&b1<255)    //类型为unsigned char的数据范围为0~255,直接进行计算可能会出现溢出现象,所以要引入中间变量进行判断    {     *b = (unsigned char)b1;    }    else if (b1>255)    {     *b = 255;    }    else    {     *b = 0;    }    if (g1>0 && g1<255)    {     *g = (unsigned char)g1;    }    else if (g1>255)    {     *g = 255;    }    else    {     *g = 0;    }    if (r1>0 && r1<255)       {       *r = (unsigned char)r1;    }    else if (r1>255)    {     *r = 255;    }else    {     *r = 0;    }    b += 3;    y ++;    u ++;    v ++;   }  }

 free(u_buffer);  free(v_buffer);

 return 0; }

void InitLookupTable() {  int i;

 for (i = 0; i < 256; i++) YUVRGB14075[i] = (float)1.4075 * (i-128);  for (i = 0; i < 256; i++) YUVRGB03455[i] = (float)0.3455 * (i-128);  for (i = 0; i < 256; i++) YUVRGB07169[i] = (float)0.7169 * (i-128);  for (i = 0; i < 256; i++) YUVRGB1779[i] = (float)1.779 * (i-128);

}

 

main.cpp部分代码

 
/* point to the specified file names */
	yuvFileName = argv[1];
	rgbFileName = argv[2];

	frameWidth = atoi(argv[3]);
	frameHeight = atoi(argv[4]);
	
	/* open the yuv file */
	yuvFile = fopen(yuvFileName, "rb");
	if (yuvFile == NULL)
	{
		printf("cannot find yuv file\n");
		exit(1);
	}
	else
	{
		printf("The input yuv file is %s\n", yuvFileName);
	}

	/* open the RAW file */
	rgbFile = fopen(rgbFileName, "wb");
	if (rgbFile == NULL)
	{
		printf("cannot find rgb file\n");
		exit(1);
	}
	else
	{
		printf("The output rgb file is %s\n", rgbFileName);
	}

	/* get an input buffer for a frame */
	rgbBuf = (u_int8_t*)malloc(frameWidth * frameHeight * 3);

	/* get the output buffers for a frame */
	yBuf = (u_int8_t*)malloc(frameWidth * frameHeight);
	uBuf = (u_int8_t*)malloc((frameWidth * frameHeight) / 4);
	vBuf = (u_int8_t*)malloc((frameWidth * frameHeight) / 4);

	if (rgbBuf == NULL || yBuf == NULL || uBuf == NULL || vBuf == NULL)
	{
		printf("no enought memory\n");
		exit(1);
	}

	while (fread(yBuf, 1, frameWidth * frameHeight ,yuvFile)&&fread(uBuf, 1, frameWidth * frameHeight /4, yuvFile)&&fread(vBuf, 1, frameWidth * frameHeight /4, yuvFile)) 
	{
	
		if(RGB2YUV(frameWidth, frameHeight, rgbBuf, yBuf, uBuf, vBuf, flip))
		{
			printf("error");
			return 0;
					}

	

		fwrite(rgbBuf, 1, frameWidth * frameHeight * 3, rgbFile);
		
		printf("\r...%d", ++videoFramesWritten);
	}
	


 

4、实验结果及分析

程序第一次执行时,yuv转换成rgb,再转换为yuv,用yuv播放器打开后图像为下图,色彩严重失真

我检查了代码,发现原来是把上采样的代码写成了下采样,修改后,再次执行程序

原图1转换后图像1

原图2转换后图像2

原图3转换后图像3

原图4转换后图像4

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值