スキャンしたPDFの処理を考える その2 画像にOCR処理をかける
https://s-densan.hatenablog.com/entry/2021/02/04/pdf1 の続きです。
処理のステップ
- PDFを画像に変換する
- 画像にOCR処理をかける ←今回はここ
- 検索の仕組みを考える
必要コマンドのダウンロード
tesseractと日本語の学習データをインストールします。 tesseractはGoogle製のOCRソフトです。 この話はWindowsを前提としているのでバイナリを探しましょう。 ドイツのマンハイム大学図書館が公開しているようです。
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.traineddata
とjpn_vert.traineddata
をダウンロードして、tesseractインストールフォルダの下のtessdata内に格納します。
お試し
コマンドプロンプトを開き、以下のコマンドを実行します。
tesseract -l jpn (画像ファイル名) stdout
少し間をおいて、画面に文字が出力されれば成功です。 なお、不自然に文字の間にスペースが挟まれるようです。
私は下図を読み込ませてみました。 某試験の一部分です。
問 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でテキスト情報を取り出すことができました。 画像のままではコンピュータで処理しづらいですが、テキスト形式ならば 例えば検索・タグ付け・分類などできることが広がります。