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 API 或 GUI 应用 吗?
欢迎继续提问!