数字图像处理(八)——Matlab实现单阈值与多阈值分割

青春壹個敷衍的年華 提交于 2020-02-01 10:30:32

实验内容

对左侧图像进行单阈值、多阈值分割,分别得到右侧的结果。请大家实现这两种方法的分割,对比单阈值与多阈值以及不同阈值的分割效果。
在这里插入图片描述

实验一:单阈值分割

方法一:人工阈值选择法:

阈值分割最简单的方法就是人工选择法。基于灰度阈值的分割方法,其关键是如何合理的选择阈值。人工选择方法是通过人眼的观察,应用人对图像的知识,在分析图像直方图的基础上,人工选择出合理的阈值。也可以在人工选择出阈值后,根据分割的效果,不断地进行交互操作,从而选择出最佳的阈值。首先,图像的原图如下:
在这里插入图片描述
其次,利用imhist()函数显示出图像的灰度直方图:
在这里插入图片描述
通过观察图像灰度直方图可以发现,在150-200之间的灰度值出现很少,而在两边出现了明显的两个高峰,因此根据人工选择阈值法选取183作为图像的阈值分割点,得到的实验效果图如下图所示:
在这里插入图片描述
通过观察可以发现人工阈值选择法成功得出了实验效果图,利用灰度直方图的峰谷阈值方法是一种有效且简单的阈值方法,但是该方法有一个局限性,就是要求图像的灰度直方图必须具有双峰型。

方法二:Ostu法:

Ostu法是一种使类间方差最大的自动确定阈值的方法,该方法具有简单、处理速度快的特点,是一种常用的阈值选取方法。算法的具体步骤如下:
1、给定一个初始阈值Th,将图像分为C1和C2两类。
2、分别计算出每个灰度值在图像矩阵中的个数,存放在count()矩阵当中。
3、计算每个灰度值在总矩阵中所占的比例,存放在pcount中,同时计算出图像总体的灰度均值,用dw表示。
4、初始化阈值从0开始遍历,利用while循环遍历找出最佳阈值,不断进行计算类间方差的运算,直至找出最大类间方差对应的Th阈值作为最佳阈值。
5、将小于Th的灰度值赋值为0,大于Th的灰度值赋值为255,得出处理后的实验图像如下图所示:

在这里插入图片描述
根据实验结果可以发现Ostu方法不需要人工选择最佳阈值,而通过计算最大类间方差来自动得出最佳阈值,且效果很好。

代码附录如下:

%%
%人工阈值选择法
clc;
clear all;
close all;
I1 = imread('01.png');
I=rgb2gray(I1);
imshow(I),title('原图','fontsize',16);
figure;
imhist(I),title('原图灰度直方图','fontsize',16);
[m,n]=size(I);
I1=I;
for i=1:m
    for j=1:n
        if(I(i,j)<183)
            I1(i,j)=0;       
        else
            I1(i,j)=255;
        end
    end
end
figure;
imshow(I1),title('人工阈值分割','fontsize',16);

%%
%Ostu法阈值分割
clc
clear all;
I1 = imread('01.png');
I1=rgb2gray(I1);
I1=double(I1);
figure,imshow(uint8(I1)),title('原图','fontsize',16);
[m,n]=size(I1);
Th=Otsu(I1);
Th
for i=1:m
    for j=1:n
        if I1(i,j)>=Th
            I1(i,j)=255;
        else
            I1(i,j)=0;
        end
    end
end
figure,imshow(I1),title('Ostu法阈值分割','fontsize',16);

function T=Otsu(I1)
[m,n]=size(I1);
I1=double(I1);
count=zeros(256,1);
pcount=zeros(256,1);
for i=1:m
    for j=1:n
        pixel=I1(i,j);
        count(pixel+1)=count(pixel+1)+1; %计算每个灰度值的个数
    end
end
dw=0;
for i=0:255
    pcount(i+1)=count(i+1)/(m*n);%计算每个灰度值在总矩阵中所占的比例,存放在pcount中
    dw=dw+i*pcount(i+1);%计算出图像总体的灰度均值
end
Th=0;%初始化阈值从0开始遍历
Thbest=0;%初始化最佳阈值为0
dfc=0;
dfcmax=0;
while(Th>=0 && Th<=255)%while循环找出最佳阈值
    dp1=0;
    dw1=0;
    for i=0:Th
        dp1=dp1+pcount(i+1);%计算出小于Th阈值的比例
        dw1=dw1+i*pcount(i+1);%算出小于阈值Th部分的灰度均值
    end
    if dp1>0%如果小于Th阈值的比例不为0
        dw1=dw1/dp1;
    end
    dp2=0;
    dw2=0;
    for i=Th+1:255
        dp2=dp2+pcount(i+1);%计算出大于Th阈值的比例
        dw2=dw2+i*pcount(i+1);%算出大于阈值Th部分的灰度均值
    end
     if dp2>0
        dw2=dw2/dp2;
     end
    dfc=dp1*(dw1-dw)^2+dp2*(dw2-dw)^2;%计算类间方差
    if dfc>=dfcmax %去类间方差的最大值作为最佳阈值
    dfcmax=dfc;
    Thbest=Th;
    end
    Th=Th+1;
