%方法一 (字幅分割:X方向投影后,根据突变边缘作为分割边界)
clear all
clc
close all
open imshow;
%1,图像的预处理,读入彩色图像将其灰度化
PS=imread('ID.jpg'); %读 入JPG彩色图像文件
PS_ini=PS;
figure,imshow(PS) %显 示出来 figureNO 1
title('输入的彩色JPG图像');
%imwrite(rgb2gray(PS),'C:\Users\lvz\Desktop\ID_figure\gray.bmp'); %将 彩色图片灰度化并保存
PS=rgb2gray(PS); %灰度化后的数据存入数组
figure;
imshow(PS) %显 示灰度化后的图像,也是均衡化前的样品 figure NO 2
title('灰度化后的图像');
%2, 对灰度化后的身份证图像进行canny边缘检测,得到二值边缘图像
figure;
THRESH=[0.4 0.9];
edge_PS=edge(PS,'canny',THRESH);
imshow(edge_PS)
title('canny 边缘检测');
%3, Hough 变换检测图像中所有直线,找出长度最长的直线,即身份证上( 或下) 边界
theta_d=1;
[H,T,R] = hough(edge_PS,'Theta',-90:theta_d:89);
figure;
H_gray=mat2gray(H);
imshow(imadjust(H_gray),'XData',T,'YData',R,...
'InitialMagnification','fit');
title('Hough 变换的映射,找出其中最大值对应的点,为身份证最长边缘');
xlabel('\theta'), ylabel('\rho');
axis on, axis normal;
[max_rows,max_cols]=find(H_gray==max(max(H_gray)));
best_theta=-90+(max_cols-1)*theta_d
if best_theta>30
best_theta=best_theta-90;
end
%5 图像旋转
image_rotation=[];
image_rotation=imrotate(PS,best_theta,'nearest');
figure;
imshow(image_rotation);
title('调正后的图像');
%6 身份证区域边界确定及分割
figure;
THRESH=[0.4 0.9];
edge_image_rotation=edge(image_rotation,'canny',THRESH);
imshow(edge_image_rotation)
title('canny 边缘检测');
[M,N]=size(edge_image_rotation);
y_max=1;
y_min=M;
x_max=1;
x_min=N;
for y=1:M
for x=1:N
if edge_image_rotation(y,x)>0
if x>x_max
x_max=x;
end
if x<x_min
x_min=x;
end
if y>y_max
y_max=y;
end
if y<y_min
y_min=y;
end
end
end
end
ID_area=image_rotation(y_min:y_max,x_min:x_max);
imshow(ID_area);
title('基于canny边缘检测,将身份证区域分割出来');
[M,N]=size(ID_area);
%7 号码区域粗分割
figure;%根据号码在身份证上的位置进行粗分割
data_area=ID_area(round(M*16/20):round(M*18/20),round(N*5/16):round(N*15/16));
imshow(data_area);
title('根据数字区域在身份中的固定位置比例,粗提取数字区域');
[M,N]=size(data_area);%绘制灰度直方图 确定二值化阈值
GP=zeros(1,256); %创建存放灰度出现概率的向量
for k=0:255
GP(k+1)=length(find(PS==k))/(M*N); %计算每级灰度出现的概率,将其存入GP中相应位置
end
figure;
bar(0:255,GP,'g')
title('原图像直方图,用于确定将数字区域二值化的阈值');
xlabel('灰度值');
ylabel('出现概率');
for y=1:M
for x=1:N
if data_area(y,x)>100
data_area(y,x)=0;
else
data_area(y,x)=255;
end
end
end
figure;
imshow(data_area);
title('二值化处理');
%8 每个数字的分割,y方向投影,确定上下边沿;x方向投影,分割字母
X_shadow=sum(data_area); %求出图像向X轴的投影
Y_shadow=sum(data_area'); %求出图像向Y轴的投影
plot(X_shadow);
title('X方向投影');
[M,N]=size(X_shadow);
X_max(1:18)=1;% 记录18个数字的开始、结束坐标
X_min(1:18)=N;
i=1;
j=1;
for x=1:N-3 % 记录18个数字的开始、结束坐标
if X_shadow(x)<800 && X_shadow(x+1)<800 && X_shadow(x+2)<800
if X_shadow(x+3)>1000
X_min(i)=x;
i=i+1;
end
end
if X_shadow(x)>1000
if X_shadow(x+1)<800 && X_shadow(x+2)<800 && X_shadow(x+3)<800
X_max(j)=x;
j=j+1;
end
end
end
[A,B]=size(Y_shadow);% 记录上下边缘的坐标
Y_max=1;
Y_min=B;
for y=1:B
if Y_shadow(y)>1000
if y>Y_max
Y_max=y;
end
if y<Y_min
Y_min=y;
end
end
end
data_area_cut=data_area(Y_min:Y_max,:); % 显示切割效果
en=0;
for x=1:N-1
en=0;
for i=1:18
if x==X_min(i) | x==X_max(i)
en=1;
end
end
if en==1
data_area_cut(:,x)=255;
end
end
figure;
imshow(data_area_cut);
title('显示切割边缘');
xlabel('方法:y方向投影,确定上下边沿;x方向投影,分割字母');
% %9将切割出来的字符输出,并建立字符库,用于之后的数字判断
%
%
% word0=imresize(data_area(Y_min:Y_max,X_min(3):X_max(3)),[40 20]);
% imwrite(word0,'C:\Users\lvz\Desktop\ID_figure\0.bmp');
% word1=imresize(data_area(Y_min:Y_max,X_min(7):X_max(7)),[40 20]);
% imwrite(word1,'C:\Users\lvz\Desktop\ID_figure\1.bmp');
% word2=imresize(data_area(Y_min:Y_max,X_min(4):X_max(4)),[40 20]);
% imwrite(word2,'C:\Users\lvz\Desktop\ID_figure\2.bmp');
% word3=imresize(data_area(Y_min:Y_max,X_min(1):X_max(1)),[40 20]);
% imwrite(word3,'C:\Users\lvz\Desktop\ID_figure\3.bmp');
% % word4=imresize(data_area(Y_min:Y_max,X_min(6):X_max(6)),[40 20]);
% % imwrite(word4,'C:\Users\lvz\Desktop\ID_figure\4.jpg');
% % word5=imresize(data_area(Y_min:Y_max,X_min(18):X_max(18)),[40 20]);
% % imwrite(word5,'C:\Users\lvz\Desktop\ID_figure\5.jpg');
% % word6=imresize(data_area(Y_min:Y_max,X_min(14):X_max(14)),[40 20]);%实例图片中,这几位数字没有
% % imwrite(word6,'C:\Users\lvz\Desktop\ID_figure\6.jpg');
% word7=imresize(data_area(Y_min:Y_max,X_min(14):X_max(14)),[40 20]);
% imwrite(word7,'C:\Users\lvz\Desktop\ID_figure\7.bmp');
% word8=imresize(data_area(Y_min:Y_max,X_min(5):X_max(5)),[40 20]);
% imwrite(word8,'C:\Users\lvz\Desktop\ID_figure\8.bmp');
% word9=imresize(data_area(Y_min:Y_max,X_min(8):X_max(8)),[40 20]);
% imwrite(word9,'C:\Users\lvz\Desktop\ID_figure\9.bmp');
% wordX=imresize(data_area(Y_min:Y_max,X_min(18):X_max(18)),[40 20]);
% imwrite(wordX,'C:\Users\lvz\Desktop\ID_figure\XX.bmp');
% word4=imresize(data_area(Y_min:Y_max,X_min(6):X_max(6)),[40 20]);
% imwrite(word4,'C:\Users\lvz\Desktop\ID_figure\4.bmp');
% word5=imresize(data_area(Y_min:Y_max,X_min(18):X_max(18)),[40 20]);
% imwrite(word5,'C:\Users\lvz\Desktop\ID_figure\5.bmp');
% word6=imresize(data_area(Y_min:Y_max,X_min(14):X_max(14)),[40 20]);%实例图片中,这几位数字没有
% imwrite(word6,'C:\Users\lvz\Desktop\ID_figure\6.bmp')
word0=imresize(imread('module\\0.bmp'),[40 20]); %读其他模板
word1=imresize(imread('module\\1.bmp'),[40 20]); %读其他模板
word2=imresize(imread('module\\2.bmp'),[40 20]); %读其他模板
word3=imresize(imread('module\\3.bmp'),[40 20]); %读其他模板
word4=imresize(imread('module\\4.bmp'),[40 20]); %读其他模板
word5=imresize(imread('module\\5.bmp'),[40 20]); %读其他模板
word6=imresize(imread('module\\6.bmp'),[40 20]); %读其他模板
word7=imresize(imread('module\\7.bmp'),[40 20]); %读其他模板
word8=imresize(imread('module\\8.bmp'),[40 20]); %读其他模板
word9=imresize(imread('module\\9.bmp'),[40 20]); %读其他模板
wordX=imresize(imread('module\\XX.bmp'),[40 20]); %读其他模板
%
%
%10输出字符作为模板,用于模式识别;模板与需要判断的字符的差,作为匹配依据
for i=1:18
m=i
word=imresize(data_area(Y_min:Y_max,X_min(i):X_max(i)),[40 20]);
for j=1:11
switch j
case 1, word_module=word0;
case 2, word_module=word1;
case 3, word_module=word2;
case 4, word_module=word3;
case 5, word_module=word4;
case 6, word_module=word5;
case 7, word_module=word6;
case 8, word_module=word7;
case 9, word_module=word8;
case 10, word_module=word9;
case 11, word_module=wordX;
end
n=j
word_error=abs(word-word_module);
total_error(j)=sum(sum(word_error))
end
min_error=min(total_error);
min_index(i)=find(total_error=