为快速识别身份证号码,以计算机视觉系统为技术手段,以第二代居民身份证为研究对象,从身份证号码图像中提取号码数字0—9的空间分布特征和结构特征,采用相似系数最大和结构特征一致准则,应用MATLAB软件编程实现了身份证号码的快速识别.运用图像处理和模式识别技术,实现了身份证号码图像的预处理、图像分割、号码图像的修正、号码体的定位、号码体的识别等算法,建立了基于摄像头的身份证号码识别系统.系统的识别速度和准确率可满足实际需要.
身份证号码是公民身份的唯一标识,出于保障公民合法权益和社会治安的考虑,越来越多的行业都开始要求录入客户的身份证,这是一项非常繁琐的工作.手工录入效率低且容易出错.为解决此问题,笔者基于各个数字的不同,对身份证进行一系列预处理后精确地把数字分割出来,采用MATLAB对身份证号码进行识别.实验证明,该方法的识别速度和准确率可以满足实际需要.
由于我国第二代身份证是彩色的,而且是大小固定的,身份证右下方有18位号码,字体类型是OCR-B10BT。基于以上这些特点,进行身份证图像采集、图像预处理、定位、字符分割、字符识别等过程最后输出身份证号码[1]。
身份正号的提取和识别,使用图像处理的方法进行提取。首先需要做的是,采集获取高质量的身份证图像信息,考虑到现在的第二代身份证是彩色的,所以推荐使用彩色的CCD相机采集获取图像。将身份证,放置在黑色背景的平板桌边上面,进行采集,并且光照尽量均匀。这样方便后续的处理。
1、打开图像
[FileName,PathName] = uigetfile('*.jpg','Select an image');
if PathName~=0
str = [PathName,FileName];
T=imread(str);
axes(handles.axes1);
imshow(T);
end
[m,n,r]=size(I);%图像的像素为width*height
%%%%%蓝色字体变黑
myI=double(I);
for i=1:m
for j=1:n
if((myI(i,j,1)>=15)&&(myI(i,j,1)<=130)&&((myI(i,j,2)<=165)&&(myI(i,j,2)>=90))&&((myI(i,j,3)<=220)&&(myI(i,j,3)>=135))) % 蓝色RGB的灰度范围
I(i,j,1)=40; %红色分量
I(i,j,2)=40; %绿色分量
I(i,j,3)=40; %蓝色分量
end
end
end
%figure, imshow(I);title('变色后的图像');
width=round(0.9*n);height=round(0.87*m);
rx=round(0.05*n);cy=round(0.075*m);
I=subim(I,height,width,rx,cy);
%figure,imshow(I);
if sum(size(I)>0)==3 %倘若是彩色图--2维*3,先转换成灰度图
I=rgb2gray(I);
end
%figure,imhist(I);
x=3;%行数分为x部分
y=1;%列数分为y部分
BW=erzhihua(I,x,y);
[n m l]=size(BW);%图像的像素为m*n
c = [0.65*m 0.65*m m m];
r = [0 0.85*n 0.85*n 0];
BW = roifill(BW,c,r);
BW=imadjust(BW);%使用imadjust函数对图像进行增强对比度
% Convert to BW
threshold = graythresh(BW);
BW =~im2bw(BW,0.6*threshold);
[image_h image_w]=size(BW);
% Remove all object containing fewer than (imagen/80) pixels
BW = bwareaopen(BW,floor(image_w/80));
% 滤波
imshow(BW);
[image_h image_w]=size(imagen);
%figure;imshow(imagen);title('INPUT IMAGE')
% Convert to gray scale
if size(imagen,3)==3 %RGB image
imagen=rgb2gray(imagen);
end
%Storage matrix word from image
word=[ ];
re=imagen;
% Compute the number of letters in template file
num_letras=size(templates,2);
plot_flag=1;
while 1
%Fcn 'lines' separate lines in text
[fl re]=lines(re);
imgn=fl;
[line_h line_w]=size(fl);%记录下切割出来的一行字符的长宽
%Uncomment line below to see lines one by one
% imshow(fl);pause(1)
%-----------------------------------------------------------------
% Label and count connected components
[L Ne] = bwlabel(imgn);
n=1;%记录循环次数
while(n<=Ne)
char_flag=0;%为0时,是第一次判断这个连通域
flag=1;%初始化两个连通域属于同个字符
while(flag==1)
if char_flag==0
[r,c] = find(L==n);
Width0=max(r)-min(r);%连通域宽度
Height0=max(c)-min(c);%连通域高度
Radio0=Width0/Height0;%连通域宽高比
Square0=Width0*Height0;%连通域面积
maxr=max(r);
maxc=max(c);
minr=min(r);
minc=min(c);
end
if n [r1,c1] = find(L==(n+1));%寻找下一个连通域 Width1=max(r)-min(r);%连通域宽度 Height1=max(c)-min(c);%连通域高度 Radio1=Width1/Height1;%连通域宽高比 Square1=Width1*Height1;%连通域面积 Uheight=max(maxc,max(c1))-min(minc,min(c1));%合并后高度 Uwidth=max(maxr,max(r1))-min(minr,min(r1));%合并后宽度 Uradio=Uwidth/Uheight;%合并后的宽高比 Oheigth=Height0+Height1-Uheight;%重叠高度 Owidth=Width0+Width1-Uwidth;%重叠宽度 Osquare=Oheigth*Owidth;%重叠面积 else flag=0;%这是这一行最后一个连通域 end ph=5;%边界因子 pw=7; if(flag==1)&&((Owidth>=-(image_w/pw)&&Owidth<=0)||(Oheigth>=-(line_h*0.3)&&Oheigth<=0))%两个连通域较近,但不重叠 if((Uradio>=0.8)&&(Uradio<=1.2))%认为两个连通域属于同一个字符 elseif Uheight else flag=0;%否则这两个连通域属于不同字符 end elseif(flag==1)&&(Owidth<-(image_w/pw))%两个连通域里相距较远 flag=0;%两个连通域属于不同字符 % elseif(flag==1)&&((Owidth>0)||(Oheigth>0))%两连通域重叠 elseif(flag==1)&&((Owidth>0))%两连通域重叠 if(((Uradio>=0.78)&&(Uradio<=1.3)))%认为两个连通域属于同一个字符 elseif(Osquare>=0.4*min(Square0,Square1)&&(Uwidth else flag=0;%两个连通域属于不同字符 end else flag=0;%两个连通域属于不同字符 end if flag==1%经过上面判断,两个连通域属于同一个字符,进行连通域合并 Width0=Uwidth;%连通域宽度 Height0=Uheight;%连通域高度 Radio0=Width0/Height0;%连通域宽高比 Square0=Width0*Height0;%连通域面积 maxr=max(maxr,max(r1)); maxc=max(maxc,max(c1)); n=n+1;%指向下一个连通域 char_flag=1; end end %while(flag==1)的end % Extract letter n1=imgn(minr:maxr,minc:maxc); % Resize letter (same size of template) % Call fcn to convert image to text letter=read_letter(img_r,num_letras); % Letter concatenation word=[word letter]; n=n+1; end % while(n<=Ne)的end %fprintf(fid,'%s\n',lower(word));%Write 'word' in text file (lower) set(handles.edit1,'string',word); word=[ ];