车牌识别的MATLAB实现

车牌识别的MATLAB实现

目录
1.图像数据读入
2.图像转换
3.边缘检测
4.腐蚀处理
5.平滑处理
6.移除小对象
7.确定车牌位置
8.定位剪切
9.车牌图像二值化
10.均值滤波,膨胀或腐蚀处理
11.切割
12.分离字符

1.图像数据读入
要实现车牌识别,首先要从计算机中读取含有要识别车牌的图片,为了使用户更方便地从文件系统中直接选取图片,这里使用了uigetfile函数。

uigetfile函数的调用格式为:[filename,filepath]=uigetfile(…),执行此函数可得到供用户选择图片文件的对话框,用户选择要识别的图片并点击“打开”按钮后,会返回此图片的文件名和路径名,分别保存到filename和pathname两个变量中(为了避免用户在对话框中选择非图片文件出现异常,在调用uigetfile函数时将函数参数设置成了“.png;.jpg”,所以文件选择对话框中只会出现图片文件),然后通过imread函数将图像数据读出,赋值给变量I,从而实现图像数据的读入。

2.图像转换
由于彩色图不易确定车牌边界,将彩色图转换为灰度图以进一步处理图片。这里使用了rgb2gray函数,该函数接收一个rgb图像变量作为参数,返回该图像转换为灰度图后的图像数据,并将该数据赋值给变量I1。

若想得到该灰度图的灰度分布情况,可使用imhist函数画出该灰度图的灰度值分布直方图。

3.边缘检测
在将彩色图转换为灰度图后,便可用edge函数识别该图像的边界,edge函数通过使用一阶导数和二阶导数检测亮度的不连续来确定图像的边界,它可以使用Sobel,Prewitt,Roberts,Canny,LoG,零交叉等多种算子,这里使用最强大的Canny算子进行边缘检测。
edge函数的调用格式如下:
BW = edge(I,’canny’,THRESH,SIGMA)

4.腐蚀处理
由于边缘检测后的图像中无关结构太多,这里需对图像进行腐蚀处理,实现腐蚀处理的函数为imerode,它接收一个图像数据和一个结构子,图像中背景与结构子完全重合的像素点输出值为1,不完全重合的和完全不重合的像素点输出值为0,最后返回使用该结构子腐蚀过后的图像数据,以此实现削减无关结构的目的。

5.平滑处理
腐蚀后的图像结构大多呈分散状分布,不连贯。为了方便之后确认车牌位置,这里需对该图像进行平滑处理,在此我们使用闭操作使车牌平滑,并减小噪音,闭操作可以理解为先膨胀后腐蚀,实现函数为imclose,调用格式如下:
IM2 = imclose(IM,SE)
(其中IM是图像数据,SE是结构子)

6.移除小对象
为了使接下来车牌位置的确定更精确,这里使用了bwareaopen函数从图象中移除小对象,调用格式如下:
BW2 = bwareaopen(BW,P,CONN)

7.确定车牌位置
在经过上面的处理之后,最初要识别的彩色图像已经变成了以车牌为主要结构的二值图像,我们可以对这种主体结构清晰的二值图像进行扫描,进而确定出车牌的位置。
这里确定车牌位置的思路为:
首先使用size函数得到该图像矩阵的行数y和列数x,用zero函数建立一个y行1列的零矩阵white_y,然后使用嵌套循环结构遍历该二值图像的每一个像素点,把每行值为1的像素点(也就是白色像素点)的数量分别记录在先前创建的矩阵white_y中。遍历完之后,找出white_y矩阵中值最大的元素,它所对应的行即为该二值图像中白色像素点最多的行,该行可认为是靠近车牌中心的一行。
然后我们以这一行为起点,分别向上向下逐行扫描,当被扫描到的行中白色像素点多于120时(该值只是一个用于判断的估计值),继续向上(或向下)扫描,直到扫描到某行中的白色像素点数量小于120时,停止扫描,并记录这一行的行数,该行数即为车牌的上边界(或下边界)。
同理,我们可以用相同的方法确定出车牌的左边界和右边界。

8.定位剪切
通过以上定位,我们得到了车牌的上边界PY1,下边界PY2,左边界PX1,右边界PX2,我们可以通过这四个边界值从原彩色图像中切割出车牌:
dw=I(PY1:PY2,PX1:PX2,:);

9.车牌图像二值化
在得到车牌的彩色图像之后,为了便于将其中的字符分离,我们将它转换为二值图像,具体代码如下:
g_max=double(max(max(b)));
g_min=double(min(min(b)));
T=round(g_max-(g_max-g_min)/3);
[m,n]=size(b);
d=(double(b)>=T);

10.均值滤波,膨胀或腐蚀处理
在车牌转换为二值图像后,为了使图像中干扰元素减少,我们对其进行均值滤波,通过fspecial函数构造均值滤波器,然后使用filter2函数进行滤波,以减小图中噪音。
由于不同原始图像的差异,处理到这里后,字符可能会不连续,也可能会连在一起,这时我们需要再次对滤波后的图像进行腐蚀或者膨胀处理,这里使用判断结构以图中白色部分的面积为判断依据决定使用腐蚀或者膨胀。

11.切割
在分离字符之前,我们还要切去车牌边缘的黑色部分,在这里我们定义了一个用于切割的函数qiege,思路如下:
从图像顶部向底部逐行扫描,对扫描到的行求和,若某行全部像素点求和为0(即该行所有像素点均为黑色),则切去这一行,直到扫描到某一行求和后值不为零,以这一行为上边界。
同理,再用相同的方法从其他三个方向扫描,切割出下边界,左边界和·右边界,最后得到切去边缘黑色部分的图像。

12.分离字符
将切割过后,就可以对图片中的字符进行分离了,这里我们定义了一个用于分离字符的函数getword,思路如下:
对图像从左到右逐列扫描,并将每列中像素点的值进行求和,若和不为零(即这一列是组成某字符的一列),则向右继续扫描下一列,直到某一列求和后值为零(即这一列是两白色字符之间的黑色间隔),图像最左侧到这一列之间即为第一个字符,将其切出,然后将该区域内所有像素点赋值为0(涂黑),重复以上操作直至分离出所有字符。

源代码

function cpsb3=main()
[filename, pathname] = uigetfile( ...
       {'*.png;*.jpg', 'All MATLAB Files (*.png, *.jpg)'; ...
        '*.*', 'All Files (*.*)'},  'Pick a file'); 
I=imread(filename);%图象的采集与转换
figure(1),subplot(2,2,1),imshow(I);title('原图');
I1=rgb2gray(I);
subplot(2,2,2),imshow(I1);title('灰度图');
subplot(2,2,3),imhist(I1);title('灰度图直方图');
I2=edge(I1,'canny',0.08,'both');%边缘算子 平滑处理 减小噪声 提取边缘
subplot(2,2,4),imshow(I2);title('canny算子边缘检测')


se=[1;1;1];%线型结构元素
I3=imerode(I2,se);
figure(2),subplot(2,2,1),imshow(I3);title('腐蚀后图像');
se=strel('rectangle',[40,40]);%生成一个矩阵 线型结构元素 
I4=imclose(I3,se);  %闭运算
subplot(2,2,2),imshow(I4);title('平滑图像的轮廓');
I5=bwareaopen(I4,2000,8);
subplot(2,2,3),imshow(I5);title('从图象中移除小对象');
subplot(2,2,4),imhist(I5);title('灰度图直方图');


[y,x]=size(I5);%【行 列 默认1 】
myI=double(I5);

white_y=zeros(y,1);
for i=1:y
    for j=1:x
        if(myI(i,j,1)==1)
           white_y(i,1)= white_y(i,1)+1;%蓝色像素点统计
        end
    end
end
[temp MaxY]=max(white_y);%temp为向量white_y的元素中的最大值,MaxY为该值的索引( 在向量中的位置)
PY1=MaxY;
while ((white_y(PY1,1)>=120)&&(PY1>1))
    PY1=PY1-1; %找车牌最上端
end
PY2=MaxY;
while ((white_y(PY2,1)>=40)&&(PY21;  %找车牌最下端
end
%begin纵向扫描
white_x=zeros(1,x);%进一步确定x方向的车牌区域
for j=1:x
    for i=PY1:PY2
        if(myI(i,j,1)==1)
            white_x(1,j)= white_x(1,j)+1;
        end
    end
end


PX1=1;  % 以下为找车牌X方向最小值???
while ((white_x(1,PX1)<3)&&(PX11;
end
PX2=x;  % 以下为找车牌X方向最大值??
while ((white_x(1,PX2)<3)&&(PX2>PX1))
    PX2=PX2-1;
end
PX2=PX2+2;
dw=I(PY1:PY2,PX1:PX2,:); % 
figure(3),subplot(2,2,1),imshow(dw),title('定位剪切后的彩色车牌图像')

imwrite(dw,'dw.jpg');   %dw
a=imread('dw.jpg');  %读取图片文件中的数据
b=rgb2gray(a);  %彩色图像转换为灰度图像
figure(3);subplot(2,2,2),imshow(b),title('1.车牌灰度图像')

%对车牌二值化  设定一个阈值T,用T将图像的数据分成两部分:大于T的像素群和小于T的像素群,即对图像二值化
g_max=double(max(max(b)));%换成双精度数值
g_min=double(min(min(b)));%换成双精度数值
T=round(g_max-(g_max-g_min)/3); % T 为二值化的阈值  最佳阈值二值化,灰度的最大值减去 最大值与最下值的1/3梯度
[m,n]=size(b);  %返回矩阵b的尺寸信息 m为行 n为列
d=(double(b)>=T);  % d:二值图像
figure(3);subplot(2,2,3),imshow(d),title('2.车牌二值图像')
% % 滤波
h=fspecial('average',3);  %均值滤波器 average指定算子的类型,3为相应的参数
d=im2bw(round(filter2(h,d)));  %BW = im2bw(I, level) 将灰度图像 I 转换为二进制图像。输出图像 %BW 将输入图像中亮度值大于 level 的像素替换为值1 (白色),其他替换为值0(黑色
imwrite(d,'4.均值滤波后.jpg');  % 保存
figure(3),subplot(2,2,4),imshow(d),title('4.均值滤波后')


% 某些图像进行操作,膨胀或腐蚀
se=eye(2); % eye(n) 返回n乘n单一矩阵 单位矩阵
[m,n]=size(d);
temp=bwarea(d);%matlab里函数bwarea 计算目标物的面积
if bwarea(d)/m/n>=0.365 %计算二值图像中白的对象占总面积
    d=imerode(d,se);   %imerode 实现图像腐蚀 d为待处理图像,se是结构元素对象
elseif bwarea(d)/m/n<=0.235
    d=imdilate(d,se); %imdilate 图像膨胀
end
imwrite(d,'5.膨胀或腐蚀处理后.jpg');
figure(4),subplot(2,2,1),imshow(d),title('5.膨胀或腐蚀处理后')

d=qiege(d);
figure(4),subplot(2,2,2),imshow(d),title('6.切割后图片')
[word1,d]=getword(d);% 分割出第二个字符
[word2,d]=getword(d);% 分割出第二个字符
[word3,d]=getword(d);% 分割出第三个字符
[word4,d]=getword(d);% 分割出第四个字符
[word5,d]=getword(d);% 分割出第五个字符
[word6,d]=getword(d);% 分割出第六个字符
[word7,d]=getword(d);% 分割出第七个字符

figure(5),subplot(1,7,1),imshow(word1)
subplot(1,7,2),imshow(word2)
subplot(1,7,3),imshow(word3)
subplot(1,7,4),imshow(word4)
subplot(1,7,5),imshow(word5)
subplot(1,7,6),imshow(word6)
subplot(1,7,7),imshow(word7)
end

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  %有白色加1知道没有白色,也就是找出一个白色区域
        wide=wide+1;
    end
    temp=qiege(imcrop(d,[1 1 wide m])); %切出第一个字符
    [m1,n1]=size(temp);
    if widey2  %像素小于  或 切割字体大小 列除以行
        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;
end
%切割
    function e=qiege(d)
        [m,n]=size(d);
        top=1;bottom=m;left=1;right=n;   % init
        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%切割出白区域(纵切)
            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]);
    end

Rafael C.Gonzalez , Richard E.Woods , Steven L. Eddins著 阮秋琪译. 数字图像处理的MATLAB实现. 清华大学出版社
百度词条 车牌识别系统

你可能感兴趣的:(MATLAB)