基于模板匹配的车牌识别

  • 一、设计思路
  • 二、功能模块
    • 1、GUI界面创建
    • 2、图片选择
    • 3、车牌粗定位
    • 4、灰度化
    • 5、倾斜矫正
    • 6、二值化和第一次形态学处理
    • 7、精确定位
    • 8、第二次形态学处理
    • 9、字符分割
    • 10、归一化切割后的字符以及模板
    • 11、字符匹配
    • 12、语音播报
    • 13、退出系统和关于按钮
  • 三、总的操作图

一、设计思路

车牌识别程序的设计主要基于车牌的固有特点,这些特点指导算法的设计。在一个识别系统中首先选择某一个或几个车牌的特点,然后根据这些特点设计算法。一般情况下,选择的特点越多,识别的正确率越高,但程序也将变得冗杂,效率低下。因为本实验主要对小型汽车车牌识别系统的设计,所以总结小型汽车车牌的特点如下所示:
(1)颜色特点:车牌为蓝底白字。并且白色的面积占总面积的比例在一定范围之内。从这个特点中可以想到通过在一张照片中查找蓝色区域,并且区域内的白色面积占总面积的比例在一定范围内来初步定为车牌区域。
(2)形状特点:车牌形状为矩形,虽然图片中的车牌区域面积的大小不确定,但车牌区域的长与宽的比在一定范围之内,这一特点很容易通过编程语言实现。
(3)纹理特点:车牌信息是以水平方式排列的,所以水平方向的纹理特点是我们的主要研究方向。
(4)背景对比特点:车牌背景为蓝色,字符信息为白色。对车牌进行灰度化处理后,当从左向右扫描时,可以看到灰度值是有明显变化的。在字符与字符之间,有峰值和谷值。利用这个特点可以设计字符分割算法。

从图1中可以看出我国小型汽车车牌的特征。其中第一个字符为汉字,它是省、直辖市和自治区的简称。图2-1中的京即为北京的简称。第二个字符为该省、直辖市或自治区内的地级市、地区、自治州和盟的代码,其中‘A’表示省会、首府或直辖市中心。并且没有字母I和O。后面五位为车牌序号,序号为0到9,大于9用字母表示。
通过车牌的特点,车牌识别系统的主程序可分为GUI界面制作、图片选择、车牌定位、字符分割、字符识别、显示内容六个个大的部分。

二、功能模块

1、GUI界面创建

GUI(Graphical User Interfaces)中文名称为图形用户界面,是一种面向对象的设计,实现用户与计算机的交互。GUI模块是MATLAB的重要组成部分,因为在GUI设计时,MATLAB提供各种控件,比如菜单、文本框、按钮等,并且可以直接修改控件的属性,极大地方便编程。
GUI界面为一个图形界面,图形内有各种控件,对这些控件的操作是通过句柄(handle)完成,每个控件都有一个句柄,并且是唯一的。通过句柄选中对象,然后修改该对象的属性,完成对控件的精确控制。GUI给出很多控件,如图7-1所示,常用的控件有按钮、单选按钮、复选按钮、坐标轴、静态文本等等,每个控件都可编写回调函数,可以选择触发回调函数的条件,比如单击鼠标、选择菜单等等。
本文使用到GUI的控件有按钮、单选框、单选按钮、坐标轴框、静态文本、按钮组和面板。



在命令行窗口输入guide再按回车就可以打开设计GUI界面的窗口啦
然后根据自己的需要,将左侧控件拖到操作区部分,双击控件可以进入到控件的属性设置,可以设置颜色啊,文本啊,控件的ID啊之类的,然后鼠标右键→查看回调→选择回调函数然后就可以在代码编辑器里面在相应控件的回调函数写对应的操作代码。

2、图片选择

图片选择的操作代码写在“选择图片”按钮的回调函数内,通过uigetfile函数打开文件选择对话框,并返回文件的名称和路径,handles找到对应对象,guidata对更新后的结构体进行保存。之后的代码都是在“开始识别”按钮的回调函数里面了。

function varargout = xuliu_OutputFcn(hObject, eventdata, handles)
varargout{1} = handles.output;
%点击‘选择图片’按钮执行的程序
function open_Callback(hObject, eventdata, handles)
[filename,pathname] = uigetfile('*.jpg','选择图片');
handles.filename = filename;
guidata(hObject,handles);
zhaopianlujing=[pathname filename];
handles.zhaopianlujing = zhaopianlujing;
guidata(hObject,handles);

3、车牌粗定位

车牌定位是车牌自动识别系统中非常重要的部分,复杂的背景和模糊的图片都给车牌定位带来困难,拥有良好的车牌识别系统性能不仅要求车牌定位的准确性高,而且定位的速度也要高。车牌的定位的方法的依据是车牌的诸多特点,在一张照片中找寻符合车牌特征的部分,并将其切割出来,实现车牌的定位。经过前人的研究,车牌定位主要有以下几种方法:
(1)根据车牌颜色信息的车牌定位。
(2)根据车牌纹理特征的车牌定位。
(3)根据边缘检测方法的车牌定位[。
(4)根据小波变换方法的车牌定位。
(5)综合多种方法的车牌定位。
本实验的车牌自动识别系统识别的车牌为蓝底白字车牌,针对我国蓝底白字车牌的颜色特征,本文的车牌粗定位算法是基于RGB颜色识别,寻找图片中蓝底白字车牌位置。根据车牌蓝底白字这一颜色特征,可以得出车牌所在位置有两个特点:(1)蓝色背景。(2)白色像素与车牌面积之比在一定范围之内。根据这两个特点可以得到疑似车牌所在区域。
因为一张车牌照片的背景可能很复杂,若仅仅根据车牌蓝底白字这一颜色特征来定位车牌,那么会出现很多错误定位。因此本文除了依靠车牌的颜色特征辨别车牌位置之外,还有车牌的形态特征,即定位出的车牌的长宽比要在允许范围之内。
运用车牌蓝底白字的颜色特征和长宽比的形状特征,对原始图片进行粗定位。

主代码:
[ydown,yup,xright,xleft]=first_location(yt);
[ydown,yup,xright,xleft,yuzhi]=xiuzheng(ydown,yup,xright,xleft);  %车牌区域根据面积二次修正
Plate = yt(yup:ydown,xleft:xright,:);
handles.Plate = Plate;   %放入handles结构体中,方便在其他回调函数中调用 第二张图片
guidata(hObject,handles);
bw=Plate;
子程序:
function [ydown,yup,xright,xleft]=first_location(img)
[y,x,~]=size(img);
img = double(img);  %转化为double型数据
y_yuzhi = 5;  %y的蓝色边界阈值
%在这里对于阈值的设置,阈值越大,截到的范围越小,为了避免车牌倾斜而导致切割掉有用部分,先设置一个较小的阈值,后面会对其进行二次切割。
%====================== Y 方向============================
y_lanse=zeros(y,1);
for b=1:yfor c=1:x  if((img(b,c,1)<=48)&&((img(b,c,2)<=100)&&(img(b,c,2)>=40))&&((img(b,c,3)<=200)&&(img(b,c,3)>=80)))     %判断是否为蓝色RGBy_lanse(b,1)= y_lanse(b,1)+1;      % Y方向蓝色象素点统计                    end  end
end
k=0;  %记录蓝色区域的循环次数
[~,y_max_hang] = max(y_lanse); % Y方向车牌区域,temp是最大值,MaxY是所在的行数。
yup=y_max_hang;    %有最多蓝点的行付给yup
while ((y_lanse(yup,1)>=y_yuzhi)&&(yup>1))%找到车牌上边界yup=yup-1;
end
%yup 存储车牌上边界值
ydown=y_max_hang;
while ((y_lanse(ydown,1)>=y_yuzhi)&&(ydown<y))  %找到车牌下边界ydown=ydown+1;
end
%==============X 方向===============================
x_yuzhi=fix((ydown-yup)/11);  %向零舍入,这个数值很重要。决定了提取的彩图的质量,适当提高可抗干扰,但是小图会造成剪裁太多
x_lanse=zeros(1,x);             % 初始化蓝色矩阵
for c=1:xfor b=yup:ydown   if((img(b,c,1)<=65)&&((img(b,c,2)<=100)&&(img(b,c,2)>=40))&&((img(b,c,3)<=160)&&(img(b,c,3)>=90)))%这里由82修改成90. x_lanse(1,c)= x_lanse(1,c)+1;     %统计每列蓝色像素个数          end  end
end
[~,x_max_lie]=max(x_lanse);  %temp是最大值,MaxX是最大值所在的列数。
xleft=x_max_lie-6*(ydown-yup);%这里根据长宽比得到初步边界。
if  xleft<=1     %防止溢出边界。xleft=1;
end
while ((x_lanse(1,xleft)<=x_yuzhi)&&(xleft<x))%确定X的左边起点。xleft=xleft+1;
end
xright=x_max_lie+6*(ydown-yup);%得到初步的X右边边界。
if  xright>=x     %防止溢出边界。xright=x;
end
while ((x_lanse(1,xright)<=x_yuzhi)&&(xright>xleft))%%确定X的右边终点。xright=xright-1;
end%=========================检验粗定位结果是否符合规范================================
kuan=ydown-yup+1;chang=xright-xleft+1;
White=0;       %设置白色像素点变量
for b=yup:ydownfor c=xleft:xrightif (std([img(b,c,1) img(b,c,2) img(b,c,3)],1,2)<=22)&&(img(b,c,1)>=90)&&(img(b,c,1)<=255)  %std为求标准差函数%第三个参数代表的是按照列求标准差还是按照行求标准差,std(A,1,1)代表的是按照列求标准差,std(A,1,2)代表的是按照行求标准差。White= White+1;    % 白色象素点统计                    end  end
end
bai_lan_bi=White/(kuan*chang);
kuan_chang_bi=kuan/chang;
k=k+1;
while(~((bai_lan_bi>=0.12)&&(bai_lan_bi<=0.5)&&(kuan_chang_bi>=0.20)&&(kuan_chang_bi<=0.6)))  %判断白蓝比与宽长比是否符合条件,若不符合则进入下面程序,继续判断。
%===========================蓝色区域不是车牌区域=====================
% y_lanse(yup:ydowm,1)=0;   %在图片中将不是车牌区域置0
for m=yup:ydownfor n=xleft:xrightimg(m,n,1)= 0;img(m,n,2)=0;img(m,n,3)=0;end
end
%防止陷入死循环
if (xright<=xleft)||(yup>=ydown)msgbox('粗定位出错','警告');pause(1);ydown=-5;break ;
end
end

4、灰度化

bw=rgb2gray(bw);
chepaihuidu = bw;
handles.chepaihuidu = chepaihuidu;     %第三张图片
guidata(hObject,handles);

5、倾斜矫正

因为拍照角度的不同,车牌经过粗略定位后,得到的图片中的车牌可能是倾斜的,所以首先要进行倾斜矫正。
倾斜矫正后的车牌图片中不仅有车牌信息,还有车牌的螺栓、边框、杂质等干扰信息。车牌精确定位的目的是去除车牌边框,清除干扰信息,获得更精确的车牌位置,为后面的字符分割和字符识别奠定基础。

主代码:%===========倾斜矫正=============
qingxiejiao=rando_bianhuan(bw);
bw=imrotate(bw,qingxiejiao,'bilinear','crop');%取值为负值向右旋转
jiaozhenghou = bw;
handles.jiaozhenghou = jiaozhenghou;     %第四张图片,车牌倾斜矫正后的图片
guidata(hObject,handles);
子程序:
function qingxiejiao=tilt_correct(I)
I=edge(I);%BW = edge(I) 返回二值图像 BW,其中的值 1 对应于灰度或二值图像 I 中函数找到边缘的位置,
% 值 0 对应于其他位置。默认情况下,edge 使用 Sobel 边缘检测方法。
theta = 1:180;
[R,~] = radon(I,theta);%R = radon(I,theta) 返回基于 theta 所指定角度的 Radon 变换。
[~,J] = find(R>=max(max(R)));%J记录了倾斜角 find查找非零元素的索引和值
qingxiejiao=90-J;


6、二值化和第一次形态学处理

bw=im2bw(bw,graythresh(bw));   %graythresh函数找到二值化阈值
erzhihua = bw;
handles.erzhihua = erzhihua;     %第五张图片,二值化后的图片
guidata(hObject,handles);
%graythresh使用 Otsu 方法 [1] 根据灰度图像 I 计算全局阈值 T。% Otsu 方法选择一个阈值,使阈值化的黑白像素的类内方差最小化。% 全局阈值 T 可与 imbinarize 结合使用以将灰度图像转换为二值图像。
bw=bwmorph(bw,'open',5); %  执行形态学开操作(先腐蚀后膨胀)
xingtaixue = bw;
handles.xingtaixue = xingtaixue;   %第六张图片,第一次形态学处理后的图片
guidata(hObject,handles);


7、精确定位

现在图像的周围可能有多余的边框,可以用投影法去除上下左右的边框。
先进行水平投影,就是每一行在Y轴上的投影,会在水平边框部分和字符部分出现波峰,字符区域一定在两个波谷之间,由曲线的上下两个极大值分别从上而下和从下而上搜索波谷部分,由这两个波谷位置分割车牌。

主代码:%==========对图像进一步裁剪,保证边框贴近字体============bw=~bw;  %转化车牌信息的颜色
%==对图像进一步裁剪,保证边框贴近字体====
bw=touying(bw);
bw=~bw;     %车牌信息为白色
diercijiancai = bw;
handles.diercijiancai = diercijiancai;     %第七张图片,第二次剪裁后的图片
guidata(hObject,handles);
子程序:
function bw_fir = touying(imane_bw)   %反色图片,黑色为车牌信息,投影法修剪车牌照片。
X_yuzhi=1;
[y,x]=size(imane_bw);
Y_touying=(sum((~imane_bw)'))';%往左边投影统计黑点    再将车牌信息转化为白色
X_touying=sum((~imane_bw));%往下面投影
%找黑体边缘
Y_up=fix(y/2);       %向0取整
Y_yuzhi=mean(Y_touying((fix(y/2)-10):(fix(y/2)+10),1))/1.6;  %mean求平均值,Y方向的阈值。
while ((Y_touying(Y_up,1)>=Y_yuzhi)&&(Y_up>1))%找到图片上边界  Y_up=Y_up-1;
end
Y_down=fix(y/2);
while ((Y_touying(Y_down,1)>=Y_yuzhi)&&(Y_down<y))%找到图片下边界 Y_down=Y_down+1;
end
%去除左边边框干扰X_right=1;if (X_touying(1,fix(x/14)))<=X_yuzhiX_right=fix(x/14);
end
%找黑体边缘
bw_fir=imane_bw(Y_up:Y_down,X_right:x);


8、第二次形态学处理

Bwareaopen函数:BW2=bareaopen(BW,P),从二值图像BW中删除小于P个像素的所有联通分量,并生成另一个二值图像BW2.

bw = bwareaopen(bw, yuzhi);     %移除小对象
dierciyichu = bw;
handles.dierciyichu = dierciyichu;     %第八张图片,第二次移除小对象后的图片
guidata(hObject,handles);


9、字符分割

字符分割即为将精确定位后得到的车牌分割为七个字符,每个字符的边界都不能有空白。若字符分割做得很好,那么字符识别的正确率将大大提高。同样地,字符分割的方法与车牌的特征紧密联系,不同的车牌特征衍生不同的分割方法。一般情况下,字符分割有以下几种方法:
(1)颜色法:颜色法由车牌的颜色特征产生的,比如蓝底白字的车牌,白色为字符且字符与字符之间不连续,白色和蓝色的不连续,这种方法对汉字分割有很好的效果。文献[12]强化车牌的颜色,提出模糊神经网络算法,利用这种算法,避免了使用单一阈值时产生的分割错误,增加了分割的正确率。
(2)连通区域法:连通区域法即先去除干扰,然后将不连通的字符做连通处理,最后查找连通区域,这些联通区域即为字符,从而达到分割字符的目的。这种方法对那些字符都是独立的情况有很好的效果,但对不独立的情况分割效果较差。
(3)车牌投影法:车牌投影法也有很多种,有很多文献对传统的投影法进行了改进,不仅使用车牌的投影特点,而且考虑了车牌字符的分布特点,设计出更好的算法,达到精确分割的目的。这种方法对有干扰的车牌也有很好的分割效果,而且精度很高。
(4)模板匹配法:根据车牌字符的排列特点,即字符与个空格等间距排列。模板匹配法使用两个模板,两个模板的宽度不同,一个为字符宽度,一个为空行的宽度。在分割时,移动两个模板,统计两个模板内的像素。将字符模板内的像素数与空格模板内的像素数相比,当为最大值时,则为字符分割点。该方法适合车牌照片有损失、车牌信息有扭曲的情况。
这里使用的分割方法为投影法。投影法的主要依据是车牌信息的水平排列特点,若将车牌信息垂直方向投影,那么可以发现投影的结果为“峰”“谷”“峰”形式,其中“峰”为字符,“谷”为分界点,所以本文字符分割使用投影法分割。
投影法的关键是分割阈值的选择,因为车牌图片的大小不一,所以阈值的选择和车牌的面积有关,根据不同的车牌面积选择相应的阈值,再将投影得到的值与阈值比较,进而得到字符位置,完成字符分割。

主程序:bw=~bw;%黑字白底[y,~]=size(bw);%============字符分割==============
fenge=zifufenge(bw);%==========剪裁7个字符============%给七张图片定位 ,将读取的字符信息分别赋值给7个数组han_zi=bw(1:y,fenge(1):fenge(2));zi_mu=bw(1:y,fenge(3):fenge(4));xuhao_1=bw(1:y,fenge(5):fenge(6));xuhao_2=bw(1:y,fenge(7):fenge(8));xuhao_3=bw(1:y,fenge(9):fenge(10));xuhao_4=bw(1:y,fenge(11):fenge(12));xuhao_5=bw(1:y,fenge(13):fenge(14));%======显示图像分割结果=======axes(handles.axes2);
imshow(han_zi);
axes(handles.axes15);
imshow(zi_mu);
axes(handles.axes16);
imshow(xuhao_1);
axes(handles.axes17);
imshow(xuhao_2);
axes(handles.axes18);
imshow(xuhao_3);
axes(handles.axes19);
imshow(xuhao_4);
axes(handles.axes20);
imshow(xuhao_5);
子函数zifufenge:
function fenge = zifufenge(imfenge)       %车牌信息为黑色
[y,x]=size(imfenge);
%将计算得到车牌区域分割后的图象,对白色进行水平垂直投影,计算水平垂直峰, 检测合理的字符高宽比.
%可用与区域分割相同的方法进行峰值的删除和合并
%对切割出的字符宽度进行统计分析,用以指导切割,对因错误切割过宽的字符进行分裂处理
%针对分割出来的字体的宽度与整个车牌的宽度对比,对误操作字符进行合并%===============用函数设定分割阈值========================
SS=x*y;         %根据不同的面积设定阈值
shedingyuzhi=4;
ganrao=SS/100;
%=========================================================
%定义数组histogram存储垂直方向的黑点数
histogram=sum(~imfenge);     %转换为白色,统计车牌像素数%figure(6);
plot(1:x,histogram);%plot(X,Y) 创建 Y 中数据对 X 中对应值的二维线图。
%=================文字分割=============================
k=1;
for h=1:x-1if  ((histogram(1,h)<=shedingyuzhi)&&(histogram(1,h+1)>shedingyuzhi))||((h==1)&&histogram(1,h)>shedingyuzhi)fenge(1,k)=h;      %储存分割左边界列数k=k+1;elseif ((histogram(1,h)>shedingyuzhi)&&(histogram(1,h+1)<=shedingyuzhi))||((h==x-1)&&histogram(1,h)>shedingyuzhi)fenge(1,k)=h+1;    %储存分割右边界列数k=k+1;end
end
k=k-1;%去掉多产生的一个K值
%==============================================
if (sum(histogram(1,fenge(1,1):fenge(1,2)))<ganrao)||((fenge(1,2)-fenge(1,1))<(fenge(1,4)-fenge(1,3))/2)       %如果车牌分割的部分出现了干扰for i=3:k                    %去除第一个分割点fenge(1,i-2)=fenge(1,i);end
end
[~,n]=size(fenge);         %完美分割时,n==14
if  n<14msgbox('分割出错','警告');sound(audioread('提取出错.wav'),48000);pause(1);
end
fenge=fenge(1,1:14);   %只返回十四个分割节点

10、归一化切割后的字符以及模板

因为分割后的字符大小不一,为了统一字符大小便于之后统计相同像素点,所以要将切割后的字符归一化。使用imrerize函数调整图片的大小为统一大小,本实验统一大小为110×70.

11、字符匹配

字符识别的方法有很多,主要可分为:特征匹配法,模板匹配法和神经网络法。本次实验使用的是模板匹配法,将模板字符和切割后的字符进行归一化后,逐个像素的比较二者的值,统计相同的像素点,像素点最多的模板就是该字符的识别结果。

主函数:%========识别结果==========jieguohanzi  = shibiehanzi(muban_hanzi,guiyihua_hanzi); %在shibiehanzi.m文件中创建函数,输入归一化后的切割汉字和模板汉字,输出识别结果      shibiejieguo(1) =jieguohanzi;  i=2;jieguozimu   = shibiezimu(muban_zimu,guiyihua_zimu);           shibiejieguo(i) =jieguozimu;   i=i+1;shibiejieguo(i) ='·';   i=i+1;jieguozm_sz_1= shibiezm_sz(muban_shuzizimu,guiyihua_xuhao1);   shibiejieguo(i) =jieguozm_sz_1;i=i+1;jieguozm_sz_2= shibiezm_sz(muban_shuzizimu,guiyihua_xuhao2);   shibiejieguo(i) =jieguozm_sz_2;i=i+1;jieguozm_sz_3= shibiezm_sz(muban_shuzizimu,guiyihua_xuhao3);   shibiejieguo(i) =jieguozm_sz_3;i=i+1;jieguozm_sz_4= shibiezm_sz(muban_shuzizimu,guiyihua_xuhao4);   shibiejieguo(i) =jieguozm_sz_4;i=i+1;
jieguozm_sz_5= shibiezm_sz(muban_shuzizimu,guiyihua_xuhao5);   shibiejieguo(i) =jieguozm_sz_5;
handles.shibiejieguo=shibiejieguo;
guidata(hObject,handles);set(handles.chepai,'string',shibiejieguo);  %=====================导出文本==================
fid=fopen('Data.dat','a');
fprintf(fid,'%s\r\n',shibiejieguo,datestr(now));
fclose(fid);子函数shibiehanzi
function shibiehanzi=shibiehanzi(muban_hanzi,fenge_hanzi)           %车牌信息为黑色
[y,x,~]=size(fenge_hanzi);
for k=1:27sum=0;for i=1:yfor j=1:xif  muban_hanzi(i,j,k)==fenge_hanzi(i,j)%统计黑白匹配程度sum=sum+1;endendendtongji(k)=sum;  %储存相同点的个数
end
num = find(tongji>=max(tongji));  %find函数返回的是非0的序数,返回由结果的线性索引组成的列向量
%在数字中,从0开始所以要减一。这里不用
switch num(1)case 1shibiehanzi = '鄂';case 2shibiehanzi = '赣';case 3shibiehanzi = '甘';case 4     shibiehanzi = '桂';case 5shibiehanzi = '贵';case 6shibiehanzi = '黑';case 7shibiehanzi = '吉';case 8shibiehanzi = '晋';case 9shibiehanzi = '京';case 10shibiehanzi = '辽';case 11shibiehanzi = '鲁';case 12shibiehanzi = '蒙';case 13shibiehanzi = '闽';case 14shibiehanzi = '宁';case 15shibiehanzi = '青';case 16shibiehanzi = '琼';case 17shibiehanzi = '陕';case 18shibiehanzi = '苏';case 19shibiehanzi = '津';case 20shibiehanzi = '皖';case 21shibiehanzi = '湘';case 22shibiehanzi = '豫';case 23shibiehanzi = '粤';case 24shibiehanzi = '云';case 25shibiehanzi = '藏';case 26shibiehanzi = '浙';case 27shibiehanzi = '冀';otherwiseshibiehanzi = '错';
end子函数shibiezimu
function shibiezimu=shibiezimu(zimu,xiuzhengzimu)
[y,x,~]=size(xiuzhengzimu);
for k=1:24sum=0;for i=1:yfor j=1:xif  zimu(i,j,k)==xiuzhengzimu(i,j)  %统计匹配程度sum=sum+1;endendend
baifenbi(1,k)=sum/(x*y);
end
chepai= find(baifenbi>=max(baifenbi));
shibiezimu=chepai;   %在数字中,从0开始所以要减一。这里不用
if         shibiezimu==1shibiezimu='A';elseif shibiezimu==2shibiezimu='B';elseif shibiezimu==3shibiezimu='C';elseif shibiezimu==4shibiezimu='D';elseif shibiezimu==5shibiezimu='E';elseif shibiezimu==6shibiezimu='F';elseif shibiezimu==7shibiezimu='G';elseif shibiezimu==8shibiezimu='H';elseif shibiezimu==9shibiezimu='J';elseif shibiezimu==10shibiezimu='K';elseif shibiezimu==11shibiezimu='L';elseif shibiezimu==12shibiezimu='M';elseif shibiezimu==13shibiezimu='N';elseif shibiezimu==14shibiezimu='P';elseif shibiezimu==15shibiezimu='Q';elseif shibiezimu==16shibiezimu='R';elseif shibiezimu==17shibiezimu='S';elseif shibiezimu==18shibiezimu='T';elseif shibiezimu==19shibiezimu='U';elseif shibiezimu==20shibiezimu='V';elseif shibiezimu==21shibiezimu='W';elseif shibiezimu==22shibiezimu='X';elseif shibiezimu==23shibiezimu='Y';elseif shibiezimu==24shibiezimu='Z';
end子函数shibiezm_sz
function shibiezm_sz=shibiezm_sz(shuzizimu,xiuzhengzm_sz)
[y,x,~]=size(xiuzhengzm_sz);for k=1:34sum=0;for i=1:yfor j=1:xif  shuzizimu(i,j,k)==xiuzhengzm_sz(i,j) %统计匹配程度sum=sum+1;endendendbaifenbi(1,k)=double(sum/(x*y));
end
chepai= find(baifenbi>=max(baifenbi));
%===================数字直接返回=========================if (chepai(1)>=1)&&(chepai(1)<=10)zm_sz=chepai(1)-1;zm_sz=num2str(zm_sz);%s = num2str(A) 将数值数组转换为表示数字的字符数组。% 输出格式取决于原始值的量级。num2str 对使用数值为绘图添加标签和标题非常有用。
else
%==================字母对应序号转字母====================
%=========11-15 ABCDE 16-20FGHIJ 21-25 KLMNP 26-30 QRSTU 31-35 VWXYZif     chepai(1)==11zm_sz='A';elseif chepai(1)==12zm_sz='B';elseif chepai(1)==13zm_sz='C';elseif chepai(1)==14zm_sz='D';elseif chepai(1)==15zm_sz='E';elseif chepai(1)==16zm_sz='F';elseif chepai(1)==17zm_sz='G';elseif chepai(1)==18zm_sz='H';elseif chepai(1)==19zm_sz='J';elseif chepai(1)==20zm_sz='K';elseif chepai(1)==21zm_sz='L';elseif chepai(1)==22zm_sz='M';elseif chepai(1)==23zm_sz='N';elseif chepai(1)==24zm_sz='P';elseif chepai(1)==25zm_sz='Q';elseif chepai(1)==26zm_sz='R';elseif chepai(1)==27zm_sz='S';elseif chepai(1)==28zm_sz='T';elseif chepai(1)==29zm_sz='U';elseif chepai(1)==30zm_sz='V';elseif chepai(1)==31zm_sz='W';elseif chepai(1)==32zm_sz='X';elseif chepai(1)==33zm_sz='Y';elseif chepai(1)==34zm_sz='Z';        end
end
shibiezm_sz=zm_sz;

12、语音播报

Audioread读取音频文件,sound将信号数据矩阵转换为声音。

主程序:
%点击语音播报执行的函数
function sound_Callback(hObject, eventdata, handles)
duchushengyin(handles.shibiejieguo);
子函数:
function shengyin=duchushengyin(shibiejieguo)
sound(audioread('检测结果.wav'),48000); %sound(y,Fs) 以采样率 Fs 向扬声器发送音频信号 y
pause(3);
for i=1:8if     shibiejieguo(1,i)=='桂'sound(audioread('桂.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='贵'sound(audioread('贵州.wav'),48000);pause(2);elseif shibiejieguo(1,i)=='京'sound(audioread('京.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='粤'sound(audioread('粤.wav'),48000);pause(2);elseif shibiejieguo(1,i)=='苏'sound(audioread('苏.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='吉'sound(audioread('吉.wav'),48000);pause(2);elseif shibiejieguo(1,i)=='鄂'sound(audioread('鄂.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='赣'sound(audioread('赣.wav'),48000);pause(2);elseif shibiejieguo(1,i)=='甘'sound(audioread('甘.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='黑'sound(audioread('黑.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='晋'sound(audioread('晋.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='辽'sound(audioread('辽.wav'),48000);pause(2);elseif shibiejieguo(1,i)=='鲁'sound(audioread('鲁.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='蒙'sound(audioread('蒙.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='闽'sound(audioread('闽.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='宁'sound(audioread('宁.wav'),48000);pause(2);elseif shibiejieguo(1,i)=='青'sound(audioread('青.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='琼'sound(audioread('琼.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='陕'sound(audioread('陕.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='津'sound(audioread('津.wav'),48000);pause(2);elseif shibiejieguo(1,i)=='皖'sound(audioread('皖.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='湘'sound(audioread('湘.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='豫'sound(audioread('豫.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='云'sound(audioread('云.wav'),48000);pause(2);elseif shibiejieguo(1,i)=='藏'sound(audioread('藏.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='浙'sound(audioread('浙.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='冀'sound(audioread('冀.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='A'sound(audioread('A.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='B'sound(audioread('B.wav'),48000); pause(1);elseif shibiejieguo(1,i)=='C'sound(audioread('C.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='D'sound(audioread('D.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='E'sound(audioread('E.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='F'sound(audioread('F.wav'),48000); pause(1);elseif shibiejieguo(1,i)=='G'sound(audioread('G.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='H'sound(audioread('H.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='J'sound(audioread('J.wav'),48000);  pause(1);elseif shibiejieguo(1,i)=='K'sound(audioread('K.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='L'sound(audioread('L.wav'),48000);  pause(1); elseif shibiejieguo(1,i)=='M'sound(audioread('M.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='N'sound(audioread('N.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='P'sound(audioread('P.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='Q'sound(audioread('Q.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='R'sound(audioread('R.wav'),48000); pause(1);elseif shibiejieguo(1,i)=='S'sound(audioread('S.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='T'sound(audioread('T.wav'),48000);   pause(1); elseif shibiejieguo(1,i)=='U'sound(audioread('U.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='V'sound(audioread('V.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='W'sound(audioread('W.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='X'sound(audioread('X.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='Y'sound(audioread('Y.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='Z'sound(audioread('Z.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='0'sound(audioread('0.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='1'sound(audioread('1.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='2'sound(audioread('2.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='3'sound(audioread('3.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='4'sound(audioread('4.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='5'sound(audioread('5.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='6'sound(audioread('6.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='7'sound(audioread('7.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='8'sound(audioread('8.wav'),48000);pause(1);elseif shibiejieguo(1,i)=='9'sound(audioread('9.wav'),48000);pause(1);end
end
sound(audioread('车牌检测.wav'),48000);

13、退出系统和关于按钮

点击按钮调用对应的回调函数,%questdlg创建问题对话框,answer = questdlg(quest) 创建一个模态对话框,其中提出问题并返回用户的回答 - ‘Yes’、‘No’、‘Cancel’ 或 ‘’。默认情况下,该对话框有三个标准按钮,其标签分别为是、否和取消。如果用户点击其中一个按钮,则 answer 值与按下的按钮的标签相同。如果用户点击对话框标题栏上的关闭按钮 (X) 或按下 Esc 键,则 answer 值为空字符向量 (’ ')。如果用户按下 Return 键,则 answer 值与默认所选按钮的标签相同。
Msgbox创建消息对话框,显示本次实践主题。增加交互体验。

%questdlg创建问题对话框
%answer = questdlg(quest) 创建一个模态对话框,其中提出问题并返回用户的回答 - 'Yes'、'No'、'Cancel' 或 ''。
%默认情况下,该对话框有三个标准按钮,其标签分别为是、否和取消。
%如果用户点击其中一个按钮,则 answer 值与按下的按钮的标签相同。
%如果用户点击对话框标题栏上的关闭按钮 (X) 或按下 Esc 键,则 answer 值为空字符向量 (' ')。
%如果用户按下 Return 键,则 answer 值与默认所选按钮的标签相同。
function exit_Callback(hObject, eventdata, handles)
button=questdlg('确定退出系统吗?','确认','No');  %当按回车键时,返回default值,default 必须是yes,no或cancel 之一。
if strcmp(button,'Yes')%tf = strcmp(s1,s2) 比较 s1 和 s2,如果二者相同,则返回 1 (true),否则返回 0 (false)。close all;
endfunction about_Callback(hObject, eventdata, handles)
str={'车牌识别系统'};
% 改变msgbox属性
% 寻找句柄,改变属性
hs = msgbox(str,'关于');
%findobj查找具有特定属性的图形对象
ht = findobj(hs, 'Type', 'text');%返回所有文本类型的对象
set(ht, 'FontWeight', 'bold','FontSize',12);%设置图形对象属性,将字符粗细设置为加粗,将字体大小设置为12


三、总的操作图

![原图







车牌识别-基于模板匹配相关推荐

  1. OpenCV(项目)车牌识别3 -- 模板匹配

    目录 一.基础理论 1.思想 2.大致过程 二.详细过程 1.首先需要模板库 2.得到模板 3.原图限定大小 4.模板匹配 5.匹配所有子文件夹,保存最佳得分(最匹配项) 三.大致过程(细分类,节省时 ...

  2. 【车牌识别】模板匹配新能源、轿车、货车车牌识别【含GUI Matlab源码 2169期】

    ⛄一.模板匹配车牌识别简介 1 系统整体设计 车牌识别系统包括4个步骤:车牌定位 (包括识别图像中的车牌位置并将其分割) .图像处理.字符分割与字符识别, 如图1所示.车牌定位的主要功能是从图像中可能 ...

  3. 【车牌识别】模板匹配车牌库识别【含GUI Matlab源码 416期】

    ⛄一.车牌识别简介 车牌识别技术起源于20世纪80年代初期,图像模式识别和计算机视觉在其中起到至关重要的作用.随着计算机技术的迅速普及和进步,80年代中后期,车牌识别系统逐步投入市场并使用,但识别精度 ...

  4. 【车牌识别】模板匹配新能源车牌识别【含Matlab源码 865期】

    ⛄一.简介 1 在进行图像处理任务之前,首先要明确处理对象和处理流程 处理对象: 新能源车牌和蓝色车牌 处理流程: 2 由于要对蓝色和新能源车牌进行识别,而且新能源车牌是渐变色,所以直接通过设定阈值的 ...

  5. 基于模板匹配的车牌识别算法,输出数字和英文字母

    目录 一.理论基础 二.核心程序 三.仿真结论 一.理论基础 车牌识别是计算机视觉领域中的一个重要问题,其目的是从图像中自动识别出车辆的车牌信息.基于模板匹配的车牌识别算法是一种常见的方法,其基本思想 ...

  6. python信用卡客户_Python开发之基于模板匹配的信用卡数字识别功能

    环境介绍 python 3.6 + OpenCV 3.4.1.15 原理介绍 首先,提取出模板中每一个数字的轮廓,再对信用卡图像进行处理,提取其中的数字部分,将该部分数字与模板进行匹配,即可得到结果. ...

  7. 基于模板匹配的数字识别

    基于模板匹配的数字识别,将标准的8*16像素的数字0123456789读取,二值化,对每个数字进行等分区域分割,统计每个区域内的黑色像素点的个数,即为特征初值.采用欧式距离的模板匹配法. z//基于模 ...

  8. python opencv数字识别_基于模板匹配的手写数字识别(python+opencv)

    智能计算课第一周的实验是做基于模板匹配的手写数字识别,光听见就很感兴趣,于是决定认真做做这个实验,本实验基于python3+opencv的python版本,所用到的知识都比较简单,基本上边学边做,技术 ...

  9. 基于模板匹配的知识图谱问答系统

    基于模板匹配的知识图谱问答系统 一,什么是基于知识图谱的问答(KBQA)? KBQA–knowledge base question answering,通过对问题进行语义理解及解析,通过知识库进行查 ...

  10. 基于模板匹配和遗传算法的人眼定位

    基于模板匹配和遗传算法的人眼定位 余甜甜,唐普英(电子科技大学光电信息学院,四川成都6l0054) 摘要:文中提出了一种利用模板匹配与遗传算法相结合的人眼定位算法.根据人脸几何特征将人脸分为几个特征区 ...

最新文章

  1. 安卓adb常用简单指令
  2. 关于android.view.WindowLeaked(窗体泄露)的解决方案
  3. 生活总是在推着你一步一步往前走
  4. HTML添加首页,添加首页分类推荐.html
  5. 简单的MSSQL恢复删除数据的方法
  6. BAT批量重命名文件擴展名
  7. 苛评VCL: 接口与TObject
  8. SpringBoot_日志-其他日志框架统一转换为slf4j
  9. JAVA标准包不存在_JAVA中引入自建包时提示包不存在
  10. 外观(门面)模式-结构型
  11. 【Linux】目录中 / 和 ~ 的区别
  12. 【UnityEditor】根据枚举的不同显示各自对应的内容
  13. MATLAB数学建模方法与实践(第3版)程序及数据
  14. java jsp实验设计心得_jsp课程设计心得_课程设计总结心得
  15. Android图片转化黑白图片,图像二值化,生成图像二值化后的黑白图像和图像矩阵(无压缩0,1矩阵),可灵活设置二值化值域
  16. Sony IPELA E系列网络摄像头远程命令执行漏洞警告
  17. 疫情期间使用AARRR规划社区电商功能
  18. 怎么退出自适应巡航_定速巡航与自适应巡航到底哪个更强?如何正确使用这些功能?...
  19. 架构分类:软件架构、系统架构。
  20. 【服务器管理】搭建FTP

热门文章

  1. matlab 函数变量保存在工作区,Matlab中保存函数内部中间变量到工作空间的两种方法...
  2. I/O多路复用select服务器
  3. 福禄克FLUKE BT521 BT520 BT510 BT508护航储能电池安全
  4. 全国各地货运量(全国与各省级指标,2005-2019数据分析对比)
  5. [分析力学]解题思路 - 最小作用量原理
  6. mysql实验感想_数据库原理实验心得
  7. TomCat8080/8081端口占用问题!如何解决
  8. 抖音极速版自动运行脚本
  9. html 显示闹钟,闹钟设置.html
  10. Word文档中标题前面的黑点如何去掉