Wie implementiert man OCR (optische Zeichenerkennung)? Der folgende Artikel stellt Ihnen vor, wie Sie node zur Implementierung von OCR verwenden. Ich hoffe, er wird Ihnen hilfreich sein!
ocr ist eine optische Zeichenerkennung, die einfach ausgedrückt den Text auf dem Bild erkennt.
Leider bin ich nur ein einfacher Webprogrammierer? Ich weiß nicht viel über KI. Wenn ich OCR implementieren möchte, kann ich nur eine Bibliothek eines Drittanbieters finden.
Es gibt viele Drittanbieter-Bibliotheken für OCR in der Python-Sprache. Ich habe lange nach einer Drittanbieter-Bibliothek für NodeJS gesucht, um OCR zu implementieren. Endlich habe ich herausgefunden, dass die Bibliothek tesseract.js immer noch OCR implementieren kann sehr praktisch. [Verwandte Tutorial-Empfehlungen: nodejs Video-Tutorial]
Online-Beispiel: http://www.lolmbbs.com/tool/ocr
tesserract.js das Die Bibliothek bietet mehrere Versionen zur Auswahl. Ich verwende die Offline-Version tesseract.js-offline. Schließlich ist jeder von schlechten Netzwerkbedingungen betroffen. Standard-Beispielcode
默认示例代码
const { createWorker } = require('tesseract.js'); const path = require('path'); const worker = createWorker({ langPath: path.join(__dirname, '..', 'lang-data'), logger: m => console.log(m), }); (async () => { await worker.load(); await worker.loadLanguage('eng'); await worker.initialize('eng'); const { data: { text } } = await worker.recognize(path.join(__dirname, '..', 'images', 'testocr.png')); console.log(text); await worker.terminate(); })();
tesseract.js 离线版本默认示例代码只支持识别英文,如果识别中文,结果会是一堆问号。但是幸运的是你可以导入多个训练好的语言模型,让它支持多个语言的识别。
从https://github.com/naptha/tessdata/tree/gh-pages/4.0.0这里下载你需要的对应语言模型,放入到根目录下的lang-data目录下
我这里选择了中(chi_sim.traineddata.gz
)日(jpn.traineddata.gz
)英(eng.traineddata.gz
)三国语言模型。
修改代码中加载和初始化模型的语言项配置,来同时支持中日英三国语言。
await worker.loadLanguage('chi_sim+jpn+eng'); await worker.initialize('chi_sim+jpn+eng');
为了方便大家的测试,我在示例的离线版本,已经放入了中日韩三国语言的训练模型和实例代码以及测试图片。
https://github.com/Selenium39/tesseract.js-offline
如果你运行了离线的版本,你会发现模型的加载和ocr的识别有点慢。可以通过这两个步骤优化。
web项目中,你可以在应用一启动的时候就加载模型,这样后续接收到ocr请求的时候就可以不用等待模型加载了。
参照Why I refactor tesseract.js v2?这篇博客,可以通过createScheduler
方法添加多个worker线程来并发的处理ocr请求。
多线程并发处理ocr请求示例
const Koa = require('koa') const Router = require('koa-router') const router = new Router() const app = new Koa() const path = require('path') const moment = require('moment') const { createWorker, createScheduler } = require('tesseract.js') ;(async () => { const scheduler = createScheduler() for (let i = 0; i < 4; i++) { const worker = createWorker({ langPath: path.join(__dirname, '.', 'lang-data'), cachePath: path.join(__dirname, '.'), logger: m => console.log(`${moment().format('YYYY-MM-DD HH:mm:ss')}-${JSON.stringify(m)}`) }) await worker.load() await worker.loadLanguage('chi_sim+jpn+eng') await worker.initialize('chi_sim+jpn+eng') scheduler.addWorker(worker) } app.context.scheduler = scheduler })() router.get('/test', async (ctx) => { const { data: { text } } = await ctx.scheduler.addJob('recognize', path.join(__dirname, '.', 'images', 'chinese.png')) // await ctx.scheduler.terminate() ctx.body = text }) app.use(router.routes(), router.allowedMethods()) app.listen(3002)
发起并发请求,可以看到多个worker再并发执行ocr任务
ab -n 4 -c 4 localhost:3002/test
<template> <div> <div style="margin-top:30px;height:500px"> <div class="show"> <vueCropper v-if="imgBase64" ref="cropper" :img="imgBase64" :output-size="option.size" :output-type="option.outputType" :info="true" :full="option.full" :can-move="option.canMove" :can-move-box="option.canMoveBox" :original="option.original" :auto-crop="option.autoCrop" :fixed="option.fixed" :fixed-number="option.fixedNumber" :center-box="option.centerBox" :info-true="option.infoTrue" :fixed-box="option.fixedBox" :max-img-size="option.maxImgSize" style="background-image:none" @mouseenter.native="enter" @mouseleave.native="leave" ></vueCropper> <el-upload v-else ref="uploader" class="avatar-uploader" drag multiple action="" :show-file-list="false" :limit="1" :http-request="upload" > <i class="el-icon-plus avatar-uploader-icon"></i> </el-upload> </div> <div class="ocr" @mouseleave="leaveCard" > <el-card v-for="(item,index) in ocrResult" :key="index" class="card-box" @mouseenter.native="enterCard(item)" > <el-form size="small" label-width="100px" label-position="left" > <el-form-item label="识别结果"> <el-input v-model="item.text"></el-input> </el-form-item> </el-form> </el-card> </div> </div> <div style="margin-top:10px"> <el-button size="small" type="primary" style="width:60%" @click="doOcr" > 文字识别(OCR) </el-button> </div> </div> </template> <script> import { uploadImage, ocr } from '../utils/api' export default { name: 'Ocr', data () { return { imgSrc: '', imgBase64: '', option: { info: true, // 裁剪框的大小信息 outputSize: 0.8, // 裁剪生成图片的质量 outputType: 'jpeg', // 裁剪生成图片的格式 canScale: false, // 图片是否允许滚轮缩放 autoCrop: true, // 是否默认生成截图框 fixedBox: false, // 固定截图框大小 不允许改变 fixed: false, // 是否开启截图框宽高固定比例 fixedNumber: [7, 5], // 截图框的宽高比例 full: true, // 是否输出原图比例的截图 canMove: false, // 时候可以移动原图 canMoveBox: true, // 截图框能否拖动 original: false, // 上传图片按照原始比例渲染 centerBox: true, // 截图框是否被限制在图片里面 infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高 maxImgSize: 10000 }, ocrResult: [] } }, methods: { upload (fileObj) { const file = fileObj.file const reader = new FileReader() reader.readAsDataURL(file) reader.onload = () => { this.imgBase64 = reader.result } const formData = new FormData() formData.append('image', file) uploadImage(formData).then(res => { this.imgUrl = res.imgUrl }) }, doOcr () { const cropAxis = this.$refs.cropper.getCropAxis() const imgAxis = this.$refs.cropper.getImgAxis() const cropWidth = this.$refs.cropper.cropW const cropHeight = this.$refs.cropper.cropH const position = [ (cropAxis.x1 - imgAxis.x1) / this.$refs.cropper.scale, (cropAxis.y1 - imgAxis.y1) / this.$refs.cropper.scale, cropWidth / this.$refs.cropper.scale, cropHeight / this.$refs.cropper.scale ] const rectangle = { top: position[1], left: position[0], width: position[2], height: position[3] } if (this.imgUrl) { ocr({ imgUrl: this.imgUrl, rectangle }).then(res => { this.ocrResult.push( { text: res.text, cropInfo: { //截图框显示的大小 width: cropWidth, height: cropHeight, left: cropAxis.x1, top: cropAxis.y1 }, realInfo: rectangle //截图框在图片上真正的大小 }) }) } }, enterCard (item) { this.$refs.cropper.goAutoCrop()// 重新生成自动裁剪框 this.$nextTick(() => { // if cropped and has position message, update crop box // 设置自动裁剪框的宽高和位置 this.$refs.cropper.cropOffsertX = item.cropInfo.left this.$refs.cropper.cropOffsertY = item.cropInfo.top this.$refs.cropper.cropW = item.cropInfo.width this.$refs.cropper.cropH = item.cropInfo.height }) }, leaveCard () { this.$refs.cropper.clearCrop() }, enter () { if (this.imgBase64 === '') { return } this.$refs.cropper.startCrop() // 开始裁剪 }, leave () { this.$refs.cropper.stopCrop()// 停止裁剪 } } } </script>
1. Unterstützung der Mehrsprachenerkennung
chi_sim.traineddata.gz
), Japanisch (jpn.traineddata.gz
) und Englisch () ausgewählt eng.traineddata.gz
) Drei-Länder-Sprachmodell.
https://github.com/Selenium39/tesseract.js-offline
2. Erkennungsleistung verbessernWenn Sie die Offline-Version ausführen, werden Sie feststellen, dass das Laden des Modells und die Erkennung von OCR ein Problem darstellen etwas langsam. Es kann durch diese beiden Schritte optimiert werden. In Webprojekten können Sie das Modell laden, sobald die Anwendung gestartet wird, sodass Sie nicht warten müssen, bis das Modell verfügbar ist geladen, wenn Sie später eine OCR-Anfrage erhalten.
createScheduler
mehrere Worker-Threads hinzufügen, um OCR-Anfragen gleichzeitig zu verarbeiten. 🎜Beispiel für die gleichzeitige Multithread-Verarbeitung von OCR-Anfragen
🎜rrreee🎜Gleichzeitige Anfragen initiieren, Sie können sehen, wie mehrere Mitarbeiter gleichzeitig OCR-Aufgaben ausführen🎜🎜ab - n 4 -c 4 localhost:3002/test
🎜🎜🎜🎜🎜🎜3. Front-End-Code 🎜🎜🎜Der Front-End-Code in der Effektanzeige wird hauptsächlich mit der Elementui-Komponente und dem Vue-Cropper implementiert Komponente. 🎜🎜Vue-Cropper-Komponente Informationen zur spezifischen Verwendung finden Sie in meinem Blog zum Zuschneiden von Vue-Bildern: Verwenden von Vue-Cropper zum Zuschneiden von Bildern🎜🎜🎜PS: 🎜Beim Hochladen von Bildern können Sie zunächst die Base64 des hochgeladenen Bildes im Frontend laden , siehe zuerst Laden Sie das Bild hoch und fordern Sie dann das Backend auf, das Bild hochzuladen, was eine bessere Benutzererfahrung bietet🎜🎜Der vollständige Code lautet wie folgt🎜rrreee🎜Weitere knotenbezogene Kenntnisse finden Sie unter: 🎜nodejs-Tutorial🎜! 🎜Das obige ist der detaillierte Inhalt vonEine kurze Analyse, wie Node OCR implementiert. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!