1. 程式人生 > 其它 >Python OpenCV 影象處理之影象直方圖,取經之旅第 23 天

Python OpenCV 影象處理之影象直方圖,取經之旅第 23 天

基礎知識鋪墊
截止到本篇部落格,已經第二次聽到直方圖這個概念了,有必要將其搞懂。
影象直方圖(histogram)是影象統計學特徵,用來統計畫素值出現的頻次,常用在分析影象的基本特徵。
建立直方圖一般分為兩個步驟:
統計資料
繪製直方圖
直方圖的定義
橫座標:影象中各個畫素點的灰度級
縱座標:該灰度級的畫素個數
繪製直方圖需要 matplotlib 庫,這個需要自行安裝一下。
matplotlib 中 pyplot 繪製直方圖
在 pyplot 中提供了域名交易一個繪製直方圖的函式,名稱為 hist。
函式原型介紹
matplotlib.pyplot.hist() 函式原型如下
(n, bins, patches)=matplotlib.pyplot.hist(x, bins=None, range=None, density=None, weights=None,

cumulative=False, bottom=None, histtype=‘bar’, align=‘mid’, orientation=‘vertical’,
rwidth=None, log=False, color=None, label=None, stacked=False, normed=None, *, data=None, **kwargs)
引數非常多,實際應用中只需掌握幾個重要引數。

n, bins, patches = plt.hist(data)
plt.show()
其中,np.random.normal(0,1,10000) 函式說明如下,np.random.normal() 是一個正態分佈,normal這裡是正態的意思。

該函式原型為:
numpy.random.normal(loc=0.0, scale=1.0, size=None)
引數說明如下:
loc:概率分佈的均值,對應著整個分佈的中心 center
scale:概率分佈的標準差,對應於分佈的寬度,scale 越大,越矮胖,scale 越小,越瘦高
size:資料型別為 int or tuple of ints, 輸出的 shape,預設為 None,只輸出一個值
其實該函式的目的就是,輸出為高斯分佈的一組數或一個值。
簡單案例:
data = np.random.normal(loc=0, scale=1, size=2)print(data)
繼續回顧 matplotlib.pyplot.hist() 函式的相關引數(官網說明):
只選取其中比較重要的幾個引數如下:
x:(n,) array or sequence of (n,) arrays
指定要繪製直方圖的資料,必須是一維陣列.使用.ravel()將你的通道值轉為一維陣列
bins:integer or sequence or ‘auto’, optional
指定直方圖條形的個數,integer 或 auto,也可以不設定.舉例[1,2,3,4],則第一個柱為取值[1,2),一次類推,最後一個是取值[3,4].預設 taken from the rcParam hist.bins.
range:tuple or None, optional
陣列或者不給.給出陣列將指定直方圖資料的上下界,超出範圍的捨棄.不設定的話包含繪圖資料的最大值和最小值;預設為 None
基於上述內容,將一副影象的直方圖顯示出來。
做一些準備工作
x: 影象,必須是一維陣列
其中函式 ravel b = a.ravel()
功能: 將多維陣列降為一維陣列
格式: 一維陣列=多維陣列.revel()
bins: 一般是 256,指[0, 255]
以上內容掌握之後,就可以處理影象的直方圖了,程式碼如下:
import cv2from matplotlib import pyplot as plt

def plot_demo(image):
# numpy 的 ravel 函式功能是將多維陣列降為一維陣列
plt.hist(image.ravel(), 256, [0, 256])
plt.show()

if name == “main”:
img = cv2.imread("./106.jpg")
cv2.namedWindow(“input image”, cv2.WINDOW_AUTOSIZE)
cv2.imshow(“input image”, img)
plot_demo(img)

cv2.waitKey(0)
cv2.destroyAllWindows()

函式原型介紹
在 Python OpenCV 中實現直方圖的函式為cv2.calcHist,原型如下:

channels:選取影象的哪個通道,用方括號給出的,計算直方圖的 channel 的索引,如果輸入時灰度圖,值就是 [0],對於彩色圖片,你可以傳 [0] ,[1] 和 [2] 來分別計算藍色,綠色和紅色通道的直方圖;
mask:掩膜,如果要找整個影象的直方圖,這裡傳入"None"。如果你想找到特定區域圖片的直方圖,需要使用掩膜,只計算值>0 的位置上畫素的顏色直方圖
histSize:直方圖大小,BINS 數量(BINS 是啥,下面細說),要方括號傳入,對於全刻度,傳入 [256]
ranges:直方圖範圍,一般來說是[0,256]
關於上文提及的 BINS 等內容涉及直方圖如下概念:
BINS: 在上面的直方圖當中,如果畫素值是 0 到 255,則需要 256 個值來顯示直方圖。
但是,如果不需要知道每個畫素值的畫素數目,只想知道兩個畫素值範圍內的畫素點數目即可?首先畫素值在 0–15 之間的畫素點數目,然後是 16–31 ……直到 240–255,即每次間隔 16 個數字,將 256 個值分成 16 份,每份計算綜合。每個分成的小組就是一個 BIN(箱)。在 opencv 中使用 histSize 表示 BINS。
彩色影象,不同通道的直方圖
首先繪製藍色通道的直方圖,程式碼如下:
import cv2 as cvimport numpy as npfrom matplotlib import pyplot as plt

img = cv.imread(’./106.jpg’)
hist = cv.calcHist([img], [0], None, [256], [0,256])

plt.plot(hist, label=‘B’, color=‘b’)
plt.show()