import sys, os # Thêm thư mục project_root vào sys.path sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) import cv2 import numpy as np # --- THÊM IMPORT MSE --- from skimage.metrics import peak_signal_noise_ratio as psnr from skimage.metrics import structural_similarity as ssim from skimage.metrics import mean_squared_error as mse from models import iterative_backprojection from modules.degradation import degrade_image from modules.upsample import upsample_bicubic # ============================================================================= # CẤU HÌNH THAM SỐ (CONFIG) # ============================================================================= OUTPUT_DIR = "../results/IBP" # Thư mục để lưu kết quả SCALE = 2 # Hệ số phóng đại ITERATIONS = 20 # Số vòng lặp IBP ALPHA = 0.2 # Tốc độ học NOISE_STD = 0.01 # Độ lệch chuẩn nhiễu (Gaussian) def save_image(path, img_float): """Chuyển từ Float RGB [0,1] sang UInt8 BGR [0,255] để lưu bằng OpenCV""" img_uint8 = np.clip(img_float * 255.0, 0, 255).astype(np.uint8) if img_uint8.ndim == 3: img_uint8 = cv2.cvtColor(img_uint8, cv2.COLOR_RGB2BGR) cv2.imwrite(path, img_uint8) def run_evaluation(): # Tạo thư mục output nếu chưa có if not os.path.exists(OUTPUT_DIR): os.makedirs(OUTPUT_DIR) print(f"Đã tạo thư mục: {OUTPUT_DIR}") IMAGE_PATH = "../data/degraded_lr/baby.png" if not os.path.exists(IMAGE_PATH): print(f"Không tìm thấy ảnh HR tại: {IMAGE_PATH}") return image_files = [IMAGE_PATH] results = [] print(f"{'='*60}") print(f"BẮT ĐẦU ĐÁNH GIÁ (Bao gồm MSE, PSNR, SSIM)") print(f"Scale: x{SCALE} | Iterations: {ITERATIONS} | Alpha: {ALPHA}") print(f"{'='*60}\n") for idx, img_name in enumerate(image_files): filename_only = os.path.basename(img_name) base_name = os.path.splitext(filename_only)[0] img_path = img_name print(f"[{idx+1}/{len(image_files)}] Đang xử lý: {img_name}...") # --- A. PRE-PROCESSING --- hr_orig = cv2.imread(img_path) if hr_orig is None: continue hr_orig = cv2.cvtColor(hr_orig, cv2.COLOR_BGR2RGB).astype(np.float32) / 255.0 h, w = hr_orig.shape[:2] h_new, w_new = h - (h % SCALE), w - (w % SCALE) hr = hr_orig[:h_new, :w_new] # --- B. TẠO LR --- lr = degrade_image(hr, SCALE, noise_std=NOISE_STD) # --- C. BICUBIC --- sr_bicubic = upsample_bicubic(lr, SCALE) sr_bicubic = np.clip(sr_bicubic, 0.0, 1.0) # --- D. IBP (OURS) --- sr_ibp = np.zeros_like(sr_bicubic) if lr.ndim == 3: for c in range(3): sr_ibp[:,:,c] = iterative_backprojection( lr[:,:,c], scale=SCALE, iterations=ITERATIONS, alpha=ALPHA ) else: sr_ibp = iterative_backprojection( lr, scale=SCALE, iterations=ITERATIONS, alpha=ALPHA ) # --- E. TÍNH TOÁN CHỈ SỐ (THÊM MSE) --- # 1. Bicubic Metrics m_bic = mse(hr, sr_bicubic) # <-- Tính MSE Bicubic p_bic = psnr(hr, sr_bicubic, data_range=1.0) s_bic = ssim(hr, sr_bicubic, channel_axis=2, data_range=1.0) # 2. IBP Metrics m_ibp = mse(hr, sr_ibp) # <-- Tính MSE IBP p_ibp = psnr(hr, sr_ibp, data_range=1.0) s_ibp = ssim(hr, sr_ibp, channel_axis=2, data_range=1.0) results.append({ "name": base_name, "bic_mse": m_bic, "bic_psnr": p_bic, "bic_ssim": s_bic, "ibp_mse": m_ibp, "ibp_psnr": p_ibp, "ibp_ssim": s_ibp }) # --- F. LƯU ẢNH --- save_image(os.path.join(OUTPUT_DIR, f"{base_name}_HR.png"), hr) save_image(os.path.join(OUTPUT_DIR, f"{base_name}_LR.png"), lr) save_image(os.path.join(OUTPUT_DIR, f"{base_name}_Bicubic.png"), sr_bicubic) save_image(os.path.join(OUTPUT_DIR, f"{base_name}_IBP.png"), sr_ibp) # ========================================================================= # 4. SINH MÃ LATEX # ========================================================================= print(f"\n{'='*60}") print("ĐÃ HOÀN TẤT! MÃ LATEX (Kèm MSE):") print(f"{'='*60}\n") latex_code = generate_latex_table(results) print(latex_code) with open(os.path.join(OUTPUT_DIR, "report_table.tex"), "w", encoding="utf-8") as f: f.write(latex_code) print(f"\n(Đã lưu mã LaTeX vào {os.path.join(OUTPUT_DIR, 'report_table.tex')})") def generate_latex_table(results): lines = [] lines.append(r"\begin{table}[H]") lines.append(r"\centering") # Cập nhật caption lines.append(rf"\caption{{So sánh MSE, PSNR (dB) và SSIM giữa Bicubic và IBP ($Scale={SCALE}\times$). Giá trị tốt nhất được \textbf{{in đậm}}.") lines.append(r"}") lines.append(r"\label{tab:ibp_comparison}") # Cập nhật cấu trúc bảng: thêm cột MSE # l | ccc | ccc (Image | Bicubic(3) | IBP(3)) lines.append(r"\setlength{\tabcolsep}{4pt}") # Thu nhỏ khoảng cách cột chút cho vừa lines.append(r"\begin{tabular}{l|ccc|ccc}") lines.append(r"\toprule") lines.append(r"\multirow{2}{*}{\textbf{Image}} & \multicolumn{3}{c|}{\textbf{Bicubic}} & \multicolumn{3}{c}{\textbf{IBP (Ours)}} \\ \cline{2-7} ") # Dòng tiêu đề phụ lines.append(r" & MSE $\downarrow$ & PSNR $\uparrow$ & SSIM $\uparrow$ & MSE $\downarrow$ & PSNR $\uparrow$ & SSIM $\uparrow$ \\ \midrule") # Biến tính trung bình avg_data = [0] * 6 # [bic_mse, bic_psnr, bic_ssim, ibp_mse, ibp_psnr, ibp_ssim] for res in results: name = res['name'].capitalize() # Dữ liệu: 0:b_mse, 1:b_psnr, 2:b_ssim, 3:i_mse, 4:i_psnr, 5:i_ssim d = [ res['bic_mse'], res['bic_psnr'], res['bic_ssim'], res['ibp_mse'], res['ibp_psnr'], res['ibp_ssim'] ] for i in range(6): avg_data[i] += d[i] # --- LOGIC IN ĐẬM --- # MSE: Nhỏ hơn là tốt s_bm = f"\\textbf{{{d[0]:.4f}}}" if d[0] < d[3] else f"{d[0]:.4f}" s_im = f"\\textbf{{{d[3]:.4f}}}" if d[3] < d[0] else f"{d[3]:.4f}" # PSNR: Lớn hơn là tốt s_bp = f"\\textbf{{{d[1]:.2f}}}" if d[1] > d[4] else f"{d[1]:.2f}" s_ip = f"\\textbf{{{d[4]:.2f}}}" if d[4] > d[1] else f"{d[4]:.2f}" # SSIM: Lớn hơn là tốt s_bs = f"\\textbf{{{d[2]:.4f}}}" if d[2] > d[5] else f"{d[2]:.4f}" s_is = f"\\textbf{{{d[5]:.4f}}}" if d[5] > d[2] else f"{d[5]:.4f}" name_tex = name.replace("_", r"\_") # Format dòng: Image & MSE & PSNR & SSIM & MSE & PSNR & SSIM lines.append(f"{name_tex} & {s_bm} & {s_bp} & {s_bs} & {s_im} & {s_ip} & {s_is} \\\\") lines.append(r"\midrule") # Tính trung bình n = len(results) avg_data = [x/n for x in avg_data] d = avg_data # Logic in đậm cho dòng Average s_abm = f"\\textbf{{{d[0]:.4f}}}" if d[0] < d[3] else f"{d[0]:.4f}" s_aim = f"\\textbf{{{d[3]:.4f}}}" if d[3] < d[0] else f"{d[3]:.4f}" s_abp = f"\\textbf{{{d[1]:.2f}}}" if d[1] > d[4] else f"{d[1]:.2f}" s_aip = f"\\textbf{{{d[4]:.2f}}}" if d[4] > d[1] else f"{d[4]:.2f}" s_abs = f"\\textbf{{{d[2]:.4f}}}" if d[2] > d[5] else f"{d[2]:.4f}" s_ais = f"\\textbf{{{d[5]:.4f}}}" if d[5] > d[2] else f"{d[5]:.4f}" lines.append(f"\\textbf{{Average}} & {s_abm} & {s_abp} & {s_abs} & {s_aim} & {s_aip} & {s_ais} \\\\") lines.append(r"\bottomrule") lines.append(r"\end{tabular}") lines.append(r"\end{table}") return "\n".join(lines) if __name__ == "__main__": run_evaluation()