1.2 分析RGB和YUV文件三个通道的概率分布,并计算各自的熵(编程实现)

1.2 分析RGB和YUV文件三个通道的概率分布,并计算各自的熵(编程实现)

一、作业要求

分析down.rgb和down.yuv三个通道的概率分布,并计算各自的熵。

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

二、分析思路

(一)RGB文件
“rgb文件按每个像素BGR分量依次存放”,即文件中的数据为BGRBGR……
“文件的分辨率均为256256”,即R、G、B分别有256256=65536个数值,且据自己前一个数据的偏移量都是3。
(二)YUV文件
“yuv为4:2:0采样空间”,如下图所示。

4:2:0采样空间
图片来源于网络

“文件的分辨率均为256256,YUV格式按照全部像素的Y数据块、U数据块和V数据块依次存放”,即YUV文件中的数据依次是256256个Y分量,256256~2562561.25为U分量数据,2562561.25~256256*1.50为V分量数据。

三、代码实现

(一)down.rgb文件

#include<iostream>
using namespace std;  

const int width = 256;   //图像宽度
const int height = 256;  //图像高度

int main(void)
{
 FILE *p_rgb=NULL;  //设置文件指针
 FILE *R=NULL;  //设置分量指针
 FILE *G=NULL;
 FILE *B=NULL;
 
 int err1;
 err1=fopen_s(&p_rgb,"C:\\Users\\user\\Desktop\\down.rgb","rb");  //打开down.rgb文件
 fopen_s(&R,"C:\\Users\\user\\Desktop\\R_result.txt","w");  //打开各分量结果存储文件
 fopen_s(&G,"C:\\Users\\user\\Desktop\\G_result.txt","w");
 fopen_s(&B,"C:\\Users\\user\\Desktop\\B_result.txt","w");
 
 unsigned char *RGB_buffer = NULL;
 RGB_buffer=(unsigned char *)malloc(sizeof(unsigned char)*3*width*height);  //动态分配指针地址内存
 if(RGB_buffer==NULL){printf("WRONG RGB_buffer!!\n");}
  
 fread(RGB_buffer,sizeof(unsigned char),3*width*height,p_rgb);  //读取文件数据
 
 unsigned char RR[width*height]={0};  //定义各分量从文件中读出后使用的数组
 unsigned char GG[width*height]={0};
 unsigned char BB[width*height]={0};
 
 int r=0;
 int g=0;
 int b=0;

 //将读出的各分量数据依次放入相应的数组
 int i=0;
 for(i;i<3*width*height;i++)
 {
  if(i%3==0)
  {
   BB[b]=*(RGB_buffer+i);
   b++;
  }
  else if(i%3==1)
  {
   GG[g]=*(RGB_buffer+i);
   g++;
  }
  else
  {
   RR[r]=*(RGB_buffer+i);
   r++;
  }
 }
 
 //统计各分量数据概率并写入txt文件
 double Bnum[256]={0};
 double Bre[256]={0};
 for(int j=0;j<256;j++)
 {
  for(int k=0;k<width*height;k++)
  {
   if(j==BB[k])
    Bnum[j]++;
  }
  Bre[j]=Bnum[j]/(width*height);
  fprintf(B,"%d\t%lf\n",j,Bre[j]);
 }

 double Gnum[256]={0};
 double Gre[256]={0};
 for(int j=0;j<256;j++)
 {
  for(int k=0;k<width*height;k++)
  {
   if(j==GG[k])
    Gnum[j]++;
  }
  Gre[j]=Gnum[j]/(width*height);
  fprintf(G,"%d\t%lf\n",j,Gre[j]);
 }

 double Rnum[256]={0};
 double Rre[256]={0};
 for(int j=0;j<256;j++)
 {
  for(int k=0;k<width*height;k++)
  {
   if(j==RR[k])
    Rnum[j]++;
  }
  Rre[j]=Rnum[j]/(width*height);
  fprintf(R,"%d\t%lf\n",j,Rre[j]);
 }

 //计算分量熵值
 double H_R=0,H_G=0,H_B=0;
 for(int i=0;i<256;i++)
 {
  if(Rre[i]!=0)
  {
   H_R=H_R-Rre[i]*(log(Rre[i])/log(double(2)));
  }
  if(Gre[i]!=0)
  {
   H_G=H_G-Gre[i]*(log(Gre[i])/log(double(2)));
  }
  if(Bre[i]!=0)
  {
   H_B=H_B-Bre[i]*(log(Bre[i])/log(double(2)));
  }
 }
 printf("R的熵=%f\n",H_R);
 printf("G的熵=%f\n",H_G);
 printf("B的熵=%f\n",H_B);
 
 free(RGB_buffer);
 fclose(p_rgb);
 fclose(R);
 fclose(G);
 fclose(B);
 system("pause");
 return 0;
}    

