直方圖均衡化
直方圖均衡化是將一幅圖像的灰度直方圖變平,使變換後的圖像中每個灰度值的分佈概率都相同。並且可以增強圖像的對比度。
灰度值的分佈概率都相同
這句話的理解,並不是每個像素值的像素個數相同,比如:像素值爲90的像素點有50個、爲40的像素點有30個、爲41的像素點有20個。這其中像素值40和41對人的肉眼來說沒有多大區別的,我們只看結果圖像,40的像素點有50個。
步驟
- 計算圖像的灰度直方圖
- 計算灰度直方圖的累加直方圖
- 根據累加直方圖和直方圖均衡化原理得到輸入與輸出之間的映射關係。
- 最後根據映射關係得到結果
原理
不管怎麼改變像素值,總像素個數不會變。而且我們最理想的目標就是結果圖像的每個像素點的個數是相等的。
對於輸入圖像的任意一個像素 總能在輸出圖像裏有對應的像素使得下面等式成立
其中和 分別是輸入圖像和輸出圖像的累加直方圖
其中,輸出圖像每個像素點的個數
再帶入到累計直方圖等式裏我們可以得到:
是輸入圖像的某個像素值,經過上述公式計算得到
計算
上面的原理,最後一步需要我們計算的只有
像它這樣的式子還有個
然後可以使用累積分佈函數線性插值計算新的像素值。約等於,與等於,約等於
CODE
原圖
此處直接用灰度圖像了
plt.imshow(lena1_gray)
原圖直方圖分佈
plt.hist(lena1_gray.ravel(), 256)
OpenCV API
一句話
equHist = cv.equalizeHist(lena1_gray)
均衡化後圖像
plt.imshow(equHist)
結果亮了許多,增強了對比度
直方圖分佈
可以看到,相對原始直方圖,分佈已經均勻許多。而且雖然右邊很密集,但是右邊的直方圖矮啊!
原理實現
def Histeq(im: np.ndarray, nbr_bins=256):
# 計算圖像直方圖
imhist, bins = np.histogram(im.flatten(), nbr_bins, normed=True)
cdf = imhist.cumsum() # 計算累計直方圖
cdf = 255 * cdf / cdf[-1] # 歸一化
im2 = np.interp(im.flatten(), bins[:-1], cdf) # 使用線性插值法計算新的像素
return im2.reshape(im.shape)
equHist2 = Histeq(lena1_gray)
plt.imshow(equHist2)
結果
直方圖分佈
和Opencv API相比,我這裏沒有考慮個別像素值個數過多(極少部分達到了4000+)的情況。
歡迎一起來參與leetcode刷題項目
刷題的GitHub: github鏈接.