yuv和rgb文件分量的概率分布及熵值的计算

目录

 

一.实验目的:

二.实验原理:

三.实验步骤:

四.实验结果与分析:


一.实验目的:

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

二.实验原理:

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

三.实验步骤:

1.特殊值计算:

YUV 4:2:0采样,则每四个Y共用一组UV分量;YUV文件分辨率为256*256,三个部分之间按顺序存储为:

YUV数据的0--256*256字节为Y分量,

扫描二维码关注公众号,回复: 12722130 查看本文章

256*256--256*256*5/4字节为U分量,

256*256*5/4--256*256*3/2为V分量。

所以每个像素占24bits=3bytes,图像共256*256*3=196608。

2.编程实现:(使用C++统计分量并求概率及熵值)

(1)yuv:

先根据之前计算设置变量和全局常量:

#define A  65536
#define B  16384
#define C  98304
int main()
{
 //读取文件
 FILE* photo, * y, * u, * v;
 fopen_s(&photo, "I:\\数据压缩\\down.yuv", "rb");
 fopen_s(&y, "I:\\数据压缩\\y.txt", "w");
 fopen_s(&u, "I:\\数据压缩\\u.txt", "w");
 fopen_s(&v, "I:\\数据压缩\\v.txt", "w");
 //定义三分量,频率分量,熵值
 unsigned char Y[A] = { 0 }, U[B] = { 0 }, V[B] = { 0 };
 double y_F[256] = { 0 }, u_F[256] = { 0 }, v_F[256] = { 0 };
 double y_S = 0, u_S = 0, v_S = 0;
 ​

设置循环将文件分量读取到数组中:

unsigned char sum[C];
 fread(sum, 1, C, photo);
 for (int i = 0, j = 0; i < A; i = i + 1, j++)
 {
  Y[j] = *(sum + i);
 }
 for (int i = A, j = 0; i < A + B; i = i + 1, j++)
 {
  U[j] = *(sum + i);
 }
 for (int i = A + B, j = 0; i < C; i = i + 1, j++)
 {
  V[j] = *(sum + i);
 }

循环统计颜色次数并计算频率值:

//求各颜色次数
 for (int i = 0; i < 256; i++)
 {
  for (int j = 0; j < A; j++)
  {
   if (int(Y[j] == i))
     { 
        y_F[i]++;
     }

  }
 }
 for (int i = 0; i < 256; i++)
 {
  for (int j = 0; j < B; j++)
  {
   if (int(U[j] == i)) 
    { 
        u_F[i]++; 
    }
   if (int(V[j] == i)) 
    {
         v_F[i]++;
     }

  }
 }

 //求出各频率
 for (int i = 0; i < 256; i++)
 {
  y_F[i] = y_F[i] / (256 * 256);
  u_F[i] = u_F[i] / (256 * 256 / 4);
  v_F[i] = v_F[i] / (256 * 256 / 4);
 }

根据公式计算熵值:

//计算熵
 for (int i = 0; i < 256; i++)
 {
  if (y_F[i] != 0) { y_S += -y_F[i] * log(y_F[i]) / log(2); }
  if (u_F[i] != 0) { u_S += -u_F[i] * log(u_F[i]) / log(2); }
  if (v_F[i] != 0) { v_S += -v_F[i] * log(v_F[i]) / log(2); }
 }
 cout << "Y熵=" << y_S << endl;
 cout << "U熵=" << u_S << endl;
 cout << "V熵=" << v_S << endl;

将统计数值写入文档保存:

for (int i = 0; i < 256; i++)
 {
  fprintf(y, "%d\t%f\n", i, y_F[i]);
 }
 for (int i = 0; i < 256; i++)
 {
  fprintf(u, "%d\t%f\n", i, u_F[i]);
 }
 for (int i = 0; i < 256; i++)
 {
  fprintf(v, "%d\t%f\n", i, v_F[i]);
 }

 

 

 

 

(2)rgb:

代码与yuv差不多,在其基础上稍作改变即可:

//分别读取R、G、B三个分量到数组中
 unsigned char sum[256 * 256 * 3];
 fread(sum, 1, 256 * 256 * 3,photo);
 for (int i = 0, j = 0; i < 256 * 256 * 3; i = i + 3, j++)
 {
  B[j] = *(sum + i);
  G[j] = *(sum + i + 1);
  R[j] = *(sum + i + 2);
 }

3.绘制概率分布图:(使用matlab的导入数据功能将.txt文件数据导入进行绘制)

(1)yuv分量概率分布图:(y-红,u-绿,v-蓝)因为图例设置老是出错,这里只能手动替代。

 

(2)rgb分量概率分布图:(r-红,g-绿,b-蓝)

 

 

四.实验结果与分析:

  1. 由实验结果熵值可知rgb文件的熵值总体大于yuv文件,由公式可得rgb文件剩余度更小。
  2. 从实验统计的频率图也可以看出yuv文件更加分散因此其熵值更小,与计算结果相一致。

猜你喜欢

转载自blog.csdn.net/qq_44018041/article/details/114463034