🐙

Google Drive APIを用いたOCRと出力内容の自動転記方法例

2023/03/07に公開

本記事の目的

企業での事務作業において、PDFの内容を転記して他の資料への転記する作業やPDFの内容を会社の独自システムにアップロードする作業が存在します。アップロードの際は、初めから読取を考えていた場合は、転記等の作業は必要ありませんが、現状は異なる書式への転記作業が必要になる場合も存在する可能性もあります。これらの単純作業は、高精度なOCRを実装により削減が可能です。このOCRの実装を自社で行うことで他企業への開発依頼をしないという選択肢も取れるのではないかと考えました。またOCRの実装を自分で行うことにより、フォーマット変更時の対応や読み取った内容の分析に関して、自社で行うことも可能ではないかと考えています。
そのための最初のステップとして、OCRの実装と出力内容を見ていきます。なお、今回はGoogle DriveのOCRを実装していきます。

今回実装するOCR

OCRはOptical Character Recognitionの略で、PDFや画像などのデジタルデータ内の文字を識別し、利用可能なテキストデータに変換する技術となります。すなわち、わざわざ人の手作業で実施している転記作業をOCRで自動化することが可能になります。
 Googleで提供されているOCR機能用のAPIはGoggle Vision APIとDriveを使った、Google Drive APIの2種類あります。Google Drive APIの方が実装が簡単に可能に見え、他の方の記事ですが、Google Drive APIの方が認識精度が高いこともあるようです。そこで、本記事ではGoogle Drive APIの実装をしていきます。

今回の設定条件

Google Drive APIをローカルで使えるようにする設定、および、コーディングはこのサイトを参考にしてください。
 また今回想定している業務フローを簡単にまとめます。
想定業務フロー
この転記部分のPDFから読み取る部分のOCRの実装と、読み取ったテキストから他資料に自動転記するコーディングをしていきます。
〇今回の必要ファイル

  • 認証設定後に取得可能なjsonファイル
  • 読み取り資料(今回はPDF資料)
    なお、読み取った出力内容のテキストファイルは読み取ったPDFファイルと同じフォルダに出力されます。また、読み取るPDFファイルは下記のような仮想の伝票を考え、今回は3ファイル分読み取ってみます。
    伝票1
    伝票2
    伝票3
    〇実行環境
    今回、jsonファイルはローカルで動かす必要があったため、Jupyter Notebookを使用します。
    〇その他必要項目
    GoogleアカウントとAPIの有効化などの設定(先程のurlを参考にしてください)

OCRの実装と認証

ローカルでGoogle Drive APIを使用するには、google_drive_ocrライブライをインストールする必要があります。

!pip install google_drive_ocr

上記ライブラリをインストール後、以下のコードを実行します。

OCRapp.py
from google_drive_ocr.application import GoogleOCRApplication
#カッコ内にjsonファイルを入れたローカルフォルダを指定
app = GoogleOCRApplication(r'C:\OCRDemo\OCRtest.json')

すると、urlが表示されるのでクリックし、googleアカウントへの認証を行います。認証ができたらOCRが使えるようになるので、以下のコードを実行します。今回は、特定のフォルダに置いた伝票3ファイルを読み取ることとします。

OCRperform.py
import pathlib
#ファイルパスの格納
path = 'C:\OCRDemo\demo\\'
file = '*.pdf'
file_list = pathlib.Path(path).glob(file)
for f in file_list :
    #OCRの実行
    app.perform_ocr(f)

上記を実行するとテキストができました。
テキストフォルダ
ここでは結果例として、伝票No.01と読取結果を示します。
読取結果
 上図より、各文字を取得できたことが分かります。枠で囲われていない箇所(伝票Noや業者等)は1行で表現され、枠で囲われている箇所は1ヶ所ずつ読み取られています。例えば、各品目番号の情報は、「品目番号、数量、単価金額、入荷予定日」の順番で5行で表現されています。他の出力内容を確認すると、
伝票2_読取結果
伝票3_読取結果
同じように出力されていることが分かります。このようにフォーマットの変更がなければ、ルールは同じなので自動転記も可能になります。そして、フォーマット変更時も一度テキスト出力しルールを把握すれば自動転記が可能になります。そこで、次節でExcelでの転記方法を考え、自動転記方法を実装していきます。

Excelへの転記方法

本記事では伝票情報はPOList.xlsxで管理され、後続の分析資料や他システムへのアップロード資料として使用していると想定します。該当Excelは以下のようなフォーマットで表現されているものとし、テキストの内容を転記するものとします。
Excelフォーマット
 まず、テキスト内容を保存します。以下のようなコーディングで実装できます。

readtxt.py
#テキスト名は、”読み取ったファイル名”.google.txtという名前になります。
txtfile = 'demo1.google.txt' 
txt_path = path + txtfile

po_data = []
with open(txt_path, encoding='utf-8-sig') as f:
    #テキスト内容を配列に格納
    po_data.extend(f.read().split())

#print(po_data)

結果は以下のようになります。(※間違えて、”単 価”としてしまっていたので、”単価”に直しています)
出力内容配列
 上記情報を基に、伝票で固定の基本情報である、伝票No、業者No、注文日の他、各品目番号の情報を保存していきます。

