一、简介
首先从身份证图像上获取0~9和X共十一个号码字符的样本图像作为后续识别的字符库样本,其次将待测身份证图像进行去噪、灰度化、二值化、水平投影切割,垂直投影并切割,将待测身份证号码分割出来,然后进行待测号码图片与字符库样本对比计算、识别判断、最终确定待测身份证号号码。本设计关于身份证号码的识别是基于Matlab软件的基础上进行的。\ 算法流程\ 1、输入身份证图片;\ 2、根据几何信息定位身份证号码位置并且切割;\ 3、利用连通域算法切割字符;\ 4、利用模板匹配算法进行识别
数学形态学操作可以分为二值形态学和灰度形态学,灰度形态学由二值形态学扩展而来。数学形态学有2个基本的运算,即腐蚀和膨胀,而腐蚀和膨胀通过结合又形成了开运算和闭运算。\ 开运算就是先腐蚀再膨胀,闭运算就是先膨胀再腐蚀。
1 二值形态学\ 粗略的说,腐蚀可以使目标区域范围“变小”,其实质造成图像的边界收缩,可以用来消除小且无意义的目标物。式子表达为:\ \ 该式子表示用结构B腐蚀A,需要注意的是B中需要定义一个原点,【而B的移动的过程与卷积核移动的过程一致,同卷积核与图像有重叠之后再计算一样】当B的原点平移到图像A的像元(x,y)时,如果B在(x,y)处,完全被包含在图像A重叠的区域,(也就是B中为1的元素位置上对应的A图像值全部也为1)则将输出图像对应的像元(x,y)赋值为1,否则赋值为0。\ 我们看一个演示图。\ \ B依顺序在A上移动(和卷积核在图像上移动一样,然后在B的覆盖域上进行形态学运算),当其覆盖A的区域为[1,1;1,1]或者[1,0;1,1]时,(也就是B中‘1’是覆盖区域的子集)对应输出图像的位置才会为1。
2 膨胀\ 粗略地说,膨胀会使目标区域范围“变大”,将于目标区域接触的背景点合并到该目标物中,使目标边界向外部扩张。作用就是可以用来填补目标区域中某些空洞以及消除包含在目标区域中的小颗粒噪声。\ \ 该式子表示用结构B膨胀A,将结构元素B的原点平移到图像像元(x,y)位置。如果B在图像像元(x,y)处与A的交集不为空(也就是B中为1的元素位置上对应A的图像值至少有一个为1),则输出图像对应的像元(x,y)赋值为1,否则赋值为0。\ 演示图为:\ \ 3 小结\ 也就是说无论腐蚀还是膨胀,都是把结构元素B像卷积操作那样,在图像上平移,结构元素B中的原点就相当于卷积核的核中心,结果也是存储在核中心对应位置的元素上。只不过腐蚀是B被完全包含在其所覆盖的区域,膨胀时B与其所覆盖的区域有交集即可。
4 灰度形态学\ 在讲述灰度值形态学之前,我们进行一个约定,即将结构元素B覆盖住的图像A的区域记为P(取Part之意)。
5 灰度形态学的腐蚀\ 那么灰度形态学中的腐蚀就是类似卷积的一种操作,用P减去结构元素B形成的小矩形,取其中最小值赋到对应原点的位置即可。\ 我们来看一个实例,进行加深对灰度形态学的理解。\ 假设我们有如下的图像A和结构元素B:\ \ 进行灰度形态学腐蚀的过程如下:\ \ 我们对输出图像的第一个元素的输出结果进行具体的展示,也就是原点对应的4的位置。输出图像其他的元素的值也都是这样得到的。我们会看到,B首先覆盖的区域就是被减数矩阵,然后在其差矩阵中求min(最小值)来作为原点对应位置的值。\ \ 灰度形态学的膨胀\ 根据上面对腐蚀的描述,我们对膨胀做出同样的描述,灰度形态学中的膨胀就是类似卷积的一种操作,用P加上B,然后取这个区域中的最大值赋值给结构元素B的原点所对应的位置。\ \ \ 这里也对输出图像第一个元素值的来历做个说明。\ \ 对上面矩阵的和求最大值就是6,所以把6赋值给结构元素原点所对应的位置。
6 小结\ 上面介绍了灰度形态学的概念,这里来说一说各自的用处。相比较于原图像,因为腐蚀的结果要使得各像元比之前变得更小,所以适用于去除高峰噪声。而灰度值膨胀的结果会使得各像元比之前的变得更大,所以适用于去除低谷噪声。
二、源代码
``` function varargout = idrecgui(varargin) % IDRECGUI MATLAB code for idrecgui.fig % IDRECGUI, by itself, creates a new IDRECGUI 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. % % IDRECGUI('CALLBACK',hObject,eventData,handles,...) calls the local % function named CALLBACK in IDRECGUI.M with the given input arguments. % % IDRECGUI('Property','Value',...) creates a new IDRECGUI or raises the % existing singleton*. Starting from the left, property value pairs are % applied to the GUI before idrecguiOpeningFcn gets called. An % unrecognized property name or invalid value makes property application % stop. All inputs are passed to idrecguiOpeningFcn 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 idrecgui
% Last Modified by GUIDE v2.5 28-May-2021 11:48:47
% Begin initialization code - DO NOT EDIT guiSingleton = 1; guiState = struct('guiName', mfilename, ... 'guiSingleton', guiSingleton, ... 'guiOpeningFcn', @idrecguiOpeningFcn, ... 'guiOutputFcn', @idrecguiOutputFcn, ... 'guiLayoutFcn', [] , ... 'guiCallback', []); if nargin && ischar(varargin{1}) guiState.gui_Callback = str2func(varargin{1}); end
if nargout [varargout{1:nargout}] = guimainfcn(guiState, varargin{:}); else guimainfcn(guiState, varargin{:}); end % End initialization code - DO NOT EDIT
% --- Executes just before idrecgui is made visible. function idrecguiOpeningFcn(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 idrec_gui (see VARARGIN)
% Choose default command line output for idrecgui handles.output = hObject;
% Update handles structure guidata(hObject, handles);
% UIWAIT makes idrecgui wait for user response (see UIRESUME) % uiwait(handles.figure1);
% --- Outputs from this function are returned to the command line. function varargout = idrecgui_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 browseCallback(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) initcontrols(handles) preprocess(handles) process(handles) end
function initcontrols(handles) global filenames currentselectidx currentselectidx=1; if ischar(filenames) filenames={filenames}; end if ischar(filenames) || length(filenames)==1 set(handles.imgidx,'String','') set(handles.imgidxslider,'Visible','off') else set(handles.imgidxslider,'Visible','on') set(handles.imgidxslider,'Min',0) set(handles.imgidxslider,'Max',length(filenames)-1) set(handles.imgidxslider,'SliderStep',ones(1,2)/(length(filenames)-1)) end set(handles.validate,'Enable','on')
function [orgimg,imggray,threshvalue]=readidcard(filename) fileinfo=imfinfo(filename); if strcmpi(fileinfo.ColorType,'indexed') [X,map]=imread(filename); orgimg=ind2rgb(X,map); else orgimg=imread(filename); end r=size(orgimg,1); c=size(orgimg,2); sizethresh=2000; if r>sizethresh orgimg=imresize(orgimg,sizethresh/r); end if c>sizethresh orgimg=imresize(orgimg,sizethresh/c); end orgimg=im2double(orgimg); if ndims(orgimg)==3 imggray=rgb2gray(orgimg); else imggray=orgimg; end imggray=imresize(imggray,[350 500]); imggray=imggray(round(size(imggray,1)2/3):end,round(size(img_gray,2)/4):end); thresh_value=.68graythresh(img_gray);
function preprocess(handles) global pathname filenames currentselectidx imggray if length(filenames)>1 imgidxstr=sprintf('%d / %d',currentselectidx,length(filenames)); set(handles.imgidx,'String',imgidxstr) set(handles.imgidxslider,'Value',currentselectidx-1) set(handles.imgidxslider,'TooltipString',imgidxstr) end try filename=fullfile(pathname,filenames{currentselectidx}); [orgimg,imggray,threshvalue]=readidcard(filename); axes(handles.img) imshow(orgimg),title(filename,'Interpreter','None') set(handles.threshvalue,'Visible','on') set(handles.threshvalue,'value',thresh_value) catch e msgbox(sprintf('Cannot read the image: %s.\n\n',filename,e.message),'Error','error') rethrow(e) end
function process(handles) global codestats imggray model filenames currentselectidx areacodes trainingdata_size if isequal(filenames,0) || isempty(filenames) return end
% init all controls for i=1:18 set(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.IDcode,'BackgroundColor',[1 1 1]) set(handles.IDcode,'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.threshvalue,'value'); [idcodes,idbw,codestats,thresh,iteration]=idrecprocess(imggray,model,thresh,trainingdatasize,1); % if isempty(idcodes) % msgbox('Cannot recognize ID codes. You can try adjusting the threshold value.','Warning','warn','modal') % return % end ```