該系列文章是講解Python OpenCV圖像處理知識,前期主要講解圖像入門、OpenCV基礎用法,中期講解圖像處理的各種算法,包括圖像銳化算子、圖像增強技術、圖像分割等,後期結合深度學習研究圖像識別、圖像分類、目標檢測應用。
前一篇文章介紹OpenCV實現圖像形態學變換,包括圖像頂帽運算和圖像黑帽運算。本篇文章主要講解灰度直方圖的基本概念,Python調用OpenCV實現繪製圖像直方圖,基礎性知識希望對您有所幫助。
一.灰度直方圖基本概率
二.繪製直方圖
三.使用OpenCV統計繪製直方圖
四.總結
文章參考自己以前系列圖像處理文章及OpenCV庫函數,同時部分參考網易雲lilizong老師的視頻,推薦大家去學習。同時,本篇文章涉及到《計算機圖形學》基礎知識,請大家下來補充。該系列在github所有源代碼:
https://github.com/eastmountyxz/ImageProcessing-Python
前文回顧(下面的超鏈接可以點擊喔):
[Python圖像處理] 一.圖像處理基礎知識及OpenCV入門函數
[Python圖像處理] 二.OpenCV+Numpy庫讀取與修改像素
[Python圖像處理] 三.獲取圖像屬性、興趣ROI區域及通道處理
[Python圖像處理] 四.圖像平滑之均值濾波、方框濾波、高斯濾波、中值濾波及雙邊濾波
[Python圖像處理] 五.圖像融合、加法運算及圖像類型轉換
[Python圖像處理] 六.圖像縮放、圖像旋轉、圖像翻轉與圖像平移
[Python圖像處理] 七.圖像閾值化處理及民族服飾實驗對比
[Python圖像處理] 八.圖像腐蝕與圖像膨脹
[Python圖像處理] 九.形態學之圖像開運算、閉運算、梯度運算
[Python圖像處理] 十.形態學之圖像頂帽運算和黑帽運算
[Python圖像處理] 十一.灰度直方圖概念及OpenCV繪製直方圖
學Python近八年,認識了很多大佬和朋友,感恩。深知自己很菜,得拼命努力前行,編程也沒有什麼捷徑,干就對了。希望未來能更透徹學習和撰寫文章,同時非常感謝參考文獻中的大佬們的文章和分享,共勉。
- https://blog.csdn.net/eastmount
一. 灰度直方圖基本概念
什麼是灰度直方圖?灰度直方圖(histogram)是灰度級的函數,描述的是圖像中每種灰度級像素的個數,反映圖像中每種灰度出現的頻率。橫坐標是灰度級,縱坐標是灰度級出現的頻率。

對於連續圖像,平滑地從中心的高灰度級變化到邊緣的低灰度級。直方圖定義為:

其中A(D)為閾值面積函數:為一幅連續圖像中被具有灰度級D的所有輪廓線所包圍的面積。對於離散函數,固定ΔD為1,則:H(D)=A(D)-A(D+1)。
色彩直方圖是高維直方圖的特例,它統計色彩的出現頻率,即色彩概率分布信息。通常這需要一定的量化過程,將色彩分成若干互不重疊的種類。一般不直接在RGB色彩空間中統計,而是在將亮度分離出來後,對代表色彩部分的信息進行統計,如在HSI空間的HS子空間、YUV空間的UV子空間,以及其它反映人類視覺特點的彩色空間表示中進行。
直方圖的計算方法如下:依據定義,若圖像具有L(通常L=256,即8位灰度級)級灰度,則大小為MxN的灰度圖像f(x,y)的灰度直方圖hist[0…L-1]可用如下計算獲得。
初始化 hist[k]=0; k=0,…,L-1
統計 hist[f(x,y)]++; x=0,…,M-1, y =0,…,N-1
歸一化 hist[f(x,y)]/=M*N
那麼說了這麼多,直方圖究竟有什麼作用呢?在使用輪廓線確定物體邊界時,通過直方圖更好的選擇邊界閾值,進行閾值化處理;對物體與背景有較強對比的景物的分割特別有用;簡單物體的面積和綜合光密度IOD可以通過圖像的直方圖求得。
二. 繪製直方圖
1.基礎概念在直方圖中,橫坐標表示圖像中各個像素點的灰度級,縱坐標表示具有該灰度級的像素個數。

假設存在一個3*3的圖像,如下圖所示,x數組統計的是像素點的灰度級,y數組統計的是具有該灰度級的像素個數。其中,灰度為1的像素共3個,灰度為2的像素共1個,灰度為3的像素共2個,灰度為4的像素共1個,灰度為5的像素共2個。
x = [1, 2, 3, 4, 5]
y = [3, 1, 2, 1, 2]
繪製的折線圖如下所示:

繪製的直方圖如下所示:

如果灰度級為0-255(最小值0黑色,最大值255白色),同樣可以繪製對應的直方圖,下圖是三張圖片拼接而成及其對應的直方圖。

2.歸一化直方圖該直方圖的橫坐標表示圖像中各個像素點的灰度級,縱坐標表示出現這個灰度級的概率。其計算方法如下:(1) 先計算灰度級及對應像素的個數x = [1, 2, 3, 4, 5]t = [3, 1, 2, 1, 2]
(2) 統計總的像素個數n = (3 + 1 + 2 + 1 +2) = 9
(3) 統計各個灰度級的出現概率y = t / n = [3/9, 1/9, 2/9, 1/9, 2/9]

