- 設計目的…………………..………………….…………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