3.3. 使用 Pillow 处理图像

pillow库操作切片、旋转、滤镜、输出文字、调色板等功能一应俱全。

3.3.1. 几何变换

Image 包含调整图像大小 resize() 和旋转 rotate() 的方法。前者采用元组给出新的大小,后者采用逆时针方向的角度。

调整大小并逆时针旋转 45度

>>> from PIL import  Image
>>> from matplotlib import pyplot as plt
>>> im=Image.open('./img6.png')
>>> o = im.resize((128, 128))
>>> outfile= o.rotate(45)
>>> plt.imshow(outfile)
>>> plt.show()
_images/sec03_pillow_processing_2_0.png

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

  • FLIP_LEFT_RIGHT 水平左右翻转

  • Image.FLIP_TOP_BOTTOM 垂直上下翻转

  • Image.ROTATE_90 逆时针90度

  • Image.ROTATE_180 逆时针180度

  • Image.ROTATE_270 逆时针270度

更多的api可以查看官方文档和源码。

3.3.2. 颜色变换

转换为灰阶图像

>>> im = Image.open("./img3.png").convert("L")
>>> plt.imshow(im)
>>> plt.show()
_images/sec03_pillow_processing_4_0.png

3.3.3. 图像增强

Filters 过滤器

ImageFilter 模块有很多预定义的增强过滤器,通过 filter() 方法运用。

>>> im=Image.open('./img4.png')
>>> plt.imshow(im)
>>> plt.show()
_images/sec03_pillow_processing_6_0.png

将图像进行增强处理

>>> from PIL import ImageFilter
>>> out = im.filter(ImageFilter.DETAIL)
>>> plt.imshow(out)
>>> plt.show()
_images/sec03_pillow_processing_8_0.png

既然可以进行增强处理自然可以进行模糊处理

>>> im2 = im.filter(ImageFilter.BLUR)
>>> plt.imshow(im2)
>>> plt.show()
_images/sec03_pillow_processing_10_0.png

像素点处理

point() 方法可用于转换图像的像素值(如对比度),在大多数情况下,可以将函数对象作为参数传递格此方法,它根据函数返回值对每个像素进行处理。将每个像素点扩大1.2倍

>>> out = im.point(lambda i: i * 1.2)
>>> plt.imshow(out)
>>> plt.show()
_images/sec03_pillow_processing_12_0.png

3.3.4. 剪贴,粘贴、合并图像

Image类包含允许您操作图像中的区域的方法。如:要从图像中复制子矩形图像使用 crop() 方法。

从图像复制子矩形

1.截取矩形图像

>>> im=Image.open('./img2.png')
>>> box = (100, 100, 400, 500)
>>> region = im.crop(box)
>>> plt.imshow(region)
>>> plt.show()
_images/sec03_pillow_processing_14_0.png

定义box元组,图像基于左上角为(0,0)的坐标,box 坐标为 (左,上,右,下)。注意,坐标是基于像素。示例中为 300 * 400 像素。

2.先将复制的内容颠倒180度,在原图上粘贴子矩形图像

粘贴时要注意几点。选择好想要粘贴的位置,paste() 方法的两个参数依次是处理后的图片;以及图片的位置,同样为(左,上,右,下),不过,他们的值的间距为图片的像素(也就是确定好左上角的点后,分别加上像素值),不可调整。

将我们复制的图片旋转180度

>>> region = region.transpose(Image.ROTATE_180)

定义要粘贴的位置。

>>> box = (100, 100, 400, 500)

将子图(region) 粘贴(paste)回原图时,粘贴位置 box 的像素与宽高必须吻合。而原图和子图的 mode 不需要匹配,Pillow会自动处理。

>>> im.paste(region, box)
>>> plt.imshow(im)
>>> plt.show()
_images/sec03_pillow_processing_20_0.png
>>> region = region.transpose(Image.ROTATE_180)
>>> box = (200, 200, 500, 600)
>>> im.paste(region, box)
>>> plt.imshow(im)
>>> plt.show()
_images/sec03_pillow_processing_21_0.png

3.移动图像

移动图像就是将图片复制再粘贴。看起就像移动。

>>> image_path = './img3.png'
>>> im = Image.open(image_path)

设置想要偏转的像素值。

>>> delta=200
>>> xsize, ysize = im.size
>>> print(im.size)
(464, 352)

移动图片通常都是在X轴的方向上进行处理,我们设置的偏移值为200个像素,比X轴的值小所以可以直接处理,但是如果是移动2000个像素呢,可能就会出现错误,所以我们对他进行求余处理,也就是将图片移动了多个周期,依旧是2000时,我们需要移动的就是144个像素。

>>> delta = delta % xsize
>>> if delta == 0:
>>>     plt.imshow(im)
>>>     plt.show()

将确定好的位置复制下来,在重新组成一幅图片,视觉上看就像是图片在移动。

>>> part1 = im.crop((0, 0, delta, ysize))
>>> part2 = im.crop((delta, 0, xsize, ysize))
>>> im.paste(part1, (xsize - delta, 0, xsize, ysize))
>>> im.paste(part2, (0, 0, xsize - delta, ysize))
>>> plt.imshow(im)
>>> plt.show()
_images/sec03_pillow_processing_29_0.png

分离和合并通道

Pillow 允许处理图像的各个通道,例如RGB图像有R、G、B三个通道,RGB 意思是红色、绿色、蓝色,有的图像会有R、G、B、A四个通道,’A’是Alpha的首字母,是指一张图片的透明和半透明度。 split() 方法分离图像通道,如果图像为单通道则返回图像本身。merge 函数采用图像的 mode 和 通道元组为参数,将它们合并成新图像。

>>> im=Image.open('./img3.png')
>>> print(im.mode)
RGBA

将通道分离为R,G,B,A

>>> r, g, b ,a= im.split()

将三个颜色打乱后合并显示。

>>> im = Image.merge("RGB", (b, g, r))
>>> plt.imshow(im)
>>> plt.show()
_images/sec03_pillow_processing_35_0.png

下面处理交换RGB图像的三个波段,需要注意的是, 如果你的图片是RGBA那么会出现异常,解决方法将图片转换为RGB:

Image.open(image_path).convert("RGB").save(outfile)
>>> Image.open('./img3.png').convert("RGB").save('./img3_3.png')
>>> im=Image.open('./img3_3.png')
>>> print(im.mode)
>>> plt.imshow(im)
>>> plt.show()
RGB
_images/sec03_pillow_processing_37_1.png

处理单独通道颜色

将RGB进行单独处理

>>> 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)
>>> plt.imshow(im)
>>> plt.show()
_images/sec03_pillow_processing_45_0.png

3.3.5. 深入处理

图像处理功能可以使用 ImageEnhance 模块中的类。从图像创建后,可以使用 ImageEnhance 快速调整图片的对比度、亮度、饱和度和清晰度。主要方法有:

  • ImageEnhance.Contrast(im) 对比度

  • ImageEnhance.Color(im) 色彩饱和度

  • ImageEnhance.Brightness(im) 亮度

  • ImageEnhance.Sharpness(im) 清晰度

需要先创建一个对象。

1.将对比度提高1.5倍

>>> from PIL import ImageEnhance
>>>
>>> img6=Image.open('./img6.png')
>>> enh = ImageEnhance.Contrast(img6)
>>> img6_cont=enh.enhance(1.5)
>>> plt.subplot(121),plt.imshow(img6),plt.title("befor")
>>> plt.subplot(122),plt.imshow(img6_cont),plt.title("after")
>>> plt.show()
_images/sec03_pillow_processing_47_0.png

2.将色彩饱和度提高2倍

>>> img1=Image.open('./img1.png')
>>> color=ImageEnhance.Color(img1)
>>> img1_cont=color.enhance(2)
>>> plt.subplot(121),plt.imshow(img1),plt.title("befor")
>>> plt.subplot(122),plt.imshow(img1_cont),plt.title("after")
>>> plt.show()
_images/sec03_pillow_processing_49_0.png

3.将亮度提高3倍

>>> img2=Image.open('./img2.png')
>>> brg=ImageEnhance.Brightness(img2)
>>> img2_brg=brg.enhance(2)
>>> plt.subplot(121),plt.imshow(img2),plt.title("befor")
>>> plt.subplot(122),plt.imshow(img2_brg),plt.title("after")
>>> plt.show()
_images/sec03_pillow_processing_51_0.png

4.将清晰度提高4倍

>>> img4=Image.open('./img/img4.png')
>>> shp=ImageEnhance.Sharpness(img4)
>>> img4_shp=shp.enhance(4)
>>> plt.subplot(121),plt.imshow(img4),plt.title("befor")
>>> plt.subplot(122),plt.imshow(img4_shp),plt.title("after")
>>> plt.show()
_images/sec03_pillow_processing_53_0.png

3.3.6. 处理动态图像

Pillow 支持一些动态图像处理(如FLI/FLC,GIF等格式)。TIFF文件同样可以包含数帧图像。

打开动态图像时,PIL 会自动加载序列中的第一帧。你可以使用 seektell 方法在不同的帧之间移动。

>>> from PIL import ImageSequence
>>> im8 = Image.open('./img/img8.gif')
>>> num=0
>>> for frame in ImageSequence.Iterator(im8):
>>>     if num <9:
>>>         num+=1
>>>         plt.subplot(int('33{}'.format(num))),plt.imshow(frame)
_images/sec03_pillow_processing_55_0.png

3.3.7. 添加水印

在一些平台上传图片时,平台都会添加一个水印,表示组织或个人对图片的所有权,使用pillow库也可以轻松的添加水印效果。

我们先试着添加文字

>>> from PIL import ImageFont,ImageDraw
>>> img=Image.open('./img/img6.png')
>>> draw=ImageDraw.Draw(img)

ImageFont.truetype 参数是设置字体类型以及字体大小。

>>> font=ImageFont.truetype('VeraMoBI.ttf',40)
>>> draw.text((100, 100), 'Pillow',(150,200,0),font=font)
>>> plt.imshow(img)
>>> plt.show()
_images/sec03_pillow_processing_59_0.png

用我们前面讲到的复制粘贴,添加图片相当于添加了图片水印效果。