该项目基于百度飞桨PPOCR,在Windows端实现电表检测模型部署。通过QT Disigner设计GUI界面,结合PyQt5实现可视化操作,利用调优后的检测和识别模型,对电表图片批量化检测识别,结果批量导出为表格。解决人工读数的重复劳动问题,虽存在识别速度较慢、准确率待提升等问题,但仍有实际意义,涉及GUI设计、模型替换等知识点。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

目前智能电表已经可以实现电表读数自动读取、自动上传等功能,但其应用还远未全面普及,考虑到更新换代需要的时间和资金成本,尤其在工业场景中,许多企业仍在大量使用传统电表,这使得电表读数仍然无法实现自动采集,人工读取电表读数暂时不可替代。
为了解决工人在电表读数读取、读数记录这一过程中重复机械劳动的痛点,项目结合当下人工智能中流行的OCR技术,应用百度飞桨的PaddleOCR文本识别工具套件,在 Windows 客户端实现可视化操作,对电表图片实现批量化检测、识别,检测结果批量化表格导出。
相比人工读取电表读数的重复机械操作,该项目一定程度上实现了读取读数、记录读数这一流程的自动化,减轻了工人的重复机械劳动,符合人工智能在工业领域应用落地产生的提升供给效率的意义。
使用 Anaconda 自带的 disigner.exe 设计一个GUI界面,生成 .ui 文件,通过一段 python 脚本将 .ui 文件转换成对应的 .py 文件,创建主程序文件 main.py,将 GUI 交互界面中获得的信息传递给主程序,由主程序完成核心的推理步骤(即电表检测识别部分),将推理结果放入一个 .csv 文件中并保存在本地电脑的指定地址。
项目文件夹 program_det_db 下各文件作用:
使用环境: Windows 10, Python 3.8, PaddlePaddle 2.3.0, paddleocr 2.5.0.3, PyQt5 5.15.4;
In [ ]
# 安装PaddlePaddle,PaddleOCR,PyQt5 !pip install PaddlePaddle !pip install paddleocr !pip install PyQt5
如果本地安装了 Anaconda,默认在 "./anaconda3/Library/bin/" 下,自带了 designer,可直接双击使用,如下图:

进入后,选择 "Widget" ,点击“创建”。

按照项目需求设计页面布局,拖动相应的图标到窗体中,共使用了3个标签,3个文本框,4个按钮,如图所示:

保存后,得到一个 .ui 文件,如图:

进入 tool_ui2py.py 文件,将第10行的地址更改成本地的项目文件夹地址,运行后,实现对 caogao.ui 文件转换成 caogao.py 文件。

为方便后期修改,将 caogao.py 文件重新复制一份并命名为 window.py 文件;
创建主程序文件 main.py;
新建 类MySignals 用于定义信号;
新建 类Signals 用于交互界面信息的传递;
在 类Signals 中,分别定义 4个函数 onclick1(), onclick2(), onclick3(), onclick4() 用于实现可视化界面的4个按钮功能;
核心推理部分的代码位于函数 onclick1() 中,也即点击按钮“开始检测”要执行的部分;
两个注意的点:

主程序文件 main.py:
In [ ]
import sys import os import csv import time import window from PyQt5 import QtWidgets from PyQt5.QtWidgets import QApplication, QMainWindow from PyQt5.QtCore import pyqtSignal, QObject from paddleocr import PaddleOCR class MySignals(QObject): # 定义信号 signal_err_ocr = pyqtSignal(str) signal_xz1 = pyqtSignal(str) signal_xz2 = pyqtSignal(str) class Signals(QMainWindow, window.Ui_Form): def __init__(self): super().__init__() self.setupUi(self) self.init_ui() # 实例化 self.ms_signals_err_ocr = MySignals() self.ms_signals_xz1 = MySignals() self.ms_signals_xz2 = MySignals() # 连接信号 self.ms_signals_err_ocr.signal_err_ocr.connect(self.update_err_ocr) self.ms_signals_xz1.signal_xz1.connect(self.update_xz1) self.ms_signals_xz2.signal_xz2.connect(self.update_xz2) # 更新第三个文本框 def update_err_ocr(self, err): self.lineEdit_3.setText(err) # 更新第一个文本框 def update_xz1(self, txt): self.lineEdit.setText(txt.replace('/', '\')) # 更新第二个文本框 def update_xz2(self, txt): self.lineEdit_2.setText(txt.replace('/', '\')) def onclick1(self): # 输入地址 lineEdit = self.lineEdit.text() # 输出地址 lineEdit_2 = self.lineEdit_2.text() # 将图片文件夹内所有图片的名字、地址存储到两个列表中,方便后续使用 # 图片文件夹位置 readpath = lineEdit # 图片名 列表 list_picturename = os.listdir(readpath) # 图片地址 列表 list_picturedir = [] self.ms_signals_err_ocr.signal_err_ocr.emit("正在进行电表检测...") for picturename in list_picturename: list_picturedir.append(readpath + '/' + picturename) # 将准备好的电表检测模型 替换掉 PaddleOCR 中的原有模型 ocr = PaddleOCR(# use_pdserving=False, det_model_dir='C:/Users/guay_/exercise_/exercise_job_wanted/det_finetune/det_db', # 地址务必修改正确 # rec_model_dir='C:/Users/guay_/exercise_/exercise_job_wanted/rec_finetune/rec_crnn', det=True, cls=True, # use_gpu=gpu, # show_log=False, # box_thresh=0.1, # det_db_box_thresh=0.2, use_angle_cls=True, lang='en') # 电表读数 list_dbds = [] # 电表编号 list_dbbh = [] # 遍历每一张图片,运用模型进行推理 for picturedir in list_picturedir: temp = ocr.ocr(picturedir, cls=True) # 若未检测出,则赋值为'null' if not temp: list_dbds.append('null') list_dbbh.append('null') # 若只检测出电表读数 elif len(temp)==1: list_dbds.append(temp[0][1][0]) list_dbbh.append('null') else: list_dbds.append(temp[0][1][0]) list_dbbh.append(temp[1][1][0]) # 获取当前时间戳 time_stamp = time.strftime('%Y-%m-%d-%H-%M-%S', time.localtime(time.time())) # 创建文件夹如果不存在的话 savepath = lineEdit_2 if not os.path.exists(savepath): os.makedirs(savepath) final_csv_path = savepath + "/result_" + time_stamp + ".csv" # 将两个列表中的数据写入一个.csv文件中 with open(final_csv_path, "w", encoding="utf-8", newline='') as f: writer = csv.writer(f) writer.writerow(('图片名', '电表读数', '电表编号')) writer.writerows(zip(list_picturename, list_dbds, list_dbbh)) self.ms_signals_err_ocr.signal_err_ocr.emit("电表检测完成!") # 点击重置按钮 触发 的事件 ,使得两个文本框 为空 def onclick2(self): self.lineEdit.setText("") self.lineEdit_2.setText("") self.lineEdit_3.setText("") # 点击第一个按钮 选择文件夹 触发的事件 def onclick3(self, filepath): m = QtWidgets.QFileDialog.getExistingDirectory(None, "选取文件夹", "C:/") # 起始路径 self.ms_signals_xz1.signal_xz1.emit(m) # 点击第二个按钮 选择文件夹 触发 的事件 def onclick4(self, filepath): m = QtWidgets.QFileDialog.getExistingDirectory(None, "选取文件夹", "C:/") # 起始路径 self.ms_signals_xz2.signal_xz2.emit(m) def init_ui(self): window.Ui_Form.setupUi(self, self) self.lineEdit.setPlaceholderText("请输入图片文件夹全路径(例如:C:\images)") self.lineEdit.setText("请输入图片文件夹全路径(例如:C:\images)") self.lineEdit_2.setPlaceholderText("请输入csv文件夹全路径(例如:C:\desktop\csv)") self.lineEdit_2.setText("请输入csv文件夹全路径(例如:C:\desktop\csv)") # 开始检测按钮 self.pushButton_3.clicked.connect(self.onclick1) # 重置按钮 self.pushButton_4.clicked.connect(self.onclick2) # 第一个选择文件夹 按钮 self.pushButton.clicked.connect(self.onclick3) # 第二个选择文件夹 按钮 self.pushButton_2.clicked.connect(self.onclick4) if __name__ == '__main__': app = QApplication(sys.argv) window_ = Signals() window_.show() sys.exit(app.exec_())本地电脑安装好环境后,将program_det_db.rar下载到本地并解压,按照上节项目创建中所述将相关地址修改好;
执行主程序文件main.py,在GUI界面中选择待检测的电表图片所在文件夹,选择输出结果保存地址,点击“开始检测”按钮,待进度框提示“电表检测完成!”,进入输出结果保存地址查看电表检测结果。
这里放上项目效果视频的链接。 https://www.bilibili.com/video/BV1Kf4y1Z7b2/?vd_source=62f69eed24d8814d22b6e0f88d6f5ca9
检测完成后效果如下图所示,在保存路径下出现检测结果的 .csv 表格文件。


本项目侧重电表检测模型的 Windows 端部署实现,推理部分使用的是 项目:PPOCR:多类别电表读数识别 中已训练好的检测、识别模型,对于实现电表读数读取、记录这一流程的自动化,减轻工人的重复机械工作,还是很有意义的。
测试时使用200张电表图片,检测、识别耗时约145秒,从速度上看并不比人手工读取、记录快,但考虑到是自动化流程,能够减轻重复机械操作,因此仍然是有意义的。目前使用的仍是本地电脑的 CPU,可考虑适配 GPU;
可考虑增大训练数据集,即电表图片数量,继续训练模型。
以上就是【AI达人特训营】PPOCR:电表检测模型的Windows端部署实现的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号