本教程将使用matplotlib的命令式绘图接口pyplot。这个界面保持全局状态,并且对于快速和容易地尝试各种绘图设置是非常有用的。另一种是面向对象的接口,它也是非常强大的,一般更适合大型应用程序的开发。如果您想了解面向对象的界面,一个好的开始就是我们关于使用的FAQ。现在,让我们继续使用命令式的方法:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
将图像数据导入Numpy数组
加载图像数据由Pillow库支持。 本地,matplotlib只支持PNG图像。 如果本地读取失败,则下面显示的命令会回落到Pillow上。
这个例子中使用的图像是一个PNG文件,但是为了您自己的数据,请记住Pillow要求。
这是我们要导入的图像。
这是一个24位RGB PNG图像(每个R,G,B 8位)。 根据您获取数据的位置,您最有可能遇到的其他类型的图像是RGBA图像,这些图像允许透明度,或单通道灰度(亮度)图像。 您可以右键点击它并选择“保存图像为”将其下载到本教程其余部分的计算机中。
现在我们开始…
img = mpimg.imread('../../doc/_static/stinkbug.png')
print(img)
Out:
[[[ 0.40784314 0.40784314 0.40784314]
[ 0.40784314 0.40784314 0.40784314]
[ 0.40784314 0.40784314 0.40784314]
...,
[ 0.42745098 0.42745098 0.42745098]
[ 0.42745098 0.42745098 0.42745098]
[ 0.42745098 0.42745098 0.42745098]]
[[ 0.41176471 0.41176471 0.41176471]
[ 0.41176471 0.41176471 0.41176471]
[ 0.41176471 0.41176471 0.41176471]
...,
[ 0.42745098 0.42745098 0.42745098]
[ 0.42745098 0.42745098 0.42745098]
[ 0.42745098 0.42745098 0.42745098]]
[[ 0.41960785 0.41960785 0.41960785]
[ 0.41568628 0.41568628 0.41568628]
[ 0.41568628 0.41568628 0.41568628]
...,
[ 0.43137255 0.43137255 0.43137255]
[ 0.43137255 0.43137255 0.43137255]
[ 0.43137255 0.43137255 0.43137255]]
注意那里的dtype - float32。 Matplotlib已经将每个通道的8位数据重新调整为0.0到1.0之间的浮点数据。作为一个方面说明,Pillow可以使用的唯一数据类型是uint8。 Matplotlib绘图可以处理float32和uint8,但对于除PNG以外的任何格式的图像读/写仅限于uint8数据。为什么8位?大多数显示器只能渲染每个通道8位色彩等级。为什么他们只能渲染8位/通道?因为这是所有人眼所能看到的。更多在这里(从摄影角度):夜光景观位深度教程。
每个内部列表代表一个像素。这里,RGB图像有3个值。由于是黑白图像,R,G和B都是相似的。 RGBA(其中A是alpha或透明度)每个内部列表具有4个值,并且简单的亮度图像只有一个值(因此只是一个二维数组,而不是一个三维数组)。对于RGB和RGBA图像,matplotlib支持float32和uint8数据类型。对于灰度,matplotlib只支持float32。如果您的阵列数据不符合这些描述之一,您需要重新调整它。
绘制一个numpy数组作为图像
图像可以读取或者用数组来表示,你的数据在一个numpy数组(可以通过导入或通过生成)。 让我们来渲染它。 在Matplotlib中,这是通过使用imshow()函数完成的。 在这里,我们将抓取plot对象。 这个对象为您提供了一个简单的方法来处理提示中的场景。
imgplot = plt.imshow(img)
你也可以绘制任何numpy数组。
应用伪彩色方案的图像
Pseudocolor可以是一个有用的工具,可以更加轻松地增强对比度和可视化数据。 使用投影仪进行数据演示时,这一点尤其有用 - 它们的对比度通常很差。Pseudocolor只与单通道,灰度,亮度图像有关。 我们目前有一个RGB图像。 由于R,G和B都是相似的(请参阅上面或在您的数据中),我们可以选择一个数据通道:
lum_img = img[:, :, 0]
# This is array slicing. You can read more in the `Numpy tutorial
# <https://docs.scipy.org/doc/numpy-dev/user/quickstart.html>`_.
plt.imshow(lum_img)
现在,使用亮度(2D,无颜色)图像,应用默认的颜色映射(即查找表,LUT)。 默认叫做viridis。 有很多其他人可以选择。
plt.imshow(lum_img, cmap="hot")
请注意,您还可以使用set_cmap()方法更改现有的阴谋对象的颜色映射:
imgplot = plt.imshow(lum_img)
imgplot.set_cmap('nipy_spectral')
注意
但是,请记住,在具有内联后端的IPython笔记本中,不能对已经呈现的图进行更改。 如果您在一个单元格中创建imgplot,则不能在稍后的单元格中调用set_cmap(),并期望更早的图形发生更改。 确保您在一个单元格中一起输入这些命令。 plt命令不会改变早期单元格的绘图。
还有许多其他的颜色映射方案可用。 查看颜色映射的列表和图像
色标参考
有一个颜色代表什么价值的想法是有帮助的。 我们可以通过添加彩条来做到这一点。
imgplot = plt.imshow(lum_img)
plt.colorbar()
这增加了一个彩条到你现有的人物。 如果您更改切换到不同的色彩映射,这不会自动更改 - 您必须重新创建您的图形,并再次添加到色彩条中。
检查特定的数据范围
有时候,你想要增强图像的对比度,或者扩大特定区域的对比度,同时牺牲颜色变化不大或者不重要的细节。 找到感兴趣的区域的一个好工具是直方图。 要创建图像数据的直方图,我们使用hist()函数。
plt.hist(lum_img.ravel(), bins=256, range=(0.0, 1.0), fc='k', ec='k')
imgplot = plt.imshow(lum_img, clim=(0.0, 0.7))
fig = plt.figure()
a = fig.add_subplot(1, 2, 1)
imgplot = plt.imshow(lum_img)
a.set_title('Before')
plt.colorbar(ticks=[0.1, 0.3, 0.5, 0.7], orientation='horizontal')
a = fig.add_subplot(1, 2, 2)
imgplot = plt.imshow(lum_img)
imgplot.set_clim(0.0, 0.7)
a.set_title('After')
plt.colorbar(ticks=[0.1, 0.3, 0.5, 0.7], orientation='horizontal')
插值根据不同的数学方案计算像素“应该”的颜色或值。 发生这种情况的一个常见的地方是当你调整图像的大小。 像素的数量会发生变化,但是您需要相同的信息。 由于像素是离散的,所以缺少空间。 插值是你如何填补这个空间。 这就是为什么当你吹起来的时候,你的图像有时会出现像素化。 当原始图像和扩大图像之间的差异更大时,效果更显着。 让我们拿我们的形象,缩小它。 我们正在有效地丢弃像素,只保留少数几个。 现在,当我们绘制它时,这些数据会被放大到屏幕上的大小。 旧的像素不再存在,计算机必须绘制像素来填充该空间。
我们将使用我们用来加载图像的Pillow库来调整图像大小。
from PIL import Image
img = Image.open('../../doc/_static/stinkbug.png')
img.thumbnail((64, 64), Image.ANTIALIAS) # resizes image in-place
imgplot = plt.imshow(img)
让我们尝试一些其他的。 这里是“最邻近”,没有插值。
imgplot = plt.imshow(img, interpolation="nearest")
imgplot = plt.imshow(img, interpolation="bicubic")
脚本的总运行时间:(0分钟0.392秒)
本文翻译来自matlotlib官方教材 点击打开链接