1、车牌识别Matlab算法详解 生成界面时注意事项1、生成文件主菜单和打开、关闭子菜单不一样的地方,在于文件主菜单不对应实际执行代码,所以在Callback回调函数,这一项,可将其删除为空。 2、在关闭Menu Editor之前,先保存正在编辑的.fig文件,让其自动生成或者更新对应的.m文件3、在.fig文件编辑器的空白处,双击,弹出Property Inspector,在其中更改Resize 属性为on,表示窗体大小可以更改;更改Units 的单位为 pixels ;Tag的名称代表窗体的名称,默认为figure1,另取一个名称为mainFrm.注意在关闭Property Inspector
2、之前总是先保存.fig文件双击之 4、假如程序运行出了问题,可先在Command window中查看错误说明,根据提示修改。或者打开.m源代码文件,重新编译运行。注意在运行之前使用命令窗口中的clc命令清空内存。5、现在一行一行来解释源代码。第一行:function varargout = LicenseRecognition(varargin)分别表示主函数的输出、函数名称、函数输入在% Begin initialization code - DO NOT EDIT% End initialization code - DO NOT EDIT这两行注释符之前的代码是编辑菜单时自动生成的,不需
3、要修改function LicenseRecognition_OpeningFcn(hObject, eventdata, handles, varargin)%系统自动生成handles.output = hObject; %系统自动生成%以下代码为手工添加,表示使用handles结构体来保存图形界面中各种对象的句柄,或者中间结果,这些句柄或者中间结果在创建图形对象或运算中产生,需要在以后的回调函数中多次用到,所以这里的作用类似于全局变量的作用,用来进行数据的传递。handles.imgIn = ; handles.imgOut = ;handles.flag = 0;%判断标志handle
4、s.pos = ;%图形对象所在位置handles.lef = 1;handles.top = 1;handles.wid = 0;handles.hig = 0;% Update handles structure 自动生成,用来将上面定义的数据guidata(hObject, handles);%自动生成,定义输出% - Outputs from this function are returned to the command line.function varargout = LicenseRecognition_OutputFcn(hObject, eventdata, handle
5、s) varargout1 = handles.output;第一步:打开读取文件% -function Menu_File_Open_Callback(hObject, eventdata, handles)%该行为自动生成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(st
6、rPath); %读取文件数据 hig,wid,page = size(img); %获得图像大小 if page = 3 %假设图像是RGB彩色 imgIn = rgb2gray(img); %转换为灰度图象 else imgIn = img; end handles.imgIn = imgIn; %将结果赋给全局变量,以便交给下一个函数处理 handles.flag = 1 %标志为1表示数据已经读取% pos = get(handles.mainFrm,Position); figure(handles.mainFrm); %创建图形界面,用来显示图像 set(handles.mainF
7、rm,Position,400,300,wid,hig); %设置该图形界面的显示位置 image(imgIn); %显示图像,其和imshow功能类似,但带有默认的调色板 colormap(gray(256); %将其默认调色板更改为256级灰度 handles.pos = 400,300,wid,hig; %将图形界面的位置保存到hdl结构体中 guidata(hObject,handles); %保存图形界面数据 set(handles.Menu_EdgeDetect,Enable,On); %设置下一个菜单为可点击的亮色end% 完成菜单退出功能-function Menu_File_
8、Exit_Callback(hObject, eventdata, handles)if handles.flag = 1 str = Are you sure about exiting the program?,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,
9、handles)if isempty(handles.imgIn) %检查图像数据是否非空 imgIn = double(handles.imgIn); %在处理之前将图像数据类型转换为double型% 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); %构
10、建soble算子的模板horz = conv2(imgIn,filt,same);%进行卷积运算 % Cs = conv2(A,B,same) Cs is the same size as A: 3-by-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
11、(handles.mainFrm); set(handles.mainFrm,Position,handles.pos); image(imgOut); colormap(gray(256); set(handles.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的矩阵,存储水
13、平方向相邻像素的差值 diff_horz = abs(imgIn(:,1:wid-1) - imgIn(:,2:wid);%类似第1列像素减第2列像素,第2列减第3列,依次减下去 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,
14、:);% cum_vert = sum(diff_vert);% figure;% bar(1:wid,cum_vert,b);% title(vertical projection); %通过观察投影图,给出车牌的大概位置是,左上角坐标为(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 = ui
15、nt8(imgIn(top:top+hig-1,lef:lef+wid-1);%按刚才给的位置大小提取出车牌,转换为无符号整型,保存到imgOut中 handles.imgOut = 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
16、(handles.Menu_RoughLocate,Enable,Off); set(handles.Menu_CharacterCutout,Enable,Off); set(handles.Menu_LicenseRecognition,Enable,Off);end第四步:车牌微定位 如图所示,在粗定位结果的基础上,还需要把红色边框外的图像去掉,以进一步确定字符范围,缩减车牌的左右上下边界,以便后续字符处理。-function Menu_FineLocate_Callback(hObject, eventdata, handles)if isempty(handles.imgOut) i
17、mgIn = double(handles.imgOut);%传入粗定位的结果图像 hig,wid = size(imgIn);% 取图像大小 lef_tem = wid * 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
18、 lef_tem(i) = j+1; break; end end%从右向左扫描,遇到相邻像素的灰度值差值大于60时,停止扫描,记下列号,说明此列是车牌右边界 for j = 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在初始化定义的时候分别
19、为ones全为1的矩阵和全为zeros 0的矩阵的原因 top_tem = hig * ones(wid,1); bot_tem = zeros(wid,1); for j = 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 =
20、min(top_tem); %按同样的方法找到上下边界,注意图像左上角为原点 bot = max(bot_tem); handles.lef = handles.lef + lef - 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.fla
21、g = 1; guidata(hObject,handles); figure(handles.mainFrm); set(handles.mainFrm,Position,handles.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_LicenseRe
22、cognition,Enable,Off);end第五步:字符分割% -function Menu_CharacterCutout_Callback(hObject, eventdata, 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:l
23、ef+wid-1);% maxvalue = max(imgIn(:);% minvalue = min(imgIn(:);% imgOut = (imgIn = (maxvalue + minvalue+30)/2); imgOut = JudgeAnalysis(imgIn); %对图像进行二值化,然后反转label,num = bwlabel(imgOut); %对二值图像进行连通成分的标记 %对于以上两个中间变量的结果,大家可以在Matlab的workspace中查看其结果变化,理解 k = 0; for i = 1:num %以下代码为找到像素总数小于10的连通成分,剔除,这里6个字
24、符,但有7个连通成分,剔除其中较少像素的连通成分 tem = (label = i); %把所有label为i的像素统计出来 if sum(tem(:) = 1) k = k+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
25、条边界 k = length(coordx); set(handles.mainFrm,Position,handles.pos); image(uint8(255*(imgOut); %将其反转回来在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 t
26、em_wid(j) = coordx(2*j) - coordx(2*j-1) + 1; %每个字符由一对边界线分割而成,由右边边界线减去左边边界线的位置,得到的是此字符的宽度 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 %从下往上扫描,
27、找出第j个字符的下边界 if proj_horz(k) = 0 tem2 = k; coordy(j,2) = tem2; break; end end tem_hig(j) = 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) = ones(maxhig,maxwid);%初始化为大小统一 Norm_Char(1:hig,1:wid,k)
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2