-
Notifications
You must be signed in to change notification settings - Fork 0
/
huffman.py
117 lines (94 loc) · 3.69 KB
/
huffman.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import heapq
from collections import defaultdict
from PIL import Image
import pickle
# Node của cây Huffman
class HuffmanNode:
def __init__(self, pixel, freq):
self.pixel = pixel
self.freq = freq
self.left = None
self.right = None
# Định nghĩa để heapq có thể so sánh các node
def __lt__(self, other):
return self.freq < other.freq
# Xây dựng cây Huffman từ tần số xuất hiện của các pixel
def build_huffman_tree(frequency):
heap = []
for pixel, freq in frequency.items():
heapq.heappush(heap, HuffmanNode(pixel, freq))
while len(heap) > 1:
node1 = heapq.heappop(heap)
node2 = heapq.heappop(heap)
merged = HuffmanNode(None, node1.freq + node2.freq)
merged.left = node1
merged.right = node2
heapq.heappush(heap, merged)
return heap[0] if heap else None
# Tạo bảng mã từ cây Huffman
def build_codes(node, current_code, codes):
if node is None:
return
if node.pixel is not None:
codes[node.pixel] = current_code
return
build_codes(node.left, current_code + "0", codes)
build_codes(node.right, current_code + "1", codes)
# Mã hóa dữ liệu ảnh
def huffman_encode(image_path, encoded_path, codebook_path):
image = Image.open(image_path).convert('L') # Chuyển ảnh sang grayscale
pixels = list(image.getdata())
frequency = defaultdict(int)
for pixel in pixels:
frequency[pixel] += 1
root = build_huffman_tree(frequency)
codes = {}
build_codes(root, "", codes)
# Mã hóa dữ liệu
encoded_data = ''.join([codes[pixel] for pixel in pixels])
# Lưu bảng mã và dữ liệu mã hóa
with open(codebook_path, 'wb') as f:
pickle.dump(codes, f)
with open(encoded_path, 'w') as f:
f.write(encoded_data)
print("Mã hóa hoàn tất!")
# Giải mã dữ liệu ảnh
def huffman_decode(encoded_path, codebook_path, output_image_path, image_size):
# Tải bảng mã
with open(codebook_path, 'rb') as f:
codes = pickle.load(f)
# Đảo bảng mã để dễ dàng tìm kiếm
inverse_codes = {v: k for k, v in codes.items()}
# Đọc dữ liệu mã hóa
with open(encoded_path, 'r') as f:
encoded_data = f.read()
decoded_pixels = []
current_code = ""
for bit in encoded_data:
current_code += bit
if current_code in inverse_codes:
decoded_pixels.append(inverse_codes[current_code])
current_code = ""
if len(decoded_pixels) == image_size[0] * image_size[1]:
break
# Tạo ảnh từ dữ liệu giải mã
decoded_image = Image.new('L', image_size)
decoded_image.putdata(decoded_pixels)
decoded_image.save(output_image_path)
print("Giải mã hoàn tất! Ảnh đã được lưu tại:", output_image_path)
# Ví dụ sử dụng
if __name__ == "__main__":
# Đường dẫn tới ảnh gốc
original_image = 'bitplaneslicing.png' # Thay thế bằng đường dẫn tới ảnh của bạn
# Đường dẫn lưu dữ liệu mã hóa và bảng mã
encoded_file = 'encoded.bin'
codebook_file = 'codebook.pkl'
# Đường dẫn lưu ảnh giải mã
decoded_image = 'decoded_image_huffman.png'
# Mã hóa ảnh
huffman_encode(original_image, encoded_file, codebook_file)
# Giải mã ảnh
# Cần biết kích thước ảnh gốc để giải mã chính xác
image = Image.open(original_image)
image_size = image.size # (width, height)
huffman_decode(encoded_file, codebook_file, decoded_image, image_size)