demo:图像处理 matlab实现迭代法全局阈值分割和局部自适应阈值分割

全局阈值分割

迭代法阈值获取方法:
1)选取一个的初始估计值T(128);
2)用T分割图像。这样便会生成两组像素集合:G1由所有灰度值大于T的像素组成,而G2由所有灰度值小于或等于T的像素组成。
3)对G1和G2中所有像素计算平均灰度值u1和u2。
4)计算新的阈值:T=1/2(u1 + u2)。
重复步骤(2)到(4),直到得到的T值之差小于一个事先定义的参数T0。

先导进来图片

I = imread('rice.png');
[width,height] = size(I);
T0 = 1;%设置门限
T1= 128; %初始阈值T1
%设置G1,G2两个列向量,各自统计<T和>T的值
gray_leval_1 = 1;
gray_leval_2 = 1;

matlab里没有do-while语句,所以用
while 1

break
代替

while 1
    for i = 1:width
        for j = 1:height
            if I(i,j)>T1
                G1(gray_leval_1) = I(i,j); %得到分组G1
                gray_leval_1 = gray_leval_1 + 1;
            else
                G2(gray_leval_2) = I(i,j); %得到分组G2
                gray_leval_2 = gray_leval_2 + 1;
            end
        end
    end
    %计算G1、G2均值
    avg1 = mean(G1);
    avg2 = mean(G2);
    T2 = (avg1 + avg2)/2;
    if abs(T2 - T1)<T0 
        break;
    end
    T1 = T2;
    gray_leval_1 = 1;
    gray_leval_2 = 1;
end
T1
T1=uint8(T1);

T1=130.7
然后画出来

for i=1:width
    for j=1:height
        if(I(i,j)<T1)
            BW1(i,j)=0;
        else 
            BW1(i,j)=1;
        end
    end
end
subplot(1,3,1);imshow(I)
subplot(1,3,2);imshow(BW1);title('阈值分割');

matlab自带的Otus阈值分割方法

T3=graythresh(I)
BW2=imbinarize(I,T3);%Otus阈值分割
subplot(1,3,3);imshow(BW2);title('Otus阈值分割');

I=130.9,差不多哈。
结果
在这里插入图片描述

这个阈值分割方法存在偏差,如果两个峰值数目相差越多,偏差越大
(假设第一次迭代前,T在正确位置,很容易看出来,随着迭代进行,越来越偏离)
在这里插入图片描述
计算的T=93,目测值应该在110-120吧。

多说一句,图像处理,一定要double一下,否则可能出现问题。比如,我想把大米图的直方图暗部拉大(偏向0),以体现这种偏差,就用了个一次函数的变换,结果这样了

在这里插入图片描述

因为先乘k,结果>255的全归于255,以后全错。

自适应阈值分割

1)将整幅图像分成一系列互相之间有50%重叠的子图像;
2)做出每个子图像的直方图;
3)检测各个子图像的直方图是否为双峰,如果是,则采用最佳阈值法确定一个阈值,否则就不进行处理;
4)根据对直方图为双峰的子图像得到的阈值通过插值得到所有子图像(像素点)的阈值。
仨坑
1、怎么割图像啊(这个还好吧,也不算割,设置好步长来就行了)
2、怎么检测单峰还是双峰啊,单峰的话,空缺imresize是不行的。
3、怎么插值啊(主要是老师上课讲的太玄学,按照距离加权,四点平均,把相距很远的点内部全部插满,听懵了。后来想到,matlab直接imresize啊!然后就码下来啦)
1、分割方式设置好矩形大小和步长就行
2、峰值个数没写,matlab统计工具箱里好像有正态拟合图像,而不是plot()这种拟合,plot拟合只是画的圆滑了些还是很多局部峰值
在这里插入图片描述
3、插值方式采用了imresize函数
A=imresize(I,2,‘nearest’);%最近邻插值
B=imresize(I,2,‘bilinear’);%双线性
C=imresize(I,2,‘bicubic’);%双三次

I=imread('rice.png');
T=zeros(15);
for i=0:14
    for j=0:14
        img = imcrop(I,[1+i*16 1+j*16 31 31]);%内核32*32,步长设置为16
        t=255*graythresh(img);%我这里直接用了
        T(j+1,i+1)=t;%这里注意坐标顺序反着
    end
end
T=uint8(T);
T1=imresize(T,[256 256],'bilinear');%看了下貌似双线性插值最好
%%
for i=1:256
    for j=1:256
        if (I(i,j)<T1(i,j))
            BW(i,j)=0;
        else
            BW(i,j)=1;
        end
    end
end
imshow(BW)

有一个地方要注意,图像[i,j],矩阵得是[j,i]。

