实验报告:彩色空间转换实验

实验报告:彩色空间转换实验

1.实验内容
①编写RGB转化为YUV程序,重点掌握函数定义,部分查找表的初始化和调用,缓冲区
分配。将得到的RGB文件转换为YUV文件,用YUV Viewer播放器观看,验证是否正确。
②编写将YUV转换为RGB的程序。将给定的实验数据用该程序转换为RGB文件。并与原
RGB文件进行比较,如果有误差,分析误差来自何处。
2.实验步骤
YUV2RGB文件转换流程分析
① 程序初始化(打开两个文件、定义变量和缓冲区 等)
② 读取YUV文件,抽取YUV数据写入缓冲区
③ 调用YUV2RGB的函数实现YUV到RGB数据的转换
④ 写RGB文件
⑤ 程序收尾工作(关闭文件,释放缓冲区)
3.实验代码
/RGB转YUV/

#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char* argv[])

{
	int w=256;
	int h=256;
	//程序初始化(打开两个文件、定义变量和缓冲区等)
	FILE* rgbFile=NULL;
	FILE* yuvFile = NULL;
	unsigned char*R,*G,*B,*pf,*Y,*U,*V,*u,*v;
	//打开rgb文件
	//rgbFile = fopen("D:\\大三下\\数据压缩\\down.rgb", "rb");
	rgbFile = fopen(argv[1], "rb");
	//开辟缓存区
    pf = (unsigned char *)malloc(sizeof(char)*(w*h*3));
	R = (unsigned char *)malloc(sizeof(char)*(w*h));
	G = (unsigned char *)malloc(sizeof(char)*(w*h));
	B = (unsigned char *)malloc(sizeof(char)*(w*h));
	Y = (unsigned char *)malloc(sizeof(char)*(w*h));
	U = (unsigned char *)malloc(sizeof(char)*(w*h));
	V = (unsigned char *)malloc(sizeof(char)*(w*h));
	u=(unsigned char *)malloc(sizeof(char)*(w*h/4));
	v=(unsigned char *)malloc(sizeof(char)*(w*h/4));
	fread(pf,1,w*h*3,rgbFile);
	int i,j,k=0;
	//提取RGB分量
	for(i=0,j=0;i<w*h*3;i=i+3,j++)
		{
		R[j]=pf[i+2];
		G[j]=pf[i+1];
		B[j]=pf[i];
		}
	//计算YUV分量
	for(i=0,j=0;i<w*h;i++,j++)
	{
		Y[j]=0.2990*R[i]+0.5870*G[i]+0.1140*B[i];
		U[j]=-0.1684*R[i]-0.3316*G[i]+0.5*B[i]+128;
		V[j]=0.5*R[i]-0.4187*G[i]-0.0813*B[i]+128;
	}
	//对UV下采样
	for(i=0;i<h;i=i+2)
	{
		for(j=0;j<w;j=j+2)
		{
		u[k]=(U[w*i+j]+U[w*i+j+1]+U[(i+1)*w+j]+U[(i+1)*w+j+1])/4;
		v[k]=(V[w*i+j]+V[w*i+j+1]+V[(i+1)*w+j]+V[(i+1)*w+j+1])/4;
		
		k++;
		}
	}
	//YUV量化后码电平分配
	for(k=0;k<w*h;k++)
	{
		if(Y[k]>235)
			Y[k]=235;
		 if(Y[k]<16)
			Y[k]=16;
	}
	for(k=0;k<w*h/4;k++)
	{
		if(u[k]>240)
			u[k]=240;
		if(u[k]<16)
			u[k]=16;
		if(v[k]>240)
			v[k]=240;
		if(v[k]<16)
			v[k]=16;
	}
	//yuvFile = fopen("D:\\大三下\\数据压缩\\down.yuv", "wb");
	yuvFile = fopen(argv[2], "wb");
	fwrite(Y,1,w*h,yuvFile);
	fwrite(u,1,w*h/4,yuvFile);
	fwrite(v,1,w*h/4,yuvFile);
		free(pf);
		free(R);
		free(G);
		free(B);
		free(Y);
		free(U);
		free(V);
		free(u);
		free(v);
		fclose(rgbFile);
		fclose(yuvFile);
	return 0;
}

转换后的down.yuv文件用YUV播放器播放
在这里插入图片描述
/YUV转RGB/此处我用了与RGB转YUV相反的方法,输出rgb文件再转换为yuv文件用YUV播放器打开

#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char* argv[])
{
	int w=256;
	int h=256;
	//程序初始化(打开两个文件、定义变量和缓冲区等)
	FILE* rgbFile=NULL;
	FILE* yuvFile = NULL;
	unsigned char*R,*G,*B,*pf,*Y,*U,*V,*u,*v;
	//打开yuv文件
	yuvFile = fopen(argv[1], "rb");
	//开辟缓存区
    pf = (unsigned char *)malloc(sizeof(char)*(w*h*3));
	R = (unsigned char *)malloc(sizeof(char)*(w*h));
	G = (unsigned char *)malloc(sizeof(char)*(w*h));
	B = (unsigned char *)malloc(sizeof(char)*(w*h));
	Y = (unsigned char *)malloc(sizeof(char)*(w*h));
	U = (unsigned char *)malloc(sizeof(char)*(w*h));
	V = (unsigned char *)malloc(sizeof(char)*(w*h));
	u=(unsigned char *)malloc(sizeof(char)*(w*h/4));
	v=(unsigned char *)malloc(sizeof(char)*(w*h/4));
	fread(Y,1,w*h,yuvFile);
	fread(u,1,w*h/4,yuvFile);
	fread(v,1,w*h/4,yuvFile);
	int i,j,k=0;
	//上采样
	for(i=0;i<h;i=i+2)
	{
		for(j=0;j<w;j=j+2)
		{
		U[w*i+j]=U[w*i+j+1]=U[(i+1)*w+j]=U[(i+1)*w+j+1]=u[k];
		V[w*i+j]=V[w*i+j+1]=V[(i+1)*w+j]=V[(i+1)*w+j+1]=v[k];
		k++;
		}
	}
	//计算RGB
	for(i=0,j=0;i<w*h;i++,j++)
	{
		R[j]=Y[i]+1.14075*(V[i]-128;
		G[j]=Y[i]-0.7169*(V[i]-128)-0.3455*(U[i]-128);
		B[j]=Y[i]+1.779*(U[i]-128);
	}
	rgbFile = fopen(argv[2], "wb");
	for(i=0,j=0;i<w*h*3;i=i+3,j++)
		{
		pf[i+2]=R[j];
		pf[i+1]=G[j];
		pf[i]=B[j];
		}
	fwrite(pf,1,w*h*3,rgbFile);
		free(pf);
		free(R);
		free(G);
		free(B);
		free(Y);
		free(U);
		free(V);
		free(u);
		free(v);
		fclose(rgbFile);
		fclose(yuvFile);
	return 0;
}

再次转为YUV文件打开
在这里插入图片描述
误差来源:RGB转YUV时有下采样和量化后码电平分配造成部分YUV数据丢失,故YUV转RGB会产生误差。

4.实验心得:
通过这次实验我对RGB和YUV文件格式其内部是如何储存的,如何读取,如何写入有了更好的理解,同时也学会如何开辟缓存区,如何使用main函数的形参。但仍有很多不足,我还是不习惯建多个文件,所有的代码都写在了main函数里,对于目标文件也只考虑当前的文件,代码不能广泛性使用,这些问题在以后的实验中都要注意。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值