直方圖均衡化

直方圖均衡化

想象一下,如果一副圖像中的大多是像素點(diǎn)的像素值都集中在一個(gè)像素值范圍之內(nèi)會(huì)怎樣呢?例如,如果一幅圖片整體很亮,那所有的像素值應(yīng)該都會(huì)很高。但是一副高質(zhì)量的圖像的像素值分布應(yīng)該很廣泛。所以你應(yīng)該把它的直方圖做一個(gè)橫向拉伸(如下圖),這就是直方圖均衡化要做的事情。通常情況下,這種操作會(huì)改善圖像的對比度。

直方圖均衡.jpg

這種方法通常用來增加許多圖像的全局對比度,尤其是當(dāng)圖像的有用數(shù)據(jù)的對比度相當(dāng)接近的時(shí)候。通過這種方法,亮度可以更好地在直方圖上分布。這樣就可以用于增強(qiáng)局部的對比度而不影響整體的對比度,直方圖均衡化通過有效地?cái)U(kuò)展常用的亮度來實(shí)現(xiàn)這種功能。

這種方法對于背景和前景都太亮或者太暗的圖像非常有用,這種方法尤其是可以帶來X光圖像中更好的骨骼結(jié)構(gòu)顯示以及曝光過度或者曝光不足照片中更好的細(xì)節(jié)。這種方法的一個(gè)主要優(yōu)勢是它是一個(gè)相當(dāng)直觀的技術(shù)并且是可逆操作,如果已知均衡化函數(shù),那么就可以恢復(fù)原始的直方圖,并且計(jì)算量也不大。這種方法的一個(gè)缺點(diǎn)是它對處理的數(shù)據(jù)不加選擇,它可能會(huì)增加背景噪聲的對比度并且降低有用信號(hào)的對比度。

我們先來看看相應(yīng)的直方圖和累積直方圖,然后使用 OpenCV 進(jìn)行直方圖均衡化。

def img_show(name,image):
    """matplotlib圖像顯示函數(shù)
    name:字符串,圖像標(biāo)題
    img:numpy.ndarray,圖像
    """
    if len(image.shape) == 3:
        image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
    plt.imshow(image,'gray')
    plt.xticks([])
    plt.yticks([])
    plt.xlabel(name,fontproperties='FangSong',fontsize=12)
    
if __name__=="__main__":

    img = cv2.imread("data/Unequalized.jpg",0)
    hist,bins = np.histogram(img.flatten(),256,[0,256])
    #print(hist)
    
    #查看累積直方圖
    cdf = hist.cumsum()
    cdf_normalized = cdf*hist.max() / cdf.max()
    #print(cdf_normalized)
    
    #均衡化
    equ = cv2.equalizeHist(img)
    
    hist1,bins1 = np.histogram(equ.flatten(),256,[0,256])
    #print(hist)
    
    #查看均衡化后的累積直方圖
    cdf1 = hist1.cumsum()
    cdf_normalized1 = cdf1*hist1.max() / cdf1.max()
    
    #顯示圖像結(jié)果
    plt.figure(figsize=(10,8),dpi=100)
    plt.subplot(221)
    img_show('原圖',img)
    plt.subplot(222)
    img_show('均衡化后',equ)
    plt.subplot(223)
    plt.plot(cdf_normalized,color='b')
    plt.hist(img.flatten(),256,[0,256],color='r')
    plt.xlabel('相應(yīng)的直方圖(紅)和累積直方圖(藍(lán))',fontproperties='FangSong',fontsize=15)
    plt.xlim([0,256])
    plt.legend(('cdf','historgram'),loc = 'upper left')
    plt.subplot(224)
    plt.plot(cdf_normalized1,color='b')
    plt.hist(equ.flatten(),256,[0,256],color='r')
    plt.xlabel('均衡化相應(yīng)的直方圖(紅)和累積直方圖(藍(lán))',fontproperties='FangSong',fontsize=15)
    plt.xlim([0,256])
    plt.legend(('cdf','historgram'),loc = 'upper left')
    plt.show()
直方圖均衡化.png

我們可以看出來直方圖大部分在灰度值較高的部分,而且分布很集中。而我們希望直方圖的分布比較分散,能夠涵蓋整個(gè) x 軸。所以,我們就需要一個(gè)變換函數(shù)幫助我們把現(xiàn)在的直方圖映射到一個(gè)廣泛分布的直方圖中,這就是直方圖均衡化。

**限制對比度自適應(yīng)性直方圖均衡化 CLAHE **

在上邊做的直方圖均衡化會(huì)改變整個(gè)圖像的對比度,但是在很多情況下,這樣做的效果并不好。的確在進(jìn)行完直方圖均衡化之后,圖片背景的對比度被改變了。但是你再對比一下兩幅圖像中雕像的面圖,由于太亮我們丟失了很多信息。

