查看: 199|回复: 1

Python+Pillow批量裁剪图片的三种实用场景与代码详解

[复制链接]
发表于 3 小时前 | 显示全部楼层 |阅读模式
在日常开发中,无论是电商主图统一、社交媒体头像裁切,还是证件照固定比例,批量裁剪图片都是高频需求。手动操作繁琐且耗时,而借助 Python 的 Pillow 库,几行代码即可自动化完成。本文整理了三种最常用的批量裁剪场景,并附上可直接运行的代码示例,涵盖固定尺寸裁剪、居中正方形裁剪、精确坐标裁剪,以及裁剪后添加水印的进阶操作。
  1. from PIL import Image
  2. import os
复制代码

上述是必备的导入,后续所有函数均基于此。注意,Pillow 需要提前安装(pip install Pillow)。

## 场景一:固定尺寸裁剪(从左上角切取)

如果所有图片都需要裁剪成完全相同的宽高(例如统一展示图的像素尺寸),最直接的方式是从图片左上角坐标 (0,0) 开始截取指定的矩形区域。
  1. def crop_fixed_size(input_dir, output_dir, width, height):
  2.     os.makedirs(output_dir, exist_ok=True)
  3.     for filename in os.listdir(input_dir):
  4.         if not filename.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp', '.webp')):
  5.             continue
  6.         img_path = os.path.join(input_dir, filename)
  7.         img = Image.open(img_path)
  8.         # 裁剪区域:从左上角到(width, height)
  9.         cropped = img.crop((0, 0, width, height))
  10.         cropped.save(os.path.join(output_dir, filename))
  11.         print(f"{filename} → {width}x{height}")
复制代码

调用示例:
  1. crop_fixed_size(r'D:\原图', r'D:\裁剪后', 800, 600)
复制代码

参数说明:input_dir 为存放原图的文件夹路径,output_dir 为裁剪后图片的输出目录,width 和 height 为裁剪目标尺寸。注意:若原图尺寸小于目标宽高,程序会抛出异常,此时可考虑使用场景二的居中裁剪作为替代方案。

## 场景二:居中裁剪成正方形(最常用)

头像、商品主图等通常要求正方形。该方法以原图最小边为边长,从中心位置切出正方形区域,随后可缩放到任意目标尺寸,确保主体内容不丢失,且无拉伸变形。
  1. def crop_center_square(input_dir, output_dir, size):
  2.     os.makedirs(output_dir, exist_ok=True)
  3.     for filename in os.listdir(input_dir):
  4.         if not filename.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp', '.webp')):
  5.             continue
  6.         img_path = os.path.join(input_dir, filename)
  7.         img = Image.open(img_path)
  8.         # 取最小边作为正方形边长
  9.         min_side = min(img.width, img.height)
  10.         left = (img.width - min_side) // 2
  11.         top = (img.height - min_side) // 2
  12.         right = left + min_side
  13.         bottom = top + min_side
  14.         cropped = img.crop((left, top, right, bottom))
  15.         # 缩放到目标尺寸(可选,若需要固定像素正方形则保留)
  16.         cropped = cropped.resize((size, size), Image.LANCZOS)
  17.         cropped.save(os.path.join(output_dir, filename))
  18.         print(f"{filename} → {size}x{size}")
复制代码

调用示例:
  1. crop_center_square(r'D:\照片', r'D:\头像', 500)
复制代码

参数 size 为最终正方形图片的边长。内部先通过计算中心偏移量确定 crop 盒,再使用 LANCZOS 重采样算法缩放,以保证清晰度。该方案对横竖图均能保留中央主体区域。

## 场景三:按坐标批量裁剪(精确控制)

当需要固定区域(如证件照头部、截图中某个按钮)时,可手动指定 (left, top, right, bottom) 四个坐标进行精确裁剪。
  1. def crop_by_coordinates(input_dir, output_dir, coords):
  2.     """
  3.     coords: (left, top, right, bottom)
  4.     例如:(100, 50, 400, 400) 表示从(100,50)到(400,400)的矩形区域
  5.     """
  6.     os.makedirs(output_dir, exist_ok=True)
  7.     left, top, right, bottom = coords
  8.     for filename in os.listdir(input_dir):
  9.         if not filename.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp', '.webp')):
  10.             continue
  11.         img_path = os.path.join(input_dir, filename)
  12.         img = Image.open(img_path)
  13.         # 检查原图尺寸是否满足裁剪区域
  14.         if img.width < right or img.height < bottom:
  15.             print(f"⚠️ {filename} 尺寸不足,跳过")
  16.             continue
  17.         cropped = img.crop((left, top, right, bottom))
  18.         cropped.save(os.path.join(output_dir, filename))
  19.         print(f"{filename} → 裁剪区域 {coords}")
