[Python][tesseract]画像ファイルを光学式文字認識(OCR)を使って文章抽出する

スポンサーリンク

前回の続き。

OCRによる文章抽出において、Google Cloud Vision APIを使った場合とtesseractを使った場合を比較しようかなと思い試していました。

結果的に、精度は、Google Cloud Vision APIの方がよさげです。
ただ、Vision APIの場合、使用量によりお金がかかる可能性があることと、APIの先の処理が非公開なので、カスタマイズも難しいこともあり、どちらも試しただけで終わりました。

前回まで

[Python][Google Cloud Vision API]画像ファイルを光学式文字認識(OCR)を使って文章抽出する
https://blog.integrityworks.co.jp/2019/11/02/python-get-paragraphs-from-png-file/

[Python]PDFファイルをページ毎にpngへ変換する
https://blog.integrityworks.co.jp/2019/11/01/python-pdf-change-to-png/

tesseractとは

オープンソースで使用可能なOCR
https://tesseract-ocr.github.io/
https://github.com/tesseract-ocr/tesseract

Pythonで使う場合も、Pythonパッケージとしてインストールするのではなく、Windowsソフトとしてインストールして使いました。
※試したのは、Windows10。Mac環境では確認していないですが、同じくインストーラがあるっぽいので、ほぼ同じようにっできるかなと思います。

環境構築

ダウンロード先
https://github.com/tesseract-ocr/tesseract/wiki
tesseract-ocr-w64-setup-v5.0.0-alpha.20191030.exe (64 bit)

インストール後、環境変数を設定します。
インストール手順は、ここが参考になるかと思います。
https://gammasoft.jp/blog/tesseract-ocr-install-on-windows/

サンプルコード

ささっと書いたので、かなり雑なコードのままになっています。。。

import sys
import os.path
from PIL import Image
import pyocr
import pyocr.builders
import glob
import shutil
import cv2
from pdf2image import convert_from_path

import matplotlib.pyplot as plt

'''
tesseractの試作

解析するときのBuilderによって、結果が違う。
LineBoxBuilderが行単位で判定できるので、今回のニーズに一番マッチしている。
raw text : TextBuilder
words + boxes : WordBoxBuilder
lines + words + boxes : LineBoxBuilder

tesseract-ocr/tesseract
Tesseract Open Source OCR Engine (main repository) - tesseract-ocr/tesseract
ページセグメンテーションモード (PSM) ※公式情報が拾えていない 0 文字方向および書字系の検出 (Orientation and script detection: OSD) のみ 1 自動ページセグメンテーション(OSDありでOCR). 2 自動ページセグメンテーション(OSDなし) 3 完全自動ページセグメンテーション(OSDなし) (Default) 4 単一カラムの様々なサイズのテキストとみなす 5 垂直方向に整列した単一カラムの均一ブロックテキストとみなす 6 単一カラムの均一ブロックテキストとみなす 7 画像を単一行のテキストとして扱う 8 画像を単語1つのみ含まれるものとして扱う 9 画像を円で囲まれた単語1つのみを含むものとして扱う 10 画像を1文字のだけが含まれるものとして扱う 11 Sparse text: 不特定の順序でできるだけ多くのテキストを探す 12 Sparse text: OSDあり 13 Raw line: 内部の処理をバイパスしつつ画像内にテキストが1行だけあるものとして扱う ''' output_dir = "output_tes" output_image_dir = output_dir + "/output_img" input_image_dir = "Intermediate_img" # tesseract周りの設定(別途Windows側でtesseractインストールなどの設定する必要あり) tools = pyocr.get_available_tools() if len(tools) == 0: print("No OCR tool found") sys.exit(1) tool = tools[0] #print("Will use tool '%s'" % (tool.get_name())) langs = tool.get_available_languages() #print("Available languages: %s" % ", ".join(langs)) lang = langs[2] #print("Will use lang '%s'" % (lang)) # 結果の出力用ディレクトリが存在していれば、クリアして再生成する def output_setting(): if os.path.exists(output_dir): shutil.rmtree(output_dir) if os.path.exists(output_image_dir): shutil.rmtree(output_image_dir) os.makedirs(output_dir) os.makedirs(output_image_dir) ##### 1. TextBuilderの取得 #builder = pyocr.builders.TextBuilder(tesseract_layout=4, cuneiform_dotmatrix=True, # cuneiform_fax=True, cuneiform_singlecolumn=True) # txt = tool.image_to_string(Image.open('test.png'), # lang=lang, # builder=builder) # with open("result2.txt", 'w', encoding='utf-8') as file_descriptor: # builder.write_file(file_descriptor, txt) ##### 2. WordBoxBuilderの取得 # builderW = pyocr.builders.WordBoxBuilder(tesseract_layout=4) # word_box = tool.image_to_string(Image.open('test.png'), # lang=lang, # builder=builderW) # # with open("resultw.txt", 'w', encoding='utf-8') as file_descriptor_w: # builderW.write_file(file_descriptor_w, word_box) ##### LineBoxBuilderの取得 ★これがよさげ def analyse_image_to_line(image_file, index): builder_line = pyocr.builders.LineBoxBuilder() box_lines = tool.image_to_string(Image.open(image_file), lang=lang, builder=builder_line) # 結果を保存(HTML形式) name, ext = os.path.splitext(os.path.basename(image_file)) name_slice = name[0:len(name)-2] save_res = output_dir + "/res_tes_line_" + name + ".txt" with open(save_res, 'w', encoding='utf-8') as file_descriptor_line: builder_line.write_file(file_descriptor_line, box_lines) save_text = output_dir + "/res_tes_text_" + name_slice + ".txt" with open(save_text, 'a', encoding='utf-8') as file_descriptor_text: for line in box_lines: file_descriptor_text.write(line.content + "\r") file_descriptor_text.write("-----------\r") out = cv2.imread(image_file) for line in box_lines: cv2.rectangle(out, line.position[0], line.position[1], (0, 255, 0), 5) # こちらの方法だと、ひとオブジェクト毎に色が変わるため、判別しやすい # x_plot = [l.position[0][0], l.position[1][0], l.position[1][0], l.position[0][0], l.position[0][0]] # y_plot = [l.position[0][1], l.position[0][1], l.position[1][1], l.position[1][1], l.position[0][1]] # plt.plot(x_plot, y_plot) # # plt.savefig("line_box.png") # plt.clf() output_img_name = output_image_dir + "/" + os.path.basename(image_file) cv2.imwrite(output_img_name, out) output_setting() image_list = glob.glob(input_image_dir + "/*.png") for index, img_file_name in enumerate(image_list): analyse_image_to_line(img_file_name, index)

その他、試したパッケージ

Pythonには、以下のようなパッケージもありました。
https://pypi.org/project/gpyocr/

Python wrapper for Tesseract OCR and Google Vision OCR to perform OCR on images and get a confidence value of the results.

サンプルコード

import gpyocr

text, conf = gpyocr.tesseract_ocr('test.png', lang='jpn', psm=6)
print(text)

aaa, confidence = gpyocr.google_vision_ocr('test.png', langs=['ja'])

参考(後日追加)

PythonとTesseract OCRで文字認識

コメント

タイトルとURLをコピーしました