求给定阶数图像形状数及其相应的近似多边形

计算以下边界的阶数为20的形状数及其相应的近似多边形。

在这里插入图片描述

1.链码

链码用于表示由顺次连接的具有指定长度和方向的直线段组成的边界。通常,这种表示基于这些线段的4连接或8连接。每个线段的方向使用科数字编号方案编码,如下图所示。以这种方向性数字序列表示的编码称为佛雷曼链码。
在这里插入图片描述

2.边界追踪

假设: (1)处理的是一值图像,其目标和背景点分别标为1和0; (2)图像已使用值为0的边界填充,因而消除了目标与图像边界合并的可能性。为方便起见,我们仅限于讨论单个区域。通过单独地处理各个区域,该方法可扩展到多个不相交的区域。给定一个二值区域R 或其边界,追踪R的边界或给定边界的算法由如下步骤组成:
1).令起始点b0为图像中左上角标记为1的点。使用c0表示b0西侧的邻点。很明显,c0总是背景点。从c0开始按顺时针方向考察b0的8个邻点。令b1表示所遇到的值为1的第一个邻点,并直接令c1(背景)是序列中b1之前的点。存储b0和b1的位置,以便在步骤5中使用。
2).令b=b1和c=c1。
3).从c开始按顺时针方向行进,令b的8个邻点为n1,n2,…,n8.
4).令b=nk和c=nk-1。
5).重复步骤(3)和步骤(4),直到b=b0且找到的下一个边界点为b1。算法停止时,所找到的b点的序列就构成了排列后的边界点的集合。

3.形状数

链码边界的-次差分取决于起始点。一条基于四方向编码的边界的形状数,定义为最小量级的一一次差分。形状数的阶n定义为其表示的数字个数。此外,对于闭合边界,n为偶数,其值限制了不同形状的数量。一次差分是通过将链码作为循环序列来计算得到的。尽管链码的-次差分与旋转无关,但总体而言,已编码的边界取决于网格的方向。归一化网格方向的一种方法是,使用基本矩形的边对准链码网格。

4.代码

%Write  by 长安 Rjex
I=imread('1.png');
I=rgb2gray(I);
imshow(I); 

%K为阈值化后的图形
K=imbinarize(I,graythresh(I));
[m,n]=size(K);

%% 对图像边界进行提取,此处使用8领域边界追踪算法%找到左上角第一个点
L=find(K'==1,1);
flag_i=ceil(L/n);
flag_j=mod(L,n);
endflag_i = flag_i;  %标记第一个点
endflag_j = flag_j;
clear L; 
%B为边界图,对左上角第一个边界点置为1
B = zeros(m,n);
B(flag_i,flag_j)=1;
oflag_i=flag_i;
oflag_j=flag_j-1;
 
C(:,:,1)=[-1,-1,-1,0,+1,+1,+1,0];
C(:,:,2)=[-1,0,+1,+1,+1,0,-1,-1]; 

k=oflag_i-flag_i;
l=oflag_j-flag_j;
for i = 1:8
    %自适应矩阵    
    h=find(C(:,:,1)==k&C(:,:,2)==l);    
    C2_left(:,:,1) = [C(1,h:end,1) C(1,1:h-1,1)];    
    C2_left(:,:,2) = [C(1,h:end,2) C(1,1:h-1,2)];    
    oflag_i=flag_i+C2_left(1,i,1);    
    oflag_j=flag_j+C2_left(1,i,2);
    if oflag_i==0||oflag_j ==0        
    	continue;   
    end    
    %对检测点和边缘进行迭代    
    if K(oflag_i,oflag_j)==1        
    	t(1) = flag_i;        
    	t(2) = flag_j;        
    	flag_i= oflag_i;        
    	flag_j= oflag_j;        
    	oflag_i = t(1)+C2_left(1,i-1,1);        
    	oflag_j = t(2)+C2_left(1,i-1,2);        
    	B(flag_i,flag_j)=1;        
    	break;    
    end
end
endflag_i2 = flag_i;  %标记第二个点
endflag_j2 = flag_j; 
%使得程序在刚开始执行时跳过结束判定程序
begin_flag = 0;

%对剩余的边界追踪
while flag_i~=endflag_i2||flag_j~=endflag_j2||t(1)~=endflag_i||t(2)~=endflag_j||begin_flag==0
    begin_flag=1;
    k=oflag_i-flag_i;
    l=oflag_j-flag_j;     
    %自适应矩阵
    h=find(C(:,:,1)==k&C(:,:,2)==l);
    C2_left(:,:,1) = [C(1,h:end,1) C(1,1:h-1,1)];        
    C2_left(:,:,2) = [C(1,h:end,2) C(1,1:h-1,2)];            
    for i = 1:8
            oflag_i=flag_i+C2_left(1,i,1);        
            oflag_j=flag_j+C2_left(1,i,2);
            if oflag_i==0||oflag_j ==0
                    continue;        
            end        
            %对检测点和边缘进行迭代        
            if K(oflag_i,oflag_j)==1
                        t(1) = flag_i;
                        t(2) = flag_j;            
                        flag_i= oflag_i;            
                        flag_j= oflag_j;            
                        oflag_i = t(1)+C2_left(1,i-1,1);            
                        oflag_j = t(2)+C2_left(1,i-1,2);            
                        B(flag_i,flag_j)=1;            
                        break;        
            end            
     end
end
clear begin_flag C2_left endflag_i endflag_j endflag_i2 endflag_j2 flag_i flag_j
clear oflag_i oflag_j t l h i k C
figure(1);
imshow(B); 

%%
%%对图像进行重取样
N = 20;  %图像的阶数为20
chainCode=zeros(1,N);
E = zeros(2,N+1);   %E来存储重取样后点的矩阵
%计算偏心率以得到适合的矩形
flag_i = m;flag_j = n;
endflag_i=1;
endflag_j=1;
for i = 1:m
    for j = 1:n
           if B(i,j)==1
                     if i < flag_i
                     	flag_i = i;
                     end          
                     if j < flag_j       
                     	flag_j = j;          
                     end          
                     if i > endflag_i              
                     	endflag_i = i;          
                     end          
                     if j > endflag_j              				 			 
                     	endflag_j = j;          
                     end       
             end    
     end
end
max_i = endflag_i - flag_i;
max_j = endflag_j - flag_j;
flag = max_i/max_j;
%此处选择5*5模板
newk = round(max_i/5);
D = zeros(m,n);
for i = 1:m
    for j = 1:n    
        if B(i,j)==1            
        	D(ceil(i/newk)*newk,ceil(j/newk)*newk)=1;        		
        end    
    end
end
figure(2)
imshow(D); 

%%
%计算图像的链码%找到左上角第一个点
L=find(D'==1,1);
flag_i=ceil(L/n);
flag_j=mod(L,n);
newe=1;E(1)=flag_i;
E(2)=flag_j;
begin_flag = 0;
endflag_i = flag_i;  %标记第一个点
endflag_j = flag_j;
clear L 

C(:,:,1)=[0,-newk,0,+newk];
C(:,:,2)=[-newk,0,+newk,0];
 
C2(:,:,1)=[0,-newk,0,+newk];%用来计算链码
C2(:,:,2)=[+newk,0,-newk,0]; 

%左上角第一个点的左边点
oflag_i=flag_i;
oflag_j=flag_j-newk;
k=oflag_i-flag_i;
l=oflag_j-flag_j; 
for i = 1:4
    %自适应矩阵    
    h=find(C(:,:,1)==k&C(:,:,2)==l);    
    C2_left(:,:,1) = [C(1,h:end,1) C(1,1:h-1,1)];    
    C2_left(:,:,2) = [C(1,h:end,2) C(1,1:h-1,2)];    
    oflag_i=flag_i+C2_left(1,i,1);    
    oflag_j=flag_j+C2_left(1,i,2);    
    if oflag_i==0||oflag_j ==0||oflag_j ==0||oflag_j>n        
    	continue;    
    end    
    %对检测点和边缘进行迭代    
    if D(oflag_i,oflag_j)==1    
        t(1) = flag_i;     %t为前一个点        
        t(2) = flag_j;        
        flag_i= oflag_i;   %此处的flag_i和flag_j为后一个点        
        flag_j= oflag_j;        
        newe = newe+1;        
        E(1,newe) = flag_i;        
        E(2,newe) = flag_j;       
        oflag_i = flag_i+C2_left(1,i-1,1);        
        oflag_j = flag_j+C2_left(1,i-1,2);        
        break;    
    end
end
newi=1;
newk=flag_i-t(1);
newl=flag_j-t(2);
chainCode(1)=find(C2(:,:,1)==newk&C2(:,:,2)==newl)-1;  
while begin_flag==0||endflag_i ~= flag_i||endflag_j ~= flag_j
    begin_flag =1;    
    k=oflag_i-flag_i;    
    l=oflag_j-flag_j;     

    for i = 1:4        
    	%自适应矩阵        
    	h=find(C(:,:,1)==k&C(:,:,2)==l);        
    	C2_left(:,:,1) = [C(1,h:end,1) C(1,1:h-1,1)];        
    	C2_left(:,:,2) = [C(1,h:end,2) C(1,1:h-1,2)];        
    	oflag_i=flag_i+C2_left(1,i,1);        
    	oflag_j=flag_j+C2_left(1,i,2);        
    	if oflag_i==0||oflag_i>m||oflag_j ==0||oflag_j>n            
    		continue;        
    	end        
    	%对检测点和边缘进行迭代        
    	if D(oflag_i,oflag_j)==1            
    		t(1) = flag_i;     %t为前一个点            
    		t(2) = flag_j;            
    		flag_i= oflag_i;   %此处的flag_i和flag_j为后一个点            
    		flag_j= oflag_j;            
    		newe = newe+1;            
    		E(1,newe) = flag_i;            
    		E(2,newe) = flag_j;            
    		%对下一个要找的点进行迭代            
    		if i==1            
    		    oflag_i = flag_i+C2_left(1,i,1);                
    		    oflag_j = flag_j+C2_left(1,i,2);            
    		else            
    		    oflag_i = flag_i+C2_left(1,i-1,1);                
    		    oflag_j = flag_j+C2_left(1,i-1,2);            
    		end            
    		newk=flag_i-t(1);            
    		newl=flag_j-t(2);            
    		newi=newi+1;            
    		chainCode(newi)=find(C2(:,:,1)==newk&C2(:,:,2)==newl)-1;            
    		break;        
    	end    
    end
end
chainCode
clear begin_flag C2 C2_left endflag_i endflag_j flag flag_i flag_j max_i max_j
clear newi newk newl oflag_i oflag_j t i j k h l C newe 

%%
%求一阶差分
difference=zeros(1,N);
newChainCode=[chainCode(N) chainCode];
for i=1:N
    difference(i)=newChainCode(i+1)-newChainCode(i);
    if difference(i)<0        
    	difference(i)=difference(i)+4;    
    end
end
difference
clear newChainCode i 
%%
%求形状数
flag = 1e21;
newflag = 0;
for i=1:N
    newdifference=[difference(i+1:end) difference(1:i)];    
    t=0;    
    for j=1:N    
        t = t+newdifference(j)*(10^(N-j));    
    end    
    if t<flag    
        newflag = i;        
        flag = t;    
    end    
end
shapeNo = [difference(newflag+1:end) difference(1:newflag)];
shapeNo
clear newdifference newflag t flag i j 

%%
%其相应的近似多边形
figure(3),imshow(D);
hold on;    
plot(E(2,:),E(1,:),'w-');
hold off;

5.输出结果

边界追踪算法得到的边界如下所示:
在这里插入图片描述
直接获得该边界的链码会生成一个变化较小的较长序列,且不能表示该边界的形状,为降低可变性,在得到其边界的链码前,通常需要对改边界重取样。由于要找阶为20的矩形,求得偏心率为0.9508,最匹配的基本矩形为55,故对图像做55的网络,做适当重取样后的图像如下所示:
在这里插入图片描述
从左上角开始对图像求链码,求得链码为:
在这里插入图片描述
其一次差分为:
在这里插入图片描述
使用该链码的故一次差分来计算形状数为:
在这里插入图片描述
阶数为20的近似多边形
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值