Python 第三方模块 Pillow 中文文档

v:5.1.x
Docs>Handbook>Tutorial
【】内为译者注

运用 Image 类

1
2
from PIL import Image
im = Image.open("hopper.ppm")

如果打开图片成功,函数回返回一个 Image 对象。可以检查文档内容:

1
2
3
>>> from __future__ import print_function
>>> print(im.format, im.size, im.mode)
PPM (512, 512) RGB

format 属性标识图像的源。

*【并不=文档格式,我将此前用 Pillow 生成的 jpg 文档改为 png 再JP读入,print 出来仍是 jpg】
2018-04-12_17-34-42.jpg

如果图像并非由文档读取而来,则设定为 None

size 属性返回图像宽高值(单位为像素)的二元元组。

mode 属性定义图像中波段的数量和名称,以及像素类型和深度。常见值有灰度图像的 L(亮度) ,真彩图像为 RGB,用于打印的图像为 CMYK。

若文档无法打开,会出现 IOError 异常。

成功得到一个 Image 类实例后,可以用这一类定义的方法去处理图片。例如展示:

1
>>> im.show()

读写图像

读取上面有例。

存储图像用 save()。如果存储时不定义格式,将会以存储文档名后缀作为格式。

文档转为 JPEG

1
2
3
4
5
6
7
8
9
10
11
12
from __future__ import print_function
import os, sys
from PIL import Image

for infile in sys.argv[1:]:
f, e = os.path.splitext(infile)
outfile = f + ".jpg"
if infile != outfile:
try:
Image.open(infile).save(outfile)
except IOError:
print("cannot convert", infile)

创建 JPEG 缩略图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from __future__ import print_function
import os, sys
from PIL import Image

size = (128, 128)

for infile in sys.argv[1:]:
outfile = os.path.splitext(infile)[0] + ".thumbnail"
if infile != outfile:
try:
im = Image.open(infile)
im.thumbnail(size)
im.save(outfile, "JPEG")
except IOError:
print("cannot create thumbnail for", infile)

识别图像文档

1
2
3
4
5
6
7
8
9
10
from __future__ import print_function
import sys
from PIL import Image

for infile in sys.argv[1:]:
try:
with Image.open(infile) as im:
print(infile, im.format, "%dx%d" % im.size, im.mode)
except IOError:
pass

剪切、粘贴和合并图像

若要从图像中提取子矩形,请用 crop() 方法。

从图像中复制子矩形

1
2
box = (100, 100, 400, 400)
region = im.crop(box)

区域由一个4-元组决定,其坐标为(左,上,右,下)。在 Python 图像库使用的座标系中 (0,0) 位于左上角。坐标单位为像素。因此上例中所选区域为 300 x 300 像素。

处理子矩形,然后将其粘贴回去

1
2
region = region.transpose(Image.ROTATE_180)
im.paste(region, box)

回贴区域时,区域的大小必须与给定区域完全匹配。此外,区域不能延伸到图像之外。然而,原始图像和区域的模式不需要匹配。如果模式不匹配,区域粘贴前会自动转换 。

下面是另一个示例:

滚动图像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def (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))
part1.load()
part2.load()
image.paste(part2, (0, 0, xsize-delta, ysize))
image.paste(part1, (xsize-delta, 0, xsize, ysize))

return image

请注意,从 crop () 操作粘贴回时,首先调用 load ()。这是因为裁剪是一个懒惰的操作。如果未调用 load (),则在粘贴命令中使用图像之前不会执行裁剪操作。这意味着第 1 部分将从已由第一次粘贴修改的图像版本中裁剪。

对于更高级的技巧,paste 方法还可以将透明度掩码作为可选参数。在此屏蔽中,值 255 表示粘贴的图像在该位置不透明 (即,粘贴的图像保持原样)。值 0 表示粘贴的图像完全透明。中间值表示不同的透明度级别。例如,粘贴一个 RGB 图像并将其用作屏蔽会粘贴图像的不透明部分,但不会粘贴其透明背景。

分割和合并波段

1
2
r, g, b = im.split()
im = Image.merge("RGB", (b, g, r))

请注意,对于单波段图像,split () 返回图像本身。要使用单个色带,您可能需要先将图像转换为 “RGB”。

几何变换

PIL.Image.Image 类包含调整图像大小 () 和旋转图像 () 的方法。前者采用给定新大小的元组,后者采用逆时针角度(以度为单位)。

简单几何变换

1
2
out = im.resize((128, 128))
out = im.rotate(45)

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

