本文目录导读:

我来为您提供一个完整的Python批量图片裁剪方案。
使用PIL/Pillow库(最常用)
基本实现
import os
from PIL import Image
import glob
def batch_crop_images(input_dir, output_dir, crop_box):
"""
批量裁剪图片
参数:
input_dir: 输入图片文件夹路径
output_dir: 输出图片文件夹路径
crop_box: 裁剪区域 (left, top, right, bottom)
"""
# 创建输出目录
os.makedirs(output_dir, exist_ok=True)
# 支持的图片格式
extensions = ['*.jpg', '*.jpeg', '*.png', '*.bmp', '*.tiff']
# 统计处理数量
processed = 0
failed = 0
for ext in extensions:
for img_path in glob.glob(os.path.join(input_dir, ext)):
try:
# 打开图片
img = Image.open(img_path)
# 执行裁剪
cropped_img = img.crop(crop_box)
# 获取文件名
filename = os.path.basename(img_path)
name, ext = os.path.splitext(filename)
output_path = os.path.join(output_dir, f"{name}_cropped{ext}")
# 保存裁剪后的图片
cropped_img.save(output_path, quality=95)
processed += 1
print(f"✓ 已处理: {filename}")
except Exception as e:
failed += 1
print(f"✗ 处理失败 {img_path}: {e}")
print(f"\n处理完成! 成功: {processed}, 失败: {failed}")
# 使用示例
if __name__ == "__main__":
# 裁剪区域 (左, 上, 右, 下)
crop_box = (100, 50, 500, 400) # 从(100,50)到(500,400)
# 执行批量裁剪
batch_crop_images(
input_dir="./input_images",
output_dir="./output_images",
crop_box=crop_box
)
中心裁剪(获取正方形图片)
def center_crop_images(input_dir, output_dir, target_size=256):
"""
中心裁剪为正方形
"""
os.makedirs(output_dir, exist_ok=True)
for img_path in glob.glob(os.path.join(input_dir, '*')):
try:
img = Image.open(img_path)
# 获取图片尺寸
width, height = img.size
# 计算裁剪区域
if width > height:
left = (width - height) // 2
top = 0
right = left + height
bottom = height
else:
left = 0
top = (height - width) // 2
right = width
bottom = top + width
# 执行中心裁剪
cropped_img = img.crop((left, top, right, bottom))
# 调整到目标尺寸
if target_size:
resized_img = cropped_img.resize((target_size, target_size),
Image.Resampling.LANCZOS)
else:
resized_img = cropped_img
# 保存
filename = os.path.basename(img_path)
output_path = os.path.join(output_dir, filename)
resized_img.save(output_path, quality=95)
print(f"✓ {filename} -> {cropped_img.size}")
except Exception as e:
print(f"✗ 处理失败 {img_path}: {e}")
按百分比裁剪
def percentage_crop_images(input_dir, output_dir, crop_percent):
"""
按百分比裁剪图片
参数:
crop_percent: 裁剪比例 [left%, top%, right%, bottom%]
"""
os.makedirs(output_dir, exist_ok=True)
for img_path in glob.glob(os.path.join(input_dir, '*')):
try:
img = Image.open(img_path)
width, height = img.size
# 将百分比转换为像素
left = int(width * crop_percent[0] / 100)
top = int(height * crop_percent[1] / 100)
right = int(width * crop_percent[2] / 100)
bottom = int(height * crop_percent[3] / 100)
# 裁剪
cropped_img = img.crop((left, top, right, bottom))
# 保存
filename = os.path.basename(img_path)
output_path = os.path.join(output_dir, filename)
cropped_img.save(output_path)
except Exception as e:
print(f"错误: {e}")
使用OpenCV(处理速度更快)
import cv2
import os
import glob
def batch_crop_opencv(input_dir, output_dir, crop_region):
"""
使用OpenCV批量裁剪图片
参数:
crop_region: (x, y, width, height)
"""
os.makedirs(output_dir, exist_ok=True)
x, y, w, h = crop_region
for img_path in glob.glob(os.path.join(input_dir, '*')):
try:
# 读取图片
img = cv2.imread(img_path)
if img is None:
continue
# 裁剪图片
cropped_img = img[y:y+h, x:x+w]
# 保存图片
filename = os.path.basename(img_path)
output_path = os.path.join(output_dir, f"cropped_{filename}")
cv2.imwrite(output_path, cropped_img)
print(f"✓ 裁剪完成: {filename}")
except Exception as e:
print(f"✗ 处理失败: {e}")
# 使用示例
batch_crop_opencv(
input_dir="./images",
output_dir="./cropped_images",
crop_region=(100, 50, 300, 400) # x=100, y=50, width=300, height=400
)
高级功能实现
交互式裁剪
def interactive_crop():
"""选择裁剪区域的交互式工具"""
import tkinter as tk
from tkinter import filedialog
# 选择输入文件夹
root = tk.Tk()
root.withdraw()
input_dir = filedialog.askdirectory(title="选择图片文件夹")
if not input_dir:
return
# 处理所有图片
for img_path in glob.glob(os.path.join(input_dir, '*.*')):
try:
img = Image.open(img_path)
img.show()
# 用户输入裁剪坐标
print(f"\n当前图片: {os.path.basename(img_path)}")
print(f"图片尺寸: {img.size}")
left = int(input("左坐标: "))
top = int(input("上坐标: "))
right = int(input("右坐标: "))
bottom = int(input("下坐标: "))
batch_crop_images(input_dir, "interactive_output",
(left, top, right, bottom))
except Exception as e:
print(f"错误: {e}")
# 启动交互式裁剪
# interactive_crop()
批量裁剪并添加水印
def crop_with_watermark(input_dir, output_dir, crop_box, watermark_text="Sample"):
"""裁剪并添加水印"""
from PIL import ImageDraw, ImageFont
os.makedirs(output_dir, exist_ok=True)
for img_path in glob.glob(os.path.join(input_dir, '*')):
try:
# 打开并裁剪
img = Image.open(img_path)
cropped_img = img.crop(crop_box)
# 添加水印
draw = ImageDraw.Draw(cropped_img)
font = ImageFont.truetype("arial.ttf", 30)
# 在右下角添加水印
text_width = draw.textlength(watermark_text, font=font)
text_height = 30
x = cropped_img.width - text_width - 10
y = cropped_img.height - text_height - 10
# 绘制水印
draw.text((x, y), watermark_text, font=font,
fill=(255, 255, 255, 128))
# 保存
filename = os.path.basename(img_path)
output_path = os.path.join(output_dir, filename)
cropped_img.save(output_path)
except Exception as e:
print(f"处理失败: {e}")
使用建议
安装依赖
pip install pillow opencv-python
选择建议
- 简单场景:使用Pillow库,易于理解和使用
- 高性能需求:使用OpenCV,处理速度快
- 批量处理:加入多线程或多进程提高效率
多线程优化
from concurrent.futures import ThreadPoolExecutor, as_completed
import threading
def process_single_image(img_path, output_dir, crop_box, lock):
"""处理单张图片"""
try:
img = Image.open(img_path)
cropped_img = img.crop(crop_box)
filename = os.path.basename(img_path)
output_path = os.path.join(output_dir, filename)
with lock:
cropped_img.save(output_path)
return True, filename
except Exception as e:
return False, str(e)
def batch_crop_multithreaded(input_dir, output_dir, crop_box, max_workers=4):
"""多线程批量裁剪"""
os.makedirs(output_dir, exist_ok=True)
lock = threading.Lock()
image_paths = glob.glob(os.path.join(input_dir, '*'))
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = []
for img_path in image_paths:
future = executor.submit(process_single_image,
img_path, output_dir, crop_box, lock)
futures.append(future)
# 处理结果
success = 0
failed = 0
for future in as_completed(futures):
result, info = future.result()
if result:
success += 1
print(f"✓ 成功: {info}")
else:
failed += 1
print(f"✗ 失败: {info}")
print(f"\n总处理: {len(image_paths)}, 成功: {success}, 失败: {failed}")
这个方案涵盖了从基础到高级的批量图片裁剪需求,您可以根据具体场景选择合适的实现方式。