針對靜止或快速移動的車輛進行自動車牌辨識(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 中高準確率的預先訓練模型時,需要以下資源:
- 來自 NGC 的 TrafficCamNet 或 DashCamNet 模型可以偵測車輛
- 車牌偵測(LPD)模型可以偵測車牌
- 車牌辨識(LPR)模型可以將影像轉換成文字
- DeepStream SDK
所有的預先訓練模型,都可以從 NVIDIA NGC 免費下載。TLT 提供兩種 LPD 模型和兩種 LPR 模型:一種在美國車牌上接受訓練,以及一種在中國車牌上接受訓練。若需要更多資訊,請參閱 LPD 和 LPR 模型卡。
透過 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% |
車牌辨識
本節將詳細探討 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 解碼器,從序列輸出中將車牌解碼。
訓練 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% |
使用預先訓練模型時,可以使用較小的期數達到高準確率。相反地,從零開始訓練時,在期數增加 4 倍的情況下模型仍未開始匯聚。因此,必須大幅增加資料集,而導致訓練時間和成本增加。
使用 DeepStream SDK 部署 LPD 和 LPR
本節逐步講解了在 DeepStream 中部署 LPD 和 LPR 模型的步驟。我們已經提供範例 DeepStream 應用程式。LPD 和 LPR 範例應用程式為多個視訊資料流輸入建構了工作流程,並使用串聯模型,推論經過批次處理的視訊,以偵測車輛及其車牌,並辨識字元。
範例應用程式的原始碼,分成兩個部分:
- 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。
平台 | 運算 |
x86 + GPU | CUDA 10.2 / cuDNN 8.0 / TensorRT 7.1 |
x86 + GPU | CUDA 10.2 / cuDNN 8.0 / TensorRT 7.2 |
x86 + GPU | CUDA 11.0 / cuDNN 8.0 / TensorRT 7.1 |
x86 + GPU | CUDA 11.0 / cuDNN 8.0 / TensorRT 7.2 |
Jetson | JetPack 4.4 |
Jetson | JetPack 4.5 |
將加密的 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.txt 和 lpr_config_sgie_us.txt 中,可以找到範例 lpd_config.txt 和 lpr_config_sgie_us.txt 檔案。請注意 parse-classifier-func-name 和 custom-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 |
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 |
範例應用程式效能
此範例應用程式的完整工作流程,執行三種不同的 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 |
總結
本文介紹適用於自動車牌辨識的端對端 AI 解決方案。此解決方案涵蓋開發智慧影像分析工作流程的所有層面-從使用轉移學習工具套件訓練深度神經網路模型,到在 DeepStream SDK 中部署經過訓練的模型。
在訓練方面,不需要專業知識,即可建構本身的 DNN以及最佳化模型。TLT 是以簡化的方式訓練模型-僅需要準備資料集與設定配置檔即可。此外,可以利用 TLT 中的高準確率預先訓練模型,以取代隨機初始化。
在部署方面,DeepStream 可以最佳化系統資源,進行視訊解碼、影像預處理和推論,進而提供最高通道密度,進行即時影像分析。您可以使用最輕鬆的方式,透過 DeepStream 將已訓練模型快速部署至多資料流影像分析管道。
採用 NVIDIA 預先訓練模型開始下一個 AI 專案,並使用轉移學習工具套件進行訓練。
若需要更多資訊,請參閱以下資源: