初学者向け「Amazon Textract」(AIドキュメント分析サービス)をPythonで利用するにはAWSチートシート

AWS活用における便利な小技を簡潔に紹介する連載「AWSチートシート」。今回は、AWSのAIドキュメント分析サービス「Amazon Textract」をPythonで利用する方法を紹介する。

» 2021年12月02日 05時00分 公開
[金晟基東京ITスクール]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

 「Amazon Web Services」(AWS)活用における便利な小技を簡潔に紹介する連載「AWSチートシート」。今回は、AWSのAIドキュメント分析サービス「Amazon Textract」をPythonで利用します。以下、Amazon Textractに用意されているメソッドを概観し、幾つかの使い方を紹介します。

「Amazon Textract」とは

 AWSには、事前トレーニング済みのAI(人工知能)を手軽に利用できる「AIサービス」が多数用意されており、その内容はコンピュータビジョン、言語、レコメンデーション、予測と多岐にわたります。

 今回紹介するAmazon Textract(以下、Textract)は、スキャンされたドキュメントから活字と手書き文字を認識し、表や書式などの構造化された情報もテンプレートなしで検出するサービスです。これによって、人による入力作業や単純な光学文字認識(OCR)ソフトウェアを使用した場合に比べて、データをより迅速かつ柔軟に抽出できるようになります。

Amazon Textract

 肝心の対応言語ですが、Textractは日本語には現在未対応です。活字で認識可能な言語は、英語、スペイン語、イタリア語、フランス語、ポルトガル語、ドイツ語、手書き文字で認識可能なのは、英語のアルファベットとASCII記号です。現時点で日本語未対応なのが残念なところですが、今後のアップデートを見据えた記事として、または、現在対応中の言語での利用を想定した記事として、本稿を参照してください。

AWSの「AIサービス」はコンソール画面から利用できますが、開発を念頭に置かなくても、慣れてくれば今回のようにAPIを利用する方がより便利で効率的に感じてくるでしょう。本稿がそのように利用するきっかけになれば幸いです。


利用料金について

 Textractは従量課金制で、用途に応じた4つのAPI操作に対して異なる料金が設定されています(Textractは東京リージョンと大阪リージョンでは提供されていないので、以下では参考としてバージニア北部リージョンの料金を掲載します)。

1.「Detect Document Text API」は、活字と手書き文字を認識します。最初の100万ページまでは1ページ当たり0.0015ドル(米ドル、以下同)、100万ページを超えると1ページ当たり0.0006ドルになります。

2.「表用Analyze Document API」は、活字と手書き文字の認識に加えて、表の構造を検出します。最初の100万ページまでは1ページ当たり0.015ドル、100万ページを超えると1ページ当たり0.01ドルになります。

3.「フォーム用Analyze Document API」は、活字と手書き文字の認識に加えて、書式における「キー」と「値」のペア(例えば、【姓】という「キー」と、対応する【山田】という「値」など)構造を検出します。最初の100万ページまでは1ページ当たり0.05ドル、100万ページを超えると1ページ当たり0.04ドルになります。

4.「Analyze Expense API」は、請求書や領収書から各項目と対応する値のペアを検出します(現在は英語のみ対応)。最初の100万ページまでは1ページ当たり0.01ドル、100万ページを超えると1ページ当たり0.008ドルになります。

 なおTextractは無料利用枠の対象になっており、最初のリクエストから3カ月間は1カ月当たりDetect Document Text APIを使用して1000ページまで、Analyze Document APIまたはAnalyze Expense APIを使用して100ページまで無料で分析することができます(ただし、無料利用枠を超えた場合には従量課金が適用されます)。

 ちなみに、上記における「ページ」とは、PNGまたはJPEGにおける画像1枚のことです。仮に1枚のスキャンイメージに複数のページあったとしても、Textractでは1ページと認識されます。PDFとTIFFの場合は、ドキュメントの各ページが処理されたページとしてカウントされます。