直方圖均衡化.png

原理:

為了解決這個(gè)問題,我們需要使用自適應(yīng)的直方圖均衡化CLAHE (Contrast Limited Adaptive Histogram Equalization)。這種情況下,整幅圖像會(huì)被分成很多小塊,這些小塊被稱為“tiles”(在 OpenCV 中 tileGridSize默認(rèn)是 8x8),然后再對每一個(gè)小塊分別進(jìn)行直方圖均衡化(跟前面類似)。所以在每一個(gè)的區(qū)域中,直方圖會(huì)集中在某一個(gè)小的區(qū)域中(除非有噪聲干擾)。如果有噪聲的話,噪聲會(huì)被放大。為了避免這種情況的出現(xiàn),要使用對比度限制。

CLAHE中,每一個(gè)像素鄰域都要進(jìn)行對比度限制,從而得到對應(yīng)的變換函數(shù),被用來降低AHE中噪聲的增強(qiáng),這主要是通過限制AHE中的對比度增強(qiáng)來實(shí)現(xiàn)的。像素周圍鄰域噪聲的增強(qiáng)主要是由變換函數(shù)的斜率造成的,由于像素鄰域的噪聲與鄰域的CDF成正比,因此也與鄰域直方圖在該中心像素位置的值成正比,CLAHE之所以能夠限制對比度,是因?yàn)樗谟?jì)算鄰域的CDF之前在指定閾值處對直方圖進(jìn)行了修剪,如下圖所示,這一做法不僅限制了CDF的斜率,也限制了變換函數(shù)的斜率,其中對直方圖進(jìn)行切割所使用的閾值,被稱作修剪限制度(clip limit),這個(gè)參數(shù)不僅依賴于直方圖的歸一化,而且依賴于像素鄰域的size大小,通常設(shè)為3到4之間。

cliplimit.jpg

對于每個(gè)小塊來說,如果直方圖中的 bin 超過對比度的上限的話,就把其中的像素點(diǎn)均勻分散到其他 bins 中,然后在進(jìn)行直方圖均衡化。最后,為了去除每一個(gè)小塊之間“人造的”(由于算法造成)邊界,再使用雙線性差值,與原圖做圖層濾色混合操作(可選)。

實(shí)現(xiàn):

def img_show(name,image):
    """matplotlib圖像顯示函數(shù)
    name:字符串,圖像標(biāo)題
    img:numpy.ndarray,圖像
    """
    if len(image.shape) == 3:
        image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
    plt.imshow(image,'gray')
    plt.xticks([])
    plt.yticks([])
    plt.xlabel(name,fontproperties='FangSong',fontsize=12)
    
if __name__=="__main__":
    img = cv2.imread("data/tsukuba_l.jpg",0)
    hist,bins = np.histogram(img.flatten(),256,[0,256])
    #print(hist)
    
    #查看累積直方圖
    cdf = hist.cumsum()
    cdf_normalized = cdf*hist.max() / cdf.max()
    #print(cdf_normalized)
    
    #均衡化
    clahe = cv2.createCLAHE(clipLimit =2.0,tileGridSize=(8,8))
    equ = clahe.apply(img)
    
    hist1,bins1 = np.histogram(equ.flatten(),256,[0,256])
    #print(hist)
    
    #查看均衡化后的累積直方圖
    cdf1 = hist1.cumsum()
    cdf_normalized1 = cdf1*hist1.max() / cdf1.max()
    
    #顯示圖像結(jié)果
    plt.figure(figsize=(10,8),dpi=100)
    plt.subplot(221)
    img_show('原圖',img)
    plt.subplot(222)
    img_show('自適應(yīng)均衡化',equ)
    plt.subplot(223)
    plt.plot(cdf_normalized,color='b')
    plt.hist(img.flatten(),256,[0,256],color='r')
    plt.xlabel('相應(yīng)的直方圖(紅)和累積直方圖(藍(lán))',fontproperties='FangSong',fontsize=15)
    plt.xlim([0,256])
    plt.legend(('cdf','historgram'),loc = 'upper left')
    plt.subplot(224)
    plt.plot(cdf_normalized1,color='b')
    plt.hist(equ.flatten(),256,[0,256],color='r')
    plt.xlabel('自適應(yīng)均衡化直方圖',fontproperties='FangSong',fontsize=15)
    plt.xlim([0,256])
    plt.legend(('cdf','historgram'),loc = 'upper left')
    plt.show()
    
自適應(yīng)均衡化.png

參考文獻(xiàn):
網(wǎng)址:直方圖均衡化
Adaptive_histogram_equalization
書籍:《數(shù)字圖像處理》《OpenCV-Python 中文教程》

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容