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?

Tesseract.jsで画像の一部だけOCRする範囲指定ツールをCodePenで試作した

0
Last updated at Posted at 2026-07-02

はじめに

OCRという技術自体は、今では珍しいものではない。

AIサービスやCopilotのような仕組みを使えば、画像やPDFから文字を読み取ることはできる。

ただ、実際に現場で使うことを考えると、費用やライセンス、社内環境の制約が壁になることがある。

「少しだけ試したい」「小さな業務で使いたい」という段階でも、有償サービスや大きな仕組みが前提になると、導入のハードルが高くなってしまう。

そこで今回は、無料で使えるOSSのTesseract OCRを使い、現場でも配布しやすい形でOCRツールを作れないかを試した。

最終的には、画像やPDF上でユーザーが読み取りたい範囲を指定し、その範囲だけをOCRできるような仕組みを作りたい。

今回はそのプロトタイプとして、CodePen上で画像の範囲指定OCRと、読み取り範囲のテンプレート保存を試した。

画像を表示する
↓
読み取りたい範囲をドラッグで指定する
↓
指定した範囲だけOCRする
↓
選択範囲に項目名をつけて保存する
↓
保存した範囲をテンプレートとして呼び出す

この記事でわかること

この記事では、以下の内容を扱う。

  • Tesseract.jsをCodePenで読み込む方法
  • 画像をcanvasに表示する方法
  • ドラッグで読み取り範囲を指定する方法
  • canvas上の選択範囲だけを切り抜く方法
  • 切り抜いた画像をTesseract.jsでOCRする方法
  • 選択範囲を比率で保存し、再利用する考え方

一方で、OCR精度を大きく改善する方法や、PDF対応、複数帳票の本格運用までは扱わない。

作りたいもの

今回作りたいのは、画像全体をOCRするツールではない。

帳票画像の中から、ユーザーが読み取りたい範囲だけを指定し、その範囲だけをOCRするツールである。

想定している使い方は以下の通り。

帳票画像を読み込む

見積番号や金額など、読み取りたい範囲をドラッグで指定する

指定した範囲だけをOCRする

範囲に項目名をつけて保存する

同じレイアウトの帳票で、保存した範囲を再利用する

同じ帳票レイアウトであれば、毎回同じ場所を指定しなくても済むようにしたい。

結論

Tesseract.jsを使って、画像の一部だけを範囲指定してOCRするプロトタイプを作ることができた。

また、選択した範囲に項目名をつけて保存し、同じ帳票レイアウトで再利用するためのテンプレート保存も実装できた。

一方で、手書き文字の認識精度は低く、Tesseract.jsだけで手書きひらがなを安定して読み取るのは難しいと感じた。

今回の検証では、手書き文字を正確に読むことよりも、帳票の決まった位置から必要項目だけを読み取る仕組みを作れる可能性が見えた。

以下Code Penリンク
https://codepen.io/editor/bolrzpnh-the-vuer/pen/019f0dc7-1009-7a96-8ca2-bc44adaaa5e1

サンプル画像
OCRテスト2.png
OCRテスト3.png

今回やったこと

今回は以下を試した。

  • CodePenでTesseract.jsを読み込む
  • 画像ファイルをアップロードする
  • 画像全体をOCRする
  • 読み取り範囲をドラッグで指定する
  • 指定した範囲だけを切り抜いてOCRする
  • 選択範囲に項目名をつけて保存する
  • 保存した範囲を呼び出して再利用する

使うもの

  • CodePen
  • Tesseract.js
  • HTML
  • CSS
  • JavaScript

Tesseract.jsとは

Tesseract.jsは、ブラウザ上でOCRを実行できるJavaScriptライブラリである。

Python版のTesseract OCRとは違い、CodePenのようなブラウザ環境ではTesseract.jsを使う。

今回は、HTML側で以下のようにTesseract.jsを読み込んだ。

<script src="https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js"></script>

生成AIを使ったところ

今回の制作では、生成AIをふんだんに使用した。

主に使った場面は以下である。

  • Tesseract OCR、CodePenの役割整理
  • CodePenで動かすHTML / CSS / JavaScriptの確認
  • エラーが出たときの原因確認
  • OCR結果がうまくいかなかった理由の整理
  • 次に作るべき機能の検討
  • テンプレートとして保存するデータ形式の整理

今回はまずCodePenとTesseract.jsを使い、ブラウザ上でOCRの動きを確認するところから始めた。

まず画像全体をOCRしてみる

最初に、画像全体をそのままOCRしてみた。

今回は、動作確認用に自分で作成した日本語の画像を読み込ませた。

画像には「きゅうり」と手書きで書いている。

OCRテスト.png

人間には読めるが、Tesseract.jsで正しく読み取れるかを確認した。

画像全体OCRの結果

実際にOCRを実行してみた結果、期待した「きゅうり」とは読み取れなかった。

