【Python】OCRライブラリTesseractで画像から文字認識

OCRってどうやっているんだろう?でも敷居が高そうと思っていませんか?
Googleが開発したオープンソースのOCRエンジン「Tesseract」を使うと、簡単に文字認識することができます。

やること
・Tesseractのインストール
・pytesseractモジュールのインストール
・画像を読み込む
・画像を加工(拡大, 二値化)
・文字認識

今回は事前準備がありますが、手順がはっきりしていれば何てことはありません。
それでは順番に見ていきましょう!

目次

順番にみていく

Tesseractのインストール

まずOCRエンジンとライブラリのインストールが必要です。
Tesseractをインストールしましょう。
Windows環境の場合と、ラズパイ環境の場合の2パターンをご紹介します。

Windows環境の場合

Github内のTesseractのページからインストーラと言語データをダウンロードします。
最後に環境パスを設定します。
順に説明していきます。


インストーラはこちらに格納されています。
次の形式でネーミングされたファイルです。(XXXはバージョン)
tesseract-ocr-w64-setup-XXX.exe (64 bit)

次に言語データを入手します。
こちらのページから該当の言語データを探してダウンロードします。
今回は日本語の言語データ「jpn.traineddata」を選びました。

ダウンロードした言語データはTesseract-OCRのインストールフォルダ内にある「tessdata」フォルダに置きます。

最後に環境変数を設定します。
Windowsロゴ横の検索ウィンドウから「環境変数」で検索します。
システムのプロパティ画面から環境変数を選択します。
環境変数のプロパティ画面からシステム環境変数のPathを編集し、Tesseractのインストールパスを追加します。
Tesseractのインストールパスのデフォルトは「C:\Program Files\Tesseract-OCR」です。

これでWindows環境の場合の準備は完了です。

Linux(ラズパイdebian, ubuntu 22.04 LTS環境などの場合)

Linuxの場合はもう少し簡単です。
少なくともラズパイdebian、ubuntu 22.04LTS環境で動作確認できています。
ターミナルを開き、次を順番に実行します。

sudo apt-get update
sudo apt-get install tesseract-ocr
sudo apt-get install libtesseract-dev
sudo apt-get install tesseract-ocr-jpn

他の言語データをインストールしたい場合はtesseract-ocr-(language_code)を使用します。
たとえば、英語の場合はsudo apt-get install tesseract-ocr-engとなります。

次に、TesseractをPythonから呼び出すために、環境変数TESSDATA_PREFIXを設定する必要があります。
以下の手順で設定します。
ユーザのホームディレクトリにある.bashrcファイルを開きます。

nano ~/.bashrc

ファイルの最後に、次の行を追加します。

export TESSDATA_PREFIX=/usr/share/tesseract-ocr/4.00/tessdata/

ターミナルで以下のコマンドを実行し、環境変数を有効にします。

source ~/.bashrc

これでラズパイ環境の場合の準備は完了です

pytesseractモジュールのインストール

ここからは共通の手順です。
TesseractをPythonで実行するためのモジュールとして、pytesseractをインストールします。

pip install pytesseract

画像を読み込む

ここからはpythonプログラムで順に解説していきます。

今回の動作環境の想定は次です。
実行ファイルと同じ階層に「target.png」ファイルがあります。
この画像をOCRするとします。

テスト環境はWindowsです。

「target.png」は次の画像です。OCRの検索ボリューム数です。
この中から数値を抜き出してOCRしたいと思います。

まずは画像の読み込みです。
今回はPILを使いました。

from PIL import Image

image_path = "target.png"
path_image = (image_path)
image = Image.open(path_image)

画像を加工(拡大, 二値化)

OCRしやすくするため、画像を拡大して二値化します。
後で利用しやすいように関数化しておきます。

from PIL import Image

