直方圖均衡化
效果
代碼
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
src = cv.imread("/home/xueaoru/下載/IMG_20190326_232636.jpg")
gray = cv.cvtColor(src,cv.COLOR_BGR2GRAY)
# 原圖
arr = gray.flatten()
eq = [np.sum(arr == i) for i in range(256)]
eq = np.array(eq)
eq = eq / eq.sum()
fg = plt.figure(1)
plt.subplot(3,2,1)
plt.imshow(gray,cmap='gray')
plt.subplot(3,2,2)
plt.hist(arr,bins = 256,density=1,alpha = 0.75)
# opencv 直方圖均值化
plt.subplot(3,2,3)
out = cv.equalizeHist(gray)
plt.imshow(out,cmap='gray')
plt.subplot(3,2,4)
arr_2 = out.flatten()
plt.hist(arr_2,bins = 256,density=1,alpha = 0.75)
# 自己實現直方圖均值化
fx = []
fx.append(eq[0])
for i in range(1,256):
fx.append(fx[i-1]+eq[i])
val = np.array([255*fx[a] for a in arr])
val = val.reshape(gray.shape)
plt.subplot(3,2,5)
plt.imshow(val,cmap="gray")
plt.subplot(3,2,6)
arr_3 = val.flatten()
plt.hist(arr_3,bins=256,density=1,alpha = 0.75)
plt.show()
原理
圖像直方圖的原始分布:
目標分布:
\[ F_Y(y) = P\lbrace Y\leq y \rbrace = P \lbrace T(X) \leq y \rbrace = P \lbrace X \leq T^{-1}(y) \rbrace = F_X(T^{-1}(y)) \tag{1} \]
那么這個公式是如何得來的呢?
\[ P \lbrace T(X) \leq y \rbrace = P \lbrace X \leq T^{-1}(y) \rbrace \tag{2} \]
\[ 例如,有Y=3X,也即T(X) = 3X,那么P \lbrace 3X \leq y \rbrace = P \lbrace X \leq \frac{y}{3} \rbrace =P \lbrace X \leq T^{-1}(y) \rbrace\\, 若T(X) = -3X,很明顯上面的公式符號方向會改變。 \]
由於我們要求的變換函數在變換后仍然要保持在變換之前變換亮度相對高的變換之后相對亮度仍然要高,所以變換函數必須是單調遞增的,所以上式不變號。
\[ 由(1)繼續推,兩邊同時求導,那么有\\ f_Y(y) = \frac{dT^{-1}(y)}{dy}*f_x(T^{-1}(y))=\frac{dx}{dy}*f_x(X) \tag{3} \]
\[ 化簡一下有\\ \frac{1}{255}dy = f_x(x)dx\\ 兩邊同時求積分有\\ y = 255*\int^{x}_0f_x(x)dx\\\tag{4} \]
\[ 離散化上式則有\\ y = \sum_{i=0}^{x} f_x(i) \]
根據上面的推導,我們寫出了上面的代碼。但是,由圖我們看到,直方圖均衡化之后的圖像的概率分布好像並不是完全均勻分布的呀?怎么回事?
我們仔細查閱了相關資料,在《岡薩雷斯數字圖像處理》這本書中查到了相關的語句。
然而,我們還是不理解,為什么有的灰度值沒有對應的變換后的值?
繼續往后看,直到看到了這個圖,恍然大悟!
可以看到,均衡后的直方圖中,灰度值為2的點,在變換函數中並沒有一個合適的sk值與之對應,因此這些點的值就這么消失了!