所谓的最终腐蚀并不是把图像不断腐蚀直到一片黑为止,那样还有什么意思呢。
最终腐蚀的意思是连续腐蚀过程中连通子区域消失前所有剩余部分的并。
看下图有一个连通区域:
那么最终腐蚀就是把图像不断腐蚀到只剩圆环最中间的白色区域为止。如下:
所以一般最终腐蚀之后,如果再腐蚀一下,那么图像就全没了。
最终腐蚀的通常算法会先对原图像使用距离变换,然后求区域极大值。不过这种方法怎么说呢,速度倒是快,不过我实验了很多次,求得的结果很不稳定。
所以我就自己开发了一个算法,虽然有些慢,不过很稳定。
1.首先对原图像进行连通区域标记。
2.对标记后图像不断进行腐蚀,每腐蚀一次,重新标记连通区域。
3.每腐蚀并且标记一次之后,检查腐蚀后的图像是否有哪一个标记的区域消失了,如果消失了,那么就把消失这一区域的最后一次出现的区域恢复。
4.直到下次腐蚀和这次腐蚀结果一样,程序结束。
运行效果如下:
原图:
最终腐蚀:
matlab代码如下:
clear all; close all; clc; img=imread('te.png'); img=img>128; imshow(img); [m n]=size(img); imgn=zeros(m,n); preimg=imgn; se= strel('square',3); while sum(sum(preimg-img))~=0 preimg=img; img=img>0; [img label]=liantong(img); %标记不同区域,label是区域个数 imgn=imerode(img,se); %腐蚀之后是否有哪个被标记的区域消失了 Hist=zeros(1,label); for i=1:m for j=1:n if imgn(i,j)~=0 Hist(imgn(i,j))=imgn(i,j); end end end %统计消失区域的标号 H=[]; for i=1:label if Hist(i)==0 H=[H i]; end end %如果这个区域消失了,那么再把这个区域恢复过来 if ~isempty(H) l=length(H); for i=1:m for j=1:n for k=1:l if img(i,j)==H(k) imgn(i,j)=img(i,j); end end end end end img=imgn; end figure; imshow(imdilate(imgn>0,se)); %再膨胀一下好看
有了最终腐蚀与条件膨胀,那么分水岭算法的实现也就近在眼前了。