Python图像处理实战

978-7-115-52768-4
作者: [印度]桑迪潘·戴伊(Sandipan Dey)
译者: 陈盈邓军
编辑: 吴晋瑜
分类: Python

图书目录:

详情

本书介绍如何用流行的Python 图像处理库、机器学习库和深度学习库解决图像处理 问题。 本书先介绍经典的图像处理技术,然后探索图像处理算法的演变历程,始终紧扣图 像处理以及计算机视觉与深度学习方面的最新进展。全书共12 章,涵盖图像处理入门基础知识、应用导数方法实现图像增强、形态学图像处理、图像特征提取与描述符、图像分割,以及图像处理中的经典机器学习方法等内容。 本书适合Python 工程师和相关研究人员阅读,也适合对计算机视觉、图像处理、机 器学习和深度学习感兴趣的软件工程师参考。

图书摘要

版权信息

书名:Python图像处理实战

ISBN:978-7-115-52768-4

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。


著    [印]桑迪潘•戴伊(Sandipan Dey)

译    陈 盈 邓 军

责任编辑 吴晋瑜

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

读者服务热线:(010)81055410

反盗版热线:(010)81055315


Copyright ©Packt Publishing 2018. First published in the English language under the title “Hands-On Image Processing with Python” (9781789343731).

All rights reserved.

本书由英国Packt Publishing公司授权人民邮电出版社有限公司出版。未经出版者书面许可,对本书的任何部分不得以任何方式或任何手段复制和传播。

版权所有,侵权必究。


本书介绍如何用流行的Python图像处理库、机器学习库和深度学习库解决图像处理问题。

本书先介绍经典的图像处理技术,然后探索图像处理算法的演变历程,始终紧扣图像处理以及计算机视觉与深度学习方面的最新进展。全书共12章,涵盖图像处理入门基础知识、应用导数方法实现图像增强、形态学图像处理、图像特征提取与描述符、图像分割,以及图像处理中的经典机器学习方法等内容。

本书适合Python工程师和相关研究人员阅读,也适合对计算机视觉、图像处理、机器学习和深度学习感兴趣的软件工程师参考。

桑迪潘·戴伊(Sandipan Dey)是一位兴趣广泛的数据科学家,主要研究机器学习、深度学习、图像处理和计算机视觉,曾在推荐系统、行业动态预测模型、传感器定位模型、情感分析和设备预测等众多数据科学领域工作过。桑迪潘·戴伊拥有美国马里兰大学计算机科学硕士学位,在IEEE数据挖掘会议和期刊上发表了数篇学术论文,并在数据科学、机器学习、深度学习、图像处理及相关课程/专业等方面获得了100多个慕课(mooc)学习认证。他经常在博客空间(sandipanweb)撰写博客,是机器学习教育爱好者。

非常感谢全球顶尖商学院最近几年提供的优秀在线课程。这些课程包括图像处理(由美国杜克大学、美国西北大学提供),计算机视觉与图像分析(由微软提供),计算摄影(由美国佐治亚理工学院提供),机器学习(由美国斯坦福大学、加拿大多伦多大学和美国加利福尼亚大学圣迭戈分校提供),深度学习(由deeplearning.ai和谷歌在线提供)。

尼基尔·博卡(Nikhil Borkar)拥有国际数量金融工程师认证和定量金融硕士学位,并有金融犯罪审查和反洗钱认证资格。他还是印度证券交易委员会(SEBI)的注册研究分析员,对证券和投资有关的监管格局有着敏锐的把握。他曾是摩根士丹利资本国际(MSCI)的全球RFP项目经理,目前是独立人士身份的金融技术者和法律顾问。

陈盈,副教授,从事教育信息科学与技术工作,研究领域涉及自然语言处理、情感分析等。

邓军,工学博士,从事计算机教育工作,研究领域涉及质量工程、机械故障诊断、锂电池性能分析等。


本书介绍如何使用流行的Python图像处理库(如PIL、scikit-image、python-opencv、SciPy ndimage和SimpleITK)、机器学习库(scikit-learn)和深度学习库(TensorFlow、Keras)来解决图像处理问题。通过学习本书,读者能够通过编写程序代码来实现复杂的图像处理(如图像增强、滤波、复原、分割、分类和目标检测)算法,还能够使用机器学习和深度学习模型解决复杂的图像处理问题。

本书从基础开始,通过书中所提供的可复制的Python实现引导读者逐步进阶。本书从经典的图像处理技术开始,探索图像处理算法的演变历程,始终紧扣图像处理以及计算机视觉与深度学习方面的最新进展。读者将学习如何用Python的PIL、scikit-image和SciPy ndimage等图像处理库编写Python 3代码片段,以及如何快速实现复杂的图像处理算法。读者还将学习如何使用scikit-learn库和机器学习模型,并随后探索深度卷积神经网络(CNN),如TensorFlow/Keras VGG-19,用端到端深度学习YOLO模型进行目标检测,将DeepLab v3+用于语义分割和神经风格迁移模型等。读者还会学到一些高级图像处理技术,如梯度混合、变分去噪、接缝雕刻、图像绗缝和人脸变形,并将学习高效图像处理的各种实现算法。

本书秉持“高度实用”的宗旨,引导读者学习一系列图像处理的概念/算法,以帮助他们详细了解如何用高级的Python库函数实现这些算法。

本书适合工程师/应用研究人员阅读,也适合对计算机视觉、图像处理、机器学习和深度学习感兴趣的软件工程师作为参考,尤其适合擅长Python编程的读者学习——他们希望深入探索图像处理的各类主题(从概念到实施),解决一系列复杂问题。阅读本书前,读者应具备一定的数学和编程知识背景,还应掌握一些基础的机器学习知识。

第1章介绍什么是图像处理及图像处理的应用、图像处理流程、在Python中安装不同的图像处理库、使用Python进行图像输入/输出和显示、处理不同的文件格式和图像类型并执行基本的图像操作。

第2章介绍采样、傅里叶变换与卷积,以及用Python实现它们的例子。读者将学习理解后续内容所需掌握的简单信号处理工具。