def image_processing(image_path, mag):
    # 拡大処理
    path_image = (image_path)
    image = Image.open(path_image)
    resized_image = image.resize((image.width * mag, image.height * mag), resample=Image.BICUBIC)

    # # 二値化処理
    thresh = 180
    max = 255
    binary_image = resized_image.convert('L')#グレースケール変換
    binary_image = binary_image.point(lambda x: 0 if x < thresh else max, '1')
    # binary_image.save('img/target_after.png')
    binary_image.save('target_after.png')
    return binary_image

# 画像を読み込む
image_path = "target.png"
image = Image.open(image_path)

# 画像を加工する
image = image_processing(image_path, 2)

文字認識

いよいよ文字認識させてみます。
画像の読み込み部分は省略しています。

まずはOCR部分だけ切り取って見てみましょう。

import pytesseract
from PIL import Image

command = '-l jpn --psm 7 -c tessedit_char_whitelist="0123456789"'
image = image_processing(image_path, 2)
text = pytesseract.image_to_string(image, config=command)

こんな感じになります。
commandで指定しているのは認識オプションです。
この例では、日本語、1列の文字数字として扱う、0~9の数字として扱うオプションです。

実際にやってみると分かりますが、コンマなどが結構邪魔になります。
そこで、正規表現を使ってもっと明示的に数値だけを抽出しています。

import pytesseract
from PIL import Image
import re

# OCRを実行する
command = '-l jpn --psm 7 -c tessedit_char_whitelist="0123456789"'
image = image_processing(image_path, 2)
text = pytesseract.image_to_string(image, config=command)
numbers = re.findall(r'\d+', text)
combined_numbers = int(''.join(numbers))


サンプルコード

これらを合体したサンプルコードは次の通りです。
windowsバッチファイルにして実行すると次のようになります。
無事、数字だけを抽出することができました。

import pytesseract
from PIL import Image
from collections import Counter
import re

def image_processing(image_path, mag):
    # 拡大処理
    path_image = (image_path)
    image = Image.open(path_image)
    resized_image = image.resize((image.width * mag, image.height * mag), resample=Image.BICUBIC)

    # # 二値化処理
    thresh = 180
    max = 255
    binary_image = resized_image.convert('L')#グレースケール変換
    binary_image = binary_image.point(lambda x: 0 if x < thresh else max, '1')
    # binary_image.save('img/target_after.png')
    binary_image.save('target_after.png')
    return binary_image

def run():
    # OCRを実行する画像ファイルのパス   
    # image_path = "./img/target.png"
    image_path = "target.png"

    # 画像を読み込む
    image = Image.open(image_path)

    # OCRを実行する
    text_lists = []
    command = '-l jpn --psm 6 -c tessedit_char_whitelist="0123456789"'
    image = image_processing(image_path, 2)
    text = pytesseract.image_to_string(image, config=command)
    numbers = re.findall(r'\d+', text)
    combined_numbers = int(''.join(numbers))
    return combined_numbers


if __name__ == '__main__':
    # print("test")
    print(f"test: {run()}")

おまけ

Tesseractの主なオプション一覧を示します。

詳細はヘルプメッセージを参照するか、Tesseractの公式ドキュメントをご覧ください。

--helpまたは-h: Tesseractのヘルプメッセージを表示します。

--versionまたは-v: Tesseractのバージョン情報を表示します。

--tessdata-dir <directory>: カスタムの言語データ(.traineddataファイル)が格納されているディレクトリを指定します。

--list-langs: 使用可能な言語を一覧表示します。

--psm <mode>: ページセグメンテーションモードを指定します。主なオプションは以下の通りです:
 3: Fully automatic page segmentation, but no OSD. (Default)
   完全に自動でページを分割しますが、OSD はありません。(デフォルト)
 6: Assume a single uniform block of text.
    単一の均一なテキストブロックを想定


実際にOCRに使えるコマンド例(サンプルコードベース)
#日本語
command = '-l jpn'

#英語
command = '-l eng'

#日本語と英語
command = '-l eng+jpn'

#日本語で単一のテキストブロック想定
command = '-l jpn --psm 6'

以上となります。
少しでもお役に立てれば幸いです。
それでは、読んで頂きありがとうございました!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次