目录
一.实验目的:
对所给的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分量,
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-蓝)
四.实验结果与分析:
- 由实验结果熵值可知rgb文件的熵值总体大于yuv文件,由公式可得rgb文件剩余度更小。
- 从实验统计的频率图也可以看出yuv文件更加分散因此其熵值更小,与计算结果相一致。