一, 車牌識別重要算法匯總
1.1 圖像預處理
1.1.1 常規機動車車牌規格
如表1.1所示,是本次設計主要處理的三種車牌形式。
表1.1 常規機動車車牌規格
1.新能源汽車專號牌:綠底黑字黑框線,新能源汽車號牌為漸變綠色。 |
![]() |
2.大型汽車號牌:黃底黑字黑框線。載貨汽車和專業作業車;半掛車;電車。 |
![]() |
3.小型汽車號牌:藍底白字白框線。 |
![]() |
1.1.2 彩色圖像的灰度圖變換
將彩 色 圖 像 進 行 灰 度 轉 換 是 為 了 提 高 系 統總體算 法 的 處 理 速 度 和實現系統的穩定性考慮,並且在程序處理比較中,在灰度圖像中處理比彩色圖像中處理的計算量會減少很多,反映整體圖像的局部和整體的色度,亮度的特征分布來看,灰度圖和彩色圖並沒有什么區別[4]。
灰度轉換是將含有R、B、G 三個通道組成的彩色照片進行轉變為單通道的灰色圖片。在此之前需要了解一下彩圖是如何構成的,一張彩照主要R.G.B分為三個分量,而且每個分量組成是由255個中值構成,所以每一個彩色像素點是由三個分量合成的。其實灰度圖就是RGB組成的彩色照片模型中的一種特殊照片,這種照片主要的優點就是在存儲時用一個字節就夠了,所以在處理時不會因為數據量太大,光線的強弱的變化受到影響。所以灰度化處理在圖像處理中是十分關鍵步驟,也是為后續處理奠定基礎。
1.1.3 圖像的灰度修正
要了解灰度修正原理就要了解將彩照進行灰圖轉化的方法,這里面方法分為3種:
方法1:對每個像素點進行單獨處理,將每個像素點的RGB的分量的權值和不同的權值進行加權處理,然后在將處理過的新像素點進行求平均值,這種方法十 分適合灰色圖的處理環境[5]。
方法2:對每個像素點的分量的權值進行對比。並將最大值作為該像素點的灰度值。這種方法操作十分簡單,但是處理過的照片十分容易失真[5]。
方法3:對每一像素點的分量中的權值進行平均值處理,這種方法可以將圖片中的各個像素點變得平滑,便於后期的字符處理[5]。
根據我們對車牌識別系統的需要我們在這里對處理主要顏色特點進行簡要的分析:
(1)當車牌是藍色牌時在RGB分量分布中B的分量占大多部分,而且 B分量遠大於另外兩種分量的占比,另外兩種分量占比相差無幾;
(2)當車牌是黃色牌時在RGB分量分布中R、G的分量占大多部分,而且 R分量和G的占比對等,B分量的占比則含量最低;
(3)當車牌是綠色牌時在RGB分量分布中G的分量占大多部分,而且G分量遠大於另外兩種分量的占比,另外兩種分量占比也是相差無幾;
(4)車牌中的白色信息在RGB分量的分布中,RGB分量的各個值都是255;
(5)車牌中的黑色信息在RGB分量的分布中,RGB分量的各個值都是0;
在本次設計中處理時則是用平均值的方法,這樣可以使含有車牌部分的圖像通過灰度處理變得簡易,有利於減少處理時間。假設g為灰度值:
具體效果如圖1.1所示:
圖1.1 車牌灰度修正圖
1.2 邊緣檢測
邊緣檢測就是把想要的部分進行提取邊緣,可以使需要的部分邊緣輪廓更加明顯,如今對於這個技術的處理已經有很多成熟的算法,主要常用的算法有:Sobel、拉普拉斯,Canny等。在本次課題中用的是Canny來進行提取邊緣,該算法是由約翰 F.Canny根據前人研究邊緣檢測算法的基礎上進行改進,該算法是將邊緣的提取結果進行封裝成框[1],顯示效果也更加明顯,有利於車牌定位時的使用。
Canny算法詳細原理計算環節如下[2]:
(1)高斯濾波器:用於平滑圖像,濾除噪聲。
下面用尺寸為3*3作為高斯卷積核進行舉例,該舉例的矩陣的求和結果必須為1(進行歸一化)。
式中
H——歸一化矩陣;
e——濾波的像素點,px;
A——圖像中一個3x3的像素窗口,px;
sum——表示矩陣中所有元素相加求和。
其中*為卷積符號。處理之后的每個像素值等於其原像素點的中值和其相鄰像素點進行加權求和。目前將圖像進行卷積操作是十分重要且運用廣泛的。對Canny影響最大的就是在選取高斯卷積核的時候,如果選擇的像素尺寸過大,雖然去噪能力也會增強,但是照片整體來看會變得模糊。所以並不是尺寸選取越大、抗噪能力越強越好。所以為了能夠在不影響定位精度的情況下,一般尺寸會選33或者55就可以了[6]。
(2)梯度強度和方向
通過灰度值的變化來作為邊緣檢測的標准,如果將邊緣檢測的灰度值作為一個二元函數。梯度就可以看做二元函數的導數,但是圖像的數據是離散型的數據,所以圖像的梯度就用差分值進行表示,在實際情況中就是兩個像素的進行求差值。一個像素點的周圍有8個相鄰的像素點,分布在它的上下左右對角的四對算子,所以Canny需要用分布在四個位置的算子進行檢測,主要通過圖像的水平、垂直和對角的四對算子來計算梯度。這里選用sodel舉例來計算水平方向和豎直方向的差分值,這里假設SX和Sy作為模板、A作為原圖,最后SX和Sy分別與A進行卷積操作,最后通過x、y方向差分值的圖進行計算該點的梯度G和方向 [7]。
(3)非極大值抑制
非極大值抑制也是在邊緣檢測中的重要部分之一,其主要目的是沿着梯度和方向將前后梯度值進行逐一比較來進行查找目標像素區域中最大值。
假設圖2.2中的相鄰像素點分別為g1 、g2、 g3、g4,c為目標像素點,圖2.2的左邊部分中的c點是我們需要處理的像素點,c點梯度方向用藍線表示。算出c點的梯度的幅值M,線段g1g2、線段g3g4與藍色直線相交與交點dtmp1和交點dtmp2。這兩個交點稱之為c點的梯度幅值。由於交點dtmp1和交點dtmp2並不是完整的像素點,所以稱之為亞像素點,其坐標則是浮點數表示的,這里要想算出交點的梯度幅值,就要利用線性插值法來[8]。首先對於g1、g2的幅值是已知的,也知道dtmp1在g1g2這條線段上,可以通過計算交點dtmp1與g1點和g2點的比值來得出dtmp1的梯度幅值,而對於dtmp1與g1點和g2點的比值可以用梯度的方向進行計算。故假設g1的幅值M(g1),g2的幅值M(g2),則dtmp1可以很容易得到。
圖1.2 線性插值圖
(4)雙閾值檢測
雙閾值檢測的原理也是十分簡單,主要就是范圍的划分,圖1.3中有兩條直線,假設這兩條直線就是兩類邊緣,當像素區域的梯度值高於maxVal,則說明此邊緣為強邊緣值。強的邊緣可以很好地展示出更多的細節邊緣,在圖1.4右邊部分可以看出,很多細節都能明顯看見邊緣部分。當像素區域的梯度值處於maxVal與minVal之間,則說明此邊緣為弱邊緣值,在圖1.4中間部分可以看出,雖然可以看出基本輪廓,但是較多的細節卻看不出來[9]。但也不是說弱的邊緣沒有利用價值,在復雜的環境下為了簡化處理圖像又不會影響輸出結果時,是可以考慮使用的。雙閾值檢測最為主要的是確定閾值范圍,通過閾值的范圍的確定,可以提高容錯率、增強算法的利用率,所以通過實際檢測發現maxVal:minVal=2:1的比例效果比較好[6]。
圖1.3 雙閾值檢測圖
圖1.4 邊緣檢測圖
1.3 形態學處理
1.3.1 圖像的腐蝕和膨脹
形態學處理是在原有的基礎之上對研究物體的現狀進行改變,這里我們利用的是 Opencv模塊進行操作,首先介紹的是圖像的腐蝕和膨脹,是通過opencv中的erode函數和dilate函數來實現的,目的就是將通過二值化過得圖片的白色部分進行放大和縮小的處理。接下來詳細介紹腐蝕和膨脹。
腐蝕是將白色部分進行收縮得過程。圖1.5就是腐蝕的原理圖,原理就是利用3*3的像素核B,與進行過二值化處理的圖片A中的每一個像素區域所取最小值的像素塊進行“與”操作,當結果為1時,則圖中該像素區視為1的,不然則認為該像素區的檢驗結果視為0,當結果為0時,就會使二值化的圖像中的為0的像素區進行一個收縮的操作。
圖1.5 圖像腐蝕算法圖
膨脹是與腐蝕的原理相反。圖1.6就是膨脹的原理圖,原理就是利用3*3的像素核B,與進行過二值化處理的圖片A中的每一個像素區域所取最小值的像素塊進行“與”操作,當結果為0時,則圖中該像素區視為0的,不然則認為該像素區的檢驗結果視為1,當結果為1時,就會使二值化的圖像中的為1的像素區進行一個擴大的操作。
圖1.6 圖像膨脹算法圖
腐蝕和膨脹的主要程序操作如下:
import cv2 # opencv讀取的格式是RGB
import numpy as np
img = cv2.imread('car01.jpg')
ker = np.ones((3,3), numpy.uint8)
ero= cv2.erode(img,ker,iterations = 1)
dil = cv2.dilate(img,ker,iterations = 1)
res = np.hstack((img,erosion,dilate))
cv_show('dige and erode and dilate',res)
cv2.imwrite('car_canny03.jpg',res)
erosion = cv2.erode()和dilate = cv2.dilate()迭代次數越多和 kernel越大效果越明顯,具體效果如圖1.7和圖1.8所示。
圖1.7 圖像腐蝕后圖
圖1.8 圖像膨脹后圖
1.3.2 圖像的開運算與閉運算
開運算與閉運算的原理就是先后執行腐蝕和膨脹的處理。如圖1.10中的左半部分所示,開運算主要功能就是剔除掉背景噪聲、對形狀的邊緣部分進行平滑處理、切斷物體與物體之間的細小噪聲[10]。如圖1.10中的右半部分所示,閉運算的主要功能剔除圖像中的小孔和小黑點。填充由噪聲產生的小空洞、而且會與旁邊的物體形狀進行連接、修復斷開的輪廓線,在不改變面積的前提下使物體形狀的邊緣部分變得平滑。不管是開運算還是閉運算選擇卷積核大小都是十分重要的,太小了無法有效的剔除黑點。對於卷積核的形狀也會有影響的。而且當選取為圓的卷積核時,對於物體形狀的邊緣不僅有平滑的作用,而且還可以去除有噪聲產生的突刺[11]。這樣可以將我們識別出來車牌的字符部分變得更加的明顯和突出。用圖2.9對比觀察利用開運算和閉運算變換前后圖像的變化[7]。
圖1.9 黑白多態原圖
開運算和閉運算的區別程序如下:
def morphologyExTest(imgObj,imgTitle=''):
if isinstance(imgObj, str):
img = cv2.imread(imgObj)
if img is None:
img = cv2.imdecode(np.fromfile(imgObj, dtype=np.uint8), -1)
imgTitle = imgTitle+imgObj+': '
else:
imgTitle = imgTitle + ': '
kernal = cv2.getStructuringElement(cv2.MORPH_RECT ,(3,3))
imgOpen = preparePreviewImg(imgTitle+'開運算,矩形核大小3*3',cv2.morphologyEx(img, cv2.MORPH_OPEN,kernal))
imgClose = preparePreviewImg(imgTitle+'閉運算,矩形核大小3*3',cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernal))
kernal = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
imgOpen = preparePreviewImg(imgTitle + '開運算,矩形核大小5*5', cv2.morphologyEx(img, cv2.MORPH_OPEN, kernal))
imgClose = preparePreviewImg(imgTitle + '閉運算,矩形核大小5*5', cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernal))
preparePreviewImg()
圖1.10 開運算和閉運算效果圖
運行結果從圖1.10可以看出,核越大,開運算被侵蝕的前景色越多,閉運算則背景色被填充越多。但是不難看出3*3開運算和閉運算都能更加看清楚邊界細節,有利於我們處理字符的邊界時,可以更加的清晰看出字體的輪廓[12]。
2.4 卷積神經網絡
這里之說CNN(Convolutional Neural Networks,)如何進行識別,根據圖1.11可知,起初淺顯確定一個“X”圖樣,計算機認識這個“X”方法是計算機內部存儲一張規范的“X”圖片樣板,在將需要辨認的不明圖樣和規范"X"圖樣作比較,假如兩者相同,就認為不明圖樣是一個"X"圖樣。況且即使不明圖樣大概有一點平移或輕微變形,仍然可以判斷出它是一個X圖樣。這樣,CNN是把不明圖樣和規范X圖樣一個部分一個部分的作比較[13]。
圖1.11 CNN識別原理圖
卷積操作如圖1.12所示,不明圖樣的部分和規范X圖樣的部分一個一個區分時的計算流程,。計算結果是1的卷積計算示意匹配,否則示意不匹配[14]。整體來講,為了判斷一幅圖樣是含有"X"還是"O",等同於我們須要斷定它有無"X"或許"O",並且如果必須二選一,要么是"X"要么是"O"[8]。
圖1.12 CNN識別原理分析圖
圖1.13 CNN識別理想結果圖
最理想的結果是:如圖1.13所示,規范的"X"和"O",在圖像的正中間顯示,而且比例適當,沒有變形,但是就計算機而言,圖像哪怕只有輕微的有變化,就不規范。因此采用CNN來解決是種好方法。CNN的具體方法就是一塊一塊地來對比。用來對比的“小塊”叫Features(特征圖塊)。在兩幅圖中大概一樣的地方取一點粗糙的特征對比,CNN可以更明顯比較出兩幅圖的類似性[11]。
圖1.14上方的小圖就是特征圖塊,特征圖塊就像是一個帶有識別功能小圖(這里理解是一個比較小的有值的二維數組)。不同的特征圖塊分別匹配圖像中不同的特征。就像識別"X"的舉例中一樣,通過對角線和交叉線組成的特征圖塊幾乎能夠識別出大多數任何"X"圖樣[12],進而到達識別的目的。
圖1.14 CNN提取特征圖