Pillow6 起步
使用 Image 类
可以使用 Image 模块的 open() 方法加载图片文件:
from PIL import Image im = Image.open("hopper.ppm")
操作成功返回 Image 对象。可以通过实例属性查看图片的属性:
#在python2中,像在python3一样使用print()方法 from __future__ import print_function print(im.format, im.size, im.mode) # PPM (512, 512) RGB
如果 image 不是从文件读取的, format 属性被设置为 None。mode 属性定义了图片频谱的数量和名称,以及像素类型和深度。常用的模式是灰度图像的“L”(亮度)、真彩色图像的“RGB”和印前图像的“CMYK”。
如果图片 open 失败,会引发 IOError 错误。
一旦实例化了 Image 类,就可以使用它的方法去处理图像。
读写图片
open()
save() 不指定图片格式的话,默认使用原来的格式
把图片的格式转换为 JPEG
from __future__ import print_function import os, sys from PIL import Image for infile in sys.argv[1:]: # Python中 sys.argv[]的用法简明解释 f, e = os.path.splitext(infile) outfile = f + ".jpg" if infile != outfile: try: Image.open(infile).save(outfile) except IOError: print("cannot convert", infile)
将以上代码写进python文件test.py,然后在命令行 python test.py ???1.png ???2.png ???3.png ...,便会生成一个 ???1.jpg,???2.jpg,???3.jpg ... 文件。
生成 JPEG 缩略图
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)
如果 size 比原来大,不会生效;如果一个大一个小,会自动把大的调小。
当打开一个图片的时候,决定图片 format, mode, size 等属性的文件头会被读取,其他的内容将之后处理。这样,意味着 open 操作非常快,只依赖于文件的大小和压缩方式。
识别图片文件
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
剪切、粘贴、合并图片
从图片中拷贝出子图片(矩形)
box = (100, 100, 400, 400)
region = im.crop(box)
box 的四个坐标分别代表:左,上,右,下。坐标的单位为像素。
处理子图,并粘贴回去
region = region.transpose(Image.ROTATE_180)
im.paste(region, box)
粘贴处理后的图像到原图的时候,图片的尺寸必须匹配。子图的尺寸不能扩展到原图之外。但是,二者的 mode 属性可以不一致,子图会在粘贴之前自动转换。(Color transforms)
移动图片(水平方向)
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
至于更多黑魔法,paste方法也可以传入一个表示透明度的可选参数。当你使用了这个黑魔法,传入255这个值将会使图像变得不透明。反之传入0则会使图像完全透明。传入中间值则会使图片半透明。例如,修改一个 RGBA 图像并且使用透明度参数将会影响它的前景色透明度,而并不会影响它的背景色透明度。
分割和合并bands
PIL 可以操作彩色图片的单个波段。split() 方法可以将图片分割成一组单波段的图片。merge() 方法需要一个 mode 参数和一组图片,将它们合并为一个图片。
r, g, b = im.split() im = Image.merge("RGB", (b, g, r))
合成的图片会失真。
几何变换
简单的变换
out = im.resize((128, 128)) # 变换后的大小 out = im.rotate(45) # 要旋转的大小,逆时针
旋转图像
out = im.transpose(Image.FLIP_LEFT_RIGHT) # 左右翻转 out = im.transpose(Image.FLIP_TOP_BOTTOM) # 上下翻转 out = im.transpose(Image.ROTATE_90) # 逆时针旋转90° out = im.transpose(Image.ROTATE_180) # 逆时针旋转180° out = im.transpose(Image.ROTATE_270) # 逆时针旋转270°
transpose(ROTATE) 操作等同于 rotate() 方法把 expand 参数置为 True 时的操作。transform() 方法使用更加普遍。
颜色转换
modes 转换
im = Image.open("hopper.ppm").convert("L")
PIL 支持的图像 mode 可以与 “L” 和 “RGB” 互相转换。如果是转换到其他模式,就需要 “RGB”(常用) 作为过渡
图像增强
过滤
使用过滤器
out = im.filter(ImageFilter.DETAIL)
像素操作
point() 方法用于修改为像素点的值,参数为 function object,每个像素点都会应用该 function
使用像素转换
# multiply each pixel by 1.2 out = im.point(lambda i: i * 1.2)
处理不同bands
# 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)
expression and 255 如果 expression 为 True,返回 255,如果为 False,则返回 0
增强
使用 ImageEnhance 模块,可以调整图像的对比度、亮度、颜色平衡度和锐度。
图片增强
from PIL import ImageEnhance enh = ImageEnhance.Contrast(im) enh.enhance(1.3).show("30% more contrast")
图像序列
PIL 支持一些图像序列(动画格式),包括 FLI/FLC, GIF等。TIFF 文件可以包含多帧。
open 一个图像序列之后,PIL 会自动加载第一帧,可以使用 seek 和 tell 方法,切换不同的帧。
读图片序列
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
使用 ImageSequence
from PIL import ImageSequence for frame in ImageSequence.Iterator(im): # ...do something to frame...
Postscript 打印
绘制 Postscript
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()
更多关于读取图片的内容
使用 open() 方法打开图片,只需简单的传入文件名作为参数,但是如果打开失败,就会产生 IOError 异常。在此,可以使用 file-like object 代替文件名,object 必须实现了read(), seek() 和 tall() 方法,并且是用二进制方式打开文件。
Reading from an open file
from PIL import Image with open("hopper.ppm", "rb") as fp: im = Image.open(fp)
Reading from a string
from PIL import Image import StringIO im = Image.open(StringIO.StringIO(buffer))
如果图片文件嵌入在一个大文件中,可以使用 ContainerIO 和 TarIO 模块处理。
Reading from a tar archive
from PIL import Image, TarIO fp = TarIO.TarIO("Tests/images/hopper.tar", "hopper.jpg") im = Image.open(fp)
控制解码器
一些解码器允许在读取图片的时候处理图片。在创建缩略图(速度通常比质量更重要时)和在单色激光打印机上打印(只需要图像的灰度版本时)时,通常可以用来加快解码速度。
重新配置解码器之后,draft() 方法可以处理打开但未加载的图片。
Reading in draft mode
这种方式只适用于 JPEG 和 MPO 文件。
from PIL import Image from __future__ import print_function im = Image.open(file) print("original =", im.mode, im.size) im.draft("L", (100, 100)) print("draft =", im.mode, im.size)
得到的结果图像,可能不完全匹配给定的 mode 和 size。为了确保得到的图片不大于给定的尺寸,可以使用 thumbnail() 方法代替。