# 基于PP-OCRv3的液晶屏读数识别 - [1. 项目背景及意义](#1-项目背景及意义) - [2. 项目内容](#2-项目内容) - [3. 安装环境](#3-安装环境) - [4. 文字检测](#4-文字检测) - [4.1 PP-OCRv3检测算法介绍](#41-PP-OCRv3检测算法介绍) - [4.2 数据准备](#42-数据准备) - [4.3 模型训练](#43-模型训练) - [4.3.1 预训练模型直接评估](#431-预训练模型直接评估) - [4.3.2 预训练模型直接finetune](#432-预训练模型直接finetune) - [4.3.3 基于预训练模型Finetune_student模型](#433-基于预训练模型Finetune_student模型) - [4.3.4 基于预训练模型Finetune_teacher模型](#434-基于预训练模型Finetune_teacher模型) - [4.3.5 采用CML蒸馏进一步提升student模型精度](#435-采用CML蒸馏进一步提升student模型精度) - [4.3.6 模型导出推理](#436-4.3.6-模型导出推理) - [5. 文字识别](#5-文字识别) - [5.1 PP-OCRv3识别算法介绍](#51-PP-OCRv3识别算法介绍) - [5.2 数据准备](#52-数据准备) - [5.3 模型训练](#53-模型训练) - [5.4 模型导出推理](#54-模型导出推理) - [6. 系统串联](#6-系统串联) - [6.1 后处理](#61-后处理) - [7. PaddleServing部署](#7-PaddleServing部署) ## 1. 项目背景及意义 目前光学字符识别(OCR)技术在我们的生活当中被广泛使用,但是大多数模型在通用场景下的准确性还有待提高,针对于此我们借助飞桨提供的PaddleOCR套件较容易的实现了在垂类场景下的应用。 该项目以国家质量基础(NQI)为准绳,充分利用大数据、云计算、物联网等高新技术,构建覆盖计量端、实验室端、数据端和硬件端的完整计量解决方案,解决传统计量校准中存在的难题,拓宽计量检测服务体系和服务领域;解决无数传接口或数传接口不统一、不公开的计量设备,以及计量设备所处的环境比较恶劣,不适合人工读取数据。通过OCR技术实现远程计量,引领计量行业向智慧计量转型和发展。 ## 2. 项目内容 本项目基于PaddleOCR开源套件,以PP-OCRv3检测和识别模型为基础,针对液晶屏读数识别场景进行优化。 Aistudio项目链接:[OCR液晶屏读数识别](https://aistudio.baidu.com/aistudio/projectdetail/4080130) ## 3. 安装环境 ```python # 首先git官方的PaddleOCR项目,安装需要的依赖 # 第一次运行打开该注释 # git clone https://gitee.com/PaddlePaddle/PaddleOCR.git cd PaddleOCR pip install -r requirements.txt ``` ## 4. 文字检测 文本检测的任务是定位出输入图像中的文字区域。近年来学术界关于文本检测的研究非常丰富,一类方法将文本检测视为目标检测中的一个特定场景,基于通用目标检测算法进行改进适配,如TextBoxes[1]基于一阶段目标检测器SSD[2]算法,调整目标框使之适合极端长宽比的文本行,CTPN[3]则是基于Faster RCNN[4]架构改进而来。但是文本检测与目标检测在目标信息以及任务本身上仍存在一些区别,如文本一般长宽比较大,往往呈“条状”,文本行之间可能比较密集,弯曲文本等,因此又衍生了很多专用于文本检测的算法。本项目基于PP-OCRv3算法进行优化。 ### 4.1 PP-OCRv3检测算法介绍 PP-OCRv3检测模型是对PP-OCRv2中的CML(Collaborative Mutual Learning) 协同互学习文本检测蒸馏策略进行了升级。如下图所示,CML的核心思想结合了①传统的Teacher指导Student的标准蒸馏与 ②Students网络之间的DML互学习,可以让Students网络互学习的同时,Teacher网络予以指导。PP-OCRv3分别针对教师模型和学生模型进行进一步效果优化。其中,在对教师模型优化时,提出了大感受野的PAN结构LK-PAN和引入了DML(Deep Mutual Learning)蒸馏策略;在对学生模型优化时,提出了残差注意力机制的FPN结构RSE-FPN。 ![](https://ai-studio-static-online.cdn.bcebos.com/c306b2f028364805a55494d435ab553a76cf5ae5dd3f4649a948ea9aeaeb28b8) 详细优化策略描述请参考[PP-OCRv3优化策略](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.5/doc/doc_ch/PP-OCRv3_introduction.md#2) ### 4.2 数据准备 [计量设备屏幕字符检测数据集](https://aistudio.baidu.com/aistudio/datasetdetail/127845)数据来源于实际项目中各种计量设备的数显屏,以及在网上搜集的一些其他数显屏,包含训练集755张,测试集355张。 ```python # 在PaddleOCR下创建新的文件夹train_data mkdir train_data # 下载数据集并解压到指定路径下 unzip icdar2015.zip -d train_data ``` ```python # 随机查看文字检测数据集图片 from PIL import Image import matplotlib.pyplot as plt import numpy as np import os train = './train_data/icdar2015/text_localization/test' # 从指定目录中选取一张图片 def get_one_image(train): plt.figure() files = os.listdir(train) n = len(files) ind = np.random.randint(0,n) img_dir = os.path.join(train,files[ind]) image = Image.open(img_dir) plt.imshow(image) plt.show() image = image.resize([208, 208]) get_one_image(train) ``` ![det_png](https://ai-studio-static-online.cdn.bcebos.com/0639da09b774458096ae577e82b2c59e89ced6a00f55458f946997ab7472a4f8) ### 4.3 模型训练 #### 4.3.1 预训练模型直接评估 下载我们需要的PP-OCRv3检测预训练模型,更多选择请自行选择其他的[文字检测模型](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.5/doc/doc_ch/models_list.md#1-%E6%96%87%E6%9C%AC%E6%A3%80%E6%B5%8B%E6%A8%A1%E5%9E%8B) ```python #使用该指令下载需要的预训练模型 wget -P ./pretrained_models/ https://paddleocr.bj.bcebos.com/PP-OCRv3/chinese/ch_PP-OCRv3_det_distill_train.tar # 解压预训练模型文件 tar -xf ./pretrained_models/ch_PP-OCRv3_det_distill_train.tar -C pretrained_models ``` 在训练之前,我们可以直接使用下面命令来评估预训练模型的效果: ```python # 评估预训练模型 python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.pretrained_model="./pretrained_models/ch_PP-OCRv3_det_distill_train/best_accuracy" ``` 结果如下: | | 方案 |hmeans| |---|---------------------------|---| | 0 | PP-OCRv3中英文超轻量检测预训练模型直接预测 |47.50%| #### 4.3.2 预训练模型直接finetune ##### 修改配置文件 我们使用configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml,主要修改训练轮数和学习率参相关参数,设置预训练模型路径,设置数据集路径。 另外,batch_size可根据自己机器显存大小进行调整。 具体修改如下几个地方: ``` epoch:100 save_epoch_step:10 eval_batch_step:[0, 50] save_model_dir: ./output/ch_PP-OCR_v3_det/ pretrained_model: ./pretrained_models/ch_PP-OCRv3_det_distill_train/best_accuracy learning_rate: 0.00025 num_workers: 0 # 如果单卡训练,建议将Train和Eval的loader部分的num_workers设置为0,否则会出现`/dev/shm insufficient`的报错 ``` ##### 开始训练 使用我们上面修改的配置文件configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml,训练命令如下: ```python # 开始训练模型 python tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.pretrained_model=./pretrained_models/ch_PP-OCRv3_det_distill_train/best_accuracy ``` 评估训练好的模型: ```python # 评估训练好的模型 python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.pretrained_model="./output/ch_PP-OCR_v3_det/best_accuracy" ``` 结果如下: | | 方案 |hmeans| |---|---------------------------|---| | 0 | PP-OCRv3中英文超轻量检测预训练模型直接预测 |47.50%| | 1 | PP-OCRv3中英文超轻量检测预训练模型fintune |65.20%| #### 4.3.3 基于预训练模型Finetune_student模型 我们使用configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml,主要修改训练轮数和学习率参相关参数,设置预训练模型路径,设置数据集路径。 另外,batch_size可根据自己机器显存大小进行调整。 具体修改如下几个地方: ``` epoch:100 save_epoch_step:10 eval_batch_step:[0, 50] save_model_dir: ./output/ch_PP-OCR_v3_det_student/ pretrained_model: ./pretrained_models/ch_PP-OCRv3_det_distill_train/student learning_rate: 0.00025 num_workers: 0 # 如果单卡训练,建议将Train和Eval的loader部分的num_workers设置为0,否则会出现`/dev/shm insufficient`的报错 ``` 训练命令如下: ```python python tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o Global.pretrained_model=./pretrained_models/ch_PP-OCRv3_det_distill_train/student ``` 评估训练好的模型: ```python # 评估训练好的模型 python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_student.yml -o Global.pretrained_model="./output/ch_PP-OCR_v3_det_student/best_accuracy" ``` 结果如下: | | 方案 |hmeans| |---|---------------------------|---| | 0 | PP-OCRv3中英文超轻量检测预训练模型直接预测 |47.50%| | 1 | PP-OCRv3中英文超轻量检测预训练模型fintune |65.20%| | 2 | PP-OCRv3中英文超轻量检测预训练模型fintune学生模型 |80.00%| #### 4.3.4 基于预训练模型Finetune_teacher模型 首先需要从提供的预训练模型best_accuracy.pdparams中提取teacher参数,组合成适合dml训练的初始化模型,提取代码如下: ```python cd ./pretrained_models/ # transform teacher params in best_accuracy.pdparams into teacher_dml.paramers import paddle # load pretrained model all_params = paddle.load("ch_PP-OCRv3_det_distill_train/best_accuracy.pdparams") # print(all_params.keys()) # keep teacher params t_params = {key[len("Teacher."):]: all_params[key] for key in all_params if "Teacher." in key} # print(t_params.keys()) s_params = {"Student." + key: t_params[key] for key in t_params} s2_params = {"Student2." + key: t_params[key] for key in t_params} s_params = {**s_params, **s2_params} # print(s_params.keys()) paddle.save(s_params, "ch_PP-OCRv3_det_distill_train/teacher_dml.pdparams") ``` 我们使用configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml,主要修改训练轮数和学习率参相关参数,设置预训练模型路径,设置数据集路径。 另外,batch_size可根据自己机器显存大小进行调整。 具体修改如下几个地方: ``` epoch:100 save_epoch_step:10 eval_batch_step:[0, 50] save_model_dir: ./output/ch_PP-OCR_v3_det_teacher/ pretrained_model: ./pretrained_models/ch_PP-OCRv3_det_distill_train/teacher_dml learning_rate: 0.00025 num_workers: 0 # 如果单卡训练,建议将Train和Eval的loader部分的num_workers设置为0,否则会出现`/dev/shm insufficient`的报错 ``` 训练命令如下: ```python python tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml -o Global.pretrained_model=./pretrained_models/ch_PP-OCRv3_det_distill_train/teacher_dml ``` 评估训练好的模型: ```python # 评估训练好的模型 python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_dml.yml -o Global.pretrained_model="./output/ch_PP-OCR_v3_det_teacher/best_accuracy" ``` 结果如下: | | 方案 |hmeans| |---|---------------------------|---| | 0 | PP-OCRv3中英文超轻量检测预训练模型直接预测 |47.50%| | 1 | PP-OCRv3中英文超轻量检测预训练模型fintune |65.20%| | 2 | PP-OCRv3中英文超轻量检测预训练模型fintune学生模型 |80.00%| | 3 | PP-OCRv3中英文超轻量检测预训练模型fintune教师模型 |84.80%| #### 4.3.5 采用CML蒸馏进一步提升student模型精度 需要从4.3.3和4.3.4训练得到的best_accuracy.pdparams中提取各自代表student和teacher的参数,组合成适合cml训练的初始化模型,提取代码如下: ```python # transform teacher params and student parameters into cml model import paddle all_params = paddle.load("./pretrained_models/ch_PP-OCRv3_det_distill_train/best_accuracy.pdparams") # print(all_params.keys()) t_params = paddle.load("./output/ch_PP-OCR_v3_det_teacher/best_accuracy.pdparams") # print(t_params.keys()) s_params = paddle.load("./output/ch_PP-OCR_v3_det_student/best_accuracy.pdparams") # print(s_params.keys()) for key in all_params: # teacher is OK if "Teacher." in key: new_key = key.replace("Teacher", "Student") #print("{} >> {}\n".format(key, new_key)) assert all_params[key].shape == t_params[new_key].shape all_params[key] = t_params[new_key] if "Student." in key: new_key = key.replace("Student.", "") #print("{} >> {}\n".format(key, new_key)) assert all_params[key].shape == s_params[new_key].shape all_params[key] = s_params[new_key] if "Student2." in key: new_key = key.replace("Student2.", "") print("{} >> {}\n".format(key, new_key)) assert all_params[key].shape == s_params[new_key].shape all_params[key] = s_params[new_key] paddle.save(all_params, "./pretrained_models/ch_PP-OCRv3_det_distill_train/teacher_cml_student.pdparams") ``` 训练命令如下: ```python python tools/train.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.pretrained_model=./pretrained_models/ch_PP-OCRv3_det_distill_train/teacher_cml_student Global.save_model_dir=./output/ch_PP-OCR_v3_det_finetune/ ``` 评估训练好的模型: ```python # 评估训练好的模型 python tools/eval.py -c configs/det/ch_PP-OCRv3/ch_PP-OCRv3_det_cml.yml -o Global.pretrained_model="./output/ch_PP-OCR_v3_det_finetune/best_accuracy" ``` 结果如下: | | 方案 |hmeans| |---|---------------------------|---| | 0 | PP-OCRv3中英文超轻量检测预训练模型直接预测 |47.50%| | 1 | PP-OCRv3中英文超轻量检测预训练模型fintune |65.20%| | 2 | PP-OCRv3中英文超轻量检测预训练模型fintune学生模型 |80.00%| | 3 | PP-OCRv3中英文超轻量检测预训练模型fintune教师模型 |84.80%| | 4 | 基于2和3训练好的模型fintune |82.70%| 如需获取已训练模型,请扫码填写问卷,加入PaddleOCR官方交流群获取全部OCR垂类模型下载链接、《动手学OCR》电子书等全套OCR学习资料🎁