From a6f5282973321b452c399b87895dbb29adf50a31 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Thu, 12 May 2022 16:14:18 +0800 Subject: [PATCH 01/12] fix --- ppocr/data/imaug/label_ops.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ppocr/data/imaug/label_ops.py b/ppocr/data/imaug/label_ops.py index 02a5187dad..8b017b3219 100644 --- a/ppocr/data/imaug/label_ops.py +++ b/ppocr/data/imaug/label_ops.py @@ -438,10 +438,10 @@ class KieLabelEncode(object): texts.append(ann['transcription']) text_ind = [self.dict[c] for c in text if c in self.dict] text_inds.append(text_ind) - if 'label' in anno.keys(): + if 'label' in ann.keys(): labels.append(ann['label']) - elif 'key_cls' in anno.keys(): - labels.append(anno['key_cls']) + elif 'key_cls' in ann.keys(): + labels.append(ann['key_cls']) else: raise ValueError("Cannot found 'key_cls' in ann.keys(), please check your training annotation.") edges.append(ann.get('edge', 0)) From 7036ec1b5f33edf431bbf414190322631c9a2d0b Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 17 May 2022 15:55:55 +0800 Subject: [PATCH 02/12] add doc --- doc/doc_ch/PPOCRv3_det_train.md | 252 ++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 doc/doc_ch/PPOCRv3_det_train.md diff --git a/doc/doc_ch/PPOCRv3_det_train.md b/doc/doc_ch/PPOCRv3_det_train.md new file mode 100644 index 0000000000..601acddee1 --- /dev/null +++ b/doc/doc_ch/PPOCRv3_det_train.md @@ -0,0 +1,252 @@ + +# PP-OCRv3 文本检测模型训练 + +- [1. 简介](#1) +- [2. PPOCRv3检测训练](#2) +- [3. 基于PPOCRv3检测的finetune训练](#3) + + +## 1. 简介 + +PP-OCRv3在PP-OCRv2的基础上进一步升级。本节介绍PP-OCRv3检测模型的训练步骤。有关PPOCRv3策略介绍参考[文档](./PP-OCRv3_introduction.md)。 + + + +## 2. 检测训练 + +PP-OCRv3检测模型是对PP-OCRv2中的[CML](https://arxiv.org/pdf/2109.03144.pdf)(Collaborative Mutual Learning) 协同互学习文本检测蒸馏策略进行了升级。PP-OCRv3分别针对检测教师模型和学生模型进行进一步效果优化。其中,在对教师模型优化时,提出了大感受野的PAN结构LK-PAN和引入了DML(Deep Mutual Learning)蒸馏策略;在对学生模型优化时,提出了残差注意力机制的FPN结构RSE-FPN。 + +PP-OCRv3检测训练包括两个步骤: +- 步骤1:采用DML蒸馏方法训练检测教师模型 +- 步骤2:使用步骤1得到的教师模型采用CML方法训练出轻量学生模型 + + +### 2.1 准备数据和运行环境 + +训练数据采用icdar2015数据,准备训练集步骤参考[ocr_dataset](./dataset/ocr_datasets.md). + +运行环境准备参考[文档](./installation.md)。 + + +### 2.2 训练教师模型 + +教师模型训练的配置文件是[ch_PP-OCRv3_det_dml.yml](https://github.com/PaddlePaddle/PaddleOCR/blob/release%2F2.5/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml)。教师模型模型结构的Backbone、Neck、Head分别为Resnet50, LKPAN, DBHead,采用DML的蒸馏方法训练。有关配置文件的详细介绍参考[文档](./knowledge_distillation)。 + + +下载ImageNet预训练模型: +``` +# 下载ResNet50_vd的预训练模型 +wget -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/pretrained/ResNet50_vd_ssld_pretrained.pdparams +``` + +**启动训练** +``` +# 单卡训练 +python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml \ + -o Architecture.Models.Student.pretrained=./pretrain_models/ResNet50_vd_ssld_pretrained \ + Architecture.Models.Student2.pretrained=./pretrain_models/ResNet50_vd_ssld_pretrained \ + Global.save_model_dir=./output/ +# 如果要使用多GPU分布式训练,请使用如下命令: +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml \ + -o Architecture.Models.Student.pretrained=./pretrain_models/ResNet50_vd_ssld_pretrained \ + Architecture.Models.Student2.pretrained=./pretrain_models/ResNet50_vd_ssld_pretrained \ + Global.save_model_dir=./output/ +``` + +训练过程中保存的模型在output目录下,包含以下文件: +``` +best_accuracy.states +best_accuracy.pdparams # 默认保存最优精度的模型参数 +best_accuracy.pdopt # 默认保存最优精度的优化器相关参数 +latest.states +latest.pdparams # 默认保存的最新模型参数 +latest.pdopt # 默认保存的最新模型的优化器相关参数 +``` +其中,best_accuracy是保存的精度最高的模型参数,可以直接使用该模型评估。 + +模型评估命令如下: +``` +python3 tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml -o Global.checkpoints=./output/best_accuracy +``` + +训练的教师模型结构更大,精度更高,用于提升学生模型的精度。 + +**提取教师模型参数** +best_accuracy包含两个模型的参数,分别对应配置文件中的Student,Student2。提取Student的参数方法如下: + +``` +import paddle +# 加载预训练模型 +all_params = paddle.load("output/best_accuracy.pdparams") +# 查看权重参数的keys +print(all_params.keys()) +# 模型的权重提取 +s_params = {key[len("Student."):]: all_params[key] for key in all_params if "Student." in key} +# 查看模型权重参数的keys +print(s_params.keys()) +# 保存 +paddle.save(s_params, "./pretrain_models/dml_teacher.pdparams") +``` + +提取出来的模型参数可以用于模型进一步的finetune训练或者蒸馏训练。 + +### 2.3 训练学生模型 + +训练学生模型的配置文件是[ch_PP-OCRv3_det_cml.yml](https://github.com/PaddlePaddle/PaddleOCR/blob/release%2F2.5/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml) +上一节训练得到的教师模型作为监督,采用CML方式训练得到轻量的学生模型。 + +下载学生模型的ImageNet预训练模型: +``` +# 下载MobileNetV3的预训练模型 +wget -P ./pretrain_models/ https://paddleocr.bj.bcebos.com/pretrained/MobileNetV3_large_x0_5_pretrained.pdparams +``` + +**启动训练** + +``` +# 单卡训练 +python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ + -o Architecture.Models.Student.pretrained=./pretrain_models/MobileNetV3_large_x0_5_pretrained \ + Architecture.Models.Student2.pretrained=./pretrain_models/MobileNetV3_large_x0_5_pretrained \ + Architecture.Models.Teacher.pretrained=./pretrain_models/dml_teacher \ + Global.save_model_dir=./output/ +# 如果要使用多GPU分布式训练,请使用如下命令: +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ + -o Architecture.Models.Student.pretrained=./pretrain_models/MobileNetV3_large_x0_5_pretrained \ + Architecture.Models.Student2.pretrained=./pretrain_models/MobileNetV3_large_x0_5_pretrained \ + Architecture.Models.Teacher.pretrained=./pretrain_models/dml_teacher \ + Global.save_model_dir=./output/ +``` + +训练过程中保存的模型在output目录下, +模型评估命令如下: +``` +python3 tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.checkpoints=./output/best_accuracy +``` + +best_accuracy包含三个模型的参数,分别对应配置文件中的Student,Student2,Teacher。提取Student参数的方法如下: + +``` +import paddle +# 加载预训练模型 +all_params = paddle.load("output/best_accuracy.pdparams") +# 查看权重参数的keys +print(all_params.keys()) +# 模型的权重提取 +s_params = {key[len("Student."):]: all_params[key] for key in all_params if "Student." in key} +# 查看模型权重参数的keys +print(s_params.keys()) +# 保存 +paddle.save(s_params, "./pretrain_models/cml_student.pdparams") +``` + +提取出来的Student的参数可用于模型部署或者做进一步的finetune训练。 + + + + +## 3. 基于PPOCRv3检测finetune训练 + +本节介绍如何使用PPOCRv3检测模型在其他场景上的finetune训练。 + +finetune训练适用于三种场景: +- 基于CML蒸馏方法的finetune训练,适用于教师模型在使用场景上精度高于PPOCRv3检测模型,且希望得到一个轻量检测模型。 +- 基于PPOCRv3轻量检测模型的finetune训练,无需训练教师模型,希望在PPOCRv3检测模型基础上提升使用场景上的精度。 +- 基于DML蒸馏方法的finetune训练,适用于采用DML方法进一步提升精度的场景。 + + +**基于CML蒸馏方法的finetune训练** + +下载PPOCRv3训练模型: +``` +wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar +tar xf ch_PP-OCRv3_det_distill_train.tar +``` +ch_PP-OCRv3_det_distill_train/best_accuracy.pdparams包含CML配置文件中Student、Student2、Teacher模型的参数。 + +启动训练: + +``` +# 单卡训练 +python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ + -o Global.pretrained_model=./ch_PP-OCRv3_det_distill_train/best_accuracy \ + Global.save_model_dir=./output/ +# 如果要使用多GPU分布式训练,请使用如下命令: +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml \ + -o Global.pretrained_model=./ch_PP-OCRv3_det_distill_train/best_accuracy \ + Global.save_model_dir=./output/ +``` + +**基于PPOCRv3轻量检测模型的finetune训练** + + +下载PPOCRv3训练模型,并提取Student结构的模型参数: +``` +wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar +tar xf ch_PP-OCRv3_det_distill_train.tar +``` + +提取Student参数的方法如下: + +``` +import paddle +# 加载预训练模型 +all_params = paddle.load("output/best_accuracy.pdparams") +# 查看权重参数的keys +print(all_params.keys()) +# 模型的权重提取 +s_params = {key[len("Student."):]: all_params[key] for key in all_params if "Student." in key} +# 查看模型权重参数的keys +print(s_params.keys()) +# 保存 +paddle.save(s_params, "./student.pdparams") +``` + +使用配置文件[ch_PP-OCRv3_det_student.yml](https://github.com/PaddlePaddle/PaddleOCR/blob/release%2F2.5/configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml)训练。 + +**启动训练** + +``` +# 单卡训练 +python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml \ + -o Global.pretrained_model=./student \ + Global.save_model_dir=./output/ +# 如果要使用多GPU分布式训练,请使用如下命令: +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml \ + -o Global.pretrained_model=./student \ + Global.save_model_dir=./output/ +``` + + +**基于DML蒸馏方法的finetune训练** + +以ch_PP-OCRv3_det_distill_train中的Teacher模型为例,首先提取Teacher结构的参数,方法如下: +``` +import paddle +# 加载预训练模型 +all_params = paddle.load("ch_PP-OCRv3_det_distill_train/best_accuracy.pdparams") +# 查看权重参数的keys +print(all_params.keys()) +# 模型的权重提取 +s_params = {key[len("Teacher."):]: all_params[key] for key in all_params if "Teacher." in key} +# 查看模型权重参数的keys +print(s_params.keys()) +# 保存 +paddle.save(s_params, "./teacher.pdparams") +``` + +**启动训练** +``` +# 单卡训练 +python3 tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml \ + -o Architecture.Models.Student.pretrained=./teacher \ + Architecture.Models.Student2.pretrained=./teacher \ + Global.save_model_dir=./output/ +# 如果要使用多GPU分布式训练,请使用如下命令: +python3 -m paddle.distributed.launch --gpus '0,1,2,3' tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml \ + -o Architecture.Models.Student.pretrained=./teacher \ + Architecture.Models.Student2.pretrained=./teacher \ + Global.save_model_dir=./output/ +``` + + From bb0c95965682fb08195b02808ebcce5efd58fc6b Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Thu, 19 May 2022 19:46:40 +0800 Subject: [PATCH 03/12] add benchmark --- applications/车牌识别.md | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index 2abb9c6f7a..afa8d57107 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -357,11 +357,13 @@ python3.7 deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCR |方案|hmeans| 模型大小 |预测速度(lite)| |---|---|------|---| -|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 2.5M || -|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%| 1M || +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 2.5M | 223ms/image | +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%| 1M | 189ms/image | 可以看到量化后能显著降低模型体积并且精度几乎无损。 +预测速度是在android骁龙855上预测275张图像的平均耗时。 + #### 4.1.4 模型导出 使用如下命令可以将训练好的模型进行导出 @@ -571,11 +573,13 @@ python3.7 deploy/slim/quantization/quant.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_ |方案| acc | 模型大小 |预测速度(lite)| |---|--------|-------|---| -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M | -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 93.4% | 4.8M | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M | 4.2ms/image | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 93.4% | 4.8M | 1.8ms/image; | 可以看到量化后能显著降低模型体积,但是由于识别数据过少,量化带来了1%的精度下降。 +预测速度是在android骁龙855上预测5006张识别文字图像的平均耗时。 + #### 4.2.5 模型导出 使用如下命令可以将训练好的模型进行导出。 @@ -618,19 +622,22 @@ python tools/infer/predict_system.py \ |方案|hmeans| 模型大小 |预测速度(lite)| |---|---|------|---| -|PP-OCRv3中英文超轻量检测预训练模型直接预测|76.12%|2.5M| -|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 2.5M || -|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%| 1M || +|PP-OCRv3中英文超轻量检测预训练模型直接预测|76.12%|2.5M| 223ms/image | +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 2.5M | 223ms/image | +|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%| 1M | 189ms/image | + +预测速度是在android骁龙855上预测275张图像的平均耗时。 - 识别 |方案| acc | 模型大小 |预测速度(lite)| |---|--------|-------|---| -|PP-OCRv3中英文超轻量识别预训练模型直接预测| 0% |10.3M|| -|PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的`·`| 90.97% |10.3M|| -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M || -|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 94.4% | 4.8M || +|PP-OCRv3中英文超轻量识别预训练模型直接预测| 0% |10.3M| 4.2ms/image | +|PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的`·`| 90.97% |10.3M| 4.2ms/image | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M | 4.2ms/image | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 94.4% | 4.8M | 1.8ms/image | +预测速度是在android骁龙855上预测5006张识别文字图像的平均耗时。 - 结论 From 16bafedeba9cdae18290717278dc9079f32411b4 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Thu, 19 May 2022 19:48:11 +0800 Subject: [PATCH 04/12] add benchmark --- applications/车牌识别.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/applications/车牌识别.md b/applications/车牌识别.md index afa8d57107..7510f3c5a8 100644 --- a/applications/车牌识别.md +++ b/applications/车牌识别.md @@ -362,7 +362,7 @@ python3.7 deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCR 可以看到量化后能显著降低模型体积并且精度几乎无损。 -预测速度是在android骁龙855上预测275张图像的平均耗时。 +预测速度是在android骁龙855上预测275张图像的平均耗时。模型在移动端的部署步骤参考[文档](../deploy/lite/readme_ch.md) #### 4.1.4 模型导出 @@ -578,7 +578,7 @@ python3.7 deploy/slim/quantization/quant.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_ 可以看到量化后能显著降低模型体积,但是由于识别数据过少,量化带来了1%的精度下降。 -预测速度是在android骁龙855上预测5006张识别文字图像的平均耗时。 +预测速度是在android骁龙855上预测5006张识别文字图像的平均耗时。模型在移动端的部署步骤参考[文档](../deploy/lite/readme_ch.md) #### 4.2.5 模型导出 From 89567ae300e6cd827d225a1dd1f7888904fdb51f Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 21 Jun 2022 15:21:58 +0800 Subject: [PATCH 05/12] fix --- tools/infer/predict_det.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/tools/infer/predict_det.py b/tools/infer/predict_det.py index 5f2675d667..73387aef59 100755 --- a/tools/infer/predict_det.py +++ b/tools/infer/predict_det.py @@ -24,6 +24,7 @@ import cv2 import numpy as np import time import sys +from scipy.spatial import distance as dist import tools.infer.utility as utility from ppocr.utils.logging import get_logger @@ -150,14 +151,22 @@ class TextDetector(object): logger=logger) def order_points_clockwise(self, pts): - rect = np.zeros((4, 2), dtype="float32") - s = pts.sum(axis=1) - rect[0] = pts[np.argmin(s)] - rect[2] = pts[np.argmax(s)] - diff = np.diff(pts, axis=1) - rect[1] = pts[np.argmin(diff)] - rect[3] = pts[np.argmax(diff)] - return rect + """ + refer to :https://github.com/PyImageSearch/imutils/blob/9f740a53bcc2ed7eba2558afed8b4c17fd8a1d4c/imutils/perspective.py#L9 + """ + # sort the points based on their x-coordinates + xSorted = pts[np.argsort(pts[:, 0]), :] + + leftMost = xSorted[:2, :] + rightMost = xSorted[2:, :] + + leftMost = leftMost[np.argsort(leftMost[:, 1]), :] + (tl, bl) = leftMost + + D = dist.cdist(tl[np.newaxis], rightMost, "euclidean")[0] + (br, tr) = rightMost[np.argsort(D)[::-1], :] + + return np.array([tl, tr, br, bl], dtype="float32") def clip_det_res(self, points, img_height, img_width): for pno in range(points.shape[0]): From 4b85f7e3e4b0c10b7d0f76e181e30ab56d80c6ce Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 21 Jun 2022 15:24:47 +0800 Subject: [PATCH 06/12] fix --- applications/轻量级车牌识别.md | 2831 -------------------------------- 1 file changed, 2831 deletions(-) delete mode 100644 applications/轻量级车牌识别.md diff --git a/applications/轻量级车牌识别.md b/applications/轻量级车牌识别.md deleted file mode 100644 index b6c3847d14..0000000000 --- a/applications/轻量级车牌识别.md +++ /dev/null @@ -1,2831 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PaddleOCR/轻量级车牌识别.md at dygraph · PaddlePaddle/PaddleOCR · GitHub - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Skip to content - - - - - - - - - - - -
- -
- - - - - - - -
- - - -
- - - - - - - - - -
-
-
- - - - - - - - - - - - - - - - - -
- - - - - - -
- - -
- - - - - - - - -Permalink - -
- -
-
- - - dygraph - - - - -
-
-
- Switch branches/tags - -
- - - -
- -
- -
- - -
- -
- - - - - - - - - - - - - - - -
- - -
-
-
-
- -
- -
- - - Go to file - - -
- - - - - -
-
-
- - - - - - - - - -
- -
-
-
 
