提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
一、实验目的
给定两图片down.rgb和down.yuv,分辨率为256*256,色度采样格式4:2:0,统计RGB和YUV图像文件各分类的概率分布,并求出熵
二、实验思路(以rgb文件为例)
1.文件导入
设置好图片的长宽:256*256,初始化r、g、b分量灰度值范围:0-65535,初始化r、g、b频率分量范围:0-256,初始化r、g、b分量的熵
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 r_f[256] = { 0 };
double g_f[256] = { 0 };
double b_f[256] = { 0 };
double h_r = 0, h_g = 0, h_b = 0; //熵
FILE* fp1, * rgb; //设置文件指针,以便打开文件
fopen_s(&fp1, "C:/Users/shl/source/repos/one/down.rgb", "rb");
fopen_s(&rgb, "C:/Users/shl/source/repos/one/rgb.txt", "w");
2.读入数据
对三通道的每个像素的灰度值进行读取和记数,rgb文件按B、G、R的顺序循环,上至下左至右逐行扫描。
//依次读取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)) { r_f[i]++; }
if (int(g[j] == i)) { g_f[i]++; }
if (int(b[j] == i)) { b_f[i]++; }
}
}
3.计算各分量的熵(显示出来)
先求出各分量中的频率分布情况,再依照公式求熵
//频率
for (int i = 0; i < 256; i++)
{
r_f[i] = r_f[i] / double(width * height);
g_f[i] = g_f[i] / double(width * height);
b_f[i] = b_f[i] / double(width * height);
}
//计算熵
for (int i = 0; i < 256; i++)
{
if (r_f[i] != 0) { h_r += r_f[i] * (log(1 / r_f[i]) / log(2.0)); }
if (g_f[i] != 0) { h_g += g_f[i] * (log(1 / g_f[i]) / log(2.0)); }
if (b_f[i] != 0) { h_b += b_f[i] * (log(1 / b_f[i]) / log(2.0)); }
}
cout << "r熵为" << h_r << endl;
cout << "g熵为" << h_g << endl;
cout << "b熵为" << h_b << endl;
4.将结果写入新文件
//由频率数值写三个文件
fprintf(rgb, "红色\t绿色\t蓝色\n");
for (int i = 0; i < 256; i++)
{
fprintf(rgb, "%f\t%f\t%f\n",r_f[i], g_f[i], b_f[i]);
}
fclose(fp1);
fclose(rgb);
system("pause");
5.YUV文件同理
说明:图像分辨率为256*256,色度取样格式为4:2:0,
Y所占字节数为65536,U、V各是Y数量的1/4,即各16384个。
根据yuv文件存储格式:先存所有Y,再存所有U,再存所有V,上至下左至右扫描可知:
Y的[0,65534]对应文件的[0,65534]
U的[0,16383]对应文件的[65535,81919]
V的[0,16383]对应文件的[81920,98303]
图像所占总字节数为98304
#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 y[65535] = { 0 };
unsigned char u[16383] = { 0 };
unsigned char v[16383] = { 0 };
//频率分量
double y_f[256] = { 0 };
double u_f[256] = { 0 };
double v_f[256] = { 0 };
double h_y = 0, h_u = 0, h_v = 0; //熵
FILE* fp1, * yuv; //设置文件指针,以便打开文件
fopen_s(&fp1, "C:/Users/shl/source/repos/one/down.yuv", "rb");
fopen_s(&yuv, "C:/Users/shl/source/repos/one/yuv.txt", "w");
//依次读取Y,U,V
unsigned char a[196608];
fread(a, sizeof(unsigned char), 196608, fp1);
for (int i = 0, j = 0; i < 65536; i++, j++)
{
y[j] = a[i];
}
for (int i = 65535, j = 0; i < 81920; i++, j++)
{
u[j] = a[i];
}
for (int i = 81920, j = 0; i < 98304; i++, j++)
{
v[j] = a[i];
}
//三通道计数
for (i = 0; i < 256; i++)
{
for (int j = 0; j < 65536; j++)
{
if (int(y[j] == i)) { y_f[i]++; }
}
for (int j = 0; j < 16383; j++)
{
if (int(u[j] == i)) { u_f[i]++; }
}
for (int j = 0; j < 16383; j++)
{
if (int(v[j] == i)) { v_f[i]++; }
}
}
//频率
for (int i = 0; i < 256; i++)
{
y_f[i] = y_f[i] / double(width * height);
u_f[i] = u_f[i] / double(width * height)*4;
v_f[i] = v_f[i] / double(width * height)*4;
}
//计算熵
for (int i = 0; i < 256; i++)
{
if (y_f[i] != 0) { h_y += y_f[i] * (log(1 / y_f[i]) / log(2.0)); }
if (u_f[i] != 0) { h_u += u_f[i] * (log(1 / u_f[i]) / log(2.0)); }
if (v_f[i] != 0) { h_v += v_f[i] * (log(1 / v_f[i]) / log(2.0)); }
}
cout << "y熵为" << h_y << endl;
cout << "u熵为" << h_u << endl;
cout << "v熵为" << h_v << endl;
//由频率数值写三个文件
fprintf(yuv, "Y\tU\tV\n");
for (int i = 0; i < 256; i++)
{
fprintf(yuv, "%f\t%f\t%f\n", y_f[i], u_f[i], v_f[i]);
}
fclose(fp1);
fclose(yuv);
system("pause");
return 0;
}
三、实验结果
1.得到六个熵结果及生成两个txt文件
2.利用作图工具将两个txt文件转化为图像
三、总结
分析实验结果:rgb文件的U、V分量相比yuv文件的U、V分量,熵明显大,说明了yuv文件冗余度更大一些,rgb文件的去相关性反而更好
遇到的问题:编程语言运用不熟,不过结构理解没问题。要了解rgb文件与yuv文件的储存格式。要了解熵的运算公式。