FakeLPR車牌識別(2) ----- 車牌角點定位

介紹

前面一篇文章介紹了我這個 FakeLPR 大體的框架,基本上可歸納爲三步

1.粗定位

2.角點檢測矯正

3.端到端識別字符

 

第一步粗定位不需要特別準,能大體定位到就可以了,因爲後面會把粗定位的結果按比例擴展,擴展出來的圖包含了車牌在裏面,要比粗定位結果大上幾圈,以便於檢測車牌角點。

本項目中沒有訓練車牌的粗定位模型,直接使用了 HyperLPR 的粗定位模型及相關代碼。https://github.com/zeusees/HyperLPR

粗定位模型可以自行替換,自己訓練個ssd,mobilenet-ssd,mtcnn都可以

 

本文主要介紹第二步,角點檢測,模型主要思路是將定位問題轉換爲分類問題,利用 caffe 實現多標籤分類來定位車牌角點


主要步驟

1.先生成車牌角點檢測的訓練數據和lmdb文件

# 從項目主目錄裏
cd train/datasets

# 生成角點檢測訓練數據
python creat_keypoint_data.py

# 生成角點檢測lmdb文件
python creat_keypoint_lmdb.py

注:要是某個包導不進去,先註釋掉試試,可能是我 import 多了,後同

2.啓動訓練

# 從項目主目錄裏
cd train

# 需要caffe環境
sh ./train_keypoint.sh

以上兩步就可以訓練出角點檢測模型,模型文件保存在 .../FakeLPR/train/keypoint_snapshot

下面詳細介紹一下


生成車牌數據

進入本項目文件夾,cd 到 train/datasets 文件夾,所有的生成數據都會在這個 datasets  文件夾下面進行

# 項目目錄裏
cd train/datasets

運行  creat_keypoint_data.py 生成角點檢測訓練數據

# 生成角點檢測訓練數據
python creat_keypoint_data.py

生成出來的文件夾有兩個 keypoint_train_data 和 keypoint_test_data ,分別是訓練和測試用,以 keypoint_train_data 爲例

keypoint_train_data/data 下保存的是生成的圖片,圖片生成出來的樣子是這樣的,尺寸爲 [748,280] 

生成出來的數據保存在 keypoint_train_data/plate.db 當中,數據結構如下

表名都叫 train,要看的話就

select * from train;

filename是主鍵,其他4個點就是八個數,分別保存,LU就是left UP,以此類推

 

其他說明

這個圖片生成腳本主要分三個部分

第一個 class 生成一張藍底的普通車牌的

第二個 class 對普通車牌進行隨機變換,變得更像真的,變換部分代碼參考了 Hyperlpr 的一個車牌變換程序

https://github.com/LCorleone/hyperlpr-train_e2e/blob/master/PlateCommon.py

最後一個就是隨機生成車牌字符。

 

你可以在 creat_keypoint_data.py 的 main 函數中修改你需要生成的數據數量,

後面的 e2e 檢測也是基於這裏的數據來的,你可以多弄一些,不過生成速度堪憂

# 根據自己的需求設置
def main():

    ############# 生成圖片數 ############
    creat_train_num = 100000
    creat_test_num = 1000
    #####################################

 

對於中文顯示和保存的問題,取了個折中的辦法,用拼音,拼音和省份的轉換工具在腳本也有,在class Tool 中

province_change = [
        [u"京",'jing'], [u"滬",'hu'], [u"津",'jin'], [u"渝",'yu'], [u"冀",'jii'], [u"晉",'jinn'], 
        [u"蒙",'meng'], [u"遼",'liao'], [u"吉",'ji'], [u"黑",'hei'], [u"蘇",'su'], [u"浙",'zhe'], 
        [u"皖",'wan'],  [u"閩",'min'], [u"贛",'gann'], [u"魯",'lu'], [u"豫",'yuu'], [u"鄂",'e'], 
        [u"湘",'xiang'], [u"粵",'yue'], [u"桂",'gui'], [u"瓊",'qiong'], [u"川",'chuan'], [u"貴",'guii'], 
        [u"雲",'yun'], [u"藏",'zang'],[u"陝",'shan'], [u"甘",'gan'], [u"青",'qing'], [u"寧",'ning'], 
        [u"新",'xin'] ]

生出角點檢測 LMDB 文件

生成完數據,現在要生成用於 caffe 訓練的 LMDB 文件,這裏要先講一下這個模型思路

