From 11954fec3c43d4dc99a2bdec4edebe54a7f47ff2 Mon Sep 17 00:00:00 2001 From: user Date: Tue, 11 Mar 2025 11:58:57 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20Tesseract=E8=AF=86=E5=88=AB=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=A2=9E=E5=8A=A0=E7=BA=A2=E8=89=B2=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 37 ++-------- package.json | 2 +- .../app/shared/components/weight-reader.vue | 74 +++++++------------ 3 files changed, 33 insertions(+), 80 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6bcd0c6..bedd2e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@fortawesome/fontawesome-svg-core": "6.7.2", "@fortawesome/free-solid-svg-icons": "6.7.2", "@fortawesome/vue-fontawesome": "3.0.8", - "@paddlejs-models/ocr": "^1.2.4", + "@techstark/opencv-js": "^4.10.0-release.1", "@vue/compat": "3.5.13", "@vuelidate/core": "2.0.3", "@vuelidate/validators": "2.0.4", @@ -2584,35 +2584,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@paddlejs-mediapipe/opencv": { - "version": "0.0.4", - "resolved": "https://registry.npmmirror.com/@paddlejs-mediapipe/opencv/-/opencv-0.0.4.tgz", - "integrity": "sha512-bfwixZPKGFh7JcAtLToTBmBiu/nyQjVrm0gf/pn92apHJQEYyhnAFGvgDubmqQbijmtP2/fbOMR4CuSSlq2g8w==", - "license": "ISC" - }, - "node_modules/@paddlejs-models/ocr": { - "version": "1.2.4", - "resolved": "https://registry.npmmirror.com/@paddlejs-models/ocr/-/ocr-1.2.4.tgz", - "integrity": "sha512-mdvaWXQaCmLULEvCxcsUzHtDgmoDVzJX2LsqyMmJxSzfhgrtnscF1eLiLbaouDwg6n08koXP0BCzeB+0oAv/AQ==", - "license": "ISC", - "dependencies": { - "@paddlejs-mediapipe/opencv": "0.0.4", - "@paddlejs/paddlejs-backend-webgl": "^1.1.19", - "@paddlejs/paddlejs-core": "^2.1.17" - } - }, - "node_modules/@paddlejs/paddlejs-backend-webgl": { - "version": "1.2.9", - "resolved": "https://registry.npmmirror.com/@paddlejs/paddlejs-backend-webgl/-/paddlejs-backend-webgl-1.2.9.tgz", - "integrity": "sha512-cVDa0/Wbw2EyfsYqdYUPhFeqKsET79keEUWjyhYQmQkJfWg8j1qdR6yp7g6nx9qAGrqFvwuj1s0EqkYA1dok6A==", - "license": "ISC" - }, - "node_modules/@paddlejs/paddlejs-core": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/@paddlejs/paddlejs-core/-/paddlejs-core-2.2.0.tgz", - "integrity": "sha512-P3rPkF9fFHtq8uSte5gA7fJQwBNl9Ytsvj6aTcfQSsirnBO/HxMNu0gJyh7+lItvEtF92PR15eI0eOwJYfZDhQ==", - "license": "ISC" - }, "node_modules/@pinia/testing": { "version": "0.1.7", "resolved": "https://registry.npmmirror.com/@pinia/testing/-/testing-0.1.7.tgz", @@ -3145,6 +3116,12 @@ "dev": true, "license": "(Unlicense OR Apache-2.0)" }, + "node_modules/@techstark/opencv-js": { + "version": "4.10.0-release.1", + "resolved": "https://registry.npmmirror.com/@techstark/opencv-js/-/opencv-js-4.10.0-release.1.tgz", + "integrity": "sha512-S4XELidRiQeA0q1s9VQLo540wCxUo24r1O4C+LqZ6llX+sPCXvZCPv3Ice8dEIr0uavyZ8YZeKXSBdDgMXSXjw==", + "license": "Apache-2.0" + }, "node_modules/@tsconfig/node18": { "version": "18.2.4", "resolved": "https://registry.npmmirror.com/@tsconfig/node18/-/node18-18.2.4.tgz", diff --git a/package.json b/package.json index 477593d..7436424 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "@fortawesome/fontawesome-svg-core": "6.7.2", "@fortawesome/free-solid-svg-icons": "6.7.2", "@fortawesome/vue-fontawesome": "3.0.8", - "@paddlejs-models/ocr": "^1.2.4", + "@techstark/opencv-js": "^4.10.0-release.1", "@vue/compat": "3.5.13", "@vuelidate/core": "2.0.3", "@vuelidate/validators": "2.0.4", diff --git a/src/main/webapp/app/shared/components/weight-reader.vue b/src/main/webapp/app/shared/components/weight-reader.vue index 3636265..f374296 100644 --- a/src/main/webapp/app/shared/components/weight-reader.vue +++ b/src/main/webapp/app/shared/components/weight-reader.vue @@ -35,11 +35,6 @@ import { defineComponent, ref, onMounted, onBeforeUnmount } from 'vue'; import { useI18n } from 'vue-i18n'; import Tesseract from 'tesseract.js'; -//import ocr from "@paddlejs-models/ocr"; -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faCheck, faRedo } from '@fortawesome/free-solid-svg-icons'; - -library.add(faCheck, faRedo); export default defineComponent({ name: 'WeightReader', @@ -110,7 +105,7 @@ export default defineComponent({ }, 2000); }; - const captureFrame = () => { + const captureFrame = async () => { if (!video.value || !canvas.value) return; const ctx = canvas.value.getContext('2d'); @@ -133,50 +128,31 @@ export default defineComponent({ const imageData = canvas.value.toDataURL('image/jpeg'); - /* - const result = await ocr.recognize(imageData); - console.log("OCR 识别结果:", result); - - const numberMatch = result.text.match(/\d+\.\d+/); // 只提取数字 - if (numberMatch && numberMatch.length > 0) { - const weightValue = numberMatch.reduce((max, current) => { - return parseFloat(current) > parseFloat(max) ? current : max; - }, '0'); - if (parseFloat(weightValue) > 0) { - weight.value = weightValue; - //emit('weight', weightValue); - if (ocrInterval.value) { - window.clearInterval(ocrInterval.value); - ocrInterval.value = null; - hasValidWeight.value = true; - } - } - } - */ - Tesseract.recognize(imageData, 'eng', { - logger: m => {}, - }) - .then(({ data: { text } }) => { - const numberMatch = text.match(/\d+(\.\d+)?/g); - if (numberMatch && numberMatch.length > 0) { - const weightValue = numberMatch.reduce((max, current) => { - return parseFloat(current) > parseFloat(max) ? current : max; - }, '0'); + // 如果PaddleOCR识别失败,使用Tesseract作为备选 + try { + const { + data: { text }, + } = await Tesseract.recognize(imageData, 'eng', { + logger: m => {}, + }); + const numberMatch = text.match(/\d+(\.\d+)?/g); + if (numberMatch && numberMatch.length > 0) { + const weightValue = numberMatch.reduce((max, current) => { + return parseFloat(current) > parseFloat(max) ? current : max; + }, '0'); - if (parseFloat(weightValue) > 0) { - weight.value = weightValue; - //emit('weight', weightValue); - if (ocrInterval.value) { - window.clearInterval(ocrInterval.value); - ocrInterval.value = null; - hasValidWeight.value = true; - } + if (parseFloat(weightValue) > 0) { + weight.value = weightValue; + if (ocrInterval.value) { + window.clearInterval(ocrInterval.value); + ocrInterval.value = null; + hasValidWeight.value = true; } } - }) - .catch(error => { - console.error('OCR识别失败:', error); - }); + } + } catch (error) { + console.error('Tesseract识别失败:', error); + } }; const handleConfirm = () => { @@ -188,10 +164,10 @@ export default defineComponent({ startOCR(); }; - onMounted(() => { + onMounted(async () => { video.value = document.querySelector('video'); canvas.value = document.querySelector('canvas'); - //await ocr.loadModel(); // 预加载 Paddle.js OCR 模型 + startCamera(); });