一.用法
灰度均衡化雖然能增大對比度、豐富灰度級數。但是爲覆蓋整個灰度區間的操作,且不受控制,即只能擴展到整個灰度區間,不能根據我們的實際需要作出相應調整。
而灰度規定化可以彌補這個缺憾,能讓我們通過灰度變換得到我們想要的灰度分佈區間。在Matlab中沒有直接實現灰度規定化的函數。但是我們可以通過imhist和histeq兩個函數的結合使用來實現。示例程序如下:
I_M = imread('pout.tif');
I = imread('tire.tif');
I_M_imhist = imhist(I_M);%產生規定化模板
J = histeq(I,I_M_imhist);%直方圖規定化
imhist(I); %顯示變換前的直方圖
imhist(I_M);%產生規定化模板
imhist(J);% 規定化變換後的直方圖
二.原理
直方圖規定化首先也得求灰度圖像的灰度級數的概率密度和累計分佈函數,得到原始圖像和模板圖像的灰度累計分佈函數直方圖後(這裏的模板的灰度級數N和原始圖像的灰度級數M我們只討論M>=N的情況),有兩種方式將模板灰度分佈特徵映射到原始圖像中。一是單映射規則(SML),二是組映射規則(GML)。
1. 單映射規則(SML)
單映射規則具體操作步驟如下:對一原始圖像的每個灰度級數i的灰度累計分佈函數(nor_I_hist(i))與模板圖像灰度級數灰度累計分佈函數值(nor_M_hist(i))作差值後取絕對值運算,比較運算得到的結果,差值絕對值的最小值對應的最小位置便是原始圖像映射到模板圖像的灰度值。
例:
設一幅原始圖像和模板圖像的灰度級數、灰度直方圖、累計分佈函數直方圖呈如下分佈:
表中爲灰度值爲0的灰度級單映射時,分別用其累計分佈函數直方圖0.19與模板的累計分佈函數直方圖作差,發現差值絕對值的最小值在模板圖像灰度級的3、4灰度級處,取最小位置處爲3,故原始圖像灰度級爲0的位置單映射後的灰度值爲3。其餘灰度級同理。
2.組映射規則(GML)
組映射也是先求出原始圖像和模板圖像的累計分佈函數直方圖。在此基礎上,與單映射相反,組映射是用模板圖像中每個灰度級的累計分佈函數(灰度直方圖概率密度爲0的灰度級除外)依次與原始圖像的所有累計分佈函數值作差,在所有差值中找出絕對值最小值所對應的原始圖像灰度級,將該灰度級與上一次映射灰度級之間的原始圖像灰度級都映射爲模板圖像中與之差值絕對值最小的灰度級。例如,對於表1-1的灰度圖像,若採用組映射方法,則應從模板圖像灰度級數爲3的位置開始運算映射,即用0.2分別與原始圖像的累計分佈函數直方圖作差,發現在0.19處有絕對值最小值,於是就將原始圖像灰度值爲0映射爲3,下一步則接着從灰度級爲5的位置開始映射,即0.8分別與原始圖像的累積分佈直方圖作差,發現在0.81出有最小值,對應原始圖像中灰度級數爲3的位置,於是原始圖像中灰度級1~3都映射爲5。其餘同理。
三.代碼示例
闡述完上述原理後,我們通過基於Matlab的編程來進一步驗證我們方法的正確性。
1. 實現單映射(SML)代碼示例:
I = imread('pout.tif');
M = imread('tire.tif');
I_out = I;
I_hist = imhist(I);
M_hist = imhist(M);%概率密度函數,即灰度直方圖
nor_I_hist = cumsum(I_hist)/numel(I);
nor_M_hist = cumsum(M_hist)/numel(M);%累積分佈函數
%累積分佈函數歸一化
[m_I,n_I] = size(nor_I_hist);
[m_M,n_M] = size(nor_M_hist);
imp=ones(m_M,1);
for i=1:m_I
for j=1:m_M
imp(j) =abs( nor_I_hist(i) -nor_M_hist(j));%作差值絕對
%值運算
end
nn = find(imp==min(imp));%找到最小值所在灰度級
ori = find(I==i-1);
L = length(ori);%測量nummin的長度,若大於1,則說明有概率密度
%爲0的位置,則取最後位。
I_out(ori) = nn(L); %將模板灰度映射到原始圖像中
end
%顯示原始圖像、模板圖像、變換後圖像的灰度直方圖
subplot(2,3,1),imhist(I),title('hist of orignal image')
subplot(2,3,2),imhist(M),title('hist of template image')
subplot(2,3,3),imhist(I_out),title('hist of output image')
subplot(2,3,4),imshow(I),title('orignal image')
subplot(2,3,5),imshow(M),title('template image')
subplot(2,3,6),imshow(I_out),title('output image')
1. 組映射(GML)代碼示例:
I = imread('tire.tif');
M = imread('pout.tif');
[m,n] = size(I);
I_out = im2uint8(zeros(m,n));
I_hist = imhist(I);
M_hist = imhist(M);
nor_I_hist = cumsum(I_hist)/numel(I);
nor_M_hist = cumsum(M_hist)/numel(M);
[M_m,M_n] = size(M_hist);
[I_m,I_n] = size(I_hist);
tick = 1;
IM = zeros(I_m,1);
for i = 1:M_m%
if M_hist(i) == 0%剔除掉直方圖概率密度爲0的灰度級
continue;
else
for j = 1:I_m
IM(j) =abs(nor_M_hist(i)-nor_I_hist(j));
end
nummin = find(IM == min(IM));% 找到差值最小的灰度值位置,便是原
%始圖像及其之前的灰度值都映射爲新的灰度值i
L= length(nummin);%測量nummin的長度,若大於1,則說明有概率密度
%爲0的位置,則取最後位。
for k=tick:nummin(L)%從上一次映射灰度級到本次灰度級之間的灰度級
matchgray = find(I==k-1);
I_out(matchgray) = i-1;%賦值到原始圖像中
end
tick = nummin(L);
end
end
%顯示原始圖像、模板圖像、變換後圖像的灰度直方圖
subplot(2,3,1),imhist(I),title('hist of orignal image')
subplot(2,3,2),imhist(M),title('hist of template image')
subplot(2,3,3),imhist(I_out),title('hist of output image')
subplot(2,3,4),imshow(I),title('orignal image')
subplot(2,3,5),imshow(M),title('template image')
subplot(2,3,6),imshow(I_out),title('output image')
3. 單映射法(SML)和組映射法(GML)的比較
首先,我們使用表1-1分別在單映射和組映射下得到的結果來量化誤差,列於表3-1中。
對單映射來說,我們可以用映射時產生的累積分佈函數差值來量化映射誤差,具體爲:|0.44-0.20|+||+|(0.89-0.44)-(0.8-0.2)|+|(1.00-0.89)-(1-0.8)|=0.48
對組映射來說,則爲:|0.2-0.19|+|(0.81-0.19)-(0.8-0.2)|+|(1.0-0.8)-(1-0.81)|=0.04
從量化數據誤差來看,組映射的誤差明顯要小於單映射。在此基礎上,爲驗證結論的普遍性,我們用期望誤差來說明,當把某個模板圖像tem(i)灰度映射到原始圖像ORI(i)時,對於單映射法,由於是採用一原始灰度與所有模板灰度值分別作差得到作差絕對值最小值位置,故最大可能誤差爲u/2,其中u表示最小差值絕對值處的模板灰度直方圖;對於組映射法,則是用一模板灰度值分別與所有原始灰度圖像作差,則最大可能誤差爲s/2,其中s表示最小值差值處的原始圖像灰度直方圖。由於根據前面所述,我們討論的都是模板灰度級數N小於等於原始圖像灰度級數M的情況,故必有s/(2*M),因此組映射的期望誤差必小於單映射誤差,需要提及的是,上述Matlab代碼是通過組映射實現的灰度規定化。