必要条件

 本稿では、読者の環境で下記要件が満たされていることを仮定しています。

  • AWSアカウントを有しており、「AWS Identity and Access Management」(IAM)ユーザーに必要な権限(今回ならAmazon Textract関連)が付与されていること
  • ホームディレクトリにAPIを利用するための認証情報が保存されていること
  • AWSが提供するPython用のSDK「Boto3」がインストールされていること

 なおこれは必須ではありませんが、以下のサンプルコードは「Jupyter Notebook」での実行を想定しています。

メソッド一覧

 Textractには以下のメソッドが用意されています。

メソッド名 機能 引数 戻り値
detect_document_text 入力ドキュメント内の文字を認識する ドキュメントデータ 辞書
analyze_document 入力ドキュメント内で検出されたアイテム間の関係を解析する ドキュメントデータ、FeatureTypes値、HumanLoop構成 辞書
analyze_expense 請求書や領収書を解析する ドキュメントデータ 辞書
start_document_text_detection 入力ドキュメント内の文字を認識する非同期処理を開始する ドキュメントデータ、ClientRequestトークン、JobTag、通知チャネル設定、出力構成、KMSキーID 辞書
get_document_text_detection start_document_text_detectionで開始したジョブの結果を取得する JobID、NextToken、レスポンスの最大値 辞書
start_document_analysis 入力ドキュメント内で検出されたアイテム間の関係を解析する非同期処理を開始する ドキュメントデータ、FeatureTypes値、ClientRequestトークン、JobTag、通知チャネル設定、出力構成、KMSキーID 辞書
get_document_analysis start_document_analysisで開始したジョブの結果を取得する JobID、NextToken、レスポンスの最大値 辞書
start_expense_analysis 請求書や領収書を解析する非同期処理を開始する ドキュメントデータ、ClientRequestトークン、JobTag、通知チャネル設定、出力構成、KMSキーID 辞書
get_expense_analysis start_expense_analysisで開始したジョブの結果を取得する JobID、NextToken、レスポンスの最大値 辞書
can_paginate 各メソッドのページネーション有無を調べる メソッド名 真偽値

 幾つか解説します。

 Textractがサポートするファイル形式は、同期処理ではJPEGとPNGが、非同期処理ではこれらに加えてPDFとTIFFがあります。また、非同期処理ではPDFとTIFFで複数ページの書類を分析できます。

 同期処理では、API実行時にドキュメントのバイトデータを直接渡す方法(最大5MB)と、Amazon S3バケットに保存されているオブジェクトを指定する方法(最大5MB)があります(本稿では全て前者で実行することにします)。一方で非同期処理では、S3バケットに保存されているオブジェクトを指定します。なお、S3バケットはTextractを呼び出す際のAPIエンドポイントと同じリージョンに作成する必要があります。

 Textractを使用してドキュメントから「ページ」「行」「単語」などの要素が検出されると、それらの情報は全て「Block」という共通の単位で、戻り値に記載されます。このBlock情報には、個別に割り振られたIDやバウンディングボックス情報、その要素に対する子要素の情報なども記載されています。逆に、戻り値に含まれる各「Block」がどの要素を指すのかについては、各Block情報内のBlockTypeキーの値を参照することになります。その値は、「ページ」では「PAGE」、「行」では「LINE」、「単語」では「WORD」です。なお「WORD」は「LINE」の子要素、「LINE」は「PAGE」の子要素です。

 ここからは、Textractのメソッドの使い方を幾つか紹介します。

detect_document_textメソッド

 最初に紹介するdetect_document_textメソッドは、入力ドキュメント内の文字情報を認識します。以下ではサンプルドキュメントとして、2016年にオバマ米国大統領が共和党のMark Kirk上院議員(ともに当時)に送った手紙を使用します。

引用元:Wikimedia Commons:https://commons.wikimedia.org/wiki/File:US_President_Obama_letter_to_Senator_Mark_Kirk_on_meeting_with_Merrick_Garland.jpg(Public domain))

 認識対象となる活字と手書き文字のターゲットは下記の通りです。

The White House

Washington

Mark -

Thank you for your fair and responsible

treatment of Merrick Garland. It upholds

the institutional values of the Senate, and helps

preserve the bipartisan ideals of an independent

judiciary.

