写一个对输入的图像进行哈夫曼编码,显示原图像的熵,编码后的平均码字长度及编码效率的c++代码
时间: 2024-03-10 18:48:27 浏览: 21
以下是对输入图像进行哈夫曼编码的C++代码,同时显示原图像的熵、编码后的平均码字长度和编码效率:
```c++
#include <iostream>
#include <fstream>
#include <queue>
#include <vector>
#include <map>
#include <cmath>
using namespace std;
//定义哈夫曼树节点结构体
struct HuffmanNode
{
int data;
int weight;
HuffmanNode *left;
HuffmanNode *right;
HuffmanNode(int d, int w) : data(d), weight(w), left(NULL), right(NULL) {}
};
//定义比较结构体,用于构建哈夫曼树时的优先队列
struct cmp
{
bool operator()(HuffmanNode *a, HuffmanNode *b) { return a->weight > b->weight; }
};
//计算图像的熵
double calcEntropy(map<int, int> histogram, int total)
{
double entropy = 0;
for (auto &p : histogram)
{
double prob = (double)p.second / total;
entropy += (-1) * prob * log2(prob + (prob == 0));
}
return entropy;
}
//构建哈夫曼树
HuffmanNode *buildHuffmanTree(map<int, int> histogram)
{
priority_queue<HuffmanNode *, vector<HuffmanNode *>, cmp> pq;
for (auto &p : histogram) pq.push(new HuffmanNode(p.first, p.second));
while (pq.size() > 1)
{
HuffmanNode *left = pq.top();
pq.pop();
HuffmanNode *right = pq.top();
pq.pop();
HuffmanNode *parent = new HuffmanNode(-1, left->weight + right->weight);
parent->left = left;
parent->right = right;
pq.push(parent);
}
return pq.top();
}
//计算编码后的平均码字长度
double calcAverageLength(HuffmanNode *root, int total)
{
if (!root) return 0;
double averageLength = 0;
queue<HuffmanNode *> q;
q.push(root);
while (!q.empty())
{
HuffmanNode *cur = q.front();
q.pop();
if (!cur->left && !cur->right)
averageLength += (double)cur->weight / total * (int)log2(total / cur->weight);
if (cur->left) q.push(cur->left);
if (cur->right) q.push(cur->right);
}
return averageLength;
}
//编码图像
void encodeImage(map<int, int> histogram, HuffmanNode *root, map<int, string> &codeTable, vector<string> &encodedImage)
{
for (auto &p : histogram)
{
int data = p.first;
string code = "";
HuffmanNode *cur = root;
while (cur)
{
if (cur->left && cur->left->data == data)
{
code += "0";
break;
}
else if (cur->right && cur->right->data == data)
{
code += "1";
break;
}
else if (cur->left && cur->left->weight >= p.second)
{
cur = cur->left;
code += "0";
}
else if (cur->right && cur->right->weight >= p.second)
{
cur = cur->right;
code += "1";
}
}
codeTable[data] = code;
}
for (auto &p : histogram)
encodedImage.push_back(codeTable[p.first]);
}
//计算编码效率
double calcEfficiency(map<int, int> histogram, vector<string> encodedImage, int total)
{
int size = 0;
for (auto &code : encodedImage) size += code.length();
return (double)total * 8 / size;
}
int main()
{
//读入图像
ifstream fin("input.bmp", ios::binary);
fin.seekg(0, ios::end);
int fileSize = fin.tellg();
fin.seekg(54, ios::beg);
map<int, int> histogram;
int total = 0;
char pixel;
while (fin.read(&pixel, sizeof(char)))
{
histogram[pixel]++;
total++;
}
fin.close();
//计算熵
double entropy = calcEntropy(histogram, total);
cout << "Entropy: " << entropy << endl;
//构建哈夫曼树
HuffmanNode *root = buildHuffmanTree(histogram);
//计算编码后的平均码字长度
double averageLength = calcAverageLength(root, total);
cout << "Average Length: " << averageLength << endl;
//编码图像
map<int, string> codeTable;
vector<string> encodedImage;
encodeImage(histogram, root, codeTable, encodedImage);
//计算编码效率
double efficiency = calcEfficiency(histogram, encodedImage, total);
cout << "Efficiency: " << efficiency << endl;
return 0;
}
```
注:该代码实现了对 BMP 格式图像进行哈夫曼编码,需要将输入图像命名为 "input.bmp" 并与代码放在同一目录下。如需对其他格式图像编码,需要根据实际情况修改代码。