实验一 彩色空间转换

一、实验目的
YUV与RGB空间的转换

二、实验原理

(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
为了使色差信号的动态范围控制在0.5之间,需要进行归一化,对色差信号引入压缩系数。归一化后的色差信号为:
U=-0.1684R-0.3316G+0.5B
V=0.5R-0.4187G-0.0813B
(2) 码电平分配及数字表达式
亮电平信号量化后码电平分配
在对分量信号进行8比特均匀量化时,共分为256个等间隔的量化级。为了防止信号变动造成过载,在256级上端留20级,下端留16级作为信号超越动态范围的保护带。
色差信号量化后码电平分配
色差信号经过归一化处理后,动态范围为-0.5-0.5,让色差零电平对应码电平128, 色差信号总共占225个量化级。在256级上端留15级,下端留16级作为信号超越动态范围 的保护带。
(3)色度格式
4:2:0格式是指色差信号U,V的取样频率为亮度信号取样频率的四分之一,在水平方 向和垂直方向上的取样点数均为Y的一半

三、实验内容
1、关键代码:YUV2GRGB的转换代码
根据色度公式和色差公式。可以推出由YUV分量表示RGB的算法如下
YUV分量表示RGB
在进行YUV2RGB的转换时,得到的RGB三个数据可能超过了unsigned char类型可以表示的范围,即可能<0或者>255。因此需要对yuv2rgb进行适当的修正,将>255的值都直接=255,<0的值都直接=0。
由此可得算法代码如下

void yuv2rgb(unsigned long picHeight, unsigned long picWidth, unsigned char *bufferYuv, int *r, int *g, int *b, FILE *rgb)
{
	unsigned int i,j;
	unsigned char *y, *u, *v,*u444,*v444;
	y = (unsigned char *)malloc(picHeight * picWidth);
	u = (unsigned char *)malloc(picHeight * picWidth /4);
	v = (unsigned char *)malloc(picHeight * picWidth /4);
	u444 = (unsigned char *)malloc(picHeight * picWidth);
	v444 = (unsigned char *)malloc(picHeight * picWidth);

	for (i = 0;i < picHeight*picWidth;i++)
	{
		*(y + i) = *(bufferYuv + i);
	}

	for (i = 0;i < picHeight*picWidth/4;i++)
	{
		*(u + i) = *(bufferYuv + i + picHeight*picWidth);
		*(v + i) = *(bufferYuv + i + picHeight*picWidth * 5 / 4);
	}

	int k = 0;
	for (i = 0;i < picHeight/2 ;i++)
	{
		for (j = 0;j < picWidth/2 ;j++)
		{
			*(u444 + picWidth * 2 * i + 2 * j) = *(u + k);
			*(u444 + picWidth * 2 * i + 2 * j + 1) = *(u + k);
			*(u444 + picWidth * (2 * i + 1) + 2 * j) = *(u + k);
			*(u444 + picWidth * (2 * i + 1) + 2 * j + 1) = *(u + k);

			*(v444 + picWidth * 2 * i + 2 * j) = *(v + k);
			*(v444 + picWidth * 2 * i + 2 * j + 1) = *(v + k);
			*(v444 + picWidth * (2 * i + 1) + 2 * j) = *(v + k);
			*(v444 + picWidth * (2 * i + 1) + 2 * j + 1) = *(v + k);
			k++;
		}
	}
	for (i = 0;i < picHeight*picWidth;i++)
	{
		*(r + i) = int((*(y + i) * 298 + *(v444 + i) * 411 - 57344) / 255);
		*(g + i) = int((*(y + i) * 298 - *(u444 + i) * 101 - *(v444 + i) * 211 + 34739) / 255);
		*(b + i) = int((*(y + i) * 298 + *(u444 + i) * 519 - 71117) / 255);

		//修正
		if (*(r + i) < 0)
			*(r + i) = 0;
		if (*(r + i) > 255)
			*(r + i) = 255;
		if (*(g + i) < 0)
			*(g + i) = 0;
		if (*(g + i) > 255)
			*(g + i) = 255;
		if (*(b + i) < 0)
			*(b + i) = 0;
		if (*(b + i) > 255)
			*(b + i) = 255;
	}



	unsigned char *rgbBuffer;
	rgbBuffer = (unsigned char *)malloc(picHeight*picWidth * 3);
	for (i = 0;i < picHeight*picWidth;i++)
	{
		*(rgbBuffer + 3 * i) = *(b + i);
		*(rgbBuffer + 3 * i + 1) = *(g + i);
		*(rgbBuffer + 3 * i + 2) = *(r + i);
	}
	fwrite(rgbBuffer, 1, picHeight*picWidth * 3, rgb);



	free(y);
	free(u);
	free(v);
	free(u444);
	free(v444);
	free(rgbBuffer);

}

2、主函数

#include <stdio.h>
#include <stdlib.h>
#include "yuv2rgb.h"

int main(int argc, const char * argv[])
{
	FILE *yuv = NULL;
	FILE *rgb = NULL;
	if ((rgb = fopen(argv[2], "wb")) == NULL)
	{
		printf("rgb file fail!");
		exit(0);
	}
	unsigned long picHeight, picWidth;
	picHeight = atoi(argv[3]);
	picWidth = atoi(argv[4]);
	if ((yuv = fopen(argv[1], "rb")) == NULL)
	{
		printf("yuv file fail!");
		exit(0);
	}
	int buffer2size = picHeight * picWidth * 3 / 2;//256*256
	printf("yuvFile length:%d\n", buffer2size);
	unsigned char *bufferYuv;
	int *r, *g, *b;
	bufferYuv = (unsigned char *)malloc(buffer2size);
	r = (int *)malloc(sizeof(int)* picHeight*picWidth);
	g = (int *)malloc(sizeof(int)* picHeight*picWidth);
	b = (int *)malloc(sizeof(int)* picHeight*picWidth);
	fread(bufferYuv, 1, buffer2size, yuv);
	yuv2rgb(picHeight,picWidth,bufferYuv,r,g,b,rgb);
	free(bufferYuv);
	free(r);
	free(g);
	free(b);
	fclose(yuv);
	fclose(rgb);
	return 0;
}

三、实验结果
1、原RGB图像
原RGB图像
2、由YUV转换后的RGB图像
转换后RGB图像

四、误差分析
从两张图片中可以看出存在一定的色度差异。可能是在YUV转换RGB过程中丢失了一部分色度信息,导致误差。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值