Pillow快速入门
前言
本教程目的
学习该库,目的是为了用python
去操作图像提供更为全面的选择。
本库进阶学习
进阶学习,首先需要很明确了解要对图像进行什么操作,然后查询相关的API
。
初学思维导图
接下来就是初学者教程。
使用 Image
Class
在PIL
中,最重要的类就是Image
这个和模块名相同的类。您可以通过多种方式创建该类的实例;要么从文件中加载图像,要么处理其他图像,要么从头创建图像。
要从文件中加载图像,请使用图像模块中的open()函数:
from PIL import Image
im = Image.open("hopper.ppm")
如果成功,此函数将返回一个图像对象。你现在可以使用实例属性来检查文件内容:
print(im.format, im.size, im.mode)
# PPM (512, 512) RGB
读写图像
Python图像库支持多种图像文件格式。要从磁盘读取文件,请使用图像模块中的open()函数。你不必知道打开一个文件的格式。库根据文件的内容自动确定格式。
保存目标格式的图像
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:
with Image.open(infile) as im:
# 核心是im.save()
im.save(outfile)
except IOError:
print("cannot convert", infile)
创建缩略图
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:
with Image.open(infile) as im:
#此处在缓冲区生成size大小的thumbnail()
im.thumbnail(size)
im.save(outfile, "JPEG")
except IOError:
print("cannot create thumbnail for", infile)
需要注意的是,除非必要,否则库不会解码或加载光栅数据。当您打开一个文件时,将读取文件头以确定文件格式,并提取解码文件所需的模式、大小和其他属性,但是文件的其余部分直到稍后才处理。
识别一系列的文件
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)
区域由一个4元组定义,其中的坐标是(左、上、右、下)。Python图像库使用左上角的坐标系统(0,0)。还要注意,坐标是指像素之间的位置,所以上面例子中的区域就是300x300像素。
现在可以以某种方式处理该区域并将其粘贴回去。
处理子矩形,并将其粘贴回去
region = region.transpose(Image.ROTATE_180)
im.paste(region, box)
当粘贴区域时,区域的大小必须与给定的区域完全匹配。此外,区域不能延伸到图像之外。但是,原始图像的模式和区域不需要匹配。如果没有,则在粘贴之前自动转换区域。
平移和拼接图像
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图像并将其用作掩码将粘贴图像的不透明部分,但不粘贴其透明的背景。
Python图像库还允许您处理多波段图像的单个波段,例如RGB图像。分割方法创建一组新图像,每个图像包含原始多频带图像中的一个频带。merge函数接受一个模式和一个图像元组,并将它们组合成一个新图像。下面的例子交换了一个RGB图像的三个波段:
分割和融合波段信息
r, g, b = im.split()
im = Image.merge("RGB", (b, g, r))
注意,对于单波段图像,split()返回图像本身。要使用单独的颜色带,您可能需要首先将图像转换为“RGB”。
几何变换
PIL.Image。Image类包含调整()和旋转()图像的方法。前者采用一个元组提供新的大小,而后者采用逆时针角度。
简单的几何变换
out = im.resize((128, 128))
out = im.rotate(45) # degrees counter-clockwise
要将图像旋转90度,可以使用rotate()方法或转置()方法。后者也可以用来翻转图像的水平或垂直轴。
翻转图像
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)
transpose(ROTATE)
操作也可以和rotate
进行相同的操作。
如果expand
为True
则原图像做相应的修改。
更加通用的操作是通过transform()
方法对其进行修改。
颜色(通道)转换
Python图像库允许您使用convert()方法在不同的像素表示之间转换图像。
模式之间的转换
from PIL import Image
with Image.open("hopper.ppm") as im:
im = im.convert("L")
该库支持在每个支持模式与“L”和“RGB”模式之间进行转换。要在其他模式之间进行转换,您可能必须使用中间图像(通常是“RGB”图像)。
图象增强
Python图像库提供了许多可以用来增强图像的方法和模块。
滤波
imageFilter
模块包含许多预定义的增强过滤器,可以与filter()方法一起使用.
from PIL import ImageFilter
out = im.filter(ImageFilter.DETAIL)
像素操作
point()方法可用于转换图像的像素值(例如,图像对比度处理)。在大多数情况下,期望一个参数的函数对象可以传递给这个方法。每个像素按照该函数进行处理:
对点进行操作
# multiply each pixel by 1.2
out = im.point(lambda i: i * 1.2)
使用上述技术,您可以快速地将任何简单的表达式应用于图像。您还可以组合使用point()和paste()方法来选择性地修改图像:
处理单个波段
# 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)
注意用于创建掩码的语法:
imout = im.point(lambda i: expression and 255)
图像增强
对于更高级的图像增强,您可以使用ImageEnhance
模块中的类。从图像创建后,可以使用增强对象快速尝试不同的设置。
你可以通过这种方式调整对比度、亮度、色彩平衡和锐度。
from PIL import ImageEnhance
enh = ImageEnhance.Contrast(im)
enh.enhance(1.3).show("30% more contrast")
图像序列
Python图像库包含对图像序列(也称为动画格式)的一些基本支持。支持的序列格式包括FLI/FLC、GIF和一些实验格式。TIFF文件也可以包含一个以上的帧。
当你打开一个序列文件时,PIL会自动加载序列中的第一帧。你可以使用查找和告诉方法在不同的帧之间移动:
序列读取
from PIL import Image
with Image.open("animation.gif") as im:
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...
图像打印
Python图像库包括在Postscript打印机上打印图像、文本和图形的函数。这里有一个简单的例子:
from PIL import Image
from PIL import PSDraw
with Image.open("hopper.ppm") as im:
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()
关于读取图像
我们可以使用上下文管理器去读取图像进行一系列的操作:
from PIL import Image
with Image.open("hopper.ppm") as im:
...
您可以使用类似文件的对象来代替文件名。该对象必须实现read()、seek()和tell()方法,并以二进制模式打开。
从打开的文件中读取图像
from PIL import Image
with open("hopper.ppm", "rb") as fp:
im = Image.open(fp)
从二进制文件中读取
要从二进制数据中读取图像,使用BytesIO
类:
from PIL import Image
import io
im = Image.open(io.BytesIO(buffer))
从压缩文件中读取图像
注意,库在读取图像头之前会回滚文件(使用seek(0))。此外,在读取图像数据时也将使用seek(通过load方法)。如果图像文件嵌入到更大的文件中,例如tar文件,则可以使用ContainerIO
或TarIO
模块来访问它。
from PIL import Image, TarIO
fp = TarIO.TarIO("Tests/images/hopper.tar", "hopper.jpg")
im = Image.open(fp)
控制编码器
一些解码器允许您在从文件中读取图像时操作图像。当创建缩略图(速度通常比质量更重要)和在单色激光打印机上打印(只需要图像的灰度版本)时,这通常可以用来加快解码速度。
draft()
方法操作打开但尚未加载的图像,使其尽可能接近给定的模式和大小。这是通过重新配置图像解码器实现的。
使用draft()
读取图像
这只在JPEG
和MPO
文件情况下适用。此方法操作打开但尚未加载的图像,使其尽可能接近给定的模式和大小。
from PIL import Image
with Image.open(file) as im:
print("original =", im.mode, im.size)
im.draft("L", (100, 100))
print("draft =", im.mode, im.size)
"""
输出:
original = RGB (512, 512)
draft = L (128, 128)
"""
注意,生成的图像可能与请求的模式和大小不完全匹配。要确保图像不大于给定的大小,请使用缩略图方法。