image.png

今回の画像でOCRがうまくいかなかった理由について、生成AIに画像の特徴をもとに整理してもらった。

認識を難しくしている可能性として、以下の点が挙げられた。

  • 手書き文字である
  • 文字の線が細い
  • 文字同士の間隔が広い
  • 画像全体に対して余白が大きい
  • 印刷された文字ではない

実際に画像を見ても、文字は人間には読めるものの、OCRにとっては難しい条件だと感じた。

特に、画像全体に対して余白が大きい場合、OCR側が「どこに文字があるのか」から判断する必要がある。

そのため、読み取りたい文字の場所が分かっている場合は、画像全体ではなく、必要な範囲だけを切り抜いてOCRした方がよさそうだと感じた。

範囲指定OCRを試す

次に、画像全体ではなく、ユーザーが読み取りたい範囲をドラッグで指定し、その範囲だけを切り抜いてOCRする処理を試した。

流れは以下の通りである。

画像をcanvasに表示する
↓
ユーザーが読み取りたい範囲をドラッグで囲む
↓
囲んだ範囲だけを切り抜く
↓
切り抜いた画像をTesseract.jsでOCRする

今回作りたい最終形は、画像やPDFの中から必要な場所だけをユーザーが指定できるOCRアプリなので、この範囲指定処理は重要だと考えた。

CodePen Projectsで詰まったこと

途中で、script.js にJavaScriptを書いているのに処理が動かない問題があった。

原因は、CodePen Projects形式では、script.js が自動では読み込まれないことだった。

index.html 側で、style.cssscript.js を明示的に読み込む必要があった。

<link rel="stylesheet" href="./style.css">
<script src="./script.js"></script>

また、Tesseract.jsもHTML側で読み込んだ。

<script src="https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js"></script>

最終的には、HTMLの末尾を以下のようにした。

<script src="https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js"></script>
<script src="./script.js"></script>

この修正により、script.js 側の処理が動くようになった。

範囲指定OCRの実装概要

範囲指定OCRでは、画像を <img> ではなく <canvas> に表示した。

canvasを使うことで、マウスの座標を取得したり、選択範囲を赤枠で描画したりできる。

実装した処理は以下の通りである。

1. 画像をcanvasに表示する
2. mousedownでドラッグ開始位置を取得する
3. mousemoveで赤枠を描画する
4. mouseupで選択範囲を確定する
5. 選択範囲だけを別canvasに切り抜く
6. 切り抜いたcanvasをTesseract.jsに渡す

実装中に、マウスカーソルと赤枠の位置がずれる問題があった。

原因は、canvasの内部サイズと、画面上に表示されているサイズが異なっていたことだった。

そのため、マウス座標をcanvas内部の座標に変換する処理を追加した。

function getMousePosition(event) {
  const rect = canvas.getBoundingClientRect();

  const scaleX = canvas.width / rect.width;
  const scaleY = canvas.height / rect.height;

  return {
    x: (event.clientX - rect.left) * scaleX,
    y: (event.clientY - rect.top) * scaleY,
  };
}

この修正により、ドラッグした位置と赤枠の位置が合うようになった。

範囲指定OCRの結果

範囲指定、切り抜き、OCRまでの流れはCodePen上で動作した。

つまり、以下の処理は確認できた。

画像を表示する
↓
ドラッグで範囲を指定する
↓
指定範囲だけ切り抜く
↓
切り抜いた範囲だけOCRする

一方で、今回の手書きひらがな画像では、範囲指定しても期待した「きゅうり」にはならなかった。

OCR結果は、以下のように誤認識された。

7。つ

範囲を指定したことで余白の問題はある程度減らせたが、手書きひらがなそのものの認識はTesseract.jsではかなり難しいと感じた。

ここで、今回の目的は「手書き文字を高精度に読むこと」ではなく、「読み取りたい範囲を指定してOCRする仕組みを作ること」だと整理した。

そのため、次は範囲指定した場所を保存し、同じ帳票で再利用できるようにすることにした。

選択範囲をテンプレートとして保存する

範囲指定OCRができたので、次に「選択した範囲をテンプレートとして保存する」処理を追加した。

最終的には、同じ帳票レイアウトであれば、毎回ユーザーが範囲を指定しなくても、前回登録した範囲を使ってOCRできるようにしたい。

今回はその第一段階として、ドラッグで選択した範囲に項目名をつけて保存するところまで実装した。

例えば、帳票上の金額欄を囲んで、項目名に「金額」と入力して保存する。

保存するデータは、canvas上のピクセル座標ではなく、画像全体に対する比率にした。

{
  "key": "金額",
  "xRatio": 0.31,
  "yRatio": 0.42,
  "wRatio": 0.28,
  "hRatio": 0.08
}

比率で保存することで、画像の表示サイズが変わっても、同じような場所を指定しやすくなる。

