電算倶楽部 富山県のコンピュータ社会人サークル

富山県、特に滑川市、富山市、魚津市周辺で活動している社会人サークルです。

スキャンしたPDFの処理を考える その2 画像にOCR処理をかける

https://s-densan.hatenablog.com/entry/2021/02/04/pdf1 の続きです。

処理のステップ

  • PDFを画像に変換する
  • 画像にOCR処理をかける ←今回はここ
  • 検索の仕組みを考える

必要コマンドのダウンロード

tesseractと日本語の学習データをインストールします。 tesseractはGoogle製のOCRソフトです。 この話はWindowsを前提としているのでバイナリを探しましょう。 ドイツのマンハイム大学図書館が公開しているようです。

github.com

32ビット版と64ビット版がありますが、特に理由なければ64ビット版で良いと思います。

インストールが終わったらtesseractコマンドが使えるようになります。

tessaract --version

以下のように表示されればOKです。

tesseract v5.0.0-alpha.20201127
 leptonica-1.78.0
  libgif 5.1.4 : libjpeg 8d (libjpeg-turbo 1.5.3) : libpng 1.6.34 : libtiff 4.0.9 : zlib 1.2.11 : libwebp 0.6.1 : libopenjp2 2.3.0
 Found AVX2
 Found AVX
 Found FMA
 Found SSE
 Found libarchive 3.3.2 zlib/1.2.11 liblzma/5.2.3 bz2lib/1.0.6 liblz4/1.7.5
 Found libcurl/7.59.0 OpenSSL/1.0.2o (WinSSL) zlib/1.2.11 WinIDN libssh2/1.7.0 nghttp2/1.31.0

次に日本語をいい感じに認識させるために学習済みデータをインストールします。

Traineddata Files for Version 4.00 + | tessdoc

公式サイトからgithubにジャンプします。 tessdata_fast、tessdata_best、tessdataの3種類がありますが、 今回は精度を重視してtessdata_bestを選びました。

jpn.traineddatajpn_vert.traineddataをダウンロードして、tesseractインストールフォルダの下のtessdata内に格納します。

お試し

コマンドプロンプトを開き、以下のコマンドを実行します。

tesseract -l jpn (画像ファイル名) stdout

少し間をおいて、画面に文字が出力されれば成功です。 なお、不自然に文字の間にスペースが挟まれるようです。

私は下図を読み込ませてみました。 某試験の一部分です。

f:id:s-densan:20210210140014p:plain

問 1 サー ビス デザ イン 思考 に よる 開発 アプ ロー チ に 関す る 次 の 記述 を 読ん で , 設問 1
4 に 答え よ 。

総合 家電 メー カ の R 社 は , “健康 "を テー マ と し た 製品 と し て , 体 組成 計 , 活動 量
計 , ラン ニン グ ウ ォ ッ チ な どの 健康 機器 を 製造 , 販売 し て いる 。

[ 新 製品 に 係る 取組

R 社 は , 人 々 が 重視 する 価値 が “モノ” から “コト "へ と シフ ト し て いる 近年 の 状
況 を 踏ま えて , 自社 の 製品 を 通じ た 人 々 の 生活 の ディ ジタル 化 の 取組 を 推進 し て お り ,
スマ ー ト フォ ン 用 の アブ リケーション ソフ トド トウェア (以下 リズ スマ ホ ア プ リ と いう ) を
開発 し て いる 。 ス マ ホ ア プリ の 利用 者 は , 体 組成 計 で 測定 し た 体重 , 体 脂肪 率 , 筋肉
量 な どの デー タ を スマ ー ト フォ ン に 転送 し て , 測定 結果 の 履歴 を 閲覧 する こと が で き
る 。 ス マ ホ ア プリ は , 体 組成 計 の 購入 者 の うち , 個人 情報 , 趣味 ・ 嗜好 , 健康 に 関す
る アン ケー ト に 回 答 し た 者 に 対し て , 無料 で 提供 し て いる 。

なお、最後のstdoutの部分には出力先ファイルを指定するのですが、stdoutは特殊で出力先を標準出力にするとのことです。

プログラムを作る

指定したフォルダの中のすべての画像に対して、OCR処理を施し、それぞれ(元のファイル名).txt ファイルに保存します。

import os
from typing import List, Dict
import glob
import subprocess

def main():
    # 入力フォルダ
    image_dir = r'C:\ocr_src'

    # 入力フォルダ内のファイル一覧を取得
    image_file_list = glob.glob(os.path.join(image_dir, '*'))

    text_path_list = []
    for image_path in image_file_list:
        # 対象とする拡張子
        allow_exts = ['.jpg', '.jpeg', '.png', '.bmp', '.webp']
        if os.path.splitext(image_path)[1].lower() not in allow_exts:
            # 対象外のファイルの場合は次のファイルへ
            continue
        # 出力テキストファイルパス
        text_path = os.path.splitext(image_path)[0] + '.txt'
        # OCR実行
        ocr_result = ocr_text(image_path, text_path)
        if ocr_result:
            text_path_list.append(text_path)
    print('完了')
    print('\n'.join(text_path_list))


def ocr_text(src_image_path: str, dst_text_path: str) -> bool:
    """
    一つの画像ファイルに対し、日本語のOCR処理を行い、dst_pathにその内容を保存する。
    
    Parameters
    ----------
    src_image_path : str
        入力画像ファイルパス
    dst_text_path : str
        出力テキストファイル名
    
    Returns
    -------
    bool
        成否(true:成功, false:失敗)
    """
    # プログラム名(必要ならばフルパスで指定)
    program = 'tesseract'
    # 実行するコマンド
    command = f'{program} -l jpn "{src_image_path}" stdout'

    # 入力画像ファイルが存在しない場合は終了
    if not os.path.isfile(src_image_path):
        return False

    # 出力先フォルダが存在しない場合は作成
    dst_dir = os.path.dirname(dst_text_path)
    if not os.path.isdir(dst_dir):
        if os.path.isfile(dst_dir):
            return False
        else:
            os.makedirs(dst_dir)
    # コマンド実行
    try:
        res = subprocess.check_output(command)
    except Exception as ex:
        print(f'コマンド実行中にエラーが発生しまshた。command = {command}, Exception = {ex}')
        return False
    res_text = res.decode('utf-8').replace(' ', '').replace('\r\n', '\n')

    # OCR情報をファイルに書き込み
    with open(dst_text_path, 'w') as fp:
        fp.write(res_text)

    return True

おわりに

画像からOCRでテキスト情報を取り出すことができました。 画像のままではコンピュータで処理しづらいですが、テキスト形式ならば 例えば検索・タグ付け・分類などできることが広がります。