强基初中数学&学Python——第250课 数字和数学第三方模块Matplotlib之四:图像教程(3)

检查特定数据范围

  有时,为了增强图像中的对比度,或在特定区域扩大对比度,无所谓牺牲颜色变化不大或无关紧要的细节。找到“有趣”区域的一个好工具是直方图。为此使用hist()函数创建图像数据的直方图。
hist():

https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.hist.html#matplotlib.pyplot.hist

· 

plt.hist(lum_img.ravel(), bins=256, range=(0.0, 1.0), fc='k', ec='k')

  完整代码:

· 

· 

· 

· 

· 

· 

· 

ipython%matplotlib tkimport matplotlib.pyplot as pltimport matplotlib.image as mpimgimg = mpimg.imread('D:/5xstar/work/stinkbug.png')lum_img = img[:, :, 0]plt.hist(lum_img.ravel(), bins=256, range=(0.0, 1.0), fc='k', ec='k')

 

  最常见的情况是,图像的“有趣”部分位于峰值附近,通过裁剪峰值上方和/或下方的区域,可以获得额外的对比度。在上面的直方图中,高段似乎没有太多有用的信息(图像中没有太多白色的东西)。这样,可以调整上限,以便有效地“放大”直方图中的部分。通过传递clim参数给imshow来实现。当然,也可以通过调用绘图对象的set_clim()方法来完成,不过在使用Jupyter Notebook时,需确保在与绘图命令相同的单元格中执行此操作(因为Jupyter Notebook不会更改以前单元格中的绘图)。set_clim():

https://matplotlib.org/stable/api/cm_api.html#matplotlib.cm.ScalarMappable.set_clim

· 

imgplot = plt.imshow(lum_img, clim=(0.0, 0.7))

注:clim参数值(0.0, 0.7)的意思是把0.00.7按比例放大为0.01.0

  完整代码:

· 

· 

· 

· 

· 

· 

· 

ipython%matplotlib tkimport matplotlib.pyplot as pltimport matplotlib.image as mpimgimg = mpimg.imread('D:/5xstar/work/stinkbug.png')lum_img = img[:, :, 0]imgplot = plt.imshow(lum_img, clim=(0.0, 0.7))

 

  使用返回的绘图对象的set_clim()方法:

· 

· 

imgplot = plt.imshow(lum_img)imgplot.set_clim((0.0, 0.7))

  完整代码:

· 

· 

· 

· 

· 

· 

· 

· 

ipython%matplotlib tkimport matplotlib.pyplot as pltimport matplotlib.image as mpimgimg = mpimg.imread('D:/5xstar/work/stinkbug.png')lum_img = img[:, :, 0]imgplot = plt.imshow(lum_img)imgplot.set_clim((0.0, 0.7))

 

  另一个例子的完整代码:

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

· 

ipython%matplotlib tkimport matplotlib.pyplot as pltimport matplotlib.image as mpimgimg = mpimg.imread('D:/5xstar/work/stinkbug.png')lum_img = img[:, :, 0]fig = plt.figure()ax = fig.add_subplot(1, 2, 1)imgplot = plt.imshow(lum_img)ax.set_title('Before')plt.colorbar(ticks=[0.1, 0.3, 0.5, 0.7], orientation='horizontal')ax = fig.add_subplot(1, 2, 2)imgplot = plt.imshow(lum_img)imgplot.set_clim(0.0, 0.7)ax.set_title('After')plt.colorbar(ticks=[0.1, 0.3, 0.5, 0.7], orientation='horizontal')

 

数组插值方案

  插值是根据不同的数学方案计算像素应该的颜色或值。当调整图像大小时,就会发生这种情况。在图像调大的过程中,需要的像素数改变了,但得到的图像的像素没有改变,以至于像素是离散开来,造成空白的空间。插值是填充这些空间的方式。这就是为什么当把图像放大时,它有时看起来像像素化一样。当原始图像和扩展图像之间的差异较大时,这种效应更加明显。为了更好的理解,截全屏得一图像,并缩小它的尺寸,保存。这样,图像中的像素会被丢弃了,只保留了一部分。然后,重新投放到全屏上,这时,一些旧的像素已经不存在了,计算机必须想办法绘制像素来填充空间,这个方法就是插值。

  这里,用Pillow库加载图像并调整图像的大小。

· 

· 

· 

· 

from PIL import Imageimg = Image.open('D:/5xstar/work/stinkbug.png')img.thumbnail((64, 64))  # resizes image in-placeimgplot = plt.imshow(img)

  完整代码:

· 

· 

· 

· 

· 

· 

· 

ipython%matplotlib tkimport matplotlib.pyplot as pltfrom PIL import Imageimg = Image.open('D:/5xstar/work/stinkbug.png')img.thumbnail((64, 64))  # resizes image in-placeimgplot = plt.imshow(img)

 

  上图使用的是默认插值方案——双线性插值(bilinear),原因是没有向imshow()传递任何插值方案参数。imshow():

https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.imshow.html#matplotlib.pyplot.imshow

  可以试试其他的方案。下面是“nearest(最近的)方案,它没有插值:

· 

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

  完整代码:

· 

· 

· 

· 

· 

· 

· 

ipython%matplotlib tkimport matplotlib.pyplot as pltfrom PIL import Imageimg = Image.open('D:/5xstar/work/stinkbug.png')img.thumbnail((64, 64))  # resizes image in-placeimgplot = plt.imshow(img, interpolation="nearest")

 

  还有,“bicubic(双立方)”方案:

· 

imgplot = plt.imshow(img, interpolation="bicubic")

  完整代码:

· 

· 

· 

· 

· 

· 

· 

ipython%matplotlib tkimport matplotlib.pyplot as pltfrom PIL import Imageimg = Image.open('D:/5xstar/work/stinkbug.png')img.thumbnail((64, 64))  # resizes image in-placeimgplot = plt.imshow(img, interpolation="bicubic")

 

  当放大照片时,通常使用双立方插值——人们倾向于模糊而不是像素化。