今回のステップでは、以下の流れを確認した。

読み取りたい範囲をドラッグで囲む
↓
項目名を入力する
↓
選択範囲を比率で保存する
↓
テンプレートJSONとして表示する

保存先は、まずは簡単に試すために localStorage を使った。

そのため、ページを再読み込みしても、同じブラウザ上であれば登録したテンプレートを保持できる。

保存したテンプレートを呼び出す

最初はテンプレートJSONを表示するだけだったが、それだけでは再利用しにくい。

そこで、登録した項目ごとに「適用」ボタンを追加した。

「適用」ボタンを押すと、保存していた比率情報をもとに、canvas上の座標へ戻して赤枠を表示する。

保存した比率情報
↓
現在のcanvasサイズに合わせて座標へ変換
↓
赤枠として表示
↓
選択範囲として再利用

これにより、一度登録した「金額」「見積番号」などの範囲を、再度ドラッグしなくても呼び出せるようになった。

今回のプロトタイプでは、以下の流れまで確認できた。

初回
帳票画像を読み込む
↓
金額欄をドラッグで囲む
↓
項目名「金額」として保存する

次回
同じ帳票画像を読み込む
↓
登録済み項目の「適用」を押す
↓
保存した範囲が赤枠で復元される
↓
その範囲だけ切り抜いてOCRする

これで、単なる範囲指定OCRではなく、同じ帳票レイアウトに再利用するための土台ができた。

切り抜き範囲の調整

途中で、赤枠で囲んだ範囲よりも少し広く切り抜かれてしまい、意図していない文字までOCRに入る問題があった。

原因は、文字の端が欠けないように、切り抜き時に余白を追加していたことだった。

しかし、テンプレートとして同じ場所を再利用する場合、赤枠と切り抜き範囲がずれていると意図しない文字が入りやすい。

そのため、今回は余白を追加せず、赤枠で指定した範囲だけを切り抜くように修正した。

これにより、ユーザーが指定した範囲と、実際にOCRに渡す範囲が一致するようになった。

試してわかったこと

今回の検証で、Tesseract.jsを使ってブラウザ上でOCRを動かすことはできた。

また、画像全体をOCRするだけではなく、ユーザーがドラッグで読み取り範囲を指定し、その範囲だけを切り抜いてOCRするプロトタイプも作成できた。

さらに、選択した範囲に項目名をつけて保存し、保存した範囲を「適用」ボタンで呼び出せるようにした。

今回できたことをまとめると、以下の通りである。

画像を表示する
↓
ユーザーが読み取りたい場所を指定する
↓
その範囲だけを切り抜く
↓
OCRに渡す
↓
選択範囲を項目名つきで保存する
↓
保存した範囲を呼び出して再利用する

一方で、Tesseract.jsだけで手書きひらがなを正確に読むのは難しかった。

この結果から、Tesseract.jsは手書き文字よりも、印刷文字や帳票のように文字の形が安定している画像の方が向いていそうだと感じた。

今回のプロトタイプは、手書き文字を正確に読むことよりも、同じ帳票レイアウトに対して読み取り範囲を再利用する仕組みを試すことに価値があると感じた。

今後の改善案

次は、手書き文字ではなく、業務帳票に近い印刷文字の画像で試したい。

例えば、以下のような見積書や報告書を想定する。

見積番号:EST-2026-001
会社名:株式会社サンプル設備
金額:120,000円
納期:2026年7月10日

このような帳票風の画像で、見積番号、会社名、金額などの範囲をテンプレートとして登録し、同じレイアウトの帳票に再利用する。

また、将来的には以下のような改善も考えられる。

  • 登録した複数項目を一括OCRする
  • テンプレート名をつけて保存する
  • 帳票ごとにテンプレートを切り替える
  • PDFのページ表示に対応する
  • OCR結果を一覧表として表示する
  • OCR結果を手修正できるようにする
  • 生成AIによるOCR結果の補正やJSON整形を行う

今回の検証では、Tesseract.jsだけで手書きひらがなを正確に読むのは難しかった。

しかし、範囲指定OCRとテンプレート保存の仕組みは作れた。

そのため、次は業務帳票を想定した印刷文字で、保存済みテンプレートを使って複数項目を自動OCRする処理を試していきたい。

今回の限界

今回のプロトタイプには、いくつか限界もある。

  • 手書き文字の認識精度は低い
  • OCR対象は画像のみで、PDFにはまだ対応していない
  • テンプレート保存はlocalStorageのため、端末やブラウザをまたいだ共有はできない
  • 帳票の傾きや撮影条件の違いには対応していない
  • 複数項目を一括でOCRする処理は未実装

そのため、すぐに業務で使える完成版ではなく、範囲指定OCRとテンプレート保存の動きを確認するためのプロトタイプとして位置づけている。

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?