《精华资料车牌识别Matlab算法详解.doc》由会员分享,可在线阅读,更多相关《精华资料车牌识别Matlab算法详解.doc(14页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、 生成界面时考前须知1、生成文件主菜单和翻开、关闭子菜单不一样的地方,在于文件主菜单不对应实际执行代码,所以在Callback回调函数,这一项,可将其删除为空。 3、在.fig文件编辑器的空白处,双击,弹出Property Inspector,在其中更改Resize 属性为on,表示窗体大小可以更改;更改Units 的单位为 pixels ;Tag的名称代表窗体的名称,默认为figure1,另取一个名称为mainFrm.双击之4、假设程序运行出了问题,可先在Command window中查看错误说明,根据提示修改。或者翻开.m源代码文件,重新编译运行。注意在运行之前使用命令窗口中的clc命令清
2、空内存。5、现在一行一行来解释源代码。第一行:function varargout = LicenseRecognition(varargin)分别表示主函数的输出、函数名称、函数输入在% Begin initialization code - DO NOT EDIT% End initialization code - DO NOT EDIT这两行注释符之前的代码是编辑菜单时自动生成的,不需要修改function LicenseRecognition_OpeningFcn(hObject, eventdata, handles, varargin)%系统自动生成handles.output
3、= hObject; %系统自动生成%以下代码为手工添加,表示使用handles结构体来保存图形界面中各种对象的句柄,或者中间结果,这些句柄或者中间结果在创立图形对象或运算中产生,需要在以后的回调函数中屡次用到,所以这里的作用类似于全局变量的作用,用来进行数据的传递。handles.imgIn = ; handles.imgOut = ;handles.flag = 0;%判断标志handles.pos = ;%图形对象所在位置handles.lef = 1;handles.top = 1;handles.wid = 0;handles.hig = 0;% Update handles str
4、ucture 自动生成,用来将上面定义的数据guidata(hObject, handles);%自动生成,定义输出% - Outputs from this function are returned to the command line.function varargout = LicenseRecognition_OutputFcn(hObject, eventdata, handles) varargout1 = handles.output;第一步:翻开读取文件% -function Menu_File_Open_Callback(hObject, eventdata, handl
5、es)%该行为自动生成fname,pname = uigetfile(*.bmp;*.jpg;*.tif, All IMAGE Files (*.bmp, *.jpg, *.tif),Open an input image); %弹出翻开文件的对话框strPath = pname fname; %设置文件名和路径名if isempty(strPath) img,cmap = imread(strPath); %读取文件数据 hig,wid,page = size(img); %获得图像大小 if page = 3 %假设图像是RGB彩色 imgIn = rgb2gray(img); %转换为灰
6、度图象 else imgIn = img; end handles.imgIn = imgIn; %将结果赋给全局变量,以便交给下一个函数处理 handles.flag = 1 %标志为1表示数据已经读取% pos = get(handles.mainFrm,Position); figure(handles.mainFrm); %创立图形界面,用来显示图像 set(handles.mainFrm,Position,400,300,wid,hig); %设置该图形界面的显示位置 image(imgIn); %显示图像,其和imshow功能类似,但带有默认的调色板 colormap(gray(2
7、56); %将其默认调色板更改为256级灰度 handles.pos = 400,300,wid,hig; %将图形界面的位置保存到hdl结构体中 guidata(hObject,handles); %保存图形界面数据 set(handles.Menu_EdgeDetect,Enable,On); %设置下一个菜单为可点击的亮色end% 完成菜单退出功能-function Menu_File_Exit_Callback(hObject, eventdata, handles)if handles.flag = 1 str = Are you sure about exiting the pro
8、gram?,If so, the data will be lost!; ret = questdlg(str,Warning); switch ret case Yes delete(gcf); case No, Cancel return; endend% 第二步:边缘检测功能实现-function Menu_EdgeDetect_Callback(hObject, eventdata, handles)if isempty(handles.imgIn) %检查图像数据是否非空 imgIn = double(handles.imgIn); %在处理之前将图像数据类型转换为double型%
9、BW = uint8(255 * edge(handles.imgIn,roberts);% handles.imgOut = BW;% guidata(hObject,handles);% set(handles.mainFrm,Position,handles.pos);% image(BW);% colormap(gray(256); filt = fspecial(sobel); %构建soble算子的模板horz = conv2(imgIn,filt,same);%进行卷积运算 % Cs = conv2(A,B,same) Cs is the same size as A: 3-by
10、-3 vert = conv2(imgIn,filt,same); imgOut = uint8(max(horz,vert); % 取水平和垂直方向运算结果的最大值% imgOut = uint8(sqrt(horz.2 + vert.2); handles.imgOut = imgOut; handles.flag = 1; guidata(hObject,handles); figure(handles.mainFrm); set(handles.mainFrm,Position,handles.pos); image(imgOut); colormap(gray(256); set(h
11、andles.Menu_RoughLocate,Enable,On); set(handles.Menu_FineLocate,Enable,Off); set(handles.Menu_CharacterCutout,Enable,Off); set(handles.Menu_LicenseRecognition,Enable,Off);end第三步:车牌粗定位% 车牌粗定位:根据车牌区域在水平方向灰度值具有明显频繁的跳变,可求边缘提取后水平方向的差分,然后进行水平方向上的投影,也即沿水平方向进行相邻像素差分值的累加,绘制的投影图横轴为图像高度,原点为左上角,纵轴即为沿水平方向的差分值累加和
12、。差分累加车牌纵向定位图像高度纵向定位-function Menu_RoughLocate_Callback(hObject, eventdata, handles)if isempty(handles.imgOut) imgIn = double(handles.imgOut); hig,wid = size(imgIn); diff_horz = zeros(hig,wid);%构建一个与图像大小一样的全为0的矩阵,存储水平方向相邻像素的差值 diff_horz = abs(imgIn(:,1:wid-1) - imgIn(:,2:wid);%类似第1列像素减第2列像素,第2列减第3列,依
13、次减下去 cum_horz = sum(diff_horz);%对图像矩阵先转置,再投影 figure; %绘制投影图形,横轴为1到图像高,纵轴为水平方向差分值累计和 bar(1:hig,cum_horz,r); title(horizontal projection); % diff_vert = zeros(hig,wid);% diff_vert = abs(imgIn(1:hig-1,:) - imgIn(2:hig,:);% cum_vert = sum(diff_vert);% figure;% bar(1:wid,cum_vert,b);% title(vertical proj
14、ection); %通过观察投影图,给出车牌的大概位置是,左上角坐标为85,225,宽度为60,高度为20。 lef = 85; top = 225; wid = 60; hig = 20; handles.lef = lef; %将检测结果传递给hdl结构体,以传递到下一个微定位的函数 handles.top = top; handles.wid = wid; handles.hig = hig; imgOut = uint8(imgIn(top:top+hig-1,lef:lef+wid-1);%按刚刚给的位置大小提取出车牌,转换为无符号整型,保存到imgOut中 handles.imgO
15、ut = imgOut; handles.flag = 1; guidata(hObject,handles); figure(handles.mainFrm); set(handles.mainFrm,Position,handles.pos); image(imgOut); colormap(gray(256); axis off; set(handles.Menu_FineLocate,Enable,On); set(handles.Menu_RoughLocate,Enable,Off); set(handles.Menu_CharacterCutout,Enable,Off); se
16、t(handles.Menu_LicenseRecognition,Enable,Off);end第四步:车牌微定位 如下图,在粗定位结果的根底上,还需要把红色边框外的图像去掉,以进一步确定字符范围,缩减车牌的左右上下边界,以便后续字符处理。-function Menu_FineLocate_Callback(hObject, eventdata, handles)if isempty(handles.imgOut) imgIn = double(handles.imgOut);%传入粗定位的结果图像 hig,wid = size(imgIn);% 取图像大小 lef_tem = wid *
17、ones(hig,1); % 构建一个hig行,1列的值全为1的矩阵,与wid相乘,矩阵值全部为wid rig_tem = zeros(hig,1); %构建一个hig*1的0矩阵 for i = 1:hig for j = 1:wid-1 %从左到右扫描,遇到相邻像素的灰度值差值大于60时,停止扫描,记以下号,说明此列是车牌左边界 tem = imgIn(i,j+1) - imgIn(i,j); if tem = 60 lef_tem(i) = j+1; break; end end%从右向左扫描,遇到相邻像素的灰度值差值大于60时,停止扫描,记以下号,说明此列是车牌右边界 for j =
18、wid : -1 : 2 tem = imgIn(i,j-1) - imgIn(i,j); if tem = 60 rig_tem(i) = j-1; break; end end end4 lef = min(lef_tem);%每一行都可以扫描得到一个左边界,取其中最小的 rig = max(rig_tem); %每一行都可以扫描得到一个右边界,取其中最大的%这也是lef_tem、rig_tem在初始化定义的时候分别为ones全为1的矩阵和全为zeros 0的矩阵的原因 top_tem = hig * ones(wid,1); bot_tem = zeros(wid,1); for j =
19、 lef:rig for i = 1:hig-1 tem = imgIn(i+1,j) - imgIn(i,j); if tem = 60 top_tem(j) = i+1; break; end end for i = hig : -1 : 2 tem = imgIn(i-1,j) - imgIn(i,j); if tem = 60 bot_tem(j) = i-1; break; end end end top = min(top_tem); %按同样的方法找到上下边界,注意图像左上角为原点 bot = max(bot_tem); handles.lef = handles.lef + l
20、ef - 1; %在原始图像上定位微定位后车牌的位置 handles.top = handles.top + top - 1; handles.wid = rig - lef + 1; handles.hig = bot - top + 1; %将微定位后的图像数据取出来 imgOut = uint8(imgIn(top:bot,lef:rig); handles.imgOut = imgOut; handles.flag = 1; guidata(hObject,handles); figure(handles.mainFrm); set(handles.mainFrm,Position,h
21、andles.pos); image(imgOut); colormap(gray(256); axis off; set(handles.Menu_CharacterCutout,Enable,On); set(handles.Menu_RoughLocate,Enable,Off); set(handles.Menu_FineLocate,Enable,Off); set(handles.Menu_LicenseRecognition,Enable,Off);end第五步:字符分割% -function Menu_CharacterCutout_Callback(hObject, even
22、tdata, handles)if handles.wid = 0 lef = handles.lef;%注意:这里是微定位后车牌在原始图像上的位置 top = handles.top; wid = handles.wid; hig = handles.hig;%此处imgIn是在原始图像上取微定位后车牌位置区域的数据产生的 imgIn = double(handles.imgIn(top:top+hig-1,lef:lef+wid-1);% maxvalue = max(imgIn(:);% minvalue = min(imgIn(:);% imgOut = (imgIn = (maxva
23、lue + minvalue+30)/2); imgOut = JudgeAnalysis(imgIn); %对图像进行二值化,然后反转label,num = bwlabel(imgOut); %对二值图像进行连通成分的标记 %对于以上两个中间变量的结果,大家可以在Matlab的workspace中查看其结果变化,理解 k = 0; for i = 1:num %以下代码为找到像素总数小于10的连通成分,剔除,这里6个字符,但有7个连通成分,剔除其中较少像素的连通成分 tem = (label = i); %把所有label为i的像素统计出来 if sum(tem(:) = 1) k = k+
24、1; coordx(k) = j-1; elseif (proj_vert(j) = 0) & (tem2 = 1) k = k+1; coordx(k) = j+1; endend%如果倒数第二列不为0,倒数第1列为0,那么说明倒数第2列为边界 if (proj_vert(wid-1) = 0) & (proj_vert(wid) = 0) k = k+1; coordx(k) = wid-1; end %k代表总共有k条边界 k = length(coordx); set(handles.mainFrm,Position,handles.pos); image(uint8(255*(img
25、Out); %将其反转回来在0-255之间显示 colormap(gray(256); axis off; hold on; for j = 1:k x = coordx(j) * ones(1,hig);%将x的数目变成和y一样多,组成(x,y)坐标点对 y = 1:hig; plot(x,y,b); hold on; end hold off; %根据上面所找边界线,对字符进行实际的分割 for j = 1:num tem_wid(j) = coordx(2*j) - coordx(2*j-1) + 1; %每个字符由一对边界线分割而成,由右边边界线减去左边边界线的位置,得到的是此字符的宽
26、度 tem = imgOut(:,coordx(2*j-1):coordx(2*j);%取出每一字符的实际数据 proj_horz = sum(tem);%对该字符的行求累加值 for k = 1:hig %从上往下扫描,找出第j个字符的上边界 if proj_horz(k) = 0 tem1 = k; coordy(j,1) = tem1; break; end end for k = hig:-1:1 %从下往上扫描,找出第j个字符的下边界 if proj_horz(k) = 0 tem2 = k; coordy(j,2) = tem2; break; end end tem_hig(j)
27、 = tem2 - tem1 + 1; %找出每一字符的高度 end %以最大的宽和高来统一每个字符的大小 maxwid = max(tem_wid); %总共有6个字符,找出其中最宽的 maxhig = max(tem_hig); %总共有6个字符,找出其中最高的 for k = 1:num lef = coordx(2*k-1); rig = coordx(2*k); top = coordy(k,1); bot = coordy(k,2); wid = rig - lef + 1; hig = bot - top + 1;Norm_Char(1:maxhig,1:maxwid,k) =
28、ones(maxhig,maxwid);%初始化为大小统一 Norm_Char(1:hig,1:wid,k) = imgOut(top:bot,lef:rig);%取出每一字符数据 end handles.Norm_Char = Norm_Char; handles.flag = 1; guidata(hObject,handles);% for k = 1:num% figure;% image(uint8(255*Norm_Char(:,:,k);% colormap(gray(256);% axis off;% end set(handles.Menu_LicenseRecognitio
29、n,Enable,On); set(handles.Menu_RoughLocate,Enable,Off); set(handles.Menu_FineLocate,Enable,Off); set(handles.Menu_CharacterCutout,Enable,Off);end第六步:字符识别%读取事先定义好的模板,将分割后的字符与模板进行匹配,取相关系数最大的。% -function Menu_LicenseRecognition_Callback(hObject, eventdata, handles)if isempty(handles.Norm_Char) Norm_Cha
30、r = handles.Norm_Char; template(:,:,1) = double(imread(FY10_0.bmp); template(:,:,2) = double(imread(FY10_1.bmp); template(:,:,3) = double(imread(FY10_3.bmp); template(:,:,4) = double(imread(FY10_F.bmp); template(:,:,5) = double(imread(FY10_M.bmp); template(:,:,6) = double(imread(FY10_P.bmp); num = s
31、ize(Norm_Char,3); %返回第3维的个数 result = ; for k = 1:num str = recognition(Norm_Char(:,:,k),template); result = result str ; end msgbox(The recognition result is:,result,Recognition of the license); end%模板比对函数function cout = recognition(cin,template) d=zeros(6,1);for i = 1:6 d(i)=corr2(cin,template(:,:,i);%求相关系数ende = find(d = max(d);switch e case 1 cout = 0; case 2 cout = 1; case 3 cout = 3; case 4 cout = F; case 5 cout = M; case 6 cout = P;end