6個步驟,告訴你如何用樹莓派和機器學習DIY一個車牌識別器!(附詳細分析)
- 2020 年 3 月 5 日
- 筆記

作者 | Robert Lucian Chiriac
翻譯 | 天道酬勤,編輯 | Carol
出品 | AI科技大本營(ID:rgznai100)
幾個月前,作者開始考慮讓汽車能夠具備檢測和識別物體的能力。他很喜歡這個主意,因為已經見識到了特斯拉的能力,並且雖然不能立即購買特斯拉(Model 3看起來越來越有吸引力了),但他認為會儘力實現自己的夢想。

預測影片的GIF,檢查結果部分,
影片地址:https://www.youtube.com/watch?v=gsYEZtecXlA
所以,他做到了。
下面,作者記錄了項目中的每個步驟。

確定項目範圍
首先要考慮這種系統應該具備的功能。如果說作者這輩子學到了什麼,那就是從小做起永遠是最好的策略:循序漸進。所以,除了顯而易見的車道保持任務(每個人都已經做過了)之外,作者想到的只是在開車時清楚地識別車牌。這個識別過程包括兩個步驟:
- 檢測車牌;
- 識別每個車牌邊框內的文本。
如果我們能夠做到這一點,那麼進行其他任務應該相當容易(如確定碰撞風險、距離等)。也許甚至可以創建一個環境的向量空間表示,這可能是一個很好的選擇。
在過多擔心細節之前,我們需要知道以下兩點:
- 一種將未標記影像作為輸入並檢測車牌的機器學習模型。
- 某種硬體。簡而言之,需要一個能鏈接到一個或多個攝像機的電腦系統來查詢我們的模型。
首先,我們來著手建立正確的對象檢測模型。

選擇正確的模型
經過認真研究,作者決定採用以下機器學習模型:
- YOLOv3——這是迄今為止最快的模型,其mAP可與其他先進模型相媲美,該模型用於檢測物體。
- 文字檢測器——用於檢測影像中的文字。
- CRNN——基本上是循環卷積神經網路(CNN)模型。卷積神經網路必須是循環的,因為它需要能夠將檢測到的字元按正確的順序排列來形成單詞。
這三個模型將如何協同工作的呢?下面是操作流程:
- 首先,YOLOv3模型在從攝像機接收的每一幀中檢測每個牌照的邊界框。建議不要非常精確地預測邊界框,包含比檢測到的物體更寬的邊界比較好。如果太窄,則可能會影響後續流程的性能。這與下面的模型相輔相成。
- CRAFT文字檢測器從YOLOv3接收裁剪的車牌。現在,如果裁剪過的幀太窄,那麼很有可能會遺漏部分車牌文字,從而預測會失敗。但是,當邊界框更大時,我們可以讓CRAFT模型檢測字母的位置。這給了我們每個字母非常精確的位置。
- 最後,我們可以將CRAFT中每個單詞的邊界框傳遞給我們的CRNN模型,來預測實際單詞。
有了的基本模型架構後,我們便可以將其轉移到硬體上了。

設計硬體
我們需要低功耗的硬體,比如樹莓派(Raspberry Pi)。它具有足夠的計算能力,可以用可觀的幀速率對幀進行預處理,並且具有Pi攝影機。Pi攝影機是樹莓派的實際相機系統。它有一個很棒的庫,而且非常成熟。
至於聯網訪問,我們可以提供一個EC25-E的4G接入,其中還嵌入了一個GPS模組。有關樹莓派接入4G網路的文章可閱讀此處:
https://www.robertlucian.com/2018/08/29/mobile-network-access-rpi/。
我們從外殼開始,將其掛在汽車的後視鏡上應該可以很好地工作,我們來設計一個由兩部分組成的支撐結構:
- 樹莓派+GPS模組+4G模組將放在後視鏡的一側。在EC25-E模組上可以查看上述文章,來查看所選擇的GPS和4G天線。
- 另一方面,通過一個帶有球形接頭的手臂來給Pi相機固定方向。
這些支援或外殼使用可靠的Prusa i3 MK3S 3D印表機列印。

圖1 樹莓派+4G/GPS防護罩的外殼

圖2 帶有球形接頭用於定向的Pi攝像機支架
圖1和圖2顯示了呈現時的結構。注意,C型支架是可插拔的,因此樹莓派的外殼和Pi相機的支援沒有與支架一起列印出來。它們有一個插座,插座上插著支架。如果有讀者決定複製該項目,這將非常有用。你們只需要調整後視鏡支架即可在汽車上工作。目前,該支架在一款路虎自由職業者的車上運作良好。

圖3 Pi 相機支撐結構的側視圖

圖4 Pi相機的支撐結構和RPi支架的前視圖

圖5 攝像機視野的富有想像力的表示

圖6 包含4G / GPS模組、Pi攝影機和樹莓派的嵌入式系統的特寫照片
顯然,這些建模需要花費一些時間,需要進行幾次迭代才能得到堅固的結構。使用PETG材料層高度為200微米,PETG可以在80-90攝氏度內很好地工作,並且對紫外線輻射的抵抗力很強,雖然不如ASA好,但強度很高。
這是在SolidWorks中設計的,因此所有的SLDPRT / SLDASM文件以及所有STL和gcode都可以在下方鏈接找到,也可以使用它們來列印你的版本。
https://www.dropbox.com/sh/fw16vy1okrp606y/AAAwkoWXODmoaOP4yR-z4T8Va?dl=0

訓練模型
一旦有了硬體,便可以開始訓練模型。
不出所料,最好不要重新發明輪子,並儘可能多地重複使用別人的工作。這就是遷移學習的全部內容——利用來自其他超大型數據集的分析。幾天前作者讀到過一個關於遷移學習非常相關案例的文章,在文章中,它談到了哈佛醫學院的一個附屬團隊,該團隊能夠對模型進行微調,來預測「從胸部X光片得出的長期死亡率,包括非癌性死亡」。他們只有一個僅50000張標籤影像的小型數據集,但是他們使用的預訓練模型(Inception-v4)訓練了大約1400萬張影像。這比最初的模型花費的訓練時間和金錢較少,然而達到的準確性仍然很高。
文章地址:
https://medium.com/m/global-identity?redirectUrl=https%3A%2F%2Ftowardsdatascience.com%2Fdeep-learning-isnt-hard-anymore-26db0d4749d7
作者也打算這樣做。
- YOLOv3
在網上可以查到很多經過預先訓練的車牌模型,但沒有預期的那麼多,但是其中有一個訓練過約3600張車牌影像。它雖然不多,但也比什麼都沒有強。此外,它還使用Darknet的預訓練模型進行了訓練。我們可以用,這是那個模型:
https://github.com/ThorPham/License-plate-detection
作者用VOTT注釋了收集的車架(當然還有車牌)。最終創建了一個由534張影像組成的小型數據集,並帶有標記為車牌的邊框。數據集鏈接如下:
https://github.com/RobertLucian/license-plate-dataset
然後,作者找到了YOLOv3網路的Keras實現。用它來訓練數據集,然後將模型預發布到這個倉庫中,以便其他人也可以使用它。在測試集中獲得的mAP為90%,考慮到數據集非常小,這已經很好了。
- CRNN&CRNN
在無數次嘗試尋找一種好的網路來識別文本之後,作者偶然發現了keras-ocr,它是CRAFT和CRNN的包和靈活的版本。並且還附帶了它們的預訓練模型。這非常好用,作者決定不對模型進行微調,並保持原樣。
最重要的是,使用keras-ocr預測文本非常簡單。基本上只是幾行程式碼。查看它們的主頁,了解其操作方法:
https://github.com/faustomorales/keras-ocr。

部署我的車牌識別器模型
這裡可以使用兩種主要的模型部署方法:
- 在本地進行所有推理。
- 在雲中進行推理。
這兩種方法都具有挑戰性。第一個意味著有一個龐大的「大腦」電腦系統,這既複雜又昂貴。第二個問題是有關延遲和基礎架構方面的挑戰,特別是使用GPU進行推理。
在本研究中,作者偶然發現了一個名為cortex的開源項目。它對遊戲來說是很新的東西,但是作為AI開發工具的下一個發展方向,確實很有意義。
基本上,cortex是一個將機器學習模型部署為生產web服務的平台。這意味著我們可以專註於自己的應用程式,而把其餘的事情留給cortex去處理。在這種情況下,它在AWS上完成所有配置,而我們唯一需要做的就是使用模板模型來編寫預測器。非常方便,只需為每個模型編寫幾十行程式碼。
這是從GitHub存儲庫中提取的終端中的cortex:https://github.com/cortexlabs/cortex 如果那不是漂亮和簡單,不知道如何該怎麼稱呼:

來源: GitHubCortex
由於自動駕駛儀不使用此電腦視覺系統,延遲對我們而言並不重要,因此我們可以使用cortex。如果它是自動駕駛系統的一部分,那麼使用通過雲提供商提供的服務並不是一個好主意,至少在現在不是。
部署帶有cortex的機器學習模型只需以下兩點:
- 定義cortex.yaml文件,這是我們API的配置文件。每個API都會處理一種任務。我們分配的yolov3 API用於檢測給定幀上車牌的邊界框,crnn API用於使用CRAFTtext檢測器和CRNN預測車牌號。
- 定義每個API的預測變數。基本上,在cortex中定義一個特定類別的預測方法以接收有效負載(所有servypart已由平台處理),使用有效負載預測結果,然後返回預測。就是這麼簡單!
這裡有一個經典iris數據集的預測器示例,但沒有詳細介紹作者是如何做到這一點的(並使本文保持適當的長度)。這兩個api的cortex實現的鏈接可以在他們的資源庫中找到:這個項目的所有其他資源都在這篇文章的末尾。
https://github.com/cortexlabs/cortex/tree/master/examples/tensorflow/license-plate-reader

然後進行預測,你只需像這樣使用curl:

預測響應看起來像是「setosa」。非常簡單!

開發客戶端
通過cortex處理我們的部署,我們可以繼續設計客戶端,這是很棘手的部分。
我們可以考慮以下架構:
- 以適當的解析度(800×450或480×270)從Pi相機以30 FPS的速度收集幀,並將每個幀放入一個公共隊列。
- 在一個單獨的過程中,我們從隊列中拉出幀,並將其分發給不同執行緒上的多個工作執行緒。
- 每個工作執行緒(或稱之為推理執行緒)都會向我們的cortexAPI發出API請求。首先,向我們的yolov3API發送請求,然後,如果檢測到任何牌照,則向我們的crnn API發送另一個請求,其中包含一批裁剪的牌照。該響應會包含文本格式的預測車牌號。
- 將每個檢測到的車牌(包含或不包含識別的文本)推入另一個隊列,最終將其廣播到瀏覽器頁面。同時,還將車牌號預測推送到另一個隊列,稍後將其保存到磁碟(csv格式)。
- 廣播隊列將接收一組無序幀。它的使用者的任務是通過在每次向客戶端廣播新幀時將它們放置在非常小的緩衝區(幾幀大小)中來對它們進行重新排序。該使用者正在另外一個進程上運行。該使用者還必須嘗試將隊列上的大小保持為指定值,以便可以以一致的幀速率(即30 FPS)顯示幀。顯然,如果隊列大小減小,則幀速率的減少是成比例的,反之亦然,當隊列大小增加時,成比例的增加。最初,作者想實現一個遲滯功能,但是意識到它會給流帶來非常起伏的感覺。
- 同時,在主進程中還有另一個執行緒正在運行,它從另一個隊列和GPS數據中提取預測。當客戶端收到終止訊號時,預測、GPS數據和時間也將轉儲到csv文件中。
下面是與AWS上的雲API相關的客戶端流程圖。

圖7 客戶端流程圖以及隨cortex設置的雲API
在我們的案例中,客戶端是樹莓派,推理請求發送到的樹莓派和雲API由cortex在亞馬遜網路服務AWS上提供。
客戶端的源程式碼也可以在其GitHub存儲庫上進行複製:
https://github.com/RobertLucian/cortex-license-plate-reader-client。
我們必須克服的一個特殊挑戰是4G的頻寬。最好減少此應用程式所需的頻寬,來減輕可能出現的掛機或對可用數據的過度使用。作者決定在Pi相機上使用非常低的解析度:480×270(我們可以使用較小的解析度,因為Pi相機的視野非常窄,因此我們仍然可以輕鬆識別車牌)。即使在此解析度下,幀的JPEG大小在10MBits時仍約為100KB。將其乘以每秒30幀,就可以得到3000KB,大約為24Mb / s,而且沒有HTTP開銷——這太大了。
相反,作者做了以下技巧:
- 將寬度減小到416像素,這正是YOLOv3模型將影像調整大小的寬度。規模顯然保持不變。
- 將影像轉換為灰度。
- 刪除了影像頂部的45%部分。他們的想法是,由於汽車不在飛行中,因此牌照不會出現在車架的頂部。據作者所知,裁剪出45%的影像不會影響預測器的性能。
- 再次將影像轉換為JPEG,但品質較低。
結果幀的大小約為7–10KB,這非常好。這相當於2.8Mb / s。但是加上所有的開銷,它大約是3.5Mb / s(包括響應)。
對於crnn API,即使沒有應用壓縮技巧,裁剪的車牌也不會花費太多。它們的大小約為2-3KB。
總而言之,要以30FPS的速度運行,推理API所需的頻寬約為6Mb / s。這個數字是我們可以接受的。

結果
通過觀看影片得知,本項目成功了,影片地址:https://youtu.be/gsYEZtecXlA。
上面的例子是通過cortex運行推理的實時示例。我需要大約20個配備GPU的實例才能順利運行。根據群集的延遲,你可能需要更多或更少的實例。從捕獲幀到將其廣播到瀏覽器窗口之間的平均等待時間約為0.9秒,考慮到推斷髮生在很遠的地方,這非常棒,這讓我們感到驚訝。
文本識別部分可能不是最好的,但至少可以證明這一點,通過提高影片的解析度,減小攝像機的視場或對其進行微調,可以使精度更高。
至於較高的GPU數量,可以通過優化減少。例如,將模型轉換為使用混合/全半精度(FP16 / BFP16)。一般而言,讓模型使用混合精度將對精度產生最小的影響,因此我們不會做太多的權衡。
T4和V100 GPU具有特殊的張量內核,這些張量內核被設計為在半精度類型的矩陣乘法上超快。在T4上,半精度加速比單精度運算的速度提高了約8倍,而在V100上,提高了10倍。這是一個數量級的差異。這意味著已轉換為使用單精度/混合精度的模型可以最多減少8倍的時間來進行推理,而在V100上則分別減少十分之一的時間。
作者沒有將模型轉換為使用單精度/混合精度,因為這超出了該項目的範圍。就作者而言,這只是一個優化問題。作者很可能會在0.14版的cortex版本發布時使用它(具有真正的多進程支援和基於隊列的自動縮放功能),因此我們也可以利用多進程的Web伺服器。
總而言之,如果實施了所有優化措施,將集群的大小從20個配備GPU的實例減少到一個實例實際上是可行的。如果進行了適當的優化,甚至不可能最大化配備單個GPU的實例。
為了使成本更加可以接受,在AWS上使用彈性推理可以將成本降低多達75%,這非常好。形象地說,你可能擁有一個管道來實時處理一個流。不幸的是,目前Cortex尚不支援彈性推理,但由於它已經應用在雷達上了,因此我們可以在不久的將來看到它的支援。
注意:YOLOv3和CRNN模型可以通過在更大的數據集(大約50–100k樣本)上進行微調來進行很多改進。到那時,甚至可以進一步減小幀的大小以減少數據使用量,而不會降低精度:「補償某處以便能夠從其他地方取走」。結合所有這些模型轉換為使用半精度類型(可能還有彈性推理),可以構成一個非常高效/具有成本效益的推理機。

更新
有了支援Web伺服器多進程工作程式的cortex版本0.14,我們能夠將yolov3 API和crnn API的GPU實例數量從8個減少到2個(在CRNN和 CRAFT模型)從12降低到10。這實際上意味著實例總數減少了40%,這是非常不錯的收益。所有這些實例都配備了單個T4 GPU和4個vCPU。
我們發現計算量最大的模型是CRAFT模型,該模型建立在具有約1.38億權重的VGG-16模型的基礎上。請記住,由於一幀中可能檢測到多個車牌,因此通常每個幀都需要進行多個推斷。這極大地增加了它的計算要求。從理論上講,應消除CRAFT模型,而應改進(微調)CRNN模型以更好地識別車牌。這樣,crnn API可以縮小很多,最多可以縮小到1或2個實例。

結論(以及5G如何適配這些)
目前,很多設備開始越來越依賴於雲計算,尤其是對於計算能力有限的邊緣設備。
而且,由於目前正在部署5G,因此從理論上講,它應該使雲距離這些計算受限的設備更近。因此,雲的影響力應隨之增長。5G網路越可靠,對於將所謂的關鍵任務(即自動駕駛汽車)的計算卸載到雲上的信心就越大。
我們可以在這個項目中一直學習的另一件事是,隨著簡化的平台的出現,事情變得如此簡單,這些簡化的平台用於在雲中部署機器學習模型。5年前,這將是一個很大的挑戰:但是現在,一個人可以在相對較短的時間內完成很多工作。
參考資源
可在此處找到3D列印支架的所有SLDPRT / SLDASM / STL / gcode :
https://www.dropbox.com/sh/fw16vy1okrp606y/AAAwkoWXODmoaOP4yR-z4T8Va?dl=0
該項目的客戶端實施可在此處找到:
https://github.com/RobertLucian/cortex-license-plate-reader-client
該項目的cortex實現在這裡找到:
https://github.com/cortexlabs/cortex/tree/master/examples/tensorflow/license-plate-reader
可在此處找到Keras的YOLOv3模型庫:
https://github.com/experiencor/keras-yolo3
可在此處找到CRAFT文本檢測器+CRNN文本識別器的庫:
https://github.com/faustomorales/keras-ocr
可在此處找到歐洲車牌的數據集(由作者的Pi相機捕獲的534個樣本組成):
https://github.com/RobertLucian/license-plate-dataset
可在此處找到Keras(license_plate.h5)和SavedModel(yolov3文件夾/zip)格式的YOLOv3模型:
https://www.dropbox.com/sh/4ltffycnzfeul01/AACe85GoIzlmjEnIhuh5JQPma?dl=0
如果有不清楚的地方或其他意見,歡迎評論告訴我們。
原文:https://towardsdatascience.com/i-built-a-diy-license-plate-reader-with-a-raspberry-pi-and-machine-learning-7e428d3c7401
(*本文由 AI 科技大本營編譯,轉載請聯繫微信1092722531)
【end】