【火爐煉AI】機器學習047-影象的直方圖均衡化操作
(本文所使用的Python庫和版本號: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )
影象的直方圖是指影象中每一畫素範圍內畫素頻率的統計關係圖,直方圖能夠給出影象灰度範圍,每個灰度的頻度和灰度的分佈,整幅圖的平均明暗,對比度等概貌性描述。灰度直方圖是灰度級的函式,反映的是影象中具有該灰度級畫素的個數。如果大部分畫素都集中在低灰度區域,影象會呈現暗的特性,反之,如果大部分影象都集中在高灰度區域,影象呈現出亮的特性。
直方圖均衡化是指,將隨機分佈的影象直方圖修改成均勻分佈的直方圖,基本思想是對原始影象的畫素灰度做某種對映變換,使得變換後的影象灰度的概率密度呈均勻分佈,這就意味著影象灰度的動態範圍得到擴大,提高了影象的對比度。
1. 獲取影象直方圖
影象直方圖有灰度直方圖和彩色直方圖的區別,如果輸入影象是灰度圖,則得到灰度直方圖,如果輸入影象是BGR影象,得到的則是某個顏色通道的直方圖。
# 獲取灰度直方圖 gray_hist=cv2.calcHist([gray], [0], None, [256], [0, 256]) plt.plot(gray_hist) 複製程式碼

取得影象的灰度直方圖,只需要呼叫cv2.calcHist()函式即可,這個函式的引數為:
第一個引數為輸入的影象,可以是灰度圖也可以是彩色圖。
第二個引數是用於計算直方圖的通道,這裡使用灰度圖計算直方圖,所以就直接使用第一個通道;
第三個引數是Mask,這裡沒有使用,所以用None。
第四個引數是histSize,表示這個直方圖分成多少份(即多少個直方柱)。
第五個引數是表示直方圖中各個畫素的值,[0.0, 256.0]表示直方圖能表示畫素值從0.0到256的畫素。
最後是兩個可選引數,由於直方圖作為函式結果返回,所以第六個hist就沒有意義了(待確定)
最後一個accumulate是一個布林值,用來表示直方圖是否疊加。
# 獲取彩色圖的各個通道直方圖 hist_B=cv2.calcHist([img],[0],None,[256],[0,256]) plt.plot(hist_B,'b',label='B') # Blue color hist_G=cv2.calcHist([img],[1],None,[256],[0,256]) plt.plot(hist_G,'g',label='G')# green color hist_R=cv2.calcHist([img],[2],None,[256],[0,256]) plt.plot(hist_R,'r',label='R')# red color plt.title('histogram of Color Chanel') plt.legend() 複製程式碼

2. 直方圖均衡化
2.1 灰度圖的直方圖均衡化
為了方便對比,我將直方圖均衡化前後的影象都繪製到同一個圖片中。如下:
# 灰度圖的直方圖均衡化: # 先顯示均衡化前後的影象 plt.figure(12,figsize=(15,30)) plt.subplot(121) plt.imshow(gray,cmap='gray') plt.title('GrayImg before Equalization') equalize = cv2.equalizeHist(gray) plt.subplot(122) plt.imshow(equalize,cmap='gray') plt.title('GrayImg after Equalization') 複製程式碼

plt.plot(gray_hist,c='b',label='raw_Hist') gray_equalized_hist=cv2.calcHist([equalize], [0], None, [256], [0, 256]) plt.plot(gray_equalized_hist,c='r',label='Equalized') plt.legend() plt.title('Histogram comparison') 複製程式碼

話說,經過直方圖均衡化之後的直方圖怎麼長的這麼醜?
直方圖均衡化只需要一個函式cv2.equalizeHist()即可,但是需要注意:cv2.equalizeHist()只提供灰度值圖片的處理,當把上面的圖片換成RGB圖片時,就會報錯了。
2.2 彩色圖的直方圖均衡化
彩色圖的直方圖均衡化需要藉助YUV空間,如下程式碼:
# 彩色直方圖均衡化需要藉助YUV空間 img_yuv = cv2.cvtColor(img, cv2.COLOR_BGR2YUV) img_yuv[:,:,0] = cv2.equalizeHist(img_yuv[:,:,0]) img_histeq = cv2.cvtColor(img_yuv, cv2.COLOR_YUV2BGR) # 顯示均衡化前後的影象 plt.figure(12,figsize=(15,30)) plt.subplot(121) img_rgb=cv2.cvtColor(img,cv2.COLOR_BGR2RGB) plt.imshow(img_rgb) plt.title('ColorImg before Equalization') plt.subplot(122) img_hist_rgb=cv2.cvtColor(img_histeq,cv2.COLOR_BGR2RGB) plt.imshow(img_hist_rgb) plt.title('ColorImg after Equalization') 複製程式碼

# 顯示均衡化前後的直方圖情況 plt.figure(12) plt.subplot(121) hist_B=cv2.calcHist([img],[0],None,[256],[0,256]) plt.plot(hist_B,'b',label='B') # Blue color hist_G=cv2.calcHist([img],[1],None,[256],[0,256]) plt.plot(hist_G,'g',label='G')# green color hist_R=cv2.calcHist([img],[2],None,[256],[0,256]) plt.plot(hist_R,'r',label='R')# red color plt.title('Color Histogram before Equalization') plt.legend() plt.subplot(122) hist_B=cv2.calcHist([img_histeq],[0],None,[256],[0,256]) plt.plot(hist_B,'b',label='B') # Blue color hist_G=cv2.calcHist([img_histeq],[1],None,[256],[0,256]) plt.plot(hist_G,'g',label='G')# green color hist_R=cv2.calcHist([img_histeq],[2],None,[256],[0,256]) plt.plot(hist_R,'r',label='R')# red color plt.title('Color Histogram after Equalization') plt.legend() 複製程式碼

同樣的,經過對比可以看出,經過直方圖均衡化之後的影象直方圖都比較醜。。。。
########################小**********結###############################
1,對於影象直方圖進行操作可以比較明顯的改變影象的對比度和明暗度。
2,使用cv2.equalizeHist函式可以直接改變灰度圖的直方圖,但是卻不能直接改變彩色圖的直方圖,對於彩色圖如果想要均衡化,需要先轉變到YUV空間再進行轉換。
#################################################################
注:本部分程式碼已經全部上傳到( ofollow,noindex"> 我的github )上,歡迎下載。
參考資料:
1, Python機器學習經典例項,Prateek Joshi著,陶俊傑,陳小莉譯