lichong 7 months ago
parent
commit
5184b8bc81
  1. 2
      code/end.py
  2. 133
      code/inference copy.py
  3. 52
      code/main.py
  4. 0
      code/models/best.pt
  5. BIN
      code/ocrCurrent.jpg
  6. 4
      code/start.bat
  7. 3
      code/start.vbs
  8. 2
      front/src/main/index.js
  9. 4
      front/src/renderer/src/assets/css/base.css
  10. 6
      front/src/renderer/src/assets/js/db.js
  11. 13
      front/src/renderer/src/assets/json/user.json
  12. 2
      front/src/renderer/src/components/formcomponent.vue
  13. 19
      front/src/renderer/src/components/tablecomponent.vue
  14. 5
      front/src/renderer/src/main.js
  15. 101
      front/src/renderer/src/views/user.vue

2
code/end.py

@ -0,0 +1,2 @@
import subprocess
subprocess.Popen(["python", "main.py"])

133
code/inference copy.py

@ -1,133 +0,0 @@
from ultralytics import YOLO
import numpy as np
import cv2
from paddleocr import PaddleOCR
import re
import os
current_dir = os.path.dirname(os.path.abspath(__file__))
img_path = os.path.join(current_dir, "test1.jpg")
img = cv2.imread(img_path)
model = YOLO(os.path.join(current_dir, "best.pt"))
results = model.predict(img_path, device='cpu')
ocr = PaddleOCR(
use_gpu=False,
use_angle_cls=True,
det_model_dir=os.path.join(current_dir, "ocr/simple/ch_PP-OCRv4_det_infer"),
rec_model_dir=os.path.join(current_dir, "ocr/simple/ch_PP-OCRv4_rec_infer"),)
for r in results:
boxes = r.boxes
clses = np.array(boxes.cls).astype(int)
points = np.array(boxes.xyxy).astype(int)
target_0 = []
target_1 = []
target_2 = []
target_3 = []
for cls, point in zip(clses, points):
if cls == 0:
target_0.append(point)
elif cls == 1:
target_1.append(point)
elif cls == 2:
target_2.append(point)
elif cls == 3:
target_3.append(point)
# 初始化结果字典
results_summary = {
'target_0': [],
'target_1': [],
'target_2': [],
'target_3': []
}
# 检查类别数量
if (len(target_0) == 2 and len(target_1) == 1 and (len(target_2) == 1 or len(target_2) == 2) and len(target_3) == 2):
# 处理类别0
target_0 = sorted(target_0, key=lambda x: x[0])
left_point = target_0[0]
right_point = target_0[1]
for target, name in zip([left_point, right_point], ['地址', '姓名']):
target_img = img[target[1]:target[3], target[0]:target[2]]
cv2.imwrite(f'{name}.jpg', target_img)
result = ocr.ocr(target_img)
out = ''
if not result or not any(result):
out = '未识别到文字'
else:
for lines in result:
for line in lines:
out += line[1][0]
results_summary['target_0'].append(f"{name.capitalize()}: {out}")
# # 处理类别1
# for target in target_1:
# target_img = img[target[1]:target[3], target[0]:target[2]]
# cv2.imwrite(f'当前有功.jpg', target_img)
# result = ocr.ocr(target_img)
# out = ''
# for lines in result:
# for line in lines:
# out += line[1][0]
# out = out[:-2] + '.' + out[-2:]
# results_summary['target_1'].append(f"当前有功: {out}")
# 处理类别1
for target in target_1:
target_img = img[target[1]-5:target[3]+5, target[0]-5:target[2]+5]
cv2.imwrite(f'当前有功.jpg', target_img)
result = ocr.ocr(target_img, det=False)
for lines in result:
for line in lines:
out = line[0]
out = re.sub(r'\.', '', out)
out = out[:-2] + '.' + out[-2:]
results_summary['target_1'].append(f"当前有功: {out}")
# 处理类别2
if len(target_2) == 2:
target_2_sorted = sorted(target_2, key=lambda x: x[1])
top_target = target_2_sorted[0]
target_img = img[top_target[1]:top_target[3], top_target[0]:top_target[2]]
elif len(target_2) == 1:
top_target = target_2[0]
target_img = img[top_target[1]:top_target[3], top_target[0]:top_target[2]]
cv2.imwrite(f'电表资产号.jpg', target_img)
result = ocr.ocr(target_img)
longest_line = ""
max_length = 0
for lines in result:
for line in lines:
text = line[1][0]
if len(text) > max_length:
longest_line = text
max_length = len(text)
results_summary['target_2'].append(f"电表资产号: {longest_line}")
# 处理类别3
target_3 = sorted(target_3, key=lambda x: x[0])
left_point = target_3[0]
right_point = target_3[1]
for target, name in zip([left_point, right_point], ['封印1', '封印2']):
target_img = img[target[1]:target[3], target[0]:target[2]]
height, width = target_img.shape[:2]
if width <= height:
target_img = cv2.transpose(target_img)
target_img = cv2.flip(target_img, flipCode=1)
cv2.imwrite(f'{name}.jpg', target_img)
result = ocr.ocr(target_img)
out = ''
for lines in result:
for line in lines:
out += line[1][0]
results_summary['target_3'].append(f"{name.capitalize()}: {out}")
for category, result_list in results_summary.items():
for result in result_list:
print(result)
else:
print("图像不清晰或要素不全请重新拍摄或人工记录")

