python
复制代码
import numpy as np
from collections import Counter
import heapq
import os
from PIL import Image
# 加载上传的图像
image_path = "图像原图.bmp"
image = Image.open(image_path)
# 将原始图像转换为RGB(以保留颜色信息)
rgb_image_data = np.array(image)
# 对彩色图像进行霍夫曼编码
def huffman_encoding_rgb(data):
data_flat = data.reshape(-1, data.shape[2])
freq = Counter(tuple(pixel) for pixel in data_flat)
# 为霍夫曼编码创建最小堆
heap = [[weight, [symbol, ""]] for symbol, weight in freq.items()]
heapq.heapify(heap)
while len(heap) > 1:
lo = heapq.heappop(heap)
hi = heapq.heappop(heap)
for pair in lo[1:]:
pair[1] = '0' + pair[1]
for pair in hi[1:]:
pair[1] = '1' + pair[1]
heapq.heappush(heap, [lo[0] + hi[0]] + lo[1:] + hi[1:])
huffman_code = dict(sorted(heap[0][1:], key=lambda p: p[0]))
encoded_data = ''.join([huffman_code[tuple(pixel)] for pixel in data_flat])
return huffman_code, encoded_data
# 解码霍夫曼编码后的RGB图像数据
def decode_huffman_rgb(encoded_data, huffman_code, image_shape):
reverse_code = {v: k for k, v in huffman_code.items()}
decoded_data = []
temp_code = ''
for bit in encoded_data:
temp_code += bit
if temp_code in reverse_code:
decoded_data.append(reverse_code[temp_code])
temp_code = ''
return np.array(decoded_data).reshape(image_shape)
# 保存编码后的数据到文件
def save_encoded_data(filename, encoded_data):
with open(filename, 'w') as f:
f.write(encoded_data)
output_dir = os.path.join(os.path.dirname(image_path), "compressed_files")
os.makedirs(output_dir, exist_ok=True)
huffman_code_rgb, encoded_data_rgb = huffman_encoding_rgb(rgb_image_data)
huffman_encoded_filename = os.path.join(output_dir, "霍夫曼编码后的文件.txt")
save_encoded_data(huffman_encoded_filename, encoded_data_rgb)
decoded_huffman_rgb_image_data = decode_huffman_rgb(encoded_data_rgb, huffman_code_rgb, rgb_image_data.shape)
decoded_huffman_rgb_image = Image.fromarray(decoded_huffman_rgb_image_data.astype(np.uint8))
huffman_decoded_rgb_image_filename = os.path.join(output_dir, "霍夫曼解码后的图片.bmp")
decoded_huffman_rgb_image.save(huffman_decoded_rgb_image_filename)
# 计算压缩比、比特率、信噪比
# 计算原始图像的大小(单位:比特)
original_size_bits = rgb_image_data.size * 8 # 每个像素3个通道,每个通道8位
# 计算霍夫曼编码后的文件大小(单位:比特)
huffman_encoded_size_bits = len(encoded_data_rgb)
# 计算压缩比
compression_ratio = original_size_bits / huffman_encoded_size_bits
# 计算比特率
bit_rate = huffman_encoded_size_bits / rgb_image_data.size # 每个像素的比特数
# 计算信噪比(SNR)
# 计算均方误差(MSE)
mse = np.mean((rgb_image_data - decoded_huffman_rgb_image_data) ** 2)
# 计算信号的方差(原始图像的方差)
signal_variance = np.var(rgb_image_data)
# 计算SNR
snr = 10 * np.log10(signal_variance / mse)
# 输出计算结果
print("压缩比:", compression_ratio)
print("比特率:", bit_rate)
print("信噪比 (SNR):", snr)
# 返回保存文件的路径供下载
huffman_encoded_filename, huffman_decoded_rgb_image_filename