このシリーズでは、Pythonの様々な活用の方法を紹介しています。

今回は「EasyOCR」を使って、画像からテキストを読み取る方法を紹介します。

実際にOCR技術を使ってみましょう。

Google colabを使用して簡単に実装することができますので、ぜひ最後までご覧ください。

今回の目標

・EasyOCRとは

・EasyOCRの基本的な使い方

・EasyOCRの精度改善

・OCRの可視化

EasyOCRとは

OCRとは

OCR(Optical Character Recognition)とは、画像内のテキストを認識し、コンピューター上で編集可能なテキストデータに変換する技術です。この技術により、紙の書類やデジタル画像に含まれる文字情報を自動的に読み取ることができます。

OCRの仕組みは以下のようなステップで構成されています。まず、スキャナーやカメラを使って画像を取り込みます。次に、その画像に対して前処理を行います。これには、画像の傾き補正、ノイズ除去、コントラスト調整などが含まれます。前処理を行うことで、テキスト認識の精度が向上します。

続いて、画像内の文字領域を特定し、個々の文字を切り出します。この過程では、文字の輪郭を検出し、文字の形状を分析します。切り出された文字は、特徴抽出アルゴリズムを用いて特徴ベクトルに変換されます。

最後に、機械学習モデルを使って、特徴ベクトルから実際の文字を識別します。この機械学習モデルは、大量の文字画像データを用いて事前に訓練されています。識別された文字は、テキストデータとして出力されます。

OCRは、紙の書類のデジタル化、名刺管理、自動データ入力など、さまざまな分野で活用されています。Pythonでは、Tesseractや、OpenCVといったライブラリを用いてOCRを実装することができます。これらのライブラリを使えば、比較的簡単にOCRシステムを構築できます。

ただし、OCRの精度は、画像の品質や文字の種類、レイアウトの複雑さなどに大きく依存します。手書き文字や複雑な背景を持つ画像では、認識精度が低下する傾向があります。そのため、OCRを適用する際は、画像の品質を高めるための前処理や、認識結果の後処理が重要となります。

OCRは、ドキュメントの電子化や自動化を進める上で非常に有用な技術です。Pythonを使ってOCRシステムを構築することで、紙の書類からデータを効率的に抽出し、業務の生産性を向上させることができるでしょう。

EasyOCRとは

EasyOCRは、Pythonで書かれた使いやすい光学式文字認識(OCR)ライブラリです。EasyOCRを使えば、画像やスキャンしたドキュメント内の文字を簡単に読み取ることができます。

EasyOCRの大きな特徴は、80以上の言語をサポートしていることです。英語や日本語はもちろん、中国語、アラビア語、キリル文字など、世界中のさまざまな言語の文字を認識することができます。言語を指定するだけで、その言語のモデルが自動的にダウンロードされ、すぐに使用できるようになります。

また、EasyOCRは、GPUを使った高速処理にも対応しています。大量の画像を処理する場合などに、処理速度を大幅に向上させることができます。GPUを使用しない場合でも、CPUでの処理も可能です。

EasyOCRの使い方は非常にシンプルです。まず、Readerオブジェクトを作成し、認識したい言語を指定します。次に、readtextメソッドに画像のパスや画像データを渡すだけで、認識結果を取得できます。認識結果は、各テキストの座標、認識されたテキスト、認識の信頼度をリストで返してくれます。

EasyOCRは、最先端の深層学習モデルを使用しているため、高い認識精度を実現しています。また、コードがオープンソースで公開されているため、開発者はモデルを自由にカスタマイズしたり、新しい言語に対応させたりすることもできます。

EasyOCRの基本的な使い方

ここからはGoogle colab環境で進めていきます。

導入

まずは「EasyOCR」をインストールします。

!pip install easyocr

インストールが完了しました。

画像の準備

まずは基本的なOCRを実装してみます。

今回はこちらの画像を使用します。

OCRの実装

以下の例では、英語と日本語を対象とします。

また、GPUを使用せずにOCRを実行します。

最後に実行結果を表示します。

import easyocr
reader = easyocr.Reader(['en','ja'], gpu=False) 
result = reader.readtext('29767855_m.jpg')
result

上記のコードでは、以下のことを行っています。

  1. easyocr.Reader で、OCRの設定を行います。[‘ja’, ‘en’] は、日本語と英語を認識対象とすることを意味します。gpu=False は、GPUを使わずにCPUで処理することを意味します。
  2. reader.readtext(‘29767855_m.jpg’) で、29767855_m.jpg という画像ファイルに対してOCRを実行します。

実行結果:

[([[923, 589], [1015, 589], [1015, 691], [923, 691]], '成', 0.9969421195671124),
 ([[624.0259849793654, 639.3195309050808],
   [924.1861792718654, 593.1081907488701],
   [932.9740150206346, 712.6804690949192],
   [632.8138207281346, 757.8918092511299]],
  '資料作',
  0.9984824140989369),
 ([[649.4780193260012, 766.7390096630006],
   [1209.0622660481395, 665.9624206519773],
   [1226.5219806739988, 774.2609903369994],
   [666.9377339518607, 875.0375793480227]],
  'プレゼンの練習',
  0.9713997451831543),
 ([[672.8626652879326, 886.6077314031057],
   [1159.9401030422644, 806.6564306633506],
   [1173.1373347120673, 923.3922685968943],
   [686.0598969577356, 1002.3435693366494]],
  'lon1の準備',
  0.7934918448755321),
 ([[688.5825808840516, 1013.6408389724568],
   [1235.1181535068565, 930.1098007637163],
   [1248.4174191159484, 1045.3591610275432],
   [701.8818464931436, 1128.8901992362837]],
  'MTG資料印刷',
  0.9891207866280942),
 ([[734.5060845773462, 1165.5518253732039],
   [1268.3019336181942, 1074.9668503015719],
   [1283.4939154226538, 1169.4481746267961],
   [749.6980663818058, 1260.0331496984281]],
  'Aさんにmail',
  0.9949341920660215)]

抽出された文字列と対応する座標が出力されていることがわかります。

出力結果を表形式で出力

出力結果を見やすくするため、表形式で表示してみます。

import easyocr
import pandas as pd

reader = easyocr.Reader(['en', 'ja'], gpu=False)
result = reader.readtext('29767855_m.jpg')

data = []

for detection in result:
    text = detection[1]
    confidence = detection[2]
    coordinates = detection[0]
    x1, y1 = coordinates[0]
    x2, y2 = coordinates[1]
    x3, y3 = coordinates[2]
    x4, y4 = coordinates[3]
    data.append({"テキスト": text, "信頼度": confidence,
                 "x1": x1, "y1": y1, "x2": x2, "y2": y2,
                 "x3": x3, "y3": y3, "x4": x4, "y4": y4})

df = pd.DataFrame(data)
df

実行結果:

indexテキスト信頼度x1y1x2y2x3y3x4y4
00.9969421195671124923.0589.01015.0589.01015.0691.0923.0691.0
1資料作0.9984824140989369624.0259849793654639.3195309050808924.1861792718654593.1081907488701932.9740150206346712.6804690949192632.8138207281346757.8918092511299
2プレゼンの練習0.9713997451831543649.4780193260012766.73900966300061209.0622660481395665.96242065197731226.5219806739988774.2609903369994666.9377339518607875.0375793480227
3lon1の準備0.7934918448755321672.8626652879326886.60773140310571159.9401030422644806.65643066335061173.1373347120673923.3922685968943686.05989695773561002.3435693366494
4MTG資料印刷0.9891207866280942688.58258088405161013.64083897245681235.1181535068565930.10980076371631248.41741911594841045.3591610275432701.88184649314361128.8901992362837
5Aさんにmail0.9949341920660215734.50608457734621165.55182537320391268.30193361819421074.96685030157191283.49391542265381169.4481746267961749.69806638180581260.0331496984281

画像と出力結果を比較してみると、「資料作」と「成」に分割されてしまっていることがわかります。

また、「1on1」は「lon1」になってしまっていることがわかりました。

もう少し精度の改善が必要となりそうです。

EasyOCRの精度改善

EasyOCRではOCR実行時の引数を設定することができます。

以下の引数とその内容です。

easyocr.Reader()で使用する引数

