Maison > interface Web > js tutoriel > le corps du texte

Une brève analyse de la façon dont le nœud implémente ocr

青灯夜游
Libérer: 2022-10-31 19:09:40
avant
1645 Les gens l'ont consulté

Comment mettre en œuvre l'OCR (reconnaissance optique de caractères) ? L'article suivant vous présentera comment utiliser node pour implémenter l'OCR. J'espère qu'il vous sera utile !

Une brève analyse de la façon dont le nœud implémente ocr

ocr est la reconnaissance optique de caractères. En termes simples, il s'agit de reconnaître le texte sur l'image.

Malheureusement, je ne suis qu'un programmeur Web de bas niveau ? Je ne connais pas grand chose en IA. Si je souhaite implémenter l'OCR, je ne peux trouver qu'une bibliothèque tierce.

Il existe de nombreuses bibliothèques tierces pour l'OCR dans le langage python. Je cherchais depuis longtemps une bibliothèque tierce pour nodejs pour implémenter l'OCR. Finalement, j'ai trouvé que la bibliothèque tesseract.js peut toujours implémenter l'OCR. très commodément. [Recommandations de didacticiel associées : Tutoriel vidéo Nodejs]

Affichage des effets

Exemple en ligne : http://www.lolmbbs.com/tool/ocr

Une brève analyse de la façon dont le nœud implémente ocr

Code détaillé

tesserract.js this La bibliothèque propose plusieurs versions parmi lesquelles choisir. J'utilise la version hors ligne tesseract.js-offline Après tout, tout le monde est affecté par de mauvaises conditions de réseau.
Une brève analyse de la façon dont le nœud implémente ocr
Exemple de code par défaut默认示例代码

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();
})();
Copier après la connexion

1. 支持多语言识别

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');
Copier après la connexion

为了方便大家的测试,我在示例的离线版本,已经放入了中日韩三国语言的训练模型和实例代码以及测试图片。
https://github.com/Selenium39/tesseract.js-offline

2. 提高识别性能

如果你运行了离线的版本,你会发现模型的加载和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, &#39;.&#39;, &#39;lang-data&#39;),
      cachePath: path.join(__dirname, &#39;.&#39;),
      logger: m => console.log(`${moment().format(&#39;YYYY-MM-DD HH:mm:ss&#39;)}-${JSON.stringify(m)}`)
    })
    await worker.load()
    await worker.loadLanguage(&#39;chi_sim+jpn+eng&#39;)
    await worker.initialize(&#39;chi_sim+jpn+eng&#39;)
    scheduler.addWorker(worker)
  }
  app.context.scheduler = scheduler
})()

router.get(&#39;/test&#39;, async (ctx) => {
  const { data: { text } } = await ctx.scheduler.addJob(&#39;recognize&#39;, path.join(__dirname, &#39;.&#39;, &#39;images&#39;, &#39;chinese.png&#39;))
  // await ctx.scheduler.terminate()
  ctx.body = text
})

app.use(router.routes(), router.allowedMethods())
app.listen(3002)
Copier après la connexion

发起并发请求,可以看到多个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 &#39;../utils/api&#39;
export default {
  name: &#39;Ocr&#39;,
  data () {
    return {
      imgSrc: &#39;&#39;,
      imgBase64: &#39;&#39;,
      option: {
        info: true, // 裁剪框的大小信息
        outputSize: 0.8, // 裁剪生成图片的质量
        outputType: &#39;jpeg&#39;, // 裁剪生成图片的格式
        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(&#39;image&#39;, 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 === &#39;&#39;) {
        return
      }
      this.$refs.cropper.startCrop() // 开始裁剪
    },
    leave () {
      this.$refs.cropper.stopCrop()// 停止裁剪
    }
  }

}
</script>
Copier après la connexion

1. Prise en charge de la reconnaissance multilingueUne brève analyse de la façon dont le nœud implémente ocr

tesseract.js L'exemple de code par défaut pour la version hors ligne ne prend en charge que la reconnaissance de l'anglais. le résultat sera un tas de points d’interrogation. Mais heureusement, vous pouvez importer plusieurs modèles linguistiques entraînés pour prendre en charge la reconnaissance de plusieurs langues.
Téléchargez le modèle de langage correspondant dont vous avez besoin depuis https://github.com/naptha/tessdata/tree/gh-pages/4.0.0 , mettez-le dans le répertoire lang-data du répertoire racine

J'ai choisi le chinois (chi_sim.traineddata.gz) le japonais (jpn.traineddata.gz) l'anglais ( eng.traineddata.gz) Modèle linguistique à trois pays.

  • Modifiez la configuration linguistique de chargement et d'initialisation du modèle dans le code pour prendre en charge les langues chinoise, japonaise et anglaise en même temps.

  • rrreeeAfin de faciliter les tests de chacun, j'ai inclus le modèle de formation, l'exemple de code et les images de test dans les trois langues de la Chine, du Japon et de la Corée dans la version hors ligne de l'exemple.

    https://github.com/Selenium39/tesseract.js-offline

    2. Améliorez les performances de reconnaissance

    Si vous exécutez la version hors ligne, vous constaterez que le chargement du modèle et la reconnaissance de l'OCR sont un un peu lent. Il peut être optimisé grâce à ces deux étapes.

    Dans les projets web, vous pouvez charger le modèle dès le démarrage de l'application, afin de ne pas avoir à attendre que le modèle soit chargé lorsque vous recevez une demande OCR plus tard.

  • 🎜Reportez-vous au blog Pourquoi je refactorise tesseract.js v2 ?, vous pouvez ajouter plusieurs threads de travail via la méthode createScheduler pour traiter les requêtes ocr simultanément. 🎜
  • 🎜Exemple de traitement simultané multithread de requêtes OCR🎜rrreee🎜Initiez des requêtes simultanées, vous pouvez voir plusieurs travailleurs exécuter des tâches OCR simultanément🎜🎜ab - n 4 -c 4 localhost:3002/test🎜🎜🎜🎜🎜🎜3. Code frontal 🎜🎜🎜Le code frontal dans l'affichage des effets est principalement implémenté à l'aide du composant elementui et de vue-cropper. composant. 🎜🎜Composant vue-cropper Pour une utilisation spécifique, veuillez vous référer à mon blog vue image recadrage : Utilisation de vue-cropper pour le recadrage d'image🎜🎜🎜ps : 🎜Lors du téléchargement d'images, vous pouvez d'abord charger le base64 de l'image téléchargée sur le front-end , voyez d'abord Télécharger l'image, puis demandez au backend de télécharger l'image, ce qui offre une meilleure expérience utilisateur🎜🎜Le code complet est le suivant🎜rrreee🎜Pour plus de connaissances sur les nœuds, veuillez visiter : 🎜Tutoriel Nodejs🎜 ! 🎜

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Étiquettes associées:
    source:csdn.net
    Déclaration de ce site Web
    Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
    Tutoriels populaires
    Plus>
    Derniers téléchargements
    Plus>
    effets Web
    Code source du site Web
    Matériel du site Web
    Modèle frontal
    À propos de nous Clause de non-responsabilité Sitemap
    Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!