Python matplotlib 的 Image tutorial图像处理教程

本教程将使用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')
大多数情况下,图像的“有趣”部分是在峰值附近,通过剪切峰顶上方和/或下方的区域,可以获得额外的对比度。 在我们的直方图中,看起来高端没有太多有用的信息(图像中不是很多白色的东西)。 让我们调整上限,以便我们有效地“放大”直方图的一部分。 我们通过向imshow传递攀登参数来做到这一点。 您也可以通过调用图像对象的set_clim()方法来做到这一点,但是确保在使用IPython Notebook时,在同一单元格中执行此操作 - 它不会更改早期单元格的图形。
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')
Array插值方案
插值根据不同的数学方案计算像素“应该”的颜色或值。 发生这种情况的一个常见的地方是当你调整图像的大小。 像素的数量会发生变化,但是您需要相同的信息。 由于像素是离散的,所以缺少空间。 插值是你如何填补这个空间。 这就是为什么当你吹起来的时候,你的图像有时会出现像素化。 当原始图像和扩大图像之间的差异更大时,效果更显着。 让我们拿我们的形象,缩小它。 我们正在有效地丢弃像素,只保留少数几个。 现在,当我们绘制它时,这些数据会被放大到屏幕上的大小。 旧的像素不再存在,计算机必须绘制像素来填充该空间。
我们将使用我们用来加载图像的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)
这里我们有默认的插值,双线性,因为我们没有给imshow()任何插值参数。
让我们尝试一些其他的。 这里是“最邻近”,没有插值。

imgplot = plt.imshow(img, interpolation="nearest")
和bucibic:

imgplot = plt.imshow(img, interpolation="bicubic")
Bicubic插值时经常使用双三次插值 - 人们倾向于模糊像素化。
脚本的总运行时间:(0分钟0.392秒)


本文翻译来自matlotlib官方教材 点击打开链接



展开阅读全文

没有更多推荐了,返回首页