大家好,欢迎来到IT知识分享网。
Pillow库,PIL的升级版,一个免费开源的Python图像处理库。
- Pillow 库能够很轻松的读取和保存各种格式的图片;
- Pillow 库提供了简洁易用的 API 接口,可以让您轻松地完成许多图像处理任务;
- Pillow 库能够配合 GUI(图形用户界面) 软件包 Tkinter 一起使用;
- Pillow 库中的 Image 对象能够与 NumPy ndarray 数组实现相互转换。
丰富功能的实现得益于 Pillow 提供了众多的模块。在 Pillow 库中有二十多个模块,比如 Image 图像处理模块、ImageFont 添加文本模块、ImageColor 颜色处理模块、ImageDraw 绘图模块等等,每个模块各自实现了不同的功能,同时模块之间又可以互相配合。
相关资源
- Python Pillow 官方文档:Pillow (PIL Fork) 10.2.0.dev0 documentation
- 本套教程的图片资源下载:https://pan.baidu.com/s/17mhdGCTuKMPS5RuAgbtv3A(提取码:n1v2)
教程特点
读者&阅读条件
本套 Pillow 教程适合有一定 Python 编程基础的人员学习,如果您已经掌握 Python 基础知识,那可以直接阅读本教程,否则建议您提前阅读《Python语言学习》。通过本套教程的学习,您将初步掌握图像处理的相关知识,将它作为学习图像处理的第一套教程,是一个非常不错的选择。
一、Pillow是什么
Pillow 的初衷只是想作为 PIL 库的分支和补充,如今它已是“青出于蓝而胜于蓝”。
除了 PIL 和 Pillow 库之外,Python 还提供了一些其他图像处理库:
- Scikit-image:一款基于 scipy 科学计算的图像处理软件包,以数组的形式对图像进行处理;
- OpenCV:其实是一个 C++ 图像处理库,不过它提供了 Python 语言的接口。
Pillow 是 Python 中较为基础的图像处理库,主要用于图像的基本处理,比如裁剪图像、调整图像大小和图像颜色处理等。与 Pillow 相比,OpenCV 和 Scikit-image 的功能更为丰富,所以使用起来也更为复杂,主要应用于机器视觉、图像分析等领域,比如众所周知的“人脸识别”应用。
1、Pillow版本支持
Pillow 支持跨平台运行,比如 Windows、Linux、MacOS 等,其最新版本为 Pillow 8.3.2,该版本支持 Python 3.6 及以上的版本(推荐使用)。Pillow 与 Python 支持版本的对照表如下所示:
| Python版本 | 3.10 | 3.9 | 3.8 | 3.7 | 3.6 | 3.5 | 2.7 |
|---|---|---|---|---|---|---|---|
| Pillow>=8.3.2 | 支持 | 支持 | 支持 | 支持 | 支持 | ||
| Pillow8.0-8.3.1 | 支持 | 支持 | 支持 | 支持 | |||
| Pillow7.0-7.2 | 支持 | 支持 | 支持 | 支持 | |||
| Pillow6.2.1-6.22 | 支持 | 支持 | 支持 | 支持 | 支持 | ||
| Pillow6..0-6.2.0 | 支持 | 支持 | 支持 | 支持 |
2、Pillow库特点
Pillow 库作为图像处理的常用库,主要有以下三大特点:
(1)支持广泛的文件格式
Pillow 支持广泛的图像格式,比如 “jpeg”,”png”,”bmp”,”gif”,”ppm”,”tiff” 等。同时,它也支持图像格式之间的相互转换。总之, Pillow 几乎能够处理任何格式的图像。
(2) 提供了丰富的功能
Pillow 提供了丰富的图像处理功能,可概括为两个方面:
- 图像归档
- 图像处理
图像归档,包括创建缩略图、生成预览图像、图像批量处理等;
而图像处理,则包括调整图像大小、裁剪图像、像素点处理、添加滤镜、图像颜色处理等。
(3)配合GUI工具使用
二、Pillow的下载与安装
Pillow 安装非常简单和方便,有三种安装途径,分别是:
- pip包管理器安装
- 二进制包安装
- Anaconda安装
下面对上述安装方式做简单介绍。
注意,PIL 库与 Pillow 库不允许在同一环境中共存,如果您之前安装了 PIL 库,请卸载后,再安装 Pillow。
1、pip包管理器安装
通过 Python 包管理器 pip 来安装 Pillow 是最简单、轻量级的一种安装方式,并且这种方法适用于任何平台。只需执行以下命令即可:
pip install pillow
2、二进制包安装
通过 Python PyPi 第三方库官网(Pillow · PyPI)下载与平台系统相对应的版本,如下所示:
pip install + whl文件名
3、Anaconda安装
Anaconda 是一款开源的 Python 发行版(下载地址:Free Download | Anaconda),它是当下较为流行的科学计算平台,支持 Windows、Linux、MacOS 系统。Anaconda 自带许多已经安装完成软件包,其中就包含 Pillow,因此无须重新安装。
图2:Anaconda安装
无论采用上述哪种方式都可以成功安装 Pillow。不过对于初学者来说,我们建议使用第一种安装方式。
注意,本教程以 Windows 平台为例对 Pillow 库的相关知识进行讲解。
最后,在 CMD 命令行打开 Python 解释器交互环境,输入以下代码,验证 Pillow 是否安装成功。
#导入Image类,该类是pillow中用于图像处理的重要类 from PIL import Image
如下所示,如果解释器没有返回错误,则证明已经安装成功。
图3:测试Pillow安装成功
注意,这里使用 PIL 导入,但实际上使用的是 Pillow 库,这里的 PIL 可以看做是 Pillow 库的简称。
三、Pillow创建Image对象
from PIL import Image
使用 Image 类可以实例化一个 Image 对象,通过调用该对象的一系列属性和方法对图像进行处理。Pilow 提供了两种创建 Image 实例对象的方法,下面对它们进行简单的介绍。
1、open()
使用 Image 类的 open() 方法,可以创建一个 Image 对象,语法格式如下:
im = Image.open(fp, mode = "r")
参数说明:
- fp:即 filepath 的缩写,表示文件路径,字符串格式;
- mode:可选参数,若出现该参数,则必须设置为 “r”,否则会引发 ValueError 异常。
示例如下:
from PIL import Image #打开一图片文件 im = Image.open("C:/Users/Administrator/Desktop/c-net.png") #要显示图像需要调用show()方法 im.show()
图像显示结果如下:
图1:显示结果
2、new()
使用 Image 类提供的 new() 方法可以创建一个新的 Image 对象,语法格式如下:
im = Image.new(mode, size, color)
参数说明如下:
- mode:图像模式,字符串参数,比如 RGB(真彩图像)、L(灰度图像)、CMYK(色彩图打印模式)等;
- size:图像大小,元组参数(width, height)代表图像的像素大小;
- color:图片颜色,默认值为 0 表示黑色,参数值支持(R,G,B)三元组数字格式、颜色的十六进制值以及颜色英文单词。
示例如下:
#使用颜色的十六进制格式 im_1 = Image.new(mode = 'RGB', (260, 100), color = "#ff0000") im_1.show()
输出图像如下所示:
图2:显示结果
四、Pillow Image对象属性
Image 对象有一些常用的基本属性,这些属性能够帮助我们了解图片的基本信息,下面对这些属性做简单的讲解:
1、size:查看图像的尺寸
from PIL import Image im = Image.open("C:/Users/Administrator/Desktop/c-net.png") #打印image图像 print(im) #查看尺寸 print("宽是%s高是%s"%(im.width, im.height)) %或者通过size查看 print("图像的大小size:", im.size)
输出结果:
<PIL.PngImagePlugin.PngImageFile image mode=RGBA size=455x191 at 0x381C750> 宽是455高是191 图像的大小size: (455, 191)
2、format:查看图片的格式
from PIL import Image im = Image.open("C:/Users/Administrator/Desktop/c-net.png") print("图像的格式:", im.format)
输出结果:
图像的格式: PNG
3、readonly:图片是否为只读
from PIL import Image im = Image.open("C:/Users/Administrator/Desktop/c-net.png") print("图像是否为只读:", im.readonly)
该属性的返回为 0 或者 1,分别对应着是和否,输出结果如下:
图像是否为只读: 1
4、 info:查看图片相关信息
from PIL import Image im = Image.open("C:/Users/Administrator/Desktop/c-net.png") #包括了每英寸像素点大小和截图软件信息 print("图像信息:", im.info)
该属性的返回值为字典格式,输出结果如下:
图像信息: {'dpi': (96, 96), 'Software': 'Snipaste'}
5、 mode:图像模式
from PIL import Image im = Image.open("C:/Users/Administrator/Desktop/c-net.png") print("图像模式信息:", im.mode)
输出结果:
图像的模式: RGBA
上述涉及了许多图片模式的名称,比如 RGB、RGBA 等,下面对常用的图片模式做简单的总结,如下表所示:
| mode | 描述 |
|---|---|
| 1 | 1 位像素(取值范围 0-1),0表示黑,1 表示白,单色通道。 |
| L | 8 位像素(取值范围 0 -255),灰度图,单色通道。 |
| P | 8 位像素,使用调色板映射到任何其他模式,单色通道。 |
| RGB | 3 x 8位像素,真彩色,三色通道,每个通道的取值范围 0-255。 |
| RGBA | 4 x 8位像素,真彩色+透明通道,四色通道。 |
| CMYK | 4 x 8位像素,四色通道,可以适应于打印图片。 |
| YCbCr | 3 x 8位像素,彩色视频格式,三色通道。 |
| LAB | 3 x 8位像素,L * a * b颜色空间,三色通道。 |
| HSV | 3 x 8位像素,色相,饱和度,值颜色空间,三色通道。 |
| I | 32 位有符号整数像素,单色通道。 |
| F | 32 位浮点像素,单色通道。 |
五、Pillow图片格式转换
1、save()
顾名思义,save() 方法用于保存图像,当不指定文件格式时,它会以默认的图片格式来存储;如果指定图片格式,则会以指定的格式存储图片。save() 的语法格式如下:
Image.save(fp, format = None)
参数说明如下:
- fp:图片的存储路径,包含图片的名称,字符串格式;
- format:可选参数,可以指定图片的格式。
示例如下:
from PIL import Image im = Image.open("C:/Users/Administrator/Desktop/c-net.png") im.save('C:/Users/Administrator/Desktop/c.biancheng.net.bmp')
此时您的计算机桌面上会存在一个 c.bianchneg.net.BMP格式的图片。
2、convert()+save()
注意,并非所有的图片格式都可以用 save() 方法转换完成,比如将 PNG 格式的图片保存为 JPG 格式,如果直接使用 save() 方法就会出现以下错误:
from PIL import Image im = Image.open("C:/Users/Administrator/Desktop/c-net.png") im.save('C:/Users/Administrator/Desktop/c.biancheng.net.jpg')
错误信息如下所示:
#系统错误,RGBA不能作为JPEG图片的模式 OSError: cannot write mode RGBA as JPEG
引发错误的原因是由于 PNG 和 JPG 图像模式不一致导致的。其中 PNG 是四通道 RGBA 模式,即红色、绿色、蓝色、Alpha 透明色;JPG 是三通道 RGB 模式。因此要想实现图片格式的转换,就要将 PNG 转变为三通道 RGB 模式。
Image 类提供的 convert() 方法可以实现图像模式的转换。该函数提供了多个参数,比如 mode、matrix、dither 等,其中最关键的参数是 mode,其余参数无须关心。语法格式如下:
convert(mode, params)
- mode:指的是要转换成的图像模式;
- params:其他可选参数。
修改后的代码如下所示:
from PIL import Image im = Image.open("C:/Users/Administrator/Desktop/c-net.png") #此时返回一个新的image图像,转换图片模式 image = im.convert('RGB') #调用save()保存 im.save('C:/Users/Administrator/Desktop/c.biancheng.net.jpg')
通过以上代码,成功将 PNG 格式的图片转换为了 JPG 格式。
六、 Pillow图像缩放操作
在图像处理过程中经常会遇到缩小或放大图像的情况,Image 类提供的 resize() 方法能够实现任意缩小和放大图像。
resize() 函数的语法格式如下:
resize(size, resample = image.BICUBIC, box = None, reducing_gap = None)
参数说明:
- size:元组参数 (width,height),图片缩放后的尺寸;
- resample:可选参数,指图像重采样滤波器,与 thumbnail() 的 resample 参数类似,默认为 Image.BICUBIC;
- box:对指定图片区域进行缩放,box 的参数值是长度为 4 的像素坐标元组,即 (左,上,右,下)。注意,被指定的区域必须在原图的范围内,如果超出范围就会报错。当不传该参数时,默认对整个原图进行缩放;
- reducing_gap:可选参数,浮点参数值,用于优化图片的缩放效果,常用参数值有 3.0 和 5.0。
注意,resize() 会返回一个新的 image 对象。下面是一组对图像进行放大操的示例:
from PIL import Image im = Image.open("C:/Users/Administrator/Desktop/c-net.png") try: #放大图片 image = im.resize((550,260)) #将新图像保存至桌面 image.save("C:/Users/Administrator/Desktop/放大图像.png") print("查看新图像的尺寸", img.size) expect IOError: print("放大图像失败")
输出结果:
查看新图像的尺寸 (550, 260)
放大后的图片效果。如下所示:
图1:pillow放大图像
对图片的局部位置进行放大,示例如下:
from PIL import Image im = Image.open("C:/Users/Administrator/Desktop/c-net.png") try: #选择放大的局部位置,并选择图片重采样方式 #box四元组指的是像素坐标(左,上,右,下) #(0, 0,120, 180),表示以原图的左上角为原点,选择宽和高分别为(120,180)的图像区域 image = im.resize((550,260), reshape = Image.LANCZOS, box = (0, 0, 120, 180)) image.show() #保存 image.save("C:/Users/Administrator/Desktop/放大图像.png") print("查看新图像的尺寸", img.size) expect IOError: print("放大失败")
图片的放大效果如下所示:
图2:局部放大操作
1、创建缩略图
缩略图(thumbnail image)指的是将原图缩小至一个指定大小(size)的图像。通过创建缩略图可以使图像更易于展示和浏览。
Image 对象提供了一个 thumbnail() 方法用来生图像的缩略图,该函数的语法格式如下:
thumbnail(size, resample)
- size:元组参数,指的是缩小后的图像大小;
- resample:可选参数,指图像重采样滤波器,有四种过滤方式,分别是 Image.BICUBIC(双立方插值法)、PIL.Image.NEAREST(最近邻插值法)、PIL.Image.BILINEAR(双线性插值法)、PIL.Image.LANCZOS(下采样过滤插值法),默认为 Image.BICUBIC。
使用示例如下:
from PIL import Image im = Image.open("C:/Users/Administrator/Desktop/c-net.png") im.thumbnail((150,50)) print("缩略图尺寸", im.size) #将缩略图保存至桌面 image.save("C:/Users/Administrator/Desktop/th.png")
输出结果:
缩略图尺寸 (118, 50)
注意,缩略图的尺寸可能与您指定的尺寸不一致,这是因为 Pillow 会对原图像的长、宽进行等比例缩小,当指定的尺寸不符合图像的尺寸规格时,缩略图就会创建失败, 比如指定的尺寸超出了原图像的尺寸规格。
2、批量修改图片尺寸
在图像处理过程中,对于某些不需要精细处理的环节,我们往往采用批量处理方法,比如批量转换格式,批量修改尺寸,批量添加水印,批量创建缩略图等,这是一种提升工作效率的有效途径,它避免了单一、重复的操作。通过 Pillow 提供的 Image.resize() 方法可以批量地修改图片尺寸,下面看一组简单的示例。
首先找一些类型相同,但尺寸不一的图片,并把它们放入桌面的 image01 文件夹中。如下所示:
图3:待处理的图片
下面开始编写代码:
#批量修改图片尺寸 import os from PIL import Image #读取图片目录 fileName = os.listdir('C:/Users/Administrator/Desktop/image01/') print(fileName) #设定尺寸 width = 350 height = 350 #如果目录不存在,则创建目录 if not os.path.exists('C:/Users/Administrator/Desktop/NewImage/'): os.mkdir('C:/Users/Administrator/Desktop/NewImage/') #循环读取每一张图片 for img in fileName: old_pic = Image.open('C:/Users/Administrator/Desktop/image01/' + img) new_image = old_pic.resize((width, height), Image.BILINEAR) print(new_img) new_pic = Image.open('C:/Users/Administrator/Desktop/NewImage/' + img)
输出结果如下所示:
['向日葵.jpg', '国宝.jpg', '矩形图.jpg', '蝴蝶.jpg'] <PIL.Image.Image image mode=RGB size=350x350 at 0x2B9E670> <PIL.Image.Image image mode=RGB size=350x350 at 0x31D0C90> <PIL.Image.Image image mode=RGB size=350x350 at 0x2B90DB0> <PIL.Image.Image image mode=RGB size=350x350 at 0x31D0C90>
NewImage 目录的内容如下:
图4:处理完成的图片
七、Pillow图像分离与合并
我们知道,图像(指数字图像)由许多像素点组成,像素是组成图像的基本单位,而每一个像素点又可以使用不同的颜色,最终呈现出了绚丽多彩的图像。在《第四部分 Pillow Image对象属性》一节,我们介绍一些图片模式,它们的本质就是图片呈现颜色时需要遵循的规则,比如 RGB、RGBA、CYMK 等,而图像的分离与合并,指的就是图像颜色的分离和合并。
Image 类提供了用于分离图像和合并图像的方法 split() 和 merge() 方法,通常情况下,这两个方法会一起使用。
1、split()
split() 的使用方法比较简单,用来分离颜色通道。我们使用它来处理蝴蝶图片:
图1:pilow 图像处理操作
代码如下所示:
im = Image.open("C:/Users/Administrator/Desktop/1.jpg") #修改图像大小,以适应图像处理 image = im.resize((450,400)) image.save("C:/Users/Administrator/Desktop/2.jpg") #分离颜色通道,产生三个Image对象 r, g,b =image.split() r.show() g.show() b.show()
输出的结果,依次展示如下:
图2:分离结果预览
2、merge()
Image 类提供的 merge() 方法可以实现图像的合并操作。注意,图像合并,可以是单个图像合并,也可以合并两个以上的图像。
merge() 方法的语法格式如下:
Image.merge(mode, bands)
参数说明如下:
- mode:指定输出图片的模式。
- bands:参数类型为元组或者列表序列,其元素值是组成图像的颜色通道,比如 RGB 分别代表三种颜色通道,可以表示为 (r,g,b)。
注意,该函数会返回一个新的 Image 对象。
下面对图像合并的两种类型分别进行介绍:
一. 单个图像的合并指的是将颜色通道进行重新组合,从而得到不一样的图片效果,代码如下所示:
from PIL import Image im = Image.open("C:/Users/Administrator/Desktop/1.jpg") #修改图像大小,以适应图像处理 image = im.resize((450,400)) image.save("C:/Users/Administrator/Desktop/2.jpg") #分离颜色通道,产生三个Image对象 r, g,b =image.split() #重新组合颜色通道,返回新的Image对象 image_merge = Image.merge('RGB', (b, g, r)) image_merge.show() #保存图像至桌面 image_merge.save("C:/Users/Administrator/Desktop/3.jpg")
新合成的图像入如下所示:
图3:图像合并操作
两张图片的合并操作也并不复杂,但是要求两张图片的模式、图像大小必须要保持一致,否则不能合并。因此,对于那些模式、大小不同的图片要进行预处理。
下面我们将蝴蝶图与向日葵图进行合并,向日葵原图如下:
图4:向日葵原图
示例代码如下:
from PIL import Image #打开图2.jpg im_1 = Image.open("C:/Users/Administrator/Desktop/2.jpg") im_2 = Image.open("C:/Users/Administrator/Desktop/向日葵.jpg") #因为两种图片的图片格式一致,所以仅需要处理图片的大小,让它们保持一致 #让 im_2 的图像尺寸与 im_1 一致,注意此处新生成了 Image 对象 image = im_2.resize(im_1.size) #接下来,对图像进行颜色分离操作 r1, g1, b1 =im_1.split() r2, g2, b2 =image.split() #合并图像 im_3 = Image.merge('RGB', [r2, g1, b2]) im_3.show() im_3.save("C:/Users/Administrator/Desktop/合成.jpg")
预览图像的合成结果:
图5:合成图像
3、扩展知识:blend() 混合图片
Image 类也提供了 blend() 方法来混合 RGBA 模式的图片(PNG 格式),函数的语法格式如下:
Image.blend(image1, image1, alpha)
参数说明如下:
- image1,image2:表示两个 Image 对象。
- alpha:表示透明度,取值范围为 0 到 1,当取值为 0 时,输出图像相当于 image1 的拷贝,而取值为 1 时,则是 image2 的拷贝,只有当取值为 0.5 时,才为两个图像的中合。因此改值的大小决定了两个图像的混合程度。
与 RGB 模式相比,RGBA 在 RGB 的基础上增加了透明度,通过 Alpha 取值来决定两个图像的混合程度。示例如下:
""" 混合rgba模式的图像 """ im1 = Image.open("C:/Users/Administrator/Desktop/c-net.png") image = Image.open("C:/Users/Administrator/Desktop/心形函数图像.png") im2 = image.resize(im1.size) def blend_im(im1, im2): #设置 alpha 为0.5 Image.blend(im1, im2, 0.5).save("C:/Users/Administrator/Desktop/C语言中文网.png") #调用函数 blend_im(im1, im2)
输出结果如下:
图6:混合图像
八、Pillow图像裁剪、复制、粘贴操作
图像的剪裁、复制、粘贴是图像处理过程中经常使用的基本操作,Pillow Image 类提供了简单、易用的 API 接口,能够帮助您快速实现这些简单的图像处理操作。
1、图像裁剪操作
Image 类提供的 crop() 函数允许我们以矩形区域的方式对原图像进行裁剪,函数的语法格式如下:
crop(box = None)
box:表示裁剪区域,默认为 None,表示拷贝原图像。
注意:box 是一个有四个数字的元组参数 (x_左上,y_左下,x1_右上,y1_右下),分别表示被裁剪矩形区域的左上角 x、y 坐标和右下角 x,y 坐标。默认 (0,0) 表示坐标原点,宽度的方向为 x 轴,高度的方向为 y 轴,每个像素点代表一个单位。
crop() 函数的会返回一个 Image 对象,使用示例如下:
""" 裁剪图像 """ im = Image.open("C:/Users/Administrator/Desktop/C语言中文网.png") box = (0, 0, 200, 100) im_crop = im.crop(box) im_crop.show()
输出图像显示如下:
图1:图像裁剪
最终,在原图的基础上裁剪出一张像素为 200 * 100 的图像。
2、图像拷贝和粘贴
拷贝、粘贴操作几乎是成对出现的,Image 类提供了 copy() 和 paste() 方法来实现图像的复制和粘贴。其中复制操作(即 copy() 方法)比较简单,下面主要介绍 paste() 粘贴方法,语法格式如下所示:
paste(image, box = None, mask = None)
该函数的作用是将一张图片粘贴至另一张图片中。注意,粘贴后的图片模式将自动保持一致,不需要进行额外的转换。参数说明如下:
- image:指被粘贴的图片;
- box:指定图片被粘贴的位置或者区域,其参数值是长度为 2 或者 4 的元组序列,长度为 2 时,表示具体的某一点 (x,y);长度为 4 则表示图片粘贴的区域,此时区域的大小必须要和被粘贴的图像大小保持一致。
- mask:可选参数,为图片添加蒙版效果。
下面复制一张原图像的副本,对副本进行裁剪、粘贴操作,代码如下所示:
im = Image.open("C:/Users/Administrator/Desktop/C语言中文网.png") #复制一张图片副本 im_copy = im.copy() #对副本进行裁剪 im_crop = im.crop((0, 0, 200, 100)) #创建一个新的图像作为蒙版,L模式,单颜色值 img_new = Image.new('L', (200, 100), 200) #将裁剪后的副本粘贴至副本图像上,并添加蒙版 im_crop.paste(im_crop, (100, 100, 300, 200), mask = image_new) #显示粘贴后的图像 im_crop.show()
输出的显示结果,如下所示:
图2:图像复制粘贴
九、Pillow图像几何变换
图像的几何变换主要包括图像翻转、图像旋转和图像变换操作,Image 类提供了处理这些操作的函数 transpose()、rotate() 和 transform(),下面分别对它们进行讲解。
1、transpose()翻转操作
该函数可以实现图像的垂直、水平翻转,语法格式如下:
Image.transpose(method)
method 参数决定了图片要如何翻转,参数值如下:
- Image.FLIP_LEFT_RIGHT:左右水平翻转;
- Image.FLIP_TOP_BOTTOM:上下垂直翻转;
- Image.ROTATE_90:图像旋转 90 度;
- Image.ROTATE_180:图像旋转 180 度;
- Image.ROTATE_270:图像旋转 270 度;
- Image.TRANSPOSE:图像转置;
- Image.TRANSVERSE:图像横向翻转。
使用示例如下:
im = Image.open("C:/Users/Administrator/Desktop/c-net.png") #返回一个新的Image对象 im_out = im.transpose(Image.FLIP_LEFT_RIGHT) im_out.show() im_out.save("C:/Users/Administrator/Desktop/水平翻转.png")
图像显示结果,如下所示:
图1:图像翻转操作
2、rotate()任意角度旋转
当我们想把图像旋转任意角度时,可以使用 rotate() 函数,语法格式如下:
Image.rotate(angle, resample = PIL.Image.NEAREST, expand = None, ceter = None, translate = None, fillcolor = None)
参数说明如下:
- angle:表示任意旋转的角度;
- resample:重采样滤波器,默认为 PIL.Image.NEAREST 最近邻插值方法;
- expand:可选参数,表示是否对图像进行扩展,如果参数值为 True 则扩大输出图像,如果为 False 或者省略,则表示按原图像大小输出;
- center:可选参数,指定旋转中心,参数值是长度为 2 的元组,默认以图像中心进行旋转;
- translate:参数值为二元组,表示对旋转后的图像进行平移,以左上角为原点;
- fillcolor:可选参数,填充颜色,图像旋转后,对图像之外的区域进行填充。
使用示例如下:
im = Image.open("C:/Users/Administrator/Desktop/c-net.png") #translate的参数值可以为负数,并将旋转图之外的区域填充为绿色 #返回同一个新的Image对象 im_out = im.rotate(45, translate = (0, -25),fillcolor = "green") im_out.show() im_out.save("C:/Users/Administrator/Desktop/旋转图像.png")
输出结果:
图2:图像旋转
3、transform()图像变换
该函数能够对图像进行变换操作,通过指定的变换方式,产生一张规定大小的新图像,语法格式如下:
Image.transform(size, method, data = None, resample = 0)
参数说明:
- size:指定新图片的大小;
- method:指定图片的变化方式,比如 Image.EXTENT 表示矩形变换;
- data:该参数用来给变换方式提供所需数据;
- resample:图像重采样滤波器,默认参数值为 PIL.Image.NEAREST。
使用示例如下:
from PIL import Image im = Image.open("C:/Users/Administrator/Desktop/c-net.png") #设置图像大小250*250,并根据data的数据截取原图像的区域,生成新的图像 im_out = im.transform((250, 250), Image.EXTENT, data = [0, 0, 30 + im.width//4, im.height//3]) im_out.show() im_out.save("C:/Users/Administrator/Desktop/变换.png")
输出图像显示如下:
图3:图像矩形变换
十、Pillow图像降噪处理
由于成像设备、传输媒介等因素的影响,图像总会或多或少的存在一些不必要的干扰信息,我们将这些干扰信息统称为“噪声”,比如数字图像中常见的“椒盐噪声”,指的是图像会随机出现的一些白、黑色的像素点。图像噪声既影响了图像的质量,又妨碍人们的视觉观赏。因此,噪声处理是图像处理过程中必不可少的环节之一,我们把处理图像噪声的过程称为“图像降噪”。
随着数字图像技术的不断发展,图像降噪方法也日趋成熟,通过某些算法来构造滤波器是图像降噪的主要方式。滤波器能够有效抑制噪声的产生,并且不影响被处理图像的形状、大小以及原有的拓扑结构。
Pillow 通过 ImageFilter 类达到图像降噪的目的,该类中集成了不同种类的滤波器,通过调用它们从而实现图像的平滑、锐化、边界增强等图像降噪操作。常见的降噪滤波器如下表所示:
| 名称 | 说明 |
|---|---|
| ImageFilter.BLUR | 模糊滤波,即均值滤波 |
| ImageFilter.CONTOUR | 轮廓滤波,寻找图像轮廓信息 |
| ImageFilter.DETAIL | 细节滤波,使得图像显示更加精细 |
| ImageFilter.FIND_EDGES | 寻找边界滤波(找寻图像的边界信息) |
| ImageFilter.EMBOSS | 浮雕滤波,以浮雕图的形式显示图像 |
| ImageFilter.EDGE_ENHANCE | 边界增强滤波 |
| ImageFilter.EDGE_ENHANCE_MORE | 深度边缘增强滤波 |
| ImageFilter.SMOOTH | 平滑滤波 |
| ImageFilter.SMOOTH_MORE | 深度平滑滤波 |
| ImageFilter.SHARPEN | 锐化滤波 |
| ImageFilter.GaussianBlur() | 高斯模糊 |
| ImageFilter.UnsharpMask() | 反锐化掩码滤波 |
| ImageFilter.Kernel() | 卷积核滤波 |
| ImageFilter.MinFilter(size) | 最小值滤波器,从 size 参数指定的区域中选择最小像素值,然后将其存储至输出图像中。 |
| ImageFilter.MedianFilter(size) | 中值滤波器,从 size 参数指定的区域中选择中值像素值,然后将其存储至输出图像中。 |
| ImageFilter.MaxFilter(size) | 最大值滤波器 |
| ImageFilter.ModeFilter() | 模式滤波 |
图1:pilow图像处理
1、模糊处理(ImageFilter.BLUR)
#导入Image类和ImageFilter类 from PIL import Image, ImageFilter im = Image.open("C:/Users/Administrator/Desktop/国宝.jpg") #图像模糊处理 im_blur = im.filter(ImageFilter.BLUR) im_blur.show() im_blur.save("C:/Users/Administrator/Desktop/模糊.png")
输出图像如下:
图2:图像模糊(注意这里模糊后的图像格式发生了变化)
2、轮廓图(ImageFilter.CONTOUR)
#导入Image类和ImageFilter类 from PIL import Image, ImageFilter im = Image.open("C:/Users/Administrator/Desktop/国宝.jpg") #生成轮廓图 im2 = im.filter(ImageFilter.CONTOUR) im2.show() im2.save("C:/Users/Administrator/Desktop/轮廓图.png")
输出图像,显示如下:
图3:图像轮廓图(注意这里处理后的图像格式发生了变化)
3、边缘检测 (ImageFilter.FIND_EDGES)
#导入Image类和ImageFilter类 from PIL import Image, ImageFilter im = Image.open("C:/Users/Administrator/Desktop/国宝.jpg") #边缘检测 im3 = im.filter(ImageFilter.FIND_EDGES) im3.show() im3.save("C:/Users/Administrator/Desktop/边缘检测.png")
输出图像结果:
图4:图像边缘检测(注意这里处理后的图像格式发生了变化)
4、浮雕图(ImageFilter.EMBOSS)
#导入Image类和ImageFilter类 from PIL import Image, ImageFilter im = Image.open("C:/Users/Administrator/Desktop/国宝.jpg") #浮雕图 im2 = im.filter(ImageFilter.EMBOSS) im2.show() im2.save("C:/Users/Administrator/Desktop/浮雕图.png")
输出图像如下:
图5:浮雕图(注意这里处理后的图像格式发生了变化)
5、平滑图像(ImageFilter.SMOOTH)
#导入Image类和ImageFilter类 from PIL import Image, ImageFilter im = Image.open("C:/Users/Administrator/Desktop/国宝.jpg") #平滑图smooth im5 = im.filter(ImageFilter.SMOOTH) im5.show() im5.save("C:/Users/Administrator/Desktop/平滑图.png")
输出图像如下:
图6:平滑图(注意这里处理后的图像格式发生了变化)
如果您使用过 PhotoShop(简称 Ps,一款专业的图像处理软件)、Fireworks(简称 Fw,一款专业的图像处理软件) 或者手机美图软件的话,其实不难发现,上述操作就是给图片添加一个“滤镜”,通过添加滤镜来改变图片的外观,从而影响了我们对于图片的感官体验。
十一、Pillow图像颜色处理
Pillow 提供了颜色处理模块 ImageColor,该模块支持不同格式的颜色,比如 RGB 格式的颜色三元组、十六进制的颜色名称(#ff0000)以及颜色英文单词(”red”)。同时,它还可以将 CSS(层叠样式表,用来修饰网页)风格的颜色转换为 RGB 格式。
注意,在 ImageColor 模块对颜色的大小并不敏感,比如 “Red” 也可以写为 ” red”。
颜色命名(ImageColor )
ImageColor 支持多种颜色模式的的命名(即使用固定的格式对颜值进行表示),比如我们熟知的 RGB 色彩模式,除此之外,还有 HSL (色调-饱和度-明度)、HSB (又称 HSV,色调-饱和度-亮度)色彩模式。下面对 HSL 做简单介绍:
- H:即 Hue 色调,取值范围 0 -360,其中 0 表示“red”,120 表示 “green”,240 表示“blue”;
- S:即 Saturation 饱和度,代表色彩的纯度,取值 0~100%,其中 0 代表灰色(gry),100% 表示色光最饱和;
- L:即 Lightness 明度,取值为 0~100%,其中 0 表示“black”黑色,50% 表示正常颜色,100% 则表示白色。
下面使用 HSL 色彩模式表示红色,格式如下:
HSL(0,100%,50%)
此时的颜色为“纯红色”,等同于 RGB (255,0,0)。如果想了解有关 HSL/HSB 的更多知识,点击链接前往。
ImageColor 模块比较简单,只提供了两个常用方法,分别是 getrgb() 和 getcolor() 函数。
1、getrgb()方法
顾名思义,该函数用来得到颜色的 RGB 值,语法格式如下:
PIL.ImageColor.getrgb(color)
使用示例如下:
from PIL import Image, ImageColor #getrgb color1 = ImageColor.getrgb("blue") print(color1) color2 = ImageColor.getrgb("#DCDCDC") print(color2) #使用HSL模式红色 color3 = ImageColor.getrgb('HSL(0, 100%, 50%)') print(color3)
输出结果如下:
(0, 0, 255) (220, 220, 220) (255, 0, 0)
通过 new() 方法可以新建图像,此时也可以使用 ImageColor.getrgb(),如下所示:
#使用new()绘制新的图像 im = Image.new("RGB", (200, 300), ImageColor.getrgb("#EEB4B4")) im5.save("C:/Users/Administrator/Desktop/xin.jpg")
显示图片如下
图1:新建图像
2、getcolor()
该方法与 getrgb() 类似,同样用来获取颜色值,不过它多了一个mode参数,因此该函数可以获取指定色彩模式的颜色值。语法格式如下:
PIL.ImageColor.getcolor(color, mode)
参数说明如下:
- color:一个颜色名称,字符串格式,可以是颜色的英文单词,或者十六进制颜色名。如果是不支持的颜色,会报 ValueError 错误;
- mode:指定色彩模式,如果是不支持的模式,会报 KeyError 错误。
使用示例如下:
color4 = ImageColor.getcolor('#EEA9B8', 'L') print(color4) color5 = ImageColor.getcolor('yellow', 'RGBA') print(color5)
输出结果:
191 (255, 255, 0, 255)
十二、Pillow为图片添加水印
- 第一、如何使文字信息附着在图片上;
- 第二、如何绘制文字信息。
只要解决了这两个问题就可以成功添加水印。Pillow 提供的ImageDraw和ImageFont模块成功解决了上述问题。
1、ImageDraw
draw = ImageDraw.Draw(im)
上述方法会返回一个 ImageDraw 对象,参数 im 表示 Image 对象。这里我们可以把 Image 对象理解成画布,通过调用 ImageDraw 对象的一些方法,实现了在画布上绘制出新的图形目的。ImageDraw 对象的常用方法如下表所示:
| 方法 | 说明 |
|---|---|
| text | 在图像上绘制文字 |
| line | 绘制直线、线段 |
| eclipse | 绘制椭圆形 |
| rectangle | 绘制矩形 |
| polygon | 绘制多边形 |
表格中第一个方法 text() 需要与 ImageFont 模块一起使用,在下面会做详细介绍。
绘制矩形图的语法格式如下:
draw.rectangle(xy, fill = None, outline = None)
参数说明如下:
- xy:元组参数值,以图像的左上角为坐标原点,表示矩形图的位置、图形大小的坐标序列,形如 ((x1,y1,x2,y2));
- fill:矩形图的背景填充色;
- outline:矩形图的边框线条颜色。
下面看一组简单的示例:
from PIL import Image, ImageDraw #创建Image对象,当做背景图 im = Image.new('RGB', (200, 200), color = 'gray') #创建ImageDraw对象 draw = ImageDraw.Draw(im) 以左上角为原点,绘制矩形。 #元组坐标序列表示矩形的位置、大小;fill设置填充色为红色,outline设置边框线为黑色 draw.rectangle((50, 100, 100, 150), fill = (255, 0, 0), outline = (0, 0, 0)) #查看原图片 im.show() #保存图片 im.save("C:/Users/Administrator/Desktop/添加矩形图.png")
图形显示结果如下:
图1:绘制红色矩形
2、ImageFont
PIL.ImagreFont 模块通过加载不同格式的字体文件,从而在图像上绘制出不同类型的文字,比如 TrueType 和 OpenType 类型的字体。
创建字体对象的语法格式如下:
font = ImageFont.truetype(font = '字体文件路径', size = 字体大小)
如果想要在图片上添加文本,还需要使用 ImageDraw.text() 方法,语法格式如下:
d.text((x,y), "text", font, fill)
参数说明如下:
- (x,y):图像左上角为坐标原点,(x,y) 表示添加文本的起始坐标位置;
- text:字符串格式,要添加的文本内容;
- font:ImageFont 对象;
- fill:文本填充颜色。
下面看一组使用示例,如下所示:
from PIL import Image, ImageFont, ImageDraw #打开图片,返回Image对象 im = Image.open("C:/Users/Administrator/Desktop/c-net.png") #创建画布对象 draw = ImageDraw.Draw(im) #加载计算机本地字体文件 font = ImageFont.truetype(font = 'C:/Windows/Fonts/msyh.ttc', size = 36) #在原图像上添加文本 draw.text(xy = (80,50), text = 'C语言中文网', fill = (255, 0, 0), font = font) im.show() im.save("C:/Users/Administrator/Desktop/c.png")
图像显示结果如下:
图2:添加文本
3、添加图片水印
通过上述知识的学习,我们对ImageDraw和ImageFont模块有了大体的认识,并且也解决了如何给图片添加水印的两个关键问题。以下示例展示了为图片添加水印的详细过程,代码如下所示:
""" 添加水印(函数式编程) """ from PIL import Image, ImageFont, ImageDraw #加载计算机本地字体文件 font = ImageFont.truetype(font = 'C:/Windows/Fonts/msyh.ttc', size = 30) def creating_watermark(im, text, font = font): #给水印添加透明度,因此需要转换图片的格式 im_rgba = im.convert('RGBA') im_text_canvas = Image.new('RGBA', im_rgba.size, (255, 255, 255, 0)) print(im_rgba.size[0]) #创建画布对象 draw = ImageDraw.Draw(im_text_canvas) #设置文本文字大小 text_x_width, text_y_height = draw.textsize(text, font = font) print(text_x_width, text_y_height) text_xy = (im_rgba.size[0] - text_x_width, im_rgba.size[1] - text_y_height) print(text_xy) #设置文本颜色(绿色)和透明度(半透明) draw.text(text_xy, text, fill = (255, 255, 255, 128), font = font) #将原图片与文字复合 im_text = Image.alpha_composite(im_rgba, im_text_canvas) return im_text image = Image.open("C:/Users/Administrator/Desktop/c-net.png") im.show() image_water = creating_watermark(image, '@c语言中文网') image_water.show() image_water.save("C:/Users/Administrator/Desktop/c语言中文网.png")
添加水印后的效果图:
图3:添加水印后效果
十三、Pillow和ndarray数组
1、ndarray数组创建图像
下面通过 ndarray 数组构建一个 Image 对象,并将图像显示出来。示例如下:
#导入相关的包 from PIL import Image #使用numpy之前需要提前安装 import numpy as np #创建 300*400 的图像,3个颜色通道 array = np.zeros([300, 400, 3], dtype = np.unit8) #rgb色彩模式 array[:, :200] = [255, 0 , 0] array[:, 200:] = [255, 255 , 0] img = Image.fromarray(array) img.show() img.save("C:/Users/Administrator/Desktop/数组生成图像.png")
输出结果如下所示:
图1:NumPy数组创建图像
2、图像转化为ndarray数组
下面将图像以 ndarray 数组的形式进行输出,示例如下:
from PIL import Image import numpy as np img = Image.open("C:/Users/Administrator/Desktop/大熊猫.png") img.show() #Image图像转换为ndarray数组 img_2 = np.array(img) print(img_2) #ndarray数组转换为Image图像 arr_img = Image.fromarray(img_2) #显示图片 arr_img.show() #保存图片 arr_img.save("C:/Users/Administrator/Desktop/arr_img.png")
图片展示结果:
图2:显示原图
组成图片的像素点数组如下所示:
[[[113 108 105] [118 113 110] [139 131 128] ... [139 148 155] [137 146 153] [139 148 155]] [[ 97 92 89] [124 118 115] [137 129 126] ... [143 152 159] [140 149 156] [140 149 156]] [[102 97 94] [123 118 115] [135 128 125] ... [144 153 160] [142 151 158] [143 152 159]] ... [[168 175 134] [175 183 142] [151 162 120] ... [ 99 143 66] [111 155 77] [131 175 98]] [[152 164 118] [147 160 114] [140 156 109] ... [123 167 87] [126 171 90] [120 165 84]] [[136 154 104] [127 145 95] [156 176 125] ... [168 213 130] [142 187 104] [ 69 114 31]]]
十四、Pillow生成GIF动态图
GIF(Graphics Interchange Format,图形交换格式)是一种“位图”图像格式,它以.gif作为图像的扩展名。GIF 图片非常适合在互联网中使用,这是因为它采用了图像预压缩技术,该技术的应用,在一定程度上减少了图像传播、加载所消耗的时间。
与其他格式的图片相比,GIF 还有一项非常重要的应用,那就是生成动态图。我们知道,Pillow 能够处理多种图像格式,包括 GIF 格式,它可以将静态格式图片(png、jpg)合成为 GIF 动态图。
注意:Pillow 总是以灰度模式(L)或调色板模式(P)来读取 GIF 文件。
下面看一组示例:如何使用 Pillow 生成 GiF 动态图。(示例中所用图片素材,点击链接下载,提取码:n1v2)
import os import random from PIL import Image def png_to_gif(png_path, gif_name): #"""png合成gif图像""" frames = [] #返回文件内的所有静态图的列表 png_files = os.listdir(png_path) #打印返回的列表 print(png_files) #读取文件内的静态图 for frame_id in range(1, len(png_files) + 1): frame = Image.open(os.path.join(png_path, 'image%d.png'%frame_id)) frames.append(frame) # 以第一张图片作为开始,将后续5张图片合并成 gif 动态图 # 参数说明: # save_all 保存图像;transparency 设置透明背景色;duration 单位毫秒,动画持续时间, # loop=0 无限循环;disposal=2 恢复原背景颜色。参数详细说明,请参阅官方文档,网址见文章末尾处。 frames[0].save(gif_name, save_all = True, append_images = frames[1:], transparency = 0, duration = 2000, loop = 0, disposal = 2) #调用函数,传入对应的参数 png_to_gif("C:/Users/Administrator/Desktop/image", 'C:/Users/Administrator/Desktop/t.gif', )
动态效果图,如下所示:
想要了解关于 Pillow 的更多的知识,请参考官方文档:点击前往
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/109685.html
































