Python图像处理入门
图像处理,顾名思义,可以简单地定义为利用计算机算法(通过代码)对图像进行分析、操作的处理。它包括如下不同的几个方面:图像的存储、表示、信息提取、操作、增强、恢复和解释。本章将对图像处理技术的各个方面进行基本介绍,并介绍使用Python库进行图像处理实践编程。本书中的所有示例代码都基于Python 3编写。
本章首先定义什么是图像处理以及图像处理的应用是什么;其次介绍图像处理的基本流程,即在计算机上处理图像的一般步骤;再次介绍用于图像处理的不同Python库及如何在Python 3下安装它们;接下来介绍如何使用不同的库编写Python代码读写(存储)图像;之后介绍基于Python表示图像的数据结构以及如何显示图像;最后介绍不同的图像类型和不同的图像文件格式以及如何由Python执行基本的图像操作。
在本章的最后,要求读者能够概念化图像处理、图像处理步骤和图像处理应用;要求掌握能够从不同的Python图像处理库导入和调用函数;要求能够理解Python中存储不同图像类型的数据结构,使用不同的Python库读写图像文件,以及利用Python库编写Python代码来执行基本图像操作。
本章主要包括以下内容:
什么是图像处理及图像处理的应用;
图像处理流程;
在Python中安装不同的图像处理库;
使用Python进行图像输入/输出和显示;
处理不同的图像类型、文件格式并执行基本的图像操作。
1.1 什么是图像处理及图像处理的应用
什么是图像?它是如何存储在计算机里的?用Python编程如何处理?
1.1.1 什么是图像以及图像是如何存储的
从概念上讲,形式最简单的图像(单通道,例如二值或单色,灰度或黑白图像)是一个二维函数f(x,y),即将坐标点映射到表示亮度/颜色相关的整数/实数。点称为像素或图像基本单位(图像元素)。一幅图像可以有多个通道(例如,对于彩色RGB图像,可以使用颜色表示三通道——红、绿、蓝)。彩色RGB图像的像素点(x,y)可以表示为三元组(rx,y, gx,y, bx,y)。
为了能够在计算机上描述图像,对于图像f(x,y),必须在空间和振幅两方面进行数字化。空间坐标(x,y)的数字化称为图像抽样,振幅数字化称为灰度量化。在计算机中,通常将像素通道所对应的值表示为整数(0~255)或浮点数(0~1)。可以将图像存储为不同类型(格式)的文件。每个文件通常包括元数据和多维数组的数据(例如,二值或灰度图像的二维数组,RGB和YUV彩色图像的三维数组)。图1-1描述了如何将图像数据存储为不同类型图像的数组,正如图中所示,对于灰度图像,用“宽度×高度”(二维数组)的模式足以存储,而对于RGB图像,则需要用“宽度×高度×3”(三维数组)的模式存储。
图1-1 图像的存储
二值、灰度和RGB图像如图1-2所示。
图1-2 二值、灰度和RGB图像
本书重点讨论图像数据的处理,用Python库实现从图像中提取数据,并运用算法进行图像处理。样本图像均取自互联网——伯克利图像分割数据集、基准数据集,以及USC-SIPI图像数据库,其中大多都是用于图像处理的标准图像。
1.1.2 什么是图像处理
图像处理是指在计算机上使用算法和代码自动处理、操作、分析和解释图像,它广泛应用于诸多学科和领域,如电视、摄影、机器人、遥感、医学诊断和工业检验。像大众所熟知的Facebook和Instagram社交网站,面临用户每天都会上传大量图片的情况,它们是行业的典型案例,需要使用图像处理算法或对图像处理算法进行创新来处理上传的图片。
在本书中,我们用Python包来处理图像:首先,用一组库来做经典的图像处理——提取图像数据,用库函数的算法将数据转换为预处理、增强、复原、表示(用描述符)、分割、分类、检测和识别(对象),从而更好地分析、理解和解释数据;其次,我们用另一组库进行基于深度学习的图像处理——这种技术近年来变得非常热门。
1.1.3 图像处理的应用
图像处理的典型应用包括医学/生物领域(如X射线和CT扫描)、计算摄影(Photoshop)、指纹认证、人脸识别等。
1.2 图像处理流程
图像处理流程的基本步骤如下。
(1)图像的获取与存储。获取图像(如使用相机获取),并以文件的形式(如JPEG文件)存储在某些设备(如硬盘)上。
(2)加载至内存并存盘。从磁盘读取图像数据至内存,使用某种数据结构(如numpy ndarray)作为存储结构,之后将数据结构序列化到一个图像文件中,也可能是对图像上运行了算法之后。
(3)操作、增强和复原。需运行预处理算法完成如下任务。
① 图像转换(采样和操作,如灰度转换);
② 图像质量增强(滤波,如图像由模糊变清晰);
③ 图像降噪,图像复原。
(4)图像分割。为了提取感兴趣的对象,需要对图像进行分割。
(5)信息提取/表示。图像需以其他形式表示,如表示为以下几项。
① 一些可从图像中计算出来的手工标识的特征描述符(如HOG描述符、经典图像处理)。
② 一些可自动从图像中学习的功能(例如,在深度学习神经网络的隐藏层中学到权重和偏差值)。
③ 以另一种表示方法表示图像。
(6)图像理解/图像解释。以下表示形式可用于更好地理解图像。
① 图像分类(例如,图像是否包含人类对象)。
② 对象识别(例如,在带有边框的图像中查找car对象的位置)。
图像处理流程如图1-3所示。
图1-3 图像处理流程
用于各种图像处理任务的不同模块如 图1-4所示。除此之外,还会用到以下图像处理模块:
(1)scipy.ndimage和opencv用于不同图像处理;
(2)scikit-learn用于经典的机器学习;
(3)tensorflow和keras用于深度学习。
图1-4 用于图像处理任务的不同模块
1.3 在Python中安装不同的图像处理库
后续将介绍如何安装不同的图像处理库,并为用Python经典图像处理技术进行图像处理编程设置环境。在本书的最后一些章节使用基于深度学习的方法时,需要使用不同的设置。
1.3.1 安装pip
用pip(或pip3)工具安装图像处理库。因此,如果还没安装它,先安装pip。如果使用从python.org下载的Python 3 >=3.4,或者已工作在由virtualenv或pyvenv创建的虚拟环境中,则说明pip已经安装好了,只需要确保pip升级即可。
1.3.2 在Python中安装图像处理库
Python有许多库可用于图像处理,如numpy、scipy、scikit-image、PIL(Pillow)、OpenCV、scikit-learn、SimpleITK和matplotlib。
matplotlib库主要用于图像显示,而numpy主要用于图像存储,scikit-learn库构建用于图像处理的机器学习模型,scipy主要用于图像增强,scikit-image、mahotas和opencv库用于不同的图像处理算法。
以下代码展示了通过Python提示符(交互模式),如何下载安装所需的库:
>>> pip install numpy>>> pip install scipy>>> pip install scikit-image>>> pip install scikit-learn>>> pip install pillow>>> pip install SimpleITK>>> pip install opencv-python>>> pip install matplotlib
如果操作系统平台不同,可能还会用到一些附加的安装说明。读者应该浏览文档站点来获取每个库在特定平台详细安装库的说明。此外,读者应该熟悉stack overflow等网站,以解决不同平台依赖安装库的问题。
最后,可以通过Python提示符导入库来验证库是否安装正确。如果库成功导入(没有抛出错误消息),那么安装没有问题。可以将安装的库的版本打印到控制台。
scikit-image和PIL Python库的版本如下面的代码所示:
>>> import skimage, PIL, numpy>>> print(skimage.__version__)# 0.14.0>>> PIL.__version__# 5.1.0>>> numpy.__version__# 1.14.5
要确保所有库为最新版本。
1.3.3 安装Anaconda发行版
请下载并安装最新版本的Anaconda发行版,以免去直接安装众多的Python包的麻烦。
1.3.4 安装Jupyter笔记本
如果用Jupyter笔记本来编写Python代码,需要先通过python提示符安装jupyter包,即首先使用>>>pip install jupyter,然后使用>>>jupyter notebook,在浏览器中启动Jupyter Notebook应用程序。在应用程序中就可以创建新的Python笔记本并选择内核了。如果使用的是Anaconda,就不需要显式安装Jupyter,因为最新的Anaconda发行版本附带了Jupyter。
1.4 使用Python进行图像输入/输出和显示
由于图像是作为文件存储在磁盘上的,因此从文件中读取和写入图像是磁盘输入/输出操作。可以通过多种方式使用不同的库完成这些任务,本节给出了其中一些方式。从导入所有必需的包开始,代码如下。
# for inline image display inside notebook# % matplotlib inlineimport numpy as npfrom PIL import Image, ImageFont, ImageDrawfrom PIL.ImageChops import add, subtract, multiply, difference, screenimport PIL.ImageStat as statfrom skimage.io import imread, imsave, imshow, show, imread_collection,imshow_collectionfrom skimage import color, viewer, exposure, img_as_float, datafrom skimage.transform import SimilarityTransform, warp, swirlfrom skimage.util import invert, random_noise, montageimport matplotlib.image as mpimgimport matplotlib.pylab as pltfrom scipy.ndimage import affine_transform, zoomfrom scipy import misc
1.4.1 使用PIL读取、保存和显示图像
PIL的open() 函数用于从Image对象的磁盘读取图像,如下面的代码所示。图像作为PIL.PngImagePlugin.PngImageFile类的对象加载,读者可以用宽度、高度和模式等属性来查找图像的大小[宽度×高度(像素)或分辨率]和模式。
im = Image.open('../images/parrot.png') # read the image, provide the correct pathprint(im.width, im.height, im.mode, im.format, type(im))# 453 340 RGB PNG <class 'PIL.PngImagePlugin.PngImageFile'>im.show() # display the image
运行上述代码,输出结果如图1-5所示,从文件中读取图像,然后再将图像显示在屏幕上。
图1-5 读取的鹦鹉图像
用PIL函数convert()将彩色RGB图像转换为灰度图像,代码如下:
im_g = im.convert('L') # convert the RGB color image to a grayscale imageim_g.save('../images/parrot_gray.png') # save the image to diskImage.open('../images/parrot_gray.png').show() # read the grayscale image from disk and show
运行上述代码,结果如图1-6所示,输出的是鹦鹉的灰度图像。
图1-6 输出鹦鹉的灰度图像
提供磁盘上图像的正确路径
建议创建一个文件夹(子目录)来存储要处理的图像(例如,对于Python代码示例,建议读者使用名为images的文件夹来存储图像),然后提供文件夹的路径以访问图像,以免出现“找不到文件”的异常。
1.4.2 使用matplotlib读取、保存和显示图像
接下来演示如何使用matplotlib.image中的imread()函数来读取浮点numpy ndarray中的图像,其中,像素值表示为介于0和1之间的真值。代码如下:
im = mpimg.imread('../images/hill.png') # read the image from disk as anumpy ndarrayprint(im.shape, im.dtype, type(im)) # this image contains anαchannel, hence num_channels= 4# (960, 1280, 4) float32 <class 'numpy.ndarray'>plt.figure(figsize=(10,10))plt.imshow(im) # display the imageplt.axis('off')plt.show()
运行上述代码,输出结果如图1-7所示。
图1-7 用imread()函数读取的山峰图像
接下来展示如何将图像更改为较暗的图像。首先将所有像素值设置为0~0.5之间的数,然后将numpy ndarray保存到磁盘。保存的图像将重新加载并显示。代码如下:
im1 = imim1[im1 < 0.5] = 0 # make the image look darkerplt.imshow(im1)plt.axis('off')plt.tight_layout()plt.savefig('../images/hill_dark.png') # save the dark imageim = mpimg.imread('../images/hill_dark.png') # read the dark imageplt.figure(figsize=(10,10))plt.imshow(im)plt.axis('off') # no axis ticksplt.tight_layout()plt.show()
运行上述代码,输出结果为较暗的山峰图像,如图1-8所示。
图1-8 较暗的山峰图像
使用matplotlib imshow()在显示时插值
matplotlib中的imshow()函数提供了多种不同类型的插值方法用以对图像进行绘制。当被绘制的图像很小时,这些方法特别有用。通过图1-9所示的尺寸为50×50的Lena图像来查看用不同插值方法绘制图像的效果。
图1-9 Lena图像
如下代码演示了如何通过imshow()使用不同的插值方法:
im = mpimg.imread('../images/lena_small.jpg') # read the image from disk asa numpy ndarraymethods = ['none', 'nearest', 'bilinear', 'bicubic', 'spline16', 'lanczos']fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(15, 30),subplot_kw={'xticks': [], 'yticks': []})fig.subplots_adjust(hspace=0.05, wspace=0.05)for ax, interp_method in zip(axes.flat, methods):ax.imshow(im, interpolation=interp_method)ax.set_title(str(interp_method), size=20)plt.tight_layout()plt.show()
运行上述代码,输出结果如图1-10所示。
图1-10 使用不同插值方法对Lena图像进行处理的效果
1.4.3 使用scikit-image读取、保存和显示图像
以下代码演示了如何用scikit-image中的imread()函数读取numpy ndarray中的图像。图像类型为uint8(8位无符号整数),因此图像像素值是介于0和255之间的数。然后,用hsv2rgb()函数从Image.color模块将彩色RGB图像转换为HSV图像(更改图像类型或模式,本书稍后讨论)。接下来,将所有像素点的饱和度(色彩)更改为常量值,但色调和值通道保持不变。这样,图像就被rgb2hsv()函数转换回了RGB模式,以创建新图像,并保存和显示图像。
im = imread('../images/parrot.png') # read image from disk, provide thecorrect pathprint(im.shape, im.dtype, type(im))# (362, 486, 3) uint8 <class 'numpy.ndarray'>hsv = color.rgb2hsv(im) # from RGB to HSV color spacehsv[:, :, 1] = 0.5 # change the saturationim1 = color.hsv2rgb(hsv) # from HSV back to RGBimsave('../images/parrot_hsv.png', im1) # save image to diskim = imread('../images/parrot_hsv.png')plt.axis('off'), imshow(im), show()
运行上述代码,输出结果如图1-11所示,这是一张饱和度发生变化的鹦鹉新图像。
图1-11 饱和度发生了变化的鹦鹉新图像
还可以用scikit-image的viewer模块在弹出窗口中显示图像,代码如下:
viewer = viewer.ImageViewer(im)viewer.show()
使用scikit-image的astronaut数据集
以下代码显示了如何使用data模块从scikit-image库的图像数据集中加载(宇航员astronaut)图像。该模块包含一些其他流行的数据集,如cameraman数据集,可以用类似的方法加载。
im = data.astronaut()imshow(im), show()
运行上述代码,输出结果如图1-12所示。
图1-12 使用data模块加载宇航员图像
一次性同时读取和显示多个图像
可以用scikit-image的io模块中的imread_collection()函数将文件名中具有特定模式的所有图像加载到一个文件夹中,并用imshow_collection()函数同时显示它们。具体代码实现留给读者作为练习。
1.4.4 使用SciPy的misc模块读取、保存和显示图像
SciPy的misc模块也可用于图像的输入/输出和显示。下面将演示如何使用misc模块的函数。
使用misc的face数据集
以下代码展示了如何显示misc模块的face数据集:
im = misc.face() # load the raccoon's face imagemisc.imsave('face.png', im) # uses the Image module (PIL)plt.imshow(im), plt.axis('off'), plt.show()
运行上述代码,输出结果如图1-13所示,即显示了misc模块的face图像。
图1-13 浣熊脸部图像
读者可以使用misc.imread()从磁盘读取图像,代码如下:
im = misc.imread('../images/pepper.jpg')print(type(im), im.shape, im.dtype)# <class 'numpy.ndarray'> (225, 225, 3) uint8
由于I/O函数的imread()在SciPy 1.0.0中已被弃用,在1.2.0中也即将删除,因此文档建议使用imageio库代替。代码展示了如何使用imageio.imread()函数读取图像,以及如何使用matplotlib显示图像。
import imageioim = imageio.imread('../images/pepper.jpg')print(type(im), im.shape, im.dtype)# <class 'imageio.core.util.Image'> (225, 225, 3)uint8plt.imshow(im), plt.axis('off'), plt.show()
运行上述代码,输出结果如图1-14所示。
图1-14 读取与显示的辣椒图像
1.5 处理不同的文件格式和图像类型并执行基本的图像操作(略)
1.6 小结
本章首先介绍了图像处理的入门知识,以及图像处理中欲解决问题的相关基本概念;接着讨论了图像处理的不同任务要求和流程,以及Python中的主要图像处理库,书中将使用这些库进行代码编写;接下来说明了如何在Python中安装不同的图像处理库,以及如何导入它们并从模块中调用函数;还介绍了有关图像类型、文件格式和数据结构的基本概念,以使用不同的Python库存储图像数据;讨论了在Python中如何使用不同的库进行图像输入/输出和显示;最后讨论了如何使用不同的Python库执行基本的图像操作。在第2章中,我们将深入研究图像的采样、量化、卷积、傅里叶变换和频域滤波。
本文摘自《Python图像处理实战》
图像处理,计算机视觉人脸识别图像修复
编程入门教程书籍零基础
深度学习爬虫,用流行的Python图像处理库、机器学习库和深度学习库解决图像处理问题
本书介绍如何用流行的Python 图像处理库、机器学习库和深度学习库解决图像处理问题。先介绍经典的图像处理技术,然后探索图像处理算法的演变历程,始终紧扣图像处理以及计算机视觉与深度学习方面的**进展。全书共12 章,涵盖图像处理入门基础知识、应用导数方法实现图像增强、形态学图像处理、图像特征提取与描述符、图像分割,以及图像处理中的经典机器学习方法等内容。
本书适合Python 工程师和相关研究人员阅读,也适合对计算机视觉、图像处理、机器学习和深度学习感兴趣的软件工程师参考。