logo

Pillow 图像处理

王哲峰 / 2022-03-10


目录

Pillow 概览

PIL: Python Imaging Library, Python 图像处理库,提供了如下的功能:

Pillow 安装

$ python3 -m pip install --upgrade pip
$ python3 -m pip install --upgrade Pillow

Pillow 核心

Image class

API:

from PIL import Image

示例:

import os
from PIL import Image

image_path = "images"
image_name = "lena"
try:
    with Image.open(os.path.join(image_path, image_name + ".png")) as im:
        # 图像格式
        print(im.format)
        # 图像尺寸
        print(im.size)
        w, h = im.size
        print(f"image size: {(w, h)}")
        # 图像模式
        print(im.mode)
        # 图像打印
        im.show()
except IOError as e:
    print(f"Can't open {image_name}")

images

图像读写

API:

示例:

将图像转换为 JPEG 格式

import os, sys
from PIL import Image

for infile in sys.argv[1:]:
    f, e = os.path.splitext(inflie)
    outfile = f + ".jpg"
    if infile != outfile:
        try:
            with Image.open(infile) as im:
                im.save(outfile)
        except OSError:
            print("cannot convert", infile)
import os
from PIL import Image

image_path = "images"
image_name = "lena"
try:
    with Image.open(os.path.join(image_path, image_name + ".png")) as im:
        im.save(os.path.join(image_path, image_name + ".jpg"))
except IOError as e:
    print(f"Can't open {image_name}")

images

创建 JPEG 缩略图 thumbnails

import os, sys
from PIL import Image

size = (128, 128)

for inflie in sys.argv[1:]:
    outfile = os.path.splitext(infile)[0] + ".thumbnail"
    if infile != outfile:
        try:
            with Image.open(infile) as im:
                im.thumbnail(size)
                im.save(outfile, "JPEG")
        except OSError:
            print(f"Can't create thumbnail for{infile}")
import os
from PIL import Image

image_path = "images"
image_name = "lena"
size = (128, 128)

try:
    with Image.open(os.path.join(image_path, image_name + ".png")) as im:
        im.thumbnail(size)
        im.save(os.path.join(image_path, image_name + ".JPEG"))
except IOError as e:
    print(f"Can't open {image_name}")

images

识别图像文件

import sys
from PIL import Image

for infile in sys.argv[1:]:
    try:
        with Image.open(infile) as im:
            print(infile, im.format, f"{im.size}x{im.mode}")
    except OSError:
        pass
import os
from PIL import Image

image_path = "images"
image_name = "lena"

try:
    with Image.open(os.path.join(image_path, image_name + ".png")) as im:
        print(image_name, im.format, f"{im.size}x{im.mode}")
except IOError as e:
    print(f"Can't open {image_name}")

图像剪切、粘贴、拼接

API:

从图像中复制子矩形

import os
from PIL import Image

image_path = "images"
image_name = "lena"

try:
    box = (100, 100, 200, 200)
    with Image.open(os.path.join(image_path, image_name + ".png")) as im:
        region = im.crop(box)
        region.show()
        region.save(os.path.join(image_path, image_name + "_region" + ".png"))
except IOError as e:
    print(f"Can't open {image_name}")

images

从图像中复制子矩形并将子矩形粘贴回去

import os
from PIL import Image

image_path = "images"
image_name = "lena"

try:
    box = (100, 100, 200, 200)
    with Image.open(os.path.join(image_path, image_name + ".png")) as im:
        region = im.crop(box)
        region = region.transpose(Image.ROTATE_180)
        im.paste(region, box)
        im.save(os.path.join(image_path, image_name + "_region_paste" + ".png"))
except IOError as e:
    print(f"Can't open {image_name}")

images

图像滚动

import os
from PIL import Image

image_path = "images"
image_name = "lena"

def roll(image, delta):
    """Roll an image sideways"""
    xsize, ysize = image.size
    delta = delta % xsize
    if delta == 0:
        return image
    part1 = image.crop((0, 0, delta, ysize))
    part2 = image.crop((delta, 0, xsize, ysize))
    image.paste(part1, (xsize - delta, 0, xsize, ysize))
    image.paste(part2, (0, 0, xsize - delta, ysize))

    return image

try:
    with Image.open(os.path.join(image_path, image_name + ".png")) as im:
        im = roll(im, 10)
        im.save(os.path.join(image_path, image_name + "_roll" + ".png"))
except OSError:
    print(f"cannot open {image_name}")

images

RGB 波段拆分、合并

import os
from PIL import Image

image_path = "images"
image_name = "lena"

try:
    with Image.open(os.path.join(image_path, image_name + ".png")) as im:
        r, g, b = im.split()
        im = Image.merge("RGB", (b, g, r))
        im.save(os.path.join(image_path, image_name + "_merge_gbr" + ".png"))
except OSError:
    print(f"cannot open {image_name}")

images images images images images images

图像几何变换

API:

简单的几何变换-改变图像像素大小

import os
from PIL import Image

image_path = "images"
image_name = "lena"

try:
    with Image.open(os.path.join(image_path, image_name + ".png")) as im:
        out = im.resize((1000, 1000))
        out.save(os.path.join(image_path, image_name + "_resize" + ".png"))
except OSError:
    print(f"cannot open {image_name}")

images

简单的几何变换-图像逆时针旋转一定的角度

import os
from PIL import Image

image_path = "images"
image_name = "lena"

try:
    with Image.open(os.path.join(image_path, image_name + ".png")) as im:
        out = im.rotate(45)
        out.save(os.path.join(image_path, image_name + "_rotate" + ".png"))
except OSError:
    print(f"cannot open {image_name}")

images

图像转置

import os
from PIL import Image

image_path = "images"
image_name = "lena"

try:
    with Image.open(os.path.join(image_path, image_name + ".png")) as im:
        out1 = im.transpose(Image.FLIP_LEFT_RIGHT)
        out2 = im.transpose(Image.FLIP_TOP_BOTTOM)
        out3 = im.transpose(Image.ROTATE_90)
        out4 = im.transpose(Image.ROTATE_180)
        out5 = im.transpose(Image.ROTATE_270)
        out1.save(os.path.join(image_path, image_name + "_rotate_1" + ".png"))
        out2.save(os.path.join(image_path, image_name + "_rotate_2" + ".png"))
        out3.save(os.path.join(image_path, image_name + "_rotate_3" + ".png"))
        out4.save(os.path.join(image_path, image_name + "_rotate_4" + ".png"))
        out5.save(os.path.join(image_path, image_name + "_rotate_5" + ".png"))
except OSError:
    print(f"cannot open {image_name}")

images images images images images images

图像颜色转换

图像增强

图像序列

PostScript 打印

图像读取

控制图像编码

ImageDraw 绘图方法

PIL 的 ImageDraw 提供了一系列绘图方法,让我们可以直接绘图。 比如要生成字母验证码图片

from PIL import Image, ImageDraw, ImageFont, ImageFilter

import random

# 随机字母:
def rndChar():
    return chr(random.randint(65, 90))

# 随机颜色1:
def rndColor():
    return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))

# 随机颜色2:
def rndColor2():
    return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))

# 240 x 60:
width = 60 * 4
height = 60
image = Image.new('RGB', (width, height), (255, 255, 255))
# 创建Font对象:
font = ImageFont.truetype('Arial.ttf', 36)
# 创建Draw对象:
draw = ImageDraw.Draw(image)
# 填充每个像素:
for x in range(width):
    for y in range(height):
        draw.point((x, y), fill=rndColor())
# 输出文字:
for t in range(4):
    draw.text((60 * t + 10, 10), rndChar(), font=font, fill=rndColor2())
# 模糊:
image = image.filter(ImageFilter.BLUR)
image.save('code.jpg', 'jpeg')

用随机颜色填充背景,再画上文字,最后对图像进行模糊,得到验证码图片如下

img

Pillow API