「 Python数据可视化系列」6.图像可视化和3D图形

来源 | 「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)所示的输出:

 


❤总结

在本章中,你学习并演示了图像可视化,你还了解并演示了图像的基本操作,如算术运算和将彩色图像拆分为组成通道。我们还讨论了如何编写三维可视化程序,包括曲线、条形图、线框和网格。

下一章将探讨如何可视化网络和图形数据结构。


  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据与智能

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值