Python中有好多工具包应用于图像处理当中,这一节(基本的图像操作和处理)作为入门章节,首先来介绍Python中最基本的几个工具包,也希望读者可以在之后自行练习。
▌PIL:Python图像处理类库
PIL(Python Imaging Library)为图像处理类库,它为Python提供了基本的图像处理功能和基本操作。PIL中最重要的模块又是Image,下面,我们就来讲一讲Image模块的一些用法。
▌读取一幅图像:
我们用Image模块中的open()方法实现
首先强调一点就是对于PNG、BMP和JPG等不同格式的彩色图像之间的互相转换都可以通过Image模块来完成,具体来说,在打开这些图像时,PIL会将它们解码为三通道的“RGB”图像。用户可以基于这个“RGB”图像,对其进行处理。
from PIL import Image #从PIL包中导入Image模块
image = Image.open('test.jpg') #读取名为test的图片
这是test.jpg图片
通过上述代码,我们的返回值image就是一个PIL对象,当我们需要对一幅图像进行各种操作时,首先都要通过上述代码读取目标图像。
上述代码的运行结果实际上为:
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=1000x1436 at 0x1826BF51D68>
怎样才能将它变为可视化的图像呢?
我们需要调用matplotlib.pyplot函数集合的 imshow() 和show()方法,完整代码为:
from PIL import Image
import matplotlib.pyplot as plt
image = Image.open('test.jpg')
plt.imshow(image)
plt.show()# 需要调用show()方法,不然图像只会在内存中而不显示出来
结果如下图所示:
▌将图像转换为灰度图像
我们使用convert()方法来实现图像的灰度转化
Convert()函数会根据传入参数的不同将图片变成不同的模式,通过相关资料我们知道PIL中有九种不同模式。分别为1,L,P,RGB,RGBA,CMYK,YCbCr,I,F。
模式“1”为二值图像,非黑即白。但是它每个像素用8个bit表示,0表示黑,255表示白。
模式L”为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。在PIL中,从模式“RGB”转换为“L”模式是按照下面的公式转换的:
L = R * 299/1000 + G * 587/1000+ B * 114/1000
模式“P”为8位彩色图像,它的每个像素用8个bit表示,其对应的彩色值是按照调色板查询出来的。
模式“RGBA”为32位彩色图像,它的每个像素用32个bit表示,其中24bit表示红色、绿色和蓝色三个通道,另外8bit表示alpha通道,即透明通道。
模式“CMYK”为32位彩色图像,它的每个像素用32个bit表示。模式“CMYK”就是印刷四分色模式,它是彩色印刷时采用的一种套色模式,利用色料的三原色混色原理,加上黑色油墨,共计四种颜色混合叠加,形成所谓“全彩印刷”。
模式“YCbCr”为24位彩色图像,它的每个像素用24个bit表示。YCbCr其中Y是指亮度分量,Cb指蓝色色度分量,而Cr指红色色度分量。人的肉眼对视频的Y分量更敏感,因此在通过对色度分量进行子采样来减少色度分量后,肉眼将察觉不到的图像质量的变化。
模式“RGB”转换为“YCbCr”的公式如下:
Y= 0.257*R+0.504*G+0.098*B+16
Cb = -0.148*R-0.291*G+0.439*B+128
Cr = 0.439*R-0.368*G-0.071*B+128
模式“I”为32位整型灰色图像,它的每个像素用32个bit表示,0表示黑,255表示白,(0,255)之间的数字表示不同的灰度。在PIL中,从模式“RGB”转换为“I”模式是按照下面的公式转换的:
I = R * 299/1000 + G * 587/1000 + B * 114/1000
模式“F”为32位浮点灰色图像,它的每个像素用32个bit表示,0表示黑,255表示白,(0,255)之间的数字表示不同的灰度。在PIL中,从模式“RGB”转换为“F”模式是按照下面的公式转换的:
F = R * 299/1000+ G * 587/1000 + B * 114/1000
我们以灰度图像为例,将目标图像转换成灰度图像,由上可知,我们要给convert()方法传入参数“L”,具体代码如下:
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.cm as cm
image = Image.open('test.jpg') # 读取名为test的图片
image_gray = image.convert("L") # 将图片转换为灰度图像
data = np.array(image_gray)
plt.imshow(data, cmap=cm.gray)
plt.show()
绘制出的灰度图像为:
我们也可以用一行代码
image = Image.open(‘test.jpg’).convert(“L”)
代替上面的两行注释代码。
在上述代码中我们引入了matplotlib.cm模块和numpy模块。
cm是colormap的缩写,这个模块提供了大量的colormaps,用于注册新的colormaps,并通过名称获得一个colormap,以及用于添加颜色映射功能的mixin类。
而在绘制灰度图像的imshow()方法给cmap传入了cm.gray参数。cmap:代表颜色图谱(colormap), 默认绘制为RGB(A)颜色空间。
为什么调取灰度图像加了这么一行代码呢?原因在于如果是彩色图像,上面的方法没有任何问题,但是如果是灰度图像,用上面的语句就不能正确显示,主要是没有加调色板。
除此之外,我们可以用一行代码plt.gray()来代替上述代码这样写会使代码看上去更加简洁。
NumPy是一个非常有名的 Python 科学计算工具包,其中包含了大量有用的工具,比如数组对象(用来表示向量、矩阵、图像等)以及线性代数函数。在显示灰度图像时array()方法将图像转换成NumPy的数组对象,图片得以显示,否则会出现AttributeError的错误。
▌转换图像的格式
通过save()方法,PIL可以将图像保存成多种格式的文件,当传入不同的扩展名时,它会根据扩展名自动转换图像的格式。
from PIL import Image
image = Image.open("smallpi.jpg") # 打开jpg图像文件
image.save("smallpi.png") # 保存图像,并转换成png格式
下面程序从文件名列表(filelist)中读取所有的图像文件,并转换成JPEG格式:
from PIL import Image
import os
for infile in filelist:
outfile = os.path.splitext(infile)[0] + “.jpg”
if infile != outfile:
try:
Image.open(infile).save(outfile)
except IOError:
print(‘cannot convert’, infile)
PIL的open()方法用于创建PIL图像对象,save()方法用于保存图像到具有指定文件名的文件,后缀变为“.jpg”,上述代码的新文件名和原文件名相同。PIL是个足够智能的类库,可以根据文件扩展名来判定图像格式PIL函数会进行简单的检查,如果文件名不是JPEG格式,会自动将其转为JPEG格式,如果转换失败,则会报错。
▌创建缩略图
使用PIL可以很方便地创建图像的缩略图,thumbnail()方法接受一个一元组参数,然后将图像转换成符合元组参数指定大小的缩略图。例如:
image.thumbnail((128,128))
thumbnail函数接受一个元组作为参数,分别对应着缩略图的宽高,在缩略时,函数会保持图片的宽高比例。如果输入的参数宽高和原图像宽高比不同,则会依据最小对应边进行原比例缩放。
比如:
一张图片为300*420大小的图片
当参数为(200,200)时,生成的缩略图大小为71*100,保持原图的宽高比
▌裁剪图像区域
使用PIL中的crop()方法可以从一幅图像中裁剪指定区域,该区域使用四元组来指定,四元组的坐标依次是(左,上,右,下)PIL中指定坐标系的左上角坐标为(0,0)。
具体代码为:
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
image = Image.open('test.jpg')
box = (500, 500, 1000, 1000)
region = image.crop(box)
data = np.array(region)
plt.imshow(data)
plt.show()
得到的结果为:
▌调整尺寸和旋转
要调整一幅图像的尺寸,我们可以调用resize()方法。该方法的参数是一个元组,用来指定新图像的大小:
out = image.resize((32,32))
结果为下图所示:
要旋转一幅图像,可以使用逆时针方式表示旋转角度,然后调用rotate()方法:
out = image.rotate(45)
结果为下图所示: