建立即時車牌偵測和辨識應用程式

作者 NVIDIA Developer

針對靜止或快速移動的車輛進行自動車牌辨識(automatic license plate recognition,ALPR),是智慧城市常見的智慧影像分析應用之一。部分常見的使用案例,包括停車輔助系統、自動化收費站、在港口以及醫療物資運輸倉庫中登記與識別運輸和物流車輛。可以即時執行上述應用是讓這些市場充分發揮潛力的關鍵。傳統技術是仰賴專用攝影機和處理硬體,不僅需要高昂的部署成本,且難以維護。

ALPR 的工作流程涉及使用物件偵測深度學習模型,偵測畫格中的車輛,以及使用車牌偵測模型定位車牌,最後辨識車牌上的字元。使用深度學習網路進行光學字元辨識(optical character recognition,OCR)為常用技術,可以辨識任何語言的字元。

本文說明如何將車牌偵測(license plate detection,LPD)車牌辨識(license plate recognition,LPR)等能實際部署的 AI 模型與 NVIDIA 轉移學習工具套件(TAO Toolkit)搭配使用。現成模型可以讓您快速啟動 ALPR 專案。使用 DeepStream SDK 可以輕鬆部署產生的 TLT 最佳化模型。


影片:即時車牌辨識。

在開始建立和部署 TLT 中高準確率的預先訓練模型時,需要以下資源:

所有的預先訓練模型,都可以從 NVIDIA NGC 免費下載。TLT 提供兩種 LPD 模型和兩種 LPR 模型:一種在美國車牌上接受訓練,以及一種在中國車牌上接受訓練。若需要更多資訊,請參閱 LPD 和 LPR 模型卡。

圖 1:即時車牌辨識應用程式的 ALPR 應用程式工作流程。

透過 tlt-launcher 介面,使用 TLT 進行訓練。想要執行 TLT 啟動器時,請使用 ~/.tlt_mounts.json 檔案,將本機電腦上的 ~/tlt-experiments 目錄對映至 Docker 容器。若需要更多資訊,請參閱 TLT 啟動器

安裝 TLT 啟動器:

pip3 install nvidia-pyindex
pip3 install nvidia-tlt

建立 ~/.tlt_mounts.json 檔案,並加入以下內容:

{
    "Mounts": [
        {
            "source": "/home//tlt-experiments",
            "destination": "/workspace/tlt-experiments"
        },
        {
            "source": "/home//openalpr",
            "destination": "/workspace/openalpr"
        }

    ]
}

將本機電腦上的路徑 /home/<username>/tlt-experiments,裝載成容器內的路徑 /workspace/tlt-experiments。此外,將本機電腦上的路徑 /home/<username>/openalpr,裝載成容器內的路徑 /workspace/openalpr

車牌偵測

本節逐步講解了如何從 NGC 取得經過預先訓練的美國 LPD 模型,並使用 OpenALPR 資料集微調模型。

資料集

使用 OpenALPR 基準做為實驗資料集。從 NGC 取得 LPD 預先訓練模型,並在 OpenALPR 資料集上進行微調。

演算法簡介

LPD 模型是以來自 TLT 的 Detectnet_v2 網路為基礎。訓練演算法最佳化網路,以減少物件的定位和信賴度損失。

訓練分為兩個階段進行。在第一階段,使用正則化訓練網路,以方便進行修剪。在第一階段之後,修剪網路,刪除核心範數低於修剪閾值的通道。在第二階段,重新訓練修剪後的網路。第二階段不包含正規化。

訓練 LPD 模型

建立 NVIDIA NGC 帳戶,並安裝 TLT 啟動器。想要微調 LPD 模型時,請從 NGC 下載 LPD notebook。然後,下載 NGC LPD 預先訓練模型(usa_unpruned.tlt)。

準備資料集

首先,使 OpenALPR 基準同步:

$ git clone https://github.com/openalpr/benchmarks benchmarks

其次,執行以下命令,以下載資料集,並調整影像/標籤大小。下載 lpd_prepare_data.py

$ python lpd_prepare_data.py --input_dir benchmarks/endtoend/us --output_dir  lpd  --target_width  640 --target_height 480

將資料分成兩個部分:80% 用於訓練,20% 用於驗證。執行以下命令,以隨機分割資料集以及產生 tfrecord。此命令是使用稱為 SPECS_tfrecord.txt 的規格檔案。

$ tlt detectnet_v2 dataset_convert -d /workspace/openalpr/SPECS_tfrecord.txt -o /workspace/openalpr/lpd_tfrecord/lpd

配置規格檔案

在準備資料集之後下載訓練規格,以配置訓練參數。使用規格檔案中的 pretrained_model_file 參數,為 LPD 指定 NGC 預先訓練模型。將批次大小設為 4,並執行 120 期訓練。每隔 10 期,使用驗證集評估訓練模型。

訓練

執行以下命令,開始在 OpenALPR 資料上微調:

$ tlt detectnet_v2 train -e /workspace/openalpr/SPECS_train.txt -r /workspace/openalpr/exp_unpruned -k nvidia_tlt

在完成訓練後會看到以下紀錄,顯示出驗證集的平均精度(average precision,AP):

class name      average precision (in %)
------------  --------------------------
lpd                     82.2808

在訓練後也可以修剪經過訓練的模型,以縮小模型。本文章不示範修剪。若需要更多資訊,請參閱修剪模型

匯出模型

在訓練之後匯出模型,以進行部署。部署格式為 .etlt 或加密 TLT。使用金鑰為匯出的模型加密,並在部署期間使用該金鑰為模型解密。

想要使用 INT8 精度執行推論時,也可以在模型匯出步驟中產生 INT8 校正表。在 DeepStream SDK 中可以直接使用加密 TLT。

想要以 INT8 匯出 LPD 模型時,請使用以下命令。此命令會先使用 –cal_image_dir 選項指定的校正影像,校正 INT8 模型。此模型的加密金鑰是由 -k 選項指定,其可以是任何字串。匯出的 .etlt 檔案和校正快取,是分別由 -o 和 –cal_cache_file 選項指定。欲深入瞭解模型匯出的所有選項,請參閱 TLT DetectNet_v2 文件

$ tlt detectnet_v2 export -m /workspace/openalpr/exp_unpruned/weights/model.tlt -o /workspace/openalpr/export/unpruned_model.etlt --cal_cache_file /workspace/openalpr/export/calibration.bin -e /workspace/openalpr/SPECS_train.txt -k nvidia_tlt --cal_image_dir /workspace/openalpr/lpd/data/image --data_type int8 --batch_size 4 --batches 10 –-engine_file /workspace/openalpr/export/unpruned_int8.trt

已訓練 LPD 模型的準確率

預先訓練模型為在您的資料集上進行訓練和微調,提供極佳的起點。我們訓練了兩個模型,以進行比較:第一個模型是使用 LPD 預先訓練模型進行訓練,第二個模型則是從零開始訓練。下表為兩個模型的平均精度均值(mAP)比較。使用預先訓練模型,可以透過更小的資料集,更快達到目標精度。如果從零開始訓練,則需要較大的資料集,且必須執行更長的時間,才能達到相同的精度。

您可以在 TLT Docker 中使用以下命令,在實驗配置檔中指定的驗證資料集上執行評估:

$ tlt detectnet_v2 evaluate -m /workspace/openalpr/exp_unpruned/weights/model.tlt -k nvidia_tlt -e /workspace/openalpr/SPECS_train.txt
模型 Epochs 批次大小 mAP
LPD:從零開始訓練 120 4 53.11%
LPD:微調預先訓練模型 120 4 82.28%
表 1:使用預先訓練模型與從零開始訓練的準確率。

車牌辨識

本節將詳細探討 LPR 模型訓練。NVIDIA 提供了在美國車牌和中國車牌上訓練的 LPRNet 模型。您可以在模型中找到這些模型的詳細資訊。下一節將使用在美國車牌上訓練的 LPRNet,做為微調的起點。

資料集

您也可以在 OpenALPR 美國影像資料集上訓練和評估 LPRNet。將其分成 80%(177 張影像)用於訓練,20%(44 張影像)用於驗證。

演算法簡介

在車牌辨識任務方面,可以在車牌影像的序列中預測字元。如同其他電腦視覺任務,首先是擷取影像特徵。利用廣泛採用之 DNN 架構(例如 ResNet 10/18)做為 LPRNet 的骨幹。ResNet 網路的原始跨度為 32,但是為了能更適用於車牌影像的空間大小,請將跨度從 32 調整成 4。然後,將影像特徵傳送至分類器。不同於一般的影像分類任務(模型僅為一張影像提供單一類別 ID),LPRNet 模型會產生類別 ID 的序列。將影像特徵沿著水平方向分成多個片段,在預測中為各個片段分配字元 ID。

最後,使用連接時間分類(connectionist temporal classification,CTC)損失,訓練此序列分類器。訓練演算法最佳化網路,以減少車牌的真值字元序列與預測字元序列之間的 CTC 損失。

基本上,LPRNet 是具有已調整 ResNet 骨幹的序列分類模型。它是以影像做為網路輸入,並產生序列輸出。之後,使用以貪婪解碼方法為基礎的 CTC 解碼器,從序列輸出中將車牌解碼。

圖 2:LPR 模型架構。

訓練 LPR 模型

使用 TLT 訓練 LPRNet,無須自行開發程式碼。僅需要準備資料集、設定實驗配置,然後執行命令即可。

準備資料

在本機電腦的 /home/<username>/tlt-experiments/ 路徑中處理資料,並將 Docker 中的對映路徑使用於 tlt-launcher。首先,從 openalpr/benchmarks 複製 OpenALPR 基準:

$ git clone https://github.com/openalpr/benchmarks benchmarks

接著,使用 preprocess_openalpr_benchmark.py script 預處理下載的資料集,並分成訓練/驗證。

$ python preprocess_openalpr_benchmark.py --input_dir=./benchmarks/endtoend/us --output_dir=./data/openalpr

在預處理之後,OpenALPR 資料集是採用 TLT 需要的格式。每一張裁切後的車牌影像,都具有對應的標籤文字檔,包含車牌影像的真值。同時建立了 characters_list.txt 檔案,而該檔案是所有美國車牌字元的字典。

實驗配置

實驗配置檔定義了 LPRNet 模型架構、訓練和評估的超參數。下載範例 LPR 訓練配置檔,並放入 /home/<username>/tlt-experiments/lprnet 路徑。使用此配置在美國 LPRNet 上進行微調。

在此配置中,定義了具有已調整 ResNet18 骨幹的 LPRNet 模型,這是您的基準。使用批次大小 32、0.0005 的 L2 正規化訓練 24 期的模型,並使用 soft_start_annealing_schedule,在訓練期間套用可變學習率。欲深入瞭解實驗配置檔中的參數,請參閱轉移學習工具套件使用指南

我們同時提供了規格檔案,以從零開始訓練。相較於微調配置,必須增加期數和學習率。雖然不是建議的訓練方式,但是我們仍提出此方式以方便進行比較。

訓練

在備妥資料集和實驗規格之後,請在 TLT 中開始訓練。使用以下命令,透過單一 GPU 訓練 LPRNet,並以美國 LPRNet 模型做為預先訓練權重:

$ tlt lprnet train -e /workspace/tlt-experiments/lprnet/tutorial_spec.txt -r /workspace/tlt-experiments/lprnet/ -k nvidia_tlt -m /workspace/tlt-experiments/lprnet/us_lprnet_baseline18_trainable.tlt

TLT 同時支援多 GPU 訓練(資料平行)和自動混合精度(automatic mixed precision,AMP)。想要提高訓練速度時,可以使用選項 –gpus <num_gpus> 執行多個 GPU,並使用選項 –use_amp 執行混合精度訓練。訓練紀錄包含驗證資料集的準確率、訓練損失和學習率,是以 .csv 格式儲存在 <results_dir> 目錄中。以下程式碼範例是顯示具有預先訓練權重的訓練紀錄:

epoch,accuracy,loss,lr
0,nan,1.085993747589952,1e-05
1,nan,0.9726232198503731,1e-05
2,nan,0.9452087508756563,1e-05
3,nan,0.7897920507495686,1e-05
4,0.8409090909090909,0.5753771635772145,1e-05               
…….

匯出模型

想要在 DeepStream 或其他應用程式中部署 LPR 模型時,請匯出為 .etlt 格式。目前,LPR 僅支援 FP32 和 FP16 精度。相較於 LPD 的模型匯出命令,LPR 較簡單:

$ tlt lprnet export -m /workspace/tlt-experiments/lprnet/weights/lprnet_epoch-24.tlt -k nvidia_tlt -e /workspace/tlt-experiments/lprnet/tutorial_spec.txt

輸出 .etlt 模型是儲存在與已訓練 .tlt 模型相同的目錄中。

已訓練 LPR 模型的準確率

LPR 之評估指標為車牌辨識的準確率。如果車牌上的所有字元和順序都正確,則視為辨識準確。您可以在 TLT Docker 中使用以下命令,在實驗配置檔中指定的驗證資料集上執行評估:

$ tlt lprnet evaluate -m /workspace/tlt-experiments/lprnet/weights/lprnet_epoch-24.tlt -k nvidia_tlt -e /workspace/tlt-experiments/lprnet/tutorial_spec.txt

下表為從零開始訓練之模型與使用 LPRNet 預先訓練模型訓練之模型的準確率比較。

模型 Epochs 訓練準確率 驗證準確率
baseline18_unpruned_from_scratch 100 0% 0%
baseline18_unpruned_from_pretrained 24 98.87% 90.90%
表 2:使用預先訓練模型與從零開始訓練的準確率。

使用預先訓練模型時,可以使用較小的期數達到高準確率。相反地,從零開始訓練時,在期數增加 4 倍的情況下模型仍未開始匯聚。因此,必須大幅增加資料集,而導致訓練時間和成本增加。

使用 DeepStream SDK 部署 LPD 和 LPR

本節逐步講解了在 DeepStream 中部署 LPD 和 LPR 模型的步驟。我們已經提供範例 DeepStream 應用程式。LPD 和 LPR 範例應用程式為多個視訊資料流輸入建構了工作流程,並使用串聯模型,推論經過批次處理的視訊,以偵測車輛及其車牌,並辨識字元。

圖 3:LPD 和 LPR 範例應用程式的 DeepStream 工作流程。

範例應用程式的原始碼,分成兩個部分:

  • lpr-test-sample— LPD 和 LPR 範例的主要應用程式,是使用 DeepStream 外掛程式建構 Gstreamer 管道。
  • nvinfer_custom_lpr_parser— 自訂的 DeepStream nvinfer 外掛程式分類器剖析器函式庫,適用於 LPR 模型。預設的 DeepStream nvinfer 分類器僅支援信賴度剖析,並從 nvinfer 配置檔中之 labelfile-path 參數配置的標籤檔案中取得標籤。由於 LPR 是以兩層輸出 argmax 和信賴度,因此需要自訂的輸出剖析函式,以剖析 LPR 輸出層,並為車牌字串產生正確的標籤。自訂的剖析器函式應查詢指定的字典,以尋找具有 argmax 值和信賴度值的字元,然後將字元組合成車牌字串做為標籤。

下載及準備模型

此應用程式需要三個來自 TLT 的模型:

  • TrafficCamNet 可以偵測車輛。
  • LPD 可以偵測車牌。
  • LPR 可以辨識字元。