end
T=Thbest;
end
         

实验二:多阈值分割

在Ostu单阈值分割的基础上,我想根据单阈值的分割方法,来实现Ostu多阈值分割,我的想法是既然可以用Ostu单阈值分割得出一个阈值,那么用这个阈值作为分界线,将图像分为两部分,分别进行单阈值分割,则又可得到两个阈值,即可将图像分为四部分,算法实现效果图如下图所示:
在这里插入图片描述
根据实验结果可以发现基本实现了图像的多阈值分割,但分割效果并不是很理想,还需继续改进。

多阈值分割代码如下:

%%
%多阈值分割
clc;
clear all;
I1 = imread('01.png');
I1=rgb2gray(I1);
I2=I1;
I1=double(I1);
figure,imshow(uint8(I1)),title('原图','fontsize',16);
[m,n]=size(I1);
I1=double(I1);
Th=161;
count=zeros(256,1);
pcount=zeros(256,1);
for i=1:m
    for j=1:n
        pixel=I1(i,j);
        count(pixel+1)=count(pixel+1)+1; %计算每个灰度值的个数
    end
end
dw=0;
x=0;
for i=1:m
    for j=1:n
        if(I1(i,j)<Th)
            x=x+1;
        end
    end
end

for i=0:Th
    pcount(i+1)=count(i+1)/x;%计算每个灰度值在总矩阵中所占的比例,存放在pcount中
    dw=dw+i*pcount(i+1);%计算出图像总体的灰度均值
end
Th1=0;%初始化阈值从0开始遍历
Thbest=0;%初始化最佳阈值为0
dfc=0;
dfcmax=0;
while(Th1>=0 && Th1<=Th)%while循环找出最佳阈值
    dp1=0;
    dw1=0;
    for i=0:Th1
        dp1=dp1+pcount(i+1);%计算出小于Th阈值的比例
        dw1=dw1+i*pcount(i+1);%算出小于阈值Th部分的灰度均值
    end
    if dp1>0%如果小于Th阈值的比例不为0
        dw1=dw1/dp1;
    end
    dp2=0;
    dw2=0;
    for i=Th1+1:Th
        dp2=dp2+pcount(i+1);%计算出大于Th阈值的比例
        dw2=dw2+i*pcount(i+1);%算出大于阈值Th部分的灰度均值
    end
     if dp2>0
        dw2=dw2/dp2;
     end
    dfc=dp1*(dw1-dw)^2+dp2*(dw2-dw)^2;%计算类间方差
    if dfc>=dfcmax %去类间方差的最大值作为最佳阈值
    dfcmax=dfc;
    Thbest=Th1;
    end
    Th1=Th1+1;
end
T1=Thbest;
T1

Th=161;
count1=zeros(256,1);
pcount1=zeros(256,1);
for i=1:m
    for j=1:n
        pixe2=I2(i,j);
        count1(pixe2+1)=count1(pixe2+1)+1; %计算每个灰度值的个数
    end
end
dw=0;
x=0;
for i=1:m
    for j=1:n
        if(I2(i,j)>Th)
            x=x+1;
        end
    end
end
for i=Th:255
    pcount1(i+1)=count1(i+1)/x;%计算每个灰度值在总矩阵中所占的比例,存放在pcount中
    dw=dw+i*pcount1(i+1);%计算出图像总体的灰度均值
end
Th2=Th;%初始化阈值从0开始遍历
Thbest=0;%初始化最佳阈值为0
dfc=0;
dfcmax=0;
while(Th2>=Th && Th2<=255)%while循环找出最佳阈值
    dp1=0;
    dw1=0;
    for i=Th:Th2
        dp1=dp1+pcount1(i+1);%计算出小于Th阈值的比例
        dw1=dw1+i*pcount1(i+1);%算出小于阈值Th部分的灰度均值
    end
    if dp1>0%如果小于Th阈值的比例不为0
        dw1=dw1/dp1;
    end
    dp2=0;
    dw2=0;
    for i=Th2+1:255
        dp2=dp2+pcount1(i+1);%计算出大于Th阈值的比例
        dw2=dw2+i*pcount1(i+1);%算出大于阈值Th部分的灰度均值
    end
     if dp2>0
        dw2=dw2/dp2;
     end
    dfc=dp1*(dw1-dw)^2+dp2*(dw2-dw)^2;%计算类间方差
    if dfc>=dfcmax %去类间方差的最大值作为最佳阈值
    dfcmax=dfc;
    Thbest=Th2;
    end
    Th2=Th2+1;
end
T2=Thbest;
T2
I3=I2;
for i=1:m
    for j=1:n
        if (I2(i,j)>=0 && I2(i,j)<T1)
            I3(i,j)=255;
        else if(I2(i,j)>=T1 && I2(i,j)<Th)
            I3(i,j)=170;
             else if(I2(i,j)>=Th && I2(i,j)<T2)
            I3(i,j)=85;
            else if(I2(i,j)>=T2 && I2(i,j)<255)
            I3(i,j)=0;
                end
                 end
            end           
        end
    end
end

figure;
imshow(I3),title('Ostu多阈值分割','fontsize',16);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!