【原創】【論文復現】【Matlab】【圖像處理】基於三維直方圖降維重建與高斯分佈擬合的Otsu全局閾值分割算法的優化

參考文獻:
[1] 龍建武, 閆何, 張建勳, 田芳, 等. 智能圖像分割技術[M]. 北京: 科學出版社. 2017
[2] 申鉉京.三維直方圖重建和降維的Otsu閾值分割算法[J]. 電子學報. 2011:1108-1114

概述:

Otsu全局閾值分割技術通過最大化圖像中目標與背景區域的類間方差,自動實現了背景與目標區域的分離。
然而,在複雜噪聲情況下,單純地使用Otsu法會導致在背景區域中出現噪點,從而影響分割結果。在[2]中,申等人構想出了一種三維直方圖重建降維的方式來消除噪聲的影響。
當使用Otsu法進行分割時,實踐表明得到的閾值並不是每次都會位於直方圖峯值之間的谷底位置。在[1]中,介紹了一種基於高斯分佈擬合的全局閾值優化算法。通過此算法得到的閾值要比單純的Otsu法更容易收斂進谷底。

細節:

1、三維直方圖重建與降維思想:

在此法中,申等人通過利用圖像每個像素點的灰度、均值與中值,構成了三維直方圖中的三個座標。在一般的帶噪情況下,原圖爲:
在這裏插入圖片描述
二維直方圖爲:
在這裏插入圖片描述
可以看到,噪聲削弱了直方圖中的尖峯,且深谷區域中的像素數量不爲0,即圖像中存在少量的、隨機分佈的噪聲點,這使得完美的全局分割變得幾乎不可能。
圖像三維直方圖爲:
在這裏插入圖片描述
上圖中,每個點均代表圖像中的一個像素,點的座標由(灰度,均值,中值)來表示。由於輸入圖像的灰度值已進行了歸一化,所以,所有的點均位於長寬高分別爲1的立方體內。
對於無噪圖像,典型的情況是,圖像的灰度、均值與中值應大致分佈於沿立方體體對角線的圓柱形區域內,即三者應近似相等。然而,上圖的情況表明,原始圖像已經被噪聲污染,無法直接分割。
爲了去噪,現在開始分析三維直方圖各個區域的性質。
首先,申等人將直方圖分成了8個部分,描述如下圖:
在這裏插入圖片描述
其中,f表示灰度,h表示中值,g表示均值
1、區域0和區域1都大致位於體對角線的圓柱形區域內,屬於無需降噪的區域。
2、其他所有區域都需要降噪操作。
重建操作:
1、對於區域2和區域3的點,將它們全部投影到gOh平面,可以看到均大致位於對角線區域內,即各自區域的均值與中值相近。公式表示爲:
dist(灰度,中值)>dist(均值,中值)&& dist(灰度,均值)>dist(均值,中值)
需要調整灰度值。即:
重建後的灰度值=0.5×(均值+中值)
2、對於區域4和區域5的點,將它們全部投影到fOh平面,可以看到均大致位於對角線區域內,即各自區域的灰度值與中值接近。公式表示爲:
dist(均值,中值)>dist(灰度值,中值)&& dist(均值,灰度值)>dist(灰度值,中值)
需要調整均值。即:
重建後的均值=0.5×(灰度值+中值)
3、對於區域6和區域7的點,將它們全部投影到fOg平面,可以看到均大致位於對角線區域內,即各自區域的灰度值與均值接近。公式表示爲:
dist(中值,灰度值)>dist(灰度值,均值)&& dist(中值,均值)>dist(灰度值,均值)
需要調整中值。然而,爲了使區域6和7的點回到體對角線區域內,申等人將中值直接賦給了灰度值與均值,使三個座標值相等。
完成重建後的三維直方圖如下圖:
在這裏插入圖片描述
可以看到三維直方圖中的絕大部分點規整地回到了體對角線周圍區域內。
下一步進行閾值搜索。
許等人曾設計了一種基於三維最大類間方差的方法,來對三維直方圖進行分割。它的步驟非常簡單,即:
1、對重建後的灰度、均值與中值圖像分別用Otsu法找到閾值,
2、將三個閾值相加,得到閾值之和th。
3、將三維直方圖中的每個點的三個座標值相加,即sum=f+g+h
4、判斷sum與th的大小關係:如果sum≥th,則在分割後的二值圖像中,相應的點爲1(白色);如果sum<th,則在分割後的二值圖像中,相應的點爲0(黑色)。
顯然,此法中,需要3次尋找閾值,計算效率較低。
爲了降低計算複雜度,申等人提出,將每個點所在的,與體對角線垂直的平面與原點的距離作爲分割依據,從而使閾值尋找次數從3次下降到1次。其中,距離公式爲:
d=(f+g+h)/sqrt(3)
由於在最大的情況下,原圖、均值圖、中值圖中最亮的像素都會爲1,所以最大的d會等於sqrt(3),即原始最大灰度級的sqrt(3)倍,爲了將距離顯示成圖像,程序將距離數據進行了歸一化。效果如下圖:
在這裏插入圖片描述
此圖就是下面尋找閾值的依據。
距離圖像的直方圖爲:
在這裏插入圖片描述
可以看到,三維直方圖重建後,待分割的圖像的直方圖出現了明顯的像素數近似爲0的深谷,即隨機分佈的噪聲點得到了抑制,且先前被噪聲削弱的尖峯變得尖銳了。

