前言
图片有点多,想做个以分辨率为主的分类。
代码
import os
import shutil
import argparse
from PIL import Image, ImageOps
def classify_images(source_dir, desktop_dir, mobile_dir, avatar_dir, ratio_threshold=0.9):
"""
根据图片方向比例分类到桌面、移动和头像目录
:param source_dir: 源图片目录
:param desktop_dir: 横屏图片目录
:param mobile_dir: 竖屏图片目录
:param avatar_dir: 头像图片目录
:param ratio_threshold: 视为头像的最小宽高比(默认0.9)
"""
# 创建所有目标目录
for d in [desktop_dir, mobile_dir, avatar_dir]:
os.makedirs(d, exist_ok=True)
valid_exts = {'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp'}
for filename in os.listdir(source_dir):
file_path = os.path.join(source_dir, filename)
if not os.path.isfile(file_path):
continue
ext = os.path.splitext(filename)[1].lower()
if ext not in valid_exts:
continue
try:
with Image.open(file_path) as img:
img = ImageOps.exif_transpose(img) # 校正方向
width, height = img.size
# 计算宽高比(总在0-1之间)
ratio = min(width, height) / max(width, height)
except Exception as e:
print(f"错误:无法处理文件 {filename} ({e})")
continue
# 分类优先级:先判断头像
if ratio >= ratio_threshold:
target_dir = avatar_dir
else:
target_dir = desktop_dir if width > height else mobile_dir
# 处理重名文件
dest_path = os.path.join(target_dir, filename)
if os.path.exists(dest_path):
base, ext = os.path.splitext(filename)
counter = 1
while os.path.exists(dest_path):
new_name = f"{base}_{counter}{ext}"
dest_path = os.path.join(target_dir, new_name)
counter += 1
try:
shutil.move(file_path, dest_path)
print(f"已分类:{filename} -> {os.path.basename(target_dir)}")
except Exception as e:
print(f"移动失败:{filename} ({e})")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='智能图片分类工具')
parser.add_argument('source_dir', help='源目录路径')
parser.add_argument('--desktop', help='横屏目录(默认:源目录/desktop)')
parser.add_argument('--mobile', help='竖屏目录(默认:源目录/mobile)')
parser.add_argument('--avatar', help='头像目录(默认:源目录/avatar)')
parser.add_argument('--ratio', type=float, default=0.9,
help='头像宽高比阈值(0-1,默认0.9)')
args = parser.parse_args()
source_dir = os.path.abspath(args.source_dir)
desktop_dir = args.desktop or os.path.join(source_dir, 'desktop')
mobile_dir = args.mobile or os.path.join(source_dir, 'mobile')
avatar_dir = args.avatar or os.path.join(source_dir, 'avatar')
classify_images(
source_dir=source_dir,
desktop_dir=desktop_dir,
mobile_dir=mobile_dir,
avatar_dir=avatar_dir,
ratio_threshold=args.ratio
)