理論:
一張像素值被限制在一個(gè)特定值范圍內(nèi)的圖像,比如,亮圖被限制所有像素都是亮值。但是一個(gè)好的圖片應(yīng)該是有所有范圍的像素。所以我們需要把histogram拉伸到兩端,這就是histogram均衡。這個(gè)一般是用來(lái)提升圖片的對(duì)比度。

我會(huì)建議你閱讀wikipedia
http://en.wikipedia.org/wiki/Histogram_equalization
我們這里看Numpy的實(shí)現(xiàn),之后,會(huì)看OpenCV的函數(shù)。
import cv2
import numpy as np
from matplotlib import pyplot as pltimg = cv2.imread('wiki.jpg',0)
hist,bins = np.histogram(img.flatten(),256,[0,256])
cdf = hist.cumsum()
cdf_normalized = cdf * hist.max()/ cdf.max()plt.plot(cdf_normalized, color = 'b')
plt.hist(img.flatten(),256,[0,256], color = 'r')
plt.xlim([0,256])
plt.legend(('cdf','histogram'), loc = 'upper left')
plt.show()

你可以看到histogram在高亮區(qū)域,我們需要全范圍的,為了這個(gè)目的,我們需要一個(gè)轉(zhuǎn)換函數(shù)來(lái)把高亮區(qū)的像素映射到全范圍的像素。這就是histogram均衡做的。
現(xiàn)在我們找到了最小的histogram值然后應(yīng)用histogram均衡。但是我這里用的masked數(shù)組,所有的運(yùn)算時(shí)在非掩的元素上的
cdf_m = np.ma.masked_equal(cdf,0)
cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min())
cdf = np.ma.filled(cdf_m,0).astype('uint8')
現(xiàn)在我們有了查詢表可以給我們對(duì)于每個(gè)輸入像素值得對(duì)應(yīng)輸出像素值。然后我們應(yīng)用這個(gè)轉(zhuǎn)換。
img2=cdf[img]
現(xiàn)在我們計(jì)算它的histogram

另一個(gè)信息是即使如果圖像是個(gè)暗圖,當(dāng)均衡之后我們會(huì)得到和之前那次幾乎一樣的圖片,所以這個(gè)可以用來(lái)讓所有圖片擁有同樣的亮度。在面部識(shí)別里,在訓(xùn)練面部數(shù)據(jù)之前,面部的圖片會(huì)做histogram均衡以讓他們所有都是同樣的亮度條件。
OpenCV里的Histograms均衡
OpenCV有一個(gè)函數(shù)可以做這個(gè),cv2.equalizeHist()。它的輸入是灰度圖像,輸出時(shí)我們的histogram均衡圖像。
下面是一個(gè)簡(jiǎn)單的代碼來(lái)展示它的使用:
img = cv2.imread('wiki.jpg',0)
equ = cv2.equalizeHist(img)
res = np.hstack((img,equ)) #stacking images side-by-side
cv2.imwrite('res.png',res)

所以現(xiàn)在你可以把不同亮度的圖像均衡以后看結(jié)果
histogram均衡在圖片的histogram被限制在一個(gè)范圍內(nèi)時(shí)很有用,它在histogram覆蓋大范圍時(shí)并不好用。
對(duì)比度受限自適應(yīng)直方圖均衡
我們第一個(gè)histogram均衡考慮的是圖片全部對(duì)比度,在很多情況下,這不是好主意,比如下面的圖片和做了全局histogram均衡的結(jié)果:

背景對(duì)比度在均衡后確實(shí)提高了。但是對(duì)比兩張圖里的雕像,我們由于過(guò)度亮而導(dǎo)致失去了大部分面部信息。這是由于圖像的histogram并不是像之前的圖片那樣限制在特定范圍內(nèi)。
要解決這個(gè)問(wèn)題,要用適應(yīng)性histogram均衡。在這里,圖像被分成小塊,這些小塊叫做瓷磚(瓷磚的大小在OpenCV里默認(rèn)是8x8)。然后這些小塊還和平常一樣做均衡,所以在小塊里,histogram是在小范圍內(nèi)的,如果有噪點(diǎn),會(huì)被放大。要避免這個(gè),要應(yīng)用對(duì)比度限制。如果任何histogram 高于特定的對(duì)比度限制(OpenCV里默認(rèn)是40),那些像素會(huì)被修剪掉并被無(wú)變化的放到其他然后再做histogram均衡。均衡后,要移除瓷磚邊界的人工因素,要應(yīng)用雙線性插值。
下面的代碼顯示了OpenCV里的CLAHE:
import numpy as np
import cv2img = cv2.imread('tsukuba_l.png',0)
# create a CLAHE object (Arguments are optional).
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(img)cv2.imwrite('clahe_2.jpg',cl1)
看下面的結(jié)果并和前面的結(jié)果對(duì)比,特別是雕塑部分

END