📅 系列:一起学Python | 难度:⭐⭐
🔗 上期回顾:Matplotlib 函数速查手册
前面我们学了十几天的 Matplotlib,专注数据可视化。但现实世界还有另一类需求:
批量压缩图片尺寸
给照片加文字水印
生成验证码图片
裁剪头像、做缩略图
图片格式转换(JPG ↔ PNG)
这些任务,Pillow 是 Python 的最佳选择。
Pillow 是什么?
Python Imaging Library (PIL) 的"继任者",PIL 已停止维护
支持 30+ 种图像格式(JPEG、PNG、GIF、BMP、TIFF、WebP 等)
提供旋转、裁剪、缩放、滤镜、文字绘制等全套图像处理功能
API 简单直观,比 OpenCV 更适合日常图像处理
一句话:Matplotlib 负责"画图",Pillow 负责"修图"。
pip install pillowfrom PIL import Image, ImageDraw, ImageFont, ImageFilterpillow,但导入时仍然用 from PIL import ...,这是历史遗留。Pillow 中,一切操作围绕 Image 对象 展开:
from PIL import Image# 打开现有图片img = Image.open("photo.jpg")# 或创建一张空白画布img = Image.new('RGB', (800, 600), color=(255, 255, 255))
from PIL import Imagefrom io import BytesIOimport requests# 从网络URL加载图片(核心代码,后续所有示例复用)url = "https://picsum.photos/600/400"response = requests.get(url, timeout=15)img = Image.open(BytesIO(response.content)).convert('RGB')print(f"加载成功: {img.size}, 格式: {img.format}")# 显示原图(弹窗预览,适合本地调试)img.show()


from PIL import ImageFontimport os# ================= 1. 字体加载(解决中文乱码的核心) =================font_path = "simhei.ttf" # 确保当前目录有 simhei.ttfif not os.path.exists(font_path):font_path = "/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc" # 备用系统字体# Pillow 使用 ImageFont.truetype 加载font = ImageFont.truetype(font_path, size=24)
from PIL import Imagefrom io import BytesIOimport requestsurl = "https://picsum.photos/600/400"response = requests.get(url, timeout=15)img = Image.open(BytesIO(response.content))print(f"图片格式: {img.format}") # JPEGprint(f"图片大小: {img.size}") # (600, 400)print(f"图片模式: {img.mode}") # RGB# 显示原图img.show()# 保存为其他格式img.save("output.png")

from PIL import Imagefrom io import BytesIOimport requestsurl = "https://picsum.photos/600/400"response = requests.get(url, timeout=15)img = Image.open(BytesIO(response.content)).convert('RGB')# 显示原图img.show()# crop((左, 上, 右, 下)),注意是坐标不是宽高cropped = img.crop((150, 100, 450, 300))# 显示裁剪结果cropped.show()cropped.save("cropped.jpg")

(left, upper, right, lower),先左上角,后右下角。from PIL import Imagefrom io import BytesIOimport requestsurl = "https://picsum.photos/600/400"response = requests.get(url, timeout=15)img = Image.open(BytesIO(response.content)).convert('RGB')# 显示原图img.show()# 方法1:resize 指定精确尺寸(可能变形)resized = img.resize((300, 200))resized.show()# 方法2:thumbnail 保持比例,不超过给定尺寸thumb = img.copy()thumb.thumbnail((150, 100))thumb.show()print(f"缩略图实际尺寸: {thumb.size}")


from PIL import Imagefrom io import BytesIOimport requestsurl = "https://picsum.photos/600/400"response = requests.get(url, timeout=15)img = Image.open(BytesIO(response.content)).convert('RGB')# 显示原图img.show()# 旋转45度,expand=True 扩展画布防止裁剪rotated = img.rotate(45, expand=True)rotated.show()# 旋转90度rotated90 = img.rotate(90, expand=True)rotated90.show()




from PIL import Image, ImageDraw, ImageFontfrom io import BytesIOimport requestsimport os# ================= 1. 字体加载(解决中文乱码的核心) =================font_path = "simhei.ttf"if not os.path.exists(font_path):font_path = "/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc"font = ImageFont.truetype(font_path, size=30)# 加载网络图片url = "https://picsum.photos/600/400"response = requests.get(url, timeout=15)img = Image.open(BytesIO(response.content)).convert('RGB')# 显示原图img.show()# 创建画笔draw = ImageDraw.Draw(img)# 添加文字水印draw.text((20, 20), "一起学Python", fill=(255, 255, 255), font=font)draw.text((20, 350), "第119天", fill=(255, 255, 255), font=font)# 显示结果img.show()img.save("watermarked.jpg")

💡 进阶技巧:ImageDraw 还可以画矩形、椭圆、线条:
draw.rectangle([x1, y1, x2, y2], fill="red", outline="black")draw.ellipse([x1, y1, x2, y2], fill="blue")
把五大操作串起来,写一个完整的处理函数:
from PIL import Image, ImageDraw, ImageFontfrom io import BytesIOimport requestsimport os# ================= 1. 字体加载(解决报错的核心) =================font_path = "simhei.ttf"if not os.path.exists(font_path):font_path = "/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc"font = ImageFont.truetype(font_path, size=20)def process_image(url, output_name):"""下载 → 裁剪 → 缩放 → 旋转 → 加水印 → 保存"""# 1. 打开网络图片resp = requests.get(url, timeout=15)img = Image.open(BytesIO(resp.content)).convert('RGB')# 2. 裁剪中间区域w, h = img.sizeimg = img.crop((w*0.2, h*0.2, w*0.8, h*0.8))# 3. 缩放到固定宽度img = img.resize((400, 300))# 4. 旋转5度(微调整)img = img.rotate(5, expand=True)# 5. 加水印draw = ImageDraw.Draw(img)draw.text((10, 10), "一起学Python", fill=(255, 255, 255), font=font)# 6. 保存img.save(output_name, quality=90)print(f"✅ 已处理: {output_name}")# 7. 显示结果img.show()# 使用process_image("https://picsum.photos/600/400", "final_output.jpg")


from PIL import Image, ImageDraw, ImageFontfrom io import BytesIOimport requests# 网络加载img = Image.open(BytesIO(requests.get(url).content)).convert('RGB')# 查看信息print(img.format, img.size, img.mode)# 显示img.show()# 保存img.save("output.jpg", quality=95)# 裁剪cropped = img.crop((left, upper, right, bottom))# 缩放resized = img.resize((300, 200))thumb = img.copy()thumb.thumbnail((150, 100))# 旋转rotated = img.rotate(45, expand=True)# 水印draw = ImageDraw.Draw(img)font = ImageFont.truetype("simhei.ttf", size=24)draw.text((10, 10), "水印文字", fill=(255, 255, 255), font=font)
今天我们掌握了 Pillow 图像处理的五大基础技能:
✅ Image.open() —— 打开网络/本地图片
✅ img.crop() —— 裁剪局部区域
✅ img.resize() / img.thumbnail() —— 缩放与缩略图
✅ img.rotate() —— 旋转任意角度
✅ ImageDraw + ImageFont —— 添加文字水印
✅ requests + BytesIO —— 网络图片直接处理
关键记忆:Pillow 的操作链 = 打开 → 处理(裁剪/缩放/旋转/水印)→ 保存。

🎯 今日金句:在 Pillow 的世界里,每一张图片都是一张画布——裁剪是取景,缩放是构图,旋转是视角,水印是签名。掌握这五大操作,你就拥有了数字图像的"瑞士军刀"。