第3章演示如何使用Python对图像进行卷积,还会讨论频域滤波等主题。

第4章介绍最基本的图像处理工具,如均值/中值滤波和直方图均衡化,它们仍然是最强大的图像处理工具。本章将对它们进行阐述,并对这些基本工具给出现代的诠释。

第5章涵盖与图像增强相关的其他主题,即改善图像外观或有用性的问题。讨论的主题包括图像导数、锐化和反锐化掩模,以及融合图像等。所有概念的描述均辅以Python示例。

第6章介绍形态学图像处理,涵盖基于scikit-image形态学模块、基于scikit-image filter.rank模块和基于SciPy ndimage.morphology模块的形态学图像处理的相关内容。

第7章描述从图像/计算图像描述符中进行特征提取的几种技术。

第8章概述图像分割的基本技术,霍夫变换、二值化和Otsu分割到更高级的图形切割算法。

第9章介绍一些图像处理中的经典机器学习方法,用于图像分割和目标检测/识别。

第10章描述图像处理/计算机视觉领域逐渐从经典的基于特征的机器学习模型过渡到深度学习模型的原因。

第11章描述卷积神经网络在目标检测、语义分割和神经风格迁移方面的一些显著应用,演示了一些流行的模型,如YOLO和目标提案(object proposal),概述如何使用迁移学习来避免从头开始学习一个非常深的神经网络。

第12章将给出许多其他的图像处理问题以及解决这些问题的各种算法。这些问题包括接缝雕刻(用于上下文感知图像大小的调整)、图像绗缝(用于非参数采样和纹理转移的图像调整)、使用泊松(梯度)图像编辑(混合)将一幅图像无缝地混合到另一幅图像中、图像修复(以复原退化的图像)以及变分图像处理(如图像去噪)。

1.运行书中代码所需的Python基本知识,以及访问图像数据集和GitHub链接的技能。

2.理解书中概念所需的基本的数学背景知识。

读者可以通过在异步社区图书详情页单击“配套资源”来下载本书的示例代码文件和彩色图像文件。下载代码文件后,请用以下最新版本的解压缩软件工具解 压缩:

CodeInText:指示文本中的代码字、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟URL、用户输入和Twitter句柄。下面是一个示例:“将下载的WebStorm-10*.dmg磁盘映像文件作为系统中的另一个磁盘挂载。”

代码块以如下样式显示:

viewer = viewer.ImageViewer(im)
viewer.show()

当希望读者注意代码块的某一部分时,相关的行或项会以粗体显示:

[default]
exten => s,1,Dial(Zap/1|30)
exten => s,2,Voicemail(u100)
exten => s,102,Voicemail(b100)
exten => i,1,Voicemail(s0)

任何命令行输入或输出如下所示:

>>> pip install numpy
>>> pip install scipy

粗体:表示读者看到的新术语、重要的单词。例如,菜单或对话框中的单词会出现在文本中,例如“从管理面板中选择系统信息”。


图像处理,顾名思义,可以简单地定义为利用计算机算法(通过代码)对图像进行分析、操作的处理技术。它包括如下不同的几个方面:图像的存储、表示、提取、操作、增强、复原和解释。本章将对图像处理技术的各个方面进行基本介绍,并介绍使用Python库进行图像处理实践编程。本书中的所有示例代码都基于Python 3编写。

本章首先介绍图像处理的概念,并介绍图像处理的应用;其次介绍图像处理的基本流程,即在计算机上处理图像的一般步骤;再次介绍用于图像处理的不同Python库及如何在Python 3下安装它们;接下来介绍如何使用不同的库编写Python代码读/写(存储)图像;之后介绍Python中用于表示图像的数据结构以及如何显示图像;最后介绍不同的图像类型和图像文件格式,以及如何用Python执行基本的图像操作。

学习本章后,读者应该能够了解图像处理的概念、图像处理的步骤和图像处理的应用;能够从不同的Python图像处理库导入和调用函数;能够了解Python中存储不同图像类型的数据结构,能够用不同的Python库读/写图像文件,并能利用Python库编写Python代码来执行基本图像操作。

本章主要包括以下内容:

什么是图像?它是如何存储在计算机里的?用Python编程如何处理?

从概念上讲,形式最简单的图像(单通道,例如二值或单色,灰度或黑白图像)是一个二维函数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图像数据库,其中大多是用于图像处理的标准图像。

图像处理是指在计算机上使用算法和代码自动处理、操控、分析和解释图像,广泛应用于诸多学科和领域,如电视、摄影、机器人、遥感、医学诊断和工业检验。像大众所熟知的Facebook和Instagram社交网站,都面临着用户每天上传大量图片的情况,需要使用图像处理算法或对图像处理算法进行创新来处理上传的图片。

在本书中,我们用Python包来处理图像:首先,用一组库来做经典的图像处理——提取图像数据,用库函数的算法将数据转换为预处理、增强、复原、表示(用描述符)、分割、分类、检测和识别(对象),从而更好地分析、理解和解释数据;其次,我们用另一组库进行基于深度学习的图像处理——这种技术近年来变得非常热门。

图像处理的典型应用包括医学/生物领域的应用(如X射线和CT扫描)、计算摄影(Photoshop)、指纹认证、人脸识别等。

图像处理流程的基本步骤如下。

(1)图像的获取与存储。获取图像(如使用相机获取),并以文件的形式(如JPEG文件)将其存储在某些设备(如硬盘)上。

(2)加载图像数据至内存并存盘。从磁盘读取图像数据至内存,使用某种数据结构(如numpy ndarray)作为存储结构,之后将数据结构序列化到一个图像文件中,也可能是在对图像运行了算法之后。

(3)操作、增强和复原。需运行预处理算法完成如下任务。

① 图像转换(采样和操作,如灰度转换)。

② 图像质量增强(滤波,如图像由模糊变清晰)。

③ 图像去噪,图像复原。

(4)图像分割。为了提取感兴趣的对象,需要对图像进行分割。

(5)信息提取/表示。图像需以其他形式表示,如表示为以下几项。

