实验题目
对down.rgb和down.yuv分析三个通道的概率分布,并计算各自的熵。(编程实现)两个文件的分辨率均为256*256,yuv为4:2:0采样空间,存储格式为:rgb文件按每个像素BGR分量依次存放;YUV格式按照全部像素的Y数据块、U数据块和V数据块依次存放。
down.rgb
- 思路
读入down.rgb文件设为fp1,将三个通道分量频率写为red、green、blue三个txt文件存放,熵值由程序直接输出,频率统计结果导入matlab画图得出。 - 代码实现:
#include<stdio.h>
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int height=256;
int width=256;
int i,j;
//R、G、B分量
unsigned char r[65535]={0};
unsigned char g[65535]={0};
unsigned char b[65535]={0};
//频率分量
double p_r[256]={0};
double p_g[256]={0};
double p_b[256]={0};
double h_r= 0,h_g= 0,h_b= 0; //熵
FILE *fp1,*red,*green,*blue; //设置文件指针,以便打开文件
fopen_s(&fp1, "D://大三下/数据压缩/down.rgb", "rb");
fopen_s(&red, "D://大三下/数据压缩/red.txt","w");
fopen_s(&green, "D://大三下/数据压缩/green.txt","w");
fopen_s(&blue, "D://大三下/数据压缩/blue.txt","w");
//依次读取R、G、B
unsigned char a[196608];
fread(a, sizeof(unsigned char), 196608, fp1);
for (i=0,j=0;i<196608;i=i+3,j++)
{
b[j] = a[i];
g[j] = a[i+1];
r[j] = a[i+2];
}
//三通道计数
for (i = 0; i < 256; i++)
{
for (int j = 0; j < 65536; j++)
{
if (int(r[j] == i)) {p_r[i]++;}
if (int(g[j] == i)) {p_g[i]++;}
if (int(b[j] == i)) {p_b[i]++;}
}
}
//频率
for(int i=0;i<256;i++)
{
p_r[i]=p_r[i]/double(width*height);
p_g[i]=p_g[i]/double(width*height);
p_b[i]=p_b[i]/double(width*height);
}
//计算熵
for (int i = 0; i < 256; i++)
{
if (p_r[i] != 0) {h_r+=p_r[i]*(log(1/p_r[i])/log(2.0));}
if (p_g[i] != 0) {h_g+=p_g[i]*(log(1/p_g[i])/log(2.0));}
if (p_b[i] != 0) {h_b+=p_b[i]*(log(1/p_b[i])/log(2.0));}
}
cout << "r熵为" << h_r << endl;
cout << "g熵为" << h_g << endl;
cout << "b熵为" << h_b << endl;
//由频率数值写三个文件
fprintf(red,"数值\t概率\n");
for(int i=0;i<256;i++)
{
fprintf(red,"%d\t%f\n",i,p_r[i]);
}
fprintf(green,"数值\t概率\n");
for(int i = 0; i < 256; i++)
{
fprintf(green,"%d\t%f\n",i,p_g[i]);
}
fprintf(blue,"数值\t概率\n");
for (int i = 0; i < 256; i++)
{
fprintf(blue,"%d\t%f\n",i,p_b[i]);
}
fclose(fp1);
fclose(red);
fclose(green);
fclose(blue);
system("pause");
return 0;
}
-
代码运行结果
-
-
三个通道频率分布图
(红色为R,绿色为G,蓝色为B)
down.yuv
-
实验思路
读入down.rgb文件设为fp2,将三个通道分量频率写为py、pu、pv三个txt文件存放,熵值由程序直接输出,频率统计结果导入matlab画图得出。 -
代码实现
只需对上述rgb实现代码稍作修改,因为yuv按4:2:0取样,所以u、v各65536/4个。
#include<stdio.h>
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
int i;
//Y、U、V分量
unsigned char y[65535]={0};
unsigned char u[65535/4]={0};
unsigned char v[65535/4]={0};
//频率分量
double p_y[256]={0};
double p_u[256]={0};
double p_v[256]={0};
//熵
double h_y= 0.0,h_u= 0.0,h_v= 0.0;
FILE *fp2,*py,*pu,*pv; //设置文件指针,以便打开文件
fopen_s(&fp2, "D://大三下/数据压缩/down.yuv", "rb");
fopen_s(&py, "D://大三下/数据压缩/py.txt", "w");
fopen_s(&pu, "D://大三下/数据压缩/pu.txt", "w");
fopen_s(&pv, "D://大三下/数据压缩/pv.txt", "w");
//依次读取Y、U、V
unsigned char a[98304];
fread(a, 1, 65535*1.5, fp2);
for (i = 0; i < 65535 ; i++)
{
y[i] = *(a + i);
}
for (i =65535; i < 65535 * 1.25; i++)
{
u[i-65536] = *(a + i);
}
for (i = 65535 * 1.25; i < 65535* 1.5; i++)
{
v[i - 81920] = *(a + i);
}
//三通道计数
for (i = 0; i < 65535; i++)
{
p_y[y[i]]++;
}
for (i = 0; i < (65535/4); i++)
{
p_u[u[i]]++;
p_v[v[i]]++;
}
//频率
for (i = 0; i < 256; i++)
{
p_y[i] = p_y[i] / (65535);
p_u[i] = p_u[i] / (65535/4);
p_v[i] = p_v[i] / (65535/4);
}
//计算熵
for (i = 0; i < 256; i++)
{
if (p_y[i] != 0) { h_y += -p_y[i] * log(p_y[i]) / log(double(2)); }
if (p_u[i] != 0) { h_u += -p_u[i] * log(p_u[i]) / log(double(2)); }
if (p_v[i] != 0) { h_v += -p_v[i] * log(p_v[i]) / log(double(2)); }
}
cout << "y熵为" << h_y << endl;
cout << "u熵为" << h_u << endl;
cout << "v熵为" << h_v << endl;
//由频率数值写三个文件
for (int i = 0; i < 256; i++)
{
fprintf(py, "%d\t%f\n", i, p_y[i]);
fprintf(pu, "%d\t%f\n", i, p_u[i]);
fprintf(pv, "%d\t%f\n", i, p_v[i]);
}
fclose(fp2);
fclose(py);
fclose(pu);
fclose(pv);
system("pause");
return 0;
}
- 运行结果
- 三个通道频率分布图
(红色为Y,绿色为V,蓝色为U)
实验结论
RGB分量的熵大于YUV分量,去相关性更好