其實很簡單,將定位問題轉換爲一個分類問題,再用多標籤分類實現,我會將訓練圖像數據壓縮到 [90,30] ,以寬爲例,角點的y座標經過壓縮就在 [0,29] 之間,分類模型的輸出設爲30類,就能得到y座標了。一共有4個點8個座標,如此反覆8次就得到了4個角點的座標,實驗結果在生成數據集上效果很好,而且這還有一個優點,就算沒有準確分到那個類上,在準確值附近也是可以,類數越多定位越精確

本來這個思路需要8個模型,但是使用多標籤分類的辦法就可以一個模型搞定

另一個問題是 caffe 不支持多標籤分類,如果不換框架的話網上的辦法基本是改 caffe 源碼,做hdf5文件或者用兩個lmdb+Slice Laye的方法,因爲我是在服務器上運行,源碼改不了,hdf5又存在一個內存佔用大的問題,所以用了兩個lmdb+Slice Laye的方法來做 caffe 多標籤分類,後面的端到端識別模型也是如此

 

運行  creat_keypoint_lmdb.py 生成角點檢測訓練用的兩個lmdb文件

# 生成角點檢測lmdb文件
python creat_keypoint_lmdb.py

生成的 lmdb 文件存在 .../FakeLPR/train/datasets/lmdb 文件夾下,兩個 lmdb 分別對應着數據和標籤

 

其他說明

多標籤的 LMDB 生成代碼參考自

https://blog.csdn.net/u013010889/article/details/53098346

 

這個腳本分兩步,第一步會先讀取 plate.db 文件,將需要的數據處理後,生成爲一個 keypoint_label.txt 保存數據,txt 裏面的格式爲

就是文件名和4個點的座標,順序是左上,右上,左下,右下

然後再讀取 txt 中的數據生成兩個 LMDB

爲什麼不連在一起,這樣做是因爲方便從其他形式來導入數據訓練,假如有小夥伴搞到了1w真實車牌的角點數據,就可以按照 txt 中的數據格式導,直接就能導成 LMDB文件了

    # 生成lmdb文件的兩步
    def get_lmdb(self,db_path,img_path,pause):
        self.writeTXT_from_db(db_path,img_path) # db文件到txt文件
        self.totwolmdb(img_path,pause)  # 生成 LMDB 的

如果要自己弄數據,要注意的點座標的比例變換,圖片尺寸到類的比例要根據原圖和類的比例來,例如我的,生成時是 [748,280],目標是 [90,30],所以座標轉換代碼是

    def resize_point(self,line):
        # 你的源圖片寬高
        # 可以讀取圖片來確定shape
        src_w = 748
        src_h = 280

        dst_w = 90
        dst_h = 30

        scale_x = float(dst_w)/float(src_w)
        scale_y = float(dst_h)/float(src_h)

        out_line = []
        for i in range(1,9,2):
            out_line.append(float(line[i]) * scale_x)
            out_line.append(float(line[i+1]) * scale_y)

        return out_line

訓練

生成完就可以訓練了

啓動訓練

# 從項目主目錄裏
cd train
sh ./train_keypoint.sh

模型文件保存在  .../FakeLPR/train/keypoint_snapshot


模型調用

這沒什麼好說的,代碼在 .../FakeLPR/py2/keypoint.py 中

檢測是用 opencv 的 dnn 模塊直接調用

    def opencv34_test(self,ex_plate):
        ex_plate = cv2.cvtColor(ex_plate, cv2.COLOR_BGR2RGB)
        inputBlob = cv2.dnn.blobFromImage(ex_plate,1,(90, 30),(104, 117, 123))
        self.kp_net.setInput(inputBlob)

        # 取出prob層結果
        result_point = []
        for i in range(1,9,2):
            probx = self.kp_net.forward('prob_'+str(i))
            proby = self.kp_net.forward('prob_'+str(i+1))
            result_point.append([probx.argmax(),proby.argmax()])
        return result_point

再根據結果來透視變換,得到矯正車牌

    def warp(self,star_points,src_img):
        # 目標尺寸
        height = 35
        width = 110 

        pts1 = np.float32([star_points[0],star_points[1],star_points[2],star_points[3]])
        pts2 = np.float32([[0,0],[width,0],[0,height],[width,height]])  
        M = cv2.getPerspectiveTransform(pts1,pts2)  
        dst = cv2.warpPerspective(src_img,M,(width,height))  

        return dst

下一篇:FakeLPR車牌識別(3) ----- 車牌端到端識別

 

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