Python图像处理入门:用Pillow快速上手

1. Pillow简介

日常开发里,做网站缩略图、生成随机验证码、批量裁剪图片尺寸,不用找复杂的Photoshop脚本或付费API,Python的Pillow库就能轻松搞定。

它是老牌 Python Imaging Library(PIL)的现代化分支:在保留PIL简洁API的同时,完全兼容Python3,还添加了新格式支持、性能优化等特性,是目前Python生态中最流行的轻量级图像处理工具。

核心亮点:

  • 支持超40种图像格式(JPEG/PNG/BMP/GIF/TIFF/WebP等)
  • 覆盖基础到进阶的常用图像处理需求
  • 代码逻辑清晰,新手友好
  • 社区活跃,维护稳定

2. 快速安装

标准pip安装

pip install pillow

Anaconda/Miniconda环境

conda install pillow

Linux/macOS权限提示:普通用户建议用--user参数避免修改系统环境:

pip install --user pillow

3. 基础图像操作

3.1 打开、查看与保存

这是Pillow最核心的第一步,代码几乎和“打开记事本”一样直观:

from PIL import Image

# 用with语句自动管理文件句柄(推荐最佳实践)
with Image.open("test.jpg") as im:
    # 打印图像元信息
    print(f"📄 格式: {im.format}")
    print(f"📐 尺寸(宽×高): {im.size[0]}×{im.size[1]}")
    print(f"🎨 色彩模式: {im.mode}")  # RGB/RGBA/L(灰度)/P(索引色)等

    # 自动根据扩展名转换格式保存
    im.save("output.png")

3.2 调整大小

有两种常用方式:

  • thumbnail()按比例缩小,原地修改图像,不会超出指定尺寸
  • resize()强制拉伸/缩放,返回新图像,尺寸完全可控
with Image.open("test.jpg") as im:
    w, h = im.size  # 解包元组更方便

    # 方式1:生成比例缩小到宽≤800的缩略图(保持纵横比)
    im.thumbnail((800, 800))
    im.save("thumbnail_800w.jpg", quality=95)  # JPEG质量1-100,推荐85-95

    # 方式2:强制调整为600×400(会变形,适合需要固定尺寸的场景)
    fixed_size_im = im.resize((600, 400))
    fixed_size_im.save("fixed_600x400.jpg")

3.3 旋转与翻转

都是返回新图像的非原地操作:

with Image.open("test.jpg") as im:
    # 逆时针旋转45度,默认背景为透明或黑色(取决于原图像模式)
    rotated_45 = im.rotate(45, expand=True)  # expand=True会自动扩大画布装下旋转后的图像

    # 水平/垂直翻转
    flip_h = im.transpose(Image.FLIP_LEFT_RIGHT)
    flip_v = im.transpose(Image.FLIP_TOP_BOTTOM)

    rotated_45.save("rotated_45_expanded.png")

4. 一键套用内置滤镜

Pillow封装了十几种常用滤镜,不用写复杂算法:

from PIL import Image, ImageFilter

with Image.open("test.jpg") as im:
    # 选择常用滤镜演示
    filters = [
        ("blur", ImageFilter.BLUR),          # 模糊
        ("contour", ImageFilter.CONTOUR),    # 轮廓提取
        ("emboss", ImageFilter.EMBOSS),      # 浮雕
        ("sharpen", ImageFilter.SHARPEN),    # 锐化
    ]

    # 批量生成并保存
    for name, f in filters:
        filtered = im.filter(f)
        filtered.save(f"filtered_{name}.jpg")

5. 简单图像绘制

搭配ImageDrawImageFont,可以生成验证码、水印、简单图表等:

5.1 基础图形绘制

from PIL import Image, ImageDraw

# 创建白色RGB画布
canvas = Image.new("RGB", (400, 300), color="white")
draw = ImageDraw.Draw(canvas)

# 画红色对角线(坐标:(x1,y1,x2,y2))
draw.line((0, 0, 400, 300), fill="red", width=3)

# 画绿色填充、蓝色边框的矩形(坐标:(左,上,右,下),注意右/下是开区间)
draw.rectangle((100, 100, 300, 200), fill="#00FF00", outline="#0000FF", width=2)

# 画蓝色圆形(本质是画椭圆的宽高相等版)
draw.ellipse((150, 50, 250, 150), fill="blue")

canvas.save("basic_drawing.png")

5.2 实用小工具:生成4位验证码

很多网站的验证码逻辑都可以用这个简化版实现:

from PIL import Image, ImageDraw, ImageFont, ImageFilter
import random

def gen_captcha(width=240, height=60, char_len=4):
    # 1. 创建浅灰背景画布
    bg_color = (240, 240, 240)
    img = Image.new("RGB", (width, height), bg_color)
    draw = ImageDraw.Draw(img)

    # 2. 加载字体(找不到系统字体就用默认位图字体)
    try:
        # Windows路径:C:/Windows/Fonts/arial.ttf
        # macOS路径:/Library/Fonts/Arial.ttf
        # Linux路径:/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf
        font = ImageFont.truetype("arial.ttf", size=40)
    except IOError:
        font = ImageFont.load_default()

    # 3. 生成随机大写字母
    captcha_text = "".join([chr(random.randint(65, 90)) for _ in range(char_len)])

    # 4. 绘制文字(带随机偏移和颜色)
    text_w, text_h = draw.textsize(captcha_text, font=font)
    start_x = (width - text_w) // 2
    start_y = (height - text_h) // 2
    for i, char in enumerate(captcha_text):
        x_offset = random.randint(-5, 5)
        y_offset = random.randint(-3, 3)
        draw.text(
            (start_x + i * (text_w//char_len) + x_offset, start_y + y_offset),
            char,
            font=font,
            fill=(random.randint(0, 100), random.randint(0, 100), random.randint(0, 100))
        )

    # 5. 加轻微模糊增加识别难度
    img = img.filter(ImageFilter.GaussianBlur(radius=1.2))

    return img, captcha_text

# 调用生成
if __name__ == "__main__":
    captcha_img, code = gen_captcha()
    captcha_img.save("my_captcha.jpg")
    print(f"✅ 验证码已生成,内容为:{code}")

6. 进阶小功能

6.1 带透明度的图像合成

比如把水印PNG叠加到照片上:

from PIL import Image

with Image.open("photo.jpg") as bg, Image.open("watermark.png") as wm:
    # 确保水印有RGBA通道
    if wm.mode != "RGBA":
        wm = wm.convert("RGBA")
    
    # 缩小水印到照片的1/4大小(放在右下角)
    wm_w, wm_h = wm.size
    bg_w, bg_h = bg.size
    wm.thumbnail((bg_w//4, bg_h//4))

    # 计算右下角坐标
    paste_x = bg_w - wm.size[0] - 20  # 留20px边距
    paste_y = bg_h - wm.size[1] - 20

    # 带透明度叠加(wm的alpha通道控制透明部分不覆盖背景)
    bg.paste(wm, (paste_x, paste_y), wm)
    bg.save("photo_with_watermark.jpg")

7. 常见问题速查

  1. 系统字体加载失败
    替换代码里的字体路径为对应系统的绝对路径,或者直接使用ImageFont.load_default()

  2. RGBA转JPEG报错
    JPEG不支持透明度,需要先转RGB:

    if im.mode == "RGBA":
        im = im.convert("RGB")
  3. 大图像处理内存溢出
    优先用thumbnail()按比例缩小,避免直接resize()超大尺寸

8. 学习资源

通过本教程,你已经掌握了Pillow的80%核心使用场景,剩下的可以根据官方文档按需探索!