一、學習目標
- 了解matplotlib繪圖庫的使用
- 了解如何通過折線圖或者直方圖對圖表進行繪制
- 了解了通過圖標對圖片內容進行直觀判斷
如有錯誤歡迎指出~
二、了解圖像直方圖及其應用
2.1 了解matplotlib庫
在了解圖像直方圖前我們需要了解一個matplotlib庫,matplotlib庫和numpy可謂是一對好伴侶,就像泡面伴侶火腿腸一樣。
matplotlib是一個繪圖庫,我們將通過matplotlib繪制圖像的直方圖。為什么圖像可以繪制直方圖呢?我們可以想一下,圖像是由一堆數據組成,既然是數據那就可以對這個圖像進行可視化的圖標操作。
首先,我們需要安裝matplotlib。使用pip工具可以直接安裝matplotlib。安裝命令為:
pip install matplotlib
安裝完matplotlib后,可以在python的交互窗口中對其進行引入,若沒問題那就肯定是安裝好了:
from matplotlib import pyplot as plt
我們先簡單了解一下matplotlib 的使用方法,查看以下示例:
from matplotlib import pyplot as pltx = [0, 5, 8, 13]
y = [2, 1, 1, 3]print(x)
print(y)
plt.title("Matplotlib")
plt.xlabel("x")
plt.ylabel("y")
plt.plot(x,y)
plt.show()
首先引入進行引入,隨后定義了x和y兩個列表,這兩個列表對應的是折線圖中x和y的兩個繪制點,其中x列表是當前坐標系中x的值,y列表則表示y坐標系的值。x列表和y列表相互對應,x[0]與y[0]構成一個坐標點,如x[0]與y[0]則表示(0,2),依次下去則是(5,1)、(8,1);隨后使用plt.title設置折線圖標題,plt.xlabel設置x標簽、plt.ylabel設置y標簽,再繼續使用plot傳入x和y的值,最后使用show方法進行展示。結果如下:
以上是一個Matplotlib折線圖的基本用法,接下來我們開始正式的編寫有關圖像直方圖的內容。
2.2 繪制圖像直方圖
圖像直方圖表示了一張圖像像素的分布,對像素進行了統計,方便與直觀的以圖的形式對圖片進行分析。一般橫坐標表示圖像像素的不同值,或者說不同的種類,縱坐標則表示了每一種顏色的個數或者百分比。直方圖用這種表現方式顯示圖像的基本內容特征方便接下來對圖像進行進行下一步的操作。一般直方圖的表示是越靠近左側縱坐標則表示當前圖像的偏暗點數據分布,越靠近右側則表示圖像偏亮的像素點分布情況。
繪制圖像直方圖需要使用一個直方圖方法hist方法,我們一般使用前兩個參數;第一個參數為一維數組,第二個參數為需要多少個間隔。現在我們先讀取一張圖片:
import cv2
import numpy as npfrom matplotlib import pyplot as pltimg = cv2.imread(r'C:\Users\mx\Desktop\1.jpg')
cv2.namedWindow("Image",cv2.WINDOW_NORMAL)
cv2.destroyWindow("Image")
cv2.imshow("Image", img)
隨后使用hist方法,使用hist方法時由于img是一個三通道的數據,那如何轉為一維數據呢?很簡單,有一個ravel方法很方便的對img數據進行轉變:
img.ravel()
隨后將該數據傳入至hist方法中:
plt.hist(img.ravel(), 256)
以上代碼中,256是表示一共分為256個數據去顯示其中的內容。最后添加show方法以及等待圖像關閉的代碼,完整代碼如下:
import cv2
import numpy as npfrom matplotlib import pyplot as pltimg = cv2.imread(r'C:\Users\mx\Desktop\1.jpg')
cv2.namedWindow("Image",cv2.WINDOW_NORMAL)
cv2.destroyWindow("Image")
cv2.imshow("Image", img)plt.hist(img.ravel(), 256)
plt.show()cv2.waitKey (0)
cv2.destroyAllWindows()
運行代碼結果如下:
由于我們這張圖片是整體偏亮的,所以數據的分布都在右側,左側分布較少。這張圖片如下:
也可以把第二個參數改為100,這樣每次分段就是一半了:
plt.hist(img.ravel(), 100)
效果如下:
hist的第三個參數是統計范圍,你需要直方圖顯示哪個范圍內的數據,例如[0,100],這時就可以寫成:
plt.hist(img.ravel(), 100,[0,100])
運行結果如下:
左邊縱坐標數據則是個數,橫坐標x是0逐漸增大,也就構成了一種越靠近左側越黑,越靠近右側越亮的這一種分布情況。我們也可以將以上的0到100范圍改成0-256,這時即可恢復原樣:
plt.hist(img.ravel(), 256,[0,256])
2.3 3通道折線圖繪制
以上只繪制了一個完整圖像的直方圖,現在我們來試一下繪制3個通道RGB的直方圖圖像。
繪制3通道的折線圖使用一個方法可以很簡便的進行繪制,那就是calcHist,calcHist可以通過你給的通道數、灰度范圍、像素值范圍可以獲取圖像的通道信息,也可以加入mask遮罩提取圖像。
由于同一個直方圖或者折線圖中,使用同一種顏色繪制會分辨不清,我們可以通過三原色的紅綠藍分別繪制3跟不同顏色的線段進行表示。這里使用折線圖首先進行圖像繪制。
首先我們定義一個列表,存儲紅綠藍三原色字符串,方便之后的繪圖時傳入色彩:
color = ["blue", "green", "red"]
隨后使用一個for循環,不過需要將color傳入enumerate中,enumerate將會給予出兩個值,一個是下標一個是值,那么這個時候就需要有兩個變量接收,for循環可以寫成:
for i, v in enumerate(color):
隨后使用calcHist方法,并且傳入5個值:
hist = cv2.calcHist([img], [i], None, [256], [0, 256])
值必須使用方括號傳入,這是語法規定,若不使用你可能會出錯。第一個值img是圖像數據,第二個值i,由于每次都會循環作為下標,那么就是0、1、2、3這3個數據,這3個數據傳入到calcHist后將會拿出紅綠藍三個不同的通道值。第三位填入NONE,因為我們不需要遮罩。然后[256]是一個灰度的范圍空間,[0,256]表示像素的范圍值。這時每次循環hist都將會是不同通道的值內容,這個時候就可以使用plot進行折線畫圖,并且傳入顏色值,繪制不同顏色的線段:
plt.plot(hist, color=v)
組后show圖片,完整代碼如下:
import cv2
import numpy as npfrom matplotlib import pyplot as pltimg = cv2.imread(r'C:\Users\mx\Desktop\1.jpg')
cv2.namedWindow("Image",cv2.WINDOW_NORMAL)
cv2.destroyWindow("Image")
cv2.imshow("Image", img)
color = ["blue", "green", "red"]
for i, v in enumerate(color):hist = cv2.calcHist([img], [i], None, [256], [0, 256])plt.plot(hist, color=v)plt.show()
cv2.waitKey (0)
cv2.destroyAllWindows()
結果如下:
該系列首發于ebaina
三、總結
- 了解matplotlib對折線圖、直方圖的繪圖方法
- 了解了matplotlib繪制的圖標左側偏暗右側偏亮的特性