① 某些可从图像中计算出来的人工标识的特征描述符(如HOG描述符、经典图像处理)。

② 某些可自动从图像中学习的功能(例如,在深度学习神经网络的隐藏层中学到权重和偏差值)。

③ 以另一种表示方法表示图像。

(6)图像理解/图像解释。以下表示形式可用于更好地理解图像。

① 图像分类(例如,图像是否包含人类  对象)。

② 对象识别(例如,在带有边框的图像中查找car对象的位置)。

图像处理流程如图1-3所示。

图1-3 图像处理流程

用于各种图像处理任务的不同模块如 图1-4所示。除此之外,还会用到以下图像处理模块。

(1)scipy.ndimageopencv用于不同图像处理。

(2)scikit-learn用于经典的机器学习。

(3)tensorflowkeras用于深度学习。

图1-4 用于图像处理任务的不同模块

后续将介绍如何安装不同的图像处理库,并为用Python经典图像处理技术进行图像处理编程设置环境。在本书的最后一些章节使用基于深度学习的方法时,需要使用不同的设置。

安装图像处理库要用到pip(或pip3)工具。因此,如果还没安装它,先安装pip。如果使用从python.org下载的Python 3 或3.4及以上的版本,或者已工作在由virtualenvpyvenv创建的虚拟环境中,则说明pip已经安装好了,只需要确保pip升级即可。

Python有许多库可用于图像处理,如NumPy、SciPy、scikit-image、PIL(Pillow)、OpenCV、scikit-learn、SimpleITK和matplotlib。matplotlib库主要用于图像显示,而numpy主要用于图像存储,scikit-learn库构建用于图像处理的机器学习模型,scipy主要用于图像增强,scikit-imagemahotasopencv库用于不同的图像处理算法。

以下代码展示了通过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-imagePILPython库的版本如下面的代码所示:

>>> import skimage, PIL, numpy
>>> print(skimage.__version__)
# 0.14.0
>>> PIL.__version__
# 5.1.0
>>> numpy.__version__
# 1.14.5

要确保所有库为最新版本。

请下载并安装最新版本的Anaconda发行版,以免去直接安装众多的Python包的麻烦。

如果用Jupyter笔记本来编写Python代码,需要先通过Python提示符安装jupyter包,即首先使用>>>pip install jupyter,然后使用>>>jupyter notebook,在浏览器中启动Jupyter Notebook应用程序。这时在应用程序中就可以新建Python笔记本并选择核了。如果使用的是Anaconda,就不需要显式安装Jupyter,因为最新的Anaconda发行版本附带了Jupyter。

由于图像是作为文件存储在磁盘上的,因此从文件中读取和写入图像是磁盘输入/输出操作。可以通过多种方式使用不同的库完成这些任务,本节给出了其中一些方式。从导入所有必需的包开始,代码如下:

# for inline image display inside notebook
# % matplotlib inline
import numpy as np
from PIL import Image, ImageFont, ImageDraw
from PIL.ImageChops import add, subtract, multiply, difference, screen
import PIL.ImageStat as stat
from skimage.io import imread, imsave, imshow, show, imread_collection,
imshow_collection
from skimage import color, viewer, exposure, img_as_float, data
from skimage.transform import SimilarityTransform, warp, swirl
from skimage.util import invert, random_noise, montage
import matplotlib.image as mpimg
import matplotlib.pylab as plt
from scipy.ndimage import affine_transform, zoom
from scipy import misc

PIL的open()函数用于从Image对象的磁盘读取图像,如下面的代码所示。图像作为PIL.PngImagePlugin.PngImageFile类的对象加载,读者可以用宽度、高度和模式等属性来查找图像的大小[宽度×高度(像素)或分辨率]和模式。