-
- -
-
 
- Cannot retrieve contributors at this time -
-
- - - - - - - - - -
- - - - -
-

一种基于PaddleOCR的轻量级车牌识别模型

- -

1. 项目介绍

-

车牌识别(Vehicle License Plate Recognition,VLPR) 是计算机视频图像识别技术在车辆牌照识别中的一种应用。车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来,在高速公路车辆管理,停车场管理和城市交通中得到广泛应用。

-

本项目难点如下:

-
    -
  1. 车牌在图像中的尺度差异大、在车辆上的悬挂位置不固定
  2. -
  3. 车牌图像质量层次不齐: 角度倾斜、图片模糊、光照不足、过曝等问题严重
  4. -
  5. 边缘和端测场景应用对模型大小有限制,推理速度有要求
  6. -
-

针对以上问题, 本例选用 PP-OCRv3 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升25%。

-

aistudio项目链接: 基于PaddleOCR的轻量级车牌识别范例

-

2. 环境搭建

-

本任务基于Aistudio完成, 具体环境如下:

-
    -
  • 操作系统: Linux
  • -
  • PaddlePaddle: 2.3
  • -
  • paddleslim: 2.2.2
  • -
  • PaddleOCR: Release/2.5
  • -
-

下载 PaddleOCR代码

-
git clone -b dygraph https://github.com/PaddlePaddle/PaddleOCR
-

安装依赖库

-
pip install -r PaddleOCR/requirements.txt
-

3. 数据集准备

-

所使用的数据集为 CCPD2020 新能源车牌数据集,该数据集为

-

该数据集分布如下:

- - - - - - - - - - - - - - - - - - - - - -
数据集类型数量
训练集5769
验证集1001
测试集5006
-

数据集图片示例如下: -

-

数据集可以从这里下载 https://aistudio.baidu.com/aistudio/datasetdetail/101595

-

下载好数据集后对数据集进行解压

-
unzip -d /home/aistudio/data /home/aistudio/data/data101595/CCPD2020.zip
-

3.1 数据集标注规则

-

CPPD数据集的图片文件名具有特殊规则,详细可查看:https://github.com/detectRecog/CCPD

-

具体规则如下:

-

例如: 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

-

每个名称可以分为七个字段,以-符号作为分割。这些字段解释如下。

-
    -
  • -

    025:车牌面积与整个图片区域的面积比。025 (25%)

    -
  • -
  • -

    95_113:水平倾斜程度和垂直倾斜度。水平 95度 垂直 113度

    -
  • -
  • -

    154&383_386&473:左上和右下顶点的坐标。左上(154,383) 右下(386,473)

    -
  • -
  • -

    386&473_177&454_154&383_363&402:整个图像中车牌的四个顶点的精确(x,y)坐标。这些坐标从右下角顶点开始。(386,473) (177,454) (154,383) (363,402)

    -
  • -
  • -

    0_0_22_27_27_33_16:CCPD中的每个图像只有一个车牌。每个车牌号码由一个汉字,一个字母和五个字母或数字组成。有效的中文车牌由七个字符组成:省(1个字符),字母(1个字符),字母+数字(5个字符)。“ 0_0_22_27_27_33_16”是每个字符的索引。这三个数组定义如下。每个数组的最后一个字符是字母O,而不是数字0。我们将O用作“无字符”的符号,因为中文车牌字符中没有O。因此以上车牌拼起来即为 皖AY339S

    -
  • -
  • -

    37:牌照区域的亮度。 37 (37%)

    -
  • -
  • -

    15:车牌区域的模糊度。15 (15%)

    -
  • -
-
provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"]
-alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W','X', 'Y', 'Z', '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']
-

3.2 制作符合PP-OCR训练格式的标注文件

-

在开始训练之前,可使用如下代码制作符合PP-OCR训练格式的标注文件。

-
import cv2
-import os
-import json
-from tqdm import tqdm
-import numpy as np
-
-provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"]
-alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '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']
-
-def make_label(img_dir, save_gt_folder, phase):
-    crop_img_save_dir = os.path.join(save_gt_folder, phase, 'crop_imgs')
-    os.makedirs(crop_img_save_dir, exist_ok=True)
-
-    f_det = open(os.path.join(save_gt_folder, phase, 'det.txt'), 'w', encoding='utf-8')
-    f_rec = open(os.path.join(save_gt_folder, phase, 'rec.txt'), 'w', encoding='utf-8')
-
-    i = 0
-    for filename in tqdm(os.listdir(os.path.join(img_dir, phase))):
-        str_list = filename.split('-')
-        if len(str_list) < 5:
-            continue
-        coord_list = str_list[3].split('_')
-        txt_list = str_list[4].split('_')
-        boxes = []
-        for coord in coord_list:
-            boxes.append([int(x) for x in coord.split("&")])
-        boxes = [boxes[2], boxes[3], boxes[0], boxes[1]]
-        lp_number = provinces[int(txt_list[0])] + alphabets[int(txt_list[1])] + ''.join([ads[int(x)] for x in txt_list[2:]])
-
-        # det
-        det_info = [{'points':boxes, 'transcription':lp_number}]
-        f_det.write('{}\t{}\n'.format(os.path.join(phase, filename), json.dumps(det_info, ensure_ascii=False)))
-
-        # rec
-        boxes = np.float32(boxes)
-        img = cv2.imread(os.path.join(img_dir, phase, filename))
-        # crop_img = img[int(boxes[:,1].min()):int(boxes[:,1].max()),int(boxes[:,0].min()):int(boxes[:,0].max())]
-        crop_img = get_rotate_crop_image(img, boxes)
-        crop_img_save_filename = '{}_{}.jpg'.format(i,'_'.join(txt_list))
-        crop_img_save_path = os.path.join(crop_img_save_dir, crop_img_save_filename)
-        cv2.imwrite(crop_img_save_path, crop_img)
-        f_rec.write('{}/crop_imgs/{}\t{}\n'.format(phase, crop_img_save_filename, lp_number))
-        i+=1
-    f_det.close()
-    f_rec.close()
-
-def get_rotate_crop_image(img, points):
-    '''
-    img_height, img_width = img.shape[0:2]
-    left = int(np.min(points[:, 0]))
-    right = int(np.max(points[:, 0]))
-    top = int(np.min(points[:, 1]))
-    bottom = int(np.max(points[:, 1]))
-    img_crop = img[top:bottom, left:right, :].copy()
-    points[:, 0] = points[:, 0] - left
-    points[:, 1] = points[:, 1] - top
-    '''
-    assert len(points) == 4, "shape of points must be 4*2"
-    img_crop_width = int(
-        max(
-            np.linalg.norm(points[0] - points[1]),
-            np.linalg.norm(points[2] - points[3])))
-    img_crop_height = int(
-        max(
-            np.linalg.norm(points[0] - points[3]),
-            np.linalg.norm(points[1] - points[2])))
-    pts_std = np.float32([[0, 0], [img_crop_width, 0],
-                          [img_crop_width, img_crop_height],
-                          [0, img_crop_height]])
-    M = cv2.getPerspectiveTransform(points, pts_std)
-    dst_img = cv2.warpPerspective(
-        img,
-        M, (img_crop_width, img_crop_height),
-        borderMode=cv2.BORDER_REPLICATE,
-        flags=cv2.INTER_CUBIC)
-    dst_img_height, dst_img_width = dst_img.shape[0:2]
-    if dst_img_height * 1.0 / dst_img_width >= 1.5:
-        dst_img = np.rot90(dst_img)
-    return dst_img
-
-img_dir = '/home/aistudio/data/CCPD2020/ccpd_green'
-save_gt_folder = '/home/aistudio/data/CCPD2020/PPOCR'
-# phase = 'train' # change to val and test to make val dataset and test dataset
-for phase in ['train','val','test']:
-    make_label(img_dir, save_gt_folder, phase)
-

通过上述命令可以完成了训练集,验证集和测试集的制作,制作完成的数据集信息如下:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
类型数据集图片地址标签地址图片数量
检测训练集/home/aistudio/data/CCPD2020/ccpd_green/train/home/aistudio/data/CCPD2020/PPOCR/train/det.txt5769
检测验证集/home/aistudio/data/CCPD2020/ccpd_green/val/home/aistudio/data/CCPD2020/PPOCR/val/det.txt1001
检测测试集/home/aistudio/data/CCPD2020/ccpd_green/test/home/aistudio/data/CCPD2020/PPOCR/test/det.txt5006
识别训练集/home/aistudio/data/CCPD2020/PPOCR/train/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt5769
识别验证集/home/aistudio/data/CCPD2020/PPOCR/val/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/val/rec.txt1001
识别测试集/home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt5006
-

在普遍的深度学习流程中,都是在训练集训练,在验证集选择最优模型后在测试集上进行测试。在本例中,我们省略中间步骤,直接在训练集训练,在测试集选择最优模型,因此我们只使用训练集和测试集。

-

4. 实验

-

由于数据集比较少,为了模型更好和更快的收敛,这里选用 PaddleOCR 中的 PP-OCRv3 模型进行文本检测和识别,并且使用 PP-OCRv3 模型参数作为预训练模型。PP-OCRv3在PP-OCRv2的基础上,中文场景端到端Hmean指标相比于PP-OCRv2提升5%, 英文数字模型端到端效果提升11%。详细优化细节请参考PP-OCRv3技术报告。

-

由于车牌场景均为端侧设备部署,因此对速度和模型大小有比较高的要求,因此还需要采用量化训练的方式进行模型大小的压缩和模型推理速度的加速。模型量化可以在基本不损失模型的精度的情况下,将FP32精度的模型参数转换为Int8精度,减小模型参数大小并加速计算,使用量化后的模型在移动端等部署时更具备速度优势。

-

因此,本实验中对于车牌检测和识别有如下3种方案:

-
    -
  1. PP-OCRv3中英文超轻量预训练模型直接预测
  2. -
  3. CCPD车牌数据集在PP-OCRv3模型上fine-tune
  4. -
  5. CCPD车牌数据集在PP-OCRv3模型上fine-tune后量化
  6. -
-

4.1 检测

-

4.1.1 预训练模型直接预测

-

从下表中下载PP-OCRv3文本检测预训练模型

- - - - - - - - - - - - - - - - - - - -
模型名称模型简介配置文件推理模型大小下载地址
ch_PP-OCRv3_det【最新】原始超轻量模型,支持中英文、多语种文本检测ch_PP-OCRv3_det_cml.yml3.8M推理模型 / 训练模型
-

使用如下命令下载预训练模型

-
mkdir models
-cd models
-wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar
-tar -xf ch_PP-OCRv3_det_distill_train.tar
-cd /home/aistudio/PaddleOCR
-

预训练模型下载完成后,我们使用ch_PP-OCRv3_det_student.yml 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下:

-
    -
  1. 模型存储和训练相关: -
      -
    1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址
    2. -
    -
  2. -
  3. 数据集相关 -
      -
    1. Eval.dataset.data_dir:指向测试集图片存放目录
    2. -
    3. Eval.dataset.label_file_list:指向测试集标注文件
    4. -
    -
  4. -
-

上述字段均为必须修改的字段,可以通过修改配置文件的方式改动,也可在不需要修改配置文件的情况下,改变训练的参数。这里使用不改变配置文件的方式 。使用如下命令进行PP-OCRv3文本检测预训练模型的评估

-
python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
-

上述指令中,通过-c 选择训练使用配置文件,通过-o参数在不需要修改配置文件的情况下,改变训练的参数。

-

使用预训练模型进行评估,指标如下所示:

- - - - - - - - - - - - - -
方案hmeans
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%
-

4.1.2 CCPD车牌数据集fine-tune

-

训练

-

为了进行fine-tune训练,我们需要在配置文件中设置需要使用的预训练模型地址,学习率和数据集等参数。 具体如下:

-
    -
  1. 模型存储和训练相关: -
      -
    1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址
    2. -
    3. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔772个step评估一次,772为一个epoch总的step数。
    4. -
    -
  2. -
  3. 优化器相关: -
      -
    1. Optimizer.lr.name: 学习率衰减器设为常量 Const
    2. -
    3. Optimizer.lr.learning_rate: 做 fine-tune 实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍
    4. -
    5. Optimizer.lr.warmup_epoch: warmup_epoch设为0
    6. -
    -
  4. -
  5. 数据集相关: -
      -
    1. Train.dataset.data_dir:指向训练集图片存放目录
    2. -
    3. Train.dataset.label_file_list:指向训练集标注文件
    4. -
    5. Eval.dataset.data_dir:指向测试集图片存放目录
    6. -
    7. Eval.dataset.label_file_list:指向测试集标注文件
    8. -
    -
  6. -
-

使用如下代码即可启动在CCPD车牌数据集上的fine-tune。

-
python tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
-    Global.save_model_dir=output/CCPD/det \
-    Global.eval_batch_step="[0, 772]" \
-    Optimizer.lr.name=Const \
-    Optimizer.lr.learning_rate=0.0005 \
-    Optimizer.lr.warmup_epoch=0 \
-    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/det.txt] \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
-

在上述命令中,通过-o的方式修改了配置文件中的参数。

-

训练好的模型地址为: det_ppocr_v3_finetune.tar

-

评估

-

训练完成后使用如下命令进行评估

-
python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
-

使用预训练模型和CCPD车牌数据集fine-tune,指标分别如下:

- - - - - - - - - - - - - - - - - -
方案hmeans
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%
-

可以看到进行fine-tune能显著提升车牌检测的效果。

-

4.1.3 CCPD车牌数据集fine-tune+量化训练

-

此处采用 PaddleOCR 中提供好的量化教程对模型进行量化训练。

-

量化训练可通过如下命令启动:

-
python3.7 deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
-    Global.save_model_dir=output/CCPD/det_quant \
-    Global.eval_batch_step="[0, 772]" \
-    Optimizer.lr.name=Const \
-    Optimizer.lr.learning_rate=0.0005 \
-    Optimizer.lr.warmup_epoch=0 \
-    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/det.txt] \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
-

训练好的模型地址为: det_ppocr_v3_quant.tar

-

量化后指标对比如下

- - - - - - - - - - - - - - - - - - - - - - - -
方案hmeans模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%2.5M223ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化98.91%1M189ms
-

可以看到通过量化训练在精度几乎无损的情况下,降低模型体积60%并且推理速度提升15%。

-

速度测试基于PaddleOCR lite教程完成。

-

4.1.4 模型导出

-

使用如下命令可以将训练好的模型进行导出

-
    -
  • 非量化模型
  • -
-
python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
-    Global.save_inference_dir=output/det/infer
-
    -
  • 量化模型
  • -
-
python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det_quant/best_accuracy.pdparams \
-    Global.save_inference_dir=output/det/infer
-

4.2 识别

-

4.2.1 预训练模型直接预测

-

从下表中下载PP-OCRv3文本识别预训练模型

- - - - - - - - - - - - - - - - - - - -
模型名称模型简介配置文件推理模型大小下载地址
ch_PP-OCRv3_rec【最新】原始超轻量模型,支持中英文、数字识别ch_PP-OCRv3_rec_distillation.yml12.4M推理模型 / 训练模型
-

使用如下命令下载预训练模型

-
mkdir models
-cd models
-wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_train.tar
-tar -xf ch_PP-OCRv3_rec_train.tar
-cd /home/aistudio/PaddleOCR
-

PaddleOCR提供的PP-OCRv3识别模型采用蒸馏训练策略,因此提供的预训练模型中会包含Teacher和Student模型的参数,详细信息可参考knowledge_distillation.md。 因此,模型下载完成后需要使用如下代码提取Student模型的参数:

-
import paddle
-# 加载预训练模型
-all_params = paddle.load("models/ch_PP-OCRv3_rec_train/best_accuracy.pdparams")
-# 查看权重参数的keys
-print(all_params.keys())
-# 学生模型的权重提取
-s_params = {key[len("Student."):]: all_params[key] for key in all_params if "Student." in key}
-# 查看学生模型权重参数的keys
-print(s_params.keys())
-# 保存
-paddle.save(s_params, "models/ch_PP-OCRv3_rec_train/student.pdparams")
-

预训练模型下载完成后,我们使用ch_PP-OCRv3_rec.yml 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下:

-
    -
  1. 模型存储和训练相关: -
      -
    1. Global.pretrained_model: 指向PP-OCRv3文本识别预训练模型地址
    2. -
    -
  2. -
  3. 数据集相关 -
      -
    1. Eval.dataset.data_dir:指向测试集图片存放目录
    2. -
    3. Eval.dataset.label_file_list:指向测试集标注文件
    4. -
    -
  4. -
-

使用如下命令进行PP-OCRv3文本识别预训练模型的评估

-
python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-

评估部分日志如下:

-
[2022/05/12 19:52:02] ppocr INFO: load pretrain successful from models/ch_PP-OCRv3_rec_train/best_accuracy
-eval model:: 100%|██████████████████████████████| 40/40 [00:15<00:00,  2.57it/s]
-[2022/05/12 19:52:17] ppocr INFO: metric eval ***************
-[2022/05/12 19:52:17] ppocr INFO: acc:0.0
-[2022/05/12 19:52:17] ppocr INFO: norm_edit_dis:0.8656084923002452
-[2022/05/12 19:52:17] ppocr INFO: Teacher_acc:0.000399520574511545
-[2022/05/12 19:52:17] ppocr INFO: Teacher_norm_edit_dis:0.8657902943394548
-[2022/05/12 19:52:17] ppocr INFO: fps:1443.1801978719905
-
-

使用预训练模型进行评估,指标如下所示:

- - - - - - - - - - - - - -
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0%
-

从评估日志中可以看到,直接使用PP-OCRv3预训练模型进行评估,acc非常低,但是norm_edit_dis很高。因此,我们猜测是模型大部分文字识别是对的,只有少部分文字识别错误。使用如下命令进行infer查看模型的推理结果进行验证:

-
python tools/infer_rec.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
-    Global.infer_img=/home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/0_0_0_3_32_30_31_30_30.jpg
-

输出部分日志如下:

-
[2022/05/01 08:51:57] ppocr INFO: train with paddle 2.2.2 and device CUDAPlace(0)
-W0501 08:51:57.127391 11326 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 11.0, Runtime API Version: 10.1
-W0501 08:51:57.132315 11326 device_context.cc:465] device: 0, cuDNN Version: 7.6.
-[2022/05/01 08:52:00] ppocr INFO: load pretrain successful from models/ch_PP-OCRv3_rec_train/student
-[2022/05/01 08:52:00] ppocr INFO: infer_img: /home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/0_0_3_32_30_31_30_30.jpg
-[2022/05/01 08:52:00] ppocr INFO:      result: {"Student": {"label": "皖A·D86766", "score": 0.9552637934684753}, "Teacher": {"label": "皖A·D86766", "score": 0.9917094707489014}}
-[2022/05/01 08:52:00] ppocr INFO: success!
-

从infer结果可以看到,车牌中的文字大部分都识别正确,只是多识别出了一个·。针对这种情况,有如下两种方案:

-
    -
  1. 直接通过后处理去掉多识别的·。
  2. -
  3. 进行 fine-tune。
  4. -
-

4.2.2 预训练模型直接预测+改动后处理

-

直接通过后处理去掉多识别的·,在后处理的改动比较简单,只需在 ppocr/postprocess/rec_postprocess.py 文件的76行添加如下代码:

-
text = text.replace('·','')
-

改动前后指标对比:

- - - - - - - - - - - - - - - - - -
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0.2%
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%
-

可以看到,去掉多余的·能大幅提高精度。

-

4.2.3 CCPD车牌数据集fine-tune

-

训练

-

为了进行fine-tune训练,我们需要在配置文件中设置需要使用的预训练模型地址,学习率和数据集等参数。 具体如下:

-
    -
  1. 模型存储和训练相关: -
      -
    1. Global.pretrained_model: 指向PP-OCRv3文本识别预训练模型地址
    2. -
    3. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔45个step评估一次,45为一个epoch总的step数。
    4. -
    -
  2. -
  3. 优化器相关 -
      -
    1. Optimizer.lr.name: 学习率衰减器设为常量 Const
    2. -
    3. Optimizer.lr.learning_rate: 做 fine-tune 实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍
    4. -
    5. Optimizer.lr.warmup_epoch: warmup_epoch设为0
    6. -
    -
  4. -
  5. 数据集相关 -
      -
    1. Train.dataset.data_dir:指向训练集图片存放目录
    2. -
    3. Train.dataset.label_file_list:指向训练集标注文件
    4. -
    5. Eval.dataset.data_dir:指向测试集图片存放目录
    6. -
    7. Eval.dataset.label_file_list:指向测试集标注文件
    8. -
    -
  6. -
-

使用如下命令启动 fine-tune

-
python tools/train.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
-    Global.save_model_dir=output/CCPD/rec/ \
-    Global.eval_batch_step="[0, 90]" \
-    Optimizer.lr.name=Const \
-    Optimizer.lr.learning_rate=0.0005 \
-    Optimizer.lr.warmup_epoch=0 \
-    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt] \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-

训练好的模型地址为: rec_ppocr_v3_finetune.tar

-

评估

-

训练完成后使用如下命令进行评估

-
python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-

使用预训练模型和CCPD车牌数据集fine-tune,指标分别如下:

- - - - - - - - - - - - - - - - - - - - - -
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0%
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%
-

可以看到进行fine-tune能显著提升车牌识别的效果。

-

4.2.4 CCPD车牌数据集fine-tune+量化训练

-

此处采用 PaddleOCR 中提供好的量化教程对模型进行量化训练。

-

量化训练可通过如下命令启动:

-
python3.7 deploy/slim/quantization/quant.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
-    Global.save_model_dir=output/CCPD/rec_quant/ \
-    Global.eval_batch_step="[0, 90]" \
-    Optimizer.lr.name=Const \
-    Optimizer.lr.learning_rate=0.0005 \
-    Optimizer.lr.warmup_epoch=0 \
-    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt] \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-

训练好的模型地址为: rec_ppocr_v3_quant.tar

-

量化后指标对比如下

- - - - - - - - - - - - - - - - - - - - - - - -
方案acc模型大小预测速度(lite)
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化93.4%4.8M1.8ms
-

可以看到量化后能降低模型体积53%并且推理速度提升57%,但是由于识别数据过少,量化带来了1%的精度下降。

-

速度测试基于PaddleOCR lite教程完成。

-

4.2.5 模型导出

-

使用如下命令可以将训练好的模型进行导出。

-
    -
  • 非量化模型
  • -
-
python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/rec/infer
-
    -
  • 量化模型
  • -
-
python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec_quant/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/rec_quant/infer
-

4.3 计算End2End指标

-

端到端指标可通过 PaddleOCR内置脚本 进行计算,具体步骤如下:

-
    -
  1. 导出模型
  2. -
-

通过如下命令进行模型的导出。注意,量化模型导出时,需要配置eval数据集

-
# 检测模型
-
-# 预训练模型
-python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
-    Global.save_inference_dir=output/ch_PP-OCRv3_det_distill_train/infer
-
-# 非量化模型
-python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/det/infer
-
-# 量化模型
-python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det_quant/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/det_quant/infer \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt] \
-    Eval.loader.num_workers=0
-
-# 识别模型
-
-# 预训练模型
-python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
-    Global.save_inference_dir=output/ch_PP-OCRv3_rec_train/infer
-
-# 非量化模型
-python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/rec/infer
-
-# 量化模型
-python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec_quant/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/rec_quant/infer \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-
    -
  1. 用导出的模型对测试集进行预测
  2. -
-

此处,分别使用PP-OCRv3预训练模型,fintune模型和量化模型对测试集的所有图像进行预测,命令如下:

-
# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型
-python3 tools/infer/predict_system.py --det_model_dir=models/ch_PP-OCRv3_det_distill_train/infer --rec_model_dir=models/ch_PP-OCRv3_rec_train/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/pretrain --use_dilation=true
-
-# PP-OCRv3中英文超轻量检测预训练模型+fine-tune,PP-OCRv3中英文超轻量识别预训练模型+fine-tune
-python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det/infer --rec_model_dir=output/CCPD/rec/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/fine-tune --use_dilation=true
-
-# PP-OCRv3中英文超轻量检测预训练模型 fine-tune +量化,PP-OCRv3中英文超轻量识别预训练模型 fine-tune +量化 结果转换和评估
-python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det_quant/infer --rec_model_dir=output/CCPD/rec_quant/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/quant --use_dilation=true
-
    -
  1. 转换label并计算指标
  2. -
-

将gt和上一步保存的预测结果转换为端对端评测需要的数据格式,并根据转换后的数据进行端到端指标计算

-
python3 tools/end2end/convert_ppocr_label.py --mode=gt --label_path=/home/aistudio/data/CCPD2020/PPOCR/test/det.txt --save_folder=end2end/gt
-
-# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型 结果转换和评估
-python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/pretrain/system_results.txt --save_folder=end2end/pretrain
-python3 tools/end2end/eval_end2end.py end2end/gt end2end/pretrain
-
-# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·` 结果转换和评估
-# 需手动修改后处理函数
-python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/post/system_results.txt --save_folder=end2end/post
-python3 tools/end2end/eval_end2end.py end2end/gt end2end/post
-
-# PP-OCRv3中英文超轻量检测预训练模型 fine-tune,PP-OCRv3中英文超轻量识别预训练模型 fine-tune 结果转换和评估
-python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/fine-tune/system_results.txt --save_folder=end2end/fine-tune
-python3 tools/end2end/eval_end2end.py end2end/gt end2end/fine-tune
-
-# PP-OCRv3中英文超轻量检测预训练模型 fine-tune +量化,PP-OCRv3中英文超轻量识别预训练模型 fine-tune +量化 结果转换和评估
-python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/quant/system_results.txt --save_folder=end2end/quant
-python3 tools/end2end/eval_end2end.py end2end/gt end2end/quant
-

日志如下:

-
The convert label saved in end2end/gt
-The convert label saved in end2end/pretrain
-start testing...
-hit, dt_count, gt_count 2 5988 5006
-character_acc: 70.42%
-avg_edit_dist_field: 2.37
-avg_edit_dist_img: 2.37
-precision: 0.03%
-recall: 0.04%
-fmeasure: 0.04%
-The convert label saved in end2end/post
-start testing...
-hit, dt_count, gt_count 4224 5988 5006
-character_acc: 81.59%
-avg_edit_dist_field: 1.47
-avg_edit_dist_img: 1.47
-precision: 70.54%
-recall: 84.38%
-fmeasure: 76.84%
-The convert label saved in end2end/fine-tune
-start testing...
-hit, dt_count, gt_count 4286 4898 5006
-character_acc: 94.16%
-avg_edit_dist_field: 0.47
-avg_edit_dist_img: 0.47
-precision: 87.51%
-recall: 85.62%
-fmeasure: 86.55%
-The convert label saved in end2end/quant
-start testing...
-hit, dt_count, gt_count 4349 4951 5006
-character_acc: 94.13%
-avg_edit_dist_field: 0.47
-avg_edit_dist_img: 0.47
-precision: 87.84%
-recall: 86.88%
-fmeasure: 87.36%
-

各个方案端到端指标如下:

- - - - - - - - - - - - - - - - - - - - - - - - - -
模型指标
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.04%
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
78.27%
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
87.14%
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
88%
-

从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到78.27%,在CCPD数据集上进行 fine-tune 后指标进一步提升到87.14%, 在经过量化训练之后,由于检测模型的recall变高,指标进一步提升到88%。但是这个结果仍旧不符合检测模型+识别模型的真实性能(99%*94%=93%),因此我们需要对 base case 进行具体分析。

-

在之前的端到端预测结果中,可以看到很多不符合车牌标注的文字被识别出来, 因此可以进行简单的过滤来提升precision

-

为了快速评估,我们在 tools/end2end/convert_ppocr_label.py 脚本的 58 行加入如下代码,对非8个字符的结果进行过滤

-
if len(txt) != 8: # 车牌字符串长度为8
-    continue
-

此外,通过可视化box可以发现有很多框都是竖直翻转之后的框,并且没有完全框住车牌边界,因此需要进行框的竖直翻转以及轻微扩大,示意图如下:

-

-

修改前后个方案指标对比如下:

-

各个方案端到端指标如下:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
模型baseA:识别结果过滤B:use_dilationC:flip_boxbest
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.04%0.08%0.02%0.05%0.00%(A)
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
78.27%90.84%78.61%79.43%91.66%(A+B+C)
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
87.14%90.40%87.66%89.9892.5%(A+B+C)
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
88%90.54%88.5%89.46%92.02%(A+B+C)
-

从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到91.66%,在CCPD数据集上进行 fine-tune 后指标进一步提升到92.5%, 在经过量化训练之后,指标变为92.02%。

-

4.4 部署

-
    -
  • 基于 Paddle Inference 的python推理
  • -
-

检测模型和识别模型分别 fine-tune 并导出为inference模型之后,可以使用如下命令基于 Paddle Inference 进行端到端推理并对结果进行可视化。

-
python tools/infer/predict_system.py \
-    --det_model_dir=output/CCPD/det/infer/ \
-    --rec_model_dir=output/CCPD/rec/infer/ \
-    --image_dir="/home/aistudio/data/CCPD2020/ccpd_green/test/04131106321839081-92_258-159&509_530&611-527&611_172&599_159&509_530&525-0_0_3_32_30_31_30_30-109-106.jpg" \
-    --rec_image_shape=3,48,320
-

推理结果如下

-

-
    -
  • 端侧部署
  • -
-

端侧部署我们采用基于 PaddleLite 的 cpp 推理。Paddle Lite是飞桨轻量化推理引擎,为手机、IOT端提供高效推理能力,并广泛整合跨平台硬件,为端侧部署及应用落地问题提供轻量化的部署方案。具体可参考 PaddleOCR lite教程

-

4.5 实验总结

-

我们分别使用PP-OCRv3中英文超轻量预训练模型在车牌数据集上进行了直接评估和 fine-tune 和 fine-tune +量化3种方案的实验,并基于PaddleOCR lite教程进行了速度测试,指标对比如下:

-
    -
  • 检测
  • -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
方案hmeans模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%2.5M233ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%2.5M233ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune + 量化98.91%1M189ms
-
    -
  • 识别
  • -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
方案acc模型大小预测速度(lite)
PP-OCRv3中英文超轻量识别预训练模型直接预测0%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%10.3M4,2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化93.4%4.8M1.8ms
-
    -
  • 端到端指标如下:
  • -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
方案fmeasure模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.08%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
91.66%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
92.5%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
92.02%5.8M224ms
-

结论

-

PP-OCRv3的检测模型在未经过fine-tune的情况下,在车牌数据集上也有一定的精度,经过 fine-tune 后能够极大的提升检测效果,精度达到99%。在使用量化训练后检测模型的精度几乎无损,并且模型大小压缩60%。

-

PP-OCRv3的识别模型在未经过fine-tune的情况下,在车牌数据集上精度为0,但是经过分析可以知道,模型大部分字符都预测正确,但是会多预测一个特殊字符,去掉这个特殊字符后,精度达到90%。PP-OCRv3识别模型在经过 fine-tune 后识别精度进一步提升,达到94.4%。在使用量化训练后识别模型大小压缩53%,但是由于数据量多少,带来了1%的精度损失。

-

从端到端结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到91.66%,在CCPD数据集上进行 fine-tune 后指标进一步提升到92.5%, 在经过量化训练之后,指标轻微下降到92.02%但模型大小降低54%。

-
-
- -
- -
- - - -
- - -
- - -
-
- - - - -
- -
- - -
- - -
-
- -
- - - - - - - - - - - - - - - - - - - - From 8b0b5d1ee56bdef51bb0e1d9897d9051df291d4f Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 21 Jun 2022 15:36:36 +0800 Subject: [PATCH 07/12] pre-commit --- applications/轻量级车牌识别.md | 2902 ++++++++++++++++++++++++++++++++ 1 file changed, 2902 insertions(+) create mode 100644 applications/轻量级车牌识别.md diff --git a/applications/轻量级车牌识别.md b/applications/轻量级车牌识别.md new file mode 100644 index 0000000000..e0f4706f14 --- /dev/null +++ b/applications/轻量级车牌识别.md @@ -0,0 +1,2902 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PaddleOCR/轻量级车牌识别.md at dygraph · PaddlePaddle/PaddleOCR · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to content + + + + + + + + + + + +
+ +
+ + + + + + + +
+ + + +
+ + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + +
+ + + + + + + + +Permalink + +
+ +
+
+ + + dygraph + + + + +
+
+
+ Switch branches/tags + +
+ + + +
+ +
+ +
+ + +
+ +
+ + + + + + + + + + + + + + + +
+ + +
+
+
+
+ +
+ +
+ + + Go to file + + +
+ + + + + +
+
+
+ + + + + + + + + +
+ +
+
+ + @MissPenguin + +
+ + + + + + +
+
+ + Latest commit + 10a3f25 + Jun 15, 2022 + + + + + + History + + +
+
+ +
+ +
+
+ + + 2 + + contributors + + +
+ +

+ Users who have contributed to this file +

+
+ + + + + + +
+
+ + + @WenmuZhou + + @MissPenguin + + + +
+
+ + + + + + + + + +
+ + + + +
+

一种基于PaddleOCR的轻量级车牌识别模型

+ +

1. 项目介绍

+

车牌识别(Vehicle License Plate Recognition,VLPR) 是计算机视频图像识别技术在车辆牌照识别中的一种应用。车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来,在高速公路车辆管理,停车场管理和城市交通中得到广泛应用。

+

本项目难点如下:

+
    +
  1. 车牌在图像中的尺度差异大、在车辆上的悬挂位置不固定
  2. +
  3. 车牌图像质量层次不齐: 角度倾斜、图片模糊、光照不足、过曝等问题严重
  4. +
  5. 边缘和端测场景应用对模型大小有限制,推理速度有要求
  6. +
+

针对以上问题, 本例选用 PP-OCRv3 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升25%。

+

aistudio项目链接: 基于PaddleOCR的轻量级车牌识别范例

+

2. 环境搭建

+

本任务基于Aistudio完成, 具体环境如下:

+
    +
  • 操作系统: Linux
  • +
  • PaddlePaddle: 2.3
  • +
  • paddleslim: 2.2.2
  • +
  • PaddleOCR: Release/2.5
  • +
+

下载 PaddleOCR代码

+
git clone -b dygraph https://github.com/PaddlePaddle/PaddleOCR
+

安装依赖库

+
pip install -r PaddleOCR/requirements.txt
+

3. 数据集准备

+

所使用的数据集为 CCPD2020 新能源车牌数据集,该数据集为

+

该数据集分布如下:

+ + + + + + + + + + + + + + + + + + + + + +
数据集类型数量
训练集5769
验证集1001
测试集5006
+

数据集图片示例如下: +

+

数据集可以从这里下载 https://aistudio.baidu.com/aistudio/datasetdetail/101595

+

下载好数据集后对数据集进行解压

+
unzip -d /home/aistudio/data /home/aistudio/data/data101595/CCPD2020.zip
+

3.1 数据集标注规则

+

CPPD数据集的图片文件名具有特殊规则,详细可查看:https://github.com/detectRecog/CCPD

+

具体规则如下:

+

例如: 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

+

每个名称可以分为七个字段,以-符号作为分割。这些字段解释如下。

+
    +
  • +

    025:车牌面积与整个图片区域的面积比。025 (25%)

    +
  • +
  • +

    95_113:水平倾斜程度和垂直倾斜度。水平 95度 垂直 113度

    +
  • +
  • +

    154&383_386&473:左上和右下顶点的坐标。左上(154,383) 右下(386,473)

    +
  • +
  • +

    386&473_177&454_154&383_363&402:整个图像中车牌的四个顶点的精确(x,y)坐标。这些坐标从右下角顶点开始。(386,473) (177,454) (154,383) (363,402)

    +
  • +
  • +

    0_0_22_27_27_33_16:CCPD中的每个图像只有一个车牌。每个车牌号码由一个汉字,一个字母和五个字母或数字组成。有效的中文车牌由七个字符组成:省(1个字符),字母(1个字符),字母+数字(5个字符)。“ 0_0_22_27_27_33_16”是每个字符的索引。这三个数组定义如下。每个数组的最后一个字符是字母O,而不是数字0。我们将O用作“无字符”的符号,因为中文车牌字符中没有O。因此以上车牌拼起来即为 皖AY339S

    +
  • +
  • +

    37:牌照区域的亮度。 37 (37%)

    +
  • +
  • +

    15:车牌区域的模糊度。15 (15%)

    +
  • +
+
provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"]
+alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W','X', 'Y', 'Z', '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']
+

3.2 制作符合PP-OCR训练格式的标注文件

+

在开始训练之前,可使用如下代码制作符合PP-OCR训练格式的标注文件。

+
import cv2
+import os
+import json
+from tqdm import tqdm
+import numpy as np
+
+provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"]
+alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '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']
+
+def make_label(img_dir, save_gt_folder, phase):
+    crop_img_save_dir = os.path.join(save_gt_folder, phase, 'crop_imgs')
+    os.makedirs(crop_img_save_dir, exist_ok=True)
+
+    f_det = open(os.path.join(save_gt_folder, phase, 'det.txt'), 'w', encoding='utf-8')
+    f_rec = open(os.path.join(save_gt_folder, phase, 'rec.txt'), 'w', encoding='utf-8')
+
+    i = 0
+    for filename in tqdm(os.listdir(os.path.join(img_dir, phase))):
+        str_list = filename.split('-')
+        if len(str_list) < 5:
+            continue
+        coord_list = str_list[3].split('_')
+        txt_list = str_list[4].split('_')
+        boxes = []
+        for coord in coord_list:
+            boxes.append([int(x) for x in coord.split("&")])
+        boxes = [boxes[2], boxes[3], boxes[0], boxes[1]]
+        lp_number = provinces[int(txt_list[0])] + alphabets[int(txt_list[1])] + ''.join([ads[int(x)] for x in txt_list[2:]])
+
+        # det
+        det_info = [{'points':boxes, 'transcription':lp_number}]
+        f_det.write('{}\t{}\n'.format(os.path.join(phase, filename), json.dumps(det_info, ensure_ascii=False)))
+
+        # rec
+        boxes = np.float32(boxes)
+        img = cv2.imread(os.path.join(img_dir, phase, filename))
+        # crop_img = img[int(boxes[:,1].min()):int(boxes[:,1].max()),int(boxes[:,0].min()):int(boxes[:,0].max())]
+        crop_img = get_rotate_crop_image(img, boxes)
+        crop_img_save_filename = '{}_{}.jpg'.format(i,'_'.join(txt_list))
+        crop_img_save_path = os.path.join(crop_img_save_dir, crop_img_save_filename)
+        cv2.imwrite(crop_img_save_path, crop_img)
+        f_rec.write('{}/crop_imgs/{}\t{}\n'.format(phase, crop_img_save_filename, lp_number))
+        i+=1
+    f_det.close()
+    f_rec.close()
+
+def get_rotate_crop_image(img, points):
+    '''
+    img_height, img_width = img.shape[0:2]
+    left = int(np.min(points[:, 0]))
+    right = int(np.max(points[:, 0]))
+    top = int(np.min(points[:, 1]))
+    bottom = int(np.max(points[:, 1]))
+    img_crop = img[top:bottom, left:right, :].copy()
+    points[:, 0] = points[:, 0] - left
+    points[:, 1] = points[:, 1] - top
+    '''
+    assert len(points) == 4, "shape of points must be 4*2"
+    img_crop_width = int(
+        max(
+            np.linalg.norm(points[0] - points[1]),
+            np.linalg.norm(points[2] - points[3])))
+    img_crop_height = int(
+        max(
+            np.linalg.norm(points[0] - points[3]),
+            np.linalg.norm(points[1] - points[2])))
+    pts_std = np.float32([[0, 0], [img_crop_width, 0],
+                          [img_crop_width, img_crop_height],
+                          [0, img_crop_height]])
+    M = cv2.getPerspectiveTransform(points, pts_std)
+    dst_img = cv2.warpPerspective(
+        img,
+        M, (img_crop_width, img_crop_height),
+        borderMode=cv2.BORDER_REPLICATE,
+        flags=cv2.INTER_CUBIC)
+    dst_img_height, dst_img_width = dst_img.shape[0:2]
+    if dst_img_height * 1.0 / dst_img_width >= 1.5:
+        dst_img = np.rot90(dst_img)
+    return dst_img
+
+img_dir = '/home/aistudio/data/CCPD2020/ccpd_green'
+save_gt_folder = '/home/aistudio/data/CCPD2020/PPOCR'
+# phase = 'train' # change to val and test to make val dataset and test dataset
+for phase in ['train','val','test']:
+    make_label(img_dir, save_gt_folder, phase)
+

通过上述命令可以完成了训练集,验证集和测试集的制作,制作完成的数据集信息如下:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
类型数据集图片地址标签地址图片数量
检测训练集/home/aistudio/data/CCPD2020/ccpd_green/train/home/aistudio/data/CCPD2020/PPOCR/train/det.txt5769
检测验证集/home/aistudio/data/CCPD2020/ccpd_green/val/home/aistudio/data/CCPD2020/PPOCR/val/det.txt1001
检测测试集/home/aistudio/data/CCPD2020/ccpd_green/test/home/aistudio/data/CCPD2020/PPOCR/test/det.txt5006
识别训练集/home/aistudio/data/CCPD2020/PPOCR/train/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt5769
识别验证集/home/aistudio/data/CCPD2020/PPOCR/val/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/val/rec.txt1001
识别测试集/home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt5006
+

在普遍的深度学习流程中,都是在训练集训练,在验证集选择最优模型后在测试集上进行测试。在本例中,我们省略中间步骤,直接在训练集训练,在测试集选择最优模型,因此我们只使用训练集和测试集。

+

4. 实验

+

由于数据集比较少,为了模型更好和更快的收敛,这里选用 PaddleOCR 中的 PP-OCRv3 模型进行文本检测和识别,并且使用 PP-OCRv3 模型参数作为预训练模型。PP-OCRv3在PP-OCRv2的基础上,中文场景端到端Hmean指标相比于PP-OCRv2提升5%, 英文数字模型端到端效果提升11%。详细优化细节请参考PP-OCRv3技术报告。

+

由于车牌场景均为端侧设备部署,因此对速度和模型大小有比较高的要求,因此还需要采用量化训练的方式进行模型大小的压缩和模型推理速度的加速。模型量化可以在基本不损失模型的精度的情况下,将FP32精度的模型参数转换为Int8精度,减小模型参数大小并加速计算,使用量化后的模型在移动端等部署时更具备速度优势。

+

因此,本实验中对于车牌检测和识别有如下3种方案:

+
    +
  1. PP-OCRv3中英文超轻量预训练模型直接预测
  2. +
  3. CCPD车牌数据集在PP-OCRv3模型上fine-tune
  4. +
  5. CCPD车牌数据集在PP-OCRv3模型上fine-tune后量化
  6. +
+

4.1 检测

+

4.1.1 预训练模型直接预测

+

从下表中下载PP-OCRv3文本检测预训练模型

+ + + + + + + + + + + + + + + + + + + +
模型名称模型简介配置文件推理模型大小下载地址
ch_PP-OCRv3_det【最新】原始超轻量模型,支持中英文、多语种文本检测ch_PP-OCRv3_det_cml.yml3.8M推理模型 / 训练模型
+

使用如下命令下载预训练模型

+
mkdir models
+cd models
+wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar
+tar -xf ch_PP-OCRv3_det_distill_train.tar
+cd /home/aistudio/PaddleOCR
+

预训练模型下载完成后,我们使用ch_PP-OCRv3_det_student.yml 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下:

+
    +
  1. 模型存储和训练相关: +
      +
    1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址
    2. +
    +
  2. +
  3. 数据集相关 +
      +
    1. Eval.dataset.data_dir:指向测试集图片存放目录
    2. +
    3. Eval.dataset.label_file_list:指向测试集标注文件
    4. +
    +
  4. +
+

上述字段均为必须修改的字段,可以通过修改配置文件的方式改动,也可在不需要修改配置文件的情况下,改变训练的参数。这里使用不改变配置文件的方式 。使用如下命令进行PP-OCRv3文本检测预训练模型的评估

+
python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
+

上述指令中,通过-c 选择训练使用配置文件,通过-o参数在不需要修改配置文件的情况下,改变训练的参数。

+

使用预训练模型进行评估,指标如下所示:

+ + + + + + + + + + + + + +
方案hmeans
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%
+

4.1.2 CCPD车牌数据集fine-tune

+

训练

+

为了进行fine-tune训练,我们需要在配置文件中设置需要使用的预训练模型地址,学习率和数据集等参数。 具体如下:

+
    +
  1. 模型存储和训练相关: +
      +
    1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址
    2. +
    3. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔772个step评估一次,772为一个epoch总的step数。
    4. +
    +
  2. +
  3. 优化器相关: +
      +
    1. Optimizer.lr.name: 学习率衰减器设为常量 Const
    2. +
    3. Optimizer.lr.learning_rate: 做 fine-tune 实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍
    4. +
    5. Optimizer.lr.warmup_epoch: warmup_epoch设为0
    6. +
    +
  4. +
  5. 数据集相关: +
      +
    1. Train.dataset.data_dir:指向训练集图片存放目录
    2. +
    3. Train.dataset.label_file_list:指向训练集标注文件
    4. +
    5. Eval.dataset.data_dir:指向测试集图片存放目录
    6. +
    7. Eval.dataset.label_file_list:指向测试集标注文件
    8. +
    +
  6. +
+

使用如下代码即可启动在CCPD车牌数据集上的fine-tune。

+
python tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
+    Global.save_model_dir=output/CCPD/det \
+    Global.eval_batch_step="[0, 772]" \
+    Optimizer.lr.name=Const \
+    Optimizer.lr.learning_rate=0.0005 \
+    Optimizer.lr.warmup_epoch=0 \
+    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
+    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/det.txt] \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
+

在上述命令中,通过-o的方式修改了配置文件中的参数。

+

训练好的模型地址为: det_ppocr_v3_finetune.tar

+

评估

+

训练完成后使用如下命令进行评估

+
python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
+

使用预训练模型和CCPD车牌数据集fine-tune,指标分别如下:

+ + + + + + + + + + + + + + + + + +
方案hmeans
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%
+

可以看到进行fine-tune能显著提升车牌检测的效果。

+

4.1.3 CCPD车牌数据集fine-tune+量化训练

+

此处采用 PaddleOCR 中提供好的量化教程对模型进行量化训练。

+

量化训练可通过如下命令启动:

+
python3.7 deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
+    Global.save_model_dir=output/CCPD/det_quant \
+    Global.eval_batch_step="[0, 772]" \
+    Optimizer.lr.name=Const \
+    Optimizer.lr.learning_rate=0.0005 \
+    Optimizer.lr.warmup_epoch=0 \
+    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
+    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/det.txt] \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
+

训练好的模型地址为: det_ppocr_v3_quant.tar

+

量化后指标对比如下

+ + + + + + + + + + + + + + + + + + + + + + + +
方案hmeans模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%2.5M223ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化98.91%1M189ms
+

可以看到通过量化训练在精度几乎无损的情况下,降低模型体积60%并且推理速度提升15%。

+

速度测试基于PaddleOCR lite教程完成。

+

4.1.4 模型导出

+

使用如下命令可以将训练好的模型进行导出

+
    +
  • 非量化模型
  • +
+
python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
+    Global.save_inference_dir=output/det/infer
+
    +
  • 量化模型
  • +
+
python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=output/CCPD/det_quant/best_accuracy.pdparams \
+    Global.save_inference_dir=output/det/infer
+

4.2 识别

+

4.2.1 预训练模型直接预测

+

从下表中下载PP-OCRv3文本识别预训练模型

+ + + + + + + + + + + + + + + + + + + +
模型名称模型简介配置文件推理模型大小下载地址
ch_PP-OCRv3_rec【最新】原始超轻量模型,支持中英文、数字识别ch_PP-OCRv3_rec_distillation.yml12.4M推理模型 / 训练模型
+

使用如下命令下载预训练模型

+
mkdir models
+cd models
+wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_train.tar
+tar -xf ch_PP-OCRv3_rec_train.tar
+cd /home/aistudio/PaddleOCR
+

PaddleOCR提供的PP-OCRv3识别模型采用蒸馏训练策略,因此提供的预训练模型中会包含Teacher和Student模型的参数,详细信息可参考knowledge_distillation.md。 因此,模型下载完成后需要使用如下代码提取Student模型的参数:

+
import paddle
+# 加载预训练模型
+all_params = paddle.load("models/ch_PP-OCRv3_rec_train/best_accuracy.pdparams")
+# 查看权重参数的keys
+print(all_params.keys())
+# 学生模型的权重提取
+s_params = {key[len("Student."):]: all_params[key] for key in all_params if "Student." in key}
+# 查看学生模型权重参数的keys
+print(s_params.keys())
+# 保存
+paddle.save(s_params, "models/ch_PP-OCRv3_rec_train/student.pdparams")
+

预训练模型下载完成后,我们使用ch_PP-OCRv3_rec.yml 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下:

+
    +
  1. 模型存储和训练相关: +
      +
    1. Global.pretrained_model: 指向PP-OCRv3文本识别预训练模型地址
    2. +
    +
  2. +
  3. 数据集相关 +
      +
    1. Eval.dataset.data_dir:指向测试集图片存放目录
    2. +
    3. Eval.dataset.label_file_list:指向测试集标注文件
    4. +
    +
  4. +
+

使用如下命令进行PP-OCRv3文本识别预训练模型的评估

+
python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
+

评估部分日志如下:

+
[2022/05/12 19:52:02] ppocr INFO: load pretrain successful from models/ch_PP-OCRv3_rec_train/best_accuracy
+eval model:: 100%|██████████████████████████████| 40/40 [00:15<00:00,  2.57it/s]
+[2022/05/12 19:52:17] ppocr INFO: metric eval ***************
+[2022/05/12 19:52:17] ppocr INFO: acc:0.0
+[2022/05/12 19:52:17] ppocr INFO: norm_edit_dis:0.8656084923002452
+[2022/05/12 19:52:17] ppocr INFO: Teacher_acc:0.000399520574511545
+[2022/05/12 19:52:17] ppocr INFO: Teacher_norm_edit_dis:0.8657902943394548
+[2022/05/12 19:52:17] ppocr INFO: fps:1443.1801978719905
+
+

使用预训练模型进行评估,指标如下所示:

+ + + + + + + + + + + + + +
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0%
+

从评估日志中可以看到,直接使用PP-OCRv3预训练模型进行评估,acc非常低,但是norm_edit_dis很高。因此,我们猜测是模型大部分文字识别是对的,只有少部分文字识别错误。使用如下命令进行infer查看模型的推理结果进行验证:

+
python tools/infer_rec.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
+    Global.infer_img=/home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/0_0_0_3_32_30_31_30_30.jpg
+

输出部分日志如下:

+
[2022/05/01 08:51:57] ppocr INFO: train with paddle 2.2.2 and device CUDAPlace(0)
+W0501 08:51:57.127391 11326 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 11.0, Runtime API Version: 10.1
+W0501 08:51:57.132315 11326 device_context.cc:465] device: 0, cuDNN Version: 7.6.
+[2022/05/01 08:52:00] ppocr INFO: load pretrain successful from models/ch_PP-OCRv3_rec_train/student
+[2022/05/01 08:52:00] ppocr INFO: infer_img: /home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/0_0_3_32_30_31_30_30.jpg
+[2022/05/01 08:52:00] ppocr INFO:      result: {"Student": {"label": "皖A·D86766", "score": 0.9552637934684753}, "Teacher": {"label": "皖A·D86766", "score": 0.9917094707489014}}
+[2022/05/01 08:52:00] ppocr INFO: success!
+

从infer结果可以看到,车牌中的文字大部分都识别正确,只是多识别出了一个·。针对这种情况,有如下两种方案:

+
    +
  1. 直接通过后处理去掉多识别的·。
  2. +
  3. 进行 fine-tune。
  4. +
+

4.2.2 预训练模型直接预测+改动后处理

+

直接通过后处理去掉多识别的·,在后处理的改动比较简单,只需在 ppocr/postprocess/rec_postprocess.py 文件的76行添加如下代码:

+
text = text.replace('·','')
+

改动前后指标对比:

+ + + + + + + + + + + + + + + + + +
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0.2%
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%
+

可以看到,去掉多余的·能大幅提高精度。

+

4.2.3 CCPD车牌数据集fine-tune

+

训练

+

为了进行fine-tune训练,我们需要在配置文件中设置需要使用的预训练模型地址,学习率和数据集等参数。 具体如下:

+
    +
  1. 模型存储和训练相关: +
      +
    1. Global.pretrained_model: 指向PP-OCRv3文本识别预训练模型地址
    2. +
    3. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔45个step评估一次,45为一个epoch总的step数。
    4. +
    +
  2. +
  3. 优化器相关 +
      +
    1. Optimizer.lr.name: 学习率衰减器设为常量 Const
    2. +
    3. Optimizer.lr.learning_rate: 做 fine-tune 实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍
    4. +
    5. Optimizer.lr.warmup_epoch: warmup_epoch设为0
    6. +
    +
  4. +
  5. 数据集相关 +
      +
    1. Train.dataset.data_dir:指向训练集图片存放目录
    2. +
    3. Train.dataset.label_file_list:指向训练集标注文件
    4. +
    5. Eval.dataset.data_dir:指向测试集图片存放目录
    6. +
    7. Eval.dataset.label_file_list:指向测试集标注文件
    8. +
    +
  6. +
+

使用如下命令启动 fine-tune

+
python tools/train.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
+    Global.save_model_dir=output/CCPD/rec/ \
+    Global.eval_batch_step="[0, 90]" \
+    Optimizer.lr.name=Const \
+    Optimizer.lr.learning_rate=0.0005 \
+    Optimizer.lr.warmup_epoch=0 \
+    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
+    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt] \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
+

训练好的模型地址为: rec_ppocr_v3_finetune.tar

+

评估

+

训练完成后使用如下命令进行评估

+
python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
+

使用预训练模型和CCPD车牌数据集fine-tune,指标分别如下:

+ + + + + + + + + + + + + + + + + + + + + +
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0%
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%
+

可以看到进行fine-tune能显著提升车牌识别的效果。

+

4.2.4 CCPD车牌数据集fine-tune+量化训练

+

此处采用 PaddleOCR 中提供好的量化教程对模型进行量化训练。

+

量化训练可通过如下命令启动:

+
python3.7 deploy/slim/quantization/quant.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
+    Global.save_model_dir=output/CCPD/rec_quant/ \
+    Global.eval_batch_step="[0, 90]" \
+    Optimizer.lr.name=Const \
+    Optimizer.lr.learning_rate=0.0005 \
+    Optimizer.lr.warmup_epoch=0 \
+    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
+    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt] \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
+

训练好的模型地址为: rec_ppocr_v3_quant.tar

+

量化后指标对比如下

+ + + + + + + + + + + + + + + + + + + + + + + +
方案acc模型大小预测速度(lite)
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化93.4%4.8M1.8ms
+

可以看到量化后能降低模型体积53%并且推理速度提升57%,但是由于识别数据过少,量化带来了1%的精度下降。

+

速度测试基于PaddleOCR lite教程完成。

+

4.2.5 模型导出

+

使用如下命令可以将训练好的模型进行导出。

+
    +
  • 非量化模型
  • +
+
python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
+    Global.save_inference_dir=output/CCPD/rec/infer
+
    +
  • 量化模型
  • +
+
python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=output/CCPD/rec_quant/best_accuracy.pdparams \
+    Global.save_inference_dir=output/CCPD/rec_quant/infer
+

4.3 计算End2End指标

+

端到端指标可通过 PaddleOCR内置脚本 进行计算,具体步骤如下:

+
    +
  1. 导出模型
  2. +
+

通过如下命令进行模型的导出。注意,量化模型导出时,需要配置eval数据集

+
# 检测模型
+
+# 预训练模型
+python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
+    Global.save_inference_dir=output/ch_PP-OCRv3_det_distill_train/infer
+
+# 非量化模型
+python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
+    Global.save_inference_dir=output/CCPD/det/infer
+
+# 量化模型
+python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Global.pretrained_model=output/CCPD/det_quant/best_accuracy.pdparams \
+    Global.save_inference_dir=output/CCPD/det_quant/infer \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt] \
+    Eval.loader.num_workers=0
+
+# 识别模型
+
+# 预训练模型
+python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
+    Global.save_inference_dir=output/ch_PP-OCRv3_rec_train/infer
+
+# 非量化模型
+python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
+    Global.save_inference_dir=output/CCPD/rec/infer
+
+# 量化模型
+python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Global.pretrained_model=output/CCPD/rec_quant/best_accuracy.pdparams \
+    Global.save_inference_dir=output/CCPD/rec_quant/infer \
+    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
+
    +
  1. 用导出的模型对测试集进行预测
  2. +
+

此处,分别使用PP-OCRv3预训练模型,fintune模型和量化模型对测试集的所有图像进行预测,命令如下:

+
# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型
+python3 tools/infer/predict_system.py --det_model_dir=models/ch_PP-OCRv3_det_distill_train/infer --rec_model_dir=models/ch_PP-OCRv3_rec_train/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/pretrain --use_dilation=true
+
+# PP-OCRv3中英文超轻量检测预训练模型+fine-tune,PP-OCRv3中英文超轻量识别预训练模型+fine-tune
+python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det/infer --rec_model_dir=output/CCPD/rec/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/fine-tune --use_dilation=true
+
+# PP-OCRv3中英文超轻量检测预训练模型 fine-tune +量化,PP-OCRv3中英文超轻量识别预训练模型 fine-tune +量化 结果转换和评估
+python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det_quant/infer --rec_model_dir=output/CCPD/rec_quant/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/quant --use_dilation=true
+
    +
  1. 转换label并计算指标
  2. +
+

将gt和上一步保存的预测结果转换为端对端评测需要的数据格式,并根据转换后的数据进行端到端指标计算

+
python3 tools/end2end/convert_ppocr_label.py --mode=gt --label_path=/home/aistudio/data/CCPD2020/PPOCR/test/det.txt --save_folder=end2end/gt
+
+# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型 结果转换和评估
+python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/pretrain/system_results.txt --save_folder=end2end/pretrain
+python3 tools/end2end/eval_end2end.py end2end/gt end2end/pretrain
+
+# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·` 结果转换和评估
+# 需手动修改后处理函数
+python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/post/system_results.txt --save_folder=end2end/post
+python3 tools/end2end/eval_end2end.py end2end/gt end2end/post
+
+# PP-OCRv3中英文超轻量检测预训练模型 fine-tune,PP-OCRv3中英文超轻量识别预训练模型 fine-tune 结果转换和评估
+python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/fine-tune/system_results.txt --save_folder=end2end/fine-tune
+python3 tools/end2end/eval_end2end.py end2end/gt end2end/fine-tune
+
+# PP-OCRv3中英文超轻量检测预训练模型 fine-tune +量化,PP-OCRv3中英文超轻量识别预训练模型 fine-tune +量化 结果转换和评估
+python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/quant/system_results.txt --save_folder=end2end/quant
+python3 tools/end2end/eval_end2end.py end2end/gt end2end/quant
+

日志如下:

+
The convert label saved in end2end/gt
+The convert label saved in end2end/pretrain
+start testing...
+hit, dt_count, gt_count 2 5988 5006
+character_acc: 70.42%
+avg_edit_dist_field: 2.37
+avg_edit_dist_img: 2.37
+precision: 0.03%
+recall: 0.04%
+fmeasure: 0.04%
+The convert label saved in end2end/post
+start testing...
+hit, dt_count, gt_count 4224 5988 5006
+character_acc: 81.59%
+avg_edit_dist_field: 1.47
+avg_edit_dist_img: 1.47
+precision: 70.54%
+recall: 84.38%
+fmeasure: 76.84%
+The convert label saved in end2end/fine-tune
+start testing...
+hit, dt_count, gt_count 4286 4898 5006
+character_acc: 94.16%
+avg_edit_dist_field: 0.47
+avg_edit_dist_img: 0.47
+precision: 87.51%
+recall: 85.62%
+fmeasure: 86.55%
+The convert label saved in end2end/quant
+start testing...
+hit, dt_count, gt_count 4349 4951 5006
+character_acc: 94.13%
+avg_edit_dist_field: 0.47
+avg_edit_dist_img: 0.47
+precision: 87.84%
+recall: 86.88%
+fmeasure: 87.36%
+

各个方案端到端指标如下:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
模型指标
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.04%
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
78.27%
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
87.14%
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
88%
+

从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到78.27%,在CCPD数据集上进行 fine-tune 后指标进一步提升到87.14%, 在经过量化训练之后,由于检测模型的recall变高,指标进一步提升到88%。但是这个结果仍旧不符合检测模型+识别模型的真实性能(99%*94%=93%),因此我们需要对 base case 进行具体分析。

+

在之前的端到端预测结果中,可以看到很多不符合车牌标注的文字被识别出来, 因此可以进行简单的过滤来提升precision

+

为了快速评估,我们在 tools/end2end/convert_ppocr_label.py 脚本的 58 行加入如下代码,对非8个字符的结果进行过滤

+
if len(txt) != 8: # 车牌字符串长度为8
+    continue
+

此外,通过可视化box可以发现有很多框都是竖直翻转之后的框,并且没有完全框住车牌边界,因此需要进行框的竖直翻转以及轻微扩大,示意图如下:

+

+

修改前后个方案指标对比如下:

+

各个方案端到端指标如下:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
模型baseA:识别结果过滤B:use_dilationC:flip_boxbest
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.04%0.08%0.02%0.05%0.00%(A)
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
78.27%90.84%78.61%79.43%91.66%(A+B+C)
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
87.14%90.40%87.66%89.9892.5%(A+B+C)
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
88%90.54%88.5%89.46%92.02%(A+B+C)
+

从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到91.66%,在CCPD数据集上进行 fine-tune 后指标进一步提升到92.5%, 在经过量化训练之后,指标变为92.02%。

+

4.4 部署

+
    +
  • 基于 Paddle Inference 的python推理
  • +
+

检测模型和识别模型分别 fine-tune 并导出为inference模型之后,可以使用如下命令基于 Paddle Inference 进行端到端推理并对结果进行可视化。

+
python tools/infer/predict_system.py \
+    --det_model_dir=output/CCPD/det/infer/ \
+    --rec_model_dir=output/CCPD/rec/infer/ \
+    --image_dir="/home/aistudio/data/CCPD2020/ccpd_green/test/04131106321839081-92_258-159&509_530&611-527&611_172&599_159&509_530&525-0_0_3_32_30_31_30_30-109-106.jpg" \
+    --rec_image_shape=3,48,320
+

推理结果如下

+

+
    +
  • 端侧部署
  • +
+

端侧部署我们采用基于 PaddleLite 的 cpp 推理。Paddle Lite是飞桨轻量化推理引擎,为手机、IOT端提供高效推理能力,并广泛整合跨平台硬件,为端侧部署及应用落地问题提供轻量化的部署方案。具体可参考 PaddleOCR lite教程

+

4.5 实验总结

+

我们分别使用PP-OCRv3中英文超轻量预训练模型在车牌数据集上进行了直接评估和 fine-tune 和 fine-tune +量化3种方案的实验,并基于PaddleOCR lite教程进行了速度测试,指标对比如下:

+
    +
  • 检测
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
方案hmeans模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%2.5M233ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%2.5M233ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune + 量化98.91%1M189ms
+
    +
  • 识别
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
方案acc模型大小预测速度(lite)
PP-OCRv3中英文超轻量识别预训练模型直接预测0%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%10.3M4,2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化93.4%4.8M1.8ms
+
    +
  • 端到端指标如下:
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
方案fmeasure模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.08%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
91.66%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
92.5%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
92.02%5.8M224ms
+

结论

+

PP-OCRv3的检测模型在未经过fine-tune的情况下,在车牌数据集上也有一定的精度,经过 fine-tune 后能够极大的提升检测效果,精度达到99%。在使用量化训练后检测模型的精度几乎无损,并且模型大小压缩60%。

+

PP-OCRv3的识别模型在未经过fine-tune的情况下,在车牌数据集上精度为0,但是经过分析可以知道,模型大部分字符都预测正确,但是会多预测一个特殊字符,去掉这个特殊字符后,精度达到90%。PP-OCRv3识别模型在经过 fine-tune 后识别精度进一步提升,达到94.4%。在使用量化训练后识别模型大小压缩53%,但是由于数据量多少,带来了1%的精度损失。

+

从端到端结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到91.66%,在CCPD数据集上进行 fine-tune 后指标进一步提升到92.5%, 在经过量化训练之后,指标轻微下降到92.02%但模型大小降低54%。

+
+
+ +
+ +
+ + + +
+ + +
+ + +
+
+ + + + +
+ +
+ + +
+ + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + From aba127fe595773f7f2f3554c6bee5300e3c27a03 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 21 Jun 2022 15:50:39 +0800 Subject: [PATCH 08/12] fix --- applications/轻量级车牌识别.md | 3113 ++++++-------------------------- 1 file changed, 521 insertions(+), 2592 deletions(-) diff --git a/applications/轻量级车牌识别.md b/applications/轻量级车牌识别.md index e0f4706f14..7012c7f4bb 100644 --- a/applications/轻量级车牌识别.md +++ b/applications/轻量级车牌识别.md @@ -1,1571 +1,129 @@ +# 一种基于PaddleOCR的轻量级车牌识别模型 +- [1. 项目介绍](#1-项目介绍) +- [2. 环境搭建](#2-环境搭建) +- [3. 数据集准备](#3-数据集准备) + - [3.1 数据集标注规则](#31-数据集标注规则) + - [3.2 制作符合PP-OCR训练格式的标注文件](#32-制作符合pp-ocr训练格式的标注文件) +- [4. 实验](#4-实验) + - [4.1 检测](#41-检测) + - [4.1.1 预训练模型直接预测](#411-预训练模型直接预测) + - [4.1.2 CCPD车牌数据集fine-tune](#412-ccpd车牌数据集fine-tune) + - [4.1.3 CCPD车牌数据集fine-tune+量化训练](#413-ccpd车牌数据集fine-tune量化训练) + - [4.1.4 模型导出](#414-模型导出) + - [4.2 识别](#42-识别) + - [4.2.1 预训练模型直接预测](#421-预训练模型直接预测) + - [4.2.2 预训练模型直接预测+改动后处理](#422-预训练模型直接预测改动后处理) + - [4.2.3 CCPD车牌数据集fine-tune](#423-ccpd车牌数据集fine-tune) + - [4.2.4 CCPD车牌数据集fine-tune+量化训练](#424-ccpd车牌数据集fine-tune量化训练) + - [4.2.5 模型导出](#425-模型导出) + - [4.3 计算End2End指标](#43-计算End2End指标) + - [4.4 部署](#44-部署) + - [4.5 实验总结](#45-实验总结) +## 1. 项目介绍 +车牌识别(Vehicle License Plate Recognition,VLPR) 是计算机视频图像识别技术在车辆牌照识别中的一种应用。车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来,在高速公路车辆管理,停车场管理和城市交通中得到广泛应用。 +本项目难点如下: +1. 车牌在图像中的尺度差异大、在车辆上的悬挂位置不固定 +2. 车牌图像质量层次不齐: 角度倾斜、图片模糊、光照不足、过曝等问题严重 +3. 边缘和端测场景应用对模型大小有限制,推理速度有要求 +针对以上问题, 本例选用 PP-OCRv3 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升25%。 - - - - - - - - - - +aistudio项目链接: [基于PaddleOCR的轻量级车牌识别范例](https://aistudio.baidu.com/aistudio/projectdetail/3919091?contributionType=1) - +## 2. 环境搭建 - - - - +本任务基于Aistudio完成, 具体环境如下: - +- 操作系统: Linux +- PaddlePaddle: 2.3 +- paddleslim: 2.2.2 +- PaddleOCR: Release/2.5 +下载 PaddleOCR代码 - - - - - - - - - - - - - - - - - - - - - - - - - - - - +```bash +git clone -b dygraph https://github.com/PaddlePaddle/PaddleOCR +``` +安装依赖库 - PaddleOCR/轻量级车牌识别.md at dygraph · PaddlePaddle/PaddleOCR · GitHub +```bash +pip install -r PaddleOCR/requirements.txt +``` +## 3. 数据集准备 +所使用的数据集为 CCPD2020 新能源车牌数据集,该数据集为 +该数据集分布如下: +|数据集类型|数量| +|---|---| +|训练集| 5769| +|验证集| 1001| +|测试集| 5006| - +数据集图片示例如下: +![](https://ai-studio-static-online.cdn.bcebos.com/3bce057a8e0c40a0acbd26b2e29e4e2590a31bc412764be7b9e49799c69cb91c) - +数据集可以从这里下载 https://aistudio.baidu.com/aistudio/datasetdetail/101595 +下载好数据集后对数据集进行解压 - +```bash +unzip -d /home/aistudio/data /home/aistudio/data/data101595/CCPD2020.zip +``` +### 3.1 数据集标注规则 - +CPPD数据集的图片文件名具有特殊规则,详细可查看:https://github.com/detectRecog/CCPD - - - - +具体规则如下: - +例如: 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 - +每个名称可以分为七个字段,以-符号作为分割。这些字段解释如下。 +- 025:车牌面积与整个图片区域的面积比。025 (25%) +- 95_113:水平倾斜程度和垂直倾斜度。水平 95度 垂直 113度 +- 154&383_386&473:左上和右下顶点的坐标。左上(154,383) 右下(386,473) +- 386&473_177&454_154&383_363&402:整个图像中车牌的四个顶点的精确(x,y)坐标。这些坐标从右下角顶点开始。(386,473) (177,454) (154,383) (363,402) +- 0_0_22_27_27_33_16:CCPD中的每个图像只有一个车牌。每个车牌号码由一个汉字,一个字母和五个字母或数字组成。有效的中文车牌由七个字符组成:省(1个字符),字母(1个字符),字母+数字(5个字符)。“ 0_0_22_27_27_33_16”是每个字符的索引。这三个数组定义如下。每个数组的最后一个字符是字母O,而不是数字0。我们将O用作“无字符”的符号,因为中文车牌字符中没有O。因此以上车牌拼起来即为 皖AY339S +- 37:牌照区域的亮度。 37 (37%) +- 15:车牌区域的模糊度。15 (15%) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Skip to content - - - - - - - - - - - -
- -
- - - - - - - -
- - - -
- - - - - - - - - -
-
-
- - - - - - - - - - - - - - - - - -
- - - - - - -
- - -
- - - - - - - - -Permalink - -
- -
-
- - - dygraph - - - - -
-
-
- Switch branches/tags - -
- - - -
- -
- -
- - -
- -
- - - - - - - - - - - - - - - -
- - -
-
-
-
- -
- -
- - - Go to file - - -
- - - - - -
-
-
- - - - - - - - - -
- -
-
- - @MissPenguin - -
- - - - - - -
-
- - Latest commit - 10a3f25 - Jun 15, 2022 - - - - - - History - - -
-
- -
- -
-
- - - 2 - - contributors - - -
- -

- Users who have contributed to this file -

-
- - - - - - -
-
- - - @WenmuZhou - - @MissPenguin - - - -
-
- - - - - - - - - -
- - - - -
-

一种基于PaddleOCR的轻量级车牌识别模型

- -

1. 项目介绍

-

车牌识别(Vehicle License Plate Recognition,VLPR) 是计算机视频图像识别技术在车辆牌照识别中的一种应用。车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来,在高速公路车辆管理,停车场管理和城市交通中得到广泛应用。

-

本项目难点如下:

-
    -
  1. 车牌在图像中的尺度差异大、在车辆上的悬挂位置不固定
  2. -
  3. 车牌图像质量层次不齐: 角度倾斜、图片模糊、光照不足、过曝等问题严重
  4. -
  5. 边缘和端测场景应用对模型大小有限制,推理速度有要求
  6. -
-

针对以上问题, 本例选用 PP-OCRv3 这一开源超轻量OCR系统进行车牌识别系统的开发。基于PP-OCRv3模型,在CCPD数据集达到99%的检测和94%的识别精度,模型大小12.8M(2.5M+10.3M)。基于量化对模型体积进行进一步压缩到5.8M(1M+4.8M), 同时推理速度提升25%。

-

aistudio项目链接: 基于PaddleOCR的轻量级车牌识别范例

-

2. 环境搭建

-

本任务基于Aistudio完成, 具体环境如下:

-
    -
  • 操作系统: Linux
  • -
  • PaddlePaddle: 2.3
  • -
  • paddleslim: 2.2.2
  • -
  • PaddleOCR: Release/2.5
  • -
-

下载 PaddleOCR代码

-
git clone -b dygraph https://github.com/PaddlePaddle/PaddleOCR
-

安装依赖库

-
pip install -r PaddleOCR/requirements.txt
-

3. 数据集准备

-

所使用的数据集为 CCPD2020 新能源车牌数据集,该数据集为

-

该数据集分布如下:

- - - - - - - - - - - - - - - - - - - - - -
数据集类型数量
训练集5769
验证集1001
测试集5006
-

数据集图片示例如下: -

-

数据集可以从这里下载 https://aistudio.baidu.com/aistudio/datasetdetail/101595

-

下载好数据集后对数据集进行解压

-
unzip -d /home/aistudio/data /home/aistudio/data/data101595/CCPD2020.zip
-

3.1 数据集标注规则

-

CPPD数据集的图片文件名具有特殊规则,详细可查看:https://github.com/detectRecog/CCPD

-

具体规则如下:

-

例如: 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

-

每个名称可以分为七个字段,以-符号作为分割。这些字段解释如下。

-
    -
  • -

    025:车牌面积与整个图片区域的面积比。025 (25%)

    -
  • -
  • -

    95_113:水平倾斜程度和垂直倾斜度。水平 95度 垂直 113度

    -
  • -
  • -

    154&383_386&473:左上和右下顶点的坐标。左上(154,383) 右下(386,473)

    -
  • -
  • -

    386&473_177&454_154&383_363&402:整个图像中车牌的四个顶点的精确(x,y)坐标。这些坐标从右下角顶点开始。(386,473) (177,454) (154,383) (363,402)

    -
  • -
  • -

    0_0_22_27_27_33_16:CCPD中的每个图像只有一个车牌。每个车牌号码由一个汉字,一个字母和五个字母或数字组成。有效的中文车牌由七个字符组成:省(1个字符),字母(1个字符),字母+数字(5个字符)。“ 0_0_22_27_27_33_16”是每个字符的索引。这三个数组定义如下。每个数组的最后一个字符是字母O,而不是数字0。我们将O用作“无字符”的符号,因为中文车牌字符中没有O。因此以上车牌拼起来即为 皖AY339S

    -
  • -
  • -

    37:牌照区域的亮度。 37 (37%)

    -
  • -
  • -

    15:车牌区域的模糊度。15 (15%)

    -
  • -
-
provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"]
-alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W','X', 'Y', 'Z', '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']
-

3.2 制作符合PP-OCR训练格式的标注文件

-

在开始训练之前,可使用如下代码制作符合PP-OCR训练格式的标注文件。

