【AI达人特训营】自定义区域OCR识别文件模型应用与打包实战
自定义区域OCR识别文件模型应用与打包实战
自定义区域OCR识别文件模型应用与打包实战
项目简介
任务描述:在实际的工作中,有时候需要根据图片中的指定区域进行重命名,为了更好的普及OCR应用,本任务需要将已经写好的代码打包为exe程序,为界面设计UI等实现,并根据导入与导出文件夹目录地址完成对导入文件夹的所有图片进行重命名。
精度指标:提供30张图片,识别正确90%以上为合格。
环境要求:
本项目有软件UI界面:需要下载QT Desinger设计软件,且需要将实例代码下载到电脑中运行。
本项目使用飞桨场景应用开发套件PaddleOCR或PaddleHUB模型的应用程序进行打包。打包可以采用QPT或是Pyinstaller。
#安装依赖包requirements.txt
!pip install -r requirements.txt -i https://mirror.baidu.com/pypi/simple
一、软件UI界面使用QT Desinger工具设计
使用界面设计工具
下载地址:QT Desinger https://build-system.fman.io/qt-designer-download
使用QT Desinger原型UI设计:
主体功能需求:
1.选择图像文件夹,将图像识别出来保存到指定目录的csv文件。图像数据集自定义,文件50张。识别的指标大于90%精度。
2.开发使用场景应用开发套件PaddleOCR或PaddleHUB模型。
3.使用QPT进行进行代码打包为exe程序。
Ui_MainWindow.py文件是绘制UI界面的代码,内容如下。
# -*- coding: utf-8 -*-
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.label_4.setGeometry(QtCore.QRect(240, 390, 301, 51))
self.label_4.setObjectName("label_4")
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setGeometry(QtCore.QRect(160, 150, 101, 16))
self.label_3.setObjectName("label_3")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(530, 20, 113, 32))
self.pushButton.setObjectName("pushButton")
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setGeometry(QtCore.QRect(530, 60, 113, 32))
self.pushButton_2.setObjectName("pushButton_2")
self.label_5 = QtWidgets.QLabel(self.centralwidget)
self.label_5.setGeometry(QtCore.QRect(240, 420, 301, 51))
self.label_5.setObjectName("label_5")
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(160, 60, 101, 31))
font = QtGui.QFont()
font.setPointSize(13)
self.label_2.setFont(font)
self.label_2.setObjectName("label_2")
self.pushButton_4 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_4.setGeometry(QtCore.QRect(380, 110, 113, 41))
self.pushButton_4.setObjectName("pushButton_4")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(160, 20, 81, 31))
font = QtGui.QFont()
font.setPointSize(13)
self.label.setFont(font)
self.label.setObjectName("label")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(240, 20, 271, 31))
self.lineEdit.setObjectName("lineEdit")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(160, 170, 551, 221))
self.textEdit.setObjectName("textEdit")
self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit_2.setGeometry(QtCore.QRect(240, 60, 271, 31))
self.lineEdit_2.setObjectName("lineEdit_2")
self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_3.setGeometry(QtCore.QRect(240, 110, 113, 41))
self.pushButton_3.setObjectName("pushButton_3")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 24))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "自定义区域OCR识别文件"))
self.label_4.setText(_translate("MainWindow", "软件版权:武汉理工大学-陈冬明所有"))
self.label_3.setText(_translate("MainWindow", "显示识别状态"))
self.pushButton.setText(_translate("MainWindow", "选择文件夹"))
self.pushButton_2.setText(_translate("MainWindow", "选择文件夹"))
self.label_5.setText(_translate("MainWindow", "技术指导:AI人工智能特训营"))
self.label_2.setText(_translate("MainWindow", "结果保存到:"))
self.pushButton_4.setText(_translate("MainWindow", "重置"))
self.label.setText(_translate("MainWindow", "图像文件夹:"))
self.pushButton_3.setText(_translate("MainWindow", "识别开始"))
二、PaddleHub关联自定义模型
PaddleHub持载选择用ch_pp-ocrv3模型。识别用的方法写在ppcorehub.py文件。
ppcorehub.py中使用paddlehub方法引用ch_pp-ocrv3模型.方法内容如下
# 定义获取名称函数
import paddlehub as hub
import cv2
#使用飞桨核心识别框架:PaddleHUB 引入 OCR的ch_pp-ocrv3模型
#注意:经过试验:在notebook上运行会报错的,报错原因notebook中运行paddlehub加载模型,需要在电脑上运行
ocr = hub.Module(name="ch_pp-ocrv3")
class PPCoreHUB(object):
def get_name(fn):
img = cv2.imread(fn)
result = ocr.recognize_text(images=[img])
# 1找到铁塔名称
indx = 0
r_data = result[0]['data']
for i in range(len(r_data)):
if '塔名称' in r_data[i]['text']:
# print(r_data[i]['text_box_position'])
indx = i
break
# 2找到铁塔名称
# 垂直方向加权,铁塔名称答案在一条直线上
weight_y = 4
# 找到离铁塔名称最近的识别框
p_x = (r_data[indx]['text_box_position'][1][0] + r_data[indx]['text_box_position'][2][0]) / 2
p_y = (r_data[indx]['text_box_position'][1][1] + r_data[indx]['text_box_position'][2][1]) / 2
min_d = p_x + p_y
name_idx = 0
for i in range(len(r_data)):
# 排除自己
if i == indx:
continue
x = (r_data[i]['text_box_position'][0][0] + r_data[i]['text_box_position'][3][0]) / 2
y = (r_data[i]['text_box_position'][0][1] + r_data[i]['text_box_position'][3][1]) / 2
dis = abs(p_x - x) + abs(p_y - y) * weight_y
# print('{0}:{1}'.format(dis,r_data[i]['text']))
if dis < min_d:
min_d = dis
name_idx = i
name = r_data[name_idx]['text']
# 3搜索夸行问题
weight_x = 1
# 底部两个点中点
p_x = (r_data[name_idx]['text_box_position'][2][0] + r_data[name_idx]['text_box_position'][3][0]) / 2
p_y = (r_data[name_idx]['text_box_position'][2][1] + r_data[name_idx]['text_box_position'][3][1]) / 2
min_d = 20 # 距离小于20存在跨行
for i in range(len(r_data)):
# 排除自己
if i == name_idx:
continue
x = (r_data[i]['text_box_position'][0][0] + r_data[i]['text_box_position'][1][0]) / 2
y = (r_data[i]['text_box_position'][0][1] + r_data[i]['text_box_position'][1][1]) / 2
dis = abs(p_x - x) * weight_x + abs(p_y - y)
# print('{0}:{1}'.format(dis,r_data[i]['text']))
if dis < min_d:
name += r_data[i]['text']
break
return name
三、数据集准备
这里引用数据集是塔类业务交付验收单
数据集链接地址:https://aistudio.baidu.com/aistudio/datasetdetail/142101
数据集包:30张手写图片,目录:/home/aistudio/data
四、运行实例
界面、识别程序、物料数据集都准备好后,开始运行。
程序需下载到你的主机本地,注意路径。
窗口呈现和执行文件mainocr.py,内容如下
import sys
import os
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5 import QtWidgets
from PyQt5.QtCore import pyqtSignal, QObject
from threading import Thread
#有UI界面展示的需要电脑运行,不然报错。
import ppcorehub as hub
import Ui_MainWindow as UI
UI =Ui_MainWindow()
#1.先定义UI端post提交信号
class UipostWay(QObject):
#图像文件夹 input框
post_lineEdit = pyqtSignal(str)
#结果保存指定文件夹 input框
post_lineEdit_2 = pyqtSignal(str)
#显示识别状态
post_label_3 = pyqtSignal(str)
#多文本框
post_textEdit = pyqtSignal(str)
#2.定义post对像传值和对应的方法
class RunnerStart(QMainWindow, UI.Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self) #加载原始定义界面
self.init_ui() #再根据实际进行初化赋值
# 实例化界面中的值
self.post_lineEdit_val = UipostWay()
self.post_lineEdit_2_val = UipostWay()
self.post_label_3_val = UipostWay()
self.post_textEdit_val = UipostWay()
# 将值 和 界面控件进行关联,并且使用connect要指明使用的方法
self.post_lineEdit_val.post_lineEdit.connect(self.update_lineEdit) #图像文件夹的input
self.post_lineEdit_2_val.post_lineEdit_2.connect(self.update_lineEdit_2)#结果保存的input
self.post_label_3_val.post_label_3.connect(self.update_label_3) #状态标签
self.post_textEdit_val.post_textEdit.connect(self.update_textEdit) #多文本框内容
#UI界面初始化
def init_ui(self):
UI.Ui_MainWindow.setupUi(self, self)
self.lineEdit.setPlaceholderText("需要选择识别图片文件夹全路径")
self.lineEdit.setText("")
self.lineEdit_2.setPlaceholderText("需要选择保存结果文件夹全路径")
self.lineEdit_2.setText("")
self.label_3.setText("显示识别状态")
#定义按钮的点击事件
self.pushButton.clicked.connect(self.open_images_folder)
self.pushButton_2.clicked.connect(self.open_save_folder)
self.pushButton_3.clicked.connect(self.start_rec_runner)
self.pushButton_4.clicked.connect(self.redo)
# 图像文件夹的input
def update_lineEdit(self,txt):
self.lineEdit.setText(txt.replace('\\', '/'))
# 结果保存的input
def update_lineEdit_2(self,txt):
self.lineEdit_2.setText(txt.replace('\\', '/'))
# 状态标签
def update_label_3(self,txt):
self.label_3.setText(txt.replace('/', '\\'))
# 多文本框内容
def update_textEdit(self,txt):
get_textEdit = self.textEdit.toPlainText()
str_content = get_textEdit + txt.replace('\\', '/')
self.textEdit.setText(str_content)
# 选择图像文件夹的按钮点击事件
def open_images_folder(self,txt):
m = QtWidgets.QFileDialog.getExistingDirectory(None, "选取文件夹", "")
self.post_lineEdit_val.post_lineEdit.emit(m)
# 选择保存文件夹的按钮点击事件
def open_save_folder(self,txt):
m = QtWidgets.QFileDialog.getExistingDirectory(None, "选取文件夹", "")
self.post_lineEdit_2_val.post_lineEdit_2.emit(m)
# 选择开始识别的按钮点击事件
def start_rec_runner(self,txt):
self.textEdit.setText("")
img_path = self.lineEdit.text()
csv_path = self.lineEdit_2.text()
img_dir = img_path
output_dir = csv_path
def run_start():
self.post_label_3_val.post_label_3.emit("正在进行识别...")
t0 = Thread(target=run_start)
t0.start()
def run_rec():
save_txt = ""
k = 1
for pic in os.listdir(img_dir):
fn = os.path.join(img_dir, pic)
#引用封装过的paddlehub方法
name = hub.PPCoreHUB.get_name(fn)
import shutil
shutil.copy(fn, os.path.join(output_dir, name + fn[-9:]))
txt_str = '{0}.{1}:{2}'.format(k,os.path.basename(fn), name) + "\r\n"
save_txt = save_txt + txt_str
self.post_textEdit_val.post_textEdit.emit(txt_str)
k = k + 1
self.post_label_3_val.post_label_3.emit("识别完成")
#识别完成后-将文本保存到指定的文件夹
rec_result_str = ''.join(save_txt)
os.chdir(csv_path)
fs = open('rec_result_file.txt', 'w', encoding='utf-8-sig')
fs.write(rec_result_str)
t1 = Thread(target=run_rec)
t1.start()
# 选择重置按钮点击事件
def redo(self):
self.lineEdit.setText("")
self.lineEdit_2.setText("")
self.textEdit.setText("")
self.label_3.setText("显示识别状态")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = RunnerStart()
window.show()
sys.exit(app.exec_())
执行命令后将会出现窗口,就可以进行识别过程了:
python3.8 /home/aistudio/mainocr.py
五、PYQT生成界面-识别过程如下
5.1选择要识别的文件夹目录
5.2点击识别开始,可以看到运行状态有:识别进行中、识别完成
5.3识别完成后,输出到output文件夹,其中包含重命名图片文件和rec_result_file.txt标识文件。
如图1:输出了重命名好的图片文件格式组合:“重命名文件_原文件最后四数字.jpg”
如图2:底部输出了rec_result_file.txt标记文件
如图3:打开rec_result_file.txt标记文件,原文件名和识别重命名标记一一对应
六、将OCR应用程序进行打包
#安装pyinstaller 需要到本机安装
!pip install pyinstaller -i https://pypi.tuna.tsinghua.edu.cn/simple
执行打包任务
#在自己的电脑上进行打包
!pyinstaller -F -w mainocr.py -p Ui_MainWindow.py -p ppcorehub.py --hidden-import PPCoreHUB --hidden-import Ui_MainWindow
执行完上边命令后,查看打包结果
1.生成了mainocr.pkg文件
2.生成目录位置:返回了succesfully等等信息
3.打开disth目录会发现mainocr和mainocr.app文件
4.打开build目录,会发现mainocr.pkg执行文件。若你是windows系统则是mainocr.exe文件.
总结
1.整个工作流程,难点在界面逻辑,因为用QT Desinger实现的界面,QT本身就是跨平台的。
2.模型策略用PPaddleHUB引入ch_pp-ocrv3模型。
3.打包原本是要用QPT的,发现它支持的windows,所以遵从导师的建议改用了pyinstaller来实现打包。
最后,感谢我的导师高睿,班长,班主任给予的建议和帮助。
开源链接:原项目地址https://aistudio.baidu.com/aistudio/projectdetail/4292245
更多推荐
所有评论(0)