一、车牌识别简介
车牌识别技术起源于20世纪80年代初期,图像模式识别和计算机视觉在其中起到至关重要的作用。随着计算机技术的迅速普及和进步,80年代中后期,车牌识别系统逐步投入市场并使用,但识别精度和速度都不理想。目前,发达国家的车牌识别系统已广泛用于市场,其中以色列和新加坡公司的车牌识别系统较为领先。由于车牌设计的不同,不存在一种通用的车牌检测技术。因中国车牌包括汉字,使得国外车牌识别系统不能直接用于国内车牌识别,需要中国自主研发。中国的车牌识别技术研究起步略晚于西方国家。目前国内技术领先的是中科院的“汉王眼”和香港的视觉科技公司。但是,这些投入市场的车牌识别系统的使用都有一定的局限性,在车牌图像质量差、车牌倾斜、光照条件不理想等情况时,识别率会大幅度降低。
为了克服上述问题,本文对不同光照条件下获得的车牌图像进行了识别和分析。由于车牌涉及保密信息,暂时没有公开的大规模数据集可供使用和实验对比。本文先对车牌数据进行采集,统一处理320×240分辨率的图片,建立测试用数据库。数据库分为两类:测试库1为光照条件较好,无阴影车牌;测试库2为光照条件较差,有阴影车牌。采用传统的模板匹配算法建立车牌识别系统,模板图片采用中值滤波算法进行平均处理,统一建立分辨率为20×40的识别模板库。为方便用户使用, 利用Matlab建立了图形用户交互界面(GUI) 。通过对测试库车牌实验, 可以看到车牌成像质量对识别率
有很大影响。因此在建立车牌识别系统时,适当角度的补光可有效提高识别的准确率。
1 图像的预处理
由于车牌多是通过交通监控等条件获得,因周边交通环境、拍摄角度、光照和实时性要求等多种原因,得到的照片直接用于车牌的识别准确率难以得到保证。因此,预处理图像可以提高识别的准确性。
1.1图像的灰度化
由相机拍摄的牌照通常是彩色图像, 即RGB图像为了提高车牌识别系统的速度、节省内存, 先将RGB图像转换为灰度图.红、蓝、绿三种基本颜色按不同的比例可以组成任意一种颜色,所以车牌照片的每一个颜色都可由不同比例的红、蓝、绿组成。灰度图像可以用数组I表示,数组且I的数据类型一般有整数和双精度两种。通常0代表黑色,255代表白色。采用适合于人类视觉系统的转换方法,如公式(1)所示。
其中,系数a,b,c要大于0,且a+b+c=1,Y表示灰度值,R、G、B分别表示红色、绿色和蓝色,a=0.299、b=0.584、c=0.117.图1显示了带有车牌照片的原始车牌图像,图2显示了在公式(1)的灰度处理之后车牌图像的灰度图像。
图1 车牌原图
图2 车牌灰度图
1.2 图像二值化
图像二值化不仅可以大大减少数据量,还可以突出图像的目标轮廓,有利于后续的图像定位和分割处理。在车牌图像的二值化处理中,被确定为目标区域的像素具有大于或等于阈值的灰度值,计算如公式(2)所示。经过测试,当阈值th=0.76时,效果较好,结果如图3所示。
图3 车牌的二值化图
1.3 图像的边缘检测
本文采用Roberts算子来进行边缘检测。采用该算子的计算量小, 速度快, 便于后续的实时处理, 其模板如表1所示。若梯度幅度G(x,y)大于设定的阈值,则判断为边缘。G(x,y)计算式如公式(3)所示,此处阈值选择为0.15。
表1 Roberts算子模板
其中,f(x,y)是图像空间(x,y)处的灰度值,G(x,y)是f(x,y)的梯度幅度。图4是边缘检测后的结果。
图4 车牌的边缘检测图
2车牌识别系统的设计 2.1车牌定位
车牌定位采用颜色特征提取,一般的车牌区域都具有很明显的特点,中国的车牌以蓝底白字居多。传统的方法一般根据车牌的色彩特征,彩色像素点统计的方法分割出合理的车牌区域假设经相机采集包含车牌的RGB图像, 水平方向记为y,垂直方向记为x。首先,确定车牌各分量分别对应的颜色范围。其次,计算水平方向上对应的像素数量和车牌的合理面积。然后,计算分割的水平方向区域中垂直方向上该颜色范围内白的像素数量,并为定位设置合理的阈值。最后,根据对应方向的范围确定车牌区域。但是这种方法的准确率较低,本文采用文献[6]提出的颜色特征提取及二值化归类方法进行算法改进,计算方法如公式(4)所示。图5为定位后的车牌。
其中的蓝色特征可用式(4)表示:
图5 车牌定位图
2.2车牌字符识别
在字符识别前,先对车牌字符分割。字符分割采用阈值分割,主要包含两个步骤【7]。
(1)确定所需要进行分割的阈值。
(2)将阈值与每个点的灰度值对照,以达到分割目的。
将分割后的图像进行归一化处理,可以有效地将字符图像的大小进行缩放以得到大小一致的字符图像,便于后续的字符识别。
模板匹配一般是数字图像处理中最常使用的识别方法之一,先建立模板库,再将字符输入到模板中寻找与之最佳匹配的模板字符。
模板图像大小为20×40,模板库由数字0-9,32个省份的简称汉字和大写英文字母(其中O一般不用作车牌字母)三部分组成。模板的部分图像如图6所示。
图6 模板库部分图片
二、部分源代码
% ******************************************************% % time : /05/26 17:12% tip : 车牌识别% change: % *******************************************************function varargout = CarId(varargin)% CARID MATLAB code for CarId.fig%CARID, by itself, creates a new CARID or raises the existing%singleton*.%%H = CARID returns the handle to a new CARID or the handle to%the existing singleton*.%%CARID('CALLBACK',hObject,eventData,handles,...) calls the local%function named CALLBACK in CARID.M with the given input arguments.%%CARID('Property','Value',...) creates a new CARID or raises the%existing singleton*. Starting from the left, property value pairs are%applied to the GUI before CarId_OpeningFcn gets called. An%unrecognized property name or invalid value makes property application%stop. All inputs are passed to CarId_OpeningFcn via varargin.%%*See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one%instance to run (singleton)".%% See also: GUIDE, GUIDATA, GUIHANDLES% Edit the above text to modify the response to help CarId% Last Modified by GUIDE v2.5 26-May- 20:30:44% Begin initialization code - DO NOT EDITgui_Singleton = 1;gui_State = struct('gui_Name', mfilename, ...'gui_Singleton', gui_Singleton, ...'gui_OpeningFcn', @CarId_OpeningFcn, ...'gui_OutputFcn', @CarId_OutputFcn, ...'gui_LayoutFcn', [] , ...'gui_Callback', []);if nargin && ischar(varargin{1})gui_State.gui_Callback = str2func(varargin{1});endif nargout[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});elsegui_mainfcn(gui_State, varargin{:});end% End initialization code - DO NOT EDIT% --- Executes just before CarId is made visible.function CarId_OpeningFcn(hObject, eventdata, handles, varargin)% This function has no output args, see OutputFcn.% hObject handle to figure% eventdata reserved - to be defined in a future version of MATLAB% handles structure with handles and user data (see GUIDATA)% varargin command line arguments to CarId (see VARARGIN)% Choose default command line output for CarIdhandles.output = hObject;%隐藏坐标轴set(handles.axes1,'visible','off');set(handles.axes2,'visible','off');set(handles.axes3,'visible','off');set(handles.axes4,'visible','off');set(handles.axes5,'visible','off');set(handles.axes6,'visible','off');set(handles.axes7,'visible','off');set(handles.axes8,'visible','off');set(handles.axes9,'visible','off');set(handles.axes10,'visible','off');set(handles.axes11,'visible','off');set(handles.axes12,'visible','off');% Update handles structureguidata(hObject, handles);% UIWAIT makes CarId wait for user response (see UIRESUME)% uiwait(handles.figure1);% --- Outputs from this function are returned to the command line.function varargout = CarId_OutputFcn(hObject, eventdata, handles) % varargout cell array for returning output args (see VARARGOUT);% hObject handle to figure% eventdata reserved - to be defined in a future version of MATLAB% handles structure with handles and user data (see GUIDATA)% Get default command line output from handles structurevarargout{1} = handles.output;%======================my code========================%% tip : 被删除的callback自己手动添加一下...55555.....function openLocal_Callback(hObject,eventdata,handles)[filename, pathname]=uigetfile({'*.jpg; *.png; *.bmp; *.tif';'*.png';'All Image Files';'*.*'},'请选择图片路径');if pathname==0return;endI=imread([pathname filename]);%显示原图axes(handles.axes1)%将Tag值为axes1的坐标轴置为当前imshow(I,[]); %解决图像太大无法显示的问题.why?貌似会自动缩放title('原图');handles.I=I; %更新图像% Update handles structureguidata(hObject, handles);function openCamera_Callback(hObject,eventdata,handles)imaqhwinfovid = videoinput('winvideo',1);usbVidRes1=get(vid,'videoResolution');%获取视频的尺寸nBands1=get(vid,'NumberOfBands');%采集视频的颜色通道axes(handles.axes1);hImage1=imshow(zeros(usbVidRes1(2),usbVidRes1(1),nBands1));preview(vid,hImage1);handles.vid=vid;% Update handles structureguidata(hObject, handles);function btnTakePhoto_Callback(hObject,eventdata,handles)vid=handles.vid;frame = getsnapshot(vid);axes(handles.axes1);imwrite(frame,'I.png');I=imread('I.png');axes(handles.axes1)%将Tag值为axes1的坐标轴置为当前imshow(I,[]); %解决图像太大无法显示的问题.why?貌似会自动缩放title('拍摄完成');handles.I=I;%更新原图% Update handles structureguidata(hObject, handles);%下面在使用原图方法: handles.I% --- Executes on button press in btnGray2.function btnGray2_Callback(hObject, eventdata, handles)% hObject handle to btnGray2 (see GCBO)% eventdata reserved - to be defined in a future version of MATLAB% handles structure with handles and user data (see GUIDATA)I=handles.Cut;I = rgb2gray(I);axes(handles.axes8)%将Tag值为axes1的坐标轴置为当前imshow(I,[]); %解决图像太大无法显示的问题.why?貌似会自动缩放title('灰度处理');handles.gray2=I;%更新原图% Update handles structureguidata(hObject, handles);% --- Executes on button press in btnBalance.function btnBalance_Callback(hObject, eventdata, handles)% hObject handle to btnBalance (see GCBO)% eventdata reserved - to be defined in a future version of MATLAB% handles structure with handles and user data (see GUIDATA)I=handles.gray2;I = histeq(I);axes(handles.axes9)%将Tag值为axes1的坐标轴置为当前imshow(I,[]); %解决图像太大无法显示的问题.why?貌似会自动缩放title('直方图均衡化');handles.balance=I;%更新原图% Update handles structureguidata(hObject, handles);% --- Executes on button press in btnDouble.function btnDouble_Callback(hObject, eventdata, handles)% hObject handle to btnDouble (see GCBO)% eventdata reserved - to be defined in a future version of MATLAB% handles structure with handles and user data (see GUIDATA)I=handles.balance;I = im2bw(I, 0.76);axes(handles.axes10)%将Tag值为axes1的坐标轴置为当前imshow(I,[]); %解决图像太大无法显示的问题.why?貌似会自动缩放title('图像二值化');handles.double=I;%更新原图% Update handles structureguidata(hObject, handles);% --- Executes on button press in btnMid.function btnMid_Callback(hObject, eventdata, handles)% hObject handle to btnMid (see GCBO)% eventdata reserved - to be defined in a future version of MATLAB% handles structure with handles and user data (see GUIDATA)I=handles.double;I = medfilt2(I);axes(handles.axes11)%将Tag值为axes1的坐标轴置为当前imshow(I,[]); %解决图像太大无法显示的问题.why?貌似会自动缩放title('中值滤波');handles.Mid=I;%更新原图% Update handles structureguidata(hObject, handles);% --- Executes on button press in btnCut2.function btnCut2_Callback(hObject, eventdata, handles)% hObject handle to btnCut2 (see GCBO)% eventdata reserved - to be defined in a future version of MATLAB% handles structure with handles and user data (see GUIDATA)I=handles.Mid;I = my_imsplit(I); %切割图像[m, n] = size(I);s = sum(I); %sum(x)就是竖向相加,求每列的和,结果是行向量;j = 1;k1 = 1;k2 = 1;while j ~= nwhile s(j) == 0j = j + 1;endk1 = j;while s(j) ~= 0 && j <= n-1j = j + 1;endk2 = j + 1;if k2 - k1 > round(n / 6.5)[val, num] = min(sum(I(:, [k1+5:k2-5])));I(:, k1+num+5) = 0;endend
三、运行结果
四、matlab版本及参考文献
1 matlab版本
a
2 参考文献
[1] 蔡利梅.MATLAB图像处理——理论、算法与实例分析[M].清华大学出版社,.
[2]杨丹,赵海滨,龙哲.MATLAB图像处理实例详解[M].清华大学出版社,.
[3]周品.MATLAB图像处理与图形用户界面设计[M].清华大学出版社,.
[4]刘成龙.精通MATLAB图像处理[M].清华大学出版社,.
[5]呙润华,苏婷婷,马晓伟.BP神经网络联合模板匹配的车牌识别系统[J].清华大学学报(自然科学版),,53(9):1221-1226.
[6]鲁扬.基于BP神经网络的车牌识别算法研究[D].大庆:东北石油大学,.
[7]李强,张娟.一种改进的基于模板匹配的污损车牌识别方法[J].智能计算机与应用. ,9(03).
[8] 梁凯.基于MATLAB的汽车车牌识别系统的设计与实现[D] .哈尔滨:黑龙江大学, .
[9]刘雄飞,朱盛春.车牌字符多特征提取与BP神经网络的识别算法[J].计算机仿真,,31(10):161-164,290.
[10]乔有田.基于数学形态学和灰度跳变特征的车牌定位方法[J].工业控制计算,(2):77-78