【身份证识别】基于matlab GUI形态学二代身份证号码识别系统【含Matlab源码 948期】
一、身份證號碼識別簡介
1 引言
作為居民身份的象征,身份證是居民身份的唯一標識,它已成為生活中必不可少的證件。在火車站、酒吧等公共場所,流動人口大人員復雜,警察需要對公民的身份證進行核對,排除可疑人員。為了提高警察的辦事效率,提出通過手機終端將居民的身份證號碼進行自動識別。
身份證號碼的自動識別技術屬于圖像數字識別領域,目前國內外采用得較多的方法主要有兩類:基于模板匹配的 OCR 算法和基于人工神經網絡的OCR算法,其中尤以模板匹配法應用最為廣泛。模板匹配法主要是通過提取目標的特征(包括灰度特征、形狀特征、網格
特征等)與模板庫中的模板進行匹配計算它們的相似度或者歐式距離,當滿足一定的閾值時就認為目標與該模板一致。模板匹配法通常用于目標特征容易提取且模板庫比較小的情形,但模板匹配法容易受噪聲干擾而降低識別的準確度,在提取的特征個數較多時匹配所需時間也會延長。
2 基本原理
身份證號碼識別技術的基本原理如圖 1 所示。首先需要掃描樣本圖像以獲得樣本字符的特征以放入特征庫中,因為第二代居民身份證號碼的字體比較特殊,需要從樣本圖像中獲取數字 0~9及字母 x的特征作為特征庫,其次掃描待識別圖像提取待識別字符的特征與特
征庫中的字符特征進行匹配從而得到識別結果。圖像處理中常用到的方法有圖像灰度化、二值化、基于投影的字符分割等算法。常常提取的字符特征包括直接將字符圖像作為字符特征或將變換后的圖像作為特征,將圖像在水平及垂直方向上的投影作為特征,還有字
符的筆畫密度特征、外圍特征、統計特征等;在字符識別這一步中常見的方法有:結構模式識別、統計模式識別、統計識別與結構識別的結合、人工神經網絡、基于改進 Adaboost的方法等。
圖 1 身份證號碼識別技術的基本原理圖
本文在獲取字符的灰度圖像后,在灰度多值化的基礎上提取字符的網格特征,再利用模板匹配的方法進行識別。具體的流程包括身份證邊緣定位,身份證號碼區域定位及灰度歸一化,身份證號碼單個字符分割,特征提取和身份證號碼識別等,如圖 2 所示為身份證號碼識別的具體流程。
圖2 身份證號碼識別的處理流程
2.1 居民身份證邊緣定位
第二代居民身份證的大小是固定的,寬度為8.6 cm,高度為 5.4 cm,但是在獲取身份證圖像時,由于焦距的遠近,不能利用它的大小信息來獲取身份證在圖像中所處的位置。如圖 3(a)所示為通過攝像頭獲得的居民身份證圖像,在這一步中要求背景比較簡單,能和身份證形成明顯對比,且身份證在圖像中的位置要大體居中不能過小,以保證在圖像的橫向及縱向 3/8、4/8、5/8處能檢測到居民身份證,這將影響到定位的結果。為了確定身份證在圖像中的位置,需要對圖像進行二值化,但考慮到如果對整張圖像進行灰度化及二值化會消耗很多時間,分別在縱向及橫向上在圖像的 3/8、4/8 及 5/8 處截取寬度為 40 個像素的區域進行灰度化及二值化運算,截取的區域如圖 3(b)及 3(c)所示。常用的灰度化處理方法有加權平均法、平均值法和最大值法等。這里采用加權平均法[14],根據重要性及其他指標,將 R、G、B 三個分量以不同的權值進行加權平均。由于人眼對綠色的敏感度最高,對藍色敏感度最低,因此,可以按公式(1),對 RGB 三個分量進行加權平
均能得到較合理的灰度圖像。f (ij) = 0.299R(ij) + 0.587G(ij) + 0.114B(ij)) (1)式中,f (ij) 為像素的灰度值,R(ij) 為彩色圖像中 R分量的值,G(ij) 為彩色圖像中 G 分量的值,B(ij) 為彩色圖像中 B 分量的值。截取的縱向及橫向區域做灰度化運算后的結果如圖 4(a)所示。對于二值化處理,采用了迭代法進行二值化,其思想是利用迭代的方法最終找到一個最佳的分割閾值。對于身份證圖像中所選取的區域,首先遍歷區域中所有
點的灰度值,找出該區域內的最大灰度值 Pmax 和最小灰度值 Pmin ,取閾值初值 T0 = (Pmax + Pmin)/2 。根據 T0 將圖像分割為兩部分并且分別求出各部分的灰度均值 Po 和 Pb ,進而計算新閾值 Ti + 1 = (Po + Pb)/2 。若 Ti + 1 = Ti ,則取閾值為 Ti ,否則返回繼續循環迭代。在灰度圖像中灰度值 i 在[0,255]這個區間內,Si 表示灰度值為 i 的像素點的個數,Ti 表示閾值,那么則有:
經過二值化運算后的區域,在邊緣處與背景區分得很明顯,如圖 4(b)為縱向區域在二值化后的結果。再通過從上到下的搜索及從下向上的搜索就很容易確定居民身份證上下邊緣在圖像中 3/8、4/8 及 5/8 處的三個邊緣點坐標。
如圖 5 所示為根據二值化結果確定的居民身份證上下邊緣三個點的位置,分別為上邊緣 A1(左)、A2(中)、A3(右)及下邊緣 B1(左)、B2(中)、B3(右)。由于光照等其他因素的影響,尋找到的邊緣點并不一定是身份證的真實邊緣點,這個時候需要排除其中一對點,該方法默認在中間區域即圖像 4/8 處所確定的邊緣點是準確的,只需要排除另一對點 A1、B1 或 A3、 B3 。以 A2、B2 為基準點,可以求得四條斜率 LA1A2、 LA3A2、LB1B2、LB3B2 ,當 |LA1A2 - LB1B2| < |LA3A2 - LB3B2| 時,則舍掉 A3、B3 這一對點,反之則舍掉 A1、B1這一對點,最后將得到上下邊緣的各兩個點作為居民身份證的上下邊緣點,斜率 L 作為身份證在圖像中旋轉的斜率。同樣,利用同樣的方法也可以得到居民身份證左右邊緣的各兩個點。在知道居民身份證各條邊上的兩個點及求得斜率,身份證在圖像中的位置也就確定了。
2.2 身份證號碼區域定位及灰度歸一化
身份證號碼在居民身份證上的位置是固定的,在拍照獲取照片時不管焦距如何變化,身份證號碼所在區域相對于身份證本身的位置是不變的,它具有一定的比例關系。根據這一比例關系截取一包含身份證號碼的矩形區域,如果身份證發生了旋轉,即斜率 L 大于經驗值
0.035時,則以該斜率為參考將矩形區域進行矯正。圖 6所示為截取的身份證號碼區域在經過矯正后的彩色圖像。
圖 6 身份證號碼彩色區域
對得到的彩色圖像利用式(1)做灰度化處理,但是因為光照的原因,有時候圖像整體偏暗,有時候圖像又整體偏亮,這會影響到數字字符的特征提取及最后的識別效果。因此在對圖像做灰度化處理后在進行字符分割前需要將號碼區域進行灰度拉伸,使得像素的灰度值分布在 0到 255間,也就是灰度歸一化。
灰度歸一化的方法是:對于輸入圖像 f (xy) ,灰度級變換 T 將產生一個輸出圖像 g(xy) ,且 g(xy) 的每一個像素值都是由 f (xy) 的對應輸入像素點的值決定的,g(xy) = T( f (xy)) 。首先找出原圖像 f (xy) 灰度的最大值max及最小值min,得到系數 k = 1.0 ′ 255/(max - min) ,那 么 對 于 圖 像 f (xy) 中 的 每 一 像 素 ,利 用 變 換 T : g(xy) = ( f (xy) - min)′ k ,即 得 到 輸 出 圖 像 g(xy) ,
圖 7 灰度拉伸后的身份證號碼區域灰度圖像
2.3 單個字符的分割及大小歸一化
單個字符的分割是在求得灰度圖像的分割閾值后,根據閾值進行行投影及列投影以確定每個字符的左右及上下邊界,將字符的左右及上下邊界坐標影射到原灰度圖像,即可得到每個字符的灰度圖像。常用的分割方法有閾值法、區域生長法、分裂合并法、邊緣檢測法、人工神經網絡法、分類器和聚類法等。在這里,對于定位得到的數字區域,首先根據迭代法找出將目標(數字)與背景分割開的閾值 t ,然后根據閾值t 將圖像在垂直方向上進行投影,計算每一列上灰度值小于閾值 t 的個數,對于數字間的背景區域在垂直方向上的投影值為 0,即可得到數字的左右邊界坐標,再根據數字的左右邊界將每個數字進行水平方向上的投影,找到數字的上邊緣及下邊緣,這樣就可以分割出每一個字符。其中閾值 t 的計算方法[15]與前文計算閾值的方法是一樣,在這不再描述。
對于分割出來的字符灰度圖像,由于輸入圖像不同分割得到的字符圖像尺寸也不相同,即使是同一幅圖像中每個字符圖像的尺寸也不盡相同,因此還需要將字符圖像進行大小的歸一化,目的是要使得字符圖像與模板圖像的尺寸一致。通過雙線性插值算法對字符圖像作
大小歸一化。雙線性插值[16]是利用了需要處理的原始圖像像素點周圍的四個像素點的相關性,通過雙線性算法計算得出的。對于一個目的坐標,通過向后映射法得到其在原始圖像的對應的浮點坐標 (i + uj + v) ,其中 ij均為非負整數,uv 為[0,1]區間的浮點數,則這個像素的值 f (i + uj + v) 可由原圖像中坐標為 (ij)、(i + 1j)、 (ij + 1)、(i + 1j + 1) 所對應的周圍四個像素的值決定,即:f (i + uj + v) = (1 - u)′(1 - v)′ f (ij) +
(1 - u)′ v ′ f (ij + 1) + u ′(1 - v)′ f (i + 1j) + u ′ v ′ f (i + 1j + 1) (4)式中 f (ij) 表示源圖像 (ij) 處的的像素值,以此類推,這就是雙線性內插值法。對于圖 7 分割得到的單個字符圖像再進行大小歸一化之后的結果如圖 8,設定字符尺寸為 40×72(寬 40像素,高 72像素)
圖 8 對分割得到的字符進行大小歸一化后的結果
2.4 特征提取
灰度多值化是指灰度圖像 A 按照一定的法則 f 將各個像素的灰度值從 0~255變換到 0~n - 1,這個過程稱為灰度多值化或 n 值化,在數學上描述為:
其中式(5)中 G(xy) 為圖像 A 中像素的灰度值,g(xy) 為 G(xy) 經過 f 運算后的值;式(6)表示圖像 A 在經過f 運算后灰度的維數從 256 維變為 n 維,當 n = 2 時,這
個過程就是人們所熟悉的灰度二值化,當 n = 26 時就是灰度 26值化。
一幅灰度圖像再進行二值化處理時,會損失掉很多信息,有時還會因為圖像質量問題使得二值化結果不能正確地區分出目標與背景,那么在此基礎上提取到的特征也就不能有效地代表字符。如圖 9 為從身份證照片中截取到的號碼區域,該區域比較模糊,但是肉眼還是
能將號碼識別出來;圖 10 為將該號碼區域進行二值化處理的結果,可以看出二值化之后目標即號碼和背景沒有被正確地區分開來,像數字 6、8、9 在二值化之后中間的空白區域被填充了,中間的背景像素被理解成了目標像素,使得二值化結果不能正確地反映出圖像原本的信息。為此,提出將圖像進行多值化處理,而不是二值化,圖像中的像素被分為多類而不僅僅是被分為兩類,這樣可以適當減少信息的損失,在此基礎上提取到的特征也
更能有效地區分出字符。
圖 9 身份證號碼的模糊圖像
圖 10 模糊圖像作二值化處理后結果
在得到身份證號碼字符的灰度圖像后,將字符圖像作 26 值化處理。為什么要將灰度圖像作 26 值化處理?在身份證號碼的灰度圖像中,對屬于同一個小區域內的像素,同屬于目標或背景的兩個像素的灰度值一般是差別不大的,如圖 11 為身份證號碼所在區域的灰度圖像,在圖像中間作一條水平線橫穿整個圖像,通過統計這條水平線上各像素的灰度值,發現在非數字區域也就是背景區域各像素的灰度值都是相差不大,在 10 個灰度級以內,同樣在數字區域各像素的灰度值也是相差 10 個灰度級以內,但是數字區域和背景區域的灰度值相差可以達到 60 個灰度級,因此可以認為灰度值變化在 10 個灰度級以內的像素是同一類,在此基礎上提出將灰度圖像的灰度值從 256個等級作降級處理變為 26個等級,也
就是進行 26 值化,這樣既能將像素進行分類又不會使原圖像所包含的信息損失太大。
圖 11 身份證號碼區域的灰度圖像為了提取字符的網格特征,首先將字符圖像分為大小一致互不重疊的若干個小網格,對于大小為 40×72(寬 40像素,高 72像素)的字符圖像,先將字符圖像劃分M ′ N 個網格,這里 M = 10 ,N = 12 ,再利用公式(7)將數字字符的灰度圖像做 26 值化,最后利用式(8)統計每個小網格中像素灰度在 26 值化后的平均值作為該方塊的特征,這些特征組合在一起構成特征向量,即得到每個數字字符的二維灰度特征。
其中,式(7)是將像素的灰度進行26值化處理,f (xy) 為像素的原灰度值,g(xy) 為 26值化后得到的值,即灰度值從原來的 0~255 降為 0~25;式(8)是計算第 (ij) 個網
格的特征值 E(ij),H 和 W 分別為該小方塊的高和寬,g(xy) 為該小方塊中像素灰度 26值化后的值,0 x < W, 0 y < H ,0 i < M ,0 j < N 。那么字符的特征向量則
等于
2.5 字符識別
字符識別就是將待識別字符的特征向量與模板庫中保存的每個字符的特征向量進行匹配,找到與待識別字符匹配的字符。本文用到的匹配方法是通過求相似度,相似度最大的即認為是與待識別字符匹配的字符。求相似度的方法如下:
式中 S 定義為相似度,Ts(ab) 為待識別字符的特征屬性,To(ab) 為模板的特征屬性。
二、部分源代碼
function varargout = id_rec_gui(varargin) % ID_REC_GUI MATLAB code for id_rec_gui.fig % ID_REC_GUI, by itself, creates a new ID_REC_GUI or raises the existing % singleton*. % % H = ID_REC_GUI returns the handle to a new ID_REC_GUI or the handle to % the existing singleton*. % % ID_REC_GUI('CALLBACK',hObject,eventData,handles,...) calls the local % function named CALLBACK in ID_REC_GUI.M with the given input arguments. % % ID_REC_GUI('Property','Value',...) creates a new ID_REC_GUI or raises the % existing singleton*. Starting from the left, property value pairs are % applied to the GUI before id_rec_gui_OpeningFcn gets called. An % unrecognized property name or invalid value makes property application % stop. All inputs are passed to id_rec_gui_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 id_rec_gui% Last Modified by GUIDE v2.5 28-May-2021 11:48:47% Begin initialization code - DO NOT EDIT gui_Singleton = 1; gui_State = struct('gui_Name', mfilename, ...'gui_Singleton', gui_Singleton, ...'gui_OpeningFcn', @id_rec_gui_OpeningFcn, ...'gui_OutputFcn', @id_rec_gui_OutputFcn, ...'gui_LayoutFcn', [] , ...'gui_Callback', []); if nargin && ischar(varargin{1})gui_State.gui_Callback = str2func(varargin{1}); endif nargout[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); elsegui_mainfcn(gui_State, varargin{:}); end % End initialization code - DO NOT EDIT% --- Executes just before id_rec_gui is made visible. function id_rec_gui_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 id_rec_gui (see VARARGIN)% Choose default command line output for id_rec_gui handles.output = hObject;% Update handles structure guidata(hObject, handles);% UIWAIT makes id_rec_gui wait for user response (see UIRESUME) % uiwait(handles.figure1);% --- Outputs from this function are returned to the command line. function varargout = id_rec_gui_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 browse. function browse_Callback(hObject, eventdata, handles) % hObject handle to browse (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) global pathname filenames [filenames,pathname]=uigetfile({'*.bmp;*.jpg;*.png;*.gif','All Image Files';'*.*','All Files' },'MultiSelect','on'); if ~isequal(filenames,0)init_controls(handles)preprocess(handles)process(handles) endfunction init_controls(handles) global filenames current_select_idx current_select_idx=1; if ischar(filenames)filenames={filenames}; end if ischar(filenames) || length(filenames)==1set(handles.img_idx,'String','')set(handles.img_idx_slider,'Visible','off') elseset(handles.img_idx_slider,'Visible','on')set(handles.img_idx_slider,'Min',0)set(handles.img_idx_slider,'Max',length(filenames)-1)set(handles.img_idx_slider,'SliderStep',ones(1,2)/(length(filenames)-1)) end set(handles.validate,'Enable','on')function [org_img,img_gray,thresh_value]=read_id_card(filename) fileinfo=imfinfo(filename); if strcmpi(fileinfo.ColorType,'indexed')[X,map]=imread(filename);org_img=ind2rgb(X,map); elseorg_img=imread(filename); end r=size(org_img,1); c=size(org_img,2); size_thresh=2000; if r>size_threshorg_img=imresize(org_img,size_thresh/r); end if c>size_threshorg_img=imresize(org_img,size_thresh/c); end org_img=im2double(org_img); if ndims(org_img)==3img_gray=rgb2gray(org_img); elseimg_gray=org_img; end img_gray=imresize(img_gray,[350 500]); img_gray=img_gray(round(size(img_gray,1)*2/3):end,round(size(img_gray,2)/4):end); thresh_value=.68*graythresh(img_gray);function preprocess(handles) global pathname filenames current_select_idx img_gray if length(filenames)>1img_idx_str=sprintf('%d / %d',current_select_idx,length(filenames));set(handles.img_idx,'String',img_idx_str)set(handles.img_idx_slider,'Value',current_select_idx-1)set(handles.img_idx_slider,'TooltipString',img_idx_str) end tryfilename=fullfile(pathname,filenames{current_select_idx});[org_img,img_gray,thresh_value]=read_id_card(filename);axes(handles.img)imshow(org_img),title(filename,'Interpreter','None')set(handles.thresh_value,'Visible','on')set(handles.thresh_value,'value',thresh_value) catch emsgbox(sprintf('Cannot read the image: %s.\n\n',filename,e.message),'Error','error')rethrow(e) endfunction process(handles) global code_stats img_gray model filenames current_select_idx area_codes training_data_size if isequal(filenames,0) || isempty(filenames)return end% init all controls for i=1:18set(eval(sprintf('handles.result%d',i)),'BackgroundColor',[1 1 1])set(eval(sprintf('handles.result%d',i)),'Enable','Inactive')set(eval(sprintf('handles.result%d',i)),'String','') end set(handles.birthday,'BackgroundColor',[1 1 1]) set(handles.birthday,'String','') set(handles.ID_code,'BackgroundColor',[1 1 1]) set(handles.ID_code,'String','') set(handles.gender,'BackgroundColor',[1 1 1]) set(handles.gender,'String','') set(handles.address,'BackgroundColor',[1 1 1]) set(handles.address,'String','') set(handles.save_results,'Enable','off')% process thresh=get(handles.thresh_value,'value'); [id_codes,id_bw,code_stats,thresh,iteration]=id_rec_process(img_gray,model,thresh,training_data_size,1); % if isempty(id_codes) % msgbox('Cannot recognize ID codes. You can try adjusting the threshold value.','Warning','warn','modal') % return % end三、運行結果
四、matlab版本及參考文獻
1 matlab版本
2014a
2 參考文獻
[1] 蔡利梅.MATLAB圖像處理——理論、算法與實例分析[M].清華大學出版社,2020.
[2]楊丹,趙海濱,龍哲.MATLAB圖像處理實例詳解[M].清華大學出版社,2013.
[3]周品.MATLAB圖像處理與圖形用戶界面設計[M].清華大學出版社,2013.
[4]劉成龍.精通MATLAB圖像處理[M].清華大學出版社,2015.
[5]李開,陳禮安,曹計昌.基于灰度多值化的身份證號碼識別[J].計算機工程與應用. 2015,51(13)
總結
以上是生活随笔為你收集整理的【身份证识别】基于matlab GUI形态学二代身份证号码识别系统【含Matlab源码 948期】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机中人民币的符号怎么打,人民币符号怎
- 下一篇: 电脑qq浏览器怎么滚动截长图_Mac系统