2、基於高斯分佈擬合的Otsu法優化

顯然,對於已經重建好的直方圖,只需要利用Otsu法找到閾值,然後直接分割就可以了。然而現實還是比較殘酷的,直接分割的結果如下圖:
在這裏插入圖片描述
可以看到,右下角的硬幣仍存在些許的圖案細節,沒有達到完全分割的目的。
在[1]中,提出了一種高斯分佈擬合直方圖中兩個峯的方法,可以對Otsu法進行優化。
1、使用Otsu法得到初始閾值。
2、將小於閾值的部分看成1組,大於等於閾值的部分看成2組。
3、分別求出1組和2組中,灰度值分佈的均值與方差。
4、通過使用第3步求得的均值與方差,構造高斯概率密度函數。
5、尋找兩個高斯概率密度函數的交點。即,從1組的均值處開始,到2組的均值處結束,判斷1組的高斯概率密度函數值是否小於2組的,如果到某一個值後,1組的小於等於2組的,那麼取該值作爲交點。
6、將第5步求得的交點作爲新的閾值
7、返回第2步,繼續執行到第6步,直到迭代出的閾值不再發生變化爲止(實驗中假設兩個閾值之差不大於0.1即爲不再發生變化)。
下圖爲優化過程:
在這裏插入圖片描述
藍色曲線爲高斯概率密度分佈函數曲線,隨着每一次迭代,函數曲線都在更好地擬合着兩個尖峯。
紅色線段爲Otsu法得到的分割線。
綠色線段爲高斯擬合法迭代出的分割線。
高斯擬合法的效果如下圖:
在這裏插入圖片描述
可以看到,雖然在背景中出現了稀疏的噪聲點,但是5個硬幣的輪廓均已被分割了出來,且內部不含任何圖案。分割效果要強於Otsu法。

3、代碼

在這裏插入圖片描述
上圖爲:3.jpg

f=imread('3.jpg');
f=rgb2gray(f);
f=imnoise(f,'gaussian');
f=imnoise(f,'speckle');
f=single(f);
f=f/255;
[m,n]=size(f);
figure(1),imshow(f);
title('原始圖像');
%原圖直方圖
figure(2),imhist(f);
title('原始圖像直方圖');
%3x3均值濾波,得到每個像素點的均值
mean_mask=fspecial('average');
f_mean=imfilter(f,mean_mask);
%3x3中值濾波,得到每個像素點的中值
f_median=medfilt2(f);
%將所有像素展開成1行m×n列的向量,並以每個像素的灰度、均值、中值爲座標軸,繪製三維直方圖
f_reshape=reshape(f,1,m*n);
f_mean_reshape=reshape(f_mean,1,m*n);
f_median_reshape=reshape(f_median,1,m*n);
figure(3),scatter3(f_reshape,f_mean_reshape,f_median_reshape,1);
title('原始圖像三維直方圖');
%進行三維直方圖重建,即將散在的點聚集到體對角線上
for i=1:m*n
    %計算每個像素點三個屬性(灰度、均值、中值)之間的關係
    %某點灰度與均值的距離
    gray2mean=abs(f_reshape(i)-f_mean_reshape(i));
    %某點灰度與中值的距離
    gray2median=abs(f_reshape(i)-f_median_reshape(i));
    %某點均值與中值的距離
    mean2median=abs(f_mean_reshape(i)-f_median_reshape(i));
    if gray2mean>mean2median && gray2median>mean2median
        f_reshape(i)=0.5*(f_mean_reshape(i)+f_median_reshape(i));
    elseif gray2mean>gray2median &&  mean2median>gray2median
        f_mean_reshape(i)=0.5*(f_reshape(i)+f_median_reshape(i));
    elseif gray2median>gray2mean && mean2median>gray2mean
        f_reshape(i)=f_median_reshape(i);
        f_mean_reshape(i)=f_median_reshape(i);
    end
end
%三維重建後的三維直方圖
figure(4),scatter3(f_reshape,f_mean_reshape,f_median_reshape,1);
title('重建後的三維直方圖');
%求三維直方圖中每個點所在分割平面到原點的距離
dist=sqrt(3)/3*(f_reshape+f_mean_reshape+f_median_reshape);
%將距離顯示成直觀圖像
dist_show=reshape(dist,m,n);
%由於計算距離後,圖像值域從0到1變爲了0到sqrt(3),所以需要歸一化回0到1之間
dist_show=dist_show/max(dist);
figure(5),imshow(dist_show);
title('三維直方圖中每個點所在垂直於體對角線的平面與原點的距離圖像');
histogram=imhist(dist_show);
figure(6),imhist(dist_show);
title('三維直方圖重建後的距離圖像直方圖');
axis([0 1 0 5000]);
%基於高斯擬合的Otsu分割法優化
%Otsu法得到初始閾值
thresh_otsu=graythresh(dist_show);
%初始閾值分割結果
figure('Name','Otsu分割圖'),imshow(dist_show>=thresh_otsu);
title('對距離圖像的Otsu分割結果');
%繪製直方圖
figure('Name','直方圖'),stem(histogram/(m*n));
axis([0 255 0 5000/(m*n)]);
thresh=thresh_otsu*255;
hold on;
plot([thresh,thresh],[0,0.01],'r');
%保存所有灰度級的出現概率,即某灰度級的像素數/像素總數
probability_per_intensity=single(histogram/(m*n));
%設置最大迭代數
max_epoch=20;
%保存所有迭代出的閾值
thresh_all=zeros(1,max_epoch,'single');
thresh_all(1)=thresh;
%從初始閾值開始,迭代更新閾值
for i=1:max_epoch
    thresh_all(i+1)=epoch(dist_show,thresh_all(i),probability_per_intensity,i);
    if abs(thresh_all(i+1)-thresh_all(i))<0.1
        thresh_result=thresh_all(i+1);
        break;
    end
end
figure('Name','高斯擬合的Otsu法優化,最終圖像'),imshow(dist_show>=thresh_result/255);

function thresh=epoch(f,thresh_input,probability_per_intensity,i)
%將所有灰度根據閾值分割成兩部分,並求出每個部分的概率
probability_group0=sum(probability_per_intensity(1:round(thresh_input)+1));
probability_group1=1-probability_group0;
%求被閾值分割開的兩部分的均值
mean_0toThresh=sum((1:round(thresh_input)+1)'.*probability_per_intensity(1:round(thresh_input)+1));
mean_all=mean(f,'all')*255;
mean_group0=mean_0toThresh/probability_group0;
mean_group1=(mean_all-mean_0toThresh)/probability_group1;
%求被閾值分割開的兩部分的方差
variance_group0=sum(probability_per_intensity(1:round(thresh_input)+1)'.*((1:round(thresh_input)+1)-mean_group0).^2)/probability_group0;
variance_group1=sum(probability_per_intensity(round(thresh_input)+2:end)'.*((round(thresh_input)+2:256)-mean_group1).^2)/probability_group1;
% 對兩個部分分別利用其均值與方差構建高斯概率密度函數
gauss_group0=1/sqrt(2*pi*variance_group0)*gaussmf(0:255,[sqrt(variance_group0),mean_group0]);
gauss_group1=1/sqrt(2*pi*variance_group1)*gaussmf(0:255,[sqrt(variance_group1),mean_group1]);
hold on;
plot(gauss_group0,'b');
hold on;
plot(gauss_group1','b');
thresh=0;
% 尋找兩個高斯概率密度函數的交點
for j=mean_group0:mean_group1
    if 1/(sqrt(2*pi*variance_group0))*gaussmf(j,[sqrt(variance_group0),mean_group0]) <= ...
       1/(sqrt(2*pi*variance_group1))*gaussmf(j,[sqrt(variance_group1),mean_group1])
        thresh=j;
        break;
    end
end
hold on;
plot([thresh,thresh],[0,0.01],'g');
end
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章