画像から文字列を抽出する
— OCR 入門(Tesseract + pytesseract)
1. OCR の仕組みとツールの全体像
OCR(Optical Character Recognition)とは、画像に含まれるテキストをコンピュータが読み取れる文字列に変換する技術です。Python では Tesseract OCR(Google 開発のオープンソースエンジン)と、それを Python から呼び出すラッパーライブラリ pytesseract の組み合わせが最もポピュラーです。
| ライブラリ | 役割 | 備考 |
|---|---|---|
| Tesseract | OCR エンジン本体(外部バイナリ) | OS にインストールが必要 |
| pytesseract | Python → Tesseract のブリッジ | pip でインストール |
| Pillow (PIL) | 画像の読み込み・前処理 | pip でインストール |
| OpenCV | 高度な前処理(PART 05 で解説) | pip でインストール |
2. Tesseract のインストール
pytesseract は Tesseract バイナリを外部コマンドとして呼び出します。そのため、まず OS に Tesseract 本体をインストールする必要があります。
Windows — インストーラー方式
UB Mannheim が配布している公式インストーラーを使います。
- UB-Mannheim の GitHub Wiki からインストーラーをダウンロード(
tesseract-ocr-w64-setup-*.exe) - インストール時に「Additional language data」→「Japanese」にチェックを入れる(日本語を使う場合)
- デフォルトインストール先:
C:\Program Files\Tesseract-OCR\
インストール後、環境変数 PATH に追加するか、Python コード内でパスを直接指定します:
import pytesseract
# Windows の場合は tesseract.exe のパスを明示的に指定
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
動作確認(コマンドプロンプト):
tesseract --version
macOS — Homebrew 方式
# Tesseract 本体をインストール
brew install tesseract
# 日本語言語データを追加でインストール
brew install tesseract-lang
動作確認:
tesseract --version
# インストール済み言語の確認
tesseract --list-langs
Linux (Ubuntu/Debian)
# Tesseract 本体をインストール
sudo apt-get update
sudo apt-get install -y tesseract-ocr
# 日本語言語データをインストール
sudo apt-get install -y tesseract-ocr-jpn
# インストール済み言語の確認
tesseract --list-langs
sudo yum install tesseract、日本語データは tesseract-langpack-jpn パッケージです。
3. pytesseract / Pillow のインストール
Tesseract のインストールが済んだら、Python ライブラリをインストールします。
# pytesseract:Tesseract の Python ラッパー
pip install pytesseract
# Pillow:画像の読み込み・操作ライブラリ
pip install Pillow
インストール確認:
import pytesseract
from PIL import Image
print(pytesseract.get_tesseract_version()) # Tesseract のバージョン確認
TesseractNotFoundError が発生します。pytesseract は Python ライブラリ、Tesseract は OS レベルのバイナリの2つがセットで必要です。
4. 基本的な文字列抽出
Pillow で画像を読み込み、pytesseract.image_to_string() を呼ぶだけで文字列を取得できます。
import pytesseract
from PIL import Image
# Windows の場合はパスを指定(不要なら削除)
# pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
# 画像を開く
img = Image.open("sample.png")
# OCR でテキストを抽出(デフォルトは英語)
text = pytesseract.image_to_string(img)
print(text)
print("---")
print(f"文字数: {len(text)}")
ファイルパスを直接渡す方法
Pillow を経由せず、ファイルパスを文字列で渡すこともできます。
import pytesseract
# ファイルパスを直接渡す
text = pytesseract.image_to_string("sample.png")
print(text)
対応している画像形式
PNG・JPEG・TIFF・BMP・GIF などの一般的な形式に対応しています。OCR の精度面では PNG(可逆圧縮) が最も安定しています。JPEG は圧縮ノイズが認識精度を落とすことがあるため、可能であれば PNG に変換してから OCR にかけることをお勧めします。
5. 日本語テキストの認識
デフォルトの認識言語は英語(eng)です。日本語を認識するには lang パラメータを指定します。
import pytesseract
from PIL import Image
img = Image.open("japanese_sample.png")
# lang='jpn' で日本語モデルを使用
text = pytesseract.image_to_string(img, lang='jpn')
print(text)
# 英語と日本語を混在させる場合(+ で区切る)
text_mixed = pytesseract.image_to_string(img, lang='jpn+eng')
print(text_mixed)
日本語の精度は英語に比べて低い傾向があります。特にフォントサイズが小さい・手書き・低解像度の画像では誤認識が増えます。PART 05 では画像の前処理(二値化・拡大・ノイズ除去)で精度を向上させる手法を解説します。
利用可能な言語を確認する
import pytesseract
# インストール済み言語データの一覧を取得
langs = pytesseract.get_languages()
print(langs)
# 例: ['eng', 'jpn', 'osd']
jpn が含まれていない場合は、OS に日本語言語データが入っていません。セクション 2 の手順でインストールしてください。
6. 出力フォーマットと詳細データ
pytesseract は文字列以外にも、信頼度スコアや座標を含む詳細なデータを取得できます。
| メソッド | 戻り値の型 | 用途 |
|---|---|---|
image_to_string() | str | シンプルにテキストだけ欲しい場合 |
image_to_data() | str(TSV)/ DataFrame | 信頼度・座標も含むフル情報 |
image_to_boxes() | str | 文字ごとの bounding box(旧形式) |
image_to_osd() | str | 画像の向き・スクリプト検出 |
image_to_pdf_or_hocr() | bytes | PDF / hOCR 形式で出力 |
image_to_data() — 詳細データの取得
import pytesseract
from PIL import Image
import pandas as pd
img = Image.open("sample.png")
# TSV 形式で取得
tsv_text = pytesseract.image_to_data(img)
print(tsv_text)
# pandas DataFrame として取得
df = pytesseract.image_to_data(img, output_type=pytesseract.Output.DATAFRAME)
print(df.columns.tolist())
# ['level', 'page_num', 'block_num', 'par_num', 'line_num', 'word_num',
# 'left', 'top', 'width', 'height', 'conf', 'text']
# 信頼度が 60 以上の単語だけ抽出
reliable = df[df['conf'] > 60][['text', 'conf', 'left', 'top', 'width', 'height']]
print(reliable.to_string())
conf(信頼度スコア)が低い単語は誤認識の可能性が高いです。閾値を設けてフィルタリングするだけで、出力品質が大幅に向上します。
7. Bounding Box — 文字位置の取得
認識されたテキストが画像のどの位置にあるかを取得し、矩形を描画する方法を紹介します。
import pytesseract
from PIL import Image, ImageDraw
import pandas as pd
img = Image.open("sample.png")
draw = ImageDraw.Draw(img)
# image_to_data で単語ごとの座標を取得
df = pytesseract.image_to_data(
img,
output_type=pytesseract.Output.DATAFRAME,
lang='eng'
)
# 信頼度が 60 以上の単語に矩形を描画
for _, row in df.iterrows():
if row['conf'] > 60 and isinstance(row['text'], str) and row['text'].strip():
x, y, w, h = int(row['left']), int(row['top']), int(row['width']), int(row['height'])
draw.rectangle([x, y, x + w, y + h], outline='red', width=2)
# テキストラベルを描画(任意)
draw.text((x, y - 12), row['text'], fill='red')
# 結果を保存
img.save("output_bbox.png")
print("output_bbox.png に保存しました")
単語レベルの bounding box — image_to_boxes()
image_to_boxes() は文字(1文字)単位で bounding box を返す旧来のメソッドです。座標系は 左下原点 であることに注意してください。
import pytesseract
from PIL import Image, ImageDraw
img = Image.open("sample.png")
h_img = img.height # 座標変換用に高さを保持
# 文字単位の bounding box を取得
boxes_str = pytesseract.image_to_boxes(img, lang='eng')
draw = ImageDraw.Draw(img)
for line in boxes_str.splitlines():
parts = line.split()
if len(parts) < 6:
continue
char = parts[0]
x1, y1, x2, y2 = int(parts[1]), int(parts[2]), int(parts[3]), int(parts[4])
# image_to_boxes は左下原点 → Pillow (左上原点) に変換
y1_pil = h_img - y2
y2_pil = h_img - y1
draw.rectangle([x1, y1_pil, x2, y2_pil], outline='blue', width=1)
img.save("output_char_bbox.png")
print("output_char_bbox.png に保存しました")
単語・行レベルで処理したい場合は
image_to_data()、1 文字単位で詳細に処理したい場合は image_to_boxes() を使います。通常は image_to_data() のほうが扱いやすいです。
8. 主要な設定オプション
config パラメータに Tesseract のコマンドラインオプションを文字列で渡すことで、認識モードを細かく制御できます。
import pytesseract
from PIL import Image
img = Image.open("sample.png")
# PSM (Page Segmentation Mode) の指定例
# --psm 6 : 単一ブロックのテキストとして処理(デフォルトは 3)
text = pytesseract.image_to_string(img, config='--psm 6')
print(text)
# OEM (OCR Engine Mode) の指定
# --oem 3 : デフォルト(LSTM + Legacy の両方を使用)
# --oem 1 : LSTM のみ使用(Tesseract 4 以降で推奨)
text2 = pytesseract.image_to_string(img, config='--oem 1 --psm 6')
print(text2)
# 数字だけを認識させる
text_num = pytesseract.image_to_string(img, config='--psm 6 -c tessedit_char_whitelist=0123456789')
print(text_num)
| PSM 値 | 説明 | 適した画像 |
|---|---|---|
--psm 3 | 自動でページ分割(デフォルト) | 通常の文書画像 |
--psm 6 | 単一の均一なテキストブロック | 段落・ブロック単位の画像 |
--psm 7 | 1行のテキスト | ラベル・バナー |
--psm 8 | 1単語 | ボタン・タグ |
--psm 10 | 1文字 | 1文字の認識 |
--psm 11 | テキストとして扱える箇所をすべて | 散在したテキスト |
--psm 13 | 1行(OSD なし) | シンプルな1行テキスト |
--psm を選ぶことが精度向上の第一歩です。迷ったらまず --psm 6 を試してみてください。
9. まとめ
import pytesseract
from PIL import Image
import pandas as pd
# Windows の場合
# pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
def ocr_image(image_path: str, lang: str = 'eng', psm: int = 3) -> str:
"""画像からテキストを抽出する基本関数"""
img = Image.open(image_path)
config = f'--psm {psm}'
return pytesseract.image_to_string(img, lang=lang, config=config).strip()
def ocr_image_with_confidence(image_path: str, lang: str = 'eng',
min_conf: int = 60) -> list[dict]:
"""信頼度付きで単語リストを返す"""
img = Image.open(image_path)
df = pytesseract.image_to_data(img, lang=lang,
output_type=pytesseract.Output.DATAFRAME)
results = []
for _, row in df.iterrows():
if row['conf'] >= min_conf and isinstance(row['text'], str) and row['text'].strip():
results.append({
'text': row['text'],
'conf': row['conf'],
'box': (int(row['left']), int(row['top']),
int(row['width']), int(row['height']))
})
return results
# 使用例
if __name__ == '__main__':
# 英語テキストの抽出
text = ocr_image('sample.png', lang='eng', psm=6)
print("=== 抽出テキスト ===")
print(text)
# 日本語テキストの抽出
text_ja = ocr_image('japanese_sample.png', lang='jpn', psm=6)
print("\n=== 日本語テキスト ===")
print(text_ja)
# 信頼度付き単語リスト
words = ocr_image_with_confidence('sample.png', min_conf=70)
print(f"\n=== 信頼度 70 以上の単語: {len(words)} 個 ===")
for w in words:
print(f" '{w['text']}' (conf={w['conf']}, box={w['box']})")
| やりたいこと | メソッド | lang 指定 |
|---|---|---|
| テキストだけ取り出す | image_to_string() | lang='eng' or 'jpn' |
| 信頼度・座標も取得 | image_to_data() | 同上 |
| 文字単位の座標 | image_to_boxes() | 同上 |
| 認識モードを変える | config='--psm N' | 組み合わせて使用 |
次のパートでは、認識精度をさらに高めるための 画像前処理(グレースケール・二値化・ノイズ除去・解像度調整)と、Tesseract の代替として注目されている EasyOCR を紹介します。