Analisis ringkas tentang cara nod melaksanakan ocr

青灯夜游
Lepaskan: 2022-10-31 19:09:40
ke hadapan
1679 orang telah melayarinya

Bagaimana untuk melaksanakan OCR (pengecaman aksara optik)? Artikel berikut akan memperkenalkan kepada anda cara menggunakan nod untuk melaksanakan OCR. Saya harap ia akan membantu anda!

Analisis ringkas tentang cara nod melaksanakan ocr

ocr ialah pengecaman aksara optik secara ringkas, ia adalah untuk mengecam teks pada gambar.

Malangnya, saya hanyalah seorang pengaturcara web peringkat rendah. Saya tidak tahu banyak tentang AI Jika saya ingin melaksanakan OCR, saya hanya boleh mencari perpustakaan pihak ketiga.

Terdapat banyak perpustakaan pihak ketiga untuk OCR dalam bahasa Python Saya telah lama mencari perpustakaan pihak ketiga untuk OCR dalam nodejs Akhirnya, saya mendapati bahawa perpustakaan tesseract.js boleh masih melaksanakan OCR dengan sangat mudah. [Cadangan tutorial berkaitan: tutorial video nodejs]

Paparan kesan

Contoh dalam talian: http://www.lolmbbs.com/tool/ ocr

Analisis ringkas tentang cara nod melaksanakan ocr

Kod terperinci

tesserract.js Pustaka ini menyediakan berbilang versi yang saya gunakan di sini adalah di luar talian. Versi tesseract.js-luar talian, lagipun, semua orang mengalami keadaan rangkaian yang buruk.
Analisis ringkas tentang cara nod melaksanakan ocr
默认示例代码

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();
})();
Salin selepas log masuk

1. Menyokong pengecaman berbilang bahasa

tesseract.js versi kod sampel lalai hanya menyokong. pengiktirafan Dalam bahasa Inggeris, jika bahasa Cina diiktiraf, hasilnya akan menjadi tanda tanya. Tetapi mujurlah, anda boleh mengimport berbilang model bahasa terlatih untuk menyokong pengiktirafan berbilang bahasa.

  • Muat turun model bahasa yang sepadan yang anda perlukan dari https://github.com/naptha/tessdata/tree/gh-pages/4.0.0 dan letakkan dalam direktori akar
    dalam direktori lang-data Di sini saya memilih tiga model bahasa Cina (chi_sim.traineddata.gz) Jepun (jpn.traineddata.gz) Inggeris (eng.traineddata.gz).

  • Ubah suai konfigurasi item bahasa untuk memuatkan dan memulakan model dalam kod untuk menyokong bahasa Cina, Jepun dan Inggeris pada masa yang sama.

await worker.loadLanguage('chi_sim+jpn+eng');
await worker.initialize('chi_sim+jpn+eng');
Salin selepas log masuk

Untuk memudahkan ujian semua orang, saya telah memasukkan model latihan dan kod contoh dalam bahasa Cina, Jepun dan Korea serta imej ujian dalam versi luar talian contoh.
https://github.com/Selenium39/tesseract.js-offline

2 Tingkatkan prestasi pengecaman

Jika anda menjalankan versi luar talian, anda Anda. akan mendapati bahawa pemuatan model dan pengecaman OCR agak perlahan. Ia boleh dioptimumkan melalui dua langkah ini.

  • Dalam projek web, anda boleh memuatkan model sebaik sahaja aplikasi bermula, supaya anda tidak perlu menunggu model dimuatkan apabila anda menerima permintaan OCR nanti .

  • Merujuk kepada blog Mengapa saya memfaktorkan semula tesseract.js v2?, anda boleh menambah berbilang urutan pekerja melalui kaedah createScheduler untuk memproses permintaan ocr secara serentak.

多线程并发处理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)
Salin selepas log masuk

Mulakan permintaan serentak dan anda boleh melihat berbilang pekerja melaksanakan tugas ocr serentak

ab -n 4 -c 4 localhost:3002/test

Analisis ringkas tentang cara nod melaksanakan ocr

3. Kod bahagian hadapan

Kod bahagian hadapan dalam paparan kesan dilaksanakan terutamanya menggunakan komponen elementui dan vue -komponen pemangkas.

Untuk kegunaan khusus komponen vue-cropper, sila rujuk pemangkasan imej vue blog saya: Menggunakan vue-cropper untuk pemangkasan imej

ps: Anda boleh lakukan ini apabila memuat naik imej Mula-mula muatkan base64 imej yang dimuat naik pada bahagian hadapan, lihat imej yang dimuat naik dahulu, dan kemudian minta bahagian belakang untuk memuat naik imej, yang lebih baik untuk pengalaman pengguna

Kod lengkap ialah seperti berikut

<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>
Salin selepas log masuk

Lebih banyak nod Untuk pengetahuan berkaitan, sila lawati: tutorial nodejs!

Atas ialah kandungan terperinci Analisis ringkas tentang cara nod melaksanakan ocr. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:csdn.net
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan