PyTorch實現的MTCNN/LPRNet車牌識別

這是一個在MTCNN和LPRNet中使用PYTORCH的兩階段輕量級和健壯的車牌識別。

MTCNN是一個非常著名的實時檢測模型,主要用於人臉識別。修改後用於車牌檢測。LPRNet是另一種實時的端到端DNN,用於模糊識別.該網絡以其優越的性能和較低的計算成本而不需要初步的字符分割。在這項工作中嵌入了Spatial Transformer Layer(空間變換層 LocNet),以便有更好的識別特性。

在Nivida Quadro P4000上使用該結構在CCPD數據集上能達到~ 80 ms/image的速度,識別準確率可達99%。下面是流程框架:

MTCNN

MTCNN 基礎知識

MTCNN 一開始主要是拿來做人臉識別的(不知道現在還是不是,希望大佬可以分享最新的人臉識別網絡)。MTCNN人臉檢測是2016年的論文提出來的,MTCNN的“MT”是指多任務學習(Multi-Task),在同一個任務中同時學習”識別人臉“、”邊框迴歸“、”人臉關鍵點識別“。

  1. 首先對test圖片不斷進行Resize,得到圖片金字塔。按照resize_factor(如0.70,這個具體根據數據集人臉大小分佈來確定,基本確定在0.70-0.80之間會比較合適,設的比較大,容易延長推理時間,小了容易漏掉一些中小型人臉)對test圖片進行resize,直到大等於Pnet要求的1212大小。這樣子你會得到原圖、原圖resize_factor、原圖*resize_factor2…、原圖*resize_factorn(注,最後一個的圖片大小會大等於12)這些不同大小的圖片,堆疊起來的話像是金字塔,簡單稱爲圖片金字塔。注意,這些圖像都是要一幅幅輸入到Pnet中去得到候選的。
  1. 圖片金字塔輸入Pnet,得到大量的候選(candidate)。根據上述步驟1得到的圖片金字塔,將所有圖片輸入到Pnet,得到輸出map形狀是(m, n, 16(2+4+10))。根據分類得分,篩選掉一大部分的候選,再根據得到的4個偏移量對bbox進行校準後得到bbox的左上右下的座標,對這些候選根據IOU值再進行非極大值抑制(NMS)篩選掉一大部分候選。詳細的說就是根據分類得分從大到小排,得到(num_left, 4)的張量,即num_left個bbox的左上、右下絕對座標。每次以隊列裏最大分數值的bbox座標和剩餘座標求出iou,幹掉iou大於0.6(閾值是提前設置的)的框,並把這個最大分數值移到最終結果。重複這個操作,會幹掉很多有大量overlap的bbox,最終得到(num_left_after_nms, 16)個候選,這些候選需要根據bbox座標去原圖截出圖片後,resize爲24*24輸入到Rnet。
  1. 經過Pnet篩選出來的候選圖片,經過Rnet進行精調。根據Pnet輸出的座標,去原圖上截取出圖片(截取圖片有個細節是需要截取bbox最大邊長的正方形,這是爲了保障resize的時候不產生形變和保留更多的人臉框周圍細節),resize爲24*24,輸入到Rnet,進行精調。Rnet仍舊會輸出二分類one-hot2個輸出、bbox的座標偏移量4個輸出、landmark10個輸出,根據二分類得分幹掉大部分不是人臉的候選、對截圖的bbox進行偏移量調整後(說的簡單點就是對左上右下的x、y座標進行上下左右調整),再次重複Pnet所述的IOU NMS幹掉大部分的候選。最終Pnet輸出的也是(num_left_after_Rnet, 16),根據bbox的座標再去原圖截出圖片輸入到Onet,同樣也是根據最大邊長的正方形截取方法,避免形變和保留更多細節。
  1. 經過Rnet幹掉很多候選後的圖片輸入到Onet,輸出準確的bbox座標和landmark座標。大體可以重複Pnet的過程,不過有區別的是這個時候我們除了關注bbox的座標外,也要輸出landmark的座標。(有小夥伴會問,前面不關注landmark的輸出嗎?嗯,作者認爲關注的很有限,前面之所以也有landmark座標的輸出,主要是希望能夠聯合landmark座標使得bbox更精確,換言之,推理階段的Pnet、Rnet完全可以不用輸出landmark,Onet輸出即可。當然,訓練階段Pnet、Rnet還是要關注landmark的)經過分類篩選、框調整後的NMS篩選,好的,至此我們就得到準確的人臉bbox座標和landmark點了,任務完滿結束。

MTCNN車牌檢測

這項工作只使用proposal net(Pnet)和output net(Onet),因爲在這種情況下跳過Rnet不會損害準確性。Onet接受24(高度)x94(寬度)bGR圖像,這與LPRNet的輸入一致。

修改後的MTCNN結構如下:

LPRNet

LPRNet全程就叫做License Plate Recognition via Deep Neural Networks(基於深層神經網絡的車牌識別)。LPRNet由輕量級的卷積神經網絡組成,所以它可以採用端到端的方法來進行訓練。據我們所知,LPRNet是第一個沒有采用RNNs的實時車牌識別系統。因此,LPRNet算法可以爲LPR創建嵌入式部署的解決方案,即便是在具有較高挑戰性的中文車牌識別上。

LPRNet特性

  1. 實時、高精度、支持車牌字符變長、無需字符分割、對不同國家支持從零開始end-to-end的訓練;
  2. 第一個不需要使用RNN的足夠輕量級的網絡,可以運行在各種平臺,包括嵌入式設備;
  3. 魯棒,LPRNet已經應用於真實的交通監控場景,事實證明它可以魯棒地應對各種困難情況,包括透視變換、鏡頭畸變帶來的成像失真、強光、視點變換等。

LocNet

首先,輸入圖像由空間變換層(Spatial Transformer Layer)預處理 LocNet 這是對檢測到的車牌形狀上的校正,使用 Spatial Transformer Layer(這一步是可選的),但用上可以使得圖像更好得被識別。

下面是他的效果圖,看起來是不是很舒服。

LPRNet的基礎構建模塊

LPRNet的基礎網絡構建模塊受啓發於SqueezeNet Fire Blocks和Inception Blocks,如下圖所示。

特徵提取骨幹網絡架構

骨幹網將原始的RGB圖像作爲輸入,計算得到空間分佈的豐富特徵。爲了利用局部字符的上下文信息,該文使用了寬卷積(1×13 kernel)而沒有使用LSTM-based RNN。骨幹網絡最終的輸出,可以被認爲是一系列字符的概率,其長度對應於輸入圖像像素寬度。

由於解碼器的輸出與目標字符序列長度不同,訓練的時候使用了CTC Loss,它可以很好的應對不需要字符分割和對齊的end-to-end訓練。

爲了進一步地提升模型的表現,增強解碼器所得的中間特徵圖,採用用全局上下文關係(global context)進行嵌入。它是通過全連接層對骨幹網絡的輸出層進行計算,隨後將其平鋪到所需的大小,最後再與骨幹網絡的輸出進行拼接 , 加入GAP思想源於Parsenet。下圖爲加入GAP拼接到feature map上進行識別的表示。

CCPD數據集

CCPD(中國城市停車數據集,ECCV)和PDRC(車牌檢測與識別挑戰)。這是一個用於車牌識別的大型國內的數據集,由中科大的科研人員構建出來的。發表在ECCV2018論文Towards End-to-End License Plate Detection and Recognition: A Large Dataset and Baseline

https://github.com/detectRecog/CCPD

該數據集在合肥市的停車場採集得來的,採集時間早上7:30到晚上10:00.涉及多種複雜環境。一共包含超多25萬張圖片,每種圖片大小720x1160x3。一共包含9項。每項佔比如下:

CCPD- 數量/k 描述
Base 200 正常車牌
FN 20 距離攝像頭相當的遠或者相當近
DB 20 光線暗或者比較亮
Rotate 10 水平傾斜20-25°,垂直傾斜-10-10°
Tilt 10 水平傾斜15-45°,垂直傾斜15-45°
Weather 10 在雨天,雪天,或者霧天
Blur(已刪除) 5 由於相機抖動造成的模糊(這個後面被刪了)
Challenge 10 其他的比較有挑戰性的車牌
NP 5 沒有車牌的新車

數據標註:

文件名就是數據標註。eg:

025-95_113-154&383_386&473-386&473_177&454_154&383_363&402-0_0_22_27_27_33_16-37-15.jpg

由分隔符-分爲幾個部分:

  1. 025爲區域,

  2. 95_113 對應兩個角度, 水平95°, 豎直113°

  3. 154&383_386&473對應邊界框座標:左上(154, 383), 右下(386, 473)

  4. 386&473_177&454_154&383_363&402對應四個角點座標

  5. 0_0_22_27_27_33_16爲車牌號碼 映射關係如下: 第一個爲省份0 對應省份字典皖, 後面的爲字母和文字, 查看ads字典.如0爲A, 22爲Y…

provinces = ["皖", "滬", "津", "渝", "冀", "晉", "蒙", "遼", "吉", "黑", "蘇", "浙", "京", "閩", "贛", "魯", "豫", "鄂", "湘", "粵", "桂", "瓊", "川", "貴", "雲", "藏", "陝", "甘", "青", "寧", "新", "警", "學", "O"]
 
ads = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'O']
  1. 37亮度

  2. 15模糊度

所以根據文件名即可獲得所有標註信息。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章