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

实验内容

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

实验一:单阈值分割

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

阈值分割最简单的方法就是人工选择法。基于灰度阈值的分割方法,其关键是如何合理的选择阈值。人工选择方法是通过人眼的观察,应用人对图像的知识,在分析图像直方图的基础上,人工选择出合理的阈值。也可以在人工选择出阈值后,根据分割的效果,不断地进行交互操作,从而选择出最佳的阈值。首先,图像的原图如下:
在这里插入图片描述
其次,利用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);
  • 45
    点赞
  • 252
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
细胞图像的分割和计数是医学图像处理中的一个重要问题,这里介绍一种MATLAB实现细胞分割的方法。以下是具体步骤: 1. 读取图像和预处理 使用MATLAB中的imread函数读取细胞图像,并将其转换为灰度图像。然后,可以使用函数imadjust来调整图像的对比度和亮度,以便更好地分割细胞。 2. 去除噪声 使用MATLAB中的medfilt2函数对图像进行中值滤波,以去除图像中的噪声。 3. 分割细胞 使用MATLAB中的阈值分割函数imbinarize对图像进行二值化。可以使用MATLAB中的otsu方法自动确定二值化的阈值。对于某些图像,可能需要手动调整阈值。 4. 去除小的对象 使用MATLAB中的bwareaopen函数去除二值图像中的小的对象,以便只保留细胞。 5. 计数细胞 使用MATLAB中的bwlabel函数标记二值图像中的对象,并使用MATLAB中的regionprops函数计算每个对象的中心位置。通过计算对象的数量,可以得到细胞的数量。 下面是MATLAB代码实现: ``` % 读取图像并转换为灰度图像 img = imread('cell_image.png'); gray_img = rgb2gray(img); % 调整图像对比度和亮度 adj_img = imadjust(gray_img); % 去除噪声 filt_img = medfilt2(adj_img); % 二值化图像 thresh_img = imbinarize(filt_img, 'otsu'); % 去除小的对象 clean_img = bwareaopen(thresh_img, 100); % 计数细胞 label_img = bwlabel(clean_img); cell_props = regionprops(label_img, 'Centroid'); cell_count = length(cell_props); % 显示结果 imshow(clean_img); title(['Cell Count: ', num2str(cell_count)]); ``` 在这个例子中,我们假设输入图像为cell_image.png。在实际应用中,可能需要针对不同的细胞图像进行参数调整。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值