来源 | 「Practical Python Data Visualization A Fast Track Approach To Learning Data Visualization With Python」
作者 | Ashwin Pajankar
译者 | Liangchu
校对 | gongyouliu
编辑 | auroral-L
全文共4220字,预计阅读时间20分钟。
第六章 图像可视化和3D图形
目录
一、图像可视化
二、操作图像
三、三维(3D)可视化
❤总结
在第五章 「使用NumPy和Matplotlib进行数据可视化」中,我们开始使用Python 3中的Matplotlib库进行可视化。在本章中,我们将继续学习Matplotlib和NumPy来可视化图像和三维形状(3D shape)。本章将学习以下内容继续探索数据可视化:
• 图像可视化
• 操作图像
• 三维(3D)可视化
本章结束后,你将能够处理图像和三维形状。
一、图像可视化
在本节中,我们将学习如何可视化图像。首先,我们为本章创建一个新笔记本。Matplotlib的函数imread()可以读取.png文件格式的图像,要使它能够读取其他格式的文件,我们必须安装另一个名为pillow的图像处理库。通过在笔记本单元格中运行以下命令进行安装:
!pip3 install pillow
使用我们在第5章中学习的命令使笔记本能够内联显示Matplotlib可视化输出:
%matplotlib inline
使用以下命令导入Matplotlib的Pyplot模块:
import matplotlib.pyplot as plt
现在,让我们使用函数imread()将图像读入,以作为变量,如下所示:
img1 = plt.imread('D:\\Dataset\\4.1.02.tiff')
如果你使用的是Linux、Unix或MacOS计算机,则需要改变一下文件路径,使用以下约定:
img1 = plt.imread('/home/pi/book/dataset/4.1.02.tiff')
你使用的路径必须是绝对路径。如果该图像文件与程序位于同一目录中,则仅写文件名就可以了。
此函数读取图像并将其作为数值矩阵存储在NumPy ndarray中。我们可以通过运行以下代码行来验证这一点:
print(type(img1))
输出如下:
<class 'numpy.ndarray'>
这证实了科学Python库将图像处理为NumPy ndarray的形式。
我们可以使用Matplotlib的imshow()函数显示该ndarray对应的图像,然后使用show()函数将其显示为图形进行输出,如下所示:
plt.imshow(img1)plt.show()
输出如图(6-1)所示:
可以按如下方式关闭轴:
plt.imshow(img1)
plt.axis(False)
plt.show()
注意:我用于演示的所有图像都是从
http://www.imageprocessingplace.com/rootfilesV3/image_databases.htm中下载的。
让我们读一个灰度图像(grayscale image)(灰度数字图像是每个像素只有一个采样颜色的图像。这类图像通常显示为从最暗黑色到最亮的白色的灰度。灰度图像与黑白图像不同,在计算机图像领域中黑白图像只有黑白两种颜色,灰度图像把白色与黑色之间按对数关系分为若干等级,称为灰度。灰度分为256阶。),如下所示:
img2 = plt.imread('D:\\Dataset\\5.3.01.tiff')
我们可以使用以下代码显示它:
plt.imshow(img2)
plt.axis(False)
plt.show()
如图(6-2)显示了输出:
如你所见,颜色看起来有点奇怪——这根本不是一个彩色图像!Matplotlib使用默认颜色映射(color map)显示灰度图像。我们可以显式地指定灰度图来正确地可视化此图像,如下所示:
plt.imshow(img2, cmap=plt.cm.gray)
plt.axis(False)
plt.show()
结果如图(6-3)所示:
我们还可以按以下方式指示颜色映射:
plt.imshow(img2, cmap='gray')
plt.axis(False)
plt.show()
接下来我们将讨论在图像上的基本操作。
二、操作图像
我们可以使用NumPy对图像执行基本操作,并使用Matplotlib进行可视化输出。首先让我们了解一些算术运算,我们需要两幅尺寸相同的图像来进行算术运算。让我们读取另一个彩色图像,代码如下:
img3 = plt.imread('D:\\Dataset\\4.1.03.tiff')
我们可以将其可视化如下:
plt.imshow(img3)plt.axis(False)plt.show()
如图(6-4)显示了输出:
我们可以将两幅图片相加,并且将它们可视化,代码如下:
add = img1+img3
plt.imshow(add)
plt.axis(False)
plt.show()
如图(6-5)显示了输出:
加法运算是一种可交换(排列次序不影响结果)的算术运算,这意味着如果我们改变操作数的顺序,它将不会影响输出:
add1 = img3+img1
plt.imshow(add)
plt.axis(False)
plt.show()
再来试试减法运算:
sub1= img1-img3
plt.imshow(sub1)
plt.axis(False)
plt.show()
如图(6-6)显示了输出:
我们知道减法运算是不可交换的,这意味着如果我们改变操作数的顺序,那么结果就不同了。让我们试一下:
sub1 = img3-img1
plt.imshow(sub1)
plt.axis(False)
plt.show()
因此,如下图(6-7)所示的输出与上图(6-6)的输出不同:
我们知道图像在SciPy中表示为NumPy ndarray。彩色图像和灰度图像的区别在于彩色图像是由多个通道(channel)组成的,这些通道本身就是ndarrays。利用NumPy中的索引技术,我们可以对彩色图像进行分割,并对组成通道分别进行可视化。彩色图像的红色、绿色和蓝色各有一个通道。可以使用NumPy索引拆分图像,如下所示:
r = img3[:, :, 0]
g = img3[:, :, 1]
b = img3[:, :, 2]
让我们使用Matplotlib中的子图(subplot)可视化原始图像和颜色通道:
plt.subplots_adjust(hspace=0.4, wspace=0.1)
plt.subplot(2, 2, 1)
plt.title('Original')
plt.imshow(img3)
plt.subplot(2, 2, 2)
plt.title('Red')
plt.imshow(r, cmap='gray')
plt.subplot(2, 2, 3)
plt.title('Green')
plt.imshow(g, cmap='gray')
plt.subplot(2, 2, 4)
plt.title('Blue')
plt.imshow(b, cmap='gray')
plt.show()
让我们检查一下前面的代码。你正在使用函数subplot()创建一个2×2的网格。函数subplots_adjust()被用于调整可视化之间的距离。2×2网格中的左上角位置为1,它在同一行中的相邻位置为2,依此类推。右下角的位置是第四个位置。在函数subplot()之前使用imshow()或plot(),我们可以决定可视化的绝对位置。输出如图(6-8)所示:
颜色通道本身就是2D矩阵,对于彩色图像的8位无符号整数表示格式来说,其成员的值从0到256不等。当它们组合在一起时,Matplotlib将它们解释为彩色图像。我们可以使用适当的颜色映射将其可视化,如下所示:
plt.subplots_adjust(hspace=0.4, wspace=0.1)
plt.subplot(2, 2, 1)
plt.title('Original')plt.imshow(img3)
plt.subplot(2, 2, 2)
plt.title('Red')
plt.imshow(r, cmap='Reds')
plt.subplot(2, 2, 3)
plt.title('Green')
plt.imshow(g, cmap='Greens')
plt.subplot(2, 2, 4)
plt.title('Blue')
plt.imshow(b, cmap='Blues')
plt.show()
输出如图(6-9)所示:
我们可以使用以下代码来组合组成通道以形成原始图像:
import numpy as npimg4 = np.dstack((r, g, b))
我们正在使用NumPy库中的函数dstack(),我们可以用一般的代码将输出可视化:
plt.imshow(img4)
plt.axis(False)plt.show()
上面讲了如何执行非常基本的图像处理操作,比起我们上面所学的,还有更多更复杂的图像处理操作,如果要进行进一步的演示与学习,就需要使用一本单独的书来讲解了。
三、三维(3D)可视化
在本节中,我们将研究Python 3的三维可视化。到目前为止,我们一直在笔记本本中展示可视化效果,这个过程很适合二维(2D)可视化,然而,在三维可视化的情况下,它只能以固定的角度来显示。因此,我们必须使用另一种方法来进行三维可视化,最好的方法是使用另一个特别神奇的命令,在单独的Qt窗口中显示可视化效果,如下所示:
%matplotlib qt
我们已经在前面的单元格中导入了Matplotlib和NumPy中的pyplot模块(假设你在整个章节中使用的是相同的笔记本)。我们必须使用以下语句导入更多功能:
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d import axes3d
让我们按照从易到难的顺序学习三维可视化。我们已经了解了如何绘制简单的绘图,所以现在我们将在3D中执行相同的操作。从简单的参数曲线开始。首先定义图形和轴:
fig = plt.figure()
ax = fig.gca(projection='3d')
对于三维可视化,我们使用参数和参数对projection='3D'启用了三维投影。接下来定义数据,需要数据点的x、y和z坐标。首先定义数据点的极坐标如下:
theta = np.linspace(-3 * np.pi, 3 * np.pi, 200)
z = np.linspace(-3, 3, 200)
r = z**3 + 1
现在,计算x和y坐标如下:
x = r * np.sin(theta)
y = r * np.cos(theta)
我们使用NumPy库中的三角函数来计算x和y。最后,让我们绘制如下:
ax.plot(x, y, z, label='Parametric Curve')
ax.legend()
plt.show()
如图(6-10)所示,输出将显示在一个单独的窗口中,它将以一种我们能够改变视角的方式进行交互:
注意:如果没有弹出单独的输出窗口,并且浏览器本身显示了三维可视化效果,则必须重新启动Jupyter内核并重新执行相关单元格。在这种情况下,不要执行包含%matplotlib inline的单元格。
接下来,让我们创建一个三维条形图。现在计算数据如下:
x = np.arange(4)
y = np.arange(4)
xx, yy = np.meshgrid(x, y)
print(xx);print(yy)
函数meshgrid()根据坐标向量创建并返回坐标矩阵,如下所示:
[[0 1 2 3]
[0 1 2 3]
[0 1 2 3]
[0 1 2 3]]
[[0 0 0 0]
[1 1 1 1]
[2 2 2 2]
[3 3 3 3]]
然后使用函数ravel()将两个矩阵展平,如下所示:
X, Y = xx.ravel(), yy.ravel()
print(X); print(Y);
这将产生以下输出:
[0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3]
[0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3]
现在,计算更多值:
top = X + Y
bottom = np.zeros_like(top)
width = depth = 1
接下来,创建一个图形和轴,并创建条形图,如下所示:
fig = plt.figure(figsize=(8, 3))
ax1 = fig.add_subplot(121, projection='3d')
ax2 = fig.add_subplot(122, projection='3d')
ax1.bar3d(X, Y, bottom, width, depth, top, shade=True)
ax1.set_title('Shaded')
ax2.bar3d(X, Y, bottom, width, depth, top, shade=False)
ax2.set_title('Not Shaded')plt.show()
这将产生如图(6-11)所示的条形图:
接下来让我们将线框可视化如下:
fig = plt.figure()
ax = fig.gca(projection='3d')
X, Y, Z = axes3d.get_test_data(delta=0.1)
ax.plot_wireframe(X, Y, Z)
plt.show()
在这个代码段中,我们首先在三维模式下创建一个图形和一个轴,然后,内置函数get_test_data()返回测试数据,接下来我们使用函数plot_wireframe()来绘制线框模型。输出如图(6-12)所示:
最后,让我们计算并可视化一个曲面。首先,计算x和y坐标,然后计算网格:
x = np.arange(-3, 3, 0.09)
y = np.arange(-3, 3, 0.09)
X, Y = np.meshgrid(x, y)
print(X); print(Y)
输出如下所示:
[[-3. -2.91 -2.82 ... 2.76 2.85 2.94]
[-3. -2.91 -2.82 ... 2.76 2.85 2.94]
[-3. -2.91 -2.82 ... 2.76 2.85 2.94]
...
[-3. -2.91 -2.82 ... 2.76 2.85 2.94]
[-3. -2.91 -2.82 ... 2.76 2.85 2.94]
[-3. -2.91 -2.82 ... 2.76 2.85 2.94]]
[[-3. -3. -3. ... -3. -3. -3. ]
[-2.91 -2.91 -2.91 ... -2.91 -2.91 -2.91]
[-2.82 -2.82 -2.82 ... -2.82 -2.82 -2.82]
...
[ 2.76 2.76 2.76 ... 2.76 2.76 2.76]
[ 2.85 2.85 2.85 ... 2.85 2.85 2.85]
[ 2.94 2.94 2.94 ... 2.94 2.94 2.94]]
接下来,计算z坐标,如下所示:
R = np.sqrt(X**2 + Y**2)
Z = np.cos(R)
print(Z)
最后,创建图形和轴,并可视化三维曲面:
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(X, Y, Z,
cmap=plt.cm.cool,
linewidth=0,
antialiased=False)
plt.show()
这将产生如图(6-13)所示的输出:
❤总结
在本章中,你学习并演示了图像可视化,你还了解并演示了图像的基本操作,如算术运算和将彩色图像拆分为组成通道。我们还讨论了如何编写三维可视化程序,包括曲线、条形图、线框和网格。
下一章将探讨如何可视化网络和图形数据结构。