直方圖均衡化演算法原理詳解
演算法
經典演算法
下面以一幅3*2畫素的簡單圖片(圖C)為例,來說明灰度直方圖均衡化的演算法。
(圖C)
圖C的直方圖:
注意看百分位(Percentile)這一項。一般軟體的百分位是 當前色階的畫素數量÷總畫素數量,而Photoshop不同,Photoshop顯示的是 當前色階與前面色階的所有畫素數量÷總畫素數量。因此圖C色階為100時的百分位就是(3+2)/6=5/6=83.33%,這個百分位其實就是我們要求的灰度值(範圍0~1),把它轉換成0~255的範圍,要再乘255。
求出每個色階的百分位之後,再乘255,就可以求出與其對應的灰度值來。
色階 | 數量 | 出現頻率 | 百分位 | 255*百分位 |
---|---|---|---|---|
50 | 3 | 3/6 | 3/6=50% | 255*50%=128 |
100 | 2 | 2/6 | (3+2)/6=83.33% | 255*83.33%=212 |
200 | 1 | 1/6 | (3+2+1)/6=100% | 255*100%=255 |
根據每個色階的 色階->255*百分位 的對應關係組成一個灰度對映表,然後根據對映表來修改原來圖片每個畫素的灰度值。對於圖C,用128替換50,用212替換100,用255替換200。這樣,灰度直方圖的均衡化就完成了。
Photoshop的演算法
經過經典演算法均衡化的圖片,最亮的畫素值總是255,因為最後一級色階(255)的百分位一定是100%。而最暗的是由色階0的數量決定的,畫素值不一定是0。
Photoshop通過對比度拉伸的方法使最暗的畫素值變為0,其它畫素也相應變暗,最亮的畫素保持255不變。對比度拉伸後的效果可能會比經典演算法稍顯偏暗。
對比度拉伸的演算法,類似於使用色階調整命令把黑場設成Min時的效果,Min是指畫素數量不為0的第一個色階。
對比度拉伸的公式:C = (Level - Min) * Scale = (Level - Min) * 255 / (255-Min)
圖C均衡化之後的灰度值分別是128、212、255,為了精確,我們使用保留2位小數的形式(127.50、212.42、255.00)來進行對比度拉伸的計算。
Min = 127.50 '均衡化之後的最小值 |
經典演算法和Photoshop演算法的直方圖比較。
彩色演算法
彩色的直方圖均衡化其實就是對影象某個或多個顏色通道進行灰度直方圖均衡化運算,常見的有以下幾種方法:
-
統計所有RGB顏色通道的直方圖的資料並做均衡化運算,然後根據均衡化所得的對映表分別替換R、G、B通道顏色值。
-
分別統計R、G、B顏色通道的直方圖的資料並做均衡化運算,然後根據R、G、B的對映表分別替換R、G、B通道顏色值。
-
用亮度公式或求RGB的平均值的方式計算亮度通道,然後統計亮度通道的直方圖的資料並做均衡化運算,然後根據對映表分別替換R、G、B通道顏色值。
Photoshop用的是第一種方法。
總結
直方圖均衡化是灰度變換的一個重要應用,它高效且易於實現,廣泛應用於影象增強處理中。影象的畫素灰度變化是隨機的,直方圖的圖形高低不齊,直方圖均衡化就是用一定的演算法使直方圖大致平和。
均衡化處理後的圖象只能是近似均勻分佈。均衡化圖象的動態範圍擴大了,但其本質是擴大了量化間隔,而量化級別反而減少了,因此,原來灰度不同的象素經處理後可能變的相同,形成了一片的相同灰度的區域,各區域之間有明顯的邊界,從而出現了偽輪廓。
如果原始影象對比度本來就很高,如果再均衡化則灰度調和,對比度降低。在泛白緩和的影象中,均衡化會合並一些象素灰度,從而增大對比度。均衡化後的圖片如果再對其均衡化,則影象不會有任何變化。
灰度直方圖均衡化的演算法,簡單地說,就是把直方圖的每個灰度級進行歸一化處理,求每種灰度的累積分佈,得到一個對映的灰度對映表,然後根據相應的灰度值來修正原圖中的每個畫素。
經典的直方圖均衡化演算法可能存在以下一些不足:
- 輸出影象的實際灰度變化範圍很難達到影象格式所允許的最大灰度變化範圍。
- 輸出影象的灰度分佈直方圖雖然接近均勻分佈, 但其值與理想值1/n仍有可能存在較大的差異, 並非是最佳值。
- 輸出影象的灰度級有可能被過多地合併。由於灰度的吞噬也易造成影象資訊的丟失。
為此人們提出了許多改進的直方圖均衡演算法,詳細內容請參閱本文末尾提供的參考資料。
基於上述程式設計思想,用MATLAB實現的演算法如下:
%直方圖均衡化
I0 = imread('lena.jpg');
I = rgb2gray(I0) %二值化
[height,width]=size(I);
figure
subplot(221)
imshow(I)%顯示原始影象
subplot(222)
imhist(I)%顯示原始影象直方圖
%根據畫素灰度統計;
NumPixel = zeros(1,256);%統計各灰度數目,共256個灰度級(初始化數目為0)
for i = 1:height
for j = 1:width
NumPixel(I(i,j)+1)=NumPixel(I(i,j)+1)+1;%對應灰度值畫素點數量加一
end
end
%計算灰度分佈密度
ProbPixel = zeros(1,256);
for i = 1:256
ProbPixel(i) = NumPixel(i)/(height*width*1.0);
end
%計算累計直方圖分佈(“離散求累積和,連續求積分”)
for i = 1:256
if i == 1
Cumupixel(i) = ProbPixel(i);
else
Cumupixel(i)=Cumupixel(i-1)+ProbPixel(i);
end
end
%累計分佈取整
for i = 1:256
Cumupixel(i) = uint8(255.0*Cumupixel(i)+0.5);
end
%對灰度值進行對映(均衡化)
for i = 1:height
for j = 1:width
I(i,j)=Cumupixel(I(i,j));
end
end
subplot(223)
imshow(I)%顯示直方圖均衡化後的影象
subplot(224)
imhist(I)%顯示直方圖均衡化後的影象的直方圖
實現效果如下: