在提取指纹细节点时,首先为细化图像中的每个像素点P建立一个8邻域像素区,如图4所示。其中P1~P8为像素点P周围的邻近环绕像素点。P1~P8中黑色点的值设为1,白色点的值设为0。
图4 8邻域像素图
根据Crossing Number (CN)理论,在8邻域像素图中按照公式1计算像素点的CN值。例如在图2和图3中,8领域像素区域内中心点的CN值分别为1和3。
把找到的端点位置存储在txy(Nx3),第一列存储x的位置,第二列存储y的位置,第三列标识点的类别,如果为交叉点则值为6,如果端点则值为2.然后对纹线再次进行光滑处理。
%找出细化后图像的所有端点
%将一个点的八个邻域依次两两相减并取绝对值,并将所有结果相加,从细化图像的特征来说
%和为2时为端点 和为6时为交叉点
function txy=point(thin)
count=1;
txy(count,:)=[0,0,0];
%取行数和列数的最小值
siz=min(size(thin,1),size(thin,2))
for x=40:siz-40
for y=40:siz-40
if(thin(y,x))
CN=0;
for i=1:8
CN=CN+abs(p(thin,y,x,i)-p(thin,y,x,i+1));
end
if (CN==2)
txy(count,:)=[x,y,2];
count=count+1;
end
if(CN==6)
txy(count,:)=[x,y,6];
count=count+1;
end
end
end
end
for i=1:count-1
x(i)=txy(i,1);
y(i)=txy(i,2);
end
imshow(double(thin));
% hold on 通知后面将要绘图
hold on;
plot(x,y,'.');
找到每个端点,使其沿着纹线的方向移动五个像素,如果在五个像素之内遇到交叉点则此点为毛刺,去除此点。判断离端点num个距离内是否有另一个端点的函数为walk判断的主要方法先将该点置为0然后根据八领域点和;和为0或大于2则证明该点距离num内有端点,然后循环向前遍历。
function [w,pxy]=guanghua(thin,txy)
%纹线光滑处理.原理:找到每个端点,使其沿着纹线的方向移动5个像素,如果在5个像素之内遇到交叉点,则认为此端点为毛刺,,去除此点
for j=1:5
txy=point(thin);
%txy第三列为2的变为1 否则变为0
pxy=txy(find(txy(:,3)==2),:);
%求取行数
n=size(pxy,1);
for i=1:n
error=0;
error=walk(thin,pxy(i,1),pxy(i,2),5);
if error==1;
thin(pxy(i,2),pxy(i,1))==0;
end
end
end
w=thin;
imshow(w);
%判断离端点num距离内是否有另一端点
function [error,a,b]=walk(thin,x0,y0,num)
error=0;
thin(x0,y0)=0;
t1=0;
for n=1:num
if error==1
break
else
x=x0;
y=y0;
%判断该点八邻域点和该点的和 来找出想要的点
for x=x0-1:x0+1
if error==1
break;
else
for y=y0-1:y0+1
t1=(sum(sum(thin(y0-1:y0+1,x0-1:x0+1))));
%=0代表一个断点(独立的点) dayu2代表不是端点
if(t1==0||t1>2)
error=1;
a=x0;
b=y0;
break;
else
% x,y还是y,x
if (thin(y,x)==1&&(x-x0)^2+(y-y0)^2~=0)
if(t1>2)
error=1;
break;
else thin(y,x)=0;
x0=x;
y0=y;
a=x0;
b=y0;
plot(x0,y0,'r.');
end
end
end
end
end
end
end
end
光滑处理后的特征点比以前少了。但是我们采集指纹时由于采集器的关系,图像的边缘会有很多端点,这已然会影响后续的识别工作,所以我们需要在特征点中去除这些端点,cut函数主要做这些工作,边缘的主要特征就是黑色多白色少,也就是均值小,所以我主要里用灰度图的分区域(31*31)求均值如果灰度值小于70则在该区域的特征点去除,然后会得到更少的特征点.
%去除图像边缘的端点
function txy=cut(thin,txy)
% thin=thin1;
% txy=txy1;
%声明一个8*8的矩阵
s(8,8)=0;
delta(8,8)=0;
n=size(txy,1);
for i=1:8
for j=1:8
%声明一个数组集合 m{1,2}=3 m=[] [3]
% m{2,5}=6
%
% m =
%
% [1,2,3] [3] [] [] []
% [] [] [] [] [6]
% 每次取31*31 先从上到下 再从做到右
mp{i,j}=thin(1+31*(i-1):31+31*(i-1),1+31*(j-1):31+31*(j-1));
s(i,j)=sum(sum(mp{i,j}))/(31*31);
mp{i,j}=(mp{i,j}-s(i,j)).^2
delta(i,j)=sum(sum(mp{i,j}));
% 边缘 黑色多 白色少
if delta(i,j)<=70
for k=1:n
if (txy(k,1)>=1+31*(i-1)&&txy(k,1)<31+31*(i-1)&&txy(k,2)>=1+31*(j-1)&&txy(k,2)<=31+31*(j-1)&&txy(k,3)==2)
txy(k,:)=[0,0,0];
end
end
end
end
end
% find()查询非零元素所在的位置
txy=txy(find(txy(:,1)),:);
plot(txy(:,1),txy(:,2),'ro');
但这些点依然不够少说明不够特殊,下面定义了combine(thin,r,txy,num)函数可以找出周围半径为r个像素的圆内没有任何端点和交叉点,沿纹线走num个距离没有交叉点和端点,comine为walk和single_point函数的综合,walk函数上面已经介绍,single_point函数主要是找出独特的点作为特征点,原理是根据两个端点之间的距离。求每个端点距离其他端点的距离,找取距离大于r的端点。执行完combine后会得到更少的端点(实验结果为3个端点)。
% 综合walk和single_point函数,通过执行[pxy3,error2]=combine(thin,r,txy,num)可以找出周围半径为r个像素的院内没有任何交叉点或端点,并且沿纹线走num个
% 距离内没有任何哟个交叉点或端点
function [pxy3,error2]=combine(thin,r,txy,num)
error=0;
[pxy2,error]=single_point(txy,r);
n=size(pxy2,1);
k=1;
erroe2=0;
for i=1:n
[error,a,b]=walk(thin,pxy2(i,1),pxy2(i,2),num);
if error~=1
pxy3(k,1)=pxy2(i,1);
pxy3(k,2)=pxy2(i,2);
pxy3(k,3)=pxy2(i,3);
k=k+1;
error2=0;
plot(pxy2(i,1),pxy2(i,2),'r+');
end
end