这是一个基于matlab模板匹配法的车牌识别,是一个不需要太多繁琐子程序也不用GUI的简单的程序,关于这个程序仅仅供大家参考,欢迎广大读者指出其中的错误。关于程序中出现的一些函数的用法,有疑问或者是有兴趣的同学可以上网检索更多有关的信息。若有需要使用本文章,欢迎转载引用。对于文章中出现的各个模板,由于这里篇幅有限,还请读者自己去查找。
这个程序算是比较简单的,多读几次程序应该是还是能弄明白的
clc
clear
close all
I=imread('chepai.jpg');
subplot(3,2,1);imshow(I), title('原始图像');
I_gray=rgb2gray(I);
subplot(3,2,2),imshow(I_gray),title('灰度图像');
首先读入原图像并灰度化处理,方便后续的操作
图1:读入车牌
I_edge=edge(I_gray,'sobel');
subplot(3,2,3),imshow(I_edge),title('边缘检测后图像');
se=[1;1;1];
I_erode=imerode(I_edge,se);
subplot(3,2,4),imshow(I_erode),title('腐蚀后边缘图像');
se=strel('rectangle',[25,25]);
I_close=imclose(I_erode,se);
subplot(3,2,5),imshow(I_close),title('填充后图像');
I_final=bwareaopen(I_close,2000);
subplot(3,2,6),imshow(I_final),title('形态滤波后图像');
以上步骤是对原图像的形态学的预处理,首先对灰度图进行边缘检测,这里用的是sobel算子,阈值默认就好。然后我们需要进行腐蚀操作,这里使用一个se=[1,1,1]的3行1列的矩阵来腐蚀,其目的是可以把图像中所有的横线给去掉。
边缘检测及腐蚀
边缘腐蚀后,我们需要对其进行图像填充,以便后续的车牌定位操作,完成填充后我们会发现把我们不需要的部分也扩大了,所以我们接着使用一个形态滤波函数对灰度团小于2000的部分进行处理得到如下图片
形态学处理
经过预处理后我们此时可以对车牌进行定位了,具体程序如下
I_new=zeros(size(I_final,1),size(I_final,2));
location_of_1=[];
for i=1:size(I_final,1) %寻找二值图像中白的点的位置
for j=1:size(I_final,2)
if I_final(i,j)==1
newlocation=[i,j];
location_of_1=[location_of_1;newlocation];
end
end
end
mini=inf;maxi=0;
for i=1:size(location_of_1,1)
%寻找所有白点中,x坐标与y坐标的和最大,最小的两个点的位置
temp=location_of_1(i,1)+location_of_1(i,2);
if temp<mini
mini=temp;
a=i;
end
if temp>maxi
maxi=temp;
b=i;
end
end
first_point=location_of_1(a,:);
last_point=location_of_1(b,:);
x1=first_point(1)+4;
x2=last_point(1)-4;
y1=first_point(2)+9.5;
y2=last_point(2)-4;
I_plate=I(x1:x2,y1:y2);
I_plate=OTSU(I_plate); %以OTSU算法对分割出的车牌进行自适应二值化处理
I_plate=bwareaopen(I_plate,50);
figure,imshow(I_plate),title('车牌提取') %画出最终车牌
首先将图像中所有的白点放入location_of_1之中通过寻找图像中坐标和最大和最小的点来确定车牌的边界。找到车牌的位置后,我们还需要对其进行二值化处理,所以我们需要确定一个可供使用的阈值,这里使用的是OTSU算法,又叫大津算法,其主要思想是,假设我们需要求得阈值K,可以把[1.k]的部分的概率定为w1,[k+1,256]的部分定义的概率定为w2,同样我们也可求得[1,k]的平均灰度值m1和[k+1,256]的平均灰度值m2,还能求得全图的平均灰度值mg,已知条件还有w1+w2=1,m1w1+m2w2=mg,可得公式Jw(k)=w1*w2*(m1-m2)^2;
再通过寻找能使等式最大的K值就是我们所需要的阈值,这里也不多做赘述,网上有更加详细的解释。
这里新建一个OTSU函数子程序如下
function J=OTSU(I)
Hi=imhist(I); %直方图
sum1=sum(Hi);
for i=1:255
w1=sum(Hi(1:i))/sum1; %第一类概率
w2=sum(Hi((i+1):256))/sum1; %第二类概率
m1=(0:(i-1))*Hi(1:i)/sum(Hi(1:i)); %第一类平均灰度值
m2=(i:255)*Hi((i+1):256)/sum(Hi((i+1):256));%第二类平均灰度值
Jw(i)=w1*w2*(m1-m2)^2;
end
[maxm,thresh]=max(Jw); %寻找阈值
% subplot(2,2,1);imshow(I);title('原图像');
% subplot(2,2,[3,4]);imhist(I);hold on;plot(thresh,3,'+r');title((strcat('阈值为',num2str(thresh))));
I(find(I<=thresh))=0;
I(find(I>thresh))=256; %二值化
J=I;
% subplot(2,2,2),imshow(I),title('二值化图像zk');
然后是字符分割,其主要思想就是通过寻找白点的位置来逐一分割各个位置,从图中我们不难发现,每个字符的上下左右之所以能被切割,真是因为有白点的存在,通过循环函数来逐行逐列地扫描定位出的车牌图像,程序如下
X=[]; %用来存放水平分割线的横坐标
flag=0;
for j=1:size(I_plate,2)
sum_y=sum(I_plate(:,j));
if logical(sum_y)~=flag %列和有变化时,记录下此列
X=[X j];
flag=logical(sum_y);
end
end
figure
for n=1:7
char=I_plate(:,X(2*n-1):X(2*n)-1); %进行粗分割
for i=1:size(char,1) %这两个for循环对分割字符的上下进行裁剪
if sum(char(i,:))~=0
top=i;
break
end
end
for i=1:size(char,1)
if sum(char(size(char,1)-i,:))~=0
bottom=size(char,1)-i;
break
end
end
char=char(top:bottom,:);
subplot(2,4,n);imshow(char);
char=imresize(char,[40,20],'nearest');
eval(strcat('Char_',num2str(n),'=char;')); %将分割的字符放入Char_i中
end
最后一步,字符的识别,这里我们需要现准备好自己的字符库,主要包括34个省份自治区直辖市的缩写,0~9十个阿拉伯数字以及没有O的25个大写英文字母。先放出程序
liccode=strcat(['0':'9' 'A':'H' 'J':'N' 'P':'Z' '藏川鄂甘赣桂贵黑沪吉冀津晋京辽鲁蒙闽宁青琼陕苏皖湘新渝豫粤云浙']); %建立自动识别字符代码表
SubBw2=zeros(40,20);
l=1;
for I=1:7
ii=int2str(I);%将整形变成字符串
t=imread([ii,'.jpg']);
SegBw2=imresize(t,[40 20],'nearest');
%进行二值化,方便比较
g_max=double(max(max(SegBw2)));
g_min=double(min(min(SegBw2)));
T=round(g_max-(g_max-g_min)/2); % T为二值化的阈值
SegBw2=(double(SegBw2)>=T); % SegBw2切割下来的字符的二值图像
if l==1 %第一位汉字识别
kmin=35;
kmax=65;
elseif l==2 %第二位 A~Z 字母识别
kmin=11;
kmax=34;
else l>=3; %第三位以后是字母或数字识别
kmin=1;
kmax=34;
end
%在每一位对应区间按顺序提取字符模板
for k2=kmin:kmax
fname=strcat('字符模板',liccode(k2),'.jpg');
SamBw2 = imread(fname);
if(k2~=2)
SamBw2=rgb2gray(SamBw2);
end
g_max=double(max(max(SamBw2)));%二值化处理字符模板
g_min=double(min(min(SamBw2)));
T=round(g_max-(g_max-g_min)/2); % T为二值化的阈值
SamBw2=(double(SamBw2)>=T); % SamBw2为字符模板的二值图像
%字符图像与模板进行比较
a1(k2)=corr2(SegBw2,SamBw2);
end
A1=a1(kmin:kmax);%将比较结果放入矩阵A1
MaxA1=max(A1);%找到比较结果最大值
findc=find(A1==MaxA1);%获取最大值所在位置
Code(l*2-1)=liccode(findc(1)+kmin-1);
Code(l*2)=' ';
l=l+1;%进行下一字符的提取和比较
end
figure,imshow('chepai.jpg')
xlabel(['识别结果为: ', Code]);
第一步先给那些模板以字符连接,然后再对具体的每一位进行顺序比对,if语句中的I所代表的就是车牌的第几位字符,比如说,I=1,是第一位,那它一定是个汉字,所以我们就对其与汉字模板进行一一比对,corr2函数就是用来比对的,如果模板与原图像越接近,那这个函数就越接近于1,我们只需要找出其最大的值就能很好的比出模板图像