分别对RGB、YUV文件分析三个通道的概率分布,并计算各自的熵

一、作业要求

对down.rgb和down.yuv分析三个通道的概率分布,并计算各自的熵。(编程实现)

  • 两个文件的分辨率均为256 * 256
  • yuv文件为4:2:0采样空间。YUV格式按照全部像素的Y数据块、U数据块和V数据块依次存放。
  • 存储格式为:rgb文件按每个像素BGR分量依次存放;

本文采用 C++ 编写

二、思路分析

1.RGB

rgb 文件中每个像素都按照 BGR 依次存放,则为BGRBGRBGRBGR…循环,由图像分辨率256 * 256可得,此 rgb 文件共有 256 * 256 * 3 = 196608个像素。

2.YUV

yuv 文件是 4:2:0 的采样空间,即每四个Y分量共用一个 UV 分量。
是基于平面模式进行存储。即先存储所有的 Y 分量,然后存储所有的 U 分量,最后 V 分量。
分别对RGB、YUV文件分析三个通道的概率分布,并计算各自的熵_第1张图片
图片来源于网络

  • y分量所占为256 * 256 = 65536

  • u分量:
    首:256 * 256 = 65536
    尾:256 * 256 *(1+1/4)= 81920

  • v分量:
    首:256 * 256 *(1+1/4)= 81920
    尾:256 * 256 *(1+1/2)= 98304

三、代码

1.rgb

#include
#include
#include
using namespace std;

//定义图像的分辨率
//256*256=65536
int height=256;
int wide=256;

int main()
{
     
	//定义R、G、B分量
	unsigned char R[65536]={
     0};
	unsigned char G[65536]={
     0};
	unsigned char B[65536]={
     0};

	//定义数量
	double R_num[256]={
     0};
	double G_num[256]={
     0};
	double B_num[256]={
     0};

	//定义频率
	double R_fre[256]={
     0};
	double G_fre[256]={
     0};
	double B_fre[256]={
     0};
	
	//定义RGB分量的熵
	double R_shang=0;
	double G_shang=0;
	double B_shang=0;
	
	//定义文件指针
	//打开所给的RGB图像文件
	FILE* image;
	fopen_s(&image,"C:\\Users\\Zhao Zhuo\\Desktop\\down.rgb", "rb");
	
	//定义文件RGB指针
	FILE* Red;
	FILE* Green;
	FILE* Blue;
	//定义最终存储数据的txt文档
	fopen_s(&Red,"C:\\Users\\Zhao Zhuo\\Desktop\\Red.txt", "w");
	fopen_s(&Green,"C:\\Users\\Zhao Zhuo\\Desktop\\Green.txt", "w");
	fopen_s(&Blue,"C:\\Users\\Zhao Zhuo\\Desktop\\Blue.txt", "w");
   	
	//256*256*3=196608
	unsigned char buffer[196608];
	fread(buffer,sizeof(unsigned char),196608,image);

	for(int i=0,j=0;i<196608;i=i+3,j++)
	{
     
		//按BGR顺序存储
		//读取RGB分量到数组
		B[j]=*(buffer+i);
		G[j]=*(buffer+i+1);
		R[j]=*(buffer+i+2);
	}

	//计算数量
	for(int i=0;i<256;i++)
	{
     
		for(int j=0;j<65536;j++)
		{
     
			if(int(R[j]==i)){
     R_num[i]++;}
			if (int(G[j]==i)){
     G_num[i]++;}
			if (int(B[j]==i)){
     B_num[i]++;}
		}
	}

	//计算频率
	for(int i=0;i<256;i++)
	{
     
		R_fre[i]=R_num[i]/(256*256);
		B_fre[i]=B_num[i]/(256*256);
		G_fre[i]=G_num[i]/(256*256);
	}

	//计算熵
	for (int i=0;i<256;i++)
	{
     
		if(R_fre[i]!=0)
			{
     R_shang += -R_fre[i]*log(R_fre[i])/log(double(2));}

		if(B_fre[i]!=0)
			{
     B_shang += -B_fre[i]*log(B_fre[i])/log(double(2));}
	
		if(G_fre[i]!=0)
			{
     G_shang += -G_fre[i]*log(G_fre[i])/log(double(2));}
	}

	//输出
	cout<<"R的熵为"<<R_shang<<endl;
	cout<<"G的熵为"<<G_shang<< endl;
	cout<<"B的熵为"<<B_shang<< endl;

	//写入文件
	for (int i=0;i<256;i++)
	{
     
		fprintf(Red,"%d\t%f\n",i,R_fre[i]);
		fprintf(Green,"%d\t%f\n",i,G_fre[i]);
		fprintf(Blue,"%d\t%f\n",i,B_fre[i]);
	}

	//关闭
	fclose(image);
	fclose(Red);
	fclose(Green);
	fclose(Blue);

	system("pause");
	return 0;
}

