Pillow 图像处理完全指南

知识库
知识库文档
/tech-stacks/pillow/tutorial/Pillow 图像处理完全指南.md

文档

Pillow 图像处理完全指南

背景

从用户头像裁剪到批量水印添加,从验证码生成到图像格式转换,Pillow 几乎覆盖了 Web 开发中所有图像处理需求。它也是 scikit-image、torchvision 等更高级库的图像读写基础。


第 1 章:图像基本操作

from PIL import Image

# 打开与属性
img = Image.open("photo.jpg")
print(img.format)      # JPEG
print(img.size)        # (1920, 1080)
print(img.mode)        # RGB
print(img.info)        # 元数据字典

# 格式转换
img.save("photo.png", "PNG")
img.save("photo.webp", "WEBP", quality=80)

# 图像模式转换
gray = img.convert("L")       # 灰度
rgba = img.convert("RGBA")    # 透明通道
cmyk = img.convert("CMYK")    # 印刷色

第 2 章:ImageDraw 绘图

from PIL import Image, ImageDraw, ImageFont

img = Image.new("RGB", (800, 600), color=(30, 30, 30))
draw = ImageDraw.Draw(img)

# 基本形状
draw.rectangle([50, 50, 300, 200], fill=(60, 120, 200), outline="white", width=3)
draw.ellipse([400, 300, 700, 500], fill=(200, 60, 60))
draw.line([(50, 400), (750, 400)], fill="yellow", width=5)
draw.polygon([(400, 100), (550, 50), (600, 150)], fill="green")

# 文字
font = ImageFont.truetype("arial.ttf", size=48)
draw.text((250, 550), "Hello, Pillow!", fill="white", font=font)

img.save("drawing.png")

第 3 章:像素级操作

# 逐像素访问(慢,适用于小图)
pixels = img.load()
for y in range(img.height):
    for x in range(img.width):
        r, g, b = pixels[x, y]
        # 替换所有接近白色的像素为透明
        if r > 240 and g > 240 and b > 240:
            pixels[x, y] = (0, 0, 0, 0)

# 批量像素操作(快,使用 NumPy)
import numpy as np
arr = np.array(img)
arr[arr > 200] = 255  # 高通阈值
result = Image.fromarray(arr)

第 4 章:批量处理实战

import os
from PIL import Image, ImageOps
from pathlib import Path

def batch_process(input_dir, output_dir, size=(800, 800)):
    """批量缩略图 + 灰度 + 增强对比度"""
    output_dir = Path(output_dir)
    output_dir.mkdir(parents=True, exist_ok=True)

    for filepath in Path(input_dir).glob("*.*"):
        if filepath.suffix.lower() not in {".jpg", ".jpeg", ".png", ".webp"}:
            continue

        with Image.open(filepath) as img:
            # 转换为 RGB(统一格式)
            if img.mode in ("RGBA", "P"):
                img = img.convert("RGB")

            # 缩略图
            img.thumbnail(size)

            # 自动对比度
            img = ImageOps.autocontrast(img)

            # 保存
            out_path = output_dir / f"processed_{filepath.stem}.jpg"
            img.save(out_path, "JPEG", quality=85, optimize=True)
            print(f"✓ {out_path}")

batch_process("./raw_photos", "./processed_photos")

第 5 章:与 Web 框架集成

# Flask 示例:上传并生成头像缩略图
from flask import Flask, request
from PIL import Image
from io import BytesIO

@app.route("/upload-avatar", methods=["POST"])
def upload_avatar():
    file = request.files["avatar"]
    img = Image.open(file.stream)

    # 裁剪为正方形中心
    w, h = img.size
    size = min(w, h)
    left = (w - size) // 2
    top = (h - size) // 2
    img = img.crop((left, top, left + size, top + size))

    # 三档缩略图
    sizes = {"lg": 512, "md": 128, "sm": 64}
    urls = {}
    for name, px in sizes.items():
        thumb = img.resize((px, px), Image.LANCZOS)
        buf = BytesIO()
        thumb.save(buf, "JPEG", quality=85)
        buf.seek(0)
        # 上传到 S3 / 保存到磁盘...
        urls[name] = f"/avatars/{name}_{user_id}.jpg"

    return {"urls": urls}

思考题

  1. Image.thumbnail()Image.resize() 有什么区别?何时用哪个?
  2. 如何在 Pillow 中实现图片的颜色直方图均衡化?
  3. 处理超大图片(>10000x10000)时,Pillow 有哪些内存优化技巧?

信息

路径
/tech-stacks/pillow/tutorial/Pillow 图像处理完全指南.md
更新时间
2026/5/30