3.繪製直方圖主要調用matplotlib的子庫pyplot實現,它提供了類似於Matlab的繪圖框架,matplotlib是非常強大基礎的一個Python繪圖包。Provides a Matlab-like plotting framework. 導入代碼如下:
import matplotlib.pyplot as plt
其中繪製直方圖主要調用hist函數實現,它根據數據源和像素級繪製直方圖。函數原型如下:
hist(數據源, 像素級)參數:數據源必須是一維數組,通常需要通過函數ravel()拉直圖像像素級一般是256,表示[0, 255]
函數ravel()將多維數組降為一維數組,格式為:一維數組 = 多維數組.ravel()

4.代碼實現
#encoding:utf-8import cv2 import numpy as npimport matplotlib.pyplot as pltsrc = cv2.imread('test01.jpg')cv2.imshow("src", src)cv2.waitKey(0)cv2.destroyAllWindows()plt.hist(src.ravel(), 256)plt.show()
輸出結果如下所示:


三. 使用OpenCV統計繪製直方圖
1.函數原型前面講解調用matplotlib庫繪製直方圖,接下來講解使用OpenCV統計繪製直方圖的例子。
直方圖橫坐標:圖像中各個像素點的灰度級
直方圖縱坐標:具有該灰度級的像素個數

主要調用函數calcHist()實現:
hist = cv2.calcHist(images, channels, mask, histSize, ranges, accumulate)
參數:
hist表示直方圖,返回的是一個二維數組
images表示原始圖像
channels表示指定通道,通道編號需要用中括號括起,輸入圖像是灰度圖像時,它的值為[0],彩色圖像則為[0]、[1]、[2],分別表示B、G、R
mask表示掩碼圖像,統計整副圖像的直方圖,設為None,統計圖像的某一部分直方圖時,需要掩碼圖像
histSize表示BINS的數量,參數子集的數目,如下圖當bins=3表示三個灰度級


ranges表示像素值範圍,例如[0, 255]
accumulate表示累計疊加標識,默認為false,如果被設置為true,則直方圖在開始分配時不會被清零,該參數允許從多個對象中計算單個直方圖,或者用於實時更新直方圖;多個直方圖的累積結果用於對一組圖像的直方圖計算

2.代碼實現首先計算圖像灰度級的基本大小、形狀及內容。
#encoding:utf-8import cv2 import numpy as npimport matplotlib.pyplot as pltsrc = cv2.imread('test01.jpg')#參數:原圖像 通道[0]-B 掩碼 BINS為256 像素範圍0-255 hist = cv2.calcHist([src], [0], None, [256], [0,255])print(type(hist))print(hist.size)print(hist.shape)print(hist)
輸出結果如下所示:

下面是繪製圖像的代碼,首先補充一些matplotlib庫繪製圖像代碼,也推薦我的文章。
六.Numpy、Pandas和Matplotlib包基礎知識
#encoding:utf-8import cv2 import numpy as npimport matplotlib.pyplot as plt#繪製sin函數曲線x1 = np.arange(0, 6, 0.1)y1 = np.sin(x1)plt.plot(x1, y1)#繪製坐標點折現x2 = [0, 1, 2, 3, 4, 5, 6]y2 = [0.3, 0.4, 2.5, 3.4, 4, 5.8, 7.2]plt.plot(x2, y2)#省略有規則遞增的x2參數 y3 = [0, 0.5, 1.5, 2.4, 4.6, 8]plt.plot(y3, color="r")plt.show()
輸出結果有三條線,如下所示:

最後給出調用calcHist()計算B、G、R灰度級並繪製圖形的代碼。
#encoding:utf-8import cv2 import numpy as npimport matplotlib.pyplot as pltsrc = cv2.imread('test01.jpg')histb = cv2.calcHist([src], [0], None, [256], [0,255])histg = cv2.calcHist([src], [1], None, [256], [0,255])histr = cv2.calcHist([src], [2], None, [256], [0,255])cv2.imshow("src", src)cv2.waitKey(0)cv2.destroyAllWindows()plt.plot(histb, color='b')plt.plot(histg, color='g')plt.plot(histr, color='r')plt.show()
輸出結果如下圖所示:


四.總結
寫到這裡,本篇文章介紹結束,基礎性知識希望對您有所幫助。
一.灰度直方圖基本概率
二.繪製直方圖
三.使用OpenCV統計繪製直方圖
四.總結
這系列文章是當時2018年考博期間撰寫的,感覺還不錯。同時,回想2018年當時寫這篇文章的感言,挺有意思的,每個階段都有每個階段的感受,並不斷激勵自己進步。
三尺講台,三寸舌,三千桃李,三杆筆。再累再苦,站在講台前就是最美的自己,幾個月的煩惱和憂愁都已消失,真的好享受這種狀態,仿佛散着光芒,終於給低年級的同學上課了越早培養編程興趣越好,恨不能傾囊相授。即使當一輩子的教書匠,平平淡淡也喜歡,而且總感覺給學生講課遠不是課酬和職稱所能比擬,這就是所謂的事業,所謂的愛好。
源代碼下載地址,記得幫忙點star和關注喔!
https://github.com/eastmountyxz/
ImageProcessing-Python
「娜璋AI安全之家」 主要圍繞Python大數據分析、網絡空間安全、人工智能、Web滲透及攻防技術進行講解,同時分享CCF、SCI、南核北核論文的算法實現。娜璋之家會更加系統,並重構作者的所有文章,從零講解Python和安全,寫了近十年文章,真心想把自己所學所感所做分享出來,還請各位多多指教,真誠邀請您的關注!謝謝。
(By:Eastmount 2022-05-10夜於武漢)
參考文獻,在此感謝這些大佬,共勉!
[1] 岡薩雷斯. 數字圖像處理(第3版)[M]. 電子工業出版社, 2013.
[2] 羅子江. Python中的圖像處理[M]. 科學出版社, 2020.
[3] https://blog.csdn.net/Eastmount
[4]《計算機圖形學》基礎知識
[5] 部分內容參考網易雲lilizong老師的視頻