分析rgb和yuv文件三个通道的概率分布并计算各自的熵
可知RGB分别有256×256=65536个,排列为BGRBGRBGR…的形式,rgb分别距离自己的前一个数据偏移量为3,rgb图像总共256×256×3个像素。
可知UV分量是Y分量的1/4,即256×256÷4=16384个;U的首数据距离第一个数据的偏移量为256×256;V的首数据距离第一个数据的偏移量为256×256×(1+1/4)=81920;yuv图像总共256×256×(1+1/2)=98304个像素。
根据这些偏移量,可以利用循环和数组的基本思想求得每个通道的概率分布。
读取和写入文件的方式参考《数字视音频处理实验一》,因此采用fread、fwrite、fopen、fclose来实现文件的读取、写入、打开、关闭的操作。
注:后续发现fwrite写入不成功
rgb文件
#include
#include
using namespace std;
int main()
{
//定义宽高
int w = 256;
int h = 256;
//动态分配地址,定义BGR三通道分量
unsigned char *BGR_buffer=(unsigned char *)malloc(sizeof(unsigned char) * w*h*3);
unsigned char B_buffer[256*256]={
0};
unsigned char G_buffer[256*256]={
0};
unsigned char R_buffer[256*256]={
0};
//设置文件指针
FILE *fp;
FILE *fp_B;
FILE *fp_G;
FILE *fp_R;
//指针指向rgb文件和三个新建的txt文件
fopen_s(&fp,"C:\\Users\\user\\Desktop\\down.rgb", "rb");
fopen_s(&fp_B,"C:\\Users\\user\\Desktop\\R.txt", "w");
fopen_s(&fp_G,"C:\\Users\\user\\Desktop\\G.txt", "w");
fopen_s(&fp_R,"C:\\Users\\user\\Desktop\\B.txt", "w");
//读文件
fread(BGR_buffer,sizeof(unsigned char), w*h*3,fp);
//memcpy(BGR_buffer, w*h*3); //检验文件打开是否成功
//将数据读入三个数组中
for(int i=0,j=0;i<w*h*3;i=i+3,j++)//RGB分别与相邻数据偏移3
{
B_buffer[j]=*(BGR_buffer+i);
G_buffer[j]=*(BGR_buffer+i+1);
R_buffer[j]=*(BGR_buffer+i+2);
}
//计算三个通道的频数
double B[256]={
0},G[256]={
0},R[256]={
0};//有256种不同灰度级
for(int i=0;i<w*h;i++)
{
B[B_buffer[i]]++;//计算每相同灰度级的出现次数
G[G_buffer[i]]++;
R[R_buffer[i]]++;
}
//计算三个通道的概率
double Bp[256]={
0},Gp[256]={
0},Rp[256]={
0};
for(int i=0;i<256;i++)
{
Bp[i]=B[i]/(w*h);
Gp[i]=G[i]/(w*h);
Rp[i]=R[i]/(w*h);
}
//写文件
fwrite(Bp,sizeof(unsigned char), 256, fp_B);
fwrite(Gp,sizeof(unsigned char), 256, fp_G);
fwrite(Rp,sizeof(unsigned char), 256,fp_R);
//计算熵
double Bs=0,Gs=0,Rs=0;
for(int i=0;i<256;i++)
{
if (Bp[i] != 0) {
Bs += -Bp[i]*log(Bp[i])/log(double(2));}
if (Gp[i] != 0) {
Gs += -Gp[i]*log(Gp[i])/log(double(2));}
if (Rp[i] != 0) {
Rs += -Rp[i]*log(Rp[i])/log(double(2));}
}
cout<<"B的熵:"<<Bs<<endl;
cout<<"G的熵:"<<Gs<<endl;
cout<<"R的熵:"<<Rs<<endl;
//关文件
fclose(fp);
fclose(fp_B);
fclose(fp_G);
fclose(fp_R);
//释放文件
free(BGR_buffer);
system("pause");
return 0;
}
yuv文件
#include
#include
using namespace std;
int main()
{
//定义宽高
int w = 256;
int h = 256;
//动态分配地址,定义YUV三通道分量
unsigned char *YUV_buffer=(unsigned char *)malloc(sizeof(unsigned char) * 98304);
unsigned char Y_buffer[256*256]={
0};
unsigned char U_buffer[16384]={
0};//Y的1/4
unsigned char V_buffer[16384]={
0};
//设置文件指针
FILE *fp;
FILE *fp_Y;
FILE *fp_U;
FILE *fp_V;
//指针指向yuv文件和三个新建的txt文件
fopen_s(&fp,"C:\\Users\\user\\Desktop\\down.yuv", "rb");
fopen_s(&fp_Y,"C:\\Users\\user\\Desktop\\Y.txt", "w");
fopen_s(&fp_U,"C:\\Users\\user\\Desktop\\U.txt", "w");
fopen_s(&fp_V,"C:\\Users\\user\\Desktop\\V.txt", "w");
//读文件
fread(YUV_buffer,sizeof(unsigned char), 98304,fp);
//memcpy(YUV_buffer, 98304); //检验文件打开是否成功
//将数据读入三个数组中
for(int i=0;i<w*h;i++)//Y从1~256*256
{
Y_buffer[i]=*(YUV_buffer+i);
}
for(int i=w*h;i<81920;i++)//U从256*256~256*256*(1+1/4)
{
U_buffer[i-256*256]=*(YUV_buffer+i);
}
for(int i=81920;i<98304;i++)//V从256*256*(1+1/4)~256*256*(1+1/2)
{
V_buffer[i-81920]=*(YUV_buffer+i);
}
//计算三个通道的频数
double Y[256]={
0},U[256]={
0},V[256]={
0};//有256种不同灰度级
for(int i=0;i<w*h;i++)
{
Y[Y_buffer[i]]++;//计算每相同灰度级的出现次数
}
for(int i=0;i<16384;i++)
{
U[U_buffer[i]]++;
V[V_buffer[i]]++;
}
//计算三个通道的概率
double Yp[256]={
0},Up[256]={
0},Vp[256]={
0};
for(int i=0;i<256;i++)
{
Yp[i]=Y[i]/(w*h);
Up[i]=U[i]/16384;
Vp[i]=V[i]/16384;
}
//写文件
fwrite(Yp,sizeof(unsigned char), 256, fp_Y);
fwrite(Up,sizeof(unsigned char), 256, fp_U);
fwrite(Vp,sizeof(unsigned char), 256,fp_V);
//计算熵
double Ys=0,Us=0,Vs=0;
for(int i=0;i<256;i++)
{
if (Yp[i] != 0) {
Ys += -Yp[i]*log(Yp[i])/log(double(2));}
if (Up[i] != 0) {
Us += -Up[i]*log(Up[i])/log(double(2));}
if (Vp[i] != 0) {
Vs += -Vp[i]*log(Vp[i])/log(double(2));}
}
cout<<"Y的熵:"<<Ys<<endl;
cout<<"U的熵:"<<Us<<endl;
cout<<"V的熵:"<<Vs<<endl;
//关文件
fclose(fp);
fclose(fp_Y);
fclose(fp_U);
fclose(fp_V);
//释放文件
free(YUV_buffer);
system("pause");
return 0;
}
fwrite&fprintf:
使用fwrite写入得到的txt文件是乱码,于是查资料发现fwrite函数的数据是以二进制方式写入的 ,而fprintf是将格式化的数据写入文件,因此参考csdn上其他博主的fprintf写法,修改如下:
fprintf(fp_B, "灰度值\t概率\n");
for (int i = 0; i < 256; i++)
{
fprintf(fp_B, "%d\t%f\n", i, Bp[i]);
}
fprintf(fp_G, "灰度值\t概率\n");
for (int i = 0; i < 256; i++)
{
fprintf(fp_G, "%d\t%f\n", i, Gp[i]);
}
fprintf(fp_R, "灰度值\t概率\n");
for (int i = 0; i < 256; i++)
{
fprintf(fp_R, "%d\t%f\n", i, Rp[i]);
}
fprintf(fp_Y, "灰度值\t概率\n");
for (int i = 0; i < 256; i++)
{
fprintf(fp_Y, "%d\t%f\n", i, Yp[i]);
}
fprintf(fp_U, "灰度值\t概率\n");
for (int i = 0; i < 256; i++)
{
fprintf(fp_U, "%d\t%f\n", i, Up[i]);
}
fprintf(fp_V, "灰度值\t概率\n");
for (int i = 0; i < 256; i++)
{
fprintf(fp_V, "%d\t%f\n", i, Vp[i]);
}
最终获得了rgb和yuv的概率分布表txt文件。
txt文件如图:(以B.txt为例)