#!/usr/bin/env python3
"""
批量调整图像色阶脚本
功能:批量调整指定目录下所有图像的色阶(对比度和亮度)
支持格式:JPG, PNG, BMP, TIFF等
"""
import os
import argparse
from PIL import Image, ImageEnhance, ImageStat
import glob
def adjust_levels(image, black_point=0, white_point=255, gamma=1.0):
"""
调整图像的色阶
:param image: PIL Image对象
:param black_point: 黑场阈值 (0-255)
:param white_point: 白场阈值 (0-255)
:param gamma: 伽马值
:return: 调整后的PIL Image对象
"""
# 转换为RGB模式(如果是RGBA则保留alpha通道)
if image.mode == 'RGBA':
# 分离通道
r, g, b, a = image.split()
# 调整RGB通道
r = r.point(lambda x: _level_map(x, black_point, white_point, gamma))
g = g.point(lambda x: _level_map(x, black_point, white_point, gamma))
b = b.point(lambda x: _level_map(x, black_point, white_point, gamma))
# 合并通道
return Image.merge('RGBA', (r, g, b, a))
else:
# 确保图像为RGB模式
if image.mode != 'RGB':
image = image.convert('RGB')
return image.point(lambda x: _level_map(x, black_point, white_point, gamma))
def _level_map(value, black_point, white_point, gamma):
"""
单像素值的色阶映射函数
"""
# 确保值在有效范围内
value = max(0, min(255, value))
# 映射到0-1范围
normalized = (value - black_point) / (white_point - black_point)
normalized = max(0, min(1, normalized))
# 应用伽马校正
if gamma != 1.0:
normalized = pow(normalized, 1.0 / gamma)
# 映射回0-255范围
return int(normalized * 255)
def auto_levels(image):
"""
自动调整色阶(拉伸到全范围)
:param image: PIL Image对象
:return: 调整后的PIL Image对象
"""
# 获取图像的直方图统计
if image.mode == 'RGBA':
# 对于RGBA图像,使用RGB通道计算
r, g, b, a = image.split()
stats_r = ImageStat.Stat(r)
stats_g = ImageStat.Stat(g)
stats_b = ImageStat.Stat(b)
# 找到所有通道中的最小和最大值
min_val = min(stats_r.min[0], stats_g.min[0], stats_b.min[0])
max_val = max(stats_r.max[0], stats_g.max[0], stats_b.max[0])
else:
if image.mode != 'RGB':
image = image.convert('RGB')
stats = ImageStat.Stat(image)
min_val = min(stats.min)
max_val = max(stats.max)
# 添加1%的裁剪以避免极端值
min_val = int(min_val * 1.01)
max_val = int(max_val * 0.99)
print(f"自动色阶: 黑场={min_val}, 白场={max_val}")
return adjust_levels(image, black_point=min_val, white_point=max_val)
def batch_process(input_dir, output_dir, black_point=0, white_point=255,
gamma=1.0, auto=False, quality=95, formats=None):
"""
批量处理图像
:param input_dir: 输入目录
:param output_dir: 输出目录
:param black_point: 黑场值
:param white_point: 白场值
:param gamma: 伽马值
:param auto: 是否自动调整
:param quality: JPEG输出质量
:param formats: 处理的文件格式列表
"""
# 支持的图像格式
if formats is None:
formats = ['*.jpg', '*.jpeg', '*.png', '*.bmp', '*.tiff', '*.tif', '*.webp']
# 创建输出目录
os.makedirs(output_dir, exist_ok=True)
# 收集所有图像文件
image_files = []
for fmt in formats:
pattern = os.path.join(input_dir, fmt)
image_files.extend(glob.glob(pattern, recursive=True))
# 也检查大写扩展名
for fmt in formats:
pattern = os.path.join(input_dir, fmt.upper())
image_files.extend(glob.glob(pattern, recursive=True))
# 去重
image_files = list(set(image_files))
if not image_files:
print(f"在 {input_dir} 中没有找到图像文件")
return
print(f"找到 {len(image_files)} 个图像文件")
# 处理每个图像
for i, filepath in enumerate(image_files, 1):
try:
print(f"[{i}/{len(image_files)}] 处理中: {os.path.basename(filepath)}")
# 打开图像
with Image.open(filepath) as img:
# 调整色阶
if auto:
img_adjusted = auto_levels(img)
else:
img_adjusted = adjust_levels(img, black_point, white_point, gamma)
# 生成输出文件路径
filename = os.path.basename(filepath)
name, ext = os.path.splitext(filename)
output_path = os.path.join(output_dir, f"{name}_adjusted{ext}")
# 保存图像
if ext.lower() in ['.jpg', '.jpeg']:
img_adjusted.save(output_path, quality=quality, optimize=True)
elif ext.lower() == '.png':
img_adjusted.save(output_path, optimize=True)
else:
img_adjusted.save(output_path)
print(f" 保存至: {output_path}")
except Exception as e:
print(f" 处理 {filepath} 时出错: {e}")
print(f"\n完成! 处理了 {len(image_files)} 个图像文件")
def main():
parser = argparse.ArgumentParser(description='批量调整图像色阶')
parser.add_argument('input_dir', help='输入图像目录')
parser.add_argument('output_dir', help='输出图像目录')
# 色阶参数
parser.add_argument('--black', type=int, default=0,
help='黑场值 (0-255,默认: 0)')
parser.add_argument('--white', type=int, default=255,
help='白场值 (0-255,默认: 255)')
parser.add_argument('--gamma', type=float, default=1.0,
help='伽马值 (默认: 1.0)')
parser.add_argument('--auto', action='store_true',
help='自动调整色阶(拉伸到全范围)')
# 其他参数
parser.add_argument('--quality', type=int, default=95,
help='JPEG输出质量 (1-100,默认: 95)')
parser.add_argument('--formats', nargs='+',
default=['*.jpg', '*.jpeg', '*.png', '*.bmp', '*.tiff', '*.tif', '*.webp'],
help='处理的文件格式 (默认: 常见图像格式)')
args = parser.parse_args()
# 验证参数
if not args.auto:
if args.black < 0 or args.black > 255:
print("错误: 黑场值必须在0-255之间")
return
if args.white < 0 or args.white > 255:
print("错误: 白场值必须在0-255之间")
return
if args.black >= args.white:
print("错误: 黑场值必须小于白场值")
return
if args.gamma <= 0:
print("错误: 伽马值必须大于0")
return
batch_process(
args.input_dir,
args.output_dir,
black_point=args.black,
white_point=args.white,
gamma=args.gamma,
auto=args.auto,
quality=args.quality,
formats=args.formats
)
if __name__ == '__main__':
main()
使用方法
安装依赖
pip install pillow
基本用法
手动调整色阶:

python batch_levels.py ./input_images ./output_images --black 30 --white 220 --gamma 1.2
自动调整色阶:
python batch_levels.py ./input_images ./output_images --auto
仅处理PNG文件:
python batch_levels.py ./input_images ./output_images --auto --formats '*.png'
参数说明
| 参数 | 说明 | 默认值 |
|---|---|---|
input_dir |
输入图像目录(必填) | |
output_dir |
输出图像目录(必填) | |
--black |
黑场值 (0-255) | 0 |
--white |
白场值 (0-255) | 255 |
--gamma |
伽马值 | 0 |
--auto |
自动调整色阶 | False |
--quality |
JPEG输出质量 | 95 |
--formats |
处理的文件格式 | 所有常见格式 |
示例
提高对比度:
python batch_levels.py ./photos ./enhanced --black 50 --white 200
提亮暗部:
python batch_levels.py ./photos ./brighter --gamma 1.5
自动优化:
python batch_levels.py ./photos ./auto_enhanced --auto
该脚本会保留原始图像格式,并在输出文件名后添加_adjusted后缀,对于RGBA图像(如透明PNG),会正确保留Alpha通道。