01 導入Matplotlib
如果你安裝了完整的Python Anaconda,那麼你已經安裝了Matplotlib,可以開始了。否則,你可能要訪問官網獲取安裝說明。
http://matplotlib.org
就像我們用縮寫np來表示NumPy一樣,我們也會用一些標準的縮寫來表示Matplotlib導入:
import matplotlib as mpl import matplotlib.pyplot as plt
plt是我們最常用的一個接口。
02 生成一個簡單的圖形
言歸正傳,讓我們創建第一個圖形。
假設我們要繪製正弦函數sin(x)的一個簡單線圖。我們希望函數求x軸(0≤x≤10)上的所有值。我們將使用NumPy的linspace函數在x軸上創建一個線性空間,x值從0到10,共100個樣本點:
import numpy as np x = np.linspace(0, 10, 100)
我們可以使用NumPy的sin函數求sin函數的所有x值,並通過調用plt的plot函數可視化結果:
plt.plot(x, np.sin(x))
你親自試過了嗎?發生什麼了?有什麼發現嗎?
問題是,這取決於你在何處運行這個腳本,你可能什麼都看不到。以下是可以考慮的可能性:
1. 從.py腳本繪圖
如果你正從一個腳本運行matplotlib,那麼你只需要調用plt,如下所示:
plt.show()
調用後,圖形就會顯示出來!
2. 從IPython shell繪圖
這實際上是以交互方式運行matplotlib的最便捷的方式之一。要顯示繪圖,你需要在啟動IPython之後,調用%matplotlib魔術命令:
%matplotlib Using matplotlib backend: Qt5Agg import matplotlib.pyplot as plt
然後,所有圖都會自動顯示出來,不必每次都調用plt.show()。
3. 從Jupyter Notebook繪圖
如果你從基於瀏覽器的Jupyter Notebook上查看這段代碼,你需要使用同樣的%matplotlib魔術命令。可是,你還可以選擇將圖形直接嵌入notebook中,這有兩種可能的結果:
%matplotlib notebook將生成的交互式圖嵌入notebook中。 %matplotlib inline將生成的靜態圖嵌入notebook中。
我們通常會選擇內聯選項:
%matplotlib inline
現在,讓我們再試一次:
plt.plot(x, np.sin(x))
上述命令給出的輸出如圖2-4所示。
▲圖2-4 應用內聯選項生成的圖
稍後,如果你想保存圖表,可以直接從IPython或Jupyter Notebook的選項中保存:
plt.savefig('figures/02.03-sine.png')
只要保證使用所支持的文件後綴即可,例如.jpg、.png、.tif、.svg、.eps或者.pdf。
在導入matplotlib之後,運行plt.style.use(style_name),你可以更改繪圖的樣式。在plt.style.available中列出了所有可用的樣式。例如,試試plt.style.use('fivethirtyeight')、plt.style.use('ggplot')或者plt.style.use('seaborn-dark')。為了增加樂趣,可以運行plt.xkcd(),再嘗試繪製其他內容。
03 可視化外部數據集的數據
作為本文的最後一個測試,讓我們可視化一些來自外部數據集的數據,例如scikit-learn的digits數據集。
具體來說,我們將需要3個可視化工具:
用於實際數據的scikit-learn 用於數據處理的NumPy Matplotlib
首先,讓我們導入所有這些可視化工具:
import numpy as np from sklearn import datasets import matplotlib.pyplot as plt %matplotlib inline
第一步是實際加載數據:
digits = datasets.load_digits()
如果我們沒有記錯的話,digits應該有2個不同的欄位:一個是data欄位,包含實際的圖像數據;另一個是target欄位,包含圖像標籤。
與其相信我們的記憶,不如讓我們研究一下digits對象。這通過輸入欄位名稱、添加句點、再按下Tab鍵—digits.來實現。這會顯示出digits對象還包含了一些其他欄位,例如一個名為images的欄位。images和data這2個欄位似乎只是形狀不同:
print(digits.data.shape) print(digits.images.shape)
輸出結果:
(1797, 64) (1797, 8, 8)
在這兩個例子中,第一維都對應於數據集中的圖像數。但是data將所有像素排列在一個大的向量中,而images則保留了每個圖像的8×8空間排列。
因此,如果我們想繪製單張圖像,images欄位可能更合適。首先,使用NumPy的數組切割,從數據集中抓取一張圖像:
img = digits.images[0, :, :]
這裡,我們說想要抓取長為1797項的數組中的第一行,以及所有對應的8×8=64個像素。然後,我們可以使用plt的imshow函數繪製圖像:
plt.imshow(img, cmap='gray') plt.savefig('figures/02.04-digit0.png')
上述命令給出的輸出如圖2-5所示。請注意,圖像是模糊的,因為我們將該圖像調整到了更大的尺寸。原始圖像的大小只有8×8。
▲圖2-5 生成單張圖像的示例結果
此外,我們還可以使用cmap參數指定一個彩圖。在默認情況下,Matplotlib使用MATLAB的默認彩圖jet。可是,對於灰度圖像,gray彩圖更有意義。
最後,我們可以利用plt的subplot函數繪製一組數字樣本。subplot函數與在MATLAB中一樣,我們指定行數、列數以及當前子圖的索引(從1開始)。我們將使用一個for循環遍歷數據集中的前10個圖像,每個圖像都有自己的子圖:
plt.figure(figsize=(14, 4)) for image_index in range(10): # images are 0-indexed, subplots are 1-indexed subplot_index = image_index + 1 plt.subplot(2, 5, subplot_index) plt.imshow(digits.images[image_index, :, :], cmap='gray')
生成的輸出如圖2-6所示。
▲圖2-6 生成包含10個數字的一組子圖
對於各種數據集,另一個很好的資源是本書作者麥可·貝耶勒的母校加州大學歐文分校的機器學習資源庫:
http://archive.ics.uci.edu/ml/index.php
關於作者:阿迪蒂亞·夏爾馬(Aditya Sharma),羅伯特·博世(Robert Bosch)公司的一名高級工程師,致力於解決真實世界的自動計算機視覺問題。曾獲得羅伯特·博世公司2019年人工智慧編程馬拉松的首名。
維什韋什·拉維·什裡馬利(Vishwesh Ravi Shrimali),於2018年畢業於彼拉尼博拉理工學院(BITS Pilani)機械工程專業。此後一直在BigVision LLC從事深度學習和計算機視覺方面的工作,還參與了官方OpenCV課程的創建。
麥可·貝耶勒(Michael Beyeler),是華盛頓大學神經工程和數據科學的博士後研究員,致力於仿生視覺的計算模型研究,以為盲人植入人工視網膜(仿生眼睛),改善盲人的感知體驗。他的工作屬於神經科學、計算機工程、計算機視覺和機器學習的交叉領域。
本文摘編自《機器學習:使用OpenCV、Python和scikit-learn進行智能圖像處理(原書第2版)》,經出版方授權發布。