目录
一、实验目的
- 将给定的实验数据用该程序转换为RGB文件。
- 并与原RGB文件进行比较,如果有误差,分析误差来自何处。
- 总结 RGB 和 YUV。
- 彩色空间转换的转换公式及编程实现的算法。 写成实验报告。
二、实验原理
Y=0.2990R+0.5870G+0.1140B
R-Y=0.7010R-0.5870G-0.1140B
B-Y=-0.2990R-0.5870G+0.8860B
(1)RGB2YUV
Y=0.299R+0.587G+0.114B
U=-0.1684R-0.3316G+0.5B+128
V=0.5R-0.4187G-0.0813B+128
(2)YUV2RGB
R=1.0753Y+1.5075(V−128)
G =1.0753Y-0.3441( U −128)-0.6084(V−128)
B = 1.0753Y-0.3441(U-128)-0.6084(V-128)
(3)RGB文件分析
- 文件中的数据为BGRBGRBGR……
- R、G、B分别有256*256=65536个数值
- R、G、B分别据自己前一个数据的偏移量都是3
(4)YUV文件分析
- 先存放256*256个像素的Y
- 再存放128*128的U
- 最后存放128*128的V
(5)量化
量化过程
三、实验思路
RGB2YUV
int RGB2YUV (int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip);
x_dim为图像宽度,y_dim为图像高度。
bmp为RGB文件读取数据的指针。
y_out、u_out、v_out为转换后存放Y、U、V数据的输出指针。
flip为是否对图像进行上下颠倒的参数。
通过循环,依次读取每个像素的B、G、R值,并代入公式计算Y、U、V。
对U、V数据进行下采样(取四个点数据均值),以实现128*128的数据量。
YUV2RGB
四、实验过程
命令行参数设置
RGB2YUV
(1)代码
程序对于变量数据类型的选择、内存的占用.使得在处理24bits(8B8G8R)的RGB图像时,为其每个像素单个分量开辟的空间都为8bits,几乎不会有任何的浪费,十分精确。
#define u_int8_t unsigned __int8
#define u_int unsigned __int32
#define u_int32_t unsigned __int32
#define FALSE false
#define TRUE true
查找表
static float r0299[256],g0587[256],b0114[256],r01684[256],g03316[256],b05[256],r05[256],g04187[256],b00813[256];
void Table()
{
for(int i=0;i<256;i++) r0299[i]=0.299*i;
for(int i=0;i<256;i++) g0587[i]=0.587*i;
for(int i=0;i<256;i++) b0114[i]=0.114*i;
for(int i=0;i<256;i++) r01684[i]=0.1684*i;
for(int i=0;i<256;i++) g03316[i]=0.3316*i;
for(int i=0;i<256;i++) b05[i]=0.5*i;
for(int i=0;i<256;i++) r05[i]=0.5*i;
for(int i=0;i<256;i++) g04187[i]=0.4187*i;
for(int i=0;i<256;i++) b00813[i]=0.0813*i;
}
主函数
int main(int argc,char** argv)
{
int height,width;
char *filename_yuv,*filename_rgb;
unsigned char *RGB_buffer=NULL;
unsigned char *YUV_buffer=NULL;
unsigned char *RGB_buffer_del,*YUV_buffer_del;
filename_yuv=argv[2];
filename_rgb=argv[1];
height=atoi(argv[3]);
width=atoi(argv[4]);
//读入
RGB_buffer=new unsigned char[height*width*3];
YUV_buffer=new unsigned char[height*width*3/2];
RGB_buffer_del=RGB_buffer;
YUV_buffer_del=YUV_buffer;
FILE *fp_yuv=NULL,*fp_rgb=NULL;
fp_yuv=fopen(filename_yuv,"wb");
fp_rgb=fopen(filename_rgb,"rb");
fread(RGB_buffer,sizeof(unsigned char),height*width*3,fp_rgb);
//RGB2YUV函数
RGB2YUV(height,width,RGB_buffer,YUV_buffer);
//写入
fwrite(YUV_buffer,sizeof(unsigned char),height*width*3/2,fp_yuv);
delete[] RGB_buffer_del;
delete[] YUV_buffer_del;
return 0;
}
由于采用4:2:0的采样空间,需要对U、V进行下采样,这就必须保证x_dim和y_dim均为偶数。
// 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;
RGB2YUV函数
int RGB2YUV(int height,int width,unsigned char *RGB__buffer,unsigned char *YUV__buffer)
{
unsigned char *b_buffer,*g_buffer,*r_buffer;
unsigned char *Y_buffer,*U_buffer,*V_buffer;
unsigned char *u_buffer,*v_buffer;
unsigned char *pu_up1,*pu_up2,*pv_up1,*pv_up2;
Y_buffer=YUV__buffer;
U_buffer=YUV__buffer+height*width;
V_buffer=YUV__buffer+height*width*5/4;
u_buffer=new unsigned char[height*width];
v_buffer=new unsigned char[height*width];
pu_up1=u_buffer;
pu_up2=u_buffer+width;
pv_up1=v_buffer;
pv_up2=v_buffer+width;
b_buffer=RGB__buffer;
g_buffer=RGB__buffer+1;
r_buffer=RGB__buffer+2;
unsigned char *pu_buffer,*pv_buffer;
pu_buffer=u_buffer;
pv_buffer=v_buffer;
for(int i=0;i<height;i++)
{
for(int j=0;j<width;j++)
{
if(r0299[*r_buffer]+g0587[*g_buffer]+b0114[*b_buffer]<0)
*Y_buffer=(unsigned char)0;
else
if(r0299[*r_buffer]+g0587[*g_buffer]+b0114[*b_buffer]>255)
*Y_buffer=(unsigned char)255;
else *Y_buffer=unsigned char (r0299[*r_buffer]+g0587[*g_buffer]+b0114[*b_buffer]);
if(-r01684[*r_buffer]-g03316[*g_buffer]+b05[*b_buffer]<-128)
*pu_buffer=(unsigned char)0;
else
if(-r01684[*r_buffer]-g03316[*g_buffer]+b05[*b_buffer]>128)
*pu_buffer=(unsigned char)255;
else *pu_buffer=unsigned char(-r01684[*r_buffer]-g03316[*g_buffer]+b05[*b_buffer]+128);
if(r05[*r_buffer]-g04187[*g_buffer]-b00813[*b_buffer]<-128)
*pv_buffer=(unsigned char)0;
else
if(r05[*r_buffer]-g04187[*g_buffer]-b00813[*b_buffer]>128)
*pv_buffer=(unsigned char)255;
else *pv_buffer=unsigned char(r05[*r_buffer]-g04187[*g_buffer]-b00813[*b_buffer]+128);
Y_buffer++;
pu_buffer++;
pv_buffer++;
r_buffer+=3;
g_buffer+=3;
b_buffer+=3;
}
}
for(int i=0;i<height/2;i++)
{
for(int j=0;j<width/2;j++)
{
*U_buffer=(*pu_up1+*(pu_up1+1)+*pu_up2+*(pu_up2+1))/4;
*V_buffer=(*pv_up1+*(pv_up1+1)+*pv_up2+*(pv_up2+1))/4;
U_buffer++;
V_buffer++;
pu_up1+=2;
pu_up2+=2;
pv_up1+=2;
pv_up2+=2;
}
if(i!=height/2)
{
pu_up1+=width;
pu_up2+=width;
pv_up1+=width;
pv_up2+=width;
}
}
delete[] u_buffer;
delete[] v_buffer;
return 0;
}
(2)结果
YUV2RGB
(1)代码
主函数
int main(int argc, char** argv)
{
int height,width;
char *filename_yuv,*filename_rgb;
filename_yuv=argv[1];
filename_rgb=argv[2];
height=atoi(argv[3]);
width=atoi(argv[4]);
unsigned char *YUV_buffer=NULL,*Y_buffer,*U_buffer,*V_buffer;
unsigned char *RGB_buffer=NULL;
unsigned char *YUV_buffer_del,*RGB_buffer_del;
YUV_buffer=new unsigned char[height*width*3/2];
YUV_buffer_del=YUV_buffer;
if((width%2==1)||(height%2==1))
{
printf("please input the right height and width/n");
}
if(YUV_buffer==NULL)
{
printf("can not new unsignde char/n");
exit(1);
}
FILE *fp_yuv=NULL,*fp_rgb=NULL;
fp_yuv=fopen(filename_yuv,"rb");
fp_rgb=fopen(filename_rgb,"wb");
if((fp_yuv==NULL)||(fp_rgb==NULL))
{
printf("can not open the file/n");
exit(1);
}
fread(YUV_buffer,sizeof(unsigned char),height*width*3/2,fp_yuv);
Y_buffer=YUV_buffer;
U_buffer=YUV_buffer+height*width;
V_buffer=YUV_buffer+(height*width*5)/4;
RGB_buffer=new unsigned char[height*width*3];
RGB_buffer_del=RGB_buffer;
if(RGB_buffer==NULL)
{
printf("can not new unsigned char/n");
exit(1);
}
YUV2RGB(height,width,Y_buffer,U_buffer,V_buffer,RGB_buffer);
fwrite(RGB_buffer,sizeof(unsigned char),height*width*3,fp_rgb);
fclose(fp_yuv);
fclose(fp_rgb);
delete[] YUV_buffer_del;
delete[] RGB_buffer_del;
return 0;
}
函数
int YUV2RGB(int height,int width,unsigned char *Y__buffer,unsigned char *U__buffer,unsigned char *V__buffer,unsigned char *RGB__buffer)
{
//查找表
float v14075[256],u03455[256],v07169[256],u1779[256],y[256];
for(int i=0;i<256;i++) v14075[i]=(i-128)*1.4075;
for(int i=0;i<256;i++) u03455[i]=(i-128)*0.3455;
for(int i=0;i<256;i++) v07169[i]=(i-128)*0.7169;
for(int i=0;i<256;i++) u1779[i]=(i-128)*1.779;
for(int i=0;i<256;i++) y[i]=i;
unsigned char *u_buffer,*v_buffer;
unsigned char *pu_up1,*pu_up2,*pv_up1,*pv_up2;
unsigned char *b_buffer,*g_buffer,*r_buffer;
unsigned char *u_buffer_del,*v_buffer_del;
u_buffer=new unsigned char[height*width];
v_buffer=new unsigned char[height*width];
u_buffer_del=u_buffer;
v_buffer_del=v_buffer;
pu_up1=u_buffer;
pu_up2=u_buffer+width;
pv_up1=v_buffer;
pv_up2=v_buffer+width;
for(int i=0;i<(height/2);i++)
{
for(int j=0;j<(width/2);j++)
{
*pu_up1=*U__buffer;
*(pu_up1+1)=*U__buffer;
*pu_up2=*U__buffer;
*(pu_up2+1)=*U__buffer;
pu_up1+=2;
pu_up2+=2;
*pv_up1=*V__buffer;
*(pv_up1+1)=*V__buffer;
*pv_up2=*V__buffer;
*(pv_up2+1)=*V__buffer;
pv_up1+=2;
pv_up2+=2;
U__buffer++;
V__buffer++;
}
if(i!=(height/2))
{
pu_up1+=width;
pu_up2+=width;
pv_up1+=width;
pv_up2+=width;
}
}
b_buffer=RGB__buffer;
g_buffer=RGB__buffer+1;
r_buffer=RGB__buffer+2;
for(int i=0;i<(height*width);i++)//计算rgb
{
if((y[*Y__buffer]+v14075[*v_buffer])<0)
*r_buffer=(unsigned char)0;
else
if((y[*Y__buffer]+v14075[*v_buffer])>255)
*r_buffer=(unsigned char)255;
else *r_buffer=(unsigned char)(y[*Y__buffer]+v14075[*v_buffer]);
if((y[*Y__buffer]-u03455[*u_buffer]-v07169[*v_buffer])<0)
*g_buffer=(unsigned char)0;
else
if((y[*Y__buffer]-u03455[*u_buffer]-v07169[*v_buffer])>255)
*g_buffer=(unsigned char)255;
else *g_buffer=(unsigned char)(y[*Y__buffer]-u03455[*u_buffer]-v07169[*v_buffer]);
if((y[*Y__buffer]+u1779[*u_buffer])<0)
*b_buffer=(unsigned char)0;
else
if((y[*Y__buffer]+u1779[*u_buffer])>255)
*b_buffer=(unsigned char)255;
else *b_buffer=(unsigned char)(y[*Y__buffer]+u1779[*u_buffer]);
b_buffer+=3;
g_buffer+=3;
r_buffer+=3;
Y__buffer++;
u_buffer++;
v_buffer++;
}
delete[] u_buffer_del;
delete[] v_buffer_del;
return 0;
}
(2) 结果
五、实验分析
分量 | 熵 |
---|---|
B | 6.85686 |
G | 7.17846 |
R | 7.22955 |
分量 | 熵 |
---|---|
Y | 6.331819 |
U | 5.126402 |
V | 4.113143 |
(1)YUV为了便于传输,U、V分量只有原本的1/4。对于原本色度变化缓慢的图像区域,这种下采样造成的影响不大;但对于色度急剧变化的区域,下采样就导致色度信息被丢失了。因此转换后的RGB文件分布曲线的抖动更大了,变化不那么平滑了。
(2)YUV与RGB色彩空间并不重合,在色彩空间变换时存在溢出。
(3)对U、V数据进行上采样时,选择直接将值进行4次复制,引入了一定的误差。
(4)查找表的思想,以空间换时间,当需要处理大量文件时,会产生更大的优势。
(5)图像数据的存储存在冗余信息,由于人眼感知特性的灵敏度有限,对于部分数据可以进行压缩,以减小传输数据量。