52
code/main.py

@ -1,4 +1,4 @@
from flask import Flask,request
from flask import Flask,request,jsonify,json
from flask_cors import CORS
from ultralytics import YOLO
import base64
@ -17,24 +17,24 @@ CORS(app) # 允许所有来源的请求
# CORS(app)
# 加载模型
current_dir = os.path.dirname(os.path.abspath(__file__))
model = YOLO(os.path.join(current_dir, "best.pt"))
model = YOLO(os.path.join(current_dir, "models/best.pt"))
print("模型加载成功")
ocrSimple = PaddleOCR(
ocrSimple = [PaddleOCR(
use_gpu=False,
use_angle_cls=True,
det_model_dir=os.path.join(current_dir, "ocr/simple/ch_PP-OCRv4_det_infer"),
rec_model_dir=os.path.join(current_dir, "ocr/simple/ch_PP-OCRv4_rec_infer"),
# det_model_dir=os.path.join(current_dir, "ocr/complex/ch_PP-OCRv4_det_server_infer"),
# rec_model_dir=os.path.join(current_dir, "ocr/complex/ch_PP-OCRv4_rec_server_infer"),
)
ocrComplex = PaddleOCR(
) for _ in range(4)]
ocrComplex =[PaddleOCR(
use_gpu=False,
use_angle_cls=True,
# det_model_dir=os.path.join(current_dir, "ocr/simple/ch_PP-OCRv4_det_infer"),
# rec_model_dir=os.path.join(current_dir, "ocr/simple/ch_PP-OCRv4_rec_infer"),
det_model_dir=os.path.join(current_dir, "ocr/complex/ch_PP-OCRv4_det_server_infer"),
rec_model_dir=os.path.join(current_dir, "ocr/complex/ch_PP-OCRv4_rec_server_infer"),
)
) for _ in range(4)]
# 开始识别
@app.route("/startOcr", methods=["post"])
def startOcr():
@ -99,10 +99,10 @@ def startOcr():
target_0 = sorted(target_0, key=lambda x: x[0])
left_point = target_0[0]
right_point = target_0[1]
for target, name in zip([left_point, right_point], ['地址', '姓名']):
for target, name in zip([left_point, right_point], ['address', 'name']):
target_img = img[target[1]:target[3], target[0]:target[2]]
# cv2.imwrite(f'{name}.jpg', target_img)
result = ocr.ocr(target_img)
result = ocr[0].ocr(target_img)
out = ''
if not result or not any(result):
out = '未识别到文字'
@ -111,30 +111,17 @@ def startOcr():
for line in lines:
out += line[1][0]
results_summary['target_0'].append(f"{name.capitalize()}: {out}")
# # 处理类别1
# for target in target_1:
# target_img = img[target[1]:target[3], target[0]:target[2]]
# cv2.imwrite(f'当前有功.jpg', target_img)
# result = ocr.ocr(target_img)
# out = ''
# for lines in result:
# for line in lines:
# out += line[1][0]
# out = out[:-2] + '.' + out[-2:]
# results_summary['target_1'].append(f"当前有功: {out}")
# 处理类别1
for target in target_1:
target_img = img[target[1]-5:target[3]+5, target[0]-5:target[2]+5]
# cv2.imwrite(f'当前有功.jpg', target_img)
result = ocr.ocr(target_img, det=False)
result = ocr[1].ocr(target_img, det=False)
for lines in result:
for line in lines:
out = line[0]
out = re.sub(r'\.', '', out)
out = out[:-2] + '.' + out[-2:]
results_summary['target_1'].append(f"当前有功: {out}")
results_summary['target_1'].append(f"lastPower: {out}")
# 处理类别2
if len(target_2) == 2:
@ -145,7 +132,7 @@ def startOcr():
top_target = target_2[0]
target_img = img[top_target[1]:top_target[3], top_target[0]:top_target[2]]
# cv2.imwrite(f'电表资产号.jpg', target_img)
result = ocr.ocr(target_img)
result = ocr[2].ocr(target_img)
longest_line = ""
max_length = 0
for lines in result:
@ -154,20 +141,20 @@ def startOcr():
if len(text) > max_length:
longest_line = text
max_length = len(text)
results_summary['target_2'].append(f"电表资产号: {longest_line}")
results_summary['target_2'].append(f"currentMeterId: {longest_line}")
# 处理类别3
target_3 = sorted(target_3, key=lambda x: x[0])
left_point = target_3[0]
right_point = target_3[1]
for target, name in zip([left_point, right_point], ['封印1', '封印2']):
for target, name in zip([left_point, right_point], ['qrcode1', 'qrcode2']):
target_img = img[target[1]:target[3], target[0]:target[2]]
height, width = target_img.shape[:2]
if width <= height:
target_img = cv2.transpose(target_img)
target_img = cv2.flip(target_img, flipCode=1)
# cv2.imwrite(f'{name}.jpg', target_img)
result = ocr.ocr(target_img)
result = ocr[3].ocr(target_img)
out = ''
for lines in result:
for line in lines:
@ -177,16 +164,17 @@ def startOcr():
for result in result_list:
resultList=result.split(":")
resultAll[resultList[0]]=resultList[1]
# print(result)
returnObj["resultsObj"]=resultAll
cleaned_data = {k.strip(): v.strip() for k, v in resultAll.items()}
returnObj["resultsObj"]=cleaned_data
returnObj["message"]="识别成功"
returnObj["hasError"]=False
else:
returnObj["resultsObj"]={}
returnObj["message"]="图像不清晰或要素不全请重新拍摄或人工记录"
returnObj["hasError"]=True
# endTime=time.time()
# print("运行时间:",endTime-startTime)
print("运行时间:",returnObj)
return returnObj
return jsonify(returnObj), 200, {'Content-Type': 'application/json'}
if __name__ == "__main__":
app.run(host="0.0.0.0", port=7003)
app.run(debug=False,host="0.0.0.0", port=7003)