(二)down.yuv文件

#include<iostream>
using namespace std;  
const int width = 256;   //图像宽度
const int height = 256;  //图像高度

int main(void)
{
	FILE *p_yuv=NULL;//设置文件指针
	FILE *Y;//设置分量指针
	FILE *U;
	FILE *V;

	fopen_s(&p_yuv,"down.yuv","rb");//打开down.yuv文件
	fopen_s(&Y,"Y_result.txt","w");//打开各分量结果存储文件
	fopen_s(&U,"U_result.txt","w");
	fopen_s(&V,"V_result.txt","w");

	unsigned char *YUV_buffer = (unsigned char *)malloc(sizeof(unsigned char) *1.5*width*height);  //动态分配指针地址内存
	if(YUV_buffer==NULL){printf("WRONG YUV_buffer!!\n");}
		
	fread(YUV_buffer,sizeof(unsigned char),1.5*width*height,p_yuv);//读取文件数据

	unsigned char YY[width*height]={0};//定义各分量从文件中读出后使用的数组
	unsigned char UU[width*height/4]={0};
	unsigned char VV[width*height/4]={0};

	//将读出的各分量数据依次放入相应的数组
	for(int i=0,j=0;i<width*height;i++,j++)
	{
		YY[j]=YUV_buffer[i];
	}
	for(int i=width*height,j=0;i<width*height*1.25;i++,j++)
	{
		UU[j]=YUV_buffer[i];
	}
	for(int i=width*height*1.25,j=0;i<width*height*1.5;i++,j++)
	{
		VV[j]=YUV_buffer[i];
	}

	int y=0;
	int u=0;
	int v=0;

	//统计各分量数据概率并写入txt文件
	double Ynum[256]={0};
	double Yre[256]={0};
	for(int j=0;j<width*height;j++)
	{
		y=YY[j];
		Ynum[y]++;
	}
	for(int k=0;k<256;k++)
	{
		Yre[k]=Ynum[k]/(width*height);
		fprintf(Y,"%d\t%lf\n",k,Yre[k]);
	}

	double Unum[256]={0};
	double Ure[256]={0};
	for(int j=0;j<width*height/4;j++)
	{
		u=UU[j];
		Unum[u]++;
	}
	for(int k=0;k<256;k++)
	{
		Ure[k]=Unum[k]/(width*height/4);
		fprintf(U,"%d\t%lf\n",k,Ure[k]);
	}

	double Vnum[256]={0};
	double Vre[256]={0};
	for(int j=0;j<width*height/4;j++)
	{
		v=VV[j];
		Vnum[v]++;
	}
	for(int k=0;k<256;k++)
	{
		Vre[k]=Vnum[k]/(width*height/4);
		fprintf(V,"%d\t%lf\n",k,Vre[k]);
	}

	//计算分量熵值
	double H_Y=0,H_U=0,H_V=0;
	for(int i=0;i<256;i++)
	{
		if(Yre[i]!=0)
		{
			H_Y=H_Y-Yre[i]*(log(Yre[i])/log(double(2)));
		}
		if(Ure[i]!=0)
		{
			H_U=H_U-Ure[i]*(log(Ure[i])/log(double(2)));
		}
		if(Vre[i]!=0)
		{
			H_V=H_V-Vre[i]*(log(Vre[i])/log(double(2)));
		}
	}
	printf("Y的熵=%f\n",H_Y);
	printf("U的熵=%f\n",H_U);
	printf("V的熵=%f\n",H_V);

	free(YUV_buffer);
	fclose(p_yuv);
	fclose(Y);
	fclose(U);
	fclose(V);
	system("pause");
	return 0;
}		

四、结果分析

(一)down.rgb文件
输出的熵值结果:
RGB熵值
R、G、B统计概率分布的txt文件:(部分截图)
R概率分布
G概率分布
B概率分布
将三个txt文件导入excel,并绘制折线图:
RGB概率折线图

(二)down.yuv文件
输出的熵值结果:
YUV熵值
Y、U、V统计概率分布的txt文件:(部分截图)
Y概率分布
U概率分布
V概率分布
将三个txt文件导入excel,并绘制折线图:
YUV概率折线图
结果分析:

  • 由程序运行结果可知,RGB三个通道的熵值比YUV三个通道的熵值大。
  • 由折线图可知,RGB三个分量的概率分布比YUV三个分量的概率分布更均匀。
  • 即RGB去相关性更好,YUV冗余度更大。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值