-
= 1.5: dst_img = np.rot90(dst_img) return dst_img @@ -1644,695 +202,414 @@ img_dir = '/home/aistudio/data/CCPD2020/ccpd_green' save_gt_folder = '/home/aistudio/data/CCPD2020/PPOCR' # phase = 'train' # change to val and test to make val dataset and test dataset for phase in ['train','val','test']: - make_label(img_dir, save_gt_folder, phase)">
import cv2
-import os
-import json
-from tqdm import tqdm
-import numpy as np
+    make_label(img_dir, save_gt_folder, phase)
+```
 
-provinces = ["皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣", "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁", "新", "警", "学", "O"]
-alphabets = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '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']
+通过上述命令可以完成了`训练集`,`验证集`和`测试集`的制作,制作完成的数据集信息如下:
 
-def make_label(img_dir, save_gt_folder, phase):
-    crop_img_save_dir = os.path.join(save_gt_folder, phase, 'crop_imgs')
-    os.makedirs(crop_img_save_dir, exist_ok=True)
+| 类型 | 数据集 | 图片地址 | 标签地址 | 图片数量 |
+| --- | --- | --- | --- | --- |
+| 检测 | 训练集 | /home/aistudio/data/CCPD2020/ccpd_green/train | /home/aistudio/data/CCPD2020/PPOCR/train/det.txt | 5769 |
+| 检测 | 验证集 | /home/aistudio/data/CCPD2020/ccpd_green/val | /home/aistudio/data/CCPD2020/PPOCR/val/det.txt | 1001 |
+| 检测 | 测试集 | /home/aistudio/data/CCPD2020/ccpd_green/test | /home/aistudio/data/CCPD2020/PPOCR/test/det.txt | 5006 |
+| 识别 | 训练集 | /home/aistudio/data/CCPD2020/PPOCR/train/crop_imgs | /home/aistudio/data/CCPD2020/PPOCR/train/rec.txt | 5769 |
+| 识别 | 验证集 | /home/aistudio/data/CCPD2020/PPOCR/val/crop_imgs | /home/aistudio/data/CCPD2020/PPOCR/val/rec.txt | 1001 |
+| 识别 | 测试集 | /home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs | /home/aistudio/data/CCPD2020/PPOCR/test/rec.txt | 5006 |
 
-    f_det = open(os.path.join(save_gt_folder, phase, 'det.txt'), 'w', encoding='utf-8')
-    f_rec = open(os.path.join(save_gt_folder, phase, 'rec.txt'), 'w', encoding='utf-8')
+在普遍的深度学习流程中,都是在训练集训练,在验证集选择最优模型后在测试集上进行测试。在本例中,我们省略中间步骤,直接在训练集训练,在测试集选择最优模型,因此我们只使用训练集和测试集。
 
-    i = 0
-    for filename in tqdm(os.listdir(os.path.join(img_dir, phase))):
-        str_list = filename.split('-')
-        if len(str_list) < 5:
-            continue
-        coord_list = str_list[3].split('_')
-        txt_list = str_list[4].split('_')
-        boxes = []
-        for coord in coord_list:
-            boxes.append([int(x) for x in coord.split("&")])
-        boxes = [boxes[2], boxes[3], boxes[0], boxes[1]]
-        lp_number = provinces[int(txt_list[0])] + alphabets[int(txt_list[1])] + ''.join([ads[int(x)] for x in txt_list[2:]])
+## 4. 实验
 
-        # det
-        det_info = [{'points':boxes, 'transcription':lp_number}]
-        f_det.write('{}\t{}\n'.format(os.path.join(phase, filename), json.dumps(det_info, ensure_ascii=False)))
+由于数据集比较少,为了模型更好和更快的收敛,这里选用 PaddleOCR 中的 PP-OCRv3 模型进行文本检测和识别,并且使用 PP-OCRv3 模型参数作为预训练模型。PP-OCRv3在PP-OCRv2的基础上,中文场景端到端Hmean指标相比于PP-OCRv2提升5%, 英文数字模型端到端效果提升11%。详细优化细节请参考[PP-OCRv3](../doc/doc_ch/PP-OCRv3_introduction.md)技术报告。
 
-        # rec
-        boxes = np.float32(boxes)
-        img = cv2.imread(os.path.join(img_dir, phase, filename))
-        # crop_img = img[int(boxes[:,1].min()):int(boxes[:,1].max()),int(boxes[:,0].min()):int(boxes[:,0].max())]
-        crop_img = get_rotate_crop_image(img, boxes)
-        crop_img_save_filename = '{}_{}.jpg'.format(i,'_'.join(txt_list))
-        crop_img_save_path = os.path.join(crop_img_save_dir, crop_img_save_filename)
-        cv2.imwrite(crop_img_save_path, crop_img)
-        f_rec.write('{}/crop_imgs/{}\t{}\n'.format(phase, crop_img_save_filename, lp_number))
-        i+=1
-    f_det.close()
-    f_rec.close()
+由于车牌场景均为端侧设备部署,因此对速度和模型大小有比较高的要求,因此还需要采用量化训练的方式进行模型大小的压缩和模型推理速度的加速。模型量化可以在基本不损失模型的精度的情况下,将FP32精度的模型参数转换为Int8精度,减小模型参数大小并加速计算,使用量化后的模型在移动端等部署时更具备速度优势。
 
-def get_rotate_crop_image(img, points):
-    '''
-    img_height, img_width = img.shape[0:2]
-    left = int(np.min(points[:, 0]))
-    right = int(np.max(points[:, 0]))
-    top = int(np.min(points[:, 1]))
-    bottom = int(np.max(points[:, 1]))
-    img_crop = img[top:bottom, left:right, :].copy()
-    points[:, 0] = points[:, 0] - left
-    points[:, 1] = points[:, 1] - top
-    '''
-    assert len(points) == 4, "shape of points must be 4*2"
-    img_crop_width = int(
-        max(
-            np.linalg.norm(points[0] - points[1]),
-            np.linalg.norm(points[2] - points[3])))
-    img_crop_height = int(
-        max(
-            np.linalg.norm(points[0] - points[3]),
-            np.linalg.norm(points[1] - points[2])))
-    pts_std = np.float32([[0, 0], [img_crop_width, 0],
-                          [img_crop_width, img_crop_height],
-                          [0, img_crop_height]])
-    M = cv2.getPerspectiveTransform(points, pts_std)
-    dst_img = cv2.warpPerspective(
-        img,
-        M, (img_crop_width, img_crop_height),
-        borderMode=cv2.BORDER_REPLICATE,
-        flags=cv2.INTER_CUBIC)
-    dst_img_height, dst_img_width = dst_img.shape[0:2]
-    if dst_img_height * 1.0 / dst_img_width >= 1.5:
-        dst_img = np.rot90(dst_img)
-    return dst_img
+因此,本实验中对于车牌检测和识别有如下3种方案:
 
-img_dir = '/home/aistudio/data/CCPD2020/ccpd_green'
-save_gt_folder = '/home/aistudio/data/CCPD2020/PPOCR'
-# phase = 'train' # change to val and test to make val dataset and test dataset
-for phase in ['train','val','test']:
-    make_label(img_dir, save_gt_folder, phase)
-

通过上述命令可以完成了训练集,验证集和测试集的制作,制作完成的数据集信息如下:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
类型数据集图片地址标签地址图片数量
检测训练集/home/aistudio/data/CCPD2020/ccpd_green/train/home/aistudio/data/CCPD2020/PPOCR/train/det.txt5769
检测验证集/home/aistudio/data/CCPD2020/ccpd_green/val/home/aistudio/data/CCPD2020/PPOCR/val/det.txt1001
检测测试集/home/aistudio/data/CCPD2020/ccpd_green/test/home/aistudio/data/CCPD2020/PPOCR/test/det.txt5006
识别训练集/home/aistudio/data/CCPD2020/PPOCR/train/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt5769
识别验证集/home/aistudio/data/CCPD2020/PPOCR/val/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/val/rec.txt1001
识别测试集/home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt5006
-

在普遍的深度学习流程中,都是在训练集训练,在验证集选择最优模型后在测试集上进行测试。在本例中,我们省略中间步骤,直接在训练集训练,在测试集选择最优模型,因此我们只使用训练集和测试集。

-

4. 实验

-

由于数据集比较少,为了模型更好和更快的收敛,这里选用 PaddleOCR 中的 PP-OCRv3 模型进行文本检测和识别,并且使用 PP-OCRv3 模型参数作为预训练模型。PP-OCRv3在PP-OCRv2的基础上,中文场景端到端Hmean指标相比于PP-OCRv2提升5%, 英文数字模型端到端效果提升11%。详细优化细节请参考PP-OCRv3技术报告。

-

由于车牌场景均为端侧设备部署,因此对速度和模型大小有比较高的要求,因此还需要采用量化训练的方式进行模型大小的压缩和模型推理速度的加速。模型量化可以在基本不损失模型的精度的情况下,将FP32精度的模型参数转换为Int8精度,减小模型参数大小并加速计算,使用量化后的模型在移动端等部署时更具备速度优势。

-

因此,本实验中对于车牌检测和识别有如下3种方案:

-
    -
  1. PP-OCRv3中英文超轻量预训练模型直接预测
  2. -
  3. CCPD车牌数据集在PP-OCRv3模型上fine-tune
  4. -
  5. CCPD车牌数据集在PP-OCRv3模型上fine-tune后量化
  6. -
-

4.1 检测

-

4.1.1 预训练模型直接预测

-

从下表中下载PP-OCRv3文本检测预训练模型

- - - - - - - - - - - - - - - - - - - -
模型名称模型简介配置文件推理模型大小下载地址
ch_PP-OCRv3_det【最新】原始超轻量模型,支持中英文、多语种文本检测ch_PP-OCRv3_det_cml.yml3.8M推理模型 / 训练模型
-

使用如下命令下载预训练模型

-
mkdir models
-cd models
-wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar
-tar -xf ch_PP-OCRv3_det_distill_train.tar
-cd /home/aistudio/PaddleOCR
-

预训练模型下载完成后,我们使用ch_PP-OCRv3_det_student.yml 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下:

-
    -
  1. 模型存储和训练相关: -
      -
    1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址
    2. -
    -
  2. -
  3. 数据集相关 -
      -
    1. Eval.dataset.data_dir:指向测试集图片存放目录
    2. -
    3. Eval.dataset.label_file_list:指向测试集标注文件
    4. -
    -
  4. -
-

上述字段均为必须修改的字段,可以通过修改配置文件的方式改动,也可在不需要修改配置文件的情况下,改变训练的参数。这里使用不改变配置文件的方式 。使用如下命令进行PP-OCRv3文本检测预训练模型的评估

-
python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
-

上述指令中,通过-c 选择训练使用配置文件,通过-o参数在不需要修改配置文件的情况下,改变训练的参数。

-

使用预训练模型进行评估,指标如下所示:

- - - - - - - - - - - - - -
方案hmeans
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%
-

4.1.2 CCPD车牌数据集fine-tune

-

训练

-

为了进行fine-tune训练,我们需要在配置文件中设置需要使用的预训练模型地址,学习率和数据集等参数。 具体如下:

-
    -
  1. 模型存储和训练相关: -
      -
    1. Global.pretrained_model: 指向PP-OCRv3文本检测预训练模型地址
    2. -
    3. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔772个step评估一次,772为一个epoch总的step数。
    4. -
    -
  2. -
  3. 优化器相关: -
      -
    1. Optimizer.lr.name: 学习率衰减器设为常量 Const
    2. -
    3. Optimizer.lr.learning_rate: 做 fine-tune 实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍
    4. -
    5. Optimizer.lr.warmup_epoch: warmup_epoch设为0
    6. -
    -
  4. -
  5. 数据集相关: -
      -
    1. Train.dataset.data_dir:指向训练集图片存放目录
    2. -
    3. Train.dataset.label_file_list:指向训练集标注文件
    4. -
    5. Eval.dataset.data_dir:指向测试集图片存放目录
    6. -
    7. Eval.dataset.label_file_list:指向测试集标注文件
    8. -
    -
  6. -
-

使用如下代码即可启动在CCPD车牌数据集上的fine-tune。

-
python tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
-    Global.save_model_dir=output/CCPD/det \
-    Global.eval_batch_step="[0, 772]" \
-    Optimizer.lr.name=Const \
-    Optimizer.lr.learning_rate=0.0005 \
-    Optimizer.lr.warmup_epoch=0 \
-    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/det.txt] \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
-

在上述命令中,通过-o的方式修改了配置文件中的参数。

-

训练好的模型地址为: det_ppocr_v3_finetune.tar

-

评估

-

训练完成后使用如下命令进行评估

-
python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
-

使用预训练模型和CCPD车牌数据集fine-tune,指标分别如下:

- - - - - - - - - - - - - - - - - -
方案hmeans
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%
-

可以看到进行fine-tune能显著提升车牌检测的效果。

-

4.1.3 CCPD车牌数据集fine-tune+量化训练

-

此处采用 PaddleOCR 中提供好的量化教程对模型进行量化训练。

-

量化训练可通过如下命令启动:

-
python3.7 deploy/slim/quantization/quant.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
+```
+
+训练好的模型地址为: [det_ppocr_v3_quant.tar](https://paddleocr.bj.bcebos.com/fanliku/license_plate_recognition/det_ppocr_v3_quant.tar)
+
+量化后指标对比如下
+
+|方案|hmeans| 模型大小 | 预测速度(lite) |
+|---|---|------|------------|
+|PP-OCRv3中英文超轻量检测预训练模型 fine-tune|99%| 2.5M | 223ms      |
+|PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化|98.91%| 1M   | 189ms      |
+
+可以看到通过量化训练在精度几乎无损的情况下,降低模型体积60%并且推理速度提升15%。
+
+速度测试基于[PaddleOCR lite教程](../deploy/lite/readme_ch.md)完成。
+
+#### 4.1.4 模型导出
+
+使用如下命令可以将训练好的模型进行导出
+
+* 非量化模型
+```bash
+python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
     Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
-    Global.save_model_dir=output/CCPD/det_quant \
-    Global.eval_batch_step="[0, 772]" \
-    Optimizer.lr.name=Const \
-    Optimizer.lr.learning_rate=0.0005 \
-    Optimizer.lr.warmup_epoch=0 \
-    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/det.txt] \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt]
-

训练好的模型地址为: det_ppocr_v3_quant.tar

-

量化后指标对比如下

- - - - - - - - - - - - - - - - - - - - - - - -
方案hmeans模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%2.5M223ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune+量化98.91%1M189ms
-

可以看到通过量化训练在精度几乎无损的情况下,降低模型体积60%并且推理速度提升15%。

-

速度测试基于PaddleOCR lite教程完成。

-

4.1.4 模型导出

-

使用如下命令可以将训练好的模型进行导出

-
    -
  • 非量化模型
  • -
-
python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
-    Global.save_inference_dir=output/det/infer
-
    -
  • 量化模型
  • -
-
python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det_quant/best_accuracy.pdparams \
-    Global.save_inference_dir=output/det/infer
-

4.2 识别

-

4.2.1 预训练模型直接预测

-

从下表中下载PP-OCRv3文本识别预训练模型

- - - - - - - - - - - - - - - - - - - -
模型名称模型简介配置文件推理模型大小下载地址
ch_PP-OCRv3_rec【最新】原始超轻量模型,支持中英文、数字识别ch_PP-OCRv3_rec_distillation.yml12.4M推理模型 / 训练模型
-

使用如下命令下载预训练模型

-
mkdir models
-cd models
-wget https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_rec_train.tar
-tar -xf ch_PP-OCRv3_rec_train.tar
-cd /home/aistudio/PaddleOCR
-

PaddleOCR提供的PP-OCRv3识别模型采用蒸馏训练策略,因此提供的预训练模型中会包含Teacher和Student模型的参数,详细信息可参考knowledge_distillation.md。 因此,模型下载完成后需要使用如下代码提取Student模型的参数:

-
import paddle
-# 加载预训练模型
-all_params = paddle.load("models/ch_PP-OCRv3_rec_train/best_accuracy.pdparams")
-# 查看权重参数的keys
-print(all_params.keys())
-# 学生模型的权重提取
-s_params = {key[len("Student."):]: all_params[key] for key in all_params if "Student." in key}
-# 查看学生模型权重参数的keys
-print(s_params.keys())
-# 保存
-paddle.save(s_params, "models/ch_PP-OCRv3_rec_train/student.pdparams")
-

预训练模型下载完成后,我们使用ch_PP-OCRv3_rec.yml 配置文件进行后续实验,在开始评估之前需要对配置文件中部分字段进行设置,具体如下:

-
    -
  1. 模型存储和训练相关: -
      -
    1. Global.pretrained_model: 指向PP-OCRv3文本识别预训练模型地址
    2. -
    -
  2. -
  3. 数据集相关 -
      -
    1. Eval.dataset.data_dir:指向测试集图片存放目录
    2. -
    3. Eval.dataset.label_file_list:指向测试集标注文件
    4. -
    -
  4. -
-

使用如下命令进行PP-OCRv3文本识别预训练模型的评估

-
python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-

评估部分日志如下:

-
[2022/05/12 19:52:02] ppocr INFO: load pretrain successful from models/ch_PP-OCRv3_rec_train/best_accuracy
-eval model:: 100%|██████████████████████████████| 40/40 [00:15<00:00,  2.57it/s]
-[2022/05/12 19:52:17] ppocr INFO: metric eval ***************
-[2022/05/12 19:52:17] ppocr INFO: acc:0.0
-[2022/05/12 19:52:17] ppocr INFO: norm_edit_dis:0.8656084923002452
-[2022/05/12 19:52:17] ppocr INFO: Teacher_acc:0.000399520574511545
-[2022/05/12 19:52:17] ppocr INFO: Teacher_norm_edit_dis:0.8657902943394548
-[2022/05/12 19:52:17] ppocr INFO: fps:1443.1801978719905
-
-

使用预训练模型进行评估,指标如下所示:

- - - - - - - - - - - - - -
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0%
-

从评估日志中可以看到,直接使用PP-OCRv3预训练模型进行评估,acc非常低,但是norm_edit_dis很高。因此,我们猜测是模型大部分文字识别是对的,只有少部分文字识别错误。使用如下命令进行infer查看模型的推理结果进行验证:

-
python tools/infer_rec.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
-    Global.infer_img=/home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/0_0_0_3_32_30_31_30_30.jpg
-

输出部分日志如下:

-
[2022/05/01 08:51:57] ppocr INFO: train with paddle 2.2.2 and device CUDAPlace(0)
-W0501 08:51:57.127391 11326 device_context.cc:447] Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 11.0, Runtime API Version: 10.1
-W0501 08:51:57.132315 11326 device_context.cc:465] device: 0, cuDNN Version: 7.6.
-[2022/05/01 08:52:00] ppocr INFO: load pretrain successful from models/ch_PP-OCRv3_rec_train/student
-[2022/05/01 08:52:00] ppocr INFO: infer_img: /home/aistudio/data/CCPD2020/PPOCR/test/crop_imgs/0_0_3_32_30_31_30_30.jpg
-[2022/05/01 08:52:00] ppocr INFO:      result: {"Student": {"label": "皖A·D86766", "score": 0.9552637934684753}, "Teacher": {"label": "皖A·D86766", "score": 0.9917094707489014}}
-[2022/05/01 08:52:00] ppocr INFO: success!
-

从infer结果可以看到,车牌中的文字大部分都识别正确,只是多识别出了一个·。针对这种情况,有如下两种方案:

-
    -
  1. 直接通过后处理去掉多识别的·。
  2. -
  3. 进行 fine-tune。
  4. -
-

4.2.2 预训练模型直接预测+改动后处理

-

直接通过后处理去掉多识别的·,在后处理的改动比较简单,只需在 ppocr/postprocess/rec_postprocess.py 文件的76行添加如下代码:

-
text = text.replace('·','')
-

改动前后指标对比:

- - - - - - - - - - - - - - - - - -
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0.2%
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%
-

可以看到,去掉多余的·能大幅提高精度。

-

4.2.3 CCPD车牌数据集fine-tune

-

训练

-

为了进行fine-tune训练,我们需要在配置文件中设置需要使用的预训练模型地址,学习率和数据集等参数。 具体如下:

-
    -
  1. 模型存储和训练相关: -
      -
    1. Global.pretrained_model: 指向PP-OCRv3文本识别预训练模型地址
    2. -
    3. Global.eval_batch_step: 模型多少step评估一次,这里设为从第0个step开始没隔45个step评估一次,45为一个epoch总的step数。
    4. -
    -
  2. -
  3. 优化器相关 -
      -
    1. Optimizer.lr.name: 学习率衰减器设为常量 Const
    2. -
    3. Optimizer.lr.learning_rate: 做 fine-tune 实验,学习率需要设置的比较小,此处学习率设为配置文件中的0.05倍
    4. -
    5. Optimizer.lr.warmup_epoch: warmup_epoch设为0
    6. -
    -
  4. -
  5. 数据集相关 -
      -
    1. Train.dataset.data_dir:指向训练集图片存放目录
    2. -
    3. Train.dataset.label_file_list:指向训练集标注文件
    4. -
    5. Eval.dataset.data_dir:指向测试集图片存放目录
    6. -
    7. Eval.dataset.label_file_list:指向测试集标注文件
    8. -
    -
  6. -
-

使用如下命令启动 fine-tune

-
python tools/train.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
-    Global.save_model_dir=output/CCPD/rec/ \
-    Global.eval_batch_step="[0, 90]" \
-    Optimizer.lr.name=Const \
-    Optimizer.lr.learning_rate=0.0005 \
-    Optimizer.lr.warmup_epoch=0 \
-    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt] \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-

训练好的模型地址为: rec_ppocr_v3_finetune.tar

-

评估

-

训练完成后使用如下命令进行评估

-
python tools/eval.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-

使用预训练模型和CCPD车牌数据集fine-tune,指标分别如下:

- - - - - - - - - - - - - - - - - - - - - -
方案acc
PP-OCRv3中英文超轻量识别预训练模型直接预测0%
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%
-

可以看到进行fine-tune能显著提升车牌识别的效果。

-

4.2.4 CCPD车牌数据集fine-tune+量化训练

-

此处采用 PaddleOCR 中提供好的量化教程对模型进行量化训练。

-

量化训练可通过如下命令启动:

-
python3.7 deploy/slim/quantization/quant.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
+```
+训练好的模型地址为: [rec_ppocr_v3_quant.tar](https://paddleocr.bj.bcebos.com/fanliku/license_plate_recognition/rec_ppocr_v3_quant.tar)
+
+量化后指标对比如下
+
+|方案| acc    | 模型大小  | 预测速度(lite) |
+|---|--------|-------|------------|
+|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M | 4.2ms      |
+|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 93.4%  | 4.8M  | 1.8ms      |
+
+可以看到量化后能降低模型体积53%并且推理速度提升57%,但是由于识别数据过少,量化带来了1%的精度下降。
+
+速度测试基于[PaddleOCR lite教程](../deploy/lite/readme_ch.md)完成。
+
+#### 4.2.5 模型导出
+
+使用如下命令可以将训练好的模型进行导出。
+
+* 非量化模型
+```bash
+python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
     Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
-    Global.save_model_dir=output/CCPD/rec_quant/ \
-    Global.eval_batch_step="[0, 90]" \
-    Optimizer.lr.name=Const \
-    Optimizer.lr.learning_rate=0.0005 \
-    Optimizer.lr.warmup_epoch=0 \
-    Train.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Train.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/train/rec.txt] \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-

训练好的模型地址为: rec_ppocr_v3_quant.tar

-

量化后指标对比如下

- - - - - - - - - - - - - - - - - - - - - - - -
方案acc模型大小预测速度(lite)
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化93.4%4.8M1.8ms
-

可以看到量化后能降低模型体积53%并且推理速度提升57%,但是由于识别数据过少,量化带来了1%的精度下降。

-

速度测试基于PaddleOCR lite教程完成。

-

4.2.5 模型导出

-

使用如下命令可以将训练好的模型进行导出。

-
    -
  • 非量化模型
  • -
-
python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/rec/infer
-
    -
  • 量化模型
  • -
-
python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec_quant/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/rec_quant/infer
-

4.3 计算End2End指标

-

端到端指标可通过 PaddleOCR内置脚本 进行计算,具体步骤如下:

-
    -
  1. 导出模型
  2. -
-

通过如下命令进行模型的导出。注意,量化模型导出时,需要配置eval数据集

-
# 检测模型
+    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
+```
 
-# 预训练模型
-python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_det_distill_train/student.pdparams \
-    Global.save_inference_dir=output/ch_PP-OCRv3_det_distill_train/infer
+2. 用导出的模型对测试集进行预测
 
-# 非量化模型
-python tools/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/det/infer
+此处,分别使用PP-OCRv3预训练模型,fintune模型和量化模型对测试集的所有图像进行预测,命令如下:
 
-# 量化模型
-python deploy/slim/quantization/export_model.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o \
-    Global.pretrained_model=output/CCPD/det_quant/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/det_quant/infer \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/ccpd_green \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/det.txt] \
-    Eval.loader.num_workers=0
-
-# 识别模型
-
-# 预训练模型
-python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=models/ch_PP-OCRv3_rec_train/student.pdparams \
-    Global.save_inference_dir=output/ch_PP-OCRv3_rec_train/infer
-
-# 非量化模型
-python tools/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/rec/infer
-
-# 量化模型
-python deploy/slim/quantization/export_model.py -c configs/rec/PP-OCRv3/ch_PP-OCRv3_rec.yml -o \
-    Global.pretrained_model=output/CCPD/rec_quant/best_accuracy.pdparams \
-    Global.save_inference_dir=output/CCPD/rec_quant/infer \
-    Eval.dataset.data_dir=/home/aistudio/data/CCPD2020/PPOCR \
-    Eval.dataset.label_file_list=[/home/aistudio/data/CCPD2020/PPOCR/test/rec.txt]
-
    -
  1. 用导出的模型对测试集进行预测
  2. -
-

此处,分别使用PP-OCRv3预训练模型,fintune模型和量化模型对测试集的所有图像进行预测,命令如下:

-
# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型
-python3 tools/infer/predict_system.py --det_model_dir=models/ch_PP-OCRv3_det_distill_train/infer --rec_model_dir=models/ch_PP-OCRv3_rec_train/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/pretrain --use_dilation=true
+python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det_quant/infer --rec_model_dir=output/CCPD/rec_quant/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/quant --use_dilation=true
+```
 
-# PP-OCRv3中英文超轻量检测预训练模型+fine-tune,PP-OCRv3中英文超轻量识别预训练模型+fine-tune
-python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det/infer --rec_model_dir=output/CCPD/rec/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/fine-tune --use_dilation=true
+3. 转换label并计算指标
 
-# PP-OCRv3中英文超轻量检测预训练模型 fine-tune +量化,PP-OCRv3中英文超轻量识别预训练模型 fine-tune +量化 结果转换和评估
-python3 tools/infer/predict_system.py --det_model_dir=output/CCPD/det_quant/infer --rec_model_dir=output/CCPD/rec_quant/infer --det_limit_side_len=736 --det_limit_type=min --image_dir=/home/aistudio/data/CCPD2020/ccpd_green/test/ --draw_img_save_dir=infer/quant --use_dilation=true
-
    -
  1. 转换label并计算指标
  2. -
-

将gt和上一步保存的预测结果转换为端对端评测需要的数据格式,并根据转换后的数据进行端到端指标计算

-
python3 tools/end2end/convert_ppocr_label.py --mode=gt --label_path=/home/aistudio/data/CCPD2020/PPOCR/test/det.txt --save_folder=end2end/gt
+python3 tools/end2end/eval_end2end.py end2end/gt end2end/quant
+```
 
-# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型 结果转换和评估
-python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/pretrain/system_results.txt --save_folder=end2end/pretrain
-python3 tools/end2end/eval_end2end.py end2end/gt end2end/pretrain
-
-# PP-OCRv3中英文超轻量检测预训练模型,PP-OCRv3中英文超轻量识别预训练模型+后处理去掉多识别的`·` 结果转换和评估
-# 需手动修改后处理函数
-python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/post/system_results.txt --save_folder=end2end/post
-python3 tools/end2end/eval_end2end.py end2end/gt end2end/post
-
-# PP-OCRv3中英文超轻量检测预训练模型 fine-tune,PP-OCRv3中英文超轻量识别预训练模型 fine-tune 结果转换和评估
-python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/fine-tune/system_results.txt --save_folder=end2end/fine-tune
-python3 tools/end2end/eval_end2end.py end2end/gt end2end/fine-tune
-
-# PP-OCRv3中英文超轻量检测预训练模型 fine-tune +量化,PP-OCRv3中英文超轻量识别预训练模型 fine-tune +量化 结果转换和评估
-python3 tools/end2end/convert_ppocr_label.py --mode=pred --label_path=infer/quant/system_results.txt --save_folder=end2end/quant
-python3 tools/end2end/eval_end2end.py end2end/gt end2end/quant
-

日志如下:

-
The convert label saved in end2end/gt
-The convert label saved in end2end/pretrain
-start testing...
-hit, dt_count, gt_count 2 5988 5006
-character_acc: 70.42%
-avg_edit_dist_field: 2.37
-avg_edit_dist_img: 2.37
-precision: 0.03%
-recall: 0.04%
-fmeasure: 0.04%
-The convert label saved in end2end/post
-start testing...
-hit, dt_count, gt_count 4224 5988 5006
-character_acc: 81.59%
-avg_edit_dist_field: 1.47
-avg_edit_dist_img: 1.47
-precision: 70.54%
-recall: 84.38%
-fmeasure: 76.84%
-The convert label saved in end2end/fine-tune
-start testing...
-hit, dt_count, gt_count 4286 4898 5006
-character_acc: 94.16%
-avg_edit_dist_field: 0.47
-avg_edit_dist_img: 0.47
-precision: 87.51%
-recall: 85.62%
-fmeasure: 86.55%
-The convert label saved in end2end/quant
-start testing...
-hit, dt_count, gt_count 4349 4951 5006
-character_acc: 94.13%
-avg_edit_dist_field: 0.47
-avg_edit_dist_img: 0.47
-precision: 87.84%
-recall: 86.88%
-fmeasure: 87.36%
-

各个方案端到端指标如下:

- - - - - - - - - - - - - - - - - - - - - - - - - -
模型指标
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.04%
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
78.27%
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
87.14%
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
88%
-

从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到78.27%,在CCPD数据集上进行 fine-tune 后指标进一步提升到87.14%, 在经过量化训练之后,由于检测模型的recall变高,指标进一步提升到88%。但是这个结果仍旧不符合检测模型+识别模型的真实性能(99%*94%=93%),因此我们需要对 base case 进行具体分析。

-

在之前的端到端预测结果中,可以看到很多不符合车牌标注的文字被识别出来, 因此可以进行简单的过滤来提升precision

-

为了快速评估,我们在 tools/end2end/convert_ppocr_label.py 脚本的 58 行加入如下代码,对非8个字符的结果进行过滤

-
if len(txt) != 8: # 车牌字符串长度为8
-    continue
-

此外,通过可视化box可以发现有很多框都是竖直翻转之后的框,并且没有完全框住车牌边界,因此需要进行框的竖直翻转以及轻微扩大,示意图如下:

-

-

修改前后个方案指标对比如下:

-

各个方案端到端指标如下:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
模型baseA:识别结果过滤B:use_dilationC:flip_boxbest
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.04%0.08%0.02%0.05%0.00%(A)
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
78.27%90.84%78.61%79.43%91.66%(A+B+C)
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
87.14%90.40%87.66%89.9892.5%(A+B+C)
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
88%90.54%88.5%89.46%92.02%(A+B+C)
-

从结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到91.66%,在CCPD数据集上进行 fine-tune 后指标进一步提升到92.5%, 在经过量化训练之后,指标变为92.02%。

-

4.4 部署

-
    -
  • 基于 Paddle Inference 的python推理
  • -
-

检测模型和识别模型分别 fine-tune 并导出为inference模型之后,可以使用如下命令基于 Paddle Inference 进行端到端推理并对结果进行可视化。

-
python tools/infer/predict_system.py \
-    --det_model_dir=output/CCPD/det/infer/ \
-    --rec_model_dir=output/CCPD/rec/infer/ \
-    --image_dir="/home/aistudio/data/CCPD2020/ccpd_green/test/04131106321839081-92_258-159&509_530&611-527&611_172&599_159&509_530&525-0_0_3_32_30_31_30_30-109-106.jpg" \
-    --rec_image_shape=3,48,320
-

推理结果如下

-

-
    -
  • 端侧部署
  • -
-

端侧部署我们采用基于 PaddleLite 的 cpp 推理。Paddle Lite是飞桨轻量化推理引擎,为手机、IOT端提供高效推理能力,并广泛整合跨平台硬件,为端侧部署及应用落地问题提供轻量化的部署方案。具体可参考 PaddleOCR lite教程

-

4.5 实验总结

-

我们分别使用PP-OCRv3中英文超轻量预训练模型在车牌数据集上进行了直接评估和 fine-tune 和 fine-tune +量化3种方案的实验,并基于PaddleOCR lite教程进行了速度测试,指标对比如下:

-
    -
  • 检测
  • -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
方案hmeans模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型直接预测76.12%2.5M233ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune99%2.5M233ms
PP-OCRv3中英文超轻量检测预训练模型 fine-tune + 量化98.91%1M189ms
-
    -
  • 识别
  • -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
方案acc模型大小预测速度(lite)
PP-OCRv3中英文超轻量识别预训练模型直接预测0%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的·90.97%10.3M4.2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune94.54%10.3M4,2ms
PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化93.4%4.8M1.8ms
-
    -
  • 端到端指标如下:
  • -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
方案fmeasure模型大小预测速度(lite)
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型
0.08%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的·
91.66%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune
92.5%12.8M298ms
PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化
92.02%5.8M224ms
-

结论

-

PP-OCRv3的检测模型在未经过fine-tune的情况下,在车牌数据集上也有一定的精度,经过 fine-tune 后能够极大的提升检测效果,精度达到99%。在使用量化训练后检测模型的精度几乎无损,并且模型大小压缩60%。

-

PP-OCRv3的识别模型在未经过fine-tune的情况下,在车牌数据集上精度为0,但是经过分析可以知道,模型大部分字符都预测正确,但是会多预测一个特殊字符,去掉这个特殊字符后,精度达到90%。PP-OCRv3识别模型在经过 fine-tune 后识别精度进一步提升,达到94.4%。在使用量化训练后识别模型大小压缩53%,但是由于数据量多少,带来了1%的精度损失。

-

从端到端结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到91.66%,在CCPD数据集上进行 fine-tune 后指标进一步提升到92.5%, 在经过量化训练之后,指标轻微下降到92.02%但模型大小降低54%。

-
-
+ --image_dir="/home/aistudio/data/CCPD2020/ccpd_green/test/04131106321839081-92_258-159&509_530&611-527&611_172&599_159&509_530&525-0_0_3_32_30_31_30_30-109-106.jpg" \ + --rec_image_shape=3,48,320 +``` +推理结果如下 -
+![](https://ai-studio-static-online.cdn.bcebos.com/76b6a0939c2c4cf49039b6563c4b28e241e11285d7464e799e81c58c0f7707a7) -
+- 端侧部署 + +端侧部署我们采用基于 PaddleLite 的 cpp 推理。Paddle Lite是飞桨轻量化推理引擎,为手机、IOT端提供高效推理能力,并广泛整合跨平台硬件,为端侧部署及应用落地问题提供轻量化的部署方案。具体可参考 [PaddleOCR lite教程](../deploy/lite/readme_ch.md) +### 4.5 实验总结 -
- - -
- - -
-
+- 检测 - +- 识别 + +|方案| acc | 模型大小 | 预测速度(lite) | +|---|--------|-------|------------| +|PP-OCRv3中英文超轻量识别预训练模型直接预测| 0% |10.3M| 4.2ms | +|PP-OCRv3中英文超轻量识别预训练模型直接预测+后处理去掉多识别的`·`| 90.97% |10.3M| 4.2ms | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune| 94.54% | 10.3M | 4,2ms | +|PP-OCRv3中英文超轻量识别预训练模型 fine-tune + 量化| 93.4% | 4.8M | 1.8ms | -
+- 端到端指标如下: -
+|方案|fmeasure|模型大小|预测速度(lite) | +|---|---|---|---| +|PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型|0.08%|12.8M|298ms| +|PP-OCRv3中英文超轻量检测预训练模型
PP-OCRv3中英文超轻量识别预训练模型 + 后处理去掉多识别的`·`|91.66%|12.8M|298ms| +|PP-OCRv3中英文超轻量检测预训练模型+fine-tune
PP-OCRv3中英文超轻量识别预训练模型+fine-tune|92.5%|12.8M|298ms| +|PP-OCRv3中英文超轻量检测预训练模型+fine-tune+量化
PP-OCRv3中英文超轻量识别预训练模型+fine-tune+量化|92.02%|5.8M|224ms| -
+**结论** +PP-OCRv3的检测模型在未经过fine-tune的情况下,在车牌数据集上也有一定的精度,经过 fine-tune 后能够极大的提升检测效果,精度达到99%。在使用量化训练后检测模型的精度几乎无损,并且模型大小压缩60%。 -
-
+PP-OCRv3的识别模型在未经过fine-tune的情况下,在车牌数据集上精度为0,但是经过分析可以知道,模型大部分字符都预测正确,但是会多预测一个特殊字符,去掉这个特殊字符后,精度达到90%。PP-OCRv3识别模型在经过 fine-tune 后识别精度进一步提升,达到94.4%。在使用量化训练后识别模型大小压缩53%,但是由于数据量多少,带来了1%的精度损失。 -
- - - - - - - - - - - - - - - - - - - - +从端到端结果中可以看到对预训练模型不做修改,只根据场景下的具体情况进行后处理的修改就能大幅提升端到端指标到91.66%,在CCPD数据集上进行 fine-tune 后指标进一步提升到92.5%, 在经过量化训练之后,指标轻微下降到92.02%但模型大小降低54%。 From 4957a923fb8ccfbfdaf2255572953ed28062e960 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 21 Jun 2022 17:55:49 +0800 Subject: [PATCH 09/12] fix training --- ppocr/data/imaug/label_ops.py | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/ppocr/data/imaug/label_ops.py b/ppocr/data/imaug/label_ops.py index 8b017b3219..44c871d9ef 100644 --- a/ppocr/data/imaug/label_ops.py +++ b/ppocr/data/imaug/label_ops.py @@ -70,14 +70,22 @@ class DetLabelEncode(object): return data def order_points_clockwise(self, pts): - rect = np.zeros((4, 2), dtype="float32") - s = pts.sum(axis=1) - rect[0] = pts[np.argmin(s)] - rect[2] = pts[np.argmax(s)] - diff = np.diff(pts, axis=1) - rect[1] = pts[np.argmin(diff)] - rect[3] = pts[np.argmax(diff)] - return rect + """ + refer to :https://github.com/PyImageSearch/imutils/blob/9f740a53bcc2ed7eba2558afed8b4c17fd8a1d4c/imutils/perspective.py#L9 + """ + # sort the points based on their x-coordinates + xSorted = pts[np.argsort(pts[:, 0]), :] + + leftMost = xSorted[:2, :] + rightMost = xSorted[2:, :] + + leftMost = leftMost[np.argsort(leftMost[:, 1]), :] + (tl, bl) = leftMost + + D = dist.cdist(tl[np.newaxis], rightMost, "euclidean")[0] + (br, tr) = rightMost[np.argsort(D)[::-1], :] + + return np.array([tl, tr, br, bl], dtype="float32") def expand_points_num(self, boxes): max_points_num = 0 @@ -443,7 +451,9 @@ class KieLabelEncode(object): elif 'key_cls' in ann.keys(): labels.append(ann['key_cls']) else: - raise ValueError("Cannot found 'key_cls' in ann.keys(), please check your training annotation.") + raise ValueError( + "Cannot found 'key_cls' in ann.keys(), please check your training annotation." + ) edges.append(ann.get('edge', 0)) ann_infos = dict( image=data['image'], From 114d3399b89e3ed762b79286de508420c5ec8a65 Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Tue, 21 Jun 2022 17:59:44 +0800 Subject: [PATCH 10/12] fix training --- ppocr/data/imaug/label_ops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ppocr/data/imaug/label_ops.py b/ppocr/data/imaug/label_ops.py index 44c871d9ef..36017a823e 100644 --- a/ppocr/data/imaug/label_ops.py +++ b/ppocr/data/imaug/label_ops.py @@ -23,7 +23,7 @@ import string from shapely.geometry import LineString, Point, Polygon import json import copy - +from scipy.spatial import distance as dist from ppocr.utils.logging import get_logger From 32c65b0dfd9114e055173d0fd23db9609a226c5e Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Wed, 22 Jun 2022 12:26:12 +0800 Subject: [PATCH 11/12] opt points order --- tools/infer/predict_det.py | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/tools/infer/predict_det.py b/tools/infer/predict_det.py index 73387aef59..b9fab7dd0d 100755 --- a/tools/infer/predict_det.py +++ b/tools/infer/predict_det.py @@ -24,7 +24,6 @@ import cv2 import numpy as np import time import sys -from scipy.spatial import distance as dist import tools.infer.utility as utility from ppocr.utils.logging import get_logger @@ -151,22 +150,15 @@ class TextDetector(object): logger=logger) def order_points_clockwise(self, pts): - """ - refer to :https://github.com/PyImageSearch/imutils/blob/9f740a53bcc2ed7eba2558afed8b4c17fd8a1d4c/imutils/perspective.py#L9 - """ - # sort the points based on their x-coordinates - xSorted = pts[np.argsort(pts[:, 0]), :] - - leftMost = xSorted[:2, :] - rightMost = xSorted[2:, :] - - leftMost = leftMost[np.argsort(leftMost[:, 1]), :] - (tl, bl) = leftMost - - D = dist.cdist(tl[np.newaxis], rightMost, "euclidean")[0] - (br, tr) = rightMost[np.argsort(D)[::-1], :] - - return np.array([tl, tr, br, bl], dtype="float32") + rect = np.zeros((4, 2), dtype="int32") + s = pts.sum(axis=1) + rect[0] = pts[np.argmin(s)] + rect[2] = pts[np.argmax(s)] + tmp = np.delete(pts, (np.argmin(s), np.argmax(s)), axis=0) + diff = np.diff(np.array(tmp), axis=1) + rect[1] = tmp[np.argmin(diff)] + rect[3] = tmp[np.argmax(diff)] + return rect def clip_det_res(self, points, img_height, img_width): for pno in range(points.shape[0]): From 715fc2377e9ad2dab94873635a4346815673fb5e Mon Sep 17 00:00:00 2001 From: LDOUBLEV Date: Wed, 22 Jun 2022 12:29:06 +0800 Subject: [PATCH 12/12] fix --- ppocr/data/imaug/label_ops.py | 26 +++++++++----------------- tools/infer/predict_det.py | 2 +- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/ppocr/data/imaug/label_ops.py b/ppocr/data/imaug/label_ops.py index 36017a823e..39c2cbbac8 100644 --- a/ppocr/data/imaug/label_ops.py +++ b/ppocr/data/imaug/label_ops.py @@ -23,7 +23,6 @@ import string from shapely.geometry import LineString, Point, Polygon import json import copy -from scipy.spatial import distance as dist from ppocr.utils.logging import get_logger @@ -70,22 +69,15 @@ class DetLabelEncode(object): return data def order_points_clockwise(self, pts): - """ - refer to :https://github.com/PyImageSearch/imutils/blob/9f740a53bcc2ed7eba2558afed8b4c17fd8a1d4c/imutils/perspective.py#L9 - """ - # sort the points based on their x-coordinates - xSorted = pts[np.argsort(pts[:, 0]), :] - - leftMost = xSorted[:2, :] - rightMost = xSorted[2:, :] - - leftMost = leftMost[np.argsort(leftMost[:, 1]), :] - (tl, bl) = leftMost - - D = dist.cdist(tl[np.newaxis], rightMost, "euclidean")[0] - (br, tr) = rightMost[np.argsort(D)[::-1], :] - - return np.array([tl, tr, br, bl], dtype="float32") + rect = np.zeros((4, 2), dtype="float32") + s = pts.sum(axis=1) + rect[0] = pts[np.argmin(s)] + rect[2] = pts[np.argmax(s)] + tmp = np.delete(pts, (np.argmin(s), np.argmax(s)), axis=0) + diff = np.diff(np.array(tmp), axis=1) + rect[1] = tmp[np.argmin(diff)] + rect[3] = tmp[np.argmax(diff)] + return rect def expand_points_num(self, boxes): max_points_num = 0 diff --git a/tools/infer/predict_det.py b/tools/infer/predict_det.py index b9fab7dd0d..7b6bebf1fb 100755 --- a/tools/infer/predict_det.py +++ b/tools/infer/predict_det.py @@ -150,7 +150,7 @@ class TextDetector(object): logger=logger) def order_points_clockwise(self, pts): - rect = np.zeros((4, 2), dtype="int32") + rect = np.zeros((4, 2), dtype="float32") s = pts.sum(axis=1) rect[0] = pts[np.argmin(s)] rect[2] = pts[np.argmax(s)]