基於easyPR和openalpr的車牌識別研究

主題 概要
車牌識別 車牌識別流程及算法
編輯 時間
新建 20161216
序號 參考資料
1 https://github.com/openalpr/openalpr
2 https://github.com/liuruoze/EasyPR
3 學習openCV,Cary Bradski,清華大學出版社
4 http://www.cnblogs.com/subconscious/
5 基於子區域投影分析的車牌傾斜校正,馬洪霞,計算機應用與軟件

業餘時間研究車牌識別近半年,接手之前沒想到這麼難,最後批量識別效果大概只有60%,只能做一個測試版。希望現場環境搭建起來後,採集更多樣本,能夠不斷迭代優化。總之,就是不要放棄。欣慰的是幾經努力,在PC機上,單張圖片的識別速度保證了在1s以內,0.5s左右。下面把整個識別過程、算法思路回顧總結一遍。
在此之前,特別感謝easyPR和openalpr的作者,可以說我只是一個代碼的搬運工,讓我從完全沒有openCV的知識背景,能夠快速起步。

應用場景及目錄結構

小區、停車場車牌自動識別。
C#寫的窗體程序做爲管理系統,接收攝像機傳來的圖片。車牌識別部分用c++完成,編譯爲一個dll,每當C#收到一張圖片,就調用這個dll,傳入圖片並返回識別結果。

程序的目錄結構:
dir

exe中是C#的exe程序和車牌識別dll及依賴的其他動態庫;log目錄保存識別過程日誌;etc目錄配置log選項及easyPR中帶有的一些配置;resources目錄保存調試模式時產生的中間圖片,及ocr、cascade訓練後的模型。另外,easypr中的ann和svm模型也放在此目錄裏面,但暫時已經沒有使用。

下面通過一組調試過程的中間圖片,詳解各個識別過程。

車牌定位

車牌定位過程實際上綜合了openalpr和easypr的過程,分爲粗略定位和精確定位兩部分。
粗略定位應用人臉識別技術(cascade)+形態學操作得到粗略的車牌,此時的車牌區域會比真正的車牌大些,包含了沒法區分的背景。而且只是經過很粗放的旋轉操作,存在水平傾斜及垂直錯切的情況。需要更進一步的精確定位。

粗略定位

這是傳遞過來的原始圖片,注意箭頭所指的文字會對cascade定位產生干擾,所以進行了瘦身處理,去掉字符。
這裏寫圖片描述
去掉字符,對上下邊界簡單的去掉10個像素:
這裏寫圖片描述
應用cascade定位後,得到兩個結果:
這裏寫圖片描述這裏寫圖片描述
可以看到這兩個車牌範圍都太大,而且傾斜嚴重。對得到cascade的結果應用easyPR裏面的sobel定位進行二次定位,在sobel定位無法得到結果時,再用顏色定位進行二次定位。應用sobel定位效果如下:
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
可以看到,成功把範圍縮小,但水平傾斜嚴重。這裏會先進行一次粗略的旋轉,並同時進行一次車牌校驗。思路是對車牌二值化後進行取輪廓操作,剔除掉不合理的輪廓後,如果合理的輪廓個數滿足大於2個,則認可是一張車牌。另外,計算穿過輪廓中心的直線斜率,可以粗略確定需要旋轉的角度。

如下圖所示,找到了6個合理的字符,並且根據第一個字符矩形和最後一個字符矩形中心的位置來計算旋轉角度。
這裏寫圖片描述
經過粗略旋轉後:
這裏寫圖片描述
可以看到,水平方向雖然旋轉了,但產生了透視,而且垂直方向是傾斜的。會影響後面的字符分割和OCR識別,因此還要進一步的精確處理。

精確定位

精確定位需要做兩件事情,一是對車牌進行更可靠的水平旋轉。因爲上面計算旋轉角度的方法不可靠,如果根據取輪廓沒找到合適的字符矩形,就沒法計算旋轉角度,而且就算計算出來了,精度也不高。這裏水平校正採用仿射變換的方式,因爲我發現openalpr裏面用於尋找字符上下邊界的算法十分可靠,可以看下找到了字符的上下邊界的mask,根據四個轉角點,就能仿射到一個固定此寸的大小。
這裏寫圖片描述
仿射變換後的車牌:
這裏寫圖片描述
初步看來,與上面經過粗略水平旋轉的車牌沒什麼兩樣。其實只是這張車牌粗略水平旋轉時,效果很好的特例。總體來看,這一步還是有必要的。
在水平旋轉變換後,車牌字符仍然是垂直傾斜的,爲了進行垂直校正,想了很多方法來求垂直傾斜角度,但魯棒性都不高。
最後參考了一篇論文:《基於子區域投影分析的車牌傾斜校正》,就是前面參考資料5提到的。實現了其中的垂直校正部分,校果很好。基本思路是,把車牌水平劃分成幾個子區域。然後求每個子區域的投影。投影只需求一次,然後用一個微小的增量來迭代尋優垂直傾斜角度,具體可參考本篇論文。

知道了垂直傾斜角度,下面就能求車牌的四個轉角點,然後再進行一次仿射變換。爲了解決上面出現的透視的情況,打算用霍夫變換求取上下水平邊界,用垂直投影法來確定左右邊界。
理想的經過霍夫變換後,上下邊界應該是像這張車牌一樣:
這裏寫圖片描述
但霍夫變換,不能都成功的找到上下邊界,像這張車牌求取上下邊界的效果:
這裏寫圖片描述
取到的下邊界太短,而且不能嚴格貼着車牌邊緣,也就很難解決透視問題了。
垂直邊緣求取垂直方向的直方圖來確定,延長水平邊緣與垂直邊緣,它們的交點就確定了車牌的四個轉角,如下圖:
這裏寫圖片描述
求垂直邊緣時候,根據垂直投影可以確定最左與最右的邊界,再加上前面計算出來的垂直傾斜角度,就能推算出邊緣。
仿射變換後,得到最終定位出來的車牌:
這裏寫圖片描述
由於背景的干擾,垂直邊界通常都不精確,後續分割字符的時候,需要對邊緣部分進行過濾。實際上這部分是對openalpr改動最大的部分,openalpr沒有進行水平校正,也沒進行垂直校正,直接應用霍夫變換求水平邊緣和垂直邊緣來求四個轉角點。但實踐發現,效果比較差,因爲很多時候都沒法找出垂直邊緣。

字符分割與識別

字符分割部分,根據openalpr的方法沒有太多變動。但是因爲中文字符的存在,還是做了很多調整。
主要有三點:
1.對於邊緣的過濾
這裏寫圖片描述
可以看到,雲字左邊的字符,應該被過濾掉。採取的思路是,如果第一個字符的寬度比第二個字符小70%或者比平均寬度大了1.3倍,都可認爲是邊緣。如果通過寬度不能過濾,就根據位置過濾,因爲先驗知識,第二個字符與第三個字符的距離會比較大。通過這樣,一般都能過濾。而右邊的字符,不需過濾,只要取前面7個字符就行了。
2.對於字符的合併
漢字具有左右結構,甚至左中右結構(如川),因此需要進行兩次合併,如果相鄰的字符寬度加起來小於平均字符寬度的1點幾倍,則可接受爲一個字符。但要注意,像上面最右邊的3和像1的邊緣可能合併成一個字符,因此合併的寬度要合理選取。
3.輪廓過濾時漢字要特殊處理
對於二值化後的車牌,可通過校驗輪廓的方法去除燥點或污染點,進行清除操作。清除前:
這裏寫圖片描述
清除後:
這裏寫圖片描述
可以看到雲字的上面短橫被去掉了,類似的,如果其它左右結構(如浙),小點也會被去掉。如果只是單純降低清除的範圍,雖然可以保留這些小點,但清除的效果就大打折扣了,因此需特殊處理。
解決方法是,把清除操作前和清除操作後的圖片都保留起來。最後漢字從清除前的圖片複製到另一張圖片,數字和字母則從清除後的圖片複製。這樣就重新集成起來,並得到一張比較乾淨的車牌。
這裏寫圖片描述
這張車牌就可進行OCR識別。分割後的效果:
這裏寫圖片描述 這裏寫圖片描述 這裏寫圖片描述 這裏寫圖片描述 這裏寫圖片描述 這裏寫圖片描述 這裏寫圖片描述
字符識別部分,是用的tesseract庫,很多人說用OCR來識別車牌字符這種字體,效果會不好。我沒試過其他方法,但想來openalpr採用了這種方法,只要分割出來的字符足夠清晰,
訓練得足夠好,應該還是可以接受的。實際上B和8,D和0這種字符確實也很易識別錯誤,後面還需想辦法提高。
Tesseract的訓練方法可以參考我的上篇博客《Tesseract-OCR字符訓練工具及方法》。

總結

目前來看,影響車牌識別的還有三個問題要解決:
一是用cascade進行車牌探測,速度很快,但是存在漏檢的情況。不知是我訓練時樣本不夠多的原因,還是其他。白天、夜間的也訓練了2萬多張,但還是可能漏檢。
二是二值化效果,應用OSTU和Niblack進行二值化,但是存在字符和背景不能分離的情況。
三是OCR的識別準確率,需要再想辦法提高。或者用其它的識別方法代替。

發佈了38 篇原創文章 · 獲贊 29 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章