直接进入正题!
本文程序的功能可实现的效果如下图所示👇
这个程序可以大致分为GUI界面的设计优化以及车牌识别功能的代码实现,下面给大家一一介绍
一、GUI界面的设计优化
首先给大家介绍什么是GUI,GUI 为图形用户界面(Graphical User Interface,简称 GUI,又称图形用户接口)是指采用图形方式显示的计算机操作用户界面,是MATLAB用户可视化交互式的工具,运用GUI生成的操作界面用户可以不用浏览繁冗的代码而进行操作。像效果图所示,我们可以直接通过简单的按键就可以实现程序的功能,美观并且简洁。下面分步介绍:第一步:在命令行输入“guide”指令
输入后会出现一个这样的界面,点击“Blank GUI”后就可以开始设计自己想要的gui界面。第二步:添加按钮及坐标轴
在这一步中可以按照个人需求在左侧添加元素,该系统只需一定数量的坐标轴和按钮,坐标轴是为了在代码中可以把图片插入进去。通过白色边框右下角的黑点我们可以设置GUI界面的大小。
(添加所需元素后)
在没有运行的时候,axes是看不见坐标轴的,运行的时候会变成下图这个样子👇。
我们可以看到每个axes都有坐标轴,为了美观,我们可以把坐标轴给隐藏掉,右键axes1控件,View Callbacks——>CreateFcn,然后在该控件的CreateFcn函数下面输入下面四行代码:
set(gca,'XColor',get(gca,'Color'));% 这两行代码功能:将坐标轴和坐标刻度转为白色set(gca,'YColor',get(gca,'Color'));set(gca,'XTickLabel',[]); % 这两行代码功能:去除坐标刻度set(gca,'YTickLabel',[]);
(逐一处理后的GUI界面)
第三步:按钮名称设置及关闭按钮名称的设置在guide指令中双击按钮,就会弹出来一个界面👇。
在String中直接修改想要的名称即可。最后,关闭GUI界面则在对应按钮的代码行,输入“close”即可。在第二步设计结束后,MATLAB会自动生成结构代码,此时这需要将功能实现的代码整合到结构中去就可以了。
我们先把GUI界面按钮1设置为载入图像。
function pushbutton1_Callback(hObject, eventdata, handles)%结构代码[filename pathname]=uigetfile({'*.jpg';'*.bmp'}, 'File Selector');f=imread([pathname '\' filename]);handles.f=f;guidata(hObject, handles);axes(handles.axes1);%将图像载入到坐标轴1imshow(f);title('原始图像');
二、车牌识别功能实现
再在GUI界面按钮2设置为处理图像,在此按钮中实现了车牌识别功能,下面给大家介绍,该功能的实现分为4个步骤,一是定位蓝色车牌区域;二是旋转图像;三是剪切蓝色车牌图像;四是分割字符并输出。
第一步:定位蓝色车牌区域
function pushbutton2_Callback(hObject, eventdata, handles)%结构代码%% 定位蓝色区域f=handles.f;gray=3*f(:,:,3)-f(:,:,1)-f(:,:,2);axes(handles.axes2);%将图像载入到坐标轴2imshow(gray),title('保留蓝色色域');%形态学处理level=graythresh(gray); %利用Ostu法获取图像的阈值bw=im2bw(gray,level); %根据Ostu法分割车牌图像bw1=bwareaopen(bw,500);%删除面积小于500的区域se=strel('cube',15);%创建一个边长为15的正方形bw2=imclose(bw1,se);%闭运算连使整个车牌区域连接在一起
定位的功能只适用于车牌是蓝色的非蓝色汽车。
第二步:旋转图像
毕竟随手一拍,无法确保角度,为了最终识别的效果,添加旋转的功能。程序应用的是Radon变换,当然也可以使用Hough变换。
%% 车牌矫正(利用radon变换)theta=0:179;r=radon(bw2,theta);[m,n]=size(r);c=0;for i=1:m for j=1:n if r(1,1) r(1,1)=r(i,j); c=j; end endendrot=90-c;fx=imrotate(f,rot,'crop');%旋转axes(handles.axes3);%将图像载入到坐标轴3imshow(fx);title('旋转后的图像');
第三步:剪切蓝色车牌图像在实现过程中我们可以使用regionprops函数(regionprops:用途是get the properties of region,即用来度量图像区域属性的函数。),真是非常的友好,功能超级强大,在这就不详细介绍。
%% 剪切定位车牌区域s1=regionprops(bw2,'BoundingBox','Centroid') ; %获取车牌矩形区域,即二值图中值为1的矩形框xy=s1(1).BoundingBox;%获取车牌矩形区域左上角坐标及矩形的长和宽, xy(1)为矩形框左上角的y坐标,xy(2)为矩形框左上角的x坐标fcrop=f(round(xy(2)):round(xy(2)+xy(4)),round(xy(1)):round(xy(1)+xy(3)),:) ;axes(handles.axes4);%将图像载入到坐标轴4imshow (fcrop),title('定位剪切后的蓝色车牌图像');
第四步:分割字符并输出到屏幕
想用利用regionprops函数进行字符分割,就必须保证每一个车牌字符通过形态学处理后都分别为单独的连通区域,由于本文处理的车牌干扰因素比较多,形态学处理也略微复杂了一些,对于其他干扰因素较少的图像来说,简单处理后就可以使用此函数。在GUI界面中需要将字符逐一分割然后输出到坐标轴,如果不需要GUI界面就可以直接通过for循环挨个输出。
%% 分割字符fgray=rgb2gray(fcrop);level2=graythresh(fgray);bw3=im2bw(fgray,level2);% imshow(bw3);title('定位剪切后的二值图像');se2=strel('line',2,90);se3=strel('cube',4);se4=strel('disk',1);bw3o=bwareaopen(bw3,30);%imshow(bw3o);title('删除小于20面积后的图像');bw3oe=imerode(bw3o,se4);%imshow(bw3oe);title('二值图像腐蚀后')bw3oc =imclose(bw3oe,se2);%imshow(bw3oc);title('二值图像闭运算后');bw4=imclearborder(bw3oc);%imshow(bw4);bw4d=imdilate(bw4,se3);bw4d=imdilate(bw4d,se3);%imshow(bw4d);title('膨胀后的图像');bw5=bwareaopen(bw4d,400);axes(handles.axes5);imshow(bw5);title('删除小于400后的图像'); s2=regionprops(bw5,'BoundingBox','Centroid');xy=s2(1).BoundingBox;bw6=fcrop(floor(xy(2)):floor(xy(2)+xy(4)),floor(xy(1)):floor(xy(1)+xy(3)),:);axes(handles.axes6);%将图像载入到坐标轴6imshow(bw6);title(num2str(1));%此处省略字符2-字符6,代码相同xy=s2(7).BoundingBox;bw6=fcrop(floor(xy(2)):floor(xy(2)+xy(4)),floor(xy(1)):floor(xy(1)+xy(3)),:);axes(handles.axes12);%将图像载入到坐标轴12imshow(bw6);title(num2str(7));
最后将按钮3设置为退出系统。
function pushbutton3_Callback(hObject, eventdata, handles)close;
在前面提到隐藏坐标轴的方法,在代码中的实现如下。
%此处为一个坐标轴去除的代码,其余方法相同故省略。function axes1_CreateFcn(hObject, eventdata, handles)set(gca,'XColor',get(gca,'Color'));set(gca,'YColor',get(gca,'Color'));set(gca,'XTickLabel',[]); set(gca,'YTickLabel',[]);
整个系统从设计到实现到这里也就结束了,希望大家的学习生活事顺利!