Barack Obama


 内容は、Kirk上院議員がMerrick Garland氏(オバマ大統領が連邦最高裁判所判事候補に指名。共和党の反対で結果的に就任できず)と面会したことに対して、感謝を伝えるものです。

import boto3
 
# Textractクライアントを作成
textract = boto3.client('textract', 'us-east-1')
 
# テキスト検出を行う関数
def detect_document_text(document):
 
    # テキスト検出を実行
    with open(document, 'rb') as img:
        response = textract.detect_document_text(Document={'Bytes': img.read()})
 
    # Block情報から「行」を取り出して出力
    for Block in response['Blocks']:
        if Block['BlockType'] == 'LINE':
            print(Block['Text'])
 
 
# 入力画像のパス
input_file = ('US_President_Obama_letter_to_Senator_Mark_Kirk_'
              'on_meeting_with_Merrick_Garland.jpeg')
 
# テキスト検出
detect_document_text(input_file)

THE WHITE HOUSE

WASHINGTON

Mark- -

Thank you for your fair and responsible

treatment of Merrick Garland. It upholds

the institutional values of the Senase, and help

preserve the bipartison ideals of an independent

judician.


 活字の行はもちろん、手書きによる崩し字の行もおおむね正しく認識できました。

 しかしながら、細かく結果を確認すると、認識ミスも幾つかありました。誤認識があった箇所としては、「judiciary」の「ry」が「n」に、「Senate」の「t」が「s」に、「bipartisan」の「a」が「o」になったものがあり、認識漏れがあった箇所としては、helpsのsの欠落がありました。

 ここで特に気になったのは、このように認識ミスした単語の中で、judiciaryとSenateに該当するWORDの信頼度はそれぞれ43%、72%と低かったのに対して、bipartisanとhelpsの信頼度はそれぞれ92%、99%と高かった点です。信頼度が低いものについては、しきい値を設定し、フラグが立ったものをヒューマンレビューに回す運用が考えられます。

 ただ今回の結果を踏まえると、信頼度にかかわらず認識された単語や行に対してスペルチェックや文法チェックをかけることもユースケースによっては必要になると考えられます。

analyze_documentメソッド

 analyze_documentメソッドを用いて、文章から表や書式の構造を検出します。このメソッドは、引数「FeatureTypes」に「TABLES」か「FORMS」、またはその両方をリストとして与えることで、ドキュメントから表か書式、またはその両方の情報を検出します。

 ドキュメントのサンプルは、Parcelforce Worldwide社が顧客に送付した、輸入小包の関税処理に関する請求書を使用します。

引用元:Wikimedia Commons:https://commons.wikimedia.org/wiki/File:Parcelforce_Import_Charge_Invoice.jpg(Public domain)

 下記サンプルコードでは、結果の視認のために、表については検出された「表」全体とそれらを構成する「マス」に対して、書式については検出された「キー」と「値」のペアに対して、バウンディングボックスの情報を基にその領域を描画させます。

バウンディングボックスについては、記事『初学者向け「Amazon Rekognition」(AI画像/動画分析サービス)をPythonで利用するには』を参照してください。


from PIL import Image, ImageDraw
 
# 画像にバウンディングボックスを重ねる際に使用する関数
def draw_bbox(draw, bbox, img_width, img_height, color):
    
    # バウンディングボックスの値を重ねる画像の大きさにスケーリング
    left = img_width * bbox['Left']
    top = img_height * bbox['Top']
    width = img_width * bbox['Width']
    height = img_height * bbox['Height']
 
    # 枠線の太さを設定
    line_width = 3 if color == 'red' else 1
 
    # バウンディングボックスの描画
    draw.rectangle([left, top, left + width, top + height],
                   outline=color,
                   width=line_width)
 
 
# ドキュメントの解析を行う関数
def analyze_document(document, feature_types):
    # ドキュメントの解析を実行
    with open(document, 'rb') as img:
        response = textract.analyze_document(
                                Document={'Bytes': img.read()},
                                FeatureTypes=feature_types)
 
    # 画像データの読み出し
    image = Image.open(document)
    # サイズ(ピクセル)情報を取得
    img_width, img_height = image.size
    # 描画のためのインスタンスを生成
    draw = ImageDraw.Draw(image)
 
    # Block情報の取得
    for block in response['Blocks']:
 
        # 「表」
        if block['BlockType'] == 'TABLE':
            # バウンディングボックス情報を取得
            bbox = block['Geometry']['BoundingBox']
            # バウンディングボックスを描画
            draw_bbox(draw, bbox, img_width, img_height, 'red')
 
        # 「マス」
        if block['BlockType'] == 'CELL':
            # バウンディングボックス情報の取得
            bbox = block['Geometry']['BoundingBox']
            # バウンディングボックスを描画
            draw_bbox(draw, bbox, img_width, img_height, 'green')
 
        # 「キー」と「値」
        if block['BlockType'] == "KEY_VALUE_SET":
            # バウンディングボックス情報を取得
            bbox = block['Geometry']['BoundingBox']
            if block['EntityTypes'][0] == "KEY":
                # 「キー」のバウンディングボックスを描画
                draw_bbox(draw, bbox, img_width, img_height, 'red')
            else:
                # 「値」のバウンディングボックスを描画
                draw_bbox(draw, bbox, img_width, img_height, 'green')
 
    # 結果を表示
    display(image)

 まず、表構造の検出を念頭に、FeatureTypesの値にTABLESを指定して、analyze_documentメソッドを実行します。

# ドキュメントのパス
input_file = '523px-Parcelforce_Import_Charge_Invoice.jpeg'
 
# FeatureTypes値
input_feature_types = ['TABLES']
 
# 解析を実行
analyze_document(input_file, input_feature_types)
引用元:Wikimedia Commons:https://commons.wikimedia.org/wiki/File:Parcelforce_Import_Charge_Invoice.jpg(Public domain)

 ドキュメントから「表」(赤色)とそれを構成する「マス」(緑色)が正しく検出されました。

 なお今回のメソッドの戻り値には、テキストの認識結果に加え、これらの表に関する検出要素の情報がBlock情報として追記されています。BlockTypeキーの値はそれぞれ、「表」がTABLE、各「マス」がCELLです。CELLはTABLEの子要素です。CELLの子要素にはWORDが含まれます。CELLのBlock情報には、その「マス」が「表」の何行何列目にあるかといった情報なども記載されています。

 最後に、書式構造の検出を念頭に、FeatureTypesの値にFORMSを指定して、analyze_documentメソッドを実行します。

# ドキュメントのパス
input_file = '523px-Parcelforce_Import_Charge_Invoice.jpeg'
 
# FeatureTypes値
input_feature_types = ['FORMS']
 
# 解析を実行
analyze_document(input_file, input_feature_types)
引用元:Wikimedia Commons:https://commons.wikimedia.org/wiki/File:Parcelforce_Import_Charge_Invoice.jpg(Public domain)

 一部誤検出はあるものの、基本的には書式から望ましい「キー」(赤色)と「値」(緑色)のペアが検出されました。今回のメソッドの戻り値には、テキストの認識結果に加え、これら書式要素の情報もBlock情報として記載されています。

 ただし、これらのBlockTypeキーの値はどちらも「KEY_VALUE_SET」というもので、これだけではどちらが「キー」で、どちらが「値」なのか見分けられません。それを見分けるのは、これらのBlock情報に加わるEntityTypesキーです。その値は、「キー」の場合はKEYに、「値」の場合はVALUEになります。

 なお、「キー」のブロック情報には、関係要素として対応する「値」のIDが含まれます。「キー」と「値」の「Block」は、子要素としてWORDを含んでいます。

最後に

 画像から文字情報と、表や書式などの構造化された情報をテンプレートなしで抽出できると、入力作業の大幅な軽減につながります。また、画像を内容に関して検索可能にすることもできます。興味を持った方は公式ドキュメントを参考にしながら、ぜひいろいろと試してみてください。

筆者紹介

金 晟基(キム ソンギ)

株式会社システムシェアード

東京ITスクールでJava研修の講師、IT専門学校の教材、カリキュラム開発、一般社団法人とのプログラミング教育を通じた国際貢献事業などを担当。AWS認定資格は「機械学習 - 専門知識」など


Copyright © ITmedia, Inc. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。