脚本如何批量调整图片自适应均衡

wen 实用脚本 23

本文目录导读:

脚本如何批量调整图片自适应均衡

  1. 方法一:使用OpenCV的CLAHE(推荐)
  2. 方法二:使用PIL(Pillow)的自动对比度增强
  3. 方法三:高级版本 - 带GUI和参数调整
  4. 使用说明

我来为您介绍几种批量调整图片自适应均衡的方法,主要使用Python脚本实现:

使用OpenCV的CLAHE(推荐)

import cv2
import numpy as np
from pathlib import Path
import os
def batch_adaptive_equalization(input_dir, output_dir, clip_limit=2.0, grid_size=(8,8)):
    """
    批量处理图片自适应直方图均衡化
    参数:
    input_dir: 输入图片目录
    output_dir: 输出图片目录
    clip_limit: 对比度限制(默认2.0)
    grid_size: 网格大小(默认8x8)
    """
    # 创建输出目录
    Path(output_dir).mkdir(parents=True, exist_ok=True)
    # 支持的文件格式
    extensions = ['.jpg', '.jpeg', '.png', '.bmp', '.tiff']
    # 获取所有图片文件
    image_files = []
    for ext in extensions:
        image_files.extend(Path(input_dir).glob(f'*{ext}'))
        image_files.extend(Path(input_dir).glob(f'*{ext.upper()}'))
    print(f"找到 {len(image_files)} 张图片")
    # 创建CLAHE对象
    clahe = cv2.createCLAHE(clipLimit=clip_limit, tileGridSize=grid_size)
    for i, img_path in enumerate(image_files, 1):
        try:
            # 读取图片
            img = cv2.imread(str(img_path))
            if img is None:
                print(f"无法读取: {img_path.name}")
                continue
            # 转换为LAB颜色空间
            lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
            l, a, b = cv2.split(lab)
            # 对亮度通道应用CLAHE
            l_eq = clahe.apply(l)
            # 合并通道并转换回BGR
            lab_eq = cv2.merge([l_eq, a, b])
            img_eq = cv2.cvtColor(lab_eq, cv2.COLOR_LAB2BGR)
            # 保存结果
            output_path = Path(output_dir) / img_path.name
            cv2.imwrite(str(output_path), img_eq)
            print(f"处理进度: {i}/{len(image_files)} - {img_path.name}")
        except Exception as e:
            print(f"处理失败 {img_path.name}: {str(e)}")
# 使用示例
if __name__ == "__main__":
    # 设置参数
    input_directory = "./input_images"
    output_directory = "./output_images"
    # 执行批量处理
    batch_adaptive_equalization(
        input_directory, 
        output_directory,
        clip_limit=3.0,  # 对比度限制,值越大对比度越强
        grid_size=(8,8)  # 网格大小,越小细节增强越明显
    )

使用PIL(Pillow)的自动对比度增强

from PIL import Image, ImageEnhance, ImageOps
from pathlib import Path
import concurrent.futures
from tqdm import tqdm
def auto_contrast_enhance(img_path, output_dir, factor=1.5):
    """
    使用PIL进行自适应对比度增强
    参数:
    img_path: 输入图片路径
    output_dir: 输出目录
    factor: 增强因子(1.0为原始,越大对比度越强)
    """
    try:
        # 打开图片
        img = Image.open(img_path)
        # 转换为RGB模式(如果是RGBA)
        if img.mode == 'RGBA':
            img = img.convert('RGB')
        # 自动均衡化
        img_eq = ImageOps.equalize(img)
        # 增强对比度
        if factor != 1.0:
            enhancer = ImageEnhance.Contrast(img_eq)
            img_eq = enhancer.enhance(factor)
        # 保存结果
        output_path = Path(output_dir) / img_path.name
        img_eq.save(output_path, quality=95)
        return True
    except Exception as e:
        print(f"处理失败 {img_path.name}: {str(e)}")
        return False
def batch_pil_equalization(input_dir, output_dir, factor=1.5, workers=4):
    """
    批量处理图片(支持多线程)
    """
    # 创建输出目录
    Path(output_dir).mkdir(parents=True, exist_ok=True)
    # 获取图片文件
    extensions = ['.jpg', '.jpeg', '.png', '.bmp', '.tiff']
    image_files = []
    for ext in extensions:
        image_files.extend(Path(input_dir).glob(f'*{ext}'))
        image_files.extend(Path(input_dir).glob(f'*{ext.upper()}'))
    print(f"找到 {len(image_files)} 张图片")
    # 使用多线程处理
    with concurrent.futures.ThreadPoolExecutor(max_workers=workers) as executor:
        futures = []
        for img_path in image_files:
            future = executor.submit(
                auto_contrast_enhance, 
                img_path, 
                output_dir, 
                factor
            )
            futures.append(future)
        # 显示进度
        results = []
        for future in tqdm(concurrent.futures.as_completed(futures), 
                          total=len(futures), 
                          desc="处理进度"):
            results.append(future.result())
    success = sum(results)
    print(f"处理完成: 成功 {success}/{len(image_files)}")