变换图像

1
2
3
4
5
out = im.transpose(Image.FLIP_LEFT_RIGHT)
out = im.transpose(Image.FLIP_TOP_BOTTOM)
out = im.transpose(Image.ROTATE_90)
out = im.transpose(Image.ROTATE_180)
out = im.transpose(Image.ROTATE_270)

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

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

色彩变换

Python 图像库允许您使用 convert() 方法在不同像素表示之间转换图像。

模式间转换

1
2
from PIL import Image
im = Image.open("hopper.ppm").convert("L")

库支持每个支持的模式与 “L” 和“RGB”模式之间的转换。【也就是所有文档格式的图像的色彩格式都可以直接在 L 与 RGB 之间】要在其他模式之间转换,可能必须使用中间图像 (通常是“RGB” 图像)。【也即以 RGB 作为中转格式】

图像增强

Python 图像库提供了许多可用于增强图像的方法和模块。

滤镜

ImageFilter 模块包含许多可与 filter ( ) 方法一起使用的预先设定好的滤镜。

添加滤镜
1
2
from PIL import ImageFilter
out = im.filter(ImageFilter.DETAIL)

点操作

point () 方法可用于转换图像的像素值 (例如图像对比度操作)。在大多数情况下,需要一个参数的函数对象可以传递给此方法。根据该函数处理每个像素:

应用点变换
1
2

out = im.point(lambda i: i * 1.2)

【试验如下图RGB、JPG,分别为原图、乘以1.2、乘以2.1。似乎效果是让图片变亮?】testcompare.jpg

使用上述技术,您可以快速将任何简单的表达式应用于图像。您也可以结合 point ()paste () 方法,选择性地修改影像:

处理单个波段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

source = im.split()

R, G, B = 0, 1, 2


mask = source[R].point(lambda i: i < 100 and 255)

# 处理绿色波段
out = source[G].point(lambda i: i * 0.7)

# 将处理过的波段粘贴回来,但仅在红色 < 100 的地方粘贴
source[G].paste(out, None, mask)

# 构建新的多波段图像
im = Image.merge(im.mode, source)

请注意用于创建掩码的语法:

1
imout = im.point(lambda i: expression and 255)

python 仅计算确定结果所需的逻辑表达式部分,并返回作为表达式结果检查的最后一个值。因此,如果上面的表达式为 false (0),Python 不查看第二个操作数,因此返回 0。否则,返回 255。

增强

要获得更高级的映像增强功能,您可以使用 image 增强模块中的类。从图像创建增强对象后,可以使用增强对象快速尝试不同的设置。

您可以用这种方式调整对比度、亮度、色彩平衡和锐度。

增强图像
1
2
3
4
from PIL import ImageEnhance

enh = ImageEnhance.Contrast(im)
enh.enhance(1.3).show("30% more contrast")

图像序列

Python 图像库包含对图像序列 (也称为动画格式) 【动图】的一些基本支持。支持的序列格式包括 FLI / FLC、GIF 和一些实验格式。TIFF 文档还可以包含多个帧。

打开序列文档时,PIL 会自动加载序列中的第一帧。您可以使用 seektell 方法在不同的帧之间移动:

读取顺序

1
2
3
4
5
6
7
8
9
10
11
from PIL import Image

im = Image.open("animation.gif")
im.seek(1) # 跳到第二帧

try:
while 1:
im.seek(im.tell()+1)
# 对im做点什么【?】
except EOFError:
pass # 序列结束

如本示例所示,当序列结束时,您将获得 EOFError 异常。

请注意,库的当前版本中的大多数驱动进程仅允许您查找下一帧 (如上面的示例所示)。要倒回文档,您可能必须重新打开它。

下列类别可让您使用 for 循环在序列上循环:

使用 ImageSequence 迭代器类

Python 图像库包括在 Postscript 打印机上打印图像、文本和图形的功能。下面是一个简单的示例:

Drawing Postscript【绘制附言,图像上的标题、文字等】
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from PIL import Image
from PIL import PSDraw

im = Image.open("hopper.ppm")
title = "hopper"
box = (1*72, 2*72, 7*72, 10*72) # in points

ps = PSDraw.PSDraw() # default is sys.stdout
ps.begin_document(title)

# 绘制图像 (75 dpi)
ps.image(box, im, 75)
ps.rectangle(box)

# 绘制标题
ps.setfont("HelveticaNarrow-Bold", 36)
ps.text((3*72, 4*72), title)

ps.end_document()