Tạm biệt Kang Daniel, khóc xong rồi thì thôi cất gọn poster anh vào góc, mình tạm thời không nhìn nhau anh nhé. Mỗi lần nhìn thấy anh em sợ lại làm tim mình đau hơn. Em không biết em có vượt qua cú sốc này không nữa. Chờ anh nửa năm, để rồi nhận trái đắng như vậy. Album đặt rồi cũng không muốn lấy về nữa. Em chưa đủ chín chắn để chấp nhận sự thật này, chắc là vậy, nên em đành ích kỷ vậy thôi. Chưa được 2 năm mà, anh có cần vội vã hẹn hò vậy không? Cắt đứt liên lạc với mọi người để không liên lụy tới họ nhưng vẫn hẹn hò được ạ? Em cảm thấy như bị lừa vậy, công sức lo lắng cho anh thừa rồi vì anh chắc vẫn luôn hạnh phúc bên ai kia. Vừa showcase gặp fan xong đã đi gặp bạn gái luôn, tình yêu của fan với anh chắc không đủ. Anh thừa biết fan girl là ntn mà 😭, vậy mà anh vẫn như vậy. Tạm biệt anh, cho em ích kỷ lần này nhé. Hẹn gặp lại khi em đã mạnh mẽ hơn, em không quay lưng đi nhưng em sẽ dừng lại.
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
~x^2~
=========================================================
HÀM HIỂN THỊ ẢNH
=========================================================
def show_gray(title, img): plt.figure() plt.title(title) plt.imshow(img, cmap="gray") plt.axis("off")
def show_color(title, img): plt.figure() plt.title(title) plt.imshow(img) plt.axis("off")
=========================================================
HÀM TÍCH CHẬP 2D
=========================================================
def convolve2d(img, kernel): h, w = img.shape kh, kw = kernel.shape pad_h = kh // 2 pad_w = kw // 2
padded = np.pad(img, ((pad_h, pad_h), (pad_w, pad_w)), mode="edge")
result = np.zeros_like(img, dtype=np.float32)
for i in range(h):
for j in range(w):
region = padded[i:i + kh, j:j + kw]
result[i, j] = np.sum(region * kernel)
return np.clip(result, 0, 255).astype(np.uint8)
=========================================================
1. ĐỌC ẢNH
=========================================================
try: img = Image.open("image.png").convert("RGB") except FileNotFoundError: print("Không đọc được ảnh. Kiểm tra lại file image.png") exit()
img = np.array(img) show_color("Original", img)
=========================================================
2. CHUYỂN ẢNH MÀU SANG ẢNH XÁM
Công thức: Gray = 0.299R + 0.587G + 0.114B
=========================================================
r = img[:, :, 0] g = img[:, :, 1] b = img[:, :, 2]
gray = 0.299 r + 0.587 g + 0.114 * b gray = gray.astype(np.uint8)
show_gray("Gray", gray)
print("Ma trận ảnh xám:") print(gray)
=========================================================
3. CHUẨN HÓA PIXEL VỀ [0, 1]
=========================================================
normalized = gray / 255.0
print("\nPixel sau chuẩn hóa:") print(normalized)
=========================================================
4. HISTOGRAM ẢNH XÁM
=========================================================
hist = np.zeros(256, dtype=int)
for value in gray.flatten(): hist[value] += 1
plt.figure() plt.title("Histogram") plt.xlabel("Mức xám") plt.ylabel("Số pixel") plt.plot(hist)
=========================================================
5. CÂN BẰNG HISTOGRAM
=========================================================
cdf = hist.cumsum() cdf_min = cdf[cdf > 0][0]
h, w = gray.shape total_pixels = h * w
equal_map = np.round((cdf - cdf_min) / (total_pixels - cdf_min) * 255) equal_map = np.clip(equal_map, 0, 255).astype(np.uint8)
equal = equal_map[gray]
show_gray("Equalized", equal)
=========================================================
6. ÂM BẢN ẢNH
Công thức: negative = 255 - pixel
=========================================================
negative = 255 - gray show_gray("Negative", negative)
=========================================================
7. TÁCH MÀU RGB
=========================================================
red = img[:, :, 0] green = img[:, :, 1] blue = img[:, :, 2]
show_gray("Red Channel", red) show_gray("Green Channel", green) show_gray("Blue Channel", blue)
=========================================================
8. CẮT ẢNH, XOAY ẢNH, LẬT ẢNH
=========================================================
crop = img[50:200, 50:200] show_color("Crop", crop)
Xoay 90 độ bằng NumPy
rotate_90 = np.rot90(img) show_color("Rotate 90", rotate_90)
Lật ngang, lật dọc
flip_horizontal = np.fliplr(img) flip_vertical = np.flipud(img)
show_color("Flip Horizontal", flip_horizontal) show_color("Flip Vertical", flip_vertical)
=========================================================
9. TẠO NHIỄU MUỐI TIÊU
=========================================================
sp_noise = gray.copy() prob = 0.02 rand = np.random.rand(*gray.shape)
sp_noise[rand < prob / 2] = 0 sp_noise[rand > 1 - prob / 2] = 255
show_gray("Salt Pepper Noise", sp_noise)
=========================================================
10. TẠO NHIỄU GAUSSIAN
=========================================================
noise = np.random.normal(0, 25, gray.shape) gaussian_noise = gray.astype(np.float32) + noise gaussian_noise = np.clip(gaussian_noise, 0, 255).astype(np.uint8)
show_gray("Gaussian Noise", gaussian_noise)
=========================================================
11. LỌC TRUNG BÌNH
=========================================================
kernel_avg = np.ones((3, 3), dtype=np.float32) / 9 average = convolve2d(gray, kernel_avg)
show_gray("Average Filter", average)
=========================================================
12. LỌC GAUSSIAN
=========================================================
kernel_gaussian = np.array([ [1, 2, 1], [2, 4, 2], [1, 2, 1] ], dtype=np.float32) / 16
gaussian = convolve2d(gray, kernel_gaussian)
show_gray("Gaussian Filter", gaussian)
=========================================================
13. LỌC TRUNG VỊ
=========================================================
def median_filter(img, k=3): h, w = img.shape pad = k // 2 padded = np.pad(img, ((pad, pad), (pad, pad)), mode="edge") result = np.zeros_like(img)
for i in range(h):
for j in range(w):
region = padded[i:i + k, j:j + k]
result[i, j] = np.median(region)
return result.astype(np.uint8)
median = median_filter(gray, 3) show_gray("Median Filter", median)
=========================================================
14. SOBEL - PHÁT HIỆN BIÊN
=========================================================
sobel_x_kernel = np.array([ [-1, 0, 1], [-2, 0, 2], [-1, 0, 1] ], dtype=np.float32)
sobel_y_kernel = np.array([ [-1, -2, -1], [0, 0, 0], [1, 2, 1] ], dtype=np.float32)
sobel_x = convolve2d(gray, sobel_x_kernel).astype(np.float32) sobel_y = convolve2d(gray, sobel_y_kernel).astype(np.float32)
sobel = np.sqrt(sobel_x 2 + sobel_y 2) sobel = np.clip(sobel, 0, 255).astype(np.uint8)
show_gray("Sobel", sobel)
=========================================================
15. LAPLACIAN - PHÁT HIỆN BIÊN
=========================================================
laplace_kernel = np.array([ [0, -1, 0], [-1, 4, -1], [0, -1, 0] ], dtype=np.float32)
laplace = convolve2d(gray, laplace_kernel) show_gray("Laplacian", laplace)
=========================================================
16. CANNY ĐƠN GIẢN
Không phải Canny đầy đủ như OpenCV.
Ở đây dùng Sobel rồi phân ngưỡng để minh họa biên.
=========================================================
canny_simple = np.zeros_like(sobel) canny_simple[sobel >= 100] = 255
show_gray("Canny Simple", canny_simple)
=========================================================
17. PHÂN NGƯỠNG THỦ CÔNG
=========================================================
T = 128 binary = np.zeros_like(gray) binary[gray > T] = 255
show_gray("Threshold", binary)
=========================================================
18. TÌM NGƯỠNG TỰ ĐỘNG OTSU
=========================================================
def otsu_threshold(img): hist = np.zeros(256, dtype=np.float64)
for value in img.flatten():
hist[value] += 1
total = img.size
sum_total = 0
for i in range(256):
sum_total += i * hist[i]
sum_background = 0
weight_background = 0
max_variance = 0
best_threshold = 0
for t in range(256):
weight_background += hist[t]
if weight_background == 0:
continue
weight_foreground = total - weight_background
if weight_foreground == 0:
break
sum_background += t * hist[t]
mean_background = sum_background / weight_background
mean_foreground = (sum_total - sum_background) / weight_foreground
variance_between = weight_background * weight_foreground * (mean_background - mean_foreground) ** 2
if variance_between > max_variance:
max_variance = variance_between
best_threshold = t
return best_threshold
otsu_T = otsu_threshold(gray)
otsu = np.zeros_like(gray) otsu[gray > otsu_T] = 255
print("\nNgưỡng Otsu:", otsu_T) show_gray("Otsu", otsu)
=========================================================
19. MORPHOLOGY: EROSION, DILATION, OPENING, CLOSING
=========================================================
def erosion(img, k=3): pad = k // 2 padded = np.pad(img, ((pad, pad), (pad, pad)), mode="edge") result = np.zeros_like(img)
h, w = img.shape
for i in range(h):
for j in range(w):
region = padded[i:i + k, j:j + k]
if np.all(region == 255):
result[i, j] = 255
else:
result[i, j] = 0
return result
def dilation(img, k=3): pad = k // 2 padded = np.pad(img, ((pad, pad), (pad, pad)), mode="edge") result = np.zeros_like(img)
h, w = img.shape
for i in range(h):
for j in range(w):
region = padded[i:i + k, j:j + k]
if np.any(region == 255):
result[i, j] = 255
else:
result[i, j] = 0
return result
erode_img = erosion(binary, 3) dilate_img = dilation(binary, 3)
opening = dilation(erosion(binary, 3), 3) closing = erosion(dilation(binary, 3), 3)
show_gray("Erosion", erode_img) show_gray("Dilation", dilate_img) show_gray("Opening", opening) show_gray("Closing", closing)
=========================================================
20. BIÊN ĐƠN GIẢN TỪ ẢNH NHỊ PHÂN
=========================================================
boundary = binary - erosion(binary, 3) show_gray("Boundary", boundary)
contour = binary - erosion(binary, 3) contour_color = img.copy() contour_color[contour == 255] = [255, 0, 0] show_color("Contour on Original", contour_color)
=========================================================
HIỂN THỊ TẤT CẢ HÌNH
=========================================================
plt.show()
=========================================================
RLC - Run Length Coding
Không dùng cv2, chỉ dùng PIL + numpy + matplotlib
=========================================================
import numpy as np import matplotlib.pyplot as plt from PIL import Image
def show_gray(title, image): plt.figure() plt.title(title) plt.imshow(image, cmap="gray") plt.axis("off")
def read_gray_image(path): """Đọc ảnh và chuyển sang ảnh xám bằng PIL.""" try: img = Image.open(path).convert("L") except FileNotFoundError: print("Không đọc được ảnh. Kiểm tra lại file:", path) return None
return np.array(img)
def rlc_encode(data): """Nén RLC: [2,2,2,3,3] -> [(3,2), (2,3)]""" if len(data) == 0: return []
result = []
prev = data[0]
count = 1
for x in data[1:]:
if x == prev:
count += 1
else:
result.append((count, prev))
prev = x
count = 1
result.append((count, prev))
return result
def rlc_decode(encoded): """Giải nén RLC: [(3,2), (2,3)] -> [2,2,2,3,3]""" result = []
for count, value in encoded:
result.extend([value] * count)
return result
=========================================================
1. RLC TRÊN LIST MẪU
=========================================================
data = [2, 2, 2, 3, 3, 1, 1, 1]
encoded_rlc = rlc_encode(data) decoded_rlc = rlc_decode(encoded_rlc)
print("RLC list:") print("Gốc:", data) print("Nén:", encoded_rlc) print("Giải nén:", decoded_rlc) print("Giải nén đúng không:", data == decoded_rlc)
=========================================================
2. RLC TRÊN ẢNH XÁM
=========================================================
gray = read_gray_image("image.png")
if gray is not None: show_gray("Gray Image", gray)
flat_gray = gray.flatten().tolist()
rlc_image = rlc_encode(flat_gray)
decoded_image = rlc_decode(rlc_image)
print("\nRLC ảnh:")
print("Số pixel ảnh gốc:", len(flat_gray))
print("Số cặp sau RLC:", len(rlc_image))
print("20 cặp RLC đầu:", rlc_image[:20])
print("Giải nén đúng không:", flat_gray == decoded_image)
# Khôi phục ảnh từ dữ liệu giải nén để kiểm tra trực quan
restored = np.array(decoded_image, dtype=np.uint8).reshape(gray.shape)
show_gray("Restored Image From RLC", restored)
plt.show()
=========================================================
Huffman Coding
Không dùng cv2, chỉ dùng PIL + numpy + matplotlib
=========================================================
import numpy as np import matplotlib.pyplot as plt from PIL import Image from collections import Counter import heapq
def show_gray(title, image): plt.figure() plt.title(title) plt.imshow(image, cmap="gray") plt.axis("off")
def read_gray_image(path): """Đọc ảnh và chuyển sang ảnh xám bằng PIL.""" try: img = Image.open(path).convert("L") except FileNotFoundError: print("Không đọc được ảnh. Kiểm tra lại file:", path) return None
return np.array(img)
class Node: def __init__(self, freq, symbol=None, left=None, right=None): self.freq = freq self.symbol = symbol self.left = left self.right = right
def __lt__(self, other):
return self.freq < other.freq
def build_huffman_tree(data): """Tạo cây Huffman từ dữ liệu.""" if len(data) == 0: return None
heap = [Node(freq, symbol) for symbol, freq in Counter(data).items()]
heapq.heapify(heap)
while len(heap) > 1:
left = heapq.heappop(heap)
right = heapq.heappop(heap)
parent = Node(left.freq + right.freq, left=left, right=right)
heapq.heappush(heap, parent)
return heap[0]
def build_huffman_codes(node, prefix="", codes=None): """Duyệt cây Huffman để tạo bảng mã.""" if codes is None: codes = {}
if node is None:
return codes
if node.symbol is not None:
codes[node.symbol] = prefix if prefix != "" else "0"
return codes
build_huffman_codes(node.left, prefix + "0", codes)
build_huffman_codes(node.right, prefix + "1", codes)
return codes
def huffman_encode(data): """Mã hóa Huffman, trả về chuỗi bit và bảng mã.""" if len(data) == 0: return "", {}
root = build_huffman_tree(data)
codes = build_huffman_codes(root)
encoded = "".join(codes[x] for x in data)
return encoded, codes
def huffman_decode(encoded, codes): """Giải mã Huffman từ chuỗi bit và bảng mã.""" reverse_codes = {code: symbol for symbol, code in codes.items()}
result = []
current = ""
for bit in encoded:
current += bit
if current in reverse_codes:
result.append(reverse_codes[current])
current = ""
return result
=========================================================
1. HUFFMAN TRÊN CHUỖI MẪU
=========================================================
text = list("AAAABBC")
encoded_huff, codes = huffman_encode(text) decoded_huff = huffman_decode(encoded_huff, codes)
print("Huffman text:") print("Gốc:", "".join(text)) print("Bảng mã:", codes) print("Chuỗi bit:", encoded_huff) print("Giải mã:", "".join(decoded_huff)) print("Giải mã đúng không:", text == decoded_huff)
=========================================================
2. HUFFMAN TRÊN ẢNH XÁM
=========================================================
gray = read_gray_image("image.png")
if gray is not None: show_gray("Gray Image", gray)
flat_gray = gray.flatten().tolist()
# Lấy 1000 pixel đầu để demo nhanh, tránh chuỗi bit quá dài
sample_pixels = flat_gray[:1000]
encoded_img_huff, img_codes = huffman_encode(sample_pixels)
decoded_img_huff = huffman_decode(encoded_img_huff, img_codes)
print("\nHuffman ảnh mẫu 1000 pixel:")
print("Số pixel gốc:", len(sample_pixels))
print("Số ký hiệu khác nhau:", len(img_codes))
print("Số bit sau Huffman:", len(encoded_img_huff))
print("Giải mã đúng không:", sample_pixels == decoded_img_huff)
# Vẽ histogram tần suất mức xám của 1000 pixel mẫu
freq = Counter(sample_pixels)
values = sorted(freq.keys())
counts = [freq[v] for v in values]
plt.figure()
plt.title("Tần suất pixel mẫu dùng cho Huffman")
plt.xlabel("Mức xám")
plt.ylabel("Số lần xuất hiện")
plt.bar(values, counts)
plt.show()
=========================================================
LZW - Lempel Ziv Welch
Không dùng cv2, chỉ dùng PIL + numpy + matplotlib
=========================================================
import numpy as np import matplotlib.pyplot as plt from PIL import Image
def show_gray(title, image): plt.figure() plt.title(title) plt.imshow(image, cmap="gray") plt.axis("off")
def read_gray_image(path): """Đọc ảnh và chuyển sang ảnh xám bằng PIL.""" try: img = Image.open(path).convert("L") except FileNotFoundError: print("Không đọc được ảnh. Kiểm tra lại file:", path) return None
return np.array(img)
def lzw_encode(data): """Nén LZW. Dữ liệu đầu vào là chuỗi, ví dụ 'ABABABA'.""" dictionary = {chr(i): i for i in range(256)} next_code = 256
w = ""
result = []
for c in data:
wc = w + c
if wc in dictionary:
w = wc
else:
result.append(dictionary[w])
dictionary[wc] = next_code
next_code += 1
w = c
if w:
result.append(dictionary[w])
return result
def lzw_decode(codes): """Giải nén LZW từ danh sách mã số.""" if len(codes) == 0: return ""
dictionary = {i: chr(i) for i in range(256)}
next_code = 256
w = dictionary[codes[0]]
result = w
for k in codes[1:]:
if k in dictionary:
entry = dictionary[k]
elif k == next_code:
entry = w + w[0]
else:
raise ValueError("Mã LZW không hợp lệ")
result += entry
dictionary[next_code] = w + entry[0]
next_code += 1
w = entry
return result
=========================================================
1. LZW TRÊN CHUỖI MẪU
=========================================================
lzw_text = "ABABABA"
encoded_lzw = lzw_encode(lzw_text) decoded_lzw = lzw_decode(encoded_lzw)
print("LZW text:") print("Gốc:", lzw_text) print("Nén:", encoded_lzw) print("Giải nén:", decoded_lzw) print("Giải nén đúng không:", lzw_text == decoded_lzw)
=========================================================
2. LZW TRÊN ẢNH XÁM
=========================================================
gray = read_gray_image("image.png")
if gray is not None: show_gray("Gray Image", gray)
flat_gray = gray.flatten().tolist()
# Chuyển 1000 pixel đầu thành chuỗi ký tự chr(pixel)
pixel_string = "".join(chr(p) for p in flat_gray[:1000])
lzw_img = lzw_encode(pixel_string)
decoded_pixel_string = lzw_decode(lzw_img)
print("\nLZW ảnh mẫu 1000 pixel:")
print("Số phần tử gốc:", len(pixel_string))
print("Số mã sau LZW:", len(lzw_img))
print("Giải nén đúng không:", pixel_string == decoded_pixel_string)
# Vẽ biểu đồ mã LZW sinh ra
plt.figure()
plt.title("Mã LZW sinh ra từ 1000 pixel đầu")
plt.xlabel("Vị trí mã")
plt.ylabel("Giá trị mã")
plt.plot(lzw_img)
plt.show() import numpy as np import matplotlib.pyplot as plt from PIL import Image
=========================================================
HÀM HIỂN THỊ ẢNH - KHÔNG DÙNG OPENCV
=========================================================
def show_gray(title, img): plt.figure() plt.title(title) plt.imshow(img, cmap="gray") plt.axis("off")
def show_color(title, img): plt.figure() plt.title(title) plt.imshow(img) plt.axis("off")
=========================================================
HÀM TÍCH CHẬP 2D
=========================================================
def convolve2d(img, kernel): h, w = img.shape kh, kw = kernel.shape
pad_h = kh // 2
pad_w = kw // 2
padded = np.pad(img, ((pad_h, pad_h), (pad_w, pad_w)), mode="edge")
result = np.zeros_like(img, dtype=np.float32)
for i in range(h):
for j in range(w):
region = padded[i:i + kh, j:j + kw]
result[i, j] = np.sum(region * kernel)
return result
=========================================================
CÂU 1. NHẬP XUẤT VÀ TIỀN XỬ LÝ ẢNH - KHÔNG DÙNG OPENCV
=========================================================
def load_and_convert_gray(image_path): """Tải ảnh màu bằng PIL, chuyển sang ảnh xám bằng công thức.""" try: img = Image.open(image_path).convert("RGB") except FileNotFoundError: print("Không đọc được ảnh:", image_path) return None, None
img = np.array(img)
r = img[:, :, 0]
g = img[:, :, 1]
b = img[:, :, 2]
gray = 0.299 * r + 0.587 * g + 0.114 * b
gray = np.round(gray).astype(np.uint8)
show_color("Anh mau", img)
show_gray("Anh xam", gray)
return img, gray
def draw_histogram(gray): """Tính và vẽ histogram ảnh xám.""" hist = np.zeros(256, dtype=int)
for value in gray.flatten():
hist[value] += 1
plt.figure()
plt.title("Histogram anh xam")
plt.xlabel("Muc xam")
plt.ylabel("So pixel")
plt.plot(hist)
return hist
def histogram_equalization(gray): """Cân bằng histogram ảnh xám.""" hist = draw_histogram(gray)
cdf = hist.cumsum()
cdf_min = cdf[cdf > 0][0]
total_pixels = gray.size
equal_map = np.round((cdf - cdf_min) / (total_pixels - cdf_min) * 255)
equal_map = np.clip(equal_map, 0, 255).astype(np.uint8)
equal = equal_map[gray]
show_gray("Anh sau can bang histogram", equal)
return equal
=========================================================
CÂU 2. LỌC KHÔNG GIAN VÀ PHÁT HIỆN BIÊN
=========================================================
def average_filter_3x3(matrix): """Làm trơn ma trận bằng bộ lọc trung bình 3x3.""" kernel = np.ones((3, 3), dtype=np.float32) / 9 result = convolve2d(matrix.astype(np.float32), kernel) return result
def sobel_edge(matrix): """Phát hiện biên bằng Sobel.""" sobel_x_kernel = np.array([ [-1, 0, 1], [-2, 0, 2], [-1, 0, 1] ], dtype=np.float32)
sobel_y_kernel = np.array([
[-1, -2, -1],
[0, 0, 0],
[1, 2, 1]
], dtype=np.float32)
gx = convolve2d(matrix.astype(np.float32), sobel_x_kernel)
gy = convolve2d(matrix.astype(np.float32), sobel_y_kernel)
mag = np.sqrt(gx ** 2 + gy ** 2)
return mag
def laplace_edge(matrix): """Phát hiện biên bằng Laplace.""" kernel = np.array([ [0, -1, 0], [-1, 4, -1], [0, -1, 0] ], dtype=np.float32)
result = convolve2d(matrix.astype(np.float32), kernel)
return result
=========================================================
CÂU 3. PHÂN VÙNG ẢNH
=========================================================
def manual_threshold(gray, T): """Tạo ảnh nhị phân với ngưỡng T.""" binary = np.zeros_like(gray, dtype=np.uint8) binary[gray > T] = 255 return binary
def otsu_threshold(gray): """Tự tìm ngưỡng theo thuật toán Otsu.""" hist = np.zeros(256, dtype=np.float64)
for value in gray.flatten():
hist[value] += 1
total = gray.size
sum_total = 0
for i in range(256):
sum_total += i * hist[i]
sum_background = 0
weight_background = 0
max_variance = 0
best_T = 0
for T in range(256):
weight_background += hist[T]
if weight_background == 0:
continue
weight_foreground = total - weight_background
if weight_foreground == 0:
break
sum_background += T * hist[T]
mean_background = sum_background / weight_background
mean_foreground = (sum_total - sum_background) / weight_foreground
variance_between = weight_background * weight_foreground * (mean_background - mean_foreground) ** 2
if variance_between > max_variance:
max_variance = variance_between
best_T = T
binary = manual_threshold(gray, best_T)
return best_T, binary
=========================================================
CÂU 4. NÉN ẢNH RLC THEO TỪNG HÀNG
=========================================================
def rlc_encode_row(row): """Nén RLC cho một hàng. Lưu dạng (count, value).""" if len(row) == 0: return []
result = []
count = 1
for i in range(1, len(row)):
if row[i] == row[i - 1]:
count += 1
else:
result.append((count, row[i - 1]))
count = 1
result.append((count, row[-1]))
return result
def rlc_encode_matrix_by_row(matrix): """Nén RLC theo từng hàng.""" encoded = []
for row in matrix:
encoded.append(rlc_encode_row(row.tolist()))
return encoded
def compression_metrics(matrix, encoded): """Tính tỷ lệ nén và độ dư thừa.""" original_size = matrix.size
compressed_size = 0
for row_code in encoded:
compressed_size += len(row_code) * 2
compression_rate = original_size / compressed_size
redundancy = 1 - (1 / compression_rate)
return original_size, compressed_size, compression_rate, redundancy
=========================================================
CHƯƠNG TRÌNH CHÍNH
=========================================================
def main():
# -----------------------------
# Câu 1
# -----------------------------
img, gray = load_and_convert_gray("input.jpg")
if gray is not None:
draw_histogram(gray)
histogram_equalization(gray)
# -----------------------------
# Câu 3
# -----------------------------
try:
T = int(input("Nhap nguong T cho cau 3.1: "))
except ValueError:
T = 128
print("Nhap sai, dung nguong mac dinh T = 128")
binary = manual_threshold(gray, T)
show_gray("Anh nhi phan voi nguong T", binary)
otsu_T, otsu = otsu_threshold(gray)
print("Nguong tu dong Otsu:", otsu_T)
show_gray("Anh phan vung Otsu", otsu)
# -----------------------------
# Câu 2
# -----------------------------
I = np.array([
[15, 15, 15, 15, 15, 15],
[15, 80, 80, 80, 80, 15],
[15, 80, 120, 120, 80, 15],
[15, 80, 120, 120, 80, 15],
[15, 80, 80, 80, 80, 15],
[15, 15, 15, 15, 15, 15]
], dtype=np.uint8)
print("\nCau 2 - Ma tran goc I:")
print(I)
avg = average_filter_3x3(I)
print("\nCau 2.1 - Ma tran sau loc trung binh 3x3:")
print(np.round(avg, 2))
sobel = sobel_edge(I)
print("\nCau 2.2 - Ma tran bien Sobel:")
print(np.round(sobel, 2))
laplace = laplace_edge(I)
print("\nCau 2.2 - Ma tran bien Laplace:")
print(np.round(laplace, 2))
# -----------------------------
# Câu 4
# -----------------------------
M = np.array([
[2, 2, 2, 3, 3],
[3, 3, 1, 1, 1]
], dtype=int)
encoded = rlc_encode_matrix_by_row(M)
print("\nCau 4 - Ma tran M:")
print(M)
print("\nCau 4.1 - Ket qua nen RLC theo tung hang:")
for i, row_code in enumerate(encoded):
print("Hang", i + 1, ":", row_code)
original_size, compressed_size, cr, rd = compression_metrics(M, encoded)
print("\nCau 4.2 - Tham so danh gia nen:")
print("So pixel ban dau:", original_size)
print("So gia tri can luu sau nen:", compressed_size)
print("Ty le nen Compression Rate:", round(cr, 4))
print("Do du thua Redundancy:", round(rd, 4))
plt.show()
if __name__ == "__main__": main()
Points breakdown
Hue ICT (290 points)
Nhập môn lập trình (1 points)
| Problem | Score |
|---|---|
| Phép tính số học trên số nguyên bản 1 | 1 / 1 |
OLP (566 points)
SPIT (50 points)
| Problem | Score |
|---|---|
| APOWB | 10 / 10 |
| Bài Tiến lên | 10 / 10 |
| Mảng tăng dần | 10 / 10 |
| Marathon | 10 / 10 |
| Pyramid | 10 / 10 |
Uncategorized (2100 points)
| Problem | Score |
|---|---|
| Khu vườn | 100 / 100 |
| Tô màu đồ thị | 2000 / 2000 |