电表检测部署应用:手把手教你把PPOCRLabel改成想要的模样
基于PPOCRLabelv2,集数据标注和业务批量化表格导出为一体的电表检测识别部署方案。
0 项目背景
在之前的电表系列项目开展过程中,用户提出了这样一个需求:
给一批图片,希望有一个前端操作界面,应用训练的电表检测识别模型,实现批量预测待识别图片,并将识别后的电表编号、电表读数、文件名匹配,以表格形式导出。
基于这个命题,之前AI达人训练营的几位同学各显身手,实现了多种Windows端部署方案:
(众人拾柴——应用篇)
应该说,单独做部署这件事,上面的几位同学的解决方案对于Windows端有相关需求的用户已经绰绰有余了。
而在本文中,我们试图进一步挖掘部署方案的其它潜力……
0.1 电表全系列其它参考资料
(主线篇)
-
数据标注懒人包:PPOCRLabel极速增强版——以电表识别为例(二)
1 问题分析
在实际业务过程中,我们会发现电表检测识别效果其实比较一般,连带着部署模型应用的时候,数据的矫正量其实一点也不少。
原因是数据量不够!因为demo的示例模型只是基于几百张标注图片训练的,在个别没训练到的场景上,表现捉襟见肘。
比如下面这张图,检测框就一个都没能识别出来(训练的图片多是单电表):
要使电表检测的精度进一步提高,除了在网络结构上下功夫(如:鸟枪换炮!基于PP-OCRv3的电表检测识别),最终还是逃不了下笨功夫——标注数据。
因为,众所周知,深度学习的最大瓶颈就是数据,企业落地深度学习技术的最大难题就是——没【标注】数据!
如果继续刨根究底,根本原因就变成了——没人!对于很多传统企业,压根不会有数据标注这个岗位,而这些企业可能由于各种经费短缺或数据敏感的原因,又不能把数据标注任务进行外包,于是整个技术应用就陷入了死循环。
我们知道,电力行业就是典型的【传统】行业之一,虽然笔者不在这个行业,但是大胆猜测,很多相关企业应该是没有专职的数据标注人员的。所以,电表检测识别模型的补充数据谁来标呢?
本文就提出一个【欠打】的解决方案——让要汇总导出抄表数据的业务员们标数据!
换句话说,就是将数据标注和用户【批量预测待识别图片,并将识别后的电表编号、电表读数、文件名匹配,以表格形式导出】的需求相结合,把两件事合并成一件事做,减少重复劳动,让业务人员在完成本职工作的同时,顺便帮企业把数据标注的活一起干了。
实现效果如下:
-
PPOCRLabel界面改造效果
-
导出识别文件示例
2 环境准备
2.1 安装PPOCRLabel
PPOCRLabel是一款适用于OCR领域的半自动化图形标注工具,内置PP-OCR模型对数据自动标注和重新识别。使用Python3和PyQT5编写,支持矩形框标注、表格标注、不规则文本标注、关键信息标注模式,导出格式可直接用于PaddleOCR检测和识别模型的训练。
本场景中,读者需要在本地环境安装PPOCRLabel,然后通过Python脚本运行PPOCRLabel
我们将会对PPOCRLabel文件有所更改(指定新的内置模型、增加按钮和函数),因此需要通过Python脚本运行。
首先需要git clone
PaddleOCR项目:
git clone https://gitee.com/paddlepaddle/PaddleOCR.git
然后切换到PPOCRLabel目录就可以启动应用了:
cd ./PPOCRLabel
python PPOCRLabel.py --lang ch
2.2 准备电表检测导出模型
依据基于PP-OCRv3的电表检测识别项目完成训练后,可以这样导出模型:
python tools/export_model.py -c ../dianbiao/ch_PP-OCRv3_det_student.yml -o Global.pretrained_model=../dianbiao/train_log_model/det_ppocrv3_1600/best_accuracy Global.save_inference_dir=./inference/infer_det
python tools/export_model.py -c ../dianbiao/rec_en_ppocrv3.yml -o Global.pretrained_model=../dianbiao/en_PP-OCRv3_rec_train/best_accuracy Global.save_inference_dir=./inference/infer_rec
本项目直接提供了训练后导出的模型,读者可以解压后放到本地PPOCRLabel目录下:
3 源码改造
3.1 配置自定义模型
在PPOCRLabel的文档中,关于自定义模型是这样说的:
自定义模型:如果用户想将内置模型更换为自己的推理模型,可根据自定义模型代码使用,通过修改
PPOCRLabel.py
中针对PaddleOCR类的实例化 实现,例如指定检测模型:self.ocr = PaddleOCR(det=True, cls=True, use_gpu=gpu, lang=lang)
,在det_model_dir
中传入 自己的模型即可。
具体地,就是在原项目的97行代码处,这样配置:
self.ocr = PaddleOCR(use_pdserving=False,
use_angle_cls=True,
det=True,
cls=True,
det_model_dir='inference/infer_det',
rec_model_dir='inference/infer_rec',
use_gpu=gpu,
lang=lang,
show_log=False)
3.2 增加导出按钮
3.2.1 观察代码结构
增加导出按钮是改造点最多的地方,这时候,我们又要祭出“依样画葫芦”大法了。
在PPOCRLabel原项目中,其实已经提供了几种类似的导出功能:
PPOCRLabel支持三种导出方式:
自动导出:点击“文件 - 自动导出标记结果”后,用户每确认过一张图片,程序自动将标记结果写入Label.txt中。若未开启此选项,则检测到用户手动确认过5张图片后进行自动导出。 默认情况下自动导出功能为关闭状态
手动导出:点击“文件 - 导出标记结果”手动导出标记。
关闭应用程序导出
测试后我们会发现,【导出部分识别结果】这个功能和我们的需求相似度比较高。
所以,在动手写代码之前,我们首先需要仔细观察,这个作为“参照系”的导出按钮是如何实现的。
在PPOCRLabel中,最核心的无疑是PPOCRLabel.py
函数,而导出按钮的绝大多数设置正是来源于此。
- 473行,定义按钮动作和绑定函数
saveRec = action(getStr('saveRec'), self.saveRecResult,
'', 'save', getStr('saveRec'), enabled=False)
-
552行,定义全部按钮动作
-
603行,增加动作到菜单
addActions(self.menus.file,
(opendir, open_dataset_dir, None, saveLabel, saveRec, exportJSON, self.autoSaveOption, None, resetAll, deleteImg,
quit))
- 1799和2464行,定义动作初始状态
self.actions.saveRec.setEnabled(True)
在PPOCRLabel中,界面按钮的GUI文字显示是通过遍历resources\strings\strings-en.properties
(英文)或resources\strings\strings-zh-CN.properties
(中文)这两个配置文件实现的。
- 91行,绑定GUI文字显示
saveRec=Export Recognition Result
或者
saveRec=导出识别结果
3.2.2 增加导出Excel按钮
我们其实有两种操作,一种是新增一个按钮,这就需要参考上面的分析,与“参照系”一一对应在下面新增。
另一种改动量比较小的做法,比较适合“懒人”,直接复用原有的【导出识别结果】,然后把绑定的具体动作函数改成Excel导出就行。
3.3 定义Excel导出函数
本项目中,我们使用openpyxl
库来进行Excel文件的创建和写入,操作如下:
import openpyxl
def saveExcel(self):
if {} in [self.PPlabelpath, self.PPlabel, self.fileStatedict]:
QMessageBox.information(self, "Information", "Check the image first")
return
excel_path = os.path.dirname(self.PPlabelpath) + '/export.xlsx'
ques_img = []
data = openpyxl.Workbook() # 新建工作簿
data.create_sheet('Sheet1') # 添加页
table = data.get_sheet_by_name('Sheet1') # 获得指定名称页
table = data.active
cell_list=[['图片名称','电表编号','电表读数']]
for key in self.fileStatedict:
idx = self.getImglabelidx(key)
try:
img = cv2.imread(key)
index = ''
metric = ''
for i, label in enumerate(self.PPlabel[idx]):
if label['difficult']:
continue
# 根据字符串长度规则,确定识别结果是编号还是电表读数
elif len(label['transcription']) > 8:
index = label['transcription']
else:
metric = label['transcription']
img_name = os.path.splitext(os.path.basename(idx))[0]
# 把图片名、编号、电表读数拼接起来
rec_result = [img_name, index, metric]
cell_list.append(rec_result)
except Exception as e:
ques_img.append(key)
print("Can not read image ", e)
for row in cell_list:
table.append(row)
data.save(excel_path) # 保存Excel文件
if ques_img:
QMessageBox.information(self,
"Information",
"The following images can not be saved, please check the image path and labels.\n"
+ "".join(str(i) + '\n' for i in ques_img))
QMessageBox.information(self, "Information", "Finish")
改造后的PPOCRLabel
项目完整版已上传到本项目中,读者可以自行下载到本地,启动后就得到改造的标注工具了。
4 总结
本项目以电表垂类场景为例,可同时实现数据标注和格式化数据批量导出,提供了一种根据自定义需求,在PPOCRLabel中,将OCR数据标注和Excel数据导出这类特定业务应用相结合的解决方案。
这下,再也不愁数据没人标注啦!
此文仅为搬运,原作链接:https://aistudio.baidu.com/aistudio/projectdetail/4355934?contributionType=1
更多推荐
所有评论(0)