主函数代码
close all
clear all
clc
im1=imread('108_4.tif');
figure
imshow(im1);title('原图像');
I=normalize2(im1);%归一化和切割
figure
imshow(uint8(I));
im3=derection_bw(I);%二值化
figure
imshow(im3);
im4=thin(im3);%细化
figure
imshow(im4);
[x0,y0]=centralizing(double(im4));%找中心点
figure
imshow(im4);
hold on;plot(x0,y0,'go');hold off;
im4=~im4;
[x3,y3,x4,y4]=find_feature2(im4,x0,y0,100);%找特征点
figure
imshow(im4);hold on;
plot(x3,y3,'bo');plot(x4,y4,'ro');hold off ;
归一化调整的是指纹灰度均值和方差,调整到标准状态,同时可以屏蔽不必要的噪声。
归一化方法如下:
函数1:归一化和切割
function y=normalize2(x)
%对指纹图像进行归一化处理
x1=double(x);
[a,b,~]=size(x);
m=20;
a1=a/m;%行分块数
b1=b/m;%列分块数
M0=mean2(x1);
V=std2(x1);
V0=V*V;
M1=80;
V1=6000;
T=60;
a3=1;%块移动的行位置
b3=1;%块移动的列位置
for i=1:a
for j=1:b
if x1(i,j)>M0
result(i,j)=M1+sqrt(V1*((x1(i,j)-M0)*(x1(i,j)-M0))/V0);
else
result(i,j)=M1-sqrt(V1*((x1(i,j)-M0)*(x1(i,j)-M0))/V0);
end
end
end
for k=1:a1
for l=1:b1
M2=mean2(result(a3:(a3+m-1),b3:(b3+m-1)));%均值
V2=std2(result(a3:(a3+m-1),b3:(b3+m-1)));%方差
V3=V2*V2;
if V3<1000
for i1=a3:a3+m-1
for j1=b3:b3+m-1
result(i1,j1)=255;
end
end
end
if V2==0
for i1=a3:a3+m-1
for j1=b3:b3+m-1
result(i1,j1)=255;
end
end
else
Th=M2/V2;
if Th>T
for i1=a3:a3+m-1
for j1=b3:b3+m-1
result(i1,j1)=255;
end
end
end
end
b3=b3+m;
end
b3=1;
a3=a3+m;
end
y=result;
二值化方案一:局部阈值法
由于原始指纹图像不同区域深浅不一, 如对整幅图像用同一阈值进行二值分割, 会造成大量有用信息的丢失。 所以我们可以选用局部阈对图像进行二值化。局部阈值法即选取 N×N的块,求该区域的阈值并对该区域二值化,可以有效地保证信息的可靠性。
二值化方案二:基于方向场的二值化
采集到的指纹图像一般都有比较清晰的方向场,方向场估计得准确与否直接决定了图像二值化算法的效果。
为估计方向场,我们把指纹脊线的走向分为如下 8 个方向
先进行均值滤波,然后对图像的每一个像素,为确定在该像素处的脊线方向,在以该像素为中心的 99 窗口内,分别计算 8
个方向上的经过处理后的灰度值,即将图中数字 1 到 8 的位置的像素灰度值去除其中最大 summax和最小值 summin, 若满足最大的 summax 和最小的 summin 与 4I(x,y)) 之和大于 (3*summ/8), 则该像素点的脊线方向为summin,否则为 summax。确定完脊线方向后再由该方向场对图像进行二值化。
function im_out=derection_bw(I)
temp=(1/9)*[1 1 1;1 1 1;1 1 1]; % 模板系数、均值滤波
[m,n,~]=size(I);
Im=double(I);
In=zeros(m,n);
Icc=ones(m,n);
for a=2:m-1
for b=2:n-1
In(a,b)=Im(a-1,b-1)*temp(1,1)+Im(a-1,b)*temp(1,2)+Im(a-1,b+1)*temp(1,3)+Im(a,b-1)*temp( 2,1)+Im(a,b)*temp(2,2)+Im(a,b+1)*temp(2,3)+Im(a+1,b-1)*temp(3,1)+Im(a+1,b)*temp(3,2)+ Im(a+1,b+1)*temp(3,3);
end
end
I=In;
Im=zeros(m,n);
for x=5:m-5
for y=5:n-5
sum1=I(x,y-4)+I(x,y-2)+I(x,y+2)+I(x,y+4);
sum2=I(x-2,y+4)+I(x-1,y+2)+I(x+1,y-2)+I(x+2,y-4);
sum3=I(x-2,y+2)+I(x-4,y+4)+I(x+2,y-2)+I(x+4,y-4);
sum4=I(x-2,y+1)+I(x-4,y+2)+I(x+2,y-1)+I(x+4,y-2);
sum5=I(x-2,y)+I(x-4,y)+I(x+2,y)+I(x+4,y);
sum6=I(x-4,y-2)+I(x-2,y-1)+I(x+2,y+1)+I(x+4,y+2);
sum7=I(x-4,y-4)+I(x-2,y-2)+I(x+2,y+2)+I(x+4,y+4);
sum8=I(x-2,y-4)+I(x-1,y-2)+I(x+1,y+2)+I(x+2,y+4);
sumi=[sum1,sum2,sum3,sum4,sum5,sum6,sum7,sum8];
summax=max(sumi); summin=min(sumi); summ=sum(sumi);
b=summ/8;
if (summax+summin+ 4*I(x,y))> (3*summ/8)
sumf = summin;
else
sumf =summax;
end
if sumf > b
Im(x,y)=128;
else
Im(x,y)=255;
end
end
end
for i=1:m
for j =1:n
Icc(i,j)=Icc(i,j)*Im(i,j);
end
end
for i=1:m
for j =1:n
if (Icc(i,j)==128)
Icc(i,j)=0;
else
Icc(i,j)=1;
end
end
end
im_out=Icc;
细化过程中要根据每个像素的八个相邻点的情况来判断该点是否可以剔除或保留,其实质类似于腐蚀操作
代码实现:
function im_out = thin2(I)%有孤岛待去除
I=im3;
[M,N]=size(I);
for i=2:M-1
for j=2:N-1
if I(i,j)==0
if (I(i-1,j)==0&&I(i,j+1)==0)||(I(i-1,j)==0&&I(i,j-1)==0)||(I(i+1,j)==0&&I(i,j-1)==0)||(I(i+1,j)==0&&I(i,j+1)==0)
I(i,j)=1;
else
I(i,j)=0;
end
end
end
end
end
经实验,效果不佳,于是采用MATLAB自带的bwmorph函数进行细化,除此之外,还加上了去除毛刺和空洞的部分
function y=thin(x)
I=ordfilt2(x,5,ones(3,3));%对指纹图像进行3×3滤波
u=I;
[m,n]=size(u)
for x=2:m-1
for y=2:n-1
if u(x,y)==0
if u(x,y-1)+u(x-1,y)+u(x,y+1)+u(x+1,y)>=3
u(x,y)=1;
else
u(x,y)=u(x,y);
end
end
end
end
for a=2:m-1
for b=2:n-1
if u(a,b)==1
if abs(u(a,b+1)-u(a-1,b+1))+abs(u(a-1,b+1)-u(a-1,b))+abs(u(a-1,b)-u(a-1,b-1))+abs(u(a-1,b-1)-u(a,b-1))+abs(u(a,b-1)-u(a+1,b-1))+abs(u(a+1,b-1)-u(a+1,b))+abs(u(a+1,b)-u(a+1,b+1))+abs(u(a+1,b+1)-u(a,b+1))~=1%寻找端点
if (u(a,b+1)+u(a-1,b+1)+u(a-1,b))*(u(a,b-1)+u(a+1,b-1)+u(a+1,b))+(u(a-1,b)+u(a-1,b-1)+u(a,b-1))*(u(a+1,b)+u(a+1,b+1)+u(a,b+1))==0 %去除毛刺和空洞
u(a,b)=0;
end
end
end
end
end
v=~u;
w=bwmorph(v,'thin',Inf);%对图像进行细化
for x=2:m-1
for y=2:n-1
if w(x,y)==1
if (w(x-1,y)==1&&w(x,y-1)==1)||(w(x-1,y)==1&&w(x,y+1)==1)||(w(x,y-1)==1&&w(x+1,y)==1)||(w(x+1,y)==1&&w(x,y+1)==1)
w(x,y)=0;
end
end
end
end
y=w;
提取指纹的中心点有很多作用,比如可以把指纹扇形化后变成特征图,用于指纹匹配。这里求中心点只是为了去除指纹边缘的伪特征点。
代码:
function [XofCenter,YofCenter]=centralizing(fingerprint)
imgN=size(fingerprint,1);
imgM=size(fingerprint,2);
image=wiener2(fingerprint,[3 3]);
[Gx,Gy]=gradient(image);
orientnum=wiener2(2.*Gx.*Gy,[3 3]);
orientden=wiener2((Gx.^2)-(Gy.^2),[3 3]);
W=8;
l1=9;
orient=zeros(imgN/W,imgM/W);
points=(imgN/W)* (imgM/W);
for i=1:1:points
x=floor((i-1)/(imgM/W))* W+1;
y=mod(i-1,(imgN/W))* W+1;
numblock=orientnum(y:y+W-1,x:x+W-1);
denblock=orientden(y:y+W-1,x:x+W-1);
somma_num=sum(sum(numblock));
somma_denom=sum(sum(denblock));
if somma_denom~=0
inside = somma_num/somma_denom;
angle=0.5*atan(inside);
else
angle=pi/2;
end
%each block
if angle<0
if somma_num<0
angle=angle+pi/2;
else
angle=angle+pi;
end
else
if somma_num>0
angle=angle+pi/2;
end
end
orient(1 +(y-1)/W,1+(x-1)/W)=angle;
end
binarize=(orientimgM/W||ydir(y,x)>imgN/W)
while binarize(ydir(y,x),xdir(y,x))>0
xtemp=xdir(y,x);
ytemp=ydir(y,x);
if xtemp<1||ytemp<1||xtemp>imgM/W||ytemp>imgN/W
break;
end
x=xtemp;
y=ytemp;
if xdir(y,x)<1||ydir(y,x)<1||xdir(y,x)>imgM/W||ydir(y,x)>imgN/W
if x-1>0
while binarize(y,x-1)>0
x=x-1;
if x-1<1
break;
end
end
end
break;
end
end
end
binarize2(y,x)=binarize2(y,x)+1;
end
[temp,y]=max(binarize2(1:end-7,:));
[temp2,x]=max(temp);
angle=orient(y(x),x)-pi/2;
XofCenter=round(x*W-(W/2)-(l1/2)*cos(angle));
YofCenter=round(y(x)*W-(W/2)-(l1/2)*sin(angle));
%Outputprint=binarize2;
end
这里我们用最常用的两类特征点:端点和分叉点
找点方法是模板匹配法。
若细化不完全,会有很多点会误识别为特征点
去除伪特征点:
因为采集、预处理过程中的空因素和提取算法的原因,提取到的特征点中会存在很多为特征点。 为了不影响后续的识别, 必须进行剔除。 本程序中剔除的伪特征点主要有两种:指纹边缘点,断点,并根据这三种伪特征点的特征进行剔除。两类伪特征点如下(红色为伪特征点)
function [X1,Y1,X2,Y2]=find_feature2(I,x0,y0,radius)
[M,N]=size(I);
t=0;
k=0;
for i=2:M-1
for j=2:N-1
if I(i,j)==0
n=I(i-1,j-1)+I(i-1,j)+I(i-1,j+1)+I(i,j-1)+I(i,j+1)+I(i+1,j-1)+I(i+1,j)+I(i+1,j+1);
if (n==5)%分叉点
t=t+1;
x1(t)=j;
y1(t)=i;
end
if (n==7)%端点
k=k+1;
x2(k)=j;
y2(k)=i;
end
end
end
end
%去除距离较近的特征点
for i=1:t-1
for j=i+1:t
d=sqrt((x1(i)-x1(j))^2+(y1(i)-y1(j))^2);
if d<20
x1(i)=-1;y1(i)=-1;x1(j)=-1;y1(j)=-1;
end
end
end
for i=1:k-1
for j=i+1:k
d=sqrt((x2(i)-x2(j))^2+(y2(i)-y2(j))^2);
if d<10
x2(i)=-1;y2(i)=-1;x2(j)=-1;y2(j)=-1;
end
end
end
%保留中心点半径之内的点
c=1;
for i=1:t
d(i)=sqrt((x1(i)-x0)^2+(y1(i)-y0)^2);
if(d(i)