im = Image.open("../images/parrot.png") # read the image, provide the 
correct path
print(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所示,从文件中读取图像,然后再将图像显示在屏幕上。

用PIL函数convert()将彩色RGB图像转换为灰度图像,代码如下:

im_g = im.convert('L')                    # convert the RGB color image to a 
                                            grayscale image
im_g.save('../images/parrot_gray.png')     # save the image to disk
Image.open("../images/parrot_gray.png").show() # read the grayscale image from disk and show

运行上述代码,结果如图1-6所示,输出的是鹦鹉的灰度图像。

图1-5 读取的鹦鹉图像

图1-6 输出鹦鹉的灰度图像

提供磁盘上图像的正确路径

建议创建一个文件夹(子目录)来存储要处理的图像(例如,对于Python代码示例,建议读者使用名为images的文件夹来存储图像),然后提供文件夹的路径以访问图像,以免出现“找不到文件”的异常。

接下来演示如何使用matplotlib.image中的imread()函数来读取浮点numpy ndarray中的图像,其中,像素值表示为介于0和1之间的真值。代码如下:

im = mpimg.imread("../images/hill.png") # read the image from disk as a numpy ndarray
print(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 image
plt.axis('off')
plt.show()

运行上述代码,输出结果如图1-7所示。

图1-7 用imread()函数读取的山峰图像

接下来展示如何将图像更改为较暗的图像。首先将所有像素值设置为0和0.5之间的数,然后将numpy ndarray保存到磁盘。保存的图像将重新加载并显示。代码如下:

im1 = im
im1[im1 < 0.5] = 0   # make the image look darker
plt.imshow(im1)
plt.axis('off')
plt.tight_layout()
plt.savefig("../images/hill_dark.png")       # save the dark image
im = mpimg.imread("../images/hill_dark.png") # read the dark image
plt.figure(figsize=(10,10))
plt.imshow(im)
plt.axis('off') # no axis ticks
plt.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 as
a numpy ndarray
methods = ['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图像进行处理的效果

以下代码演示了如何用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 the
 correct path
print(im.shape, im.dtype, type(im))
# (362, 486, 3) uint8 <class 'numpy.ndarray'>
hsv = color.rgb2hsv(im) # from RGB to HSV color space
hsv[:, :, 1] = 0.5 # change the saturation
im1 = color.hsv2rgb(hsv) # from HSV back to RGB
imsave('../images/parrot_hsv.png', im1) # save image to disk
im = imread("../images/parrot_hsv.png")
plt.axis('off'), imshow(im), show()

运行上述代码,输出结果如图1-11所示。这是一张饱和度发生了变化的鹦鹉新图像。

图1-11 饱和度发生了变化的鹦鹉新图像

还可以用scikit-imageviewer模块在弹出窗口中显示图像,代码如下:

viewer = viewer.ImageViewer(im)
viewer.show()

1.使用scikit-image的astronaut数据集

以下代码显示了如何使用data模块从scikit-image库的图像数据集中加载astronaut(宇航员)图像。该模块包含一些其他流行的数据集,如cameraman数据集,该数据集可以用类似的方法加载。

im = data.astronaut()
imshow(im), show()

运行上述代码,输出结果如图1-12所示。

图1-12 使用data模块加载宇航员图像

2.一次性同时读取和显示多个图像

可以用scikit-imageio模块中的imread_collection()函数将文件名中具有特定模式的所有图像加载到一个文件夹中,并用imshow_collection()函数同时显示它们。具体代码实现留给读者作为练习。

SciPy的misc模块也可用于图像的输入/输出和显示。下面将演示如何使用misc模块的函数。

使用misc模块的face数据集

以下代码展示了如何显示misc模块的face数据集:

im = misc.face() # load the raccoon's face image
misc.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 imageio
im = imageio.imread('../images/pepper.jpg')
print(type(im), im.shape, im.dtype)
# <class 'imageio.core.util.Image'> (225, 225, 3)  
uint8
plt.imshow(im), plt.axis('off'), plt.show()

运行上述代码,输出结果如图1-14所示。

图1-14 读取与显示的辣椒图像

本节将讨论处理不同的文件格式和图像类型,并执行基本的图像操作。

图像可以以不同的文件格式和不同的模式(类型)保存。接下来我们将讨论如何使用Python库来处理不同的文件格式和类型的图像。

1.文件格式

图像文件可以有不同的格式,其中一些流行的格式包括BMP(8位、24位、32位)、PNG、JPG(JPEG)、GIF、PPM、PNM和TIFF。读者不需要担心图像文件的特定格式(如何存储元数据)以及从中提取数据。

Python图像处理库将读取图像,并提取数据和一些其他有用的信息(例如图像尺寸、类型/模式和数据类型)。

从一种文件格式转换为另一种文件格式 使用PIL可以读取一种文件格式的图像并将其保存为另一种文件格式,将PNG格式的图像保存为JPG格式的图像的代码如下:

im = Image.open("../images/parrot.png")
print(im.mode)

# RGB
im.save("../images/parrot.jpg")

但如果PNG文件是在RGBA模式下,则读者在将其保存为JPG格式之前需要将其转换为RGB模式,否则将报错。以下代码展示了先转换再保存的方法:

im = Image.open("../images/hill.png")
print(im.mode)
# RGBA
im.convert('RGB').save("../images/hill.jpg") # first convert to RGB mode

2.图像类型(模式)

图像可以是以下不同的类型。

(1)单通道图像。每个像素由单个值表示。包括二值(单色)图像(每个像素由一个0~1位表示)和灰度图像(每个像素由8位表示,其值通常在0~255内)都是单通道图像。

(2)多通道图像。每个像素由一组值表示。多通道图像包括三通道图像和四通道图像。

① 三通道图像。RGB图像和HSV图像都是三通道图像。RGB图像的每个像素由三元组(rgb)值表示,这三个值分别表示每个像素的红色、绿色和蓝色的通道颜色值。HSV图像的每个像素由三元组(hsv)值表示,这三个值分别表示每个像素的色调(颜色)、饱和度(色彩,即颜色与白色的混合程度)和值(亮度,即颜色与黑色的混合程度)的通道颜色值。HSV模型描述颜色的方式与人眼感知颜色的方式是相似的。

② 四通道图像。RGBA图像的每个像素由四元组(rgba)值表示,其中最后一个通道表示透明度。

一种图像模式转换为另一种图像模式 例如,读者可以在读取图像本身的同时将RGB图像转换为灰度图像,如下面的代码所示:

im = imread("images/parrot.png", as_gray=True)
print(im.shape)
#(362L, 486L)

请注意,在将某些彩色图像转换为灰度图像时,可能会丢失一些信息。以下代码显示了使用石原板(Ishihara plate)检测色盲这样一个例子,这里使用color模块中的rgb2gray()函数,彩色图像和灰度图像并排显示。

im = imread("../images/Ishihara.png")
im_g = color.rgb2gray(im)
plt.subplot(121), plt.imshow(im, cmap='gray'), plt.axis('off')
plt.subplot(122), plt.imshow(im_g, cmap='gray'), plt.axis('off')
plt.show()

运行上述代码,输出结果如图1-15所示。可以看到,彩色图像转换成了灰度图像。在彩色图像中,数字8是可见的,而在转换后的灰色版本图像中,数字8几乎不可见。

图1-15 彩色图像至灰色图像的转换

3.一些颜色空间(通道)

图像的几个常用通道/颜色空间包括RGB、HSV、XYZ、YUV、YIQ、YPbPr、YCbCr和YDbDr。我们可以使用仿射映射将图像从一个颜色空间转换到另一个颜色空间。RGB颜色空间与YIQ颜色空间的线性映射关系矩阵如图1-16所示。

图1-16 RGB颜色空间与YIQ颜色空间的线性映射关系矩阵

从一个颜色空间转换到另一个颜色空间 读者可以使用库函数将图像从一个颜色空间转换到另一个颜色空间,例如将图像从RGB颜色空间转换为HSV颜色空间,代码如下所示:

im = imread("../images/parrot.png")
im_hsv = color.rgb2hsv(im)
plt.gray()
plt.figure(figsize=(10,8))
plt.subplot(221), plt.imshow(im_hsv[...,0]), plt.title('h', size=20),
plt.axis('off')
plt.subplot(222), plt.imshow(im_hsv[...,1]), plt.title('s', size=20),
plt.axis('off')
plt.subplot(223), plt.imshow(im_hsv[...,2]), plt.title('v', size=20),
plt.axis('off')
plt.subplot(224), plt.axis('off')
plt.show()

上述代码的运行结果如图1-17所示,即创建的鹦鹉HSV图像的H(hue或color:色调)、S(饱和度或浓度)和V(明度)通道。类似地,读者可以使用rgb2yuv()函数将图像转换到YUV颜色空间。

图1-17 从RGB颜色空间转换到HSV颜色空间的鹦鹉图像

4.用于存储图像的数据结构

如前所述,PIL使用Image对象存储图像,而scikit-image使用numpy ndarray数据结构存储图像数据。接下来,我们将描述如何在这两种数据结构之间进行转换。

转换图像数据结构 如下代码将展示如何从PIL的Image对象转换为numpy ndarray(由scikit-image使用):

im = Image.open('../images/flowers.png') # read image into an Image object with PIL
im = np.array(im) # create a numpy ndarray from the Image object
imshow(im) # use skimage imshow to display the image
plt.axis('off'), show()

运行上述代码,输出结果如图1-18所示,可以看到,输出的是一幅花的图像。

图1-18 从PIL的image对象转换为numpy ndarray对象

如下代码将展示如何将numpy ndarray转换为PIL的image对象。运行代码后,会看到与图1-18相同的输出。

im = imread('../images/flowers.png') # read image into numpy ndarray with skimage
im = Image.fromarray(im) # create a PIL Image object from the numpy ndarray
im.show() # display the image with PIL Image.show() method

不同的Python库都可以用于基本的图像操作。几乎所有库都以numpy ndarray存储图像(例如灰度图像的二维数组和RGB图像的三维数组)。彩色Lena图像的正xy方向(原点是图像二维数组的左上角)如图1-19所示。

图1-19 Lena彩色图像的坐标方向

1.使用numpy数组的切片进行图像处理

如下代码显示了如何使用numpy数组的切片和掩模在Lena图像上创建圆形掩模:

lena = mpimg.imread("../images/lena.jpg") # read the image from disk as a numpy ndarray
print(lena[0, 40])
# [180  76  83]
# print(lena[10:13, 20:23,0:1]) # slicing
lx, ly, _ = lena.shape
X, Y = np.ogrid[0:lx, 0:ly]
mask = (X - lx / 2) ** 2 + (Y - ly / 2) ** 2 > lx * ly / 4
lena[mask,:] = 0 # masks
plt.figure(figsize=(10,10))
plt.imshow(lena), plt.axis('off'), plt.show()

运行上述代码,输出结果如图1-20所示。

图1-20 Lena图像的圆形掩模

简单的图像变形——使用交叉溶解的两个图像的α混合 

如下代码展示了通过使用如下公式给出的两张图像numpy ndarrays的线性组合,如何从一张人脸图像(image1)开始,以另一张人脸图像(image2)结束。

通过迭代地将α从0增加到1来实现图像的变形效果。

im1 = mpimg.imread("../images/messi.jpg") / 255 # scale RGB values in [0,1]
im2 = mpimg.imread("../images/ronaldo.jpg") / 255
i = 1
plt.figure(figsize=(18,15))
for alpha in np.linspace(0,1,20):
 plt.subplot(4,5,i)
 plt.imshow((1-alpha)*im1 + alpha*im2)
 plt.axis('off')
 i += 1
plt.subplots_adjust(wspace=0.05, hspace=0.05)
plt.show()

运行上述代码,输出结果是α-混合图像的序列。本书后续章节将介绍更加高级的图像变形技术。

2.使用PIL进行图像处理

PIL提供了许多进行图像处理的函数,例如,使用点变换来更改像素值或对图像实现几何变换。在使用PIL进行图像处理之前,加载鹦鹉的PNG图像,如下面的代码所示:

im = Image.open("../images/parrot.png")          # open the image, provide the correct path
print(im.width, im.height, im.mode, im.format) # print image size, mode and format
# 486 362 RGB PNG

接下来将介绍如何使用PIL执行不同类型的图像操作。

(1)裁剪图像。可以使用带有所需矩形参数的crop()函数从图像中裁剪相应的区域,如下面的代码所示:

im_c = im.crop((175,75,320,200)) # crop the rectangle given by (left, top,right,   
bottom) from the image
im_c.show()

运行上述代码,输出结果如图1-21所示,此图即所创建的裁剪图像。

图1-21 裁剪的鹦鹉图像

(2)调整图像尺寸。为了增大或缩小图像的尺寸,可以使用resize()函数,该函数可在内部分别对图像进行上采样或下采样。这部分内容将在下一章中详细讨论。

① 调整为较大的图像。从尺寸为107×105的小时钟图像开始,创建一个尺寸较大的图像。如下代码展示了将要处理的小时钟图像:

im = Image.open("../images/clock.jpg")
print(im.width, im.height)
# 107 105
im.show()

运行上述代码,输出结果如图1-22所示,此图即小时钟图像。

图1-22 小时钟图像

如下代码说明了通过使用双线性插值(一种上采样技术),使用resize()函数放大先前的输入时钟图像(放大5倍),以获得比输入图像放大25倍的输出图像。

im_large = im.resize((im.width*5, im.height*5),   
Image.BILINEAR) # bi-linear interpolation

有关此技术如何工作的详细信息参见第2章。

② 调整为较小的图像。现在让我们来做相反的事情:从维多利亚纪念堂的大图像(尺寸为720×540)开始,创建一个尺寸较小的图像。如下代码展示了将要处理的大图像:

im = Image.open("../images/victoria_memorial.png")
print(im.width, im.height)
# 720 540
im.show()

运行上述代码,输出结果如图1-23所示,图为维多利亚纪念堂图像。

图1-23 维多利亚纪念堂图像

下面一行代码说明了如何使用resize()函数来缩小维多利亚纪念堂的当前图像,通过使用抗混叠技术(一种高质量的下采样技术),将图像的宽度和高度都调整为原宽度和高度的1/5。读者将在第2章中看到它是如何实现的。

im_small = im.resize((im.width//5, im.height//5), Image.ANTIALIAS)

(3)图像负片。可以使用point()函数,用单参数函数来转换每个像素值。可以使用它来生成图像负片,如下面的代码所示。像素值用1字节无符号整数表示,因此,从最大可能值中减去该值将是每个像素上获得图像反转所需的精确点操作。

im = Image.open("../images/parrot.png")
im_t = im.point(lambda x: 255 - x)
im_t.show()

运行上述代码,输出结果如图1-24所示,图中显示的即是鹦鹉负片图像。

(4)将图像转换为灰度图像。可以使用带有“L”参数的convert()函数将RGB彩色图像更改为灰度图像,如下面的代码所示:

im_g = im.convert('L')  # convert the RGB color image to a grayscale image

本书将在接下来的几个灰度转换中使用这个图像。

(5)某些灰度级变换。在这里将探讨两个变换。其中一个使用一个函数,将输入图像中的每个像素值变换为输出图像的相应像素值。函数point()可用于此操作。每个像素的值介于0和255之间(含0和255)。

图1-24 鹦鹉负片图像

① 对数变换。对数变换可以有效地压缩具有动态像素值范围的图像。下面的代码使用了点变换进行对数变换:

im_g.point(lambda x: 255*np.log(1+x/255)).show()

图1-25所示为鹦鹉图像的对数变换结果,可以看到,像素值的范围缩小,输入图像中较亮的像素变暗,较暗的像素变亮,从而缩小了像素值的范围。

图1-25 鹦鹉图像的对数变换

② 幂律变换。幂律变换用作图像的γ校正。下面一行代码说明了如何使用point()函数进行幂律变换,其中γ = 0.6:

im_g.point(lambda x: 255*(x/255)**0.6).show()

图1-26显示了运行上述代码生成的鹦鹉的幂律变换图像。

图1-26 鹦鹉图像的幂律变换

(6)一些几何变换。本节将讨论另一些变换,这些变换是通过将适当的矩阵(通常用齐次坐标表示)与图像矩阵相乘来完成的。由于这些变换会改变图像的几何方向,因此称这些变换为几何变换。

① 镜像图像。可以使用transpose()函数得到在水平或垂直方向上的镜像图像,代码如下所示:

im.transpose(Image.FLIP_LEFT_RIGHT).show() # reflect about the vertical axis

运行上述代码,得到图1-27所示的鹦鹉图像的镜像。

图1-27 鹦鹉图像的镜像

② 旋转图像。可以使用rotate()函数将图像旋转一个角度(以度为单位),代码如下所示:

im_45 = im.rotate(45)   #rotate the image by 45 degrees
im_45.show()            #show the retated image

运行上述代码,输出鹦鹉图像的旋转变换图像,如图1-28所示。

图1-28 鹦鹉图像的旋转变换

③ 在图像上应用仿射变换。二维仿射变换矩阵T可以应用于图像的每个像素(在齐次坐标中),以进行仿射变换,这种变换通常通过反向映射(扭曲)来实现。

如下代码所示的是用shear(剪切)变换矩阵变换输入图像时得到的输出图像。transform()函数中的数据参数是一个六元组(abcdef),其中包含仿射变换矩阵(affine transform matrix)的前两行。对于输出图像中的每个像素(xy),新值取自输入图像中的位置(ax+by+cdx+ey+f),使用最接近的像素进行近似。transform()函数可用于缩放、平移、旋转和剪切原始图像。

im = Image.open("../images/parrot.png")
im.transform((int(1.4*im.width), im.height), Image.AFFINE,
data=(1,-0.5,0,0,1,0)).show() # shear

运行上述代码,所输出的剪切变换图像如图1-29所示。

图1-29 鹦鹉图像的剪切变换

④ 透视变换。通过使用Image.PERSPECTIVE参数,可以使用transform()函数对图像进行透视变换,如下面的代码所示:

params = [1, 0.1, 0, -0.1, 0.5, 0, -0.005, -0.001]
im1 = im.transform((im.width//3, im.height), Image.PERSPECTIVE, params,Image.BICUBIC)
im1.show()

运行上述代码,透视投影之后获得的图像如图1-30所示。

图1-30 鹦鹉图像的透视变换

(7)更改图像的像素值。可以使用putpixel()函数更改图像中的像素值。接着讨论使用函数向图像中添加噪声的主流应用。

可以通过从图像中随机选择几个像素值,然后将这些像素值的一半设置为黑色,另一半设置为白色,来为图像添加一些椒盐噪声(salt-and-pepper noise)。如下代码展示了如何添加噪声:

# choose 5000 random locations inside image
im1 = im.copy() # keep the original image, create a copy
n = 5000
x, y = np.random.randint(0, im.width, n), np.random.randint(0, im.height,n)
for (x,y) in zip(x,y):
 im1.putpixel((x, y), ((0,0,0) if np.random.rand() < 0.5 else 
(255,255,255))) # salt-and-pepper noise
im1.show()

运行上述代码,输出噪声图像,如图1-31所示。

图1-31 添加了椒盐噪声的鹦鹉图像

(8)在图像上绘制图形。可以用PIL.ImageDraw模块中的函数在图像上绘制线条或其他几何图形(例如ellipse()函数可用于绘制椭圆),如下面的代码所示:

im = Image.open("../images/parrot.png")
draw = ImageDraw.Draw(im)
draw.ellipse((125, 125, 200, 250), fill=(255,255,255,128))
del draw
im.show()

运行上述代码,输出结果如图1-32所示。

图1-32 在鹦鹉图像上绘制椭圆

(9)在图像上添加文本。可以使用PIL.ImageDraw模块中的text()函数向图像添加文本,如下面的代码所示:

draw = ImageDraw.Draw(im)
font = ImageFont.truetype("arial.ttf", 23) # use a truetype font
draw.text((10, 5), "Welcome to image processing with python", font=font)
del draw
im.show()

运行上述代码,输出结果如图1-33所示。

图1-33 在鹦鹉图像上绘制文本

(10)创建缩略图。可以使用thumbnail()函数创建图像的缩略图,如下面的代码所示:

im_thumbnail = im.copy() # need to copy the original image first
im_thumbnail.thumbnail((100,100))
# now paste the thumbnail on the image
im.paste(im_thumbnail, (10,10))
im.save("../images/parrot_thumb.jpg")
im.show()

运行上述代码,输出结果如图1-34所示。

图1-34 鹦鹉图像的缩略图

(11)计算图像的基本统计信息。可以使用stat模块来计算一幅图像的基本统计信息(不同通道像素值的平均值、中值、标准差等),如下面的代码所示:

s = stat.Stat(im)
print(s.extrema) # maximum and minimum pixel values for each channel R, G,B
# [(4, 255), (0, 255), (0, 253)]
print(s.count)
# [154020, 154020, 154020]
print(s.mean)
# [125.41305674587716, 124.43517724970783, 68.38463186599142]
print(s.median)
# [117, 128, 63]
print(s.stddev)
# [47.56564506512579, 51.08397900881395, 39.067418896260094]

(12)绘制图像RGB通道像素值的直方图。histogram()函数可用于计算每个通道像素的直方图(像素值与频率表),并返回相关联的输出(例如,对于RGB图像,输出包含3×256 = 768个值),如下面的代码所示:

pl = im.histogram()
plt.bar(range(256), pl[:256], color='r', alpha=0.5)
plt.bar(range(256), pl[256:2*256], color='g', alpha=0.4)
plt.bar(range(256), pl[2*256:], color='b', alpha=0.3)
plt.show()

运行上述代码,输出结果如图1-35所示,即RGB三色直方图。

图1-35 RGB三色直方图

(13)分离图像的RGB通道。可以用split()函数来分离多通道图像的通道,如下面的代码可对RGB图像实现RGB通道的分离:

ch_r, ch_g, ch_b = im.split() # split the RGB image into 3 channels: R, G and B
# we shall use matplotlib to display the channels
plt.figure(figsize=(18,6))
plt.subplot(1,3,1); plt.imshow(ch_r, cmap=plt.cm.Reds); plt.axis('off')
plt.subplot(1,3,2); plt.imshow(ch_g, cmap=plt.cm.Greens); plt.axis('off')
plt.subplot(1,3,3); plt.imshow(ch_b, cmap=plt.cm.Blues); plt.axis('off')
plt.tight_layout()
plt.show() # show the R, G, B channels

运行上述代码,输出结果如图1-36所示,即R(红色)、G(绿色)和B(蓝色)通道创建的三个输出图像。

图1-36 红、绿、蓝通道输出的鹦鹉图像

(14)合并图像的多个通道。可以使用merge()函数合并多通道图像的通道,如下面的代码所示。其中颜色通道是通过分离鹦鹉的RGB图像,并在红蓝通道交换后合并得到的。

im = Image.merge('RGB', (ch_b, ch_g, ch_r)) # swap the red and blue channels obtained last time with split()
im.show()

运行上述代码,输出结果如图1-37所示,即合并B、G和R通道而创建的RGB输出图像。

图1-37 通过合并通道创建的鹦鹉图像

(15)两幅图像的α-混合。blend()函数可将一个常量α 插入两个给定的图像(大小相同),从而创建一个新的图像。两个图像的大小和模式必须相同。输出图像由下式给出:

out = (1.0–α).image1+α.image2

如果α 为0.0,则返回第一个图像的副本;如果α 为1.0,则返回第二个图像的副本。以下代码展示了一个示例:

im1 = Image.open("../images/parrot.png")
im2 = Image.open("../images/hill.png")
# 453 340 1280 960 RGB RGBA
im1 = im1.convert('RGBA') # two images have different modes, must be converted to 
# the same mode
im2 = im2.resize((im1.width, im1.height), Image.BILINEAR) # two images have different sizes,
#must be converted to the same size
im = Image.blend(im1, im2, alpha=0.5).show()

运行上述代码,输出结果如图1-38所示,这是混合两个图像生成的输出图像。

图1-38 鹦鹉图像与山峰图像的α 混合

(16)两幅图像叠加。通过将两个输入图像(大小相同)的像素相乘,可以将一个图像叠加到另一个图像的顶部。如下代码演示了一个示例:

im1 = Image.open("../images/parrot.png")
im2 = Image.open("../images/hill.png").convert('RGB').resize((im1.width,im1.height))
multiply(im1, im2).show()

运行上述代码,输出结果如图1-39所示,图中即叠加两个图像时生成的输出图像。

图1-39 鹦鹉与山峰图像的叠加

(17)两幅图像相加。下面的代码展示了如何通过逐个对像素相加的方式,使用两个输入图像(大小相同)生成一个新图像:

add(im1, im2).show()

运行上述代码,输出结果如图1-40所示。

图1-40 鹦鹉与山峰图像的相加

(18)计算两个图像之间的差值。图像差值可以用来检测两个图像之间的变化。如下代码展示了如何计算图像的差值(difference),图像取自2018年国际足联世界杯比赛的视频录制(来自YouTube)中的连续两帧。

from PIL.ImageChops import subtract, multiply, screen, difference, add
im1 = Image.open("../images/goal1.png") # load two consecutive frame images
from the video
im2 = Image.open("../images/goal2.png")
im = difference(im1, im2)
im.save("../images/goal_diff.png")

plt.subplot(311)
plt.imshow(im1) 
plt.axis('off')
plt.subplot(312)
plt.imshow(im2)
plt.axis('off')
plt.subplot(313)
plt.imshow(im), plt.axis('off')
plt.show()

运行上述代码,输出图1-41所示的连续两帧图像及两幅图像的差值图像。

第一帧

第二帧

差值图像

图1-41 国际足联世界杯比赛的连续两帧图像及其差值图像

(19)减去两个图像和叠加两个图像负片。substract()函数的作用是:首先减去两个图像,然后将结果除以比例(默认值为1.0),再加上偏移量(默认值为0.0)。类似地,screen()函数可用于将两个反转图像叠加在一起。

3.使用scikit-image进行图像操作

正如前面使用PIL库所做的那样,还可以使用scikit-image库函数进行图像操作。下面将展示一些实例。

(1)使用warp()函数进行反向扭曲和几何转换。scikit-imagetransform模块的warp()函数可用于图像几何变换的反向扭曲(在前一节中讨论过),示例如下。

在图像上应用仿射变换 可以使用SimilarityTransform()函数来计算变换矩阵,然后使用warp()函数来执行变换,如下面的代码所示:

im = imread("../images/parrot.png")
tform = SimilarityTransform(scale=0.9,
rotation=np.pi/4,translation=(im.shape[0]/2, -100))
warped = warp(im, tform)
import matplotlib.pyplot as plt
plt.imshow(warped), plt.axis('off'), plt.show()

运行上述代码,输出结果如图1-42所示。

图1-42 鹦鹉图像的仿射变换

(2)应用旋流变换(swirl transform)。这是scikit-image文档中定义的非线性变换。如下代码展示了如何使用swirl()函数来实现变换,其中strength是函数的旋流量参数,radius以像素表示旋流程度,rotation用来添加旋转角度。

radius变换为r是为了确保变换在指定半径内衰减到约1/1000th。

im = imread("../images/parrot.png")
swirled = swirl(im, rotation=0, strength=15, radius=200)
plt.imshow(swirled)
plt.axis('off')
plt.show()

运行上述代码,输出图1-43所示的通过旋流变换生成的输出图像。

图1-43 鹦鹉图像的旋流变换

(3)在图像中添加随机高斯噪声。可以使用random_noise()函数向图像添加不同类型的噪声。如下代码展示了如何将具有不同方差的高斯噪声添加到图像中:

im = img_as_float(imread("../images/parrot.png"))
plt.figure(figsize=(15,12))
sigmas = [0.1, 0.25, 0.5, 1]
for i in range(4):
 noisy = random_noise(im, var=sigmas[i]**2)
 plt.subplot(2,2,i+1)
 plt.imshow(noisy)
 plt.axis('off')
 plt.title('Gaussian noise with sigma=' + str(sigmas[i]), size=20)
plt.tight_layout()
plt.show()

运行上述代码,输出图1-44所示的添加不同方差的高斯噪声生成的输出图像,从图中可以看到,高斯噪声的标准差越大,输出图像的噪声就越大。

图1-44 鹦鹉图像添加不同高斯噪声生成的输出图像

(4)计算图像的累积分布函数。可以使用cumulative_distribution()函数计算已知图像的累积分布函数(Cumulative Distribution Function,CDF),正如读者将在第4章中看到的那样。然而现在,鼓励读者找到这个函数的用法来计算CDF。

4.使用matplotlib进行图像操作

可以使用matplotlib库中的pylab模块进行图像操作。为此,接下来将演示一个相应的示例,即为图像绘制轮廓线。图像的轮廓线是一条连接所有像素的曲线,这些像素具有相同的特定值。如下代码演示了如何为爱因斯坦的灰度图像绘制轮廓线和填充轮廓:

im = rgb2gray(imread("../images/einstein.jpg")) # read the image from disk
as a numpy ndarray
plt.figure(figsize=(20,8))
plt.subplot(131), plt.imshow(im, cmap='gray'), plt.title('Original Image',
size=20)
plt.subplot(132), plt.contour(np.flipud(im), colors='k',
levels=np.logspace(-15, 15, 100))
plt.title('Image Contour Lines', size=20)
plt.subplot(133), plt.title('Image Filled Contour', size=20),
plt.contourf(np.flipud(im), cmap='inferno')
plt.show()

运行上述代码,输出结果如图1-45所示。

图1-45 为爱因斯坦图像绘制轮廓线和填充轮廓

5.使用scipy.misc和scipy.ndimage模块进行图像操作

也可以使用scipy库中的miscndimage模块进行图像操作,这部分留给读者作为练习,请找到相关的函数并熟悉它们的用法。

本章首先介绍了图像处理的入门知识,以及图像处理中所要解决问题的相关基本概念;接着讨论了图像处理的不同任务要求和步骤,以及Python中的主要图像处理库,并将使用这些库进行代码编写;接下来说明了如何在Python中安装不同的图像处理库,以及如何导入它们并从模块中调用函数;讨论了在Python中如何使用不同的库进行图像输入/输出和显示;还介绍了有关图像类型、文件格式和数据结构的基本概念,以使用不同的Python库存储图像数据。在第2章中,我们将深入研究图像的采样、量化、卷积、傅里叶变换和频域滤波。

1.使用scikit-image库的函数来读取图像集,并将它们展示出来。

2.使用SciPy ndimagemisc模块的函数,对图像进行缩放、裁剪、调整大小和仿射变换。

3.创建一个Python翻版的Gotham Instagram滤波器(提示:使用PIL的split()merge()numpy interp()函数操作图像,创建通道插值)。

4.使用scikit-imagewarp()函数来实现旋流变换。注意,旋流变换也可以用以下公式表示:

5.实现如下所示的波形转换(提示:使用scikit-imagewarp()):

6.使用PIL加载带有调色板的RGB.png文件并转换为灰度图像。通过对调色板进行索引,将图1-46所示的RGB图像(来自VOC2012数据集)转换为灰度图像。

图1-46 RGB图像

7.为本章中所使用的鹦鹉图像的每个颜色通道绘制3D图(提示:使用mpl_toolkits. mplot3d模块的plot_surface()函数和NumPy的meshgrid()函数)。

8.使用scikit-image变换模块的ProjectTransform从原始图像到目标图像估计单应矩阵,并使用inverse()函数将Lena图像(或读者自己的图像)嵌入空白画布处,如图1-47所示。

图1-47 将Lena图像嵌入空白画布处


相关图书

深度学习的数学——使用Python语言
深度学习的数学——使用Python语言
动手学自然语言处理
动手学自然语言处理
Web应用安全
Web应用安全
Python高性能编程(第2版)
Python高性能编程(第2版)
图像处理与计算机视觉实践——基于OpenCV和Python
图像处理与计算机视觉实践——基于OpenCV和Python
Python数据科学实战
Python数据科学实战

相关文章

相关课程