Jupyter上でPyOCRを使える環境を整えて、実際にOCRしてみた
どうも。
最近画像関連でOCRに手を出したので年末年始のこのタイミングでまとめようかなと。(もう成人式も終わってるけど)
まあ、目的は「アプリのプロ野球速報をOCRしたら面白そう」って思いつきで始めたのですが…*1
もともと大学時代に画像処理は少し齧っていたので、改めて触れたいなという気持ちもあったり。
基本的なことについて
OCRとは
OCRとは、「光学文字認識」の英語の頭文字をとったもので、画像の中の文字を文字コードの列(機械が認識できる文字)に変換するソフトウェアのことを指す。(Wikipediaより)
要するに、画像の中から文字列を抽出するソフトってことです。
JupyterでPyOCR
Jupyter NotebookであればPyOCRも同様にわかりやすい形で出力してくれます。
下記画像みたいな感じで(結果はさておき)
ちなみに元画像はこちら。野球好きならよく見たことある画像ですね。
リポジトリ情報
ここにプッシュしております。
github.com
作成したDockerfile
作成したDockerfileは下記です。今回はJupyter用イメージを引っ張ってきて、そこにtesseract-OCRを追加するような感じ。
FROM jupyter/datascience-notebook USER root RUN sudo apt update && sudo apt -y install tesseract-ocr && \ apt install tesseract-ocr-jpn && \ apt install tesseract-ocr-script-jpan WORKDIR /home/jovyan/work COPY requirements.txt ./ RUN pip install -r requirements.txt
今回は日本語を抽出したいので、日本語エンジンも併せてインストールします。(tesseract-ocr-jpn
とtesseract-ocr-script-jpan
)
Jupyterの起動
コンテナを起動すればJupyterも同時に起動するので、下記コマンドでビルドや起動を行えばOK。
ビルド
$ docker build -t sokuho/jupyter .
サーバ起動
$ docker run -v <current_directory>:/home/jovyan/work --name sokuho -p 8888:8888 sokuho/jupyter
コンテナ起動
$ docker start -a sokuho
簡単なPyOCRの実践
とりあえず簡単に作ったコードがこちら
from PIL import Image import sys sys.path.append('/path/to/dir') import pyocr import pyocr.builders def print_ocr(img_path,tesseract_layout=3): tools = pyocr.get_available_tools() if len(tools) == 0: print("No OCR tool found") sys.exit(1) tool = tools[0] txt = tool.image_to_string( Image.open(img_path), lang='jpn', builder=pyocr.builders.TextBuilder(tesseract_layout=tesseract_layout) ) print(txt)
PILは、画像の読み込みに必要です。
OCRツールの取得
9~13行目でOCRの実行に必要なツールを取得します。
このツールの中で、下記メソッドを使うことで、利用可能言語データも確認できます。
import pyocr tools = pyocr.get_available_tools() tool = tools[0] langs = tool.get_available_languages() print(langs)
実行例
['Japanese', 'osd', 'eng', 'jpn']
OCRの実行
ツールのimage_to_string()
を利用して、OCRを実行します。
引数については下記。
- 画像データ(サンプルだとファイル取得までやってる)
- 利用言語(上記利用可能言語参照)
- レイアウト解析のオプション(詳細は下記、デフォルトは3)
ちなみに実行結果のサンプルは上の方にある、Jupyterによる出力がそれです。
レイアウト解析のオプション
エンジン内で画像をレイアウト解析する際の挙動をオプションを指定することによってコントロール出来ます。
各オプションの挙動は下記。
- 0: 方向とスクリプト検出(OSD)のみ。
- 1: OSDによる自動ページセグメンテーション。
- 2: 自動ページセグメンテーション(OSDなし)。
- 3: 完全自動ページセグメンテーション(OSDなし)。(デフォルト)
- 4: 様々なサイズのテキストの単一列を想定。
- 5: 垂直に配置されたテキストの単一の均一なブロックを想定。
- 6: 単一の均一なテキストブロックを想定。
- 7: 画像を単一のテキスト行として扱う。
- 8: 画像を単一の単語として扱う。
- 9: 画像を円の中の1つの単語として扱う。
- 10: 画像を単一の文字として扱う。
- 11: スパーステキスト。順不同でできるだけ多くのテキストを検索する。
- 12: OSDによるスパーステキスト。
- 13: 生のライン。内部の処理をバイパスしつつ画像内にテキストが1行だけあるものとして扱う。
所感
なんとなく始めたOCRですが、思った以上に壁はでかかったようです。
上の実行例の通り、デフォルトの使用だけだと目的の実現は難しそうですが…
調べたところ、訓練データの精度をあげるツールがあるそうなので、(jTessBoxEditorというらしい)
sourceforge.net
こういうのを触ってみるのもありかもです。*2
あと訓練データ自体も日本語の各フォントに対応したものがあるみたいなので、
その点で調査してみてもいいかもです。
qiita.com
今回は勉強がてらOCRを使ってみたかったのでPyOCRを使いましたが、
単純にOCRを利用したいだけなら各企業が提供しているサービスを利用するのが現実的かな、と。
有名なのはGoogleの「Vision API」
cloud.google.com
LINEの「LINE BRAIN OCR」(API公開はまだだそう)
www.linebrain.ai
Amazon(AWSサービスの一つ)の「Amazon Textract」(日本語未対応)
aws.amazon.com
速報のスクショをとってOCRエンジンに投げてデータ連携を行う、みたいなことをしたければ
上記APIを使うことになるのかな〜と思います。*3
速報以外にもスクショして画像投げて〜って流れを作れば色々なことが出来そうですね。
以上、お読み頂きありがとうございました〜