po_info.py
#伝票No.
po_no = po_data[1]
#業者No
po_company = po_data[7]
#注文日
po_date = po_data[5]
#品目番号情報リスト item_info_list
item_info_list = po_data[13:len(po_data[:-2])]
# item_info_listに格納するための変数
i = 0
list_num = 5
item_info_list = []

while i <= len(temp_info) - list_num :
  #各品目番号の情報リスト item_info
    item_info = [temp_info[i],temp_info[i+1],temp_info[i+2],temp_info[i+3],temp_info[i+4]]
    #print(item_info)
    #item_info毎に格納
    item_info_list.append(item_info)
    i += list_num

#print(item_info_list)

それでは、実際にExcelへの転記を行っていきます。

writeExcel.py
import openpyxl
#Excelファイル
xlsx_folder = 'C:\OCRDemo\demo\\'
file = 'POList.xlsx'
xlsx_path = xlsx_folder + file
#print(xlsx_path)

#Excelを開く
book = openpyxl.load_workbook(xlsx_path)
sheet = book.active

for i,(item,quantity,price,cost,day) in enumerate(item_info_list,1) :
    #最終行の取得
    write_row = sheet.max_row + 1
    #Excelへの転記
    sheet[f'A{write_row}'] = po_no
    sheet[f'B{write_row}'] = item
    sheet[f'C{write_row}'] = quantity
    sheet[f'D{write_row}'] = price
    sheet[f'E{write_row}'] = cost
    sheet[f'F{write_row}'] = day

#Excel保存
book.save(xlsx_path)

結果は以下の通りです。
転記結果
 ここでは伝票No.01のみの転記を行いましたが、実際には読み取ったテキストファイル全てにおいて転記作業を行うので、readtxt.py、po_info.py、writeExcel.pyをfor文で組み合わせる等の処理が必要になります。
 以上より、OCRで読み取った内容を転記する実装ができました。

おまけ(手書き文字と文章の認識)

今回の主目的ではありませんが、手書き文字や文章に対する精度が気になったので、やってみました。

手書き文字の認識

まず伝票が手書きであった際の精度です。今回は、何項目か記入ミスがあった際にどのように出力されるかも気になったので、以下のようなものを読み取ってみます。
 まず、以下の画像を読み取ってみます。
伝票4
 伝票04の内容は品目番号、数量、単価、金額に関して、同じ内容、かつ、結構雑に書いてみました。結果は以下の通りです。
伝票4_読取結果
 まず出力フォーマットが変わりました。これに関しては、私の自宅に手書き伝票をスキャンする機器がなく、コンビニで印刷した手書き伝票を携帯で撮った後、必要部分をPDF化したこともあり、転記作業で使ったPDFとはデータ上異なってしまったことが要因である可能性が高いように思うので、申し訳ありませんが、今回は変化理由の考察は保留にさせてください。
 出力内容については、大きな文字で書けた伝票Noや業者関連の文字は正確に読み取れているようです。しかしながら表部分については違いがみられます。
 品目番号に関して、1行目の品目番号「52157k70808A」では最初の「5」を「3」で読み取っています。これに関しては確かに「3」に見えます。また、「7078」に関して、1つ目の「7」を「1」に3つ目の「7」を読み取れていません。2行目の品番の「b」に関しても、「b」を「6」と読み取っています。
 数値に関しては、2行目の金額「7,970」を「2170」で読み取っています。おそらく、「7,」部分を「2」、「9」を「1」で読み取っているように思います。
記入ミスをした入荷予定日に関しては、最初の「/」を「1」で読み取って、「2/」を組み合わせて「4」で読み取っています。OCR内部プログラムのことは分かりませんが、他の入荷予定日の「/」の書き方から考えるに、黒塗りにしたことで日付として捉えられず、「1」と見なしてしまったということも考えられるような気がします。
 以上より、雑な文字に対する精度や修正文字列に対する精度を考えると、Google Drive APIで手書き文字を読み取る際には注意が必要であることが分かります。今後の記事では、Google Vision API(有料)や他のAPIとの比較もしてみたいです。

文章の認識

次は文章の認識をしていきます。認識内容は私の記事の最初の方を保存してPDF化したものとします。
文章PDF
 結果は以下の通りです。
文章読取結果
 結果を見ると、PDFで行が変わる部分(例、赤四角部分)は空白文字が入っていますが、読み取り内容としては問題ないことが分かります。

本記事のまとめ

本記事では、OCRを用いたPDF資料の転記作業の自動化方法を考えていきました。結果として、手書き文字ではなければ、Google Drive APIを用いて読み取り精度が高く、転記も間違えなくできることが分かりました。手書き文字については、Goggle Vision AIや他のAPIでの比較を今後していきたいです。
 また、文章においても読み取りが可能ということで、言語処理ができるAPIや機械学習手法と組み合わせることで、レポートの分析等他のことにも活用できると考えられるので、次回のOCR関連の記事はこちらを主題においてみたいと考えています。

参考文献

〇Google Drive API実装/Google APIについて
Pythonでgoogle-drive-ocrを使用し文字認識を行う
Google Drive APIでOCRをしよう!
光学式文字認識(OCR)のチュートリアル(google 公式ページ)
Google Cloud Vision APIのOCRを使ってPythonから文字認識する方法

〇Excel転記方法について
Python[完全]入門(Amazon url,書籍)
u'\ufeff' in Python string
【Python】最終行の行番号を取得する|OpenPyXL基礎

Discussion