3.3. 使用 Pillow 处理图像¶
pillow库操作切片、旋转、滤镜、输出文字、调色板等功能一应俱全。
几何变换¶
Image
包含调整图像大小 resize()
和旋转 rotate()
的方法。前者采用元组给出新的大小,后者采用逆时针方向的角度。
调整大小并逆时针旋转 45度
>>> from PIL import Image
>>> from matplotlib import pyplot as plt
>>> im=Image.open('./img/img6.png')
>>> o = im.resize((128, 128))
>>> outfile= o.rotate(45)
>>> plt.imshow(outfile)
>>> plt.show()
要以90度为单位旋转图像,可以使用 rotate()
或 transpose()
方法。后者也可用于围绕其水平轴或垂直轴翻转图像。
FLIP_LEFT_RIGHT
水平左右翻转Image.FLIP_TOP_BOTTOM
垂直上下翻转Image.ROTATE_90
逆时针90度Image.ROTATE_180
逆时针180度Image.ROTATE_270
逆时针270度
更多的api可以查看官方文档和源码。
图像增强¶
Filters 过滤器¶
ImageFilter 模块有很多预定义的增强过滤器,通过 filter()
方法运用。
>>> im=Image.open('./img/img4.png')
>>> plt.imshow(im)
>>> plt.show()
将图像进行增强处理
>>> from PIL import ImageFilter
>>> out = im.filter(ImageFilter.DETAIL)
>>> plt.imshow(out)
>>> plt.show()
既然可以进行增强处理自然可以进行模糊处理
>>> im2 = im.filter(ImageFilter.BLUR)
>>> plt.imshow(im2)
>>> plt.show()
像素点处理¶
point()
方法可用于转换图像的像素值(如对比度),在大多数情况下,可以将函数对象作为参数传递格此方法,它根据函数返回值对每个像素进行处理。将每个像素点扩大1.2倍
>>> out = im.point(lambda i: i * 1.2)
>>> plt.imshow(out)
>>> plt.show()
剪贴,粘贴、合并图像¶
Image类包含允许您操作图像中的区域的方法。如:要从图像中复制子矩形图像使用
crop()
方法。
从图像复制子矩形
1.截取矩形图像
>>> im=Image.open('./img/img2.png')
>>> box = (100, 100, 400, 500)
>>> region = im.crop(box)
>>> plt.imshow(region)
>>> plt.show()
定义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()
>>> region = region.transpose(Image.ROTATE_180)
>>> box = (200, 200, 500, 600)
>>> im.paste(region, box)
>>> plt.imshow(im)
>>> plt.show()
3.移动图像
移动图像就是将图片复制再粘贴。看起就像移动。
>>> image_path = './img/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()
分离和合并通道¶
Pillow 允许处理图像的各个通道,例如RGB图像有R、G、B三个通道,RGB
意思是红色、绿色、蓝色,有的图像会有R、G、B、A四个通道,‘A’是Alpha的首字母,是指一张图片的透明和半透明度。
split()
方法分离图像通道,如果图像为单通道则返回图像本身。merge
函数采用图像的 mode
和 通道元组为参数,将它们合并成新图像。
>>> im=Image.open('./img/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()
下面处理交换RGB图像的三个波段,需要注意的是, 如果你的图片是RGBA那么会出现异常,解决方法将图片转换为RGB:
Image.open(image_path).convert("RGB").save(outfile)
>>> Image.open('./img/img3.png').convert("RGB").save('./img/img3_3.png')
>>> im=Image.open('./img/img3_3.png')
>>> print(im.mode)
>>> plt.imshow(im)
>>> plt.show()
RGB
处理单独通道颜色¶
将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()
深入处理¶
图像处理功能可以使用 ImageEnhance 模块中的类。从图像创建后,可以使用 ImageEnhance 快速调整图片的对比度、亮度、饱和度和清晰度。主要方法有:
ImageEnhance.Contrast(im)
对比度ImageEnhance.Color(im)
色彩饱和度ImageEnhance.Brightness(im)
亮度ImageEnhance.Sharpness(im)
清晰度
需要先创建一个对象。
1.将对比度提高1.5倍
>>> from PIL import ImageEnhance
>>>
>>> img6=Image.open('./img/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()
2.将色彩饱和度提高2倍
>>> img1=Image.open('./img/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()
3.将亮度提高3倍
>>> img2=Image.open('./img/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()
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()
处理动态图像¶
Pillow 支持一些动态图像处理(如FLI/FLC,GIF等格式)。TIFF文件同样可以包含数帧图像。
打开动态图像时,PIL 会自动加载序列中的第一帧。你可以使用 seek
和
tell
方法在不同的帧之间移动。
>>> 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)
添加水印¶
在一些平台上传图片时,平台都会添加一个水印,表示组织或个人对图片的所有权,使用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()
用我们前面讲到的复制粘贴,添加图片相当于添加了图片水印效果。