运行结果:
分别对RGB、YUV文件分析三个通道的概率分布,并计算各自的熵_第2张图片

2.yuv

#include
#include
#include
using namespace std;

//定义图像的分辨率
//256*256=65536
int height=256;
int wide=256;

int main()
{
     
	//定义Y、U、V分量
	//256*256*1/4=16384
	unsigned char Y[65536]={
     0};
	unsigned char U[16384]={
     0};
	unsigned char V[16384]={
     0};

	//定义数量
	double Y_num[256]={
     0};
	double U_num[256]={
     0};
	double V_num[256]={
     0};

	//定义频率
	double Y_fre[256]={
     0};
	double U_fre[256]={
     0};
	double V_fre[256]={
     0};
	
	//定义YUV分量的熵
	double Y_shang=0;
	double U_shang=0;
	double V_shang=0;
	
	//定义文件指针
	//打开所给的YUV图像文件
	FILE* image;
	fopen_s(&image,"C:\\Users\\Zhao Zhuo\\Desktop\\down.yuv", "rb");
	
	//定义文件YUV指针
	FILE* Ym;
	FILE* Um;
	FILE* Vm;
	//定义最终存储数据的txt文档
	fopen_s(&Ym,"C:\\Users\\Zhao Zhuo\\Desktop\\Y.txt", "w");
	fopen_s(&Um,"C:\\Users\\Zhao Zhuo\\Desktop\\U.txt", "w");
	fopen_s(&Vm,"C:\\Users\\Zhao Zhuo\\Desktop\\V.txt", "w");
   	
	//256*256*(1+1/2)=98304
	unsigned char buffer[98304];
	fread(buffer,sizeof(unsigned char),98304,image);

	//按YUV数据块顺序存储
	for(int i=0;i<256*256;i=i+1)
	{
     
		//读取Y分量到数组
		Y[i]=*(buffer+i);
	}

	for(int i=65536;i<81920;i=i+1)
	{
     
		//读取U分量到数组
		U[i-65536]=*(buffer+i);
	}
	for(int i=81920;i<98304;i=i+1)
	{
     
		//读取V分量到数组
		V[i-81920]=*(buffer+i);
	}

	//计算数量
	for(int i=0;i<256*256;i++)
	{
     
		Y_num[Y[i]]++;
	}

	for(int i=0;i<16384;i++)
	{
     
		U_num[U[i]]++;
		V_num[V[i]]++;
	}

	//计算频率
	for(int i=0;i<256;i++)
	{
     
		Y_fre[i]=Y_num[i]/(256*256);
		U_fre[i]=U_num[i]/(256*256/4);
		V_fre[i]=V_num[i]/(256*256/4);
	}

	//计算熵
	for (int i=0;i<256;i++)
	{
     
		if(Y_fre[i]!=0)
			{
     Y_shang += -Y_fre[i]*log(Y_fre[i])/log(double(2));}

		if(U_fre[i]!=0)
			{
     U_shang += -U_fre[i]*log(U_fre[i])/log(double(2));}

		if(V_fre[i]!=0)
			{
     V_shang += -V_fre[i]*log(V_fre[i])/log(double(2));}
	}

	//输出
	cout<<"Y的熵为"<<Y_shang<<endl;
	cout<<"U的熵为"<<U_shang<<endl;
	cout<<"V的熵为"<<V_shang<<endl;

	//写入文件
	for(int i=0;i<256;i++)
	{
     fprintf(Ym,"%d\t%f\n",i,Y_fre[i]);}

	for(int i=0;i<256;i++)
	{
     fprintf(Um,"%d\t%f\n",i,U_fre[i]);}

	for(int i=0;i<256;i++)
	{
     fprintf(Vm,"%d\t%f\n",i,V_fre[i]);}

	//关闭
	fclose(image);
	fclose(Ym);
	fclose(Um);
	fclose(Vm);

	system("pause");
	return 0;
}

运行结果:
分别对RGB、YUV文件分析三个通道的概率分布,并计算各自的熵_第3张图片

四、结果分析

将输出到桌面上的几个 txt 文件结果导入 excel 中,并绘制折线图观察概率分布。
分别对RGB、YUV文件分析三个通道的概率分布,并计算各自的熵_第4张图片
分别对RGB、YUV文件分析三个通道的概率分布,并计算各自的熵_第5张图片
分别对RGB、YUV文件分析三个通道的概率分布,并计算各自的熵_第6张图片
由输出结果可以看到

  • rgb 的熵要比 yuv 的熵更大
  • yuv 的概率分布相比 rgb 不均匀

两结果可相互验证

你可能感兴趣的:(数据压缩)