引数名説明
lang_list認識したい言語コードのリスト。例えば、[‘ch_sim’, ‘en’] のように指定します。
gpuGPU を有効にするかどうかを指定します。デフォルトは True です。gpu=Falseとすることで、CPUでも動作します。
model_storage_directoryモデルデータを保存するディレクトリのパスを指定します。指定しない場合、環境変数 EASYOCR_MODULE_PATH(推奨)、MODULE_PATH(定義されている場合)、または ~/.EasyOCR/ で定義されたディレクトリからモデルが読み込まれます。
download_enabledEasyOCR がモデルファイルを見つけられない場合にダウンロードを有効にするかどうかを指定します。デフォルトは True です。
user_network_directoryユーザー定義の認識ネットワークのパスを指定します。指定しない場合、MODULE_PATH + ‘/user_network’ (~/.EasyOCR/user_network) からモデルが読み込まれます。
recog_network標準モードの代わりに、独自の認識ネットワークを選択できます。これについてのチュートリアルは今後作成される予定です。デフォルトは ‘standard’ です。
detector検出モデルをメモリに読み込むかどうかを指定します。デフォルトは True です。
recognizer認識モデルをメモリに読み込むかどうかを指定します。デフォルトは True です。

reader.readtext()で使用する引数

パラメータ名説明
image入力画像。文字列、NumPy配列、バイト列のいずれかで指定。
decoder使用するデコーダー。’greedy’(貪欲法)、’beamsearch’(ビーム探索)、’wordbeamsearch’(単語単位のビーム探索)から選択。デフォルトは’greedy’。
beamWidth‘beamsearch’または’wordbeamsearch’を使用する際に保持するビームの数。デフォルトは5。
batch_sizeバッチサイズ。1より大きい値を指定するとEasyOCRの処理速度が向上しますが、より多くのメモリを消費します。デフォルトは1。
workersデータローダーで使用するスレッド数。デフォルトは0。
allowlist認識対象の文字を制限する文字列。特定の問題(ナンバープレートなど)に役立ちます。
blocklist認識対象から除外する文字を指定する文字列。allowlistが指定されている場合は無視されます。
detail出力の詳細度を指定。0にすると簡易出力になります。デフォルトは1。
paragraph結果を段落としてまとめるかどうか。デフォルトはFalse。
min_sizeピクセル単位で、これより小さいテキストボックスをフィルタリングします。デフォルトは10。
rotation_infoEasyOCRが各テキストボックスを回転させ、最も確信度の高いものを返すことを許可します。90、180、270の値が利用可能です。例えば、[90, 180, 270]とすることで、考えられるすべてのテキストの向きを試すことができます。デフォルトはNone。
contrast_thsこの値より低いコントラストのテキストボックスは、元の画像と’adjust_contrast’の値に調整された画像の2回モデルに渡されます。より確信度の高い方が結果として返されます。デフォルトは0.1。
adjust_contrast低コントラストのテキストボックスに対するターゲットのコントラストレベル。デフォルトは0.5。
text_thresholdテキスト確信度の閾値。デフォルトは0.7。
low_textテキストの下限スコア。デフォルトは0.4。
link_thresholdリンク確信度の閾値。デフォルトは0.4。
canvas_size最大画像サイズ。この値より大きい画像はリサイズされます。デフォルトは2560。
mag_ratio画像の拡大率。デフォルトは1。
slope_thsマージを検討する最大の傾き(delta y/delta x)。低い値は、傾いたボックスがマージされないことを意味します。デフォルトは0.1。
ycenter_thsy方向の最大シフト量。異なるレベルのボックスはマージされるべきではありません。デフォルトは0.5。
height_thsボックスの高さの最大差。非常に異なるテキストサイズのボックスはマージされるべきではありません。デフォルトは0.5。
width_thsボックスをマージするための最大水平距離。デフォルトは0.5。
add_marginすべての方向のバウンディングボックスを特定の値だけ拡張します。これは、タイ語のような複雑な文字を持つ言語に重要です。デフォルトは0.1。
x_thsparagraph=Trueの場合にテキストボックスをマージするための最大水平距離。デフォルトは1.0。
y_thsparagraph=Trueの場合にテキストボックスをマージするための最大垂直距離。デフォルトは0.5。

精度改善

先ほどの画像に対して、引数を変更して、精度を改善します。

  • link_threshold を 0.3 に設定:link_threshold は、単語間のリンク確信度の閾値を表します。この値を下げることで、単語間の関連性がより低い場合でも、それらを1つの文章としてまとめる可能性が高くなります。つまり、文章の連続性に対する判断基準が緩くなります。
  • mag_ratio を 1.1 に設定:mag_ratio は、画像の拡大率を表します。デフォルト値は 1 ですが、1.1 に設定することで、画像を10%拡大して処理します。これにより、小さな文字をより認識しやすくなります。ただし、拡大によって画像の品質が若干低下する可能性があります。
import easyocr
reader = easyocr.Reader(['en','ja'], gpu=False)
result = reader.readtext('29767855_m.jpg',  link_threshold=0.3,mag_ratio=1.1)

実行結果:

indexテキスト信頼度x1y1x2y2x3y3x4y4
0資料作成0.997967541217804623.8005305310426643.00132632760641014.6341038492525577.96846454654341025.1994694689574693.9986736723936635.3658961507475759.0315354534566
1プレゼンの練習0.977445970814249650.8525919657369766.31155517944221207.1576651173118668.39661223713441224.147408034263773.6884448205578667.8423348826882872.6033877628656
21on1の準備0.5931251849512019672.1005050633884890.10050506338841158.952099161938807.68557366225411173.8994949366117919.8994949366116687.04790083806211001.3144263377459
3MTG資料印刷0.9954317802241432689.58258088405161013.64083897245681236.101159914352929.06445454903111249.41741911594841045.3591610275432702.89884008564811129.935545450969
4Aさんにmail0.9986604964795984732.85827970937691163.54331188375071267.30450066249681073.97405107190751282.14172029062321168.4566881162493747.69549933750321259.0259489280925

先ほどと比較して、正しく文字認識ができていることがわかりました。

精度改善の手法

OCRの精度は、画像の品質や文字の種類などによって大きく変化します。以下のようなコツを使うことで、精度を改善することができます。

  • 画像の品質を上げる:解像度が高く、ノイズの少ない画像を用意することで、OCRの精度が向上します。
  • 画像を適切な大きさに拡大・縮小する:mag_ratio パラメータを使って画像の大きさを調整することで、小さな文字でも認識しやすくなります。ただし、拡大しすぎるとかえって精度が下がることがあるので注意が必要です。
  • 文字の色と背景のコントラストを上げる:文字と背景の色の差が大きいほど、OCRの精度が上がります。
  • 認識対象の文字を制限する:数字のみを認識したい場合など、認識対象を制限することで不要な認識結果を減らすことができます。allowlist パラメータを使います。
  • 単語や行をまとめる:link_threshold パラメータを調整することで、単語や行をうまく結合できるようになります。

OCRの可視化

出力結果を枠線で囲んで可視化することができます。

簡単のため、先ほどの画像を回転しておきます。

import cv2
import easyocr

# 画像を読み込む
image = cv2.imread('29767855_m_rot.jpg')

# OCRを実行
reader = easyocr.Reader(['en','ja'], gpu=False) 
result = reader.readtext('29767855_m_rot.jpg',  link_threshold=0.3,mag_ratio=1.1)

# 結果を元の画像に描画
for (bbox, text, prob) in result:
    # 確率が50%以上の場合のみ描画
    if prob >= 0.5:
        # 枠線の座標を取得
        (top_left, top_right, bottom_right, bottom_left) = bbox
        top_left = (int(top_left[0]), int(top_left[1]))
        bottom_right = (int(bottom_right[0]), int(bottom_right[1]))
        
        # 枠線を描画
        cv2.rectangle(image, top_left, bottom_right, (0, 255, 0), 2)

# 結果を保存
cv2.imwrite("result_image.jpg", image)

出力結果:

OCRによって文字認識された部分を可視化することができました。

まとめ

最後までご覧いただきありがとうございました。

easyOCRを使えば、初心者でも簡単にOCRを実装することができます。

精度改善のコツを押さえて、画像の前処理を工夫することが大切です。

OCRは様々な場面で活用できる技術なので、ぜひ色々な画像で試してみてください。

コメントを残す