实验内容
对左侧图像进行单阈值、多阈值分割,分别得到右侧的结果。请大家实现这两种方法的分割,对比单阈值与多阈值以及不同阈值的分割效果。
实验一:单阈值分割
方法一:人工阈值选择法:
阈值分割最简单的方法就是人工选择法。基于灰度阈值的分割方法,其关键是如何合理的选择阈值。人工选择方法是通过人眼的观察,应用人对图像的知识,在分析图像直方图的基础上,人工选择出合理的阈值。也可以在人工选择出阈值后,根据分割的效果,不断地进行交互操作,从而选择出最佳的阈值。首先,图像的原图如下:
其次,利用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);
来源:CSDN
作者:小明同学爱学习
链接:https://blog.csdn.net/weixin_44244154/article/details/103671535