0 项目背景

在之前的电表系列项目开展过程中,用户提出了这样一个需求:

给一批图片,希望有一个前端操作界面,应用训练的电表检测识别模型,实现批量预测待识别图片,并将识别后的电表编号、电表读数、文件名匹配,以表格形式导出。

基于这个命题,之前AI达人训练营的几位同学各显身手,实现了多种Windows端部署方案:

(众人拾柴——应用篇)

  • AI达人特训营】PPOCR:电表检测模型的Windows端部署实现
  • AI达人特训营】电表检测WEB部署方案
  • AI达人特训营】多类别电表读数识别的Windows客户端Web端部署

应该说,单独做部署这件事,上面的几位同学的解决方案对于Windows端有相关需求的用户已经绰绰有余了。

而在本文中,我们试图进一步挖掘部署方案的其它潜力……
在这里插入图片描述

0.1 电表全系列其它参考资料

(主线篇)

1 问题分析

在实际业务过程中,我们会发现电表检测识别效果其实比较一般,连带着部署模型应用的时候,数据的矫正量其实一点也不少。

原因是数据量不够!因为demo的示例模型只是基于几百张标注图片训练的,在个别没训练到的场景上,表现捉襟见肘。

比如下面这张图,检测框就一个都没能识别出来(训练的图片多是单电表):

在这里插入图片描述

要使电表检测的精度进一步提高,除了在网络结构上下功夫(如:鸟枪换炮!基于PP-OCRv3的电表检测识别),最终还是逃不了下笨功夫——标注数据。

因为,众所周知,深度学习的最大瓶颈就是数据,企业落地深度学习技术的最大难题就是——没【标注】数据!

如果继续刨根究底,根本原因就变成了——没人!对于很多传统企业,压根不会有数据标注这个岗位,而这些企业可能由于各种经费短缺或数据敏感的原因,又不能把数据标注任务进行外包,于是整个技术应用就陷入了死循环。

我们知道,电力行业就是典型的【传统】行业之一,虽然笔者不在这个行业,但是大胆猜测,很多相关企业应该是没有专职的数据标注人员的。所以,电表检测识别模型的补充数据谁来标呢?

本文就提出一个【欠打】的解决方案——让要汇总导出抄表数据的业务员们标数据!
在这里插入图片描述

换句话说,就是将数据标注和用户【批量预测待识别图片,并将识别后的电表编号、电表读数、文件名匹配,以表格形式导出】的需求相结合,把两件事合并成一件事做,减少重复劳动,让业务人员在完成本职工作的同时,顺便帮企业把数据标注的活一起干了。
在这里插入图片描述

实现效果如下:

  1. PPOCRLabel界面改造效果
    在这里插入图片描述

  2. 导出识别文件示例
    在这里插入图片描述

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函数,而导出按钮的绝大多数设置正是来源于此。

  1. 473行,定义按钮动作和绑定函数
saveRec = action(getStr('saveRec'), self.saveRecResult,
                 '', 'save', getStr('saveRec'), enabled=False)
  1. 552行,定义全部按钮动作
    在这里插入图片描述

  2. 603行,增加动作到菜单

addActions(self.menus.file,
                   (opendir, open_dataset_dir, None, saveLabel, saveRec, exportJSON, self.autoSaveOption, None, resetAll, deleteImg,
                    quit))
  1. 1799和2464行,定义动作初始状态
self.actions.saveRec.setEnabled(True)

在PPOCRLabel中,界面按钮的GUI文字显示是通过遍历resources\strings\strings-en.properties(英文)或resources\strings\strings-zh-CN.properties(中文)这两个配置文件实现的。

  1. 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

Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