1. Paddle框架
目前支持Window、Linux多平台,v2.0后,也已支持python3.8。MacOS似乎不支持GPU,具體請查看官網最新說明。
1.1. 基於pip安裝
使用pip3的話,需要注意 pip3>20.2.2
:
pip3 install -U pip
-
CPU版本
pip3 install paddlepaddle -i https://mirror.baidu.com/pypi/simple
-
GPU版本
pip3 install paddlepaddle-gpu -i https://mirror.baidu.com/pypi/simple
測試安裝是否成功:
python3 -c 'import paddle; paddle.utils.run_check()'
1.2. 編譯安裝
2. PP-OCR
2.1. 安裝
安裝paddlepaddle模塊后,克隆PaddleOCR repo代碼:
git clone https://gitee.com/paddlepaddle/PaddleOCR
安裝第三方庫
cd PaddleOCR
pip3 install -r requirements.txt
2.2. 下載推理模型
接下來配置模型:
推理模型
用於python預測引擎推理,即實際部署是所使用的模型訓練模型
是基於預訓練模型在真實數據與豎排合成文本數據上finetune得到的模型,在真實應用場景中有着更好的表現預訓練模型
則是直接基於全量真實數據與合成數據訓練得到,更適合用於在自己的數據集上finetune
以超輕量級模型為例:
mkdir inference && cd inference
# 下載超輕量級中文OCR模型的檢測模型並解壓
wget https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_infer.tar && tar xf ch_ppocr_mobile_v2.0_det_infer.tar
# 下載超輕量級中文OCR模型的識別模型並解壓
wget https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_infer.tar && tar xf ch_ppocr_mobile_v2.0_rec_infer.tar
# 下載超輕量級中文OCR模型的文本方向分類器模型並解壓
wget https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.tar && tar xf ch_ppocr_mobile_v2.0_cls_infer.tar
解壓完畢后應有如下文件結構:
├── ch_ppocr_mobile_v2.0_cls_infer
│ ├── inference.pdiparams
│ ├── inference.pdiparams.info
│ └── inference.pdmodel
├── ch_ppocr_mobile_v2.0_det_infer
│ ├── inference.pdiparams
│ ├── inference.pdiparams.info
│ └── inference.pdmodel
├── ch_ppocr_mobile_v2.0_rec_infer
├── inference.pdiparams
├── inference.pdiparams.info
└── inference.pdmodel
注意:PaddleOCR的優勢在於中文識別,但其也提供了在無需單獨的 (英文+數字)
的組合識別模型,地址如下:gitee_paddleocr_doc
說明:2.0版模型和1.1版模型的主要區別在於動態圖訓練vs.靜態圖訓練,模型性能上無明顯差距。而v1.1版本的模型分類各細致,並提供了slim高度裁剪的lite版本,地址如下gitee_paddle_doc_v1.1。
而v2.0版本的模型庫中,多語言支持已經極大地豐富了!
2.3. 模型文件的深度解析
-
checkpoints模型,是訓練過程中保存的模型,文件中只記錄了模型的參數,多用於恢復訓練等。
-
inference模型(paddle.jit.save保存的模型),一般是模型訓練,把模型結構和模型參數保存在文件中的固化模型,多用於預測部署場景。
與checkpoints模型相比,inference 模型會額外保存模型的結構信息,在預測部署、加速推理上性能優越,靈活方便,適合於實際系統集成。
2.3.1. 檢測模型轉inference模型
wget -P ./ch_lite/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_det_train.tar
tar xf ./ch_lite/ch_ppocr_mobile_v2.0_det_train.tar -C ./ch_lite/
-c
后面設置訓練算法的yml配置文件-o
配置可選參數Global.pretrained_model
參數設置待轉換的訓練模型地址,不用添加文件后綴 .pdmodel,.pdopt或.pdparams。Global.load_static_weights
參數需要設置為 False。Global.save_inference_dir
參數設置轉換的模型將保存的地址。
python3 tools/export_model.py \
-c configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml \
-o Global.pretrained_model=./ch_lite/ch_ppocr_mobile_v2.0_det_train/best_accuracy \
Global.load_static_weights=False \
Global.save_inference_dir=./inference/det_db/
轉inference模型時,使用的配置文件和訓練時使用的配置文件相同。另外,還需要設置配置文件中的 Global.pretrained_model
參數,其指向訓練中保存的模型參數文件。
轉換成功后,在模型保存目錄下有三個文件:
inference/det_db/
├── inference.pdiparams # 檢測inference模型的參數文件
├── inference.pdiparams.info # 檢測inference模型的參數信息,可忽略
└── inference.pdmodel # 檢測inference模型的program文件
2.3.2. 識別模型轉inference模型
wget -P ./ch_lite/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_rec_train.tar
tar xf ./ch_lite/ch_ppocr_mobile_v2.0_rec_train.tar -C ./ch_lite/
python3 tools/export_model.py \
-c configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yml \
-o Global.pretrained_model=./ch_lite/ch_ppocr_mobile_v2.0_rec_train/best_accuracy
Global.load_static_weights=False \
Global.save_inference_dir=./inference/rec_crnn/
2.3.3. 方向分類模型轉inference模型
wget -P ./ch_lite/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_train.tar
tar xf ./ch_lite/ch_ppocr_mobile_v2.0_cls_train.tar -C ./ch_lite/
python3 tools/export_model.py \
-c configs/cls/cls_mv3.yml \
-o Global.pretrained_model=./ch_lite/ch_ppocr_mobile_v2.0_cls_train/best_accuracy \
Global.load_static_weights=False \
Global.save_inference_dir=./inference/cls/
2.4. 使用:圖像預測
# 預測image_dir指定的單張圖像
python3 tools/infer/predict_system.py --image_dir="./doc/imgs/11.jpg" --det_model_dir="./inference/ch_ppocr_mobile_v2.0_det_infer/" --rec_model_dir="./inference/ch_ppocr_mobile_v2.0_rec_infer/" --cls_model_dir="./inference/ch_ppocr_mobile_v2.0_cls_infer/" --use_angle_cls=True --use_space_char=True
# 預測image_dir指定的圖像集合
python3 tools/infer/predict_system.py --image_dir="./doc/imgs/" --det_model_dir="./inference/ch_ppocr_mobile_v2.0_det_infer/" --rec_model_dir="./inference/ch_ppocr_mobile_v2.0_rec_infer/" --cls_model_dir="./inference/ch_ppocr_mobile_v2.0_cls_infer/" --use_angle_cls=True --use_space_char=True
# 如果想使用CPU進行預測,需設置use_gpu參數為False
python3 tools/infer/predict_system.py --image_dir="./doc/imgs/11.jpg" --det_model_dir="./inference/ch_ppocr_mobile_v2.0_det_infer/" --rec_model_dir="./inference/ch_ppocr_mobile_v2.0_rec_infer/" --cls_model_dir="./inference/ch_ppocr_mobile_v2.0_cls_infer/" --use_angle_cls=True --use_space_char=True --use_gpu=False
注意:
- 如果希望使用不支持空格的識別模型,在預測的時候需要注意:請將代碼更新到最新版本,並添加參數
--use_space_char=False
。 - 如果不希望使用方向分類器,在預測的時候需要注意:請將代碼更新到最新版本,並添加參數
--use_angle_cls=False
。
2.5. 部署
PaddleOCR提供2種Server端部署服務的方式:
- 基於PaddleHub Serving的部署:代碼路徑為"./deploy/hubserving",按照本教程使用;
(coming soon) - 基於PaddleServing的部署:代碼路徑為"./deploy/pdserving",使用方法參考文檔。
2.5.1. 啟動服務
-
命令行啟動(僅支持CPU)服務
$ hub serving start --modules [Module1==Version1, Module2==Version2, ...] \ --port XXXX \ --use_multiprocess \ --workers \
-
配置文件啟動(支持CPU、GPU)
hub serving start -c config.json
2.5.2. 發送預測請求
配置好服務端,可使用以下命令發送預測請求,獲取預測結果:
python tools/test_hubserving.py server_url image_path
需要給腳本傳遞2個參數:
- server_url:服務地址,例如
http://127.0.0.1:8868/predict/ocr_system
- image_path:測試圖像路徑,可以是單張圖片路徑,也可以是圖像集合目錄路徑
訪問示例:
python3 tools/test_hubserving.py http://127.0.0.1:8868/predict/ocr_system ./doc/imgs/
2.6. 數據標注與合成
2.6.1. 半自動標注工具: PPOCRLabel
運行:
# Windows + Anaconda
pip install pyqt5
cd ./PPOCRLabel # 將目錄切換到PPOCRLabel文件夾下
python PPOCRLabel.py --lang ch
# Ubuntu Linux
pip3 install pyqt5 trash-cli
cd ./PPOCRLabel # 將目錄切換到PPOCRLabel文件夾下
python3 PPOCRLabel.py --lang ch
2.6.2. 數據合成工具: Style-Text
2.7. FAQ精選
對於中文行文本識別,CTC和Attention哪種更優?
A:(1)從效果上來看,通用OCR場景CTC的識別效果優於Attention,因為帶識別的字典中的字符比較多,常用中文漢字三千字以上,如果訓練樣本不足的情況下,對於這些字符的序列關系挖掘比較困難。中文場景下Attention模型的優勢無法體現。而且Attention適合短語句識別,對長句子識別比較差。
(2)從訓練和預測速度上,Attention的串行解碼結構限制了預測速度,而CTC網絡結構更高效,預測速度上更有優勢。
PaddleOCR項目中的中文超輕量和通用模型用了哪些數據集?訓練多少樣本,gpu什么配置,跑了多少個epoch,大概跑了多久?
A: (1)檢測的話,LSVT街景數據集共3W張圖像,超輕量模型,150epoch左右,2卡V100 跑了不到2天;通用模型:2卡V100 150epoch 不到4天。 (2) 識別的話,520W左右的數據集(真實數據26W+合成數據500W)訓練,超輕量模型:4卡V100,總共訓練了5天左右。通用模型:4卡V100,共訓練6天。
超輕量模型訓練分為2個階段: (1)全量數據訓練50epoch,耗時3天 (2)合成數據+真實數據按照1:1數據采樣,進行finetune訓練200epoch,耗時2天
通用模型訓練: 真實數據+合成數據,動態采樣(1:1)訓練,200epoch,耗時 6天左右。
PaddleOCR中,對於模型預測加速,CPU加速的途徑有哪些?基於TenorRT加速GPU對輸入有什么要求?
A:(1)CPU可以使用mkldnn進行加速;對於python inference的話,可以把enable_mkldnn改為true,參考代碼,對於cpp inference的話,在配置文件里面配置use_mkldnn 1即可,參考代碼
(2)GPU需要注意變長輸入問題等,TRT6 之后才支持變長輸入
目前OCR普遍是二階段,端到端的方案在業界落地情況如何?
A:端到端在文字分布密集的業務場景,效率會比較有保證,精度的話看自己業務數據積累情況,如果行級別的識別數據積累比較多的話two-stage會比較好。百度的落地場景,比如工業儀表識別、車牌識別都用到端到端解決方案。
如何更換文本檢測/識別的backbone?
A:無論是文字檢測,還是文字識別,骨干網絡的選擇是預測效果和預測效率的權衡。一般,選擇更大規模的骨干網絡,例如ResNet101_vd,則檢測或識別更准確,但預測耗時相應也會增加。而選擇更小規模的骨干網絡,例如MobileNetV3_small_x0_35,則預測更快,但檢測或識別的准確率會大打折扣。幸運的是不同骨干網絡的檢測或識別效果與在ImageNet數據集圖像1000分類任務效果正相關。飛槳圖像分類套件PaddleClas匯總了ResNet_vd、Res2Net、HRNet、MobileNetV3、GhostNet等23種系列的分類網絡結構,在上述圖像分類任務的top1識別准確率,GPU(V100和T4)和CPU(驍龍855)的預測耗時以及相應的117個預訓練模型下載地址。
(1)文字檢測骨干網絡的替換,主要是確定類似與ResNet的4個stages,以方便集成后續的類似FPN的檢測頭。此外,對於文字檢測問題,使用ImageNet訓練的分類預訓練模型,可以加速收斂和效果提升。
(2)文字識別的骨干網絡的替換,需要注意網絡寬高stride的下降位置。由於文本識別一般寬高比例很大,因此高度下降頻率少一些,寬度下降頻率多一些。可以參考PaddleOCR中MobileNetV3骨干網絡的改動。
對於CRNN模型,backbone采用DenseNet和ResNet_vd,哪種網絡結構更好?
A:Backbone的識別效果在CRNN模型上的效果,與Imagenet 1000 圖像分類任務上識別效果和效率一致。在圖像分類任務上ResnNet_vd(79%+)的識別精度明顯優於DenseNet(77%+),此外對於GPU,Nvidia針對ResNet系列模型做了優化,預測效率更高,所以相對而言,resnet_vd是較好選擇。如果是移動端,可以優先考慮MobileNetV3系列。
對於特定文字檢測,例如身份證只檢測姓名,檢測指定區域文字更好,還是檢測全部區域再篩選更好?
A:兩個角度來說明一般檢測全部區域再篩選更好。
(1)由於特定文字和非特定文字之間的視覺特征並沒有很強的區分行,只檢測指定區域,容易造成特定文字漏檢。
(2)產品的需求可能是變化的,不排除后續對於模型需求變化的可能性(比如又需要增加一個字段),相比於訓練模型,后處理的邏輯會更容易調整。
3. paddle2onnx
ONNX(Open Neural Network Exchange)是一種針對機器學習所設計的開放式的文件格式,用於存儲訓練好的模型。它使得不同的人工智能框架,可以采用相同格式存儲模型數據並交互。簡而言之,ONNX相當於是一套統一的深度學習模型格式。基於這一套統一的格式,很多廠商的硬件和軟件天然支持運行ONNX格式的模型。
關注飛槳的用戶此前就應該了解到,Paddle Lite不僅可以支持飛槳原生模型部署,同時也支持PyTorch模型的部署,其技術路徑就是通過PyTorch導出ONNX格式模型,再通過X2Paddle轉換為飛槳模型格式進行部署。
安裝
pip install paddle2onnx
靜態圖模型導出(Paddle2.0后主推動態圖版本)
# Paddle模型的參數保存為多個文件(not combined)
paddle2onnx --model_dir paddle_model \
--save_file onnx_file \
--opset_version 10 \
--enable_onnx_checker True
# Paddle模型的參數保存在一個單獨的二進制文件中(combined)
paddle2onnx --model_dir paddle_model \
--model_filename model_filename \
--params_filename params_filename \
--save_file onnx_file \
--opset_version
動態圖版本
import paddle
from paddle import nn
from paddle.static import InputSpec
import paddle2onnx as p2o
class LinearNet(nn.Layer):
def __init__(self):
super(LinearNet, self).__init__()
self._linear = nn.Linear(784, 10)
def forward(self, x):
return self._linear(x)
layer = LinearNet()
# configure model inputs
x_spec = InputSpec([None, 784], 'float32', 'x')
# convert model to inference mode
layer.eval()
save_path = 'onnx.save/linear_net'
p2o.dygraph2onnx(layer, save_path + '.onnx', input_spec=[x_spec])
# when you paddlepaddle>2.0.0, you can try:
# paddle.onnx.export(layer, save_path, input_spec=[x_spec])
3.1. 實例:轉換英文識別模型
# 注意:下載訓練模型
wget -P ~/ch_lite/ https://paddleocr.bj.bcebos.com/dygraph_v2.0/multilingual/en_number_mobile_v2.0_rec_train.tar && tar xf ~/ch_lite/en_number_mobile_v2.0_rec_train.tar -C ~/ch_lite/
# 轉換為inference預測模型
cd ~/PaddleOCR
python3 tools/export_model.py -c configs/rec/multi_language/rec_en_number_lite_train.yml -o Global.pretrained_model=/home/aistudio/ch_lite/en_number_mobile_v2.0_rec_train/best_accuracy Global.load_static_weights=False Global.save_inference_dir=/home/aistudio/inference_model/paddle/rec_en_crnn
# 轉換為onnx模型
paddle2onnx -m /home/aistudio/inference_model/paddle/rec_en_crnn/ --model_filename inference.pdmodel --params_filename inference.pdiparams -s /home/aistudio/inference_model/onnx/rec_en_db/model.onnx --opset_version 11
注意,需要將model的目錄修改,同時變更識別的字符集:
- rec_char_type
- rec_char_dict_path: 在
ppocr/utils/dict/
目錄下,如en_dict.txt。
參考PaddleOCR的源碼 ppocr/postprocess/rec_postprocess.py
:
support_character_type = [
'ch', 'en', 'EN_symbol', 'french', 'german', 'japan', 'korean',
'it', 'xi', 'pu', 'ru', 'ar', 'ta', 'ug', 'fa', 'ur', 'rs', 'oc',
'rsc', 'bg', 'uk', 'be', 'te', 'ka', 'chinese_cht', 'hi', 'mr',
'ne', 'EN'
]
if character_type == "en":
self.character_str = "0123456789abcdefghijklmnopqrstuvwxyz"
dict_character = list(self.character_str)
elif character_type == "EN_symbol":
# same with ASTER setting (use 94 char).
self.character_str = string.printable[:-6]
dict_character = list(self.character_str)
elif character_type in support_character_type:
self.character_str = ""
assert character_dict_path is not None, "character_dict_path should not be None when character_type is {}".format(
character_type)
with open(character_dict_path, "rb") as fin:
lines = fin.readlines()
for line in lines:
line = line.decode('utf-8').strip("\n").strip("\r\n")
self.character_str += line
if use_space_char:
self.character_str += " "
dict_character = list(self.character_str)
3.2. ONNXRunTime
參考上述教程,獲取onnx模型。但項目依然依賴於paddle。為了解耦,做了以下工作:
-
從paddle項目中解耦
ppocr/data/imaug
,這個項目用於圖像增強。但實際onnx只需要調用其中的各種operators定義。無需
imgaug
模塊的安裝(依賴scikit-image,項目龐大),但需要shapely的支持。而shapely又需要GEOS:
apt install libgeos-c1v5
另,需要
pip install setuptools_scm pyclipper
,一個圖像分割時邊緣關鍵點的處理工具,負責多邊形裁剪(依賴setuptools_scm管理)。 -
從paddle項目中解耦
ppocr/post_process
,這里主要是定義了多個模型的后處理器。可直接解除paddle框架的依賴。 -
掛載攝像頭
-
優化內存和程序
嵌入式設備采用jetson_nano_2GB,運行時ONNX對模型的加載會占用300M左右的空間。程序本身運行並不吃力(相比於OpenCV_dnn的CUDA版本,內存被吃爆)。
最終運行起來,深度網絡約占用了1.3GB的內存,無明顯Swap消耗。
運行效果截圖