Files
Dehaze/※程序-后处理汇总/2_Adjust_V2_SV自动调整_※Best.py
2026-06-10 17:42:11 +08:00

156 lines
6.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import numpy as np
from PIL import Image
from skimage import color
from scipy.optimize import minimize
import os
import time
from concurrent.futures import ProcessPoolExecutor, as_completed
# ================= 配置区域 =================
max_workers = 8 # 【并行】 并行处理的进程数 (建议设为 CPU 核心数,如 4, 8, 16)
# 图片后缀
prefix = "_AOD-Net" # "_10_0.2_result" # "_result"
# 输入文件夹 (带 prefix 后缀的图片)
src_dir = "AOD-Net"
# 参考文件夹 (GT/Ground Truth无 prefix 后缀)
ref_dir = "去雾图像-北航合作-雾图"
# 输出文件夹
out_dir = "AOD-Net+后处理"
# ===========================================
# 尝试导入 tqdm如果没安装则定义一个简单的占位符
try:
from tqdm import tqdm
except ImportError:
def tqdm(iterable, **kwargs):
return iterable
def process_single_image(filename, src_folder, ref_folder, output_folder, prefix=prefix):
"""
处理单张图片的函数,用于并行调用
"""
source_path = os.path.join(src_folder, filename)
try:
# --- 寻找对应的参考图 ---
# 逻辑:去除文件名后缀 "prefix"
name_no_ext, ext = os.path.splitext(filename)
if name_no_ext.endswith(prefix):
ref_name_no_ext = name_no_ext[:-len(prefix)] # 去掉最后n个字符 (prefix)
else:
ref_name_no_ext = name_no_ext
ref_filename = ref_name_no_ext + ext
ref_path = os.path.join(ref_folder, ref_filename)
# 检查参考图是否存在
if not os.path.exists(ref_path):
return f"[跳过] 找不到参考图: {ref_filename} (对应: {filename})"
# --- 读取图片并归一化 ---
img_src_pil = Image.open(source_path).convert('RGB')
img_src = np.array(img_src_pil) / 255.0
img_ref_pil = Image.open(ref_path).convert('RGB')
# 确保参考图尺寸和源图一致
if img_src_pil.size != img_ref_pil.size:
img_ref_pil = img_ref_pil.resize(img_src_pil.size, Image.BILINEAR)
img_ref = np.array(img_ref_pil) / 255.0
# --- 转换到 HSV ---
hsv_src = color.rgb2hsv(img_src)
hsv_ref = color.rgb2hsv(img_ref)
# --- 定义损失函数 ---
# 注意在多进程中loss_function 必须定义在 worker 内部才能访问到 hsv_src/ref
def loss_function(params):
ks, kv = params
adj_s = np.clip(hsv_src[:,:,1] * ks, 0, 1)
adj_v = np.clip(hsv_src[:,:,2] * kv, 0, 1)
loss_s = np.mean((adj_s - hsv_ref[:,:,1])**2)
loss_v = np.mean((adj_v - hsv_ref[:,:,2])**2)
return loss_s + loss_v
# --- 开始优化 ---
res = minimize(loss_function, [1.0, 1.0], method='Nelder-Mead', tol=1e-4)
best_s, best_v = res.x
s_percent = int(best_s * 100)
v_percent = int(best_v * 100)
# --- 应用最佳参数 ---
hsv_new = hsv_src.copy()
hsv_new[:, :, 1] = np.clip(hsv_new[:, :, 1] * best_s, 0, 1)
hsv_new[:, :, 2] = np.clip(hsv_new[:, :, 2] * best_v, 0, 1)
# --- 转回 RGB 并保存 ---
img_result_rgb = color.hsv2rgb(hsv_new)
img_save = Image.fromarray((img_result_rgb * 255).astype(np.uint8))
new_filename = f"{name_no_ext}_S_{s_percent}_V_{v_percent}{ext}"
save_path = os.path.join(output_folder, new_filename)
img_save.save(save_path)
return f"OK: {filename} -> S={s_percent}%, V={v_percent}%"
except Exception as e:
return f"[错误] 处理文件 {filename} 时出错: {str(e)}"
def calculate_and_process_batch_parallel(src_folder, ref_folder, output_folder, max_workers=None):
# 1. 确保输出目录存在
if not os.path.exists(output_folder):
os.makedirs(output_folder)
print(f"已创建输出目录: {output_folder}")
# 2. 获取源文件夹内所有图片文件
valid_extensions = ('.png', '.jpg', '.jpeg', '.bmp', '.tif')
file_list = [f for f in os.listdir(src_folder) if f.lower().endswith(valid_extensions)]
total_files = len(file_list)
print(f"共发现 {total_files} 张图片,准备开始并行处理 (进程数: {max_workers if max_workers else '自动'})...\n")
# 3. 并行处理
results = []
# ProcessPoolExecutor 自动管理进程池
# max_workers=None 意味着使用 CPU 核心数
with ProcessPoolExecutor(max_workers=max_workers) as executor:
# 提交所有任务
future_to_file = {
executor.submit(process_single_image, filename, src_folder, ref_folder, output_folder): filename
for filename in file_list
}
# 使用 tqdm 显示进度条as_completed 会在任何一个任务完成时yield
pbar = tqdm(total=total_files, unit="img")
for future in as_completed(future_to_file):
result_msg = future.result()
pbar.update(1)
# 如果是错误或跳过信息打印出来如果是OK只更新进度条不刷屏可选
if not result_msg.startswith("OK"):
tqdm.write(result_msg) # 使用 tqdm.write 防止打断进度条
# else:
# tqdm.write(result_msg) # 如果想看每张图的详细结果,取消注释这行
pbar.close()
print("\n" + "="*30)
print("所有处理已完成。")
# 执行
if __name__ == "__main__":
# Windows 下使用多进程必须放在 if __name__ == "__main__": 之下
if os.path.exists(src_dir) and os.path.exists(ref_dir):
# max_workers 可以手动指定,例如 max_workers=4。如果不填则默认跑满 CPU。
calculate_and_process_batch_parallel(src_dir, ref_dir, out_dir, max_workers = max_workers)
else:
print("错误: 找不到输入文件夹或参考文件夹,请检查路径。")