求RGB图像各分量的概率分布和熵

求RGB图像各分量的概率分布和熵

功能

该程序可以实现读入一个24bit RGB文件(以down.rgb为例,分辨率为256×256),计算R、G、B三个分量(各8bit表示)的概率分布和熵,并输出到csv(Comma-Separated Values)文件中(相比于txt文件,将csv文件数据导入到Excel中更加方便)。


down.rgb

需要注意的是,与YUV文件不同,RGB文件是按照每个像素的b、g、r分量依次排列而成。

代码

为了清晰,将程序写在globalVariables.hPmf.cppmain.cpp三个文件中。

globalVariables.h

#pragma once
extern const char* inPath;	// 原始图像路径及文件
extern const char* outPathR;	// R分量统计结果
extern const char* outPathG;	// G分量统计结果
extern const char* outPathB;	// B分量统计结果
extern int w;	// 图像宽
extern int h;	// 图像高
void Pmf(unsigned char* buffer,int size, FILE* outFile);

Pmf.cpp

#include <iostream>
#include "globalVariables.h"
using namespace std;

const char* inPath = "C:\\Users\\s.z.zheng\\OneDrive\\文档\\CUC课程 - OD\\大三下学期课程 - OD\\数据压缩原理与应用A - OD\\作业\\作业3:RGB文件的概率分布\\down.rgb";	// 原始图像路径及文件
const char* outPathR = "C:\\Users\\s.z.zheng\\OneDrive\\文档\\CUC课程 - OD\\大三下学期课程 - OD\\数据压缩原理与应用A - OD\\作业\\作业3:RGB文件的概率分布\\down_RStats.csv";	// R分量统计结果
const char* outPathG = "C:\\Users\\s.z.zheng\\OneDrive\\文档\\CUC课程 - OD\\大三下学期课程 - OD\\数据压缩原理与应用A - OD\\作业\\作业3:RGB文件的概率分布\\down_GStats.csv";	// G分量统计结果
const char* outPathB = "C:\\Users\\s.z.zheng\\OneDrive\\文档\\CUC课程 - OD\\大三下学期课程 - OD\\数据压缩原理与应用A - OD\\作业\\作业3:RGB文件的概率分布\\down_BStats.csv";	// B分量统计结果
int w = 256;	// 图像宽
int h = 256;	// 图像高

void Pmf(unsigned char* buffer, int size, FILE* outFile)
{
	int count[256] = { 0 };	// 计数器
	double freq[256] = { 0 };	// 频率
	double entropy = 0;	// 该分量的熵

	// 统计某一分量
	for (int i = 0; i < size / 3; i++)
	{
		int index = (int)buffer[i];
		count[index]++;
	}

	// 计算该分量的频率,并输出该分量
	for (int i = 0; i < 256; i++)
	{
		freq[i] = (double)count[i] / (w * h);	//分子分母都为int型,进行类型转换,保证结果为double类型
		if (freq[i] != 0)
		{
			entropy += (-freq[i]) * log(freq[i]) / log(2);
		}
	}

	fprintf(outFile, "Symbol,Frequency\n");
	for (int i = 0; i < 256; i++)
	{
		fprintf(outFile, "%-3d,%-8.2e\n", i, freq[i]);	// 将数据输出到文件中(csv文件以“,”作为分隔符)
	}
	fprintf(outFile, "%.4lf", entropy);
}

main.cpp

#include <iostream>
#include "globalVariables.h"
using namespace std;

int main()
{
	FILE* img;
	FILE* outR;	// 存储R分量数据的文件
	FILE* outG;	// 存储G分量数据的文件
	FILE* outB;	// 存储B分量数据的文件
	int imgSize;	// 图像总字节数

	// 打开文件
	if (fopen_s(&img, inPath, "rb") == 0)
	{
		cout << "Successfull opened the original image." << endl;
	}
	else
	{
		cout << "Failed to open the original image." << endl;
	}
	fopen_s(&outR, outPathR, "w");
	fopen_s(&outG, outPathG, "w");
	fopen_s(&outB, outPathB, "w");

	// 计算图片总字节数
	fseek(img, 0L, SEEK_END);	// 使文件指针指向文件末尾
	imgSize = ftell(img);	// 文件总字节数
	rewind(img);	// 使文件指针再回到文件起始(若不回到起始,无法将img中的数据读入到缓冲区中)
	cout << "The space that original image accounts for: " << imgSize << " Bytes = " << imgSize / 1024 << " kB" << endl;

	// 建立缓冲区
	unsigned char* imgBuffer = new unsigned char[imgSize];	// 图像缓冲区
	unsigned char* rBuffer = new unsigned char[imgSize / 3];	// R分量缓冲区
	unsigned char* gBuffer = new unsigned char[imgSize / 3];	// G分量缓冲区
	unsigned char* bBuffer = new unsigned char[imgSize / 3];	// B分量缓冲区

	// 将数据读入缓冲区
	fread(imgBuffer, sizeof(unsigned char), imgSize, img);	// 先将全部像素的RGB三个分量读入图像缓冲区
	for (int i = 0; i < imgSize / 3; i++)
	{
		// 再分别将图像缓冲区的内容对应地分配给R、G、B缓冲区(注意:img中存储的顺序为G、B、R)
		bBuffer[i] = imgBuffer[3 * i];
		gBuffer[i] = imgBuffer[3 * i + 1];
		rBuffer[i] = imgBuffer[3 * i + 2];
	}

	// 分别统计R、G、B分量的概率分布
	Pmf(rBuffer, imgSize, outR);
	Pmf(gBuffer, imgSize, outG);
	Pmf(bBuffer, imgSize, outB);

	// 关闭文件
	fclose(img);
	fclose(outR);
	fclose(outG);
	fclose(outB);
	// 释放内存
	delete[]imgBuffer;
	delete[]rBuffer;
	delete[]gBuffer;
	delete[]bBuffer;
}

结果

down_RStats.csvdown_GStats.csvdown_BStats.csv三个文件中的数据拷贝到Excel中,作出图像,如下:


R、G、B各分量概率分布

R、G、B各分量的信源熵
发布了11 篇原创文章 · 获赞 1 · 访问量 1238

猜你喜欢

转载自blog.csdn.net/szzheng/article/details/104773222