Matplotlib is hiring a Research Software Engineering Fellow! See discourse for details. Apply by January 3, 2020
关于使用matplotlib绘制图像的简短教程。
首先,让我们从伊比森开始。它是对标准python提示的最优秀的增强,它与matplotlib尤其密切相关。现在就从外壳或ipython笔记本开始ipython。
随着IPython的启动,我们现在需要连接到一个GUI事件循环。这将告诉IPython在何处(以及如何)显示绘图。要连接到GUI循环,请执行 %Matlab 在你的ipython提示下变魔术。有更多的细节说明这到底是在干什么 IPython's documentation on GUI event loops .
如果您使用的是ipython笔记本,则可以使用相同的命令,但人们通常使用特定的参数来实现 %matplotlib 魔力:
In [1]: %matplotlib inline
这将打开内嵌打印,打印图形将显示在笔记本中。这对交互性有重要影响。对于内联打印,输出打印的单元格下方单元格中的命令不会影响打印。例如,无法从创建绘图的单元格下方的单元格更改颜色映射。但是,对于其他后端,例如打开单独窗口的qt5,在创建绘图的那些后面的单元格将更改绘图-它是内存中的活动对象。
本教程将使用matplotlib的命令式打印界面pyplot。此界面保持全局状态,对于快速轻松地尝试各种绘图设置非常有用。另一种选择是面向对象的接口,它也非常强大,通常更适合于大型应用程序开发。如果你想了解面向对象的接口,一个很好的起点是 Usage guide . 现在,让我们继续使用命令式方法:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
加载图像数据支持 Pillow 类库。Matplotlib本身只支持PNG图像。如果本机读取失败,下面显示的命令将返回到枕头上。
本例中使用的图像是一个PNG文件,但请记住您自己的数据需要枕头。
下面是我们将要播放的图像:
这是一个24位的r g b png图像(每一个r、g、b对应8位)。根据获取数据的位置,您最可能遇到的其他类型的图像是允许透明度的rgba图像,或单通道灰度(亮度)图像。您可以右键单击它,然后选择“将图像另存为”将其下载到您的计算机上,以完成本教程的其余部分。
我们开始…
img = mpimg.imread('../../doc/_static/stinkbug.png')
print(img)
出:
[[[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.4117647 0.4117647 0.4117647 ]
[0.4117647 0.4117647 0.4117647 ]
[0.4117647 0.4117647 0.4117647 ]
...
[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]]
...
[[0.4392157 0.4392157 0.4392157 ]
[0.43529412 0.43529412 0.43529412]
[0.43137255 0.43137255 0.43137255]
...
[0.45490196 0.45490196 0.45490196]
[0.4509804 0.4509804 0.4509804 ]
[0.4509804 0.4509804 0.4509804 ]]
[[0.44313726 0.44313726 0.44313726]
[0.44313726 0.44313726 0.44313726]
[0.4392157 0.4392157 0.4392157 ]
...
[0.4509804 0.4509804 0.4509804 ]
[0.44705883 0.44705883 0.44705883]
[0.44705883 0.44705883 0.44705883]]
[[0.44313726 0.44313726 0.44313726]
[0.4509804 0.4509804 0.4509804 ]
[0.4509804 0.4509804 0.4509804 ]
...
[0.44705883 0.44705883 0.44705883]
[0.44705883 0.44705883 0.44705883]
[0.44313726 0.44313726 0.44313726]]]
注意这里的数据类型-float32。Matplotlib已将每个通道的8位数据重新调整为介于0.0和1.0之间的浮点数据。作为旁注,枕头可以使用的唯一数据类型是uint8。Matplotlib Plotting可以处理float32和uint8,但除png之外的任何格式的图像读/写都限于uint8数据。为什么是8位?大多数显示器只能显示每个通道8位的颜色渐变值。为什么它们只能渲染8位/通道?因为这是人眼所能看到的。更多信息(从摄影角度来看): Luminous Landscape bit depth tutorial .
每个内部列表代表一个像素。这里,对于一个RGB图像,有3个值。因为它是黑白图像,r、g和b都是相似的。一个rgba(其中a是alpha或transparency),每个内部列表有4个值,一个简单的亮度图像只有一个值(因此只有二维数组,而不是三维数组)。对于rgb和rgba图像,matplotlib支持float32和uint8数据类型。对于灰度,matplotlib仅支持float32。如果数组数据不符合其中一个描述,则需要重新缩放它。
所以,您的数据在一个numpy数组中(通过导入或生成它)。我们来渲染一下。在Matplotlib中,使用 imshow()
功能。在这里我们将抓取绘图对象。此对象提供了一种从提示操作绘图的简单方法。
imgplot = plt.imshow(img)
您还可以绘制任何numpy数组。
伪彩色可以成为增强对比度和更容易可视化数据的有用工具。这在使用投影仪显示数据时尤其有用-它们的对比度通常很差。
伪彩色只与单通道、灰度、亮度图像有关。我们目前有一个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/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命令不会更改早期单元格的绘图。
还有许多其他的配色方案可用。见 list and images of the colormaps .
了解颜色代表的值是很有帮助的。我们可以通过添加颜色条来做到这一点。
imgplot = plt.imshow(lum_img)
plt.colorbar()
这会在现有图形中添加颜色条。这不会自动改变,如果你改变你切换到一个不同的颜色映射-你必须重新创建你的绘图,并再次添加到颜色栏。
有时,您希望增强图像中的对比度,或者在特定区域扩大对比度,同时牺牲颜色变化不大或不重要的细节。找到有趣区域的一个好工具是柱状图。为了创建图像数据的柱状图,我们使用 hist()
功能。
plt.hist(lum_img.ravel(), bins=256, range=(0.0, 1.0), fc='k', ec='k')
最常见的是,图像中“有趣的”部分位于峰值附近,您可以通过剪切峰值上方和/或下方的区域来获得额外的对比度。在我们的柱状图中,高端似乎没有太多有用的信息(图像中没有太多白色的东西)。让我们调整上限,以便有效地“放大”柱状图的一部分。我们通过将clim参数传递给imshow来实现这一点。您也可以通过拨打 set_clim()
图像打印对象的方法,但在使用ipython笔记本时,请确保在与plot命令相同的单元格中执行此操作-它不会更改早期单元格的打印。
您可以在调用中指定clim plot
.
imgplot = plt.imshow(lum_img, clim=(0.0, 0.7))
还可以使用返回的对象指定clim
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')
插值根据不同的数学方案计算像素“应该”的颜色或值。一个常见的情况是当你调整图像的大小。像素数会改变,但您需要相同的信息。因为像素是离散的,所以有丢失的空间。插值就是你如何填充这个空间。这就是为什么你的图像有时会在放大时看起来像像素。当原始图像和扩展图像之间的差异较大时,效果更明显。让我们把图像缩小。我们有效地丢弃了像素,只保留少数选择。现在,当我们绘制它时,数据会放大到屏幕上的大小。旧的像素已经不存在了,计算机必须绘制像素来填充这个空间。
我们将使用我们用来加载图像的枕头库来调整图像的大小。
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)
这里我们有默认的插值,双线性,因为我们没有给出 imshow()
任何插值参数。
我们试试其他的吧。这是“最近的”,没有插值。
imgplot = plt.imshow(img, interpolation="nearest")
双三次:
imgplot = plt.imshow(img, interpolation="bicubic")
双三次插值常用于放大照片-人们倾向于模糊而不是像素化。
脚本的总运行时间: (0分2.042秒)