Skip to content

Pillow - 强大的Python图像处理库

在 Python 2 中,Python Image Library 是一个非常好用的图像处理库,但它不支持 Python 3,所以有人(Alex Clark和Contributors)将其迁移至 Python 3,并重命名为 Pillow。

官方文档地址为 https://pillow.readthedocs.io/en/stable/ ,PyPi 地址为 https://pypi.org/project/pillow/

安装

使用 Python 3 自带的包管理器就可以安装。

shell
pip install pillow

若运行速度缓慢,可考虑加上国内镜像源。

shell
# 如
pip install pillow -i https://mirrors.aliyun.com/pypi/simple/

使用 - Image 类

Python Imaging Library中最重要的类是Image类,它在模块中以相同的名称定义。可以通过多种方式创建此类的实例;从文件加载图像、处理其他图像或从头开始创建图像。

要从文件加载图像,需使用 Image 模块中的 open() 函数:

python
>>> from PIL import Image
>>> im = Image.open("img.png")

如果成功,这个函数返回一个Image对象。现在可以使用实例属性来检查文件内容:

python
>>> print(im.format, im.size, im.mode)
PNG (241, 243) RGB

调用此对象的 show() 方法可以显示图片。

python
>>> im.show()

这个方法会使用本地计算机的软件打开此图片,比如 WPS 图片。

需要注意的是,这种方法显示图片效率不高,因为 PIL 将此图片转化为一个临时文件,然后再唤起程序。

在结束使用一张图片的资源后,调用 Image 对象的 close() 方法释放资源。

使用 - 转换图片

Python Imaging Library 支持多种图像文件格式。要从磁盘读取文件,需要使用 Image 模块中的 open() 函数。你不需要知道文件格式就可以打开一个文件。库会根据文件的内容自动确定格式。

要保存文件,请使用 Image 类的 save() 方法。若不指定格式,PIL 会将图片保存为图片原格式。

python
from PIL import Image

im = Image.open("img.png")

im.save("img", "WEBP")
im.close()

若图片尺寸过大,PIL 可转换图像尺寸以便于节省空间,典型的使用场景就是缩略图。

python
from PIL import Image

size = (128, 128)

im = Image.open("img.png")
im.thumbnail(size)

# 若是要调整尺寸,就使用:
# im.resize(size)

im.show()
im.close()

使用 - 剪切、粘贴和合并图像

裁剪图片使用 Image 对象的 crop() 方法,该方法接收一个包含四角坐标的四元元组。

python
box = (100, 100, 400, 400)
region = im.crop(box)

坐标的位置依次是左上右下,左上角为坐标原点 (0, 0),每一个像素为一个单位。

现在可以将它们粘贴回去。

python
region = region.transpose(Image.Transpose.ROTATE_180)
im.paste(region, box)

粘贴回区域时,区域的大小必须与给定区域完全匹配。此外,该区域不能延伸到图像之外。然而,原始图像和区域的模式不需要匹配。如果没有,则在粘贴之前会自动转换该区域(有关详细信息,请参阅下面的颜色转换部分)。

合并文档这里不演示了。

使用 - 几何变换

PIL.Image.Image类包含用于 resize()rotate() 图像的方法。前者采用一个元组,给出新的大小,后者采用逆时针方向的角度。

python
out = im.resize((128, 128))
out = im.rotate(45) # degrees counter-clockwise

要将图像旋转90度,我们可以使用 rotate() 方法或 transpose() 方法。后者也可以用于围绕其水平或垂直轴翻转图像。

python
out = im.transpose(Image.Transpose.FLIP_LEFT_RIGHT)
out = im.transpose(Image.Transpose.FLIP_TOP_BOTTOM)
out = im.transpose(Image.Transpose.ROTATE_90)
out = im.transpose(Image.Transpose.ROTATE_180)
out = im.transpose(Image.Transpose.ROTATE_270)

如果 transpose(ROTATE) 标志为真,则 rotate() 操作也可以与 expand 操作相同地执行,以提供对图像大小的相同改变。

更一般形式的图像变换可以通过 transform() 方法进行。

上面的尺寸变换都是自定义,我们也可以使用相对于原图片大小的相对大小。

python
from PIL import Image, ImageOps
size = (100, 150)
with Image.open("Tests/images/hopper.webp") as im:
    ImageOps.contain(im, size).save("imageops_contain.webp")
    ImageOps.cover(im, size).save("imageops_cover.webp")
    ImageOps.fit(im, size).save("imageops_fit.webp")
    ImageOps.pad(im, size, color="#f00").save("imageops_pad.webp")

    # thumbnail() can also be used,
    # but will modify the image object in place
    im.thumbnail(size)
    im.save("image_thumbnail.webp")

使用 - 颜色转换

我们可以使用 convert() 方法在不同像素间转换图像,如在模式中:

python
from PIL import Image

with Image.open("img.png") as im:
    im = im.convert("L")

支持的参数如下:

mode描述
11位像素,黑白,每字节存储一个像素
L8位像素,黑白
P8位像素,使用调色板映射到任何其他模式
RGB3x8位像素,真彩
RGBA4x8位像素,带透明蒙版的真彩
CMYK4x8位像素,分色
YCbCr3x8位像素,彩色视频格式
LAB3x8位像素,L * a * b颜色空间
HSV3x8位像素,色相,饱和度,值颜色空间
I32位有符号整数像素
F32位浮点像素

典型使用场景示例

这里不讲原理,给出一些示例代码,读者可根据代码内容调整。

  1. 为突破图片水印
python
from PIL import Image, ImageDraw, ImageFont

def add_watermark(input_image_path, watermark_text, output_image_path, font_path='arial.ttf', font_size=36, position=(10, 10), color=(255, 255, 255, 128)):
    # 打开原始图像
    with Image.open(input_image_path) as img:
        # 创建一个透明层
        draw = ImageDraw.Draw(img)
        
        # 加载字体
        font = ImageFont.truetype(font_path, font_size)
        
        # 绘制水印
        draw.text(position, watermark_text, fill=color, font=font)
        
        # 保存带有水印的图像
        img.save(output_image_path)

if __name__ == "__main__":
    add_watermark('example.jpg', 'Sample Watermark', 'watermarked_example.jpg')

函数的参数包括:

  • input_image_path: 输入图片路径。
  • watermark_text: 水印文字。
  • output_image_path: 输出图片路径。
  • font_path: 字体文件路径,默认为 arial.ttf。
  • font_size: 字体大小,默认为 36。
  • position: 水印位置,默认为 (10, 10)。
  • color: 水印颜色,默认为 (255, 255, 255, 128)(白色,半透明)
  1. 批量压缩图片
python
from PIL import Image
import os

def compress_images(directory, output_directory, max_size=(800, 800), quality=75):
    if not os.path.exists(output_directory):
        os.makedirs(output_directory)
    
    for filename in os.listdir(directory):
        if filename.lower().endswith(('.png', '.jpg', '.jpeg')):
            input_path = os.path.join(directory, filename)
            output_path = os.path.join(output_directory, filename)
            
            with Image.open(input_path) as img:
                img.thumbnail(max_size, Image.ANTIALIAS)
                img.save(output_path, optimize=True, quality=quality)

if __name__ == "__main__":
    compress_images('images', 'compressed_images')

参数列表说明:

  • directory: 输入图片目录。
  • output_directory: 输出图片目录。
  • max_size: 最大尺寸,默认为 (800, 800)。
  • quality: 图片质量,默认为 75。
  1. 为图片添加滤镜
python
from PIL import Image
import os

def apply_filter_to_images(directory, output_directory, filter_type=ImageFilter.BLUR):
    if not os.path.exists(output_directory):
        os.makedirs(output_directory)
    
    for filename in os.listdir(directory):
        if filename.lower().endswith(('.png', '.jpg', '.jpeg')):
            input_path = os.path.join(directory, filename)
            output_path = os.path.join(output_directory, filename)
            
            with Image.open(input_path) as img:
                filtered_image = img.filter(filter_type)
                filtered_image.save(output_path)

if __name__ == "__main__":
    apply_filter_to_images('images', 'filtered_images', ImageFilter.BLUR)

参数列表说明:

  • directory: 输入图片目录。
  • output_directory: 输出图片目录。
  • filter_type: 滤镜类型,默认为 ImageFilter.BLUR。

为方便开发而创建的常用库指南