0
code/best.pt → code/models/best.pt

BIN
code/ocrCurrent.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 MiB

After

Width:  |  Height:  |  Size: 4.3 MiB

4
code/start.bat

@ -0,0 +1,4 @@
@echo off
cd E:\code\code
python main.py start
exit

3
code/start.vbs

@ -0,0 +1,3 @@
DIM objShell
set objShell = wscript.createObject("wscript.shell")
iReturn = objShell.Run("start.bat", 0, TRUE)

2
front/src/main/index.js

@ -57,7 +57,7 @@ app.whenReady().then(() => {
})
ipcMain.on('ocrIdentify', async (eve, params) => {
let res = await axios.post(`http://127.0.0.1:7003/startOcr`, params)
mainWindow.webContents.send(`ocrResult`, res)
mainWindow.webContents.send(`ocrResult`, res.data)
})
})
app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required');

4
front/src/renderer/src/assets/css/base.css

@ -4,9 +4,9 @@ body {
padding: 0;
}
.el-table .cell {
/* .el-table .cell {
padding: 0 !important;
}
} */
.el-table .blueRow {
background-color: #a0cfff;

6
front/src/renderer/src/assets/js/db.js

@ -0,0 +1,6 @@
import Dexie from 'dexie';
export const myDatabase = new Dexie('myDatabase');
myDatabase.version(1).stores({
users: '++id, Name,Address, lastPower,currentMeterId,Qrcode1,qrcode1,create_at,update_at', // Primary key and indexed props
});

13
front/src/renderer/src/assets/json/user.json

@ -1,7 +1,14 @@
[
{
"label": "姓名",
"prop": "name",
"prop": "Name",
"type": "text",
"tableShow": true,
"formShow": true
},
{
"label": "地址",
"prop": "Address",
"type": "text",
"tableShow": true,
"formShow": true
@ -22,14 +29,14 @@
},
{
"label": "二维码1",
"prop": "qrcode1",
"prop": "Qrcode1",
"type": "text",
"tableShow": true,
"formShow": true
},
{
"label": "二维码2",
"prop": "qrcode2",
"prop": "Qrcode2",
"type": "text",
"tableShow": true,
"formShow": true

2
front/src/renderer/src/components/formcomponent.vue

@ -1,6 +1,6 @@
<template>
<div class="tableClass">
<el-form :model="formData" label-suffix="" inline :disabled="disabled">
<el-form :model="formData" label-suffix="" :disabled="disabled">
<el-form-item :label="formItem.label" :key="formIndex" v-for="(formItem, formIndex) in formHeader">
<template v-if="formItem.type === 'text'">
<el-input v-model="formData[formItem.prop]" />

19
front/src/renderer/src/components/tablecomponent.vue

@ -1,10 +1,10 @@
<template>
<div class="tableClass">
<el-table :data="tableData" height="calc(100vh - 91px)" border @select="selectChange" @select-all="selectChange" fit
:row-key="getRowKeys">
<el-table-column type="selection" width="38" :reserve-selection="true" fixed="left">
:row-key="getRowKeys" ref="tableRef">
<el-table-column type="selection" width="50" :reserve-selection="true" fixed="left">
</el-table-column>
<el-table-column type="index" width="38" :reserve-selection="true" fixed="left" label="序号">
<el-table-column type="index" width="60" :reserve-selection="true" fixed="left" label="序号">
<template #default="scope">
<span>{{ pageSize * (currentPage - 1) + scope.$index + 1 }}</span>
</template>
@ -44,10 +44,10 @@
</template>
</el-table-column>
</el-table>
<el-pagination style="margin:8px 0 0 0;place-content:center;" v-model:current-page="currentPage" v-model:page-size="pageSize"
:total="total" @size-change="handleSizeChange" layout="total, sizes, prev, pager, next, jumper"
:page-sizes="pageSizes" @current-change="handleCurrentChange" @prev-click="handleCurrentChange"
@next-click="handleCurrentChange"></el-pagination>
<el-pagination style="margin:8px 0 0 0;place-content:center;" v-model:current-page="currentPage"
v-model:page-size="pageSize" :total="total" @size-change="handleSizeChange"
layout="total, sizes, prev, pager, next, jumper" :page-sizes="pageSizes" @current-change="handleCurrentChange"
@prev-click="handleCurrentChange" @next-click="handleCurrentChange"></el-pagination>
</div>
</template>
@ -109,8 +109,11 @@ export default {
},
// key
getRowKeys(row) {
return row._id; //
return row.id; //
},
clearSelection() {
this.$refs.tableRef.clearSelection()
}
},
async mounted() { },
watch: {},

5
front/src/renderer/src/main.js

@ -6,12 +6,7 @@ import 'element-plus/dist/index.css'
import App from './App.vue'
import './assets/css/base.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import Dexie from 'dexie';
export const db = new Dexie('myDatabase');
db.version(1).stores({
friends: '++id, name, age', // Primary key and indexed props
});
const app = createApp(App)
// window.__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ = true
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {

101
front/src/renderer/src/views/user.vue

@ -37,8 +37,8 @@
<span>刷新</span>
</el-button>
<div class="inputClass">
<el-input v-model="searchParams.username" style="max-width: 600px" placeholder="请输入简称" clearable
@clear="searchData" @keyup.enter="searchData">
<el-input v-model="searchParams.Name" style="max-width: 600px" placeholder="请输入简称" clearable @clear="searchData"
@keyup.enter="searchData">
<template #append>
<el-button @click="searchData">
<el-icon>
@ -52,7 +52,7 @@
<div>
<tablecomponent :tableHeader="tableHeader" :tableData="tableData" :pageSizes="pageSizes" :total="total"
@selectChange="selectChange" @handleCurrentChange="handleCurrentChange" @handleSizeChange="handleSizeChange"
@edit="edit" @info="info" @del="del">
@edit="edit" @info="info" @del="del" ref="tableComponentRef">
</tablecomponent>
</div>
<el-dialog v-model="dialogFrom.visible" :title="dialogFrom.title" width="80%">
@ -72,10 +72,12 @@
<script>
import _ from 'lodash'
import tableHeaderLocal from '../assets/json/user.json'
import { myDatabase } from '../assets/js/db.js'
import dayjs from 'dayjs'
import tablecomponent from "../components/tablecomponent.vue"
import formcomponent from "../components/formcomponent.vue"
import { ElMessage, ElMessageBox } from 'element-plus'
import { set } from 'lodash'
export default {
name: 'user',
components: { tablecomponent, formcomponent },
@ -91,7 +93,7 @@ export default {
pageSizes: [16, 50, 100, 200],
total: 0,
searchParams: {
username: ""
Name: ""
},
selectionData: [],
dialogFrom: {
@ -103,6 +105,7 @@ export default {
},
fileOriData: [],
displayedMessages: [],//
pngCount: 0,
}
},
methods: {
@ -123,14 +126,12 @@ export default {
},
//
async successSubmit(opts) {
if (!this.displayedMessages.includes("识别中...")) {
this.displayedMessages.push("识别中...")
this.pngCount++
if (this.pngCount === 1) {
ElMessage.info({
message: '识别中...',
message: `识别图片中请稍后`,
duration: 0
})
} else {
this.displayedMessages.push("识别中...")
}
let that = this
let file = opts.file
@ -140,7 +141,7 @@ export default {
let base64Data = fileReader.result;
let params = {
base64Str: base64Data,
ocrType: "complex",//:complex_simple_
ocrType: "simple",//:complex_simple_
}
window.electron.ipcRenderer.send('ocrIdentify', params)
}
@ -153,23 +154,49 @@ export default {
initInfo() {
let that = this
window.electron.ipcRenderer.on('ocrResult', (eve, res) => {
console.log(97111, res)
if (that.displayedMessages.includes("识别中...")) {
that.displayedMessages.splice(that.displayedMessages.indexOf("识别中..."), 1)
console.log(7411, res)
ElMessage.closeAll()
if (res.hasError) {
ElMessage.info({
message: `倒数第${that.pngCount}张图片识别失败`,
duration: 0
})
} else {
ElMessage.info({
message: `正在识别倒数第${that.pngCount - 1}张图片,请稍后`,
duration: 0
})
let tableItem = _.get(res, ['resultsObj'], {})
myDatabase.users.add({ ...tableItem, create_at: dayjs().format('YYYY-MM-DD HH:mm:ss'), update_at: dayjs().format('YYYY-MM-DD HH:mm:ss') })
}
that.pngCount--
if (that.pngCount === 0) {
ElMessage.closeAll()
ElMessage.success({
message: `识别完成`,
duration: 3000
})
}
setTimeout(() => {
that.searchData()
}, 1000);
})
},
//
async updateSeach(params = {}) {
// console.log(777, params)
let userList = []
if (params.Name) {
userList = await myDatabase.users.where('Name').anyPass(user => user.includes(params.Name)).offset(this.currentPage - 1).limit(this.pageSize).toArray()
} else {
userList = await myDatabase.users.offset(this.currentPage - 1).limit(this.pageSize).toArray()
}
this.tableData = _.cloneDeep(userList)
},
//
async searchData() {
let params = {}
if (this.searchParams.username) {
params["username"] = { $regex: `${_.trim(this.searchParams.username)}`, $options: 'i' }
if (this.searchParams.Name) {
params["Name"] = { $regex: `${_.trim(this.searchParams.Name)}`, $options: 'i' }
}
this.updateSeach(params)
},
@ -199,18 +226,16 @@ export default {
},
//
async submitDialog() {
let postMethod = ["add", "multi", "edit", "get", "del"]
if (postMethod.indexOf(this.dialogFrom.type) !== -1) {
let params = {
subType: this.dialogFrom.type,
url: "/api/userInfo",
list: [{ ...this.dialogFrom.formData }]
}
await this.updateSeach(params)
await setTimeout(async () => {
await this.searchData()
}, 500);
let postMethod = ["add", "put"]
console.log(7411, postMethod, this.dialogFrom.type, this.dialogFrom.formData)
if (this.dialogFrom.type === "add") {
myDatabase.users[this.dialogFrom.type]({ ...this.dialogFrom.formData, create_at: dayjs().format('YYYY-MM-DD HH:mm:ss'), update_at: dayjs().format('YYYY-MM-DD HH:mm:ss') })
} else if (this.dialogFrom.type === "put") {
myDatabase.users[this.dialogFrom.type]({ ...this.dialogFrom.formData, update_at: dayjs().format('YYYY-MM-DD HH:mm:ss') })
}
await setTimeout(async () => {
await this.searchData()
}, 500);
this.cancelDialog()
},
//
@ -240,7 +265,7 @@ export default {
this.dialogFrom = {
visible: true,
title: "编辑用户",
type: "edit",
type: "put",
disabled: false,
formHeader: this.formHeader,
formData: { ...row }
@ -267,8 +292,8 @@ export default {
let idList = []
for (let i = 0; i < delList.length; i++) {
let element = delList[i];
tooltipList.push(element.username)
idList.push(element._id)
tooltipList.push(element.Name)
idList.push(element.id)
}
ElMessageBox.confirm(
`是否删除(${_.join(tooltipList, ",")})?`,
@ -280,15 +305,12 @@ export default {
}
)
.then(async () => {
let params = {
subType: "del",
url: "/api/userInfo",
ids: idList,
}
await this.updateSeach(params)
this.$refs.tableComponentRef.clearSelection()
await myDatabase.users.bulkDelete(idList)
await this.searchData()
})
.catch(() => {
console.log(333)
ElMessage({
type: 'info',
message: '取消删除',
@ -308,11 +330,8 @@ export default {
}
)
.then(async () => {
let params = {
subType: "delAll",
url: "/api/userInfo",
}
await this.updateSeach(params)
this.$refs.tableComponentRef.clearSelection()
await myDatabase.users.clear()
await this.searchData()
})
.catch(() => {

Loading…
Cancel
Save