基于FPGA的車牌識別系統(tǒng)
智能交通系統(tǒng)(Intelligent Transportation System,ITS)是一種將計算機、信息、通訊及自動化控制技術(shù)相結(jié)合的運用于交通方面的現(xiàn)代化管理體系。它的主要功能是解決城市交通擁擠和堵塞問題,在不增加現(xiàn)有交通道路建設(shè)的情況下,運用現(xiàn)代化的信息和通信方面的技術(shù),提高交通道路的通行能力,改善交通擁擠問題。
本文引用地址:http://cafeforensic.com/article/201706/348703.htm汽車牌照識別技術(shù)(LicensePlateReeognition,LPR)是一種專用的計算機視覺系統(tǒng),在智能交通系統(tǒng)中占有極其重要的地位。該系統(tǒng)的主要功能是,從一副含有車牌的汽車圖片中,自動定位出車牌圖像,并對車牌上的字符進行分割,最后識別出分割后的單個字符。
1、系統(tǒng)框圖
整個系統(tǒng)可以大致分為下面幾個模塊:
圖1-1 系統(tǒng)模塊圖
系統(tǒng)的處理過程如下圖所示:
圖1-2 系統(tǒng)處理流程
2、算法介紹
下面就對每個步驟的具體算法進行介紹:
預(yù)處理部分主要作用是為了增強圖像和去除噪聲,一邊在后續(xù)處理時減少誤差。使用的具體方法是先對圖像進行拉氏變換和梯度變換來增強圖像的邊緣和細節(jié)。由于采集到的圖像所包含的噪聲屬于高斯噪聲,所以進行高斯濾波來去噪[2]。
拉式變換:
拉式算子:
上式中x值對應(yīng)像素點所在位置的行數(shù),y為所在位置的列數(shù),f(x,y)為在第x行y列的像素點的像素值。所以拉式變換就轉(zhuǎn)化為對待處理像素的鄰域像素的帶參運算。
梯度變換:
梯度算子
圖2-1 待處理像素鄰域像素
同樣梯度算子轉(zhuǎn)換成相應(yīng)像素點的帶參運算。高斯濾波的原理與拉氏變換和梯度變換相同,只是高斯濾波的參數(shù)是取自高斯函數(shù)。
這樣就可以完成圖像的預(yù)處理過程
車牌定位
(1)運用行掃描的方法定位牌照的上下邊界: 若某一行的0→1(白到黑)和1→0(黑到白) 變化次數(shù)大于設(shè)定的閾值(如13,車牌有7個字符,所以跳變至少14次), 則設(shè)其為待處理像素鄰域像素。
待測車牌的最低點,繼續(xù)掃描直 至0→1 和1→0 變化次數(shù)小于閾值,將該閾值設(shè)為待測車牌的最高點。若最高點與最低點之差大于15(即車牌圖像的高度),則認為目標已檢測到,否則繼續(xù)進行掃描;如果未檢測到符合上述條件的目標,則自動門限值重復(fù)以上的操作,直到找到目標為止。
(2)垂直投影法定位牌照的左右邊界:在找到車牌的上下限后,利用二值圖像在豎直方向上的投影作為特征, 從左到右尋找目標的中心點坐標。
字符分割
字符分割可采用垂直投影法。由于字符塊在豎直方向上的投影必然在字符間或字符內(nèi)的間隙處取得局部最小值, 因此字符的正確分割位置應(yīng)該在上述局部最小值的附近, 并且這個位置應(yīng)滿足車牌的字符書寫格式、字符尺寸限制和一些其他條件。
利用垂直投影法, 對復(fù)雜環(huán)境下的汽車圖像中的字符分割有較好的效果。
字符識別
字符識別使用模板匹配法。
首先將標準模板入庫,把每一張“ 標準車牌”分割出來的字符歸一化, 接著將歸一化后的模板矩陣存入FPGA 中作為標準模板庫。采用20×15 bit 大小的數(shù)組作為標準模板。
當車牌上的待識別字符歸一化以后, 依次與標準庫中的模板進行匹配,即矩陣對應(yīng)位依次做差,分別計算總的相同像素個數(shù),則有最大相同數(shù)目的那一組數(shù)認為是相似度最大,則用此時的標準模板所對應(yīng)的數(shù)字或字母作為最終識別的結(jié)果。
3、Matlab仿真結(jié)果
用matlab對上述算法進行了仿真,仿真結(jié)果如下(仿真程序見附錄):
圖3-1 原彩色圖像
圖3-2 灰度圖像
圖3-3 二值化后的圖像
圖3-4 定位出的車牌圖像
圖3-5 字符分割的結(jié)果
將字符歸一化為20*15的模板形式以后再與模板庫里的字符相比較即可得到識別結(jié)果。
圖3-6 歸一化后的模板
模板庫里的模板是與上面的具有相同大小的圖像,將歸一化后的圖像與模板庫里存儲的圖像進行比較運算,距離最小的即認為是判斷字符。
從仿真結(jié)果來看,使用這種算法完全可以實現(xiàn)車牌識別,由于這種算法對每一個元素的處理過程非常清楚,可以由FPGA實現(xiàn),從而可以保證整個系統(tǒng)的實時性,提高它的實用價值。
5、附錄
Matlab仿真程序:
主函數(shù):
RGB=imread(chepai.jpg);
figure,imshow(RGB),title(ÔͼÏñ);
GRAY=rgb2gray(RGB);
figure,imshow(GRAY),title(»Ò¶ÈͼÏñ);
%Ô¤´¦Àí¬°üÀ¨Àʽ±ä»»¬Ìݶȱ任¬È»ºó¸ß˹Â˲¨
%ÀÊϱ任
l=[0,1,0;1,-4,1;0,1,0];
LAP=imfilter(GRAY,l);
%Ìݶȱ任¨sobelËã×Ó
s=fspecial(sobel);
DIV=imfilter(LAP,s);
GRAY2=imsubtract(GRAY,DIV);
%¸ß˹Â˲¨
g=fspecial(gaussian,3,3);
GRAY3=imfilter(GRAY2,g);
%½Ç¶È±ä»»
%==================================================
theta=0:180;
RD=radon(GRAY3,theta);
thetaiw=maxtheta(RD);
GRAY4=imrotate(GRAY3,358);
%
%¶þÖµ»¯Í¼Ïñ
BW=im2bw(GRAY4);
%³µÅƶ¨Î»
[m,n]=size(BW);
for x=1:m
ch(x)=0;
end
%ͳ¼ÆÌø±ä´ÎÊý
for x=1:m
for y=2:n
if BW(x,y)~=BW(x,y-1)
ch(x)=ch(x)+1;
end
end
end
plot(ch),title(Ìø±ä´ÎÊý);
%È·¶¨³µÅÆͼÏñµÄÉÏϱ߽ç
k=1;
for x=1:m
if ch(x)>13
p(k)=x;
k=k+1;
else
if k50
k=1;
else break;
end
end
end
p(1)
p(k-1)
% pÖаüº¬ÓÐÁ¬ÐøµÄ±ä»¯Êý³¬¹ý13µÄÐÐÊý
LINE=GRAY4(p(1):p(k-1),:);
figure,imshow(LINE),title(³µÅÆÐÐͼÏñ);
LINE1=BW(p(1):p(k-1),:);
figure,imshow(LINE1);
%È·¶¨³µÅƵÄ×óÓұ߽ç
for y=1:n
col(y)=0;
end
for y=1:n
for x=1:(k-1)
col(y)=col(y)+LINE1(x,y);
end
end
i=0;
j=0;
for y=2:n
if col(y)>0
if col(y-1)==0
i=i+1;
raise(i)=y;
end
else
if col(y-1)>0
j=j+1;
down(j)=y;
end
end
end
CP=LINE1(:,raise(1):down(j));
%¶Ô³µÅƽøÐÐ×Ö·û·Ö¸î
t=0;
for a=1:(i-1)
if raise(a+1)-down(a)>5
t=t+1;
raise1(t+1)=raise(a+1);
down1(t)=down(a);
end
end
raise1(1)=raise(1);
down1(t+1)=down(j);
w=raise(1);
for u=1:(t+1)
raise1(u)=raise1(u)-w+1;
down1(u)=down1(u)-w+1;
end
ZF1=CP(:,raise1(1):down1(1));
ZF2=CP(:,raise1(2):down1(2));
ZF3=CP(:,raise1(3):down1(3));
ZF4=CP(:,raise1(4):down1(4));
ZF5=CP(:,raise1(5):down1(5));
ZF6=CP(:,raise1(6):down1(6));
ZF7=CP(:,raise1(7):down1(7));
ZF8=CP(:,raise1(8):down1(8));
figure,imshow(ZF1),title(×Ö·û1);
figure,imshow(ZF2),title(×Ö·û2);
figure,imshow(ZF3),title(×Ö·û3);
figure,imshow(ZF4),title(×Ö·û4);
figure,imshow(ZF5),title(×Ö·û5);
figure,imshow(ZF6),title(×Ö·û6);
figure,imshow(ZF7),title(×Ö·û7);
figure,imshow(ZF8),title(×Ö·û8);
MB1=temp(ZF1);
MB2=temp(ZF2);
MB3=temp(ZF3);
MB4=temp(ZF4);
MB5=temp(ZF5);
MB6=temp(ZF6);
MB7=temp(ZF7);
MB8=temp(ZF8);
figure,imshow(MB1);
figure,imshow(MB2);
figure,imshow(MB3);
figure,imshow(MB4);
figure,imshow(MB5);
figure,imshow(MB6);
figure,imshow(MB7);
figure,imshow(MB8);
subplot(2,4,1),imshow(MB1);
subplot(2,4,2),imshow(MB2);
subplot(2,4,3),imshow(MB3);
subplot(2,4,4),imshow(MB4);
subplot(2,4,5),imshow(MB5);
subplot(2,4,6),imshow(MB6);
subplot(2,4,7),imshow(MB7);
subplot(2,4,8),imshow(MB8);
求偏轉(zhuǎn)角的子程序(maxtheta):
function y =maxtheta(A)
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
[m,n]=size(A);
k=0;
for i=1:m
for j=1:n
if A(i,j)>k
k=A(i,j);
x=i;
y=j;
end
end
end
制作模板的子程序(temp):
function B=temp(A)
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
[m,n]=size(A);
B=zeros(20,15);
C=zeros(20,n);
a=m/19;
a1=m/20;
b=n/14,
b1=n/15;
%½«Í¼Ïñת»»Îª20ÐеÄͼÏñ
if m>=40
for y=1:n
for x=1:m
c=uint8(x/a)+1;
C(c,y)=C(c,y)+A(x,y);
end
end
elseif m>=20
for y=1:n
for x=1:m
c=uint8(x/a1);
C(c,y)=C(c,y)+A(x,y);
end
end
else
for y=1:n
for x=1:20
c=uint8(x*a1)
C(x,y)=A(c,y);
end
end
end
if n>=30
for x=1:20
for y=1:n
d=uint8(y/b)+1;
B(x,d)=B(x,d)+C(x,y);
end
end
elseif n>=15
for x=1:20
for y=1:n
d=uint8(y/b1);
B(x,d)=B(x,d)+C(x,y);
end
end
else
for x=1:20
for y=1:15
d=uint8(y*b1);
B(x,y)=C(x,d);
end
end
end
for x=1:20
for y=1:15
if B(x,y)~=0
B(x,y)=1;
else
B(x,y)=0;
end
end
end
end
評論