阈值图像:
在这里插入图片描述
底部更暗,所以阈值也更低才能滤完整
阈值分割结果
在这里插入图片描述
嗯,上部噪声少了,下部也更完整了
然后试了下这位兄弟博客的图片
这老哥跑的OPENCV中自带的函数,效果一级棒(怎么看着像边缘检测)
我这个…毕竟没字的地方有黑背景有白背景,一加权,也没法搞,不过还阔以吧
在这里插入图片描述

matlab中自带的阈值分割,对大米图还行。全局阈值分割底部大米都割残了,这个方法完整,可是,这跟局部有关系?貌似先调了调灰度,就好分割了

 I=imread('rice.png');
 I=im2double(I);
se=strel('disk',10);%se.Neighborhood:10*10圆盘
ft=imtophat(I,se);% 高帽变换
gt=uint8(255*ft);
Th=graythresh(ft);                       
G=imbinarize(ft,Th);%阈值分割                       
figure,imshow(G),title('局部阈值');

在这里插入图片描述

Otsu算法

matlab自带的阈值分割方法
参考动态阈值–大津法基于Otsu算法的图像自适应阈值分割,重新打了一下
调用:

[counts x] = imhist(img);
[m n] = size(img);
BW1 = otsu(counts, m*n);
第一个元素为直方图,第二个元素为图片大小
或者:
T=graythresh(I)
BW2=imbinarize(I,T);

原理:
在这里插入图片描述

在这里插入图片描述
让T遍历所有灰度值,找到g的最大值
代码:

function level = otsu(histogramCounts, total)%histogramCounts是图像的直方图, total图像的总像素数
sum0 = 0;
w0 = 0;%像素个数
maximum = 0.0;%保存T的最大值
total_value = sum((0:255).*histogramCounts');
for ii=1:256
    w0 = w0 + histogramCounts(ii);%<T像素个数累加
    if (w0 == 0)
        continue;
    end
    w1 = total - w0;
    if (w1 == 0)%遍历结束>T像素=0
        break;
    end
    sum0 = sum0 +  (ii-1) * histogramCounts(ii);%灰度和
    m0 = sum0 / w0;%平局灰度u0
    m1 = (total_value - sum0) / w1;%平局灰度u1
    icv = w0 * w1 * (m0 - m1) * (m0 - m1);
    if ( icv >= maximum )
        level = ii;
        maximum = icv;
    end
end
end
  • 46
    点赞
  • 308
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
好的,我会帮您完成这个任务。 首先,您可以在 MATLAB 中打开“Image Processing Toolbox”中的“实战分割:标记控制的分水岭分割”Demo。该 Demo 旨在演示如何使用分水岭算法进行图像分割,并使用标记控制方法来提高分割效果。 接下来,我将为您解释每个函数的作用并展示如何使用它们。请注意,以下函数均属于 MATLAB 的“Image Processing Toolbox”。 1. `imread()`:读取图像文件。 2. `rgb2gray()`:将 RGB 彩色图像转换为灰度图像。 3. `im2double()`:将图像转换为 double 类型,以便进行数学计算(例如除法运算)。 4. `imadjust()`:调整图像的对比度和亮度。 5. `imerode()`:对二进制图像进行腐蚀操作。 6. `imfill()`:填充二进制图像中的空洞。 7. `imclose()`:对二进制图像进行闭合操作。 8. `bwdist()`:计算二进制图像中每个像素到最近非零像素的距离。 9. `watershed()`:基于分水岭算法进行图像分割。 10. `label2rgb()`:将标记图像转换为 RGB 彩色图像。 接下来,我将展示如何使用这些函数实现Demo: ```matlab % 读取图像文件 I = imread('coins.png'); % 将 RGB 彩色图像转换为灰度图像 Igray = rgb2gray(I); % 将图像转换为 double 类型 Igray = im2double(Igray); % 调整图像的对比度和亮度 Igray = imadjust(Igray); % 对图像进行腐蚀操作 se = strel('disk', 20); Ierode = imerode(Igray, se); % 填充二进制图像中的空洞 Ifill = imfill(Ierode, 'holes'); % 对二进制图像进行闭合操作 se2 = strel('disk', 20); Iclose = imclose(Ifill, se2); % 计算二进制图像中每个像素到最近非零像素的距离 D = bwdist(Iclose); % 基于分水岭算法进行图像分割 L = watershed(-D); % 将标记图像转换为 RGB 彩色图像 Lrgb = label2rgb(L, 'jet', 'w', 'shuffle'); % 显示原始图像和分割结果 figure; subplot(1,2,1), imshow(I); subplot(1,2,2), imshow(Lrgb); ``` 运行上述代码后,您将看到原始图像和分割结果的显示。您可以根据需要更改输入图像和参数来优化分割效果。 希望这篇回答对您有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值