设计利用区域生长算法进行图像分割的程序
1、目的:把一幅图像划分成满足某种判据的一些区域,在这里形成一个二值图。
2、原理:首先确定每个区域中的某个已知点,加上与已知点相似的邻近点形成一个区域,在这里利用区域的均值。当邻近点与区域均值的差值的绝对值小于阈值T 时,即满足生长条件。方法是从种子点开始,在8连通方向上生长区域,当其邻近点满足生长条件,则就并入小快区域,当新的点被合并后再用新的区域重复这一过程,直到没有可接受的邻近点时该区域生成过程终止。
3、设计思路:
1)通过具体观察某幅图像的直方图,估计其确定种子点范围[S1,S2],并确定其阈值T;
2)透过对整幅图像的扫描,找出某个区域的一个种子点:(.)f x y
3)开始利用8连通方向,以该种子点为中心进行生成区域;[(),()]s r s θ
|(,)(.)|diff f i j f x y T =-<(,)ave f i j =
4)继续用8连通方向,以该区域为中心,把邻近满足生长条件的点并入,生成新的区域; 1(,)k
ave f i j k =∑ |(,)|diff f i j ave T ''=-<
5)重复4)步,直到不再存在邻近满足生长条件的点为止,该区域生成过程结束;
6)继续对图像进行扫描,寻找其他区域的一个种子点,按3)~5)的步骤进行
4、程序设计
根据下面的流程图可分为
区域生长算法实现流程图
5、程序
%district.m主函数
clear
clc
I = imread('bacteria.tif');
subplot(1,2,1)
imshow(I)
title('初始图像');
subplot(1,2,2)
imhist(I)
title('初始图像的直方图');
%透过该直方图确定种子满足S1~S2 的值(灰度值)和判定的依据阈值T
S1=8;S2=70;T=33;
f=double(I);
[m,n]=size(I);
shed1=zeros(3,round(m*n/2)); %存储区域生长方向上的点和该区域的均值的绝对差值和
该%点的坐标
sp1=0; % sp1 相当于指针,指向shed1 中的最后放入的值和坐标
shed2=zeros(2,m); %存储符合生长条件的点的坐标
sp2=0; % sp2 指针,指向shed2 中的最后放入点的坐标
Cut=zeros(size(f)); % Cut 为区域生长后的新图像
Cut=Cut+255; % Cut 矩阵初始值设为255
vb=0; %标记值,当vb=1 时,即要求重新计算已有的栈shed1(1,:) 的大小
for i=1:m
for j=1:n
if (f(i,j)>S1&f(i,j) 已% 有生长区域 Cut(i,j)=0; % 0 时,标记该点在原图像的对应点已并入生长区域 ave=f(i,j); %确定新区域的均值的起始值 k=1; %设置生成的区域的象素个数 [Cut,shed1,sp1,vb]=ruzhan(f,Cut,shed1,sp1,ave,i,j,m,n,vb); %把周围的8 个点 入%栈 [shed1,sp1]=arrange(shed1,sp1); %对栈shed1 的数据进行由大到小的排序 [shed1,sp1,shed2,sp2]=listed(shed1,sp1,T,shed2,sp2); %% 确定符合条件的 生%%长点,将它从shed1 中取出,并放入shed2 中end % 根据生长点开始用8 连通方式进行生长 while (sp2~=0) %当sp2=0 时表示找不到符合的点, if (sp2~=0) %当有新的值加入区域时,求新的平均值 sum=ave*k; for t=1:sp2 x=shed2(1,t); y=shed2(2,t); sum=sum+f(x,y); k=k+1; end ave=sum/k; end for t=1:sp2 %合并栈shed2 中的点,生成新的区域 x=shed2(1,t); y=shed2(2,t); Cut(x,y)=0; [Cut,shed1,sp1,vb]=ruzhan(f,Cut,shed1,sp1,ave,x,y,m,n,vb); end sp2=0; [shed1,sp1]=arrange(shed1,sp1); [shed1,sp1,shed2,sp2]=listed(shed1,sp1,T,shed2,sp2); end % 在一片区域生成之后,对栈shed1(1,:)中未并入区域的值进行处理 if (sp1~=0) for t=1:sp1 x=shed1(2,t); y=shed1(3,t); Cut(x,y)=255; end sp1=0; shed1=zeros(3,round(m*n/2)); end end end II=uint8(Cut); figure; imshow(II); title('区域生长后的图像(黑色部分)'); %------------------------------------------------------------- function [shed1,sp1,shed2,sp2]=listed(shed11,sp11,T,shed21,sp21) % 确定符合条件的生长点,将它从shed1 中取出,并放入shed2 中 shed1=shed11; sp1=sp11; shed2=shed21; sp2=sp21; while ((sp1~=0)&(shed1(1,sp1)<=T)) %确定shed1 不为空,且存在符合生长条件的点sp2=sp2+1; shed2(1,sp2)=shed1(2,sp1); shed2(2,sp2)=shed1(3,sp1); sp1=sp1-1; end %----------------------------------------------------------------- function [shed1,sp1]=arrange(shed11,sp11) % 排序 shed1=shed11; sp1=sp11; % 根据shed1(1,:)的大小,重新排列shed1,按由大到小的顺序 for i=1:sp1-1 maxvalue=shed1(1,i); x=shed1(2,i); y=shed1(3,i); for j=i+1:sp1 if maxvalue shed1(1,i)=shed1(1,j); shed1(2,i)=shed1(2,j); shed1(3,i)=shed1(3,j); shed1(1,j)=maxvalue; shed1(2,j)=x; shed1(3,j)=y; maxvalue=shed1(1,i); x=shed1(2,i); y=shed1(3,i); end end end %----------------------------------------------------------------------- function [Cut,shed1,sp1,vb]=ruzhan(f,Cut1,shed11,sp11,ave,i,j,m,n,vb1) % 入栈 Cut=Cut1; shed1=shed11; sp1=sp11; vb=vb1; if (vb==1) %重新计算已有的栈shed1(1,:) 的大小 for t=1:sp1 shed1(1,t)=abs(f(shed1(2,t),shed1(3,t))-ave); end vb=0; end %把新的生长方向上的点存入矩阵zb for x=i-1:i+1 for y=j-1:j+1 if (x>0&x<=m&y>0&y<=n&Cut(x,y)==255) % 排除已经的生长区域上的点,或 者%已入栈的点,以及防止出界diff=abs(f(x,y)-ave); %该点灰度值和均值的绝对差值 %插入shed1 栈中 sp1=sp1+1; %指向新的入栈点 shed1(1,sp1)=diff; shed1(2,sp1)=x; shed1(3,sp1)=y; Cut(x,y)=125; %标记已入栈的点 end end end 6、结果 7、结论 1)基本实现了区域分割的目的; 2)若是种子灰度值和阈值设置妥当,可将一幅图像分成多灰度级的灰度图,同理,也可对 彩色图像进行处理; 3)由于各个图像其特征不同,在种子、阈值上的选取也会有所不同,要根据具体情况而定。4)在这里,种子选取了满足一小段特定灰度值的点,已避免漏过某些模糊区域,(因不含某个灰度值的点而漏过); 5)该算法不足之处是运算量大,占用时间多。