Matlab实现车牌识别结合详细案例

Matlab实现车牌识别结合详细案例

参考来源:https://blog.csdn.net/zhangquan2015/article/details/78994551##


前言


一、Matlab结果呈现

GUI界面

运行结果

二、实现代码

1.实现代码,解释可见代码注释处

matlab车牌实现代码:

%===========================GUI交互界面========================================
function varargout = runs(varargin)
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @runs_OpeningFcn, ...
                   'gui_OutputFcn',  @runs_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
%结束初始化
function runs_OpeningFcn(hObject,eventdata, handles, varargin)
handles.output = hObject;
guidata(hObject, handles);
function varargout = runs_OutputFcn(h0bject,eventdata,handles)  
varargout{1} = handles.output;

% =========================自定义2个方法===========================
%定义切割字符的方法
function e=qiege(d)
[m,n]=size(d);
top=1;
bottom=m;
left=1;
right=n;
while sum(d(top,:))==0 && top<=m
    top=top+1;
end
while sum(d(bottom,:))==0 && bottom>1
    bottom=bottom-1;
end
while sum(d(:,left))==0 && left<n
    left=left+1;
end
while sum(d(:,right))==0 && right>=1
    right=right-1;
end
dd=right-left;
hh=bottom-top;
e=imcrop(d,[left top dd hh]);


%定义获取字符的方法
function[word,result]=getword(d)
word=[];
flag=0;
y1=8;
y2=0.5;
while flag==0
    [m,n]=size(d);
    wide=0;
    while sum(d(:,wide+1))~=0 && wide<=n-2
        wide=wide+1;
    end
    temp=qiege(imcrop(d,[1 1 wide m]));%用于返回图像的一个裁剪区域
    [m1,n1]=size(temp);
    if wide<y1 && n1/m1>y2
        d(:,[1:wide])=0;
        if sum(sum(d))~=0
            d=qiege(d);%切割出最小范围
        else word=[];flag=1;
        end
    else
        word=qiege(imcrop(d,[1 1 wide m]));
        d(:,[1:wide])=0;
        if sum(sum(d))~=0;
            d=qiege(d);
            flag=1;
        else d=[];
        end
    end
end
result=d;

% ======================输入图像===============================
function pushbutton1_Callback(hObject, eventdata, handles)
[filename pathname]=uigetfile({'*.jpg';'*.bmp'}, 'File Selector');%点击按钮
I=imread([pathname '\' filename]);%读入图像
handles.I=I;
guidata(hObject, handles);
axes(handles.axes1);
imshow(I);title('原始图像');%原始图像窗口

% ======================开始识别(图像处理)======================
function pushbutton2_Callback(hObject, eventdata, handles)

%※﹏﹋﹏ 前期准备﹏﹋﹏﹋﹏ ※
rd=randint(1,1,[1 1000]);%产生一个随机数用来存save

%※﹏﹋﹏ 图像预处理﹋﹏﹋﹏ ※
I=handles.I;
I1=rgb2gray(I);%转换为灰度图
I2=edge(I1,'sobel',0.15,'both');%sobel算子边缘检测操作
axes(handles.axes2);
imshow(I1);title('灰度图');
axes(handles.axes13);
imhist(I1);title('灰度图直方图');
axes(handles.axes3);
imshow(I2);title('算子边缘检测');
se=[1;1;1];
I3=imerode(I2,se);%腐蚀操作
axes(handles.axes14);
imshow(I3);title('腐蚀后');
se=strel('rectangle',[25,25]);
I4=imclose(I3,se);%图像聚类,填充图像:平滑图像的轮廓
axes(handles.axes15);
imshow(I4);title('图像平滑化');
I5=bwareaopen(I4,2000);%去除聚团灰度值小于2000的部分:从对象中移除小对象
%imwrite(I5,['./save/',num2str(rd),'_移除小对象.jpg']);
axes(handles.axes16);
imshow(I5);title('移除小对象');

%※﹏﹋﹏ 车牌定位﹏﹋﹏﹋﹏ ※
[y,x,z]=size(I5);%返回15各维的尺寸,存储在x,y,z中
myI=double(I5);
tic      %tic计时开始,toc结束
Blue_y=zeros(y,1);%产生一个y*1的零针
for i=1:y
    for j=1:x
        if(myI(i,j,1)==1)%如果myI图像坐标为(i,j)点值为1,即背景颜色为蓝色,blue加一
            Blue_y(i,1)=Blue_y(i,1)+1;%蓝色像素点统计
        end
    end
end
[temp MaxY]=max(Blue_y);
%Y方向车牌区域确定
%temp为向量yellow_y的元素中的最大值,MaxY为该值得索引
PY1=MaxY;
while((Blue_y(PY1,1)>=5)&&(PY1>1))
    PY1=PY1-1;
end
PY2=MaxY;
while((Blue_y(PY2,1)>=5)&&(PY2<y))
    PY2=PY2+1;
end
IY=I(PY1:PY2,:,:);
%X方向车牌区域确定
Blue_x=zeros(1,x);%进一步确认x方向的车牌区域
for j=1:x
    for i=PY1:PY2
        if(myI(i,j,1)==1)
            Blue_x(1,j)=Blue_x(1,j)+1;
        end
    end
end
PX1=1;
while((Blue_x(1,PX1)<3)&&(PX1<x))
    PX1=PX1+1;
end
PX2=x;
while((Blue_x(1,PX2)<3)&&(PX2>PX1))
    PX2=PX2-1;
end
PX1=PX1-1;%对车牌区域的矫正
PX2=PX2+1;
dw=I(PY1:PY2-8,PX1:PX2,:);
t=toc;
axes(handles.axes17);
imshow(IY);title('行方向合理区域');
axes(handles.axes4);
imshow(dw),title('车牌定位结果');

%=========字符分割==========imwrite(dw,['./save/',num2str(rd),'_dw.jpg']);%将彩色车牌写入dw文件中
a=imread(['./save/',num2str(rd),'_dw.jpg']);%读取车牌
b=rgb2gray(a);%功能是将真彩色图像转换为灰度图像,即灰度化处理
imwrite(b,['./save/',num2str(rd),'_车牌灰度图像.jpg']);%将灰度图写入文件
axes(handles.axes18);
imshow(b),title('车牌灰度图像');
g_max=double(max(max(b)));
g_min=double(min(min(b)));
T=round(g_max-(g_max-g_min)/3);%T为二值化的阈值 向最近的方向取整
[m,n]=size(b);
d=(double(b)>=T);%d:二值图像
imwrite(d,['./save/',num2str(rd),'_车牌二值图像.jpg']);
axes(handles.axes19);
imshow(d),title('车牌二值图像');
% 均值滤波处理
h=fspecial('average',3);
%建立预定义的滤波算子,average为均值滤波,模板尺寸为3*3
d=im2bw(round(filter2(h,d)));%filter2(h,d),h为滤波器.d为要滤波的数据,这里将h放在d上,一个一个移动进行模板滤波. 
imwrite(d,['./save/',num2str(rd),'_均值滤波后.jpg']);
axes(handles.axes20);
imshow(d),title('均值滤波操作');
%膨胀或腐蚀处理
se=eye(2);%产生m×n的单位矩阵
[m,n]=size(d);%返回信息矩阵
if bwarea(d)/m/n>=0.365%计算二值图像中对象的总面积与整个面积的比是否大于0.365,bwarea是计算二值图像中对象的总面积的函数
    d=imerode(d,se);%如果大于0.365则进行腐蚀
elseif bwarea(d)/m/n<=0.235%计算二值图像中对象的总面积与整个面积的比值是否小于0.235
    d=imdilate(d,se);%如果小于则实现膨胀操作
end
imwrite(d,['./save/',num2str(rd),'_膨胀或腐蚀处理后.jpg']);
axes(handles.axes21);
imshow(d),title('膨胀或腐蚀处理');
%寻找连续有文字的块,若长度大于某阈值,则认为该块有两个字符组成,需要分割
d=qiege(d);%使用自定义的字符分割函数
[m,n]=size(d);
k1=1;
k2=1;
s=sum(d);
j=1;
while j~=n
    while s(j)==0
        j=j+1;
    end
    k1=j;
    while s(j)~=0 && j<=n-1
        j=j+1;
    end
    k2=j-1;
    if k2-k1>=round(n/6.5)
        [val,num]=min(sum(d(:,[k1+5:k2-5])));
        d(:,k1+num+5)=0;%判定有两个字符,需要分割
    end
end
%再切割
d=qiege(d);
%切割出7个字符
y1=10;
y2=0.25;
flag=0;
word1=[];
while flag==0
    [m,n]=size(d);
    left=1;
    wide=0;
    while sum(d(:,wide+1))~=0
        wide=wide+1;
    end
    if wide<y1 %认为是左干扰 
        d(:,[1:wide])=0;
        d=qiege(d);
    else
        temp=qiege(imcrop(d,[1 1 wide m]));
        [m,n]=size(temp);
        all=sum(sum(temp));
        two_thirds=sum(sum(temp([round(m/3):2*round(m/3)],:)));
        if two_thirds/all>y2
            flag=1;word1=temp;% 此处为切割出来的WORD 1
        end
        d(:,[1:wide])=0;d=qiege(d);
    end
end
% 分割出第二个字符
[word2,d]=getword(d);
% 分割出第三个字符
[word3,d]=getword(d);
% 分割出第四个字符
[word4,d]=getword(d);
% 分割出第五个字符
[word5,d]=getword(d);
% 分割出第六个字符
[word6,d]=getword(d);
% 分割出第七个字符
[word7,d]=getword(d);
[m,n]=size(word1);
%归一化大小为40*20
word1=imresize(word1,[40 20]);
word2=imresize(word2,[40 20]);
word3=imresize(word3,[40 20]);
word4=imresize(word4,[40 20]);
word5=imresize(word5,[40 20]);
word6=imresize(word6,[40 20]);
word7=imresize(word7,[40 20]);
axes(handles.axes5);imshow(word1),title('1');
axes(handles.axes6);imshow(word2),title('2');
axes(handles.axes7);imshow(word3),title('3');
axes(handles.axes8);imshow(word4),title('4');
axes(handles.axes9);imshow(word5),title('5');
axes(handles.axes10);imshow(word6),title('6');
axes(handles.axes40);imshow(word7),title('7');
imwrite(word1,['./save/',num2str(rd),'_1.jpg']);
imwrite(word2,['./save/',num2str(rd),'_2.jpg']);
imwrite(word3,['./save/',num2str(rd),'_3.jpg']);
imwrite(word4,['./save/',num2str(rd),'_4.jpg']);
imwrite(word5,['./save/',num2str(rd),'_5.jpg']);
imwrite(word6,['./save/',num2str(rd),'_6.jpg']);
imwrite(word7,['./save/',num2str(rd),'_7.jpg']);
liccode=char(['0':'9' 'A':'Z' '辽粤豫鄂鲁陕京津浙']);%京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼
SubBw2=zeros(40,20);%产生一个40*20大小的零矩阵
l=1;
for I=1:7;%I为待识别的字符位
    ii=int2str(I);%整形数据转化为字符串类型
    t=imread(['./save/',num2str(rd),'_',ii,'.jpg']);
    SegBw2=imresize(t,[40 20],'nearest');%缩放处理
    SegBw2=double(SegBw2)>20;
    if l==1 %车牌号第一位为汉字识别,使用37-45号字符模板
        kmin=37;
        kmax=45;
    elseif l==2 %车牌号第二位为 A~Z 大写字母识别,使用11-36号字符模板
        kmin=11;
        kmax=36;
    else l>=3   %第三位以后是字母或数字识别,使用1-36号字符模板
        kmin=1;
        kmax=36;
    end
    for k2=kmin:kmax
        fname=strcat('字符模板\',liccode(k2),'.jpg');
        SamBw2=imread(fname);%调用字符模板图像文件 
        SamBw2=double(SamBw2)>1;
        for i=1:40
            for j=1:20
                SubBw2(i,j)=SegBw2(i,j)-SamBw2(i,j);% 这里是将待识别图像与模板图像两幅图相减得到第三幅图
            end
        end
        
        Dmax=0;
        for k1=1:40;
            for l1=1:20
                if(SubBw2(k1,l1)>0 || SubBw2(k1,l1)<0)
                    Dmax=Dmax+1;
                end
            end
        end
        Error(k2)=Dmax;
    end
    Error1=Error(kmin:kmax);
    MinError=min(Error1);
    findc=find(Error1==MinError);
    Code(l*2-1)=liccode(findc(1)+kmin-1);
    Code(l*2)=' ';
    l=l+1;
end
axes(handles.axes12);imshow(dw),title(['车牌号码:',Code],'Color','b');

% ==========================结束============================

2.补充说明

在这里插入图片描述
在这里插入图片描述

需要自己在网络上下载0-9和A-Z的字符模板

  • 13
    点赞
  • 112
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值