參考自:
數字圖像處理第三版,岡薩雷斯
圖像處理基礎(8):圖像的灰度直方圖、直方圖均衡化、直方圖規定化(匹配) - Brook_icv - 博客園 https://www.cnblogs.com/wangguchangqing/p/7098213.html
直方圖規定化,又叫直方圖匹配。理想情況下,直方圖均衡化實現了圖像灰度的均衡分布,提高了圖像對比度、提升了圖像亮度。在實際應用中,有時並不需要圖像的直方圖具有整體的均勻分布,而希望直方圖與規定要求的直方圖一致,這就是直方圖規定化。
通過一個灰度映像函數,將原灰度直方圖改造成所希望的直方圖,把圖像變換為某一特定的灰度分布,也就是其目的的灰度直方圖是已知的。這其實和均衡化很類似,均衡化后的灰度直方圖也是已知的,是一個均勻分布的直方圖;而規定化后的直方圖可以隨意的指定,也就是在執行規定化操作時,首先要知道變換后的直方圖,這樣才能確定變換函數。規定化操作能夠有目的的增強某個灰度區間,相比於,均衡化操作,規定化多了一個輸入,但是其變換后的結果也更靈活。
在理解了上述的均衡化過程后,直方圖的規定化也較為簡單。可以利用均衡化后的直方圖作為一個中間過程,然后求取規定化的變換函數。具體步驟如下:
- 將原始圖像的灰度直方圖進行均衡化,得到一個變換函數s=T(r),其中s是均衡化后的像素,r是原始像素
- 對規定的直方圖進行均衡化,得到一個變換函數v=G(z)v=G(z),其中v是均衡化后的像素,z是規定化的像素
- 上面都是對同一圖像(變換前的待規定化圖像和變換后的規定化結果圖像)的均衡化,其結果應該是相等的,s=v,且z=G−1(v)=G−1(T(r)),這個公式就是r和z的關系
通過,均衡化作為中間結果,將得到原始像素 r 和 z 規定化后像素之間的映射關系。
詳解規定化過程
對圖像進行直方圖規定化操作,原始圖像的直方圖和以及規定化后的直方圖是已知的。
假設Pr(r)表示原始圖像的灰度概率密度,Pz(z)表示規定化圖像的灰度概率密度(r和z分別是原始圖像的灰度級,規定化后圖像的灰度級)。
- 對原始圖像進行均衡化操作,則有

- 對規定化的直方圖進行均衡化操作,則

- 由於是對同一圖像的均衡化操作,所以有

-
規定化操作的目的就是找到原始圖像的像素sk到規定化后圖像像素的zm之間的一個映射。
有了上一步的等式后,可以得到sk=G(zm),因此要想找到sk對應的zm只需要在z進行迭代,找到使式子G(zm)−sk的絕對值最小即可。
- 上述描述只是理論的推導過程,在實際的計算過程中,不需要做兩次的均衡化操作,具體的推導過程如下:


上面公式表示,假如sk規定化后的對應灰度是zm的話,需要滿足的條件是sk的累積概率和zm的累積概率是最接近的
下面是一個具體計算的例子:

首先得到原直方圖的各個灰度級的累積概率Vs以及規定化后直方圖的各個灰度級的累積概率Vz,那么確定sk到zm之間映射關系的條件就是:
∣Vs−Vz∣的值最小。
以k=2為例,其原始直方圖的累積概率是:0.65,在規定化后的直方圖的累積概率中和0.65最接近(相等)的是灰度值為5的累積概率密度,則可以得到原始圖像中的灰度級2,在規定化后的圖像中的灰度級是5。
直方圖規定化的實現
直方圖規定化的實現可以分為一下三步:
- 計算原圖像的累積直方圖
- 計算規定直方圖的累積直方圖
- 計算兩累積直方圖的差值的絕對值
- 根據累積直方圖差值建立灰度級的映射
具體代碼
"""直方圖規定化,又叫直方圖匹配""" import numpy as np import matplotlib.pyplot as plt import cv2 # 定義函數,計算直方圖累積概率 def histCalculate(src): row, col = np.shape(src) hist = np.zeros(256, dtype=np.float32) # 直方圖 cumhist = np.zeros(256, dtype=np.float32) # 累積直方圖 cumProbhist = np.zeros(256, dtype=np.float32) # 累積概率probability直方圖,即Y軸歸一化 for i in range(row): for j in range(col): hist[src[i][j]] += 1 cumhist[0] = hist[0] for i in range(1, 256): cumhist[i] = cumhist[i-1] + hist[i] cumProbhist = cumhist/(row*col) return cumProbhist # 定義函數,直方圖規定化 def histSpecification(specImg, refeImg): # specification image and reference image spechist = histCalculate(specImg) # 計算待匹配直方圖 refehist = histCalculate(refeImg) # 計算參考直方圖 corspdValue = np.zeros(256, dtype=np.uint8) # correspond value # 直方圖規定化 for i in range(256): diff = np.abs(spechist[i] - refehist[i]) matchValue = i for j in range(256): if np.abs(spechist[i] - refehist[j]) < diff: diff = np.abs(spechist[i] - refehist[j]) matchValue = j corspdValue[i] = matchValue outputImg = cv2.LUT(specImg, corspdValue) return outputImg img = cv2.imread('F:\program_study\Python\data\city.tif', cv2.IMREAD_GRAYSCALE) # 讀入參考圖像 img1 = cv2.imread('F:\program_study\Python\data\Lena.tif', cv2.IMREAD_GRAYSCALE) cv2.imshow('input', img) cv2.imshow('refeImg', img1) imgOutput = histSpecification(img, img1) cv2.imshow('output', imgOutput) cv2.waitKey(0) cv2.destroyAllWindows() fig = plt.figure('整個過程直方圖顯示', (8, 8)) plt.subplot(311) plt.plot(histCalculate(img), 'r', lw=1, label='待匹配累積概率直方圖') plt.legend(loc='best') plt.subplot(312) plt.plot(histCalculate(img1), 'b', lw=1, label='參考累積概率直方圖') plt.legend(loc='best') plt.subplot(313) plt.plot(histCalculate(imgOutput), 'g', lw=1, label='規則化后的概率直方圖') plt.legend(loc='best') plt.show()
局部的直方圖處理
除了全局的直方圖處理外,還有局部直方圖處理。它可以增前圖像中小區域的細節。過程是定義一個領域模板,並將模板中心從一個像素移至另一個像素。在每個位置,計算領域中的點的直方圖,均衡化或規定化,並將局部的中心元素的作為圖像的當前值。