# 使用示例
if __name__ == "__main__":
    # 参数设置
    input_dir = "./input"
    output_dir = "./processed"
    # 批量处理
    batch_pil_equalization(
        input_dir, 
        output_dir, 
        factor=1.3,  # 对比度增强系数
        workers=4     # 线程数
    )

高级版本 - 带GUI和参数调整

import tkinter as tk
from tkinter import filedialog, ttk
import cv2
import numpy as np
from pathlib import Path
import threading
class BatchEqualizerUI:
    def __init__(self, root):
        self.root = root
        self.root.title("批量自适应均衡工具")
        self.root.geometry("500x400")
        self.input_dir = ""
        self.output_dir = ""
        self.setup_ui()
    def setup_ui(self):
        # 输入目录选择
        ttk.Label(self.root, text="输入目录:").grid(row=0, column=0, padx=5, pady=5)
        self.input_entry = ttk.Entry(self.root, width=40)
        self.input_entry.grid(row=0, column=1, padx=5, pady=5)
        ttk.Button(self.root, text="选择", command=self.select_input).grid(row=0, column=2)
        # 输出目录选择
        ttk.Label(self.root, text="输出目录:").grid(row=1, column=0, padx=5, pady=5)
        self.output_entry = ttk.Entry(self.root, width=40)
        self.output_entry.grid(row=1, column=1, padx=5, pady=5)
        ttk.Button(self.root, text="选择", command=self.select_output).grid(row=1, column=2)
        # 参数设置
        ttk.Label(self.root, text="clip_limit:").grid(row=2, column=0, padx=5, pady=5)
        self.clip_limit_var = tk.DoubleVar(value=2.0)
        ttk.Spinbox(self.root, from_=0.5, to=10.0, increment=0.5, 
                   textvariable=self.clip_limit_var, width=10).grid(row=2, column=1, sticky='w')
        # 进度条
        self.progress = ttk.Progressbar(self.root, length=400, mode='determinate')
        self.progress.grid(row=3, column=0, columnspan=3, padx=5, pady=20)
        # 状态标签
        self.status_label = ttk.Label(self.root, text="就绪")
        self.status_label.grid(row=4, column=0, columnspan=3, pady=10)
        # 开始按钮
        self.start_button = ttk.Button(self.root, text="开始处理", command=self.start_processing)
        self.start_button.grid(row=5, column=0, columnspan=3, pady=10)
    def select_input(self):
        directory = filedialog.askdirectory()
        if directory:
            self.input_entry.delete(0, tk.END)
            self.input_entry.insert(0, directory)
    def select_output(self):
        directory = filedialog.askdirectory()
        if directory:
            self.output_entry.delete(0, tk.END)
            self.output_entry.insert(0, directory)
    def start_processing(self):
        if not self.input_entry.get() or not self.output_entry.get():
            self.status_label.config(text="请选择输入和输出目录")
            return
        # 在新线程中处理,避免阻塞UI
        thread = threading.Thread(target=self.process_images)
        thread.daemon = True
        thread.start()
    def process_images(self):
        input_dir = self.input_entry.get()
        output_dir = self.output_entry.get()
        clip_limit = self.clip_limit_var.get()
        Path(output_dir).mkdir(parents=True, exist_ok=True)
        # 获取图片文件
        image_files = list(Path(input_dir).glob('*.jpg')) + \
                     list(Path(input_dir).glob('*.png')) + \
                     list(Path(input_dir).glob('*.jpeg'))
        total_files = len(image_files)
        self.progress['maximum'] = total_files
        clahe = cv2.createCLAHE(clipLimit=clip_limit, tileGridSize=(8,8))
        for i, img_path in enumerate(image_files, 1):
            try:
                img = cv2.imread(str(img_path))
                if img is None:
                    continue
                lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
                l, a, b = cv2.split(lab)
                l_eq = clahe.apply(l)
                lab_eq = cv2.merge([l_eq, a, b])
                img_eq = cv2.cvtColor(lab_eq, cv2.COLOR_LAB2BGR)
                output_path = Path(output_dir) / img_path.name
                cv2.imwrite(str(output_path), img_eq)
                # 更新进度
                self.progress['value'] = i
                self.status_label.config(text=f"处理中: {i}/{total_files}")
                self.root.update_idletasks()
            except Exception as e:
                print(f"处理失败 {img_path.name}: {str(e)}")
        self.status_label.config(text="处理完成!")
# 运行GUI
def main():
    root = tk.Tk()
    app = BatchEqualizerUI(root)
    root.mainloop()
if __name__ == "__main__":
    main()

使用说明

  1. 安装依赖

    pip install opencv-python pillow tqdm numpy
  2. 使用方法

    • 方法一和二:直接修改输入输出目录路径运行
    • 运行后会显示GUI界面,选择目录和参数后点击开始
  3. 参数调整建议

    • clip_limit:2.0-3.0 适合大多数图片
    • grid_size:默认(8,8)适用于大多数情况
    • 对于过度曝光或欠曝的图片,可以适当增大clip_limit

这些脚本会自动处理目录中的所有图片,并保持原始文件格式和质量。

抱歉,评论功能暂时关闭!