复制代码

调用示例:
  1. crop_by_coordinates(r'D:\截图', r'D:\裁剪后', (100, 50, 600, 550))
复制代码

该函数增加了尺寸校验,避免因原图过小导致数据越界。对于一组需要统一区域裁切的图片,只需设定一次坐标即可批量处理。

## 进阶:批量裁剪 + 加水印(一气呵成)

电商平台常需要在商品图上添加店铺水印。以下函数在居中裁剪并缩放到正方形后,于图片底部居中位置叠加半透明文字水印。
  1. from PIL import Image, ImageDraw, ImageFont
  2. def crop_and_watermark(input_dir, output_dir, size, watermark_text):
  3.     os.makedirs(output_dir, exist_ok=True)
  4.     for filename in os.listdir(input_dir):
  5.         if not filename.lower().endswith(('.jpg', '.jpeg', '.png')):
  6.             continue
  7.         img_path = os.path.join(input_dir, filename)
  8.         img = Image.open(img_path)
  9.         # 居中裁剪正方形
  10.         min_side = min(img.width, img.height)
  11.         left = (img.width - min_side) // 2
  12.         top = (img.height - min_side) // 2
  13.         cropped = img.crop((left, top, left + min_side, top + min_side))
  14.         cropped = cropped.resize((size, size), Image.LANCZOS)
  15.         # 添加水印
  16.         draw = ImageDraw.Draw(cropped)
  17.         font = ImageFont.truetype("simhei.ttf", int(size * 0.08))  # Windows 系统自带黑体
  18.         text_bbox = draw.textbbox((0, 0), watermark_text, font=font)
  19.         text_width = text_bbox[2] - text_bbox[0]
  20.         x = (size - text_width) // 2
  21.         y = size - int(size * 0.1)
  22.         draw.text((x, y), watermark_text, fill=(255, 255, 255, 128), font=font)
  23.         cropped.save(os.path.join(output_dir, filename), quality=95)
  24.         print(f"{filename} → 裁剪+水印完成")
复制代码

调用示例:
  1. crop_and_watermark(r'D:\商品图', r'D:\成品', 800, '店铺名称')
复制代码

注意:若在 Mac/Linux 下运行,需将字体路径改为系统中已安装的中文 ttf 文件路径(如 /System/Library/Fonts/Supplemental/Arial Unicode.ttf),或者先安装中文字体。

## 常见问题与解决方案

- **图片透明通道导致保存后变黑底**:在保存前执行 cropped = cropped.convert('RGB')。
- **裁剪后图片模糊**:resize() 时使用 Image.LANCZOS 代替默认的 Image.BILINEAR。
- **批量处理速度慢**:可引入 concurrent.futures.ThreadPoolExecutor 实现多线程并发。
- **需保留EXIF信息**:使用 piexif 库,或 pillow-heif 处理 HEIC 格式。

## 总结

批量裁剪的核心流程始终是:打开图片 → 计算裁剪区域 → 执行 crop( ) → 保存结果。本文提供的三个函数覆盖了绝大多数批量裁剪需求:固定尺寸、居中正方形、精确坐标。若需更高级的功能(如基于人脸检测自动裁剪或添加圆角),可在此框架基础上扩展。

将以上代码保存为 .py 文件,只需修改输入输出目录及尺寸参数,即可一键完成成百上千张图片的裁剪工作,极大提升效率。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python+Pillow批量裁剪图片的三种实用场景与代码详解

楼主这个帖子太实用了!正好最近在整理一批商品图,手动裁剪到崩溃,看到你这三种场景的代码直接拿过来就能用,省了我好多时间。特别是那个居中正方形裁剪,还带了 LANCZOS 缩放,连清晰度都照顾到了,真的贴心。不过看标题里提到了“裁剪后添加水印”,正文好像还没写到那部分?是打算在下一个回复里补全吗?期待进阶玩法!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-22 15:05 , Processed in 0.036977 second(s), 19 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部