图像分割就是把图像分成若干特定的、具有独特性质的区域并提取出感兴趣目标的技术和过程,它是图像处理到图像分析的关键步骤。区域生长需要选择一组能正确代表所需区域的种子像素,确定在生长过程中的相似性准则,制定让生长停止的条件或准则。相似性准则可以是灰度级、彩色、纹理、梯度等特性。选取的种子像素可以是单个像素,也可以是包含若干像素的小区域。大部分区域生长准则使用图像的局部性质。生长准则可根据不同原则制定,而使用不同的生长准则会影响区域的生长过程。区域归并方法是指在通过某种初始化分割方法得到的很多小区域上,根据一定的归并标准将满足归并标准的两个邻接区域合并为一个区域,直到所有满足归并标准邻接区域都归并起来。在分割方法分割图像后,结果中可能存在过分割现象,利用区域归并方法则可以进一步将相邻的区域按照合并准则合并起来。制定合并准则是进行合并的重点。
1.区域生长
区域生长是指将成组的像素或区域发展成更大区域的过程。从种子点的集合开始,这些点的区域增长是通过将与每个种子点有相似属性(强度、灰度级、纹理颜色等)的相邻像素合并到此区域。区域生长是根据事先定义的准则将像素或者子区域聚合成更大区域的过程。其基本思想是从一组生长点开始(生长点可以是单个像素,也可以为某个小区域),将与该生长点性质相似的相邻像素或者区域与生长点合并,形成新的生长点,重复此过程直到不能生长为止。该方法一般有以下3个步骤:
(1)选择合适的生长点;
(2)确定相似性准则即生长准则;
(3)确定生长停止条件。
一般来说,在无像素或者区域满足加入生长区域的条件时,区域生长就会停止。
利用区域生长法对图像进行分割
clear all
close all
A0=imread('football.jpg');
seed=[100,220];%选择起始位置
thresh=16;%相似性选择阈值
A=rgb2gray(A0);
A=imadjust(A,[min(min(double(A)))/255,max(max(double(A)))/255],[]);
A=double(A);
B=A;
[r,c]=size(B);%图像尺寸,r为行数,c为列数
n=r*c;%计算图像中所包含点的个数
pixel_seed=A(seed(1),seed(2));%原图起始点位置
q=[seed(1) seed(2)];%用q来装载起始位置
top=1;%循环判断flag
M=zeros(r,c);%建立一个与原图形同等大小的矩阵
M(seed(1),seed(2))=1;
count=1;%计数器
while top~=0 %循环结束条件
r1=q(1,1);
c1=q(1,2);
p=A(r1,c1);
dge=0;
for i=-1:1
for j=-1:1
if r1+i<=r&&r1+i>0&&c1+j<=c&&c1+j>0
if abs(A(r1+i,c1+j)-p)<=thresh&&M(r1+i,c1+j)~=1
top=top+1;
q(top,:)=[r1+i c1+j];
M(r1+i,c1+j)=1;
count=count+1;
B(r1+i,c1+j)=1;%满足判定条件将B中对应的点赋为1
end
if M(r1+i,c1+j)==0
dge=1;%将dge赋为1
end
else
dge=1;%点在图像外,将dge赋为1
end
end
end
if dge~=1
B(r1,c1)=A(seed(1),seed(2));%将原图像起始位置灰度值赋予B
end
if count >=n
top =1;
end
q=q(2:top,:);
top=top-1;
end
subplot(121)
imshow(A,[])
title('灰度图像')
subplot(122)
imshow(B,[])
title('区域生长法分割图像')
2.区域分裂与合并
区域生长是从某个或者某些像素点出发,最后得到整个区域,进而实现目标提取。分裂合并是区域生长的逆过程:从整个图像出发,不断分裂得到各个子区域,然后再把前景区域合并,实现目标提取。分裂合并的假设是对于一幅图像,前景区域由一些相互连通的像素组成。因此,如果把一幅图像分裂到像素级,那么就可以判定该像素是否为前景像素。当所有像素点或者子区域完成判断以后,把前景区域或者像素合并就可得到前景目标。
假定一幅图像分为若干区域,按照有关区域的逻辑词P的性质,各个区域上所有的像素将是一致的。区域分裂与合并的算法如下:
(1)将整幅图像设置为初始区域;
(2)选择一个区域R,若P(R)错误,则将该区域分为4个子区域;
(3)考虑图像中任意两个或更多的邻接子区域R1,R2,…,Rn;
(4)如果P(R1∪R2∪…∪Rn)正确,则将这n个区域合并为一个区域;
(5)重复上述步骤,直到不能再进行区域分裂和合并。
四叉树分解法是常见的分裂合并算法。令R代表整个图像区域,P代表逻辑词。对R进行分割的方法是反复将分割得到的结果图分成4个区域,直到对任意区域Ri,有P(Ri)=TRUE。也就是说,对整幅图像,对整副图像如果P(R)=FALSE,那么就将该图像分成四等分。对任何区域如果有P(Ri)=FALSE,那么就将Ri分成4等分。如此类推,直到Ri为单个为单个像素。
若只使用分裂,最后可能出现相邻的两个区域具有相同的性质但并没有合并的情况。因此,允许拆分的同时进行区域合并,即在每次分裂后允许其继续分裂或合并,如P(Ri∪Rj)=TRUE,则将Ri和Rj合并起来。当再无法进行聚合或拆分时停止。
在MATLAB中,qtdecomp函数可实现图像的四叉树分解。该函数调用方法如下:
S=qtdecomp(I,Threshold,[MinDim MaxDim])
其中,I是输入图像;Threshold是一个可选参数,如果某个子区域中的最大像素灰度值减去最小像素灰度值大于Threshold设定的阈值,那么继续进行分解,否则停止并返回;[MinDim MaxDim]是可选参数,用来指定最终分解得到的子区域大小;返回值S是一个稀疏矩阵,其非零元素的位置在块的左上角,每一个非零元素值代表块的大小。
对下列矩阵进行四叉树分解。
J=[1 1 1 1 2 3 6 6
1 1 2 1 4 5 6 8
1 1 1 1 10 15 7 7
1 1 1 1 20 25 7 7
20 22 20 22 1 2 3 4
20 22 22 20 5 6 7 8
20 22 20 20 9 10 11 12
22 22 20 20 13 14 15 16];
S=qtdecomp(J,5);
full(S)
ans =
4 0 0 0 2 0 2 0
0 0 0 0 0 0 0 0
0 0 0 0 1 1 2 0
0 0 0 0 1 1 0 0
4 0 0 0 2 0 2 0
0 0 0 0 0 0 0 0
0 0 0 0 2 0 2 0
0 0 0 0 0 0 0 0
对图像进行四叉树分解
I1=imread('liftingbody.png');
S=qtdecomp(I1,0.25);%其中0.25为每个方块所需要达到的最小差值
I2=full(S);
subplot(121);
imshow(I1);
title('原图像')
subplot(122)
imshow(I2)
title('四叉树分解的图像')
在得到稀疏矩阵S后,qtgetblk函数可进一步获得四叉树分解后所有指定大小的子块像素及位置信息。该函数的调用方法为
[vals,r,c]=qtgetblk(I,S,dim)
其中,I为输入的灰度图像;稀疏矩阵S是I经过qtdecomp函数处理的输出结果;dim是指定的子块大小;vals是dimXdimXk的三维矩阵,包含I中所有符合条件的子块数据;r和c均为列向量,分别表示图像I中符合条件子块左上角的纵坐标和横坐标。
J=qtsetblk(I,S,dim,vals)
其中,I为输入的灰度图像;稀疏矩阵S是I经过qtdecomp函数处理的输出结果;dim是指定的子块大小;vals是dimXdimXk的三维矩阵,包含了用来替换原有子块的新子块信息;J是经过子块替换后的新图像。
对图像进行块状的四叉树分解
clear all
close all
I=imread('rice.png');
S=qtdecomp(I,.26);%四叉树分解
blocks=repmat(uint8(0),size(S));%块
for dim=[512 256 128 64 32 16 8 4 2 1]
numblocks=length(find(S==dim));
if(numblocks>0)
values=repmat(uint8(1),[dim dim numblocks]);
values(2:dim,2:dim,:)=0;
blocks=qtsetblk(blocks,S,dim,values);
end
end
blocks(end,1:end)=1;
blocks(1:end,end)=1;
subplot(121)
imshow(I)
title('原始图像')
subplot(122)
imshow(blocks,[])
title('块状四叉树分解图像')