PyOCRでTesseractを使う

Tesseract OCRのPythonバインディング、pyocrのセットアップと使い方を紹介します。

pyocrは現在もメンテナンスされているTesseractのPython用ライブラリ(バインディング)としては最古参です(2012年リリース)。

目次#

PyOCRについて#

pyocrはTesseractとCuneiform(ロシア製のOCRエンジンでヨーロッパ系の言語をサポート)の2つに対応しています。

OpenPaper.workというプロジェクトの一部でライセンスはGPL v3。

プロジェクトのページ:OpenPaper.work - Open-source

公式リポジトリ:World / OpenPaperwork / pyocr · GitLab

Tesseractに関してはC言語用のAPIを使う方式とtesseractコマンドを呼び出す方式の2つの方式に対応している点が特徴です。

なお、この記事ではCuneiformについては日本語に対応していない関係で対象外とします。

tesseractコマンドの呼び出しにはPythonのsubprocessモジュールが使用されます。

コマンド呼び出し(tesseract)とC言語用API(libtesseract)機能の比較は以下のようになります。

実行方式 文字の認識 数字限定 文字方向検出 PDF出力
コマンド呼び出し(tesseract Yes Yes (ver. 3.0x) Yes (only ver. 3.0x) No
C言語用API(libtesseract Yes Yes (ver. 3.0x) Yes Yes

認識対象を数字に限定するオプションが用意されていますがTesseract 4.0系では通常の認識モードと同じ結果になります(理由は後述)。

pyocrの欠点としてはTesseract 4.0系と組み合わせる際に、OCRエンジンのモードを切り替えることができません(--oemオプションに対応していない)。

またコマンド呼び出し方式で使用する場合は画像データの一時ファイルへの書き出しと、結果をテキストファイルから読み込む処理が入る分、処理に余分に時間がかかります。

コマンド呼び出し方式での実行時は、tesseractコマンドをpsmオプションとconfigファイルとしてmakeboxを指定して実行する形式になります。

環境とインストール#

この記事ではUbuntu 18.04LTSおよび標準パッケージのTesseract OCR 4.00beta.1を対象としています。

  • Ubuntu 18.04 LTS
  • Tesseract OCR 4.00beta.1
  • Python 3.6.5
  • pyocr 0.5.2
  • Pillow 5.2.0

Tesseract本体はaptコマンドでインストールしてあるものとします。

$ pip3 install pyocr

依存ライブラリとして画像処理ライブラリのPillowが必要です。下記のコマンドでインストールします。

$ pip3 install Pillow

使い方#

テスト画像は以下を使用します。

テスト用の画像ファイル(英文)

なお、tesseractコマンドの詳細はで解説しているのでそちらも参照して下さい。

利用可能なOCR tool の確認#

pyocrでは利用可能なOCRエンジンをtoolという名前で抽象化しています。
利用可能なツールのリストをget_available_tools()で取得できます。

import pyocr

tools = pyocr.get_available_tools()
for tool in tools :
print(tool.get_name())

出力は以下のようになります。

Tesseract (sh)
Tesseract (C-API)

利用可能な言語の確認#

import pyocr

tools = pyocr.get_available_tools()

tool = tools[0]
langs = tool.get_available_languages()

print(langs)

出力結果の例を示します。

['Japanese', 'eng', 'Japanese_vert', 'Latin', 'jpn_vert', 'osd', 'jpn']

OCR処理の実行#

文字認識処理の実行にはimage_to_string()メソッドを使用します。

引数の入力画像はPILのImage、langに言語を指定します。出力形式の制御はbuilderオプションで制御できます。

langを省略した場合のデフォルトはtool依存(ほとんどのケースでeng)。

また、builderに指定可能なオプションは以下のとおり(省略した場合はTextBuilder

  • TextBuilder : テキスト全体
  • WordBoxBuilder : 単語単位(画像内の位置座標付き)
  • LineBoxBuilder : 行単位(画像内の位置座標付き)
  • DigitBuilder : 数字のみ
  • DigitLineBoxBuilder :

DigitBuilderおよびDigitLineBoxBuilderは認識対象の文字の種類を数字に限定してTesseractを動作させるオプション。ただし、Tesseract 4.0系の新しい認識エンジンでは機能しない。

from PIL import Image
import sys

import pyocr
import pyocr.builders

tools = pyocr.get_available_tools()
if len(tools) == 0:
print("No OCR tool found")
sys.exit(1)
# The tools are returned in the recommended order of usage
tool = tools[0]

lang = 'eng'
txt = tool.image_to_string(
Image.open('images/sample.jpg'),
lang=lang,
builder=pyocr.builders.TextBuilder()
)

print(txt)

認識結果は以下のようになります。

出力
The quick brown fox jumped over the lazy dogs.

詳細#

Builderのオプション#

pyocrではTesseractのオプションはbuilderオブジェクトでコントロールするようです。

例えば、ページセグメンテーションモードはbuilderオブジェクトのtesseract_layoutオプションで設定します。

txt = tool.image_to_string(
Image.open('images/sample.jpg'),
lang=lang,
builder=pyocr.builders.TextBuilder(tesseract_layout=6))
)

tesseract_layoutのデフォルト値は3です。

BoxBuilder#

BoxBuilderという名前のついたbuilderimage_to_string()メソッドのオプションに指定すると、LineBoxオブジェクトのリストを返します。このオブジェクトはcontentspostionというattributeを持ちます。

ループ処理することで認識結果と座標(左下原点系)を得ることができます。


word_box = tool.image_to_string( Image.open('images/sample.jpg'),
builder=pyocr.builders.WordBoxBuilder())

for box in word_box:
print("word: {}, pos: {}".format(box.content, box.position))

出力例を以下にに示します。

word: The, pos: ((41, 50), (66, 63))
word: quick, pos: ((71, 50), (108, 66))
word: brown, pos: ((113, 50), (155, 63))
word: fox, pos: ((161, 50), (183, 63))
word: jumped, pos: ((186, 50), (237, 66))
word: over, pos: ((242, 54), (273, 63))
word: the, pos: ((277, 50), (297, 63))
word: lazy, pos: ((302, 50), (330, 66))
word: dogs., pos: ((334, 50), (369, 66))

方向検出#

Tesseract 4.0系で方向検出機能を使用する場合、tesseractコマンドの出力が変化している。そのため、pyocrとの組み合わせではlibtesseractを使う必要がある。

from PIL import Image
import sys

import pyocr
import pyocr.builders

tools = pyocr.get_available_tools()

tool = tools[1] # libtesseractを使う

if tool.can_detect_orientation() :
try:
orientation = tool.detect_orientation(Image.open('test.png'), lang='osd')

print(orientation)
except pyocr.PyocrException as exc:
print("Orientation detection failed: {}".format(exc))

出力例は以下のように、角度と確からしさが出力されます。

{'angle': 0, 'confidence': 2.7592315673828125}

PDF生成#

libtesseractを使用する場合、TesseractのPDF生成機能を利用できます。

from PIL import Image
import sys

import pyocr
import pyocr.builders

tools = pyocr.get_available_tools()

tool = tools[1] # libtesseractを使う

tool.image_to_pdf(Image.open('test.png'), lang='jpn' , output_file='pdf_test')

エラーメッセージが表示されますが、PDFの生成は成功します。

Error in fopenReadStream: file not found
Error in findFileFormat: image file not found

上記の例の場合、pdf_test.pdfという名前でPDFファイルが作成されます。

その他#

hOCR出力#

BoxBuilder系の出力オプションを指定した場合、builder.write_file()メソッドを使うことによりxml(hOCR)形式でファイルに書き出すことができます。

詳細は公式ドキュメントを参照。

World / OpenPaperwork / pyocr · GitLab

macOS環境での注意#

pyocrは*nix環境ではlibtesseractの共有ライブラリの拡張子が.soであることを期待しています。macOS環境では拡張子が違うのでlibtesseractを検出しません。
対処方法としてはソースをいじるか、libtesseract.dylibに対してlibtesseract.so.3またはlibtesseract.so.4というシンボリックリンクを作成する必要があります。
サーバーサイドで使うケースがほとんどだろうと思いますが念の為。