【指紋識別】基于模板匹配算法指紋識別匹配門禁系統(tǒng)matlab源碼
一、簡介
1 指紋識別的引入和原理
1.1 指紋的基本知識
指紋,由于其具有終身不變性、唯一性和方便性,已幾乎成為生物特征識別的代名詞。指紋是指人的手指末端正面皮膚上凸凹不平產(chǎn)生的紋線。紋線有規(guī)律的排列形成不同的紋型。紋線的起點、終點、結(jié)合點和分叉點,稱為指紋的細節(jié)特征點(minutiae)。如圖1-1所示。

1.2 指紋識別的原理及算法流程
指紋識別即指通過比較不同指紋的細節(jié)特征點來進行鑒別。指紋識別技術(shù)涉及圖像處理、模式識別、計算機視覺、數(shù)學形態(tài)學、小波分析等眾多學科。由于每個人的指紋不同,就是同一人的十指之間,指紋也有明顯區(qū)別,因此指紋可用于身份鑒定。由于每次捺印的方位不完全一樣,著力點不同會帶來不同程度的變形,又存在大量模糊指紋,如何正確提取特征和實現(xiàn)正確匹配,是指紋識別技術(shù)的關(guān)鍵。
指紋識別技術(shù)主要包括三大部分:指紋圖像采集、指紋預(yù)處理、特征提取與匹配。如圖1-4所示。

2 指紋圖像預(yù)處理
圖像預(yù)處理是對原始圖像進行的一種前期處理,方便后續(xù)的模塊識別。無論采用何種方式獲取的指紋圖像, 都有一部分由于質(zhì)量原因, 不能被系統(tǒng)直接識別,因此圖像的預(yù)處理就顯得非常有必要。
指紋圖像的預(yù)處理目的就是將自己感興趣的目標區(qū)域保留下來,去除背景區(qū)域和沒有用的部分,同時根據(jù)指紋目標區(qū)域中脊線的結(jié)構(gòu)特征,采取較好的濾波方法,提高指紋脊線清晰度,平滑脊線邊緣的毛刺和空洞,抑制圖像噪聲,保證指紋特征的可靠提取,并使灰度圖像轉(zhuǎn)化成黑白的二值圖像,最終得到脊線結(jié)構(gòu)清晰的單像素寬的二值圖像。本文預(yù)處理的主要流程如圖2-1所示。

2.1 指紋圖像的采集
因本設(shè)計重點是對指紋圖像的處理,最終得到匹配結(jié)果,因此指紋圖像的獲取并非本設(shè)計的重點。指紋圖像的獲取可以借助市面上的指紋采集器貨得,或者自行利用手機和數(shù)碼相機等拍攝器材采集。
2.2圖像的灰度處理
圖像的灰度化是保留原有像素的透明度的,即透明度不參與像素的運算。該運算公式為:
gray = R?0.299 + G * 0.587 + B * 0.114
這個公式的意思是原圖的一個像素區(qū)域包含了RGB的三個顏色值,而目標灰度圖上相對應(yīng)的像素上的顏色值為由上面的公式計算得到。這里有個問題就是,你需要結(jié)果圖是24位(如果包含Alpha則是32位)還是8位,如果是24位,則結(jié)果灰度圖還是RGB的,只不過R=G=B=gray,如果是8位的,一個像素就只包含一個顏色值gray。
圖像的灰度化是圖像處理中很基本的算法,同時也是其他圖像處理或是識別的基礎(chǔ),有些智能算法都是基于單色8位灰度圖進行的,因為他減少了計算量。
2.3 圖像的二值化
二值化就是將圖像上的像素點的灰度值設(shè)置為0或1,也就是將整個圖像呈現(xiàn)出明顯的黑白視覺效果。指紋圖像中包括目標和背景還有眾多噪聲,要想從原始的指紋圖像中提取出目標,一般用的方法是設(shè)定一個閾值T,用T將圖像中像素數(shù)據(jù)分成兩部分,若輸入灰度圖像的函數(shù)為:

通過求解閾值T,從而把圖像f(x,y)分成目標和背景兩個區(qū)域,其中大于T的像素群為目標區(qū)域,小于等于T的像素群為背景區(qū)域,閾值的選取原則是:(1)盡可能的多保存圖像信息;(2)盡可能的減少噪聲。
本文將討論基于方向場的二值化處理。
采集到的指紋圖像一般都有比較清晰的方向場,方向場估計得準確與否直接決定了圖像二值化算法的效果。
為估計方向場,我們把指紋脊線的走向分為如下8個方向,如圖2-6所示:

我們先對分割后的圖像進行了平均濾波,然后對圖像的每一個像素,為確定在該像素處的脊線方向,在以該像素為中心的99窗口內(nèi),分別計算8個方向上的經(jīng)過處理后的灰度值,即將圖2-6中數(shù)字1到8的位置的像素灰度值去除其中最大summax和最小值summin,若滿足最大的summax和最小的summin與 4I(x,y))之和大于 (3summ/8),則該像素點的脊線方向為summin,否則為summax.確定完脊線方向后再由該方向場對圖像進行二值化。
結(jié)果如下:

2.4 圖像細化
二值化處理后,脊線仍然有一定的寬度,指紋識別的匹配是只利用圖像的點或線的特征,這些點或者特征只與脊線的走向或者紋理有關(guān)系,有一定寬度的二值化圖像顯得有些多余,所以需要對二值化圖像進行細化處理,指紋二值化圖像經(jīng)過細化處理即可得到一個單一像素寬度的脊線,經(jīng)過上述的細化處理,在后續(xù)的指紋特征提取和特征匹配的算法中大大的減少了計算的冗余量和出錯率,使得指紋識別的速度和準確度有了很大的提高。
細化目的是在不破壞指紋圖像連通性的情況下去除掉多余的信息(即多余的像素點),將二值化的指紋圖像的脊線采用逐層剝離的方法,將圖像中的指紋脊線細化成單象素寬(實際為保存原圖的骨架)。
這里是利用matlab庫函數(shù)bwmorph,調(diào)用格式為:BW2 = bwmorph(BW,operation,n)應(yīng)用形態(tài)學操作n次,n可以是Inf,這種情況下該操作被重復執(zhí)行直到圖像不再發(fā)生變化為止。
‘thin’ n = Inf時,減薄目標成線。沒有孔洞的目標縮成最低限度的連通邊;有孔洞的目標縮成連通環(huán)。
3 圖像特征提取和特征匹配
3.1 特征點提取
(1)提取指紋的端點和交叉點
端點和交叉點均是指紋圖像的兩個細節(jié)特征,同時在指紋識別的的過程中起著重要的作用,因為識別的首要前提就是找到圖像的所有端點和交叉點。通過point.m函數(shù)來找出細化后指紋圖像的所有端點及交叉點。
將八鄰域中的每個點依次兩兩相減并取其絕對值,后將所有結(jié)果加起來,因為端點處是兩個點,即和為2時細化圖像有端點,和為6時圖像特征為交叉點。
運行完上面的point.m函數(shù)的程序后,能把細化圖像的的端點和交叉點全部找出。在定義函數(shù)的程序中有數(shù)組txy,其中t為橫坐標,x為縱坐標,y為2時為端點,y為6時為交叉點。
(2)去除圖像邊緣的端點[去偽]
可以看出,指紋圖像細化的邊緣,由于采集儀器不同的關(guān)系,因此不可避免的會多出很多的端點,這些端點不僅增加了后續(xù)的工作量,還可能導致識別過程中產(chǎn)生錯誤,所以要把這些邊緣的端點都去除,在matlab中這些操作都可以采用一函數(shù)來實現(xiàn),本實驗中設(shè)計了一cut.m函數(shù)來進行處理。
3.2 找出特征點
設(shè)置三個函數(shù)來找出圖像的特征點:
(1)single_point函數(shù)
經(jīng)過去除邊緣端點的操作后進一步減少了指紋細化圖像中的端點和交叉點的個數(shù)。下面就需要找出一些在細化圖像中比較獨特的端點來作為識別的特征點。在一幅細化的指紋圖像中,如果在一個像素(該像素為端點)的周圍半徑為r(r為像素的個數(shù))的圓內(nèi)沒有任何的端點或者交叉點,那么隨著r的逐漸增大,這樣的點就會越來越少,因此該點也就越來越獨特。于是我們設(shè)計了一single_point函數(shù)來找出這樣獨特的點。
(2)walk函數(shù)
為了進一步找出特征點,我們還需定義一walk函數(shù),它的主要作用就是判斷某一端點在num的距離內(nèi)是否還有其他的端點。
(3)last1函數(shù)
single_point函數(shù)和walk函數(shù)都是找細化圖像特征點的函數(shù),因此可以設(shè)計另一個新的last1函數(shù),通過執(zhí)行
[pxy3,error2]=last1(thin,r,txy,num)
可以找出一端點以r為半徑的像素內(nèi)的任何端點和交叉點且沿著脊線走向的num內(nèi)沒有任何的其他端點和交叉點。
3.3 特征點匹配
由上文的函數(shù)可知,已經(jīng)找出了指紋細化圖像中的特征點,并畫出了一段獨特的脊線,在圖像中用紅色來標示。下面就是指紋匹配[12]的問題了。在此我們設(shè)置了三層匹配。
(1)脊線長度匹配
對于上面的函數(shù)即可找出細化圖像中的特征點和一段脊線,沿著該段脊線走向,每隔五個像素測量一下,看到到原始端點的距離,此段距離由一distance函數(shù)得到。
函數(shù)結(jié)果會得到一數(shù)組(內(nèi)有脊線的長度信息)。如果兩幅指紋細化圖像中的紋路是相同的,則它們就包含相同的端點和交叉點及用distance函數(shù)找出的相同的一段脊,則這兩個指紋圖像中的長度數(shù)組對應(yīng)的位置比例會基本相等(我們選擇的指紋圖像大小基本相等,因此該比例選1),因此函數(shù)最終定義了一個數(shù)f=(sum(abs((d1./d2)-1))),其中若f的值越接近于0,這兩幅圖像的匹配度就越高,在一定范圍的閾值內(nèi)我們可以認定為匹配。
(2)三角形邊長匹配
找到一個指紋細化圖像的特征點后,可以找出距離這個端點距離最近的兩個端點或者交叉點,與這個指紋圖像細化的特征點構(gòu)成一個三角形,若兩幅圖像中的邊長比例基本相等(原理同上,也選1),則說明這兩幅圖像匹配,越接近于1說明這兩幅指紋圖像越匹配。其中設(shè)置一find_point函數(shù)來找出距離最近的端點或交叉點。
函數(shù)最后定義了一個數(shù)ff=(sum(abs((dd1./dd2)-1))),因此ff值越接近于0,這兩幅指紋圖像的匹配度越高,在一定范圍的閾值內(nèi)我們可以認定為匹配。
二、源代碼
function varargout = gui1(varargin)
% GUI1 MATLAB code for gui1.fig
% ? ? ?GUI1, by itself, creates a new GUI1 or raises the existing
% ? ? ?singleton*.
%
% ? ? ?H = GUI1 returns the handle to a new GUI1 or the handle to
% ? ? ?the existing singleton*.
%
% ? ? ?GUI1('CALLBACK',hObject,eventData,handles,...) calls the local
% ? ? ?function named CALLBACK in GUI1.M with the given input arguments.
%
% ? ? ?GUI1('Property','Value',...) creates a new GUI1 or raises the
% ? ? ?existing singleton*. ?Starting from the left, property value pairs are
% ? ? ?applied to the GUI before gui1_OpeningFcn gets called. ?An
% ? ? ?unrecognized property name or invalid value makes property application
% ? ? ?stop. ?All inputs are passed to gui1_OpeningFcn via varargin.
%
% ? ? ?*See GUI Options on GUIDE's Tools menu. ?Choose "GUI allows only one
% ? ? ?instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES
% Edit the above text to modify the response to help gui1
% Last Modified by GUIDE v2.5 19-May-2018 10:57:01
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', ? ? ? mfilename, ...
? ? ? ? ? ? ? ? ? 'gui_Singleton', ?gui_Singleton, ...
? ? ? ? ? ? ? ? ? 'gui_OpeningFcn', @gui1_OpeningFcn, ...
? ? ? ? ? ? ? ? ? 'gui_OutputFcn', ?@gui1_OutputFcn, ...
? ? ? ? ? ? ? ? ? 'gui_LayoutFcn', ?[] , ...
? ? ? ? ? ? ? ? ? 'gui_Callback', ? []);
if nargin && ischar(varargin{1})
? ?gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
? ?[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
? ?gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT
% --- Executes just before gui1 is made visible.
function gui1_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject ? ?handle to figure
% eventdata ?reserved - to be defined in a future version of MATLAB
% handles ? ?structure with handles and user data (see GUIDATA)
% varargin ? command line arguments to gui1 (see VARARGIN)
% Choose default command line output for gui1
handles.output = hObject;
A=imread('指紋3.jpg');
set(handles.pushbutton1,'CData',A);
B=imread('指紋19.jpg');
set(handles.pushbutton3,'CData',B);
C=imread('指紋18.jpg');
set(handles.pushbutton7,'CData',C);
D=imread('指紋6.jpg');
set(handles.pushbutton4,'CData',D);
E=imread('指紋17.jpg');
set(handles.pushbutton5,'CData',E);
F=imread('指紋5.jpg');
set(handles.pushbutton8,'CData',F);
G=imread('指紋8.jpg');
set(handles.pushbutton9,'CData',G);
% ha=axes('units','normalized','position',[0 0 1 1]);
% uistack(ha,'down')
% II=imread('動態(tài)圖片2.jpg');%里面的參數(shù)可以是你自己的圖片,把名字連同格式寫進去就可以了
% image(II)
% colormap gray
% set(ha,'handlevisibility','off','visible','off');
guidata(hObject, handles);
% UIWAIT makes gui1 wait for user response (see UIRESUME)
% uiwait(handles.figure1);
% --- Outputs from this function are returned to the command line.
function varargout = gui1_OutputFcn(hObject, eventdata, handles)
% varargout ?cell array for returning output args (see VARARGOUT);
% hObject ? ?handle to figure
% eventdata ?reserved - to be defined in a future version of MATLAB
% handles ? ?structure with handles and user data (see GUIDATA)
% Get default command line output from handles structure
varargout{1} = handles.output;
% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject ? ?handle to pushbutton1 (see GCBO)
% eventdata ?reserved - to be defined in a future version of MATLAB
% handles ? ?structure with handles and user data (see GUIDATA)
hfigure2=Fingerprint_gui();
handles.hfigure2=hfigure2;
guidata(hObject,handles);
% --- Executes on button press in pushbutton3.
function pushbutton3_Callback(hObject, eventdata, handles)
% hObject ? ?handle to pushbutton3 (see GCBO)
% eventdata ?reserved - to be defined in a future version of MATLAB
% handles ? ?structure with handles and user data (see GUIDATA)
function out = thinning2(in);
%thinning process obtain a one pixel wide image skeleton
% use function n_sum and t_sum
[w,h] = size(in);
out = in;
for i= 3:h-2
for j= 3:w-2
? ? ? ?if out(i,j) == 1
? ? ? ? ? ? ? ?if 1 < n_sum(i,j,out) & ?n_sum(i,j,out) < 7
? ? ? ? ? ? ? ? ? ? ? ?if ?t_sum(i,j,out) == 2
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if or ( and_157(i,j,out) == 0 ?, t_sum(i,j-1,out) ~= 2 )
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if or (and_357(i,j,out) == 0 ?, t_sum(i+1,j,out) ~=2 ) ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? % ? ? ? ?if and_157(i,j,out) == 0
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? % if ?and_357(i,j,out) == 0 ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?out(i,j) = 0;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?else
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?out(i,j) = 1;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?end;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?else
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?out(i,j) = 1;
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?end;
? ? ? ? ? ? ? ? ? ? ? ?else
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ?end;
? ? ? ? ? ? ? ?end;
三、運行結(jié)果


?