PIL 使用

Pillow 是PIL全称,是一个python图像处理库,由Fredrik Lundh and Contributors创建的。

安装

basic
1
$ pip install Pillow

基本上安装python和pip就可以安装pil。

入门教程

Image class

PIL中最重要的类是Image,定义在PIL 底下的Image中。可以通过以下方式来创建一个Image类对象:

  • 通过打开一个图片文件来创建
  • 通过处理其他的图片
  • 从头创建图片

从图片文件中打开文件的:

1
2
from PIL import Image
im = Image.open('pic.png')

如果成功,函数会返回一个Image对象。可以通过检查它的属性来查看它的内容:

1
print(im.format, im.size, im.mode)

其中,

  • im.format是该图片的来源,如果不是来自图像文件,则会使None
  • im.size是图片的大小,是一个二维数组,单位是pixel
  • im.mode 是图片的显示模式,定义了图片的色带个数和名字;或像素的类型和深度;常见的模式有“L”是灰度图,“RGB”是真彩图片,“CMYK”是预印图片。

如果文件不能打开,则会返回一个IOError异常。

图片的显示:

1
im.show()

图片的保存:

1
im.save("...")

其他的图像打开方式:

从打开的文件中读取:
1
2
3
from PIL import Image
with open("hopper.ppm", "rb") as fp:
im = Image.open(fp)
从string中读取:
1
2
3
import StringIO

im = Image.open(StringIO.StringIO(buffer))
从tar文件中读取
1
2
3
4
from PIL import Image, TarIO

fp = TarIO.TarIO("Tests/images/hopper.tar", "hopper.jpg")
im = Image.open(fp)

读写图片

将文件转换成JPEG

1
2
3
4
5
6
7
8
9
10
11
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文件即可。需要注意,打开文件需要try except以防IOError

创建JPEG文件的缩略图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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)

思路是使用自带的thumbnai函数。

鉴定图片

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

剪切合并图片

Image class可以通过crop()函数来提取局部区域图片。

复制图像的一个长方形区域:
1
2
box = (100, 100, 400, 400)
region = im.crop(box)

box是一个四维tuple,定义了(左,上,右,下)。该库的坐标系是将左上角定义为原点(0,0),同时所采用的距离是pixel。

处理长方形区域并paste回去
1
2
region = region.transpose(Image.ROTATE_180)
im.paste(region, box)

paste函数要求region和box需要一致。

分离合并图像channel
1
2
r, g, b = im.split()
im = Image.merge("RGB", (b, g, r))

集合转换

图片resize和旋转
1
2
out = im.resize((128, 128))
out = im.rotate(45) # degrees counter-clockwise
图片翻转
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)

颜色转换

不同图像mode转换
1
2
from PIL import Image
im = Image.open("hopper.ppm").convert("L")

图像增强

过滤
1
2
from PIL import ImageFilter
out = im.filter(ImageFilter.DETAIL)
点操作

用于操作图像的像素值。

应用点操作
1
2
# multiply each pixel by 1.2
out = im.point(lambda i: i * 1.2)
处理单个通道
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# split the image into individual bands
source = im.split()

R, G, B = 0, 1, 2

# select regions where red is less than 100
mask = source[R].point(lambda i: i < 100 and 255)

# process the green band
out = source[G].point(lambda i: i * 0.7)

# paste the processed band back, but only where red was < 100
source[G].paste(out, None, mask)

# build a new multiband image
im = Image.merge(im.mode, source)
增强图片
1
2
3
4
from PIL import ImageEnhance

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

图像序列

PIL支持FLI、FLC、GIF等图像序列文件。

当使用图像序列文件,PIL会自动地打开序列中的第一帧。可以使用seek和tell方法来移动帧。

读取序列

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

im = Image.open("animation.gif")
im.seek(1) # skip to the second frame

try:
while 1:
im.seek(im.tell()+1)
# do something to im
except EOFError:
pass # end of sequence

在序列停止的时候,会返还一个EOFError。

使用ImageSequen Iterator class

1
2
3
from PIL import ImageSequence
for frame in ImageSequence.Iterator(im):
# ...do something to frame...

Postscript printing

用Postscript printers来打印图片文本和图像

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)

# draw the image (75 dpi)
ps.image(box, im, 75)
ps.rectangle(box)

# draw title
ps.setfont("HelveticaNarrow-Bold", 36)
ps.text((3*72, 4*72), title)

ps.end_document()