所有模型都可以從 NVIDIA NGC 下載。或者,如果您遵循前兩節的訓練步驟,則可以改用經過訓練的 LPD 和 LPR 模型。

下載 TrafficCamNet 模型:

mkdir -p /opt/nvidia/deepstream/deepstream-5.0/samples/models/tlt_pretrained_models/trafficcamnet

cd /opt/nvidia/deepstream/deepstream-5.0/samples/models/tlt_pretrained_models/trafficcamnet

wget https://api.ngc.nvidia.com/v2/models/nvidia/tlt_trafficcamnet/versions/pruned_v1.0/files/trafficnet_int8.txt

wget https://api.ngc.nvidia.com/v2/models/nvidia/tlt_trafficcamnet/versions/pruned_v1.0/files/resnet18_trafficcamnet_pruned.etlt

下載 LPD 模型:

mkdir -p /opt/nvidia/deepstream/deepstream-5.0/samples/models/LP/LPD

cd /opt/nvidia/deepstream/deepstream-5.0/samples/models/LP/LPD

wget https://api.ngc.nvidia.com/v2/models/nvidia/tlt_lpdnet/versions/pruned_v1.0/files/usa_pruned.etlt

wget https://api.ngc.nvidia.com/v2/models/nvidia/tlt_lpdnet/versions/pruned_v1.0/files/usa_lpd_cal.bin

wget https://api.ngc.nvidia.com/v2/models/nvidia/tlt_lpdnet/versions/pruned_v1.0/files/usa_lpd_label.txt

下載 LPR 模型:

mkdir -p /opt/nvidia/deepstream/deepstream-5.0/samples/models/LP/LPR

cd /opt/nvidia/deepstream/deepstream-5.0/samples/models/LP/LPR

wget https://api.ngc.nvidia.com/v2/models/nvidia/tlt_lprnet/versions/deployable_v1.0/files/us_lprnet_baseline18_deployable.etlt

#create an empty label file

echo > labels_us.txt

在 DeepStreamSDK 5.x 方面,gst-nvinfer 外掛程式無法從 TLT 的 ONNX 格式自動產生 TensorRT 引擎。LPR 模型是以來自 TLT 的加密 ONNX 格式匯出,且是 LPR 模型的限制。LPD 模型是採用舊的加密 UFF 格式,會自動與 DeepStream 結合。應使用 tlt-converter tool 產生 LPR 模型的引擎檔案。從 TLT 入門頁面下載適用於您的硬體,以及 CUDA 或 cuDNN 版本的最新 tlt-converter

表 3:各平台和硬體的下載位置。

將加密的 LPR ONNX 模型轉換成 TLT 引擎:

tlt-converter -k nvidia_tlt -p image_input,1x3x48x96,4x3x48x96,16x3x48x96 ./us_lprnet_baseline18_deployable.etltunpruned.etlt -t fp16 -e /opt/nvidia/deepstream/deepstream-5.0/samples/models/LP/LPR/lpr_us_onnx_b16.engine

建構與執行範例應用程式

NVIDIA-AI-IOT/deepstream_lpr_app GitHub 儲存庫下載範例程式碼,並建構應用程式。

nvinfer_custom_lpr_parser 的資料夾複製到剪貼簿,並建構程式碼:

cd  nvinfer_custom_lpr_parser
make

將產生的 libnvdsinfer_custom_impl_lpr.so 檔案複製到 /opt/nvidia/deepstream/deepstream-5.0/lib/ 目錄。

lpr-test-sample 的資料夾複製到裝置,並建構程式碼。產生範例應用程式 lpt-test-app

cd lpr-test-sample
make

根據實際的模型路徑和名稱,修改 TrafficCamNet、LPD 和 LPR 的 nvinfer 配置檔。DeepStream SDK 在以下路徑下提供 TrafficCamNet 的配置檔:

/opt/nvidia/deepstream/deepstream-5.0/samples/configs/tlt_pretrained_models/deepstream_app_source1_trafficcamnet.txt

lpd_config.txtlpr_config_sgie_us.txt 中,可以找到範例 lpd_config.txtlpr_config_sgie_us.txt 檔案。請注意 parse-classifier-func-namecustom-lib-path,將使用步驟 1 中新的 nvinfer LPR 函式庫。

根據已訓練 TLT LPR 模型,為 OCR 準備字典檔案。字典檔案名稱應為 dict.txt。使用美國版本建立 dict.txt

$ cp dict_us.txt dict.txt

執行範例應用程式。

lpr-test-app [language mode:1-us 2-chinese]
  [sink mode:1-output as 264 stream file 2-no output 3-display on screen]
  [ROI enable:0-disable ROI 1-enable ROI]
  [input mp4 file path and name] [input mp4 file path and name] ... [input mp4 file path and name]
  [output 264 file path and name]

例如:

$ lpr-test-app 1 3 0 file1.mp4 file2.mp4 output.264

效能

下表為在具有 45,000 多張美國汽車影像之專有資料集上,訓練已修剪美國 LPD 模型的推論傳輸量,是以每秒畫格數(frames per seconds,FPS)為單位。效能會因輸入大小、修剪比例、裝置等因素而異。效能是對應於 NGC 上提供之模型的已修剪版本,而不是前幾節中訓練的模型。

裝置 輸入大小(CHW) 精度 批次大小 FPS
Jetson Nano 3x480x640 FP16 1 66
Jetson NX 3x480x640 INT8 1 461
Jetson Xavier 3x480x640 INT8 1 913
T4 3x480x640 INT8 1 2748
表 4:車牌偵測的推論效能。

LPR 獨立效能

下表為使用不同之裝置,在美國車牌上訓練之 LPR 的推論效能。我們是使用 TensorRT 的 trtexec 命令,剖析模型推論。

裝置 輸入大小(CHW) 精度 批次大小 FPS
Jetson Nano 3x480x640 FP16 1 16
Jetson NX 3x480x640 INT8 1 600
Jetson Xavier 3x480x640 INT8 1 1021
T4 3x480x640 INT8 1 3821
表 5:車牌辨識的推論效能。

範例應用程式效能

此範例應用程式的完整工作流程,執行三種不同的 DNN 模型。在 TLT 中使用經過預先訓練的 TrafficCamNet 進行車輛偵測。LPD 和 LPR 已使用 NVIDIA 美國車牌訓練資料集進行預先訓練。

使用範例 LPR 應用程式,針對 1080p (1920×1080) 解析度影像進行以下測試。下表為使用三種 DNN 模型處理整個影像分析管道的端對端效能,從接收視訊資料,到在畫格上呈現中繼資料。在不同的裝置上收集資料。

裝置 資料流數量 批次大小 總 FPS
Jetson Nano 1 1 9.2
Jetson NX 3 3 80.31
Jetson Xavier 5 5 146.43
T4 14 14 447.15
表 6:使用 DeepStream 針對 ALPR 應用程式進行端對端推論。

總結

本文介紹適用於自動車牌辨識的端對端 AI 解決方案。此解決方案涵蓋開發智慧影像分析工作流程的所有層面-從使用轉移學習工具套件訓練深度神經網路模型,到在 DeepStream SDK 中部署經過訓練的模型。

在訓練方面,不需要專業知識,即可建構本身的 DNN以及最佳化模型。TLT 是以簡化的方式訓練模型-僅需要準備資料集與設定配置檔即可。此外,可以利用 TLT 中的高準確率預先訓練模型,以取代隨機初始化。

在部署方面,DeepStream 可以最佳化系統資源,進行視訊解碼、影像預處理和推論,進而提供最高通道密度,進行即時影像分析。您可以使用最輕鬆的方式,透過 DeepStream 將已訓練模型快速部署至多資料流影像分析管道。

採用 NVIDIA 預先訓練模型開始下一個 AI 專案,並使用轉移學習工具套件進行訓練。

若需要更多資訊,請參閱以下資源: