0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Vue.jsで画像、PDFから文字の抽出

Posted at

使用したインストールコマンド

npm install tesseract.js

npm install pdfjs-dist

npm install pdfjs-dist@2.15.349

App.vue

<template>
  <div id="app" class="container">
    <h1>OCR Web App with Tesseract.js</h1>
    <!-- PDF/画像ファイルのアップロード -->
    <input type="file" @change="onFileChange" accept="image/*,.pdf" />
    
    <!-- ページ番号入力(PDFのみ表示) -->
    <input
      v-if="file"
      type="number"
      v-model="pagenum"
      name="tentacles"
      min="1"
      max="100"
      class="input-large border border-blue-400 bg-emerald-200"
      @change="onInputPage"
      :disabled="!isPdf"
    />

    <!-- OCR実行ボタン -->
    <button 
      class="bg-emerald-200 border border-blue-400 rounded-full"
      @click="processOCR" 
      :disabled="!file"
    >
      Process OCR
    </button>
    
    <!-- 処理中メッセージ -->
    <p v-if="isProcessing">Processing...</p>
    
    <!-- 抽出されたテキスト -->
    <div v-if="ocrText" class="ocr-result">
      <h3>Extracted Text:</h3>
      <pre>{{ ocrText }}</pre>
    </div>
    
    <!-- 画像プレビュー -->
    <img v-if="imageSrc" :src="imageSrc" alt="Uploaded Image" class="image-preview" />
  </div>
</template>

<script>
import Tesseract from "tesseract.js";
import { getDocument, GlobalWorkerOptions } from "pdfjs-dist";

// PDF.jsのワーカーパスを設定
GlobalWorkerOptions.workerSrc = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.15.349/pdf.worker.min.js`;

export default {
  data() {
    return {
      file: null, // アップロードされたファイル (画像またはPDF)
      imageSrc: null, // プレビュー用の画像URL
      ocrText: "", // OCR結果
      isProcessing: false, // 処理中フラグ
      pagenum: 1, // 現在のページ番号
      isPdf: false, // ファイルがPDFかどうかを管理
    };
  },
  methods: {
    // ファイルを取得または特定ページを表示
    async onFileChange(event = null) {
      const file = event ? event.target.files[0] : this.file;
      if (!file) {
        this.file = null;
        this.imageSrc = null;
        this.isPdf = false;
        return;
      }

      this.file = file;
      this.isPdf = file.type === "application/pdf"; // PDFファイルかどうかを判定

      if (this.isPdf) {
        // PDF の指定ページを画像に変換
        const pdf = await getDocument(URL.createObjectURL(file)).promise;
        const page = await pdf.getPage(this.pagenum);
        const viewport = page.getViewport({ scale: 2 });
        const canvas = document.createElement("canvas");
        const context = canvas.getContext("2d");

        canvas.width = viewport.width;
        canvas.height = viewport.height;

        await page.render({ canvasContext: context, viewport }).promise;

        this.imageSrc = canvas.toDataURL("image/png"); // プレビュー用
      } else {
        // 画像ファイルの場合
        this.imageSrc = URL.createObjectURL(file);
      }
    },

    // ページ番号変更時に特定ページを表示
    async onInputPage() {
      if (this.file) {
        await this.onFileChange();
      } else {
        console.warn("No file selected.");
      }
    },

    // OCRを実行
    async processOCR() {
      if (!this.file) return;

      this.isProcessing = true;
      this.ocrText = "";

      let input;
      if (this.isPdf) {
        // PDFの場合、現在のプレビュー画像をOCRに渡す
        const response = await fetch(this.imageSrc);
        input = await response.blob();
      } else {
        // 画像ファイルの場合
        input = this.file;
      }

      Tesseract.recognize(input, "jpn", {
        logger: (info) => console.log(info), // ログ情報を表示
      })
        .then(({ data: { text } }) => {
          this.ocrText = text;
        })
        .catch((error) => {
          console.error("OCR Error:", error);
          this.ocrText = "An error occurred during OCR processing.";
        })
        .finally(() => {
          this.isProcessing = false;
        });
    },
  },
};
</script>

<style>
.input-large {
  font-size: 1.5rem; /* フォントサイズを大きくする */
  padding: 10px; /* 内側の余白を広げる */
  width: 150px; /* 幅を調整 */
  height: 50px; /* 高さを調整 */
  border-radius: 10px; /* 角を丸くする */
  text-align: center; /* テキストを中央揃え */
  margin: 10px 0; /* 上下の余白を調整 */
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); /* 影をつけて目立たせる */
  cursor: pointer; /* カーソルをポインタに変更 */
}

.input-large:focus {
  outline: none; /* フォーカス時のデフォルトのアウトラインを削除 */
  border-color: #4caf50; /* フォーカス時の枠の色を変更 */
  box-shadow: 0 0 10px rgba(76, 175, 80, 0.5); /* フォーカス時に目立つ影を追加 */
}
.container {
  text-align: center;
  margin: 20px auto;
  max-width: 600px;
}

button {
  margin-top: 10px;
  padding: 10px 20px;
  font-size: 16px;
  cursor: pointer;
}

pre {
  text-align: left;
  white-space: pre-wrap;
  word-wrap: break-word;
  background: #f4f4f4;
  padding: 10px;
  border-radius: 5px;
  color: #333;
}

.image-preview {
  max-width: 100%;
  margin-top: 20px;
  border: 1px solid #ddd;
  border-radius: 5px;
}

.ocr-result {
  margin-top: 20px;
  text-align: left;
  background: #e9f7ef;
  border: 1px solid #c3e6cb;
  padding: 15px;
  border-radius: 5px;
}
</style>

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?