目录
- 设计目的…………………..………………….…………3
- 设计要求………………….………………………….….3
- 设计的内容………………..……………………….……3
- 题目分析…………………………………………….………..3
- 总体设计……………….…………………………….……….4
- 具体设计……………………………………………..…….…5
1、文件……………….………………………………….……….5
1.1、打开………..…………………………………….…………5
1.2、保存…………………………..………………….…………5
1.3、退出……………………..……………………………….…5
2、编辑…………………………..…………………………………5
6.2.1、灰度………………………..………………….……………5
6.2.2、亮度………………………..………………….……………6
6.2.3、截图…………………………..……………….……………7
6.2.4、缩放…………………………..…………….………………7
3、旋转…………………………………..…………………………9
6.3.1、上下翻转…………………….…………….………………9
6.3.2、左右翻转………………….…………….…………………9
6.3.3任意角度翻转…………………………….…………………9
6.4、噪声………………………………..…………..………………10
6.5、滤波……………………………………..………..……………10
6.6、直方图统计……………………………………………………11
6.7、频谱分析………………………………………..…..…………12
6.7.1、频谱图………………………… …… …… ……….……12
6.7.2、通过高通滤波器………………… …… .……………….12
6.7.3、通过低通滤波器……………………………….. ……….13
6.8、灰度图像处理………………………………………… . …….14
6.8.1、二值图像……………………………………………….. .14
6.8.2、创建索引图像……………………………………… .…..14
6.9、颜色模型转换……………………………..… ..……………14
6.10、操作界面设计……………………………………..…………15
- 程序调试及结果分析………………….……………………15
- 心得体会…………………………….………………………16
- 参考文献…………………………….………………………17
- 附录………………………….………………………………18
基于MATLAB的图像处理系统
摘要:
数字图像处理技术是20世纪60年代发展起来的一门新兴学科,随着图像处理理论和方法的进一步完善,使得数字图像处理技术在各个领域得到了广泛应用,并显示出广阔的应用前景。MATLAB既是一种直观、高效的计算机语言,同时又是一个科学计算平台。它为数据分析和数据可视化、算法和应用程序开发提供了最核心的数学和高级图形工具。根据它提供的500多个数学和工程函数,工程技术人员和科学工作者可以在它的集成环境中交互或编程以完成各自的计算。
MATLAB中集成了功能强大的图像处理工具箱。由于MATLAB语言的语法特征与C语言极为相似,而且更加简单,更加符合科技人员对数学表达式的书写格式,而且这种语言可移植性好、可扩展性强,再加上其中有丰富的图像处理函数,所以MATLAB在图像处理的应用中具有很大的优势。
本文从预处理、边缘检测、车牌定位、字符分割、字符识别五个方面,具体介绍了车牌自动识别的原理。并用MATLAB软件编程来实现每一个部分,最后识别出汽车牌照。
关键词:MATLAB,数字图像处理,车牌识别系统
一、课程设计目的
Matlab技术课程设计是利用Matlab应用软件的基础知识和基本程序设计方法,解决选修专业课程中数字信号处理的实际应用问题,从而加深对理论知识的掌握,并把所学的知识系统、高效的贯穿到实践中来,避免理论与实践的脱离。同时提高独立编程水平,并在实践中不断完善理论基础,有助于培养综合能力。
二、设计的内容
学习MATLAB程序设计,利用MATLAB图像处理工具箱,设计和实现通过设计一个车牌识别系统
三、课程设计的要求:按照软件工程方法,根据需求进行程序的功能分析和界面设计,给出设计详细说明。然后按照自己拟定的功能要求进行程序设计和调试。
以下几点是程序必须实现的功能。
1)设计图像用户界面,让用户能够对图像进行调整,显示和对比变换前后的图像。
2)图像直方图统计和直方图均衡,要求显示直方图统计,比较直方图均衡后的效果。
3)显示识别结果
四、题目分析
(一)研究背景:随着我国经济的发展,综合实力的增强和城市化进程的加快,国内各大城市交通管理能力将面临重大考验。近年来,各主要城市都将城市智能交通系统(ITS)的建设作为改善城市交通状况的重点,以缓解城市交通管理的压力,车牌识别系统作为智能交通系统的主要技术之一也得到了很大的发展。
(二)现状目前,国内的ITS 产业仍然处于起步阶段,在产业链中,电子地图商、导航终端商、嵌入式操作系统均已经具备产业规模,而所欠缺的环节则是对实时交通信息的采集和处理系统。车牌识别系统是城市智能交通管理系统的一个重要组成部分,广泛用于是针对公路行驶的机动车辆进行实时监控的智能化交通系统,电子收费,交通违规管理,安全停车管理等重要领域。
五、总体设计
车牌识是一辆汽车独一无二的信息,因此,对车辆牌照的识别技术可以作为辨识一样车最为有效地方法。车牌识别系统包括摄取的汽车图像,车牌号码的识别,车牌图像的采集和预处理,牌照区域的定位和提取,牌照字符的分割和识别等几个部分组成,如下图所示。
字符分割
归一化
输出结果
字符识别
车牌定位
预处理
输入图像
图1 车牌识别系统流程图
六、具体设计
界面效果图
(1)灰度校正
由于牌照图象在拍摄时受到种种条件的限制和干扰,图象的灰度值往往与实际景物不完全匹配,这将直接影响到图象的后续处理。如果造成这种影响的原因主要是由于被摄物体的远近不同,使得图象中央区域和边缘区域的灰度失衡,或是由于摄像头在扫描时各点的灵敏度有较大的差异而产生图象灰度失真,或是由于曝光不足而使得图像的灰度变化范围很窄。这时就可以采用灰度校正的方法来处理,增强灰度的变化范围、丰富灰度层次,以达到增强图象的对比度和分辨率。我们发现车辆牌照图象的灰度取值范围大多局限在r=(50,200)间,而且总体上灰度偏低,图象较暗
图6 灰度增强后的图像
(2)平滑处理
对于受噪声干扰严重的图象,由于噪声点多在频域中映射为高频分量,因此可以在通过低通滤波器来滤除噪声,但实际中为了简化算法,也可以直接在空域中用求邻域平均值的方法来削弱噪声的影响,这种方法称为图象平滑处理。
例如,某一象素点的邻域S 有两种表示方法:8邻域和4邻域分别对应的邻域平均值为,
其中,M 为邻域中除中心象素点f(i,j) 之外包括的其它象素总数,对于4邻M=4,8 邻域M=8。然而,邻域平均值的平滑处理会使得图象灰度急剧变化的地方,尤其是物体边缘区域和字符轮廓等部分产生模糊作用。为了克服这种平均化引起的图象模糊现象,我们给中心点象素值与其邻域平均值的差值设置一固定的阈值,只有大于该阈值的点才能替换为邻域平均值,而差值不大于阈值时,仍保留原来的值,从而减少由于平均化引起的图象模糊。边缘提取是较经典的算法,此处边缘的提取采用的是Roberts算子。
综上所述,结合MATLAB实验过程,得出不是每一种图像处理之初都适合滤波和边界增强。本次汽车车牌的识别,为了保存更多的有用信息,经过多次比较,选择图9作为后期处理的依据。
(6)操作界面设计
为了使整个操作界面更加的美观,对背景颜色和字体颜色进行设置。
二、程序调试及结果分析
在程序设计过程中,碰到很多的问题。
-
- 一个函数只能对灰度图像处理,不能对RGB图像处理,那么如何才能对RGB图像处理呢?
这主要是对MATLAB函数的不够清楚,用到的很多函数是针对二维数据的,而RGB图像的数据是一个三维矩阵,所以处理要与灰度图像不同,在开始的时候,我认为应该找一个能够应用于三维矩阵的函数,结果却没找到,后来想到可以把三维数据进行降维处理,同样使用二维的函数,只要是同样处理三次。比如,彩色图像的滤波处理,直方图均衡等。
2/同一个操作对灰度图像可以使用,当用户选择的是彩色图像时,该操作就会出错?
这是由于设计程序时,本身程序是有针对性的,有些程序只能对灰度图像有效,有些对彩色图像有效,但是用户并不清楚这些,所以在设计的过程中就要考虑全面,要分开设计。在本次课程设计中,我均对每个程序的开始时,用if isrgb(x)进行判断。
- 在没有加入噪声的情况下,点击“中值滤波”或是其它滤波,会提示错误?
这是由于在滤波程序设计的过程中,开始用到的变量是handles.noise_img,而这个变量是在加入噪声时候才定义的,所以在没有加入噪声的情况下,点击各个滤波就会弹出变量没有定义的错误,解决方法就是在文件打开的时候就给定义handles.noise_img=x。
- 本次设计存在一个比较大的问题,就是每次操作都是独立的,比如:要对图像加入噪声,然后在此基础上进行亮度调整,截图,频谱分析等等就不行。
我认为应该是整个程序设计过程中对变量的设置没有做好,应该每次操作后,把处理后的数据保存在一个全局变量,这样还要对处理后的数据进行在处理时,只要把这个全局变量作为原始数据带入就可。
- 心得体会
1、在这次设计过程中,感触很深,由于对MATLAB图像处理的函数不熟悉,导致自己走了很多的弯路,比如在设计图像左转90度和右转90度时,由于开始并不知道imrotate函数,只知道上下翻转flipud和左右翻转fliplr函数,想着要怎么用这两个函数来实现左转和右转呢,如果当当只用矩阵转置的话,并不能达到要求,后来想可以结合flipud和fliplr函数来实现,下面程序是实现左转90度:
axes(handles.axes2);
x=(handles.img);
if isrgb(handles.img)
a=x(:,:,1);
b=x(:,:,2);
c=x(:,:,3);
e=a';
g=b';
f=c';
y(:,:,1)=e;
y(:,:,2)=g;
y(:,:,3)=f;
axes(handles.axes2);
for k=1:3
f(:,:,k)=flipud(y(:,:,k));
end
imshow(f);
else
m=x';
y=flipud(m);
imshow(y);
end
同理,也可以通过转置和fliplr函数实现右转90度。
但是后来发现其实只要用imrotate函数就可以解决问题。通过这次经历后,后来在设计其它程序时,尽量找MATLAB自带的现成函数,而不是一碰到问题就自己想算法,这样可以节省较多的时间。
2、在理工科的专业应用背景下,用matlab 进行相关计算与仿真编程的优势非常突出。特定的问题处理算法,我们通常都以M文件的文本形式给定最终的解决方案,自己设计的程序是在MATLAB环境下,用MATLAB语言编写的,这对于有安装MATLAB软件的计算机上运行并不存在什么问题,关键是一般的计算机很少有去安装MATLAB软件的,那么要在这些机子上运行该程序要怎么办呢,难道要先安装MATLAB软件,这显然太麻烦了,对于一个通用的,比较成熟的解决方案,我们当然期望它能应用到更多的场合,而.exe (可执行)文件可运行于所有的通用WINDOWS操作系统,为此,将M文件转换成.exe文件倒是个不错的想法。
通过查找资料,了解到在生成可执行性文件之前,需要进行一系列编译环境方面的配置:
要将用Matlab语言编写的函数文件编译成可独立执行的*.exe文件(即可脱离Matalab环境的执行程序),首先要安装和配置好Matlab Compiler,一般来说,在安装Matlab时就已经安装了相应版本的Matlab Compiler。只是不同版本的Matlab,其编译器的使用方法有一定的差异,这一点要引起一定的注意。
在确定安装好Matlab Compiler后,还需要对Compiler进行适当的配置,方法是在Matlab命令窗口输入:
Mbuild –setup
然后根据提示执行相应的操作,使用者可根据自己计算机中现有编译器的情况选择合适的编译器,如VC++ 6.0、VC++7.0、Bland C的编译器等,目前Matlab好象还不支持VC++8.0(我计算机安装的就是VC++2005,Matlab就无法识别)。当然,如果你的计算机里根本就没有安装其他任何语言的编译器,也可选择Matlab自带的Lcc编译器,其实这个编译器对大多数用户已经够用了(我就是选择的Matlab自带的Lcc编译器)。
配置好编译器后,自然就是对自己编写的M文件进行编译了。
将M文件编译为独立可执行文件的语法是:
>>mcc –m fun1.m fun2.m…..
其中fun1就是最后的可执行文件的名称。
3、通过本次设计,使自己对MATLAB GUI设计流程有了比较深刻的体会,同时也了解了一般软件设计的过程。在设计过程中碰到了很多的问题,通过这些问题,使自己分析问题,解决问题的能力得到了较大的提高。
- 参考文献
- 郑阿奇,曹戈,赵阳.MATLAB实用教程[M].北京:电子工业出版社
- 程卫国,冯峰,姚东,徐听.MATLAB5.3应用指南[M].北京:人民邮电出版社
- 陈杨.MATLAB 6.X图像编程与图像处理[M].西安:西安电子科技大学出版社
- 附录
function varargout = two(varargin)
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @two_OpeningFcn, ...
'gui_OutputFcn', @two_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
% End initialization code - DO NOT EDIT
% --- Executes just before erzhi is made visible.
function two_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
---------------------------------------------------------
%接下来是菜单的程序
---------------------------------------------------------
function file_Callback(hObject, eventdata, handles)
--------------------------------------------------------
%文件打开程序
function open_Callback(hObject, eventdata, handles)
[name,path]=uigetfile({'*.bmp'},'载入图像');
if isequal(name,0)|isequal(path,0)
errordlg('没有选中文件','出错');
return;
else
x=imread([path,name]);
axes(handles.axes1);
imshow(x);
handles.img=x;
handles.noise_img=x;
guidata(hObject,handles)
end
---------------------------------------------------
function save_Callback(hObject, eventdata, handles)
%文件保存
[filename,pathname] = uiputfile('*.bmp','图片保存为');
if isequal([filename,pathname],[0,0])
errordlg('没有保存','出错');
return;
else
file=strcat(pathname,filename);
(handles.axes2);
i=getimage(gca);
imwrite(i,file);
end
-----------------------------------------------------
function exit_Callback(hObject, eventdata, handles)
clc;
close all;
close(gcf);
---------------------------------------------------------
%编辑菜单的程序
------------------------------------------------------
function edit_Callback(hObject, eventdata, handles)
-------------------------------------------------
function huidu_Callback(hObject, eventdata, handles)
%灰度处理
axes(handles.axes2);
if isrgb(handles.img)
y=rgb2gray(handles.img); %RGB
imshow(y);
else
msgbox('这已经是灰度图像','转换失败');
end
------------------------------------------------------
function liangdu_Callback(hObject, eventdata, handles)
%亮度处理
prompt={'输入参数1','输入参数2','输入gamma'};
defans={'[0 0.7]','[0 1]','1'};
p=inputdlg(prompt,'输入参数',1,defans);
p1=str2num(p{1});
p2=str2num(p{2});
p3=str2num(p{3});
gamma=p3;
x=(handles.img);
y=imadjust(x,p1,p2,gamma);
axes(handles.axes2);
imshow(y);
------------------------------------------------------
function jietu_Callback(hObject, eventdata, handles)
%截图
set(handles.axes2,'HandleVisibility','ON');
axes(handles.axes2);
y=imcrop(handles.img);
imshow(y);
handles.Timage=y;
------------------------------------------------------
function fangda_Callback(hObject, eventdata, handles)
------------------------------------------------------
function lingjz_Callback(hObject, eventdata, handles)
%邻近插值放大
axes(handles.axes2);
prompt={'输入放大倍数:'};
defans={'2'};
p=inputdlg(prompt,'输入放大倍数',1,defans);
p1=str2num(p{1});
y=imresize(handles.img,p1,'nearest'); %最近邻插值法放大
imshow(y);
------------------------------------------------------
function shuangxianfa_Callback(hObject, eventdata, handles)
%双线放大
axes(handles.axes2);
prompt={'输入放大倍数:'};
defans={'2'};
p=inputdlg(prompt,'输入放大倍数',1,defans);
p1=str2num(p{1});
y=imresize(handles.img,p1,'bilinear'); %最近邻插值法放大
imshow(y);
------------------------------------------------
function shuangsanci_Callback(hObject, eventdata, handles)
%双三次放大
axes(handles.axes2);
prompt={'输入放大倍数:'};
defans={'2'};
p=inputdlg(prompt,'输入放大倍数',1,defans);
p1=str2num(p{1});
y=imresize(handles.img,p1,'bicubic');
imshow(y);
-------------------------------------------------------
function suoxiao_Callback(hObject, eventdata, handles)
%邻近插值缩小
axes(handles.axes2);
prompt={'输入放大倍数:'};
defans={'0.2'};
p=inputdlg(prompt,'输入放大倍数',1,defans);
p1=str2num(p{1});
y=imresize(handles.img,p1,'nearest'); %最近邻插值法缩小
imshow(y);
------------------------------------------------------
function shuangxian_Callback(hObject, eventdata, handles)
%双线性缩小
axes(handles.axes2);
prompt={'输入放大倍数:'};
defans={'0.2'};
p=inputdlg(prompt,'输入放大倍数',1,defans);
p1=str2num(p{1});
y=imresize(handles.img,p1,'bilinear'); %最近邻插值法缩小
imshow(y); --------------------------------------------------------
function shuangsancisuox_Callback(hObject, eventdata, handles)
%双三次缩小
axes(handles.axes2);
prompt={'输入放大倍数:'};
defans={'0.2'};
p=inputdlg(prompt,'输入放大倍数',1,defans);
p1=str2num(p{1});
y=imresize(handles.img,p1,'bicubic');
imshow(y);
------------------------------------------------------
function xuanzhuan_Callback(hObject, eventdata, handles)
-------------------------------------------------------
function updown_Callback(hObject, eventdata, handles)
%上下翻转
axes(handles.axes2);
x=(handles.img);
if isrgb(handles.img)
for k=1:3
y(:,:,k)=flipud(x(:,:,k));%上下翻转函数
end
imshow(y);
else
x=(handles.img);
y=flipud(x);
imshow(y);
end
---------------------------------------------------------
function leftright_Callback(hObject, eventdata, handles)
%左右翻转
axes(handles.axes2);
if isrgb(handles.img)
x=(handles.img);
for k=1:3
y(:,:,k)=fliplr(x(:,:,k));%左右翻转函数
end
imshow(y);
else
x=(handles.img);
y=fliplr(x);
imshow(y);
end
------------------------------------------------------
function zeft90_Callback(hObject, eventdata, handles)
%左转90度
axes(handles.axes2);
x=(handles.img);
y=imrotate(x,90);
imshow(y);
-------------------------------------------------------
function right90_Callback(hObject, eventdata, handles)
%右转90度
axes(handles.axes2);
x=(handles.img);
y=imrotate(x,-90);
imshow(y);
------------------------------------------------------
function other_Callback(hObject, eventdata, handles)
%任意角度旋转
axes(handles.axes2);
prompt={'输入参数1:'};
defans={'30'};
p=inputdlg(prompt,'输入参数',1,defans);
p1=str2num(p{1});
y=imrotate(handles.img,p1);
imshow(y);
-----------------------------------------------------
function gs_Callback(hObject, eventdata, handles)
%加入高斯噪声
axes(handles.axes2);
prompt={'输入参数1:','输入参数2'};
defans={'0','0.02'};
p=inputdlg(prompt,'输入参数',1,defans);
p1=str2num(p{1});
p2=str2num(p{2}); y=imnoise(handles.img,'gaussian',p1,p2);
imshow(y);
handles.noise_img=y;
guidata(hObject,handles);
-------------------------------------------------------
function jy_Callback(hObject, eventdata, handles)
%加入椒盐噪声
prompt={'输入参数1:'}; %对话框的设置,用户输入的是字符串
defans={'0.02'}; %缺省值
p=inputdlg(prompt,'输入参数',1,defans);
p1=str2num(p{1}); %字符串转化为数值
axes(handles.axes2);
x=(handles.img);
y=imnoise(x,'salt & pepper',p1);
imshow(y);
handles.noise_img=y;
guidata(hObject,handles);
--------------------------------------------------------
function cx_Callback(hObject, eventdata, handles)
%加入乘性噪声
axes(handles.axes2);
prompt={'输入参数1:'};
defans={'0.02'};
p=inputdlg(prompt,'输入参数',1,defans);
p1=str2num(p{1});
y=imnoise(handles.img,'speckle',p1);
imshow(y);
handles.noise_img=y;
guidata(hObject,handles);
-----------------------------------------------------
function zhifangtutongji_Callback(hObject, eventdata, handles)
---------------------------------------------------------
function red_Callback(hObject, eventdata, handles)
%R直方图
set(handles.axes2,'HandleVisibility','ON');
axes(handles.axes2);
x=imhist(handles.img(:,:,1)); %直方图统计
x1=x(1:10:256);
horz=1:10:256;
bar(horz,x1);
set(handles.axes2,'xtick',0:50:255);
---------------------------------------------------------
function gray_Callback(hObject, eventdata, handles)
%G直方图
set(handles.axes2,'HandleVisibility','ON');
axes(handles.axes2);
if isrgb(handles.img)
x=imhist(handles.img(:,:,2)); %直方图统计
x1=x(1:10:256);
horz=1:10:256;
bar(horz,x1);
set(handles.axes2,'xtick',0:50:255);
else
msgbox('这是灰度图像','旋转失败');
end
------------------------------------------------------
function blue_Callback(hObject, eventdata, handles)
%B直方图
set(handles.axes2,'HandleVisibility','ON');
axes(handles.axes2);
if isrgb(handles.img)
x=imhist(handles.img(:,:,3)); %直方图统计
x1=x(1:10:256);
horz=1:10:256;
bar(horz,x1);
%axis([0 255 0 150000]);
set(handles.axes2,'xtick',0:50:255);
%set(handles.axes2,'ytick',0:2000:15000);
else
msgbox('这是灰度图像','旋转失败');
end