【Python】GoogleDriveAPIでOCR処理(テキストファイル出力)

概要

GoogleDriveAPIを利用して、画像からOCR処理でテキスト抽出していきます。
(GoogleDriveでは画像をグーグルドキュメントとして保存するとOCRがかかります)

なぜOCR目的でわざわざGoogleDriveを使用するかというと、精度が良いからです。
Pythonでは他にTesseractOCRやEasyOCRがありますが、精度がイマイチです。
他にもWindows.Media.Ocrも試してみましたが、上記よりは多少マシといった感じです。
日本語でなければ問題ないと思いますが・・・

ちなみにGoogleのOCRは「GoogleVisionAPI」と「GoogleDriveAPI」がありますが、
「GoogleVisionAPI」は有料になります。精度はこちらのほうが良いみたいですが。

GoogleDriveAPIの準備

GoogleDriveAPIについては下記参照。
割り当て数の上限はありますが、無料で利用することが出来ます。

事前準備のためにGoogleDriveAPIを有効にする必要があります。
詳細は下記参照。

また以下のモジュールのインストールが必要になります。

pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib

サンプルコード

クイックスタートにある「quickstart.py」をベースに改造しました。
処理の流れとしては以下の通りです。

①GoogleDriveAPIを使用してGoogleDriveに接続
②GoogleDriveに画像をgdoc形式としてアップロード(同時にOCR処理が実施される)
③gdocをtxt形式でエクスポート
④アップロードしたgdocを削除

画像ファイルをgdoc形式指定でアップロードすることや、テキスト形式でダウンロードする記述方法が、
情報が少なく苦戦しました。


import os.path
import io
import matplotlib.pyplot as plt

from PIL import Image
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from apiclient.http import MediaFileUpload
from googleapiclient.http import MediaIoBaseDownload


def main():
    # ======================================
    # メイン処理
    # ======================================

    # Google Drive接続処理
    service = get_service()

    # OCR対象設定
    input_file = r'C:\sample.png'

    # Google Drive Upload
    upload_result = upload(service, input_file)

    # OCR結果出力定義
    output_file = r'output.txt'

    # Google Drive Download
    download_result = download(service, upload_result['id'], output_file)


def get_service():
    # ======================================
    # Google Drive接続処理
    # Google公式「quickstart.py」参考
    # https://developers.google.com/drive/api/quickstart/python?hl=ja
    # ======================================

    creds = None

    # GoogleDrive全権限
    SCOPES = ["https://www.googleapis.com/auth/drive"]

    if os.path.exists("token.json"):
        creds = Credentials.from_authorized_user_file("token.json", SCOPES)

    if not creds or not creds.valid:
        # Tokenの有効期限が切れていれば更新
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                "credentials.json", SCOPES
            )
            creds = flow.run_local_server(port=0)
        with open("token.json", "w") as token:
            token.write(creds.to_json())
    service = build("drive", "v3", credentials=creds)
    return service


def upload(service, input_file):
    # ======================================
    # Google Drive Upload
    # ======================================

    # -----ローカルファイル定義-----
    # ファイル種類
    # https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
    Local_MIME_TYPE = 'image/png'
    media_body = MediaFileUpload(
        input_file,
        mimetype=Local_MIME_TYPE,
        resumable=True
    )

    # -----GoogleDriveファイル定義-----
    # ファイル名
    newfile = 'output'

    # ファイル種類(OCRを行うためGoogle ドキュメントとする)
    # https://developers.google.com/drive/api/guides/mime-types?hl=ja
    Google_MIME_TYPE = 'application/vnd.google-apps.document'

    # -----アップロード実行-----
    # 同時にOCR読み取りも行う
    # https://developers.google.com/drive/api/reference/rest/v3/files/create?hl=ja
    output = service.files().create(
        body={'name': newfile, 'mimeType': Google_MIME_TYPE},
        media_body=media_body,
        # OCR言語の指定を行う(ISO 639-1コード)
        ocrLanguage='ja',
    ).execute()

    return output


def download(service, id, output_file):
    # ======================================
    # Google Drive Download
    # ======================================

    # -----GoogleDriveファイル定義-----
    request = service.files().export_media(
        # ファイルID指定
        fileId=id,
        # エクスポートファイル種類
        # https://developers.google.com/drive/api/guides/ref-export-formats?hl=ja
        mimeType="text/plain"
    )

    # -----ダウンロードファイル設定-----
    fh = io.FileIO(output_file, "wb")
    downloader = MediaIoBaseDownload(fh, request)

    # -----ダウンロード実行-----
    done = False
    while done is False:
        status, done = downloader.next_chunk()

    # -----Google Drive上のfile削除-----
    service.files().delete(fileId=id).execute()


if __name__ == "__main__":
    main()

備考

「GoogleDrive API OCR」で検索すると以下のライブラリがヒットしますが、
google-drive-ocr 0.2.6 Mar 2, 2022で更新日が古く使用できないようです。残念。

!pip install google_drive_ocr