【原创】【论文复现】【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

猜你喜欢

转载自blog.csdn.net/u011861755/article/details/85481812