Pillow 高级图像处理

Pillow 高级图像处理

超越基础,解锁 专业级图像处理 技巧(合成、滤镜、蒙版、颜色分析、批量自动化)


1. 透明图像合成(Alpha 贴图)

from PIL import Image

# 背景图
bg = Image.open("background.jpg").convert("RGBA")

# 前景图(带透明度)
overlay = Image.open("logo.png").convert("RGBA")
overlay = overlay.resize((200, 200), Image.LANCZOS)

# 粘贴(使用 overlay 自身作为 mask)
bg.paste(overlay, (50, 50), overlay)  # 关键:第三个参数是 mask

bg.save("composite.png")

核心paste(image, position, mask)mask 决定透明区域


2. 渐变透明水印(高级防盗)

from PIL import Image, ImageDraw, ImageFont
import numpy as np

def add_gradient_watermark(img_path, text="© 2025", opacity=80):
    img = Image.open(img_path).convert("RGBA")
    watermark = Image.new("RGBA", img.size, (255,255,255,0))

    draw = ImageDraw.Draw(watermark)
    font = ImageFont.truetype("simhei.ttf", 60)

    # 计算文字位置
    bbox = draw.textbbox((0,0), text, font=font)
    w = bbox[2] - bbox[0]
    h = bbox[3] - bbox[1]
    x = img.width - w - 50
    y = img.height - h - 50

    # 创建渐变蒙版
    mask = Image.new("L", img.size, 0)
    mask_draw = ImageDraw.Draw(mask)
    for i in range(0, 255, 5):
        alpha = int(opacity * (255-i)/255)
        mask_draw.rectangle([i, i, img.width-i, img.height-i], fill=alpha)

    # 绘制文字到蒙版
    draw.text((x, y), text, font=font, fill=(255,255,255,200))

    # 合成
    result = Image.composite(img, watermark, mask)
    return result.convert("RGB")

# 使用
result = add_gradient_watermark("photo.jpg")
result.save("watermarked_pro.jpg")

3. 自定义滤镜(卷积核)

from PIL import ImageFilter

# 3x3 锐化核
sharpen_kernel = ImageFilter.Kernel(
    (3, 3),
    [-1, -1, -1,
     -1,  9, -1,
     -1, -1, -1],
    scale=1, offset=0
)

img = Image.open("input.jpg")
sharp = img.filter(sharpen_kernel)
sharp.save("custom_sharpen.jpg")

常用卷积核

效果
浮雕[-2,-1,0, -1,1,1, 0,1,2]
边缘检测[-1,-1,-1, -1,8,-1, -1,-1,-1]
高斯模糊(近似)[1,2,1, 2,4,2, 1,2,1]scale=16

4. 颜色替换(换色)

from PIL import Image
import numpy as np

def replace_color(img_path, old_color, new_color, threshold=30):
    img = Image.open(img_path).convert("RGBA")
    data = np.array(img)

    # 构造颜色掩码
    r, g, b = old_color[:3]
    mask = (
        (abs(data[:,:,0] - r) < threshold) &
        (abs(data[:,:,1] - g) < threshold) &
        (abs(data[:,:,2] - b) < threshold)
    )

    # 替换颜色(保留透明度)
    data[mask] = new_color + (data[mask, 3],)  # 保留原 alpha

    result = Image.fromarray(data)
    return result

# 示例:把红色换成蓝色
img = replace_color("tshirt.png", (255,0,0), (0,0,255))
img.save("tshirt_blue.png")

5. 智能蒙版合成(人像抠图)

def paste_with_mask(background_path, foreground_path, mask_path, position=(0,0)):
    bg = Image.open(background_path).convert("RGBA")
    fg = Image.open(foreground_path).convert("RGBA")
    mask = Image.open(mask_path).convert("L")  # 灰度蒙版

    # 调整大小
    fg = fg.resize(mask.size)

    bg.paste(fg, position, mask)
    return bg

# 使用
result = paste_with_mask("bg.jpg", "person.png", "person_mask.png", (100, 50))
result.save("cutout.png")

6. 图像直方图分析

from PIL import ImageStat

img = Image.open("photo.jpg").convert("RGB")
stat = ImageStat.Stat(img)

print("亮度均值:", stat.mean)        # [R, G, B]
print("标准差:", stat.stddev)
print("中位数:", stat.median)
print("极值:", stat.extrema)         # [(minR,maxR), ...]

自动曝光校正

def auto_exposure(img):
    stat = ImageStat.Stat(img)
    target = 128  # 目标亮度
    factor = target / np.mean(stat.mean)
    return ImageEnhance.Brightness(img).enhance(factor)

img = auto_exposure(Image.open("dark.jpg"))
img.save("auto_exposure.jpg")

7. 批量处理 + 多线程

import os
from PIL import Image
from concurrent.futures import ThreadPoolExecutor

def process_image(filepath, output_dir, size=(800, None)):
    try:
        img = Image.open(filepath)
        if size[1] is None:  # 等比缩放
            img.thumbnail((size[0], 10000))
        else:
            img = img.resize(size)

        name = os.path.basename(filepath)
        img.save(os.path.join(output_dir, name), quality=90)
        print(f"处理完成: {name}")
    except Exception as e:
        print(f"错误: {filepath} - {e}")

# 批量处理
input_dir = "raw/"
output_dir = "processed/"
os.makedirs(output_dir, exist_ok=True)

files = [os.path.join(input_dir, f) for f in os.listdir(input_dir) if f.endswith(('.jpg', '.png'))]

with ThreadPoolExecutor(max_workers=4) as executor:
    executor.map(lambda f: process_image(f, output_dir), files)

8. 生成缩略图 + 智能裁剪(方形)

def smart_thumbnail(img, size=300):
    img = img.convert("RGB")
    w, h = img.size

    # 1. 缩放到短边为 size
    if w < h:
        img = img.resize((size, int(h*size/w)), Image.LANCZOS)
    else:
        img = img.resize((int(w*size/h), size), Image.LANCZOS)

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

    return img

# 使用
thumb = smart_thumbnail(Image.open("photo.jpg"))
thumb.save("thumb.jpg")

9. 动态生成验证码

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

def generate_captcha(text="AB12", size=(200, 80)):
    img = Image.new("RGB", size, "white")
    draw = ImageDraw.Draw(img)
    font = ImageFont.truetype("arial.ttf", 40)

    # 随机颜色文字
    for i, char in enumerate(text):
        x = 20 + i * 40 + random.randint(-10, 10)
        y = 15 + random.randint(-10, 10)
        color = (random.randint(0,150), random.randint(0,150), random.randint(0,150))
        draw.text((x, y), char, font=font, fill=color)

    # 干扰线
    for _ in range(10):
        x1, y1 = random.randint(0, size[0]), random.randint(0, size[1])
        x2, y2 = random.randint(0, size[0]), random.randint(0, size[1])
        draw.line([(x1,y1), (x2,y2)], fill=(100,100,100), width=1)

    # 轻微模糊
    img = img.filter(ImageFilter.GaussianBlur(0.5))

    return img

captcha = generate_captcha("Xy9K")
captcha.save("captcha.png")

10. 图像相似度检测(感知哈希)

from PIL import Image
import numpy as np

def phash(img, hash_size=8):
    img = img.convert("L").resize((hash_size, hash_size), Image.LANCZOS)
    pixels = np.array(img).flatten()
    avg = pixels.mean()
    return ''.join('1' if p > avg else '0' for p in pixels)

def hamming_distance(s1, s2):
    return sum(c1 != c2 for c1, c2 in zip(s1, s2))

# 比较两张图
img1 = Image.open("a.jpg")
img2 = Image.open("b.jpg")
dist = hamming_distance(phash(img1), phash(img2))
print(f"汉明距离: {dist} (越小越相似,<10 通常为同一图)")

高级技巧总结表

功能关键 API
透明合成paste(..., mask)
渐变蒙版Image.composite()
自定义滤镜ImageFilter.Kernel()
颜色替换numpy + Image.fromarray()
直方图分析ImageStat.Stat()
多线程批量ThreadPoolExecutor
智能缩略图thumbnail() + crop()
验证码random + GaussianBlur
相似度检测phash + 汉明距离

推荐工具链

pip install pillow numpy opencv-python  # 增强处理能力

复杂任务建议:Pillow(读写)+ NumPy(计算)+ OpenCV(算法)


一键运行完整示例

# 保存为 advanced_pillow.py
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import numpy as np

img = Image.open("input.jpg").convert("RGBA")

# 1. 智能缩略图
thumb = img.copy()
thumb.thumbnail((300, 300))
w, h = thumb.size
size = min(w, h)
thumb = thumb.crop(((w-size)//2, (h-size)//2, (w+size)//2, (h+size)//2))

# 2. 添加高级水印
overlay = Image.new("RGBA", img.size, (0,0,0,0))
draw = ImageDraw.Draw(overlay)
font = ImageFont.truetype("simhei.ttf", 50)
draw.text((50, 50), "机密文件", fill=(255,0,0,100), font=font)

# 渐变蒙版
mask = Image.new("L", img.size, 0)
for i in range(200):
    alpha = int(100 * (1 - i/200))
    draw.rectangle([i, i, img.width-i, img.height-i], fill=alpha, outline=alpha)

result = Image.composite(img, overlay, mask)
result = result.convert("RGB")

# 3. 保存
result.save("advanced_output.jpg", quality=95)
thumb.save("thumb.jpg")
print("高级处理完成!")

掌握以上技巧,你已进入 Pillow 高级玩家行列!


需要我为你打包成 命令行工具Web APIGUI 应用 吗?
欢迎继续提问!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注