Python Pillow(PIL)库的用法介绍(二)
在上一篇文章中介绍了Pillow库的一些基本用法,参考:https://blog.csdn.net/weixin_43790276/article/details/108478270
Pillow库的功能非常多,本文继续介绍。
官方文档路径:https://pillow.readthedocs.io/en/latest/
一、图片的变换
原图:
# coding=utf-8
from PIL import Image
image = Image.open("yazi.jpg")
data = (200, 300, 1100, 1200)
image_trans = image.transform((500, 400), Image.EXTENT, data=data, resample=Image.NEAREST, fillcolor='blue')
image_trans.show()
运行结果:
transform(size, method, data=None, resample=NEAREST, fill=1, fillcolor=None): 对图片进行变换,截取的同时进行缩放和填充等。返回指定大小的图片副本,图片的模式与原图相同。有6个参数。
size, 返回图片的尺寸。传入一个长度为2的元组(width, height)。
method, 转换方法。可以传入Image.EXTENT(一个矩形区), Image.AFFINE(仿射变换), Image.PERSPECTIVE(透视变换), Image.QUAD(一个四边形映射到一个矩形), Image.MESH(图源的四边形在一个操作)。
data, 转换方法需要的额外数据。需要根据method的不同传入不同的数据,这个参数是辅助method的,强依赖于转换方法method,格式不匹配会报错(格式详见源码中的__transformer()方法)。
(1) method为Image.EXTENT时,data格式为(x0, y0, x1, y1),传入截取矩形区域的坐标,可以超出原图的边界。
(2) method为Image.AFFINE时,data格式为(a, b, c, d, e, f),将原图中(ax+by+c, dx+ey+f)坐标的点映射到返回图片的(x, y)坐标。
(3) method为Image.PERSPECTIVE时,data格式为(a, b, c, d, e, f, g, h),将原图中((ax+by+c)/(gx+hy+1), (dx+ey+f)/(gx+hy+1))坐标的点映射到返回图片的(x, y)坐标,如果后面两个数g, h为0,则效果与Image.AFFINE相同,其实g, h一般都用0,因为随着x和y变大,相当于要除一个很大的数,原图基本会被缩成一个点。
(4) method为Image.QUAD时,data格式为(x0, y0, x1, y1, x2, y2, x3, y3),传入一个四边形的四个坐标(西北,西南,东南,东北),将这个四边形映射到返回的矩形图片中。
(5) method为Image.MESH时,其实MESH转换方法的源码(for box, quad in data:)中有错误,需要自己修改后才能用。
resample, 重采样,是一个可选的重采样过滤器。可以传入Image.NEAREST, Image.BILINEAR, Image.BICUBIC。默认为Image.NEAREST。如果图像的模式为'1'或'P',则始终设置为Image.NEAREST。
fill, 填充。如果method参数是一个Image.ImageTransformHandler对象,fill是传给转换方法的一个参数,否则,fill无效。
fillcolor, 填充颜色。超出原图区域的部分使用此颜色填充。
现在将不同转换方法method的效果进行对比。
from PIL import Image
image = Image.open("yazi.jpg")
# data = (200, 300, 1100, 1200)
# image_trans = image.transform((500, 400), Image.NEAREST, data=data, resample=Image.NEAREST, fillcolor='blue')
# image_trans.show()
# data = (0, 1, 300, 1, 0, 400)
# image_trans = image.transform((500, 400), Image.AFFINE, data=data, resample=Image.NEAREST, fillcolor='blue')
# image_trans.show()
# data = (0, 1, 500, 1, 0, 400, 0, 0)
# image_trans = image.transform((500, 400), Image.PERSPECTIVE, data=data, resample=Image.NEAREST, fillcolor='blue')
# image_trans.show()
data = (300, 200, 300, 500, 800, 800, 1100, 0)
image_trans = image.transform((500, 400), Image.QUAD, data=data, resample=Image.NEAREST, fillcolor='blue')
image_trans.show()
运行结果:
二、图片的分离
from PIL import Image
image = Image.open("yazi.jpg")
print(image.mode)
r, g, b, a = image.split()
print(r.mode, r.size)
print(g.mode, g.size)
print(b.mode, b.size)
print(a.mode, a.size)
# r.show()
# g.show()
# b.show()
a.show()
运行结果:
RGBA
L (1557, 911)
L (1557, 911)
L (1557, 911)
L (1557, 911)
split(): 对图片进行分离提取。将此图片分离成单独的颜色通道。返回组成原图的单颜色通道图片元组。如分离'RGB'图片会返回三张新图片,每张图片是一个颜色通道(红色,绿色,蓝色)的副本,都是灰度的图片。同理,'RGBA'返回四张新图片。
如果只需要提取其中一种颜色的图片,可以使用getchannel(channel)方法。
r = image.getchannel('R')
print(r.mode, r.size)
r.show()
运行结果:
L (1557, 911)
getchannel(channel): 分离出原图中的一个颜色通道。如分离'RGB'图片中的某个通道时可以传入'R', 'G', 'B'或0, 1, 2来进行分离。分离'RGBA'中的'A'时只能传入'A',不能传入3。
三、图片的合并
from PIL import Image
image = Image.open("yazi.jpg")
r, g, b, a = image.split()
image_merge = Image.merge('RGB', (r, g, a))
print(image_merge.mode, image_merge.size)
image_merge.show()
运行结果:
RGB (1557, 911)
merge(mode, bands): 将多个单通道的图片合并成一张多通道的图片。merge()是Image模块中的一个函数,不是Image类中的方法,有两个参数。
mode, 需要合成的目标图片的模式。如'RGB','RGBA'。
bands, 用于合并的单通道图片列表。传入一个列表或元组,列表长度与目标图片的模式要对应,如'RGB'需要传入长度为3的列表,'RGBA'需要传入长度为4的列表。列表中的每张单通道图片尺寸必须相同,否则报错。
四、图片的过滤
1. 图片过滤器
Pillow提供了以下预定义的图片过滤器,参考:https://pillow.readthedocs.io/en/latest/reference/ImageFilter.html#module-PIL.ImageFilter
filter | 描述 |
BLUR | 模糊 |
CONTOUR | 轮廓 |
DETAIL | 详情 |
EDGE_ENHANCE | 边缘增强 |
EDGE_ENHANCE_MORE | 边缘增强更多 |
EMBOSS | 电磁波 |
FIND_EDGES | 寻找边缘 |
SHARPEN | 夏普 |
SMOOTH | 光滑 |
SMOOTH_MORE | 更光滑 |
2. 图片的过滤
from PIL import Image, ImageFilter
image = Image.open("yazi.jpg")
# image_blur = image.filter(ImageFilter.BLUR)
# image_blur.show()
# image_contour = image.filter(ImageFilter.CONTOUR)
# image_contour.show()
# image_edge = image.filter(ImageFilter.EDGE_ENHANCE_MORE)
# image_edge.show()
image_emboss = image.filter(ImageFilter.EMBOSS)
image_emboss.show()
运行结果:
filter(filter): 使用指定的过滤器对图片进行过滤。传入一个ImageFilter过滤器,上面表格中的过滤器都支持。
五、图片的混合
为了体现出混合的效果,需要使用两张图片,所以再加入一张图片。
from PIL import Image
image = Image.open('yazi.jpg').crop((100, 100, 1300, 900))
image2 = Image.open('yazi2.jpg').crop((100, 0, 1300, 800))
image.save('duck1.png')
image2.save('duck2.png')
duck1 = Image.open('duck1.png')
duck2 = Image.open('duck2.png')
print(duck1.size, duck1.mode)
print(duck2.size, duck2.mode)
image_blend = Image.blend(duck1, duck2, 0.7)
image_blend.show()
运行结果:
(1200, 800) RGBA
(1200, 800) RGBA
blend(im1, im2, alpha): 将两张图片混合成一张图片。blend()是Image模块中的一个函数,不是Image类中的方法,有3个参数。
im1, 混合的第一张图片。
im2, 混合的第二张图片。图片的尺寸和模式必须与第一张图片相同,否则报错。
alpha, 混合的因子。一般传入一个0~1的浮点数,如果alpha等于0.0,混合结果为第一张图片,如果alpha等于1.0,混合结果为第二张图片。如果alpha为0~1之间的数,则混合的图片out=im1*(1.0-alpha) + image2*alpha,效果为两张图片的叠加。如果传入其他值,则混合出来的图片效果比较混乱。
六、图片的复合
from PIL import Image
duck1 = Image.open('duck1.png')
duck2 = Image.open('duck2.png')
r, g, b, a = duck2.split()
image_compo = Image.composite(duck1, duck2, r)
image_compo.show()
运行结果:
composite(image1, image2, mask): 将两张图片复合成一张图片,使用蒙版。composite()是Image模块中的一个函数,不是Image类中的方法,有3个参数。
image1, 复合的第一张图片。
image2, 复合的第二张图片。图片的尺寸和模式必须与第一张图片相同,否则报错。
mask, 蒙版。也是一张图片,这张图片的模式为'1', 'L'或'RGBA',尺寸必须与前两张图片相同。
此方法其实是将第一张图片粘贴到第二张图片上,相当于image2.paste(image1, None, mask),可以参考Image类中paste()方法的用法。
七、图片的旋转
from PIL import Image
duck1 = Image.open('duck1.png')
print(duck1.size)
image = duck1.rotate(15, center=(0, 0), expand=1, translate=(100, 100), fillcolor=(0, 0, 255))
print(image.size)
image.show()
运行结果:
(1200, 800)
(1367, 1084)
rotate(angle, resample=NEAREST, expand=0, center=None, translate=None, fillcolor=None): 对图片进行旋转,返回一张旋转后的图片副本。有6个参数。
angle, 旋转的角度。这个参数是一个必传参数,按角度制计算,按逆时针方向旋转。
resample, 重采样,是一个可选的重采样过滤器。可以传入Image.NEAREST, Image.BILINEAR, Image.BICUBIC。默认为Image.NEAREST。如果图像的模式为'1'或'P',则始终设置为Image.NEAREST。
expand, 可扩展性。传入数字0或1,表示布尔值,默认为0。如果值为0,对图片旋转后,返回图片的尺寸与原图尺寸一样。如果值为1,则旋转后,返回图片的尺寸会根据旋转角度自动调整(如果旋转中心保持默认和没有进行平移,则返回图片中可以看到完整的原图)。
center, 旋转的中心。传入长度为2的元组(x, y),表示旋转中心的像素点。默认为原图的几何中心。
translate, 平移的坐标。传入长度为2的元组(x, y),将原图按(x, y)进行平移,默认为(0, 0)。
fillcolor, 填充颜色。传入一个颜色值,颜色值可以是元组表示法,也可以是颜色的十六进制表示法或颜色英文。如上面的(0, 0, 255)可以换成'#0000FF'或'blue'。当图片旋转后,原图变斜了,但返回图片还是矩形的,所以空出的部分需要进行填充,默认为黑色。
八、图片的转置和翻转
from PIL import Image
image = Image.open("yazi.jpg")
image1 = image.transpose(Image.FLIP_LEFT_RIGHT)
# image1.show()
image2 = image.transpose(Image.FLIP_TOP_BOTTOM)
# image2.show()
image3 = image.transpose(Image.ROTATE_180)
# image3.show()
image4 = image.transpose(Image.TRANSVERSE)
image4.show()
运行结果:
transpose(method): 转置或翻转图片,返回转置后的图片副本。method可以传入Image.FLIP_LEFT_RIGHT, Image.FLIP_TOP_BOTTOM, Image.ROTATE_90, Image.ROTATE_180, Image.ROTATE_270, Image.TRANSPOSE, Image.TRANSVERSE。这些方法都是旋转90度和翻转组合的结果。
九、改变图片的像素点位置
from PIL import Image
image = Image.open("yazi.jpg")
image_effect = image.effect_spread(7)
image_effect.show()
运行结果:
effect_spread(distance): 随机改变图片中像素点的位置,返回处理后的图片副本。将每个像素点随机移动到指定距离范围内的另一个点,distance表示每个像素点的随机变化距离,处理后的图片有“粒度”的变化。
在Image模块中,还有很多对图片处理的方法和函数,如有一组以get和put开头的方法,用于获取或修改图片的属性,有将图片与字节等互相转换的方法,有对动图的处理方法等。这里就不继续一一介绍了,感兴趣可以看看源码和官方文档,并多做尝试。