1. 程式人生 > >Python matplotlib 的 Image tutorial影象處理教程

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官方教材 點選開啟連結