查看原文
其他

【干货】计算机视觉实战系列01——用Python做图像处理

2018-03-07 专知内容组 专知

【导读】在当今互联网飞速发展的社会中,数量庞大的图像和视频充斥着我们的生活,让我们需要对图片进行检索、分类等操作时,利用人工手段显然是不现实的,于是,计算机视觉相关技术便应运而生,并且得到了快速的发展。专知成员hui计划推出一系列计算机视觉入门实战讲解,以时下最流行的Python语言为工具,对图像处理技术的具体操作进行详细讲述,旨在让零基础的读者也可以轻松上手!

 


基本的图像操作和处理

 

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)

结果为下图所示:

 


参考文献:

python计算机视觉编程:http://yongyuan.name/pcvwithpython/

-END-

专 · 知

人工智能领域主题知识资料查看获取【专知荟萃】人工智能领域26个主题知识资料全集(入门/进阶/论文/综述/视频/专家等)

请PC登录www.zhuanzhi.ai或者点击阅读原文,注册登录专知,获取更多AI知识资料

请扫一扫如下二维码关注我们的公众号,获取人工智能的专业知识!

请加专知小助手微信(Rancho_Fang),加入专知主题人工智能群交流!

点击“阅读原文”,使用专知

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存