编写一个对输入的图像进行哈夫曼编码,显示原图像的熵,编码后 的平均码子长度以及编码效率的代码
时间: 2023-07-19 14:30:46 浏览: 49
以下是一个Python代码示例,用于对输入图像进行哈夫曼编码,并计算原图像的熵,编码后的平均码字长度以及编码效率。
```python
import numpy as np
from PIL import Image
import heapq
import os
class Node:
def __init__(self, freq, value=None):
self.freq = freq
self.value = value
self.left = None
self.right = None
def __lt__(self, other):
return self.freq < other.freq
def calc_freq(img):
# 计算图像中每个像素值的频率
freq = np.zeros(256, dtype=int)
for row in range(img.shape[0]):
for col in range(img.shape[1]):
freq[img[row][col]] += 1
return freq
def build_tree(freq):
# 构建哈夫曼树
heap = [Node(freq[i], i) for i in range(256)]
heapq.heapify(heap)
while len(heap) > 1:
node1 = heapq.heappop(heap)
node2 = heapq.heappop(heap)
merged = Node(node1.freq + node2.freq)
merged.left = node1
merged.right = node2
heapq.heappush(heap, merged)
return heap[0]
def build_codebook(node, codebook, code_str):
# 构建编码表
if node is None:
return
if node.value is not None:
codebook[node.value] = code_str
build_codebook(node.left, codebook, code_str + "0")
build_codebook(node.right, codebook, code_str + "1")
def encode(img, codebook):
# 对图像进行编码
encoded_str = ""
for row in range(img.shape[0]):
for col in range(img.shape[1]):
encoded_str += codebook[img[row][col]]
return encoded_str
def decode(encoded_str, root):
# 对编码后的字符串进行解码
decoded_img = np.zeros((512, 512), dtype=int)
node = root
for i in range(len(encoded_str)):
if encoded_str[i] == "0":
node = node.left
else:
node = node.right
if node.value is not None:
decoded_img[i // 512][i % 512] = node.value
node = root
return decoded_img
if __name__ == "__main__":
img = np.array(Image.open("lena.png").convert("L"))
freq = calc_freq(img)
root = build_tree(freq)
codebook = {}
build_codebook(root, codebook, "")
encoded_str = encode(img, codebook)
decoded_img = decode(encoded_str, root)
# 计算原图像的熵
p = freq / np.sum(freq)
entropy = -np.sum(p * np.log2(p))
# 计算编码后的平均码字长度
avg_len = 0
for i in range(256):
if freq[i] > 0:
avg_len += freq[i] * len(codebook[i])
avg_len /= img.shape[0] * img.shape[1]
# 计算编码效率
original_size = os.path.getsize("lena.png")
encoded_size = (len(encoded_str) + 7) // 8
efficiency = encoded_size / original_size
print("Entropy: {:.4f} bits/pixel".format(entropy))
print("Average codeword length: {:.4f} bits".format(avg_len))
print("Efficiency: {:.4f}".format(efficiency))
```
需要注意的是,此示例仅适用于灰度图像。对于彩色图像,需要对每个颜色通道分别进行哈夫曼编码。另外,编码后的字符串长度可能不是8的倍数,需要在末尾补0,以便于解码。