Google Document AIで画像から表形式データを抽出する(Vision API OCRとの違い)

本記事では、GoogleのDocument AIを利用して、表形式(テーブル形式)で記載された画像から、表形式の情報を抽出してみます。また、GoogleのVision API OCRを利用した場合との違いについてもみておきます。

【目次】

[1]はじめに

Google Vision APIを利用すると、画像から文字を抽出(OCR)できます。

Vision APIは、本などの文章の画像や、風景の画像から文字を抽出するといったケースでは、かなりいい感じで文字を抽出してくれます。文章が書かれているような画像の場合は、画像から文字を抽出するだけでなく、大雑把に文書の構造も得ることができます。

しかし、Vision API OCRでは期待した抽出が難しい例もあります。
例えば、下図のような、よくある表形式で書かれた書類です。


文章の画像は、隣接する文字の塊を抽出するだけでも、期待した文章が抽出できることが多いと思います。
しかし、上図のような表形式の書類は、隣接した文字の塊を抽出するだけでは利用価値が低い場合が多く、表形式のデータとして認識する必要があります。

表形式の書類は、人間が見れば、表組の意味を理解して要点を把握しやすい表現だと思います。例えば、「2021/2/2のお菓子の値段は300円であり、同日のお弁当は1,000円」云々と文章でつらつら書かれるより分かりやすいです。

一方で、これを機械的に認識しようとすると、単語レベルの文字列が散らばって配置されているレイアウトのようにも見えて、解釈が難しい場合が多いです。実際、汎用目的の機械的な表の認識を行うことは難しい問題です。

これに対して、Googleは、現状はプレビュー版(2021年2月現在)ですが、Document AIというサービスをを公開しています。これは、画像から表形式のデータを抽出できるとされています。

そこで、本記事では、Document AIの表形式データの抽出と、Vision API OCRの認識結果を比較することで、その違いを見ていきたいと思います。

(注意)
本記事は、ベータ版のDocument AIについて書いているため、正式リリース版では結果が異なる可能性があります。

[2]Document AIとVision API(OCR)の違い

Document AIの情報(ガイドやリファレンス)は以下のサイトにあります。

Document AIも文書から情報を抽出するものですが、私なりにVision API(OCR)とDocument AIの違いについて考えてみました。

<Vision API(OCR)>
  • 汎用目的のOCRであり、文書や風景を問わず、画像の中にある文字を抽出することを基本としたサービス。
    • 文章構造を認識することもできますが、どちらかというとレイアウト的な構造と考えたほうがよいと思います。
<Document AI>
  • 文書画像に特化したサービスで、文字の抽出から一歩踏み込んで、意味的な情報抽出を行うもの。
    • 具体的には、汎用的なフォーム情報(キー・バリューでの情報抽出)や表形式(テーブル)情報のような、少し意味を持った構造的情報を抽出します。その延長として請求書などのより分野特化した解析サービスもあります。
  • GoogleのVision API(OCR)やNatural Language APIをビルディングブロックとして利用しており、お互い関連したサービスである。
    • OCRのような技術的目標ではなく、ユーザよりの業務自動化が目標と思われます。また、1つの大きなDocument AIとしてサービスを構成せず、特定の業務向けのプロセッサを用意することで様々な業務に対応することが想定されているように感じます。

こう考えると、業務システムなどの具体的なシステムと連携させるには、Vision APIなどの低レベルサービスよりも、Document AIのような高レベルサービスを利用するほうが便利なようにも思えます。
しかし、Document AIを利用しなくても十分解析ができるものもありますし、画像によっては独自の解析アルゴリズムを利用した方がDocument AIより性能が良い場合もあるかもしれません。

ということで、これらはどちらを使うべきか?、ということではなく、ケースバイケースで使い分けるもののような気がします。(料金の違いもあるし。。。)

今回は表形式の情報抽出という観点で、Vision APIとの対比を通して Document AI を見てみます。

(参考)
Document AIのうち、主にフォーム解析については、技術記事(論文も)があります。

[3]テスト用の表形式画像

本来は紙文書をスキャンしたテスト画像がよいとは思いますが、文字の読み取り精度の違いではなく、抽出される情報の違いを中心に見るために、スプレッドシートで作った画像をサンプルとして利用することにしました。

(1)英語版表形式画像(shoppinglist.jpg)


(2)日本語版表形式画像(okaimonolist.jpg)



(3)PDFファイルへの変換

Document AIへの入力は、PDFファイルとなっています。Vision APIもPDFファイルを解析できますので、条件を合わせるため、上記二つのJPEGファイルを、img2pdfを利用してPDFファイルに変換して利用します。

img2pdf  -o  kaimonolist.pdf   kaimonolist.jpg
img2pdf  -o  shoppinglist.pdf  shoppinglist.jpg

img2pdfを利用した変換方法については以下の記事を参考にしてください。

[4]Vision APIによる表形式画像の認識

(1)実験方法

今回はPDFファイルを入力としてVision APIのドキュメントテキスト検出(DOCUMENT_TEXT_DETECTION)を実行してみます。

<実行コード>
def batch_annotate_file(pdf_file):
  from google.cloud import vision
  
  import io
  with io.open(pdf_file, 'rb') as image_file:
    binary_content = image_file.read()

  req = {
    'input_config': {'content': binary_content, 'mime_type': 'application/pdf'},
    'features': [{'type_': vision.Feature.Type.DOCUMENT_TEXT_DETECTION}],
    'pages': [1]
  }

  client = vision.ImageAnnotatorClient()
  return client.batch_annotate_files(requests=[req])

(参考)
Vision APIの利用方法については、以下の記事も参考にしてください。

(2)英語版表形式画像の認識結果

以下のコードを実行して、shoppinglist.pdfから抽出したテキストを表示してみます。
response_sl = batch_annotate_file('shoppinglist.pdf')
print(response_sl.responses[0].responses[0].full_text_annotation.text)

<抽出されたテキスト>
Shopping List
Price
Date
Description
2021/2/1 Sweets
2021/2/1 Bento
$300.00
$1,000.00
$0.00
$1,300.00
2021/2/2 TechnoDaifukucho
Total

正確に文字は抽出されていますが、期待した結果とは少々違うと思います。

どのように解釈されているのか、解析情報を可視化してみます。
まず、full_text_annotationのBlock, Paragraph, Wordを表示してみます。
Page[0]
*Block[0]
   Paragraph[0]
     Word[0]=Shopping
     Word[1]=List
*Block[1]
   Paragraph[0]
     Word[0]=Price
*Block[2]
   Paragraph[0]
     Word[0]=Date
   Paragraph[1]
     Word[0]=Description
     Word[1]=2021/2/1
     Word[2]=Sweets
     Word[3]=2021/2/1
     Word[4]=Bento
*Block[3]
   Paragraph[0]
     Word[0]=$
     Word[1]=300.00
     Word[2]=$
     Word[3]=1,000.00
   Paragraph[1]
     Word[0]=$
     Word[1]=0.00
     Word[2]=$
     Word[3]=1,300.00
*Block[4]
   Paragraph[0]
     Word[0]=2021/2/2
     Word[1]=TechnoDaifukucho
*Block[5]
   Paragraph[0]
     Word[0]=Total

続いて、BlockとWordの矩形を表示してみます。(BlockはGreen、WordはRedです。)


これを見ると、文字の塊はちゃんと認識されており、なぜ先のようなテキスト抽出結果になったかが何となく分かります。そして「表形式」を意識したブロックの認識ではないことも分かります。

しかし、今回の抽出結果のテキストから、例えば、「2021/2/1のSweetsのPriceの値は?」に答えようとすると、かなり難しいです。
これに答えるためには、抽出結果のテキストを利用するのではなく、Block、Paragraph、Word、Symbolの情報から表形式構造を認識する処理を行う必要があります。
(もっとも、今回のような文書の形が予め決まっている場合、解釈処理の実装は難しくない場合もあります。)

但し、表形式の情報抽出が目的ではなく、文書に現れる単語の抽出だけが目的の場合は、今回の結果でも十分役に立ちます。

(3)日本語版表形式画像の認識結果

続いて、以下のコードを実行して、kaimonolist.pdfから抽出したテキストを表示してみます。
response_kl = batch_annotate_file('kaimonolist.pdf')
print(response_kl.responses[0].responses[0].full_text_annotation.text)

<抽出されたテキスト>
お買い物リスト
金額
¥300
日付
品目
2021/2/1|お菓子
2021/2/1|お弁当
2021/2/2|テクノ大福帳
合計
¥1,000
¥0
¥1,300

予想通り、結果は英語版と同様で、文字はほぼ正確に抽出されていますが、期待した結果とは違うと思います。
(ちなみに、今回は日付の後に文字「|」が抽出されています。これは英語版にはありませんでしたが、罫線を「|」と認識したのかもしれません。)

こちらも、どのように解釈されているのか、解析情報を可視化してみます。
まず、full_text_annotationのBlock, Paragraph, Wordを表示してみます。
Page[0]
*Block[0]
   Paragraph[0]
     Word[0]=お
     Word[1]=買い物
     Word[2]=リスト
*Block[1]
   Paragraph[0]
     Word[0]=金額
*Block[2]
   Paragraph[0]
     Word[0]=¥
     Word[1]=300
*Block[3]
   Paragraph[0]
     Word[0]=日
     Word[1]=付
   Paragraph[1]
     Word[0]=品目
     Word[1]=2021/2/1
     Word[2]=|
     Word[3]=お菓子
     Word[4]=2021/2/1
     Word[5]=|
     Word[6]=お
     Word[7]=弁当
     Word[8]=2021/2/2
     Word[9]=|
     Word[10]=テクノ
     Word[11]=大福帳
   Paragraph[2]
     Word[0]=合計
*Block[4]
   Paragraph[0]
     Word[0]=¥
     Word[1]=1,000
*Block[5]
   Paragraph[0]
     Word[0]=¥
     Word[1]=0
*Block[6]
   Paragraph[0]
     Word[0]=¥
     Word[1]=1,300

続いて、BlockとWordの矩形を表示してみます。(BlockはGreen、WordはRedです。)


ブロックの認識結果が英語版と少し異なるところが興味深いです。。。

[5]Document AIによる表形式画像の認識


(追記:2021/7/14、2021/7/19)
Pythonクライアントライブラリを利用してDocument AIを利用する記事を書きました。
よろしければご覧ください。

(1)実験方法

本来はGCPのプロジェクト設定やクライアントライブラリを用意して Document AI の実験をしたいところですが、まだベータ版であることから、今回はお手軽に試す方法を利用します。
(実は課金も気になったので以下の無料で試す方法を利用しました。Vision APIは無料枠があるので、お気軽に試せるのですが。。。)

以下のサイトで Document AI による解析を無料で試すことができます。

このページの「Try it now」の下にある領域にPDFファイルをドラッグ&ドロップすると解析結果が表示されます。

今回はGeneralを選択して解析します。
解析結果は、以下の4つのタブで確認することができます。
  • key value pairs
  • Tables
  • OCR text
  • JSON

今回は「表形式」のテスト画像ですので、Tablesタブを選択すると、テーブル解析の結果を見ることができます。(しかも可視化してくれてます!)

さらに、JSONタブから、Document AIのレスポンスデータをダウンロードすることもできます。

以下では、Vision APIのテストと同じPDFファイルを「Try it now」で解析して、JSONタブからダウンロードしたレスポンスデータを利用して結果を確認します。

なお、JSONファイルの仕様は以下を参考に解釈しました(現時点では、v1beta3のようです)。

(2)英語版表形式画像の認識結果

まず、レスポンスのtextフィールドの値を見てみます。
Shopping List
Price
$300.00
Date
Description
2021/2/1 Sweets
2021/2/1 Bento
2021/2/2 TechnoDaifukucho
$1,000.00
$0.00
$1,300.00
Total

textフィールドの値は、Vision APIの結果と大差ありません。

しかし、レスポンスにはページ毎にtablesフィールドがあり、HTMLのTABLEタグと同様の構成でテーブル解析の結果を得ることができます(各セルの値は上記textフィールドの文字インデックスの範囲で与えられます)。

このtablesフィールドから、以下の情報が得られます。


DateDescriptionPrice
2021/2/1Sweets$300.00
2021/2/1Bento$1,000.00
2021/2/2TechnoDaifukucho$0.00
Total$1,300.00

さらに、レスポンスには画像も返却されていますので、これにtablesのセル領域を描画すると、ちゃんと表領域が認識されていることがわかります。
(以下の画像は、返却された画像に、headerRowsをRED、bodyRowsをGREENで描画して、テーブル付近のみ切り出したものです。)


tablesフィールドの情報を利用すると、2021/2/1のSweetsのPriceの値を答えることができます。
これは凄いです。。。

(3)日本語版表形式画像の認識結果

まず、レスポンスのtextフィールドの値を見てみます。
SECURE
¥300
AB
2021/2/17
2021/2/15
2021/2/2 itt
Ait
¥1,000
¥0
¥1,300

残念ながら、現状のプレビュー版では、まだ日本語対応ができていないようです。
(現状では、リージョンもUSかEUしか利用できないようです。もしかしたらAPIから何らかのパラメータを指定すると解析できるのかもしれませんが、試していません。。。)

ところで今回の主題とは関係ありませんが、日本語に対応していないという前提で、認識結果がABとかAitとなるのは受け入れやすいですが、SECUREという意味ありげな認識は。。。

さて、同様に、tablesフィールドのテーブル情報もみておきます。

AB
2021/2/17¥300
2021/2/15¥1,000
2021/2/2itt¥0
Ait¥1,300


日本語は解析できていないものの、テーブルの枠組みは認識できています。
これも凄いです。。。
正式リリースになって、さらに日本語に対応する時が楽しみになってきました。

[6]最後に

まだプレビュー版だし、簡単な表形式の画像を試しただけではありますが、Document AI は凄そうだと感じました。今回はテーブル認識だけを取り上げましたが、フォーム解析など、その他の機能もあります。

正式リリースになったら、ちゃんと試してみたいと思いました。
同時に、その元になるVision APIやNatural Language APIのモデルも更新されて良くなっていくと思いますので、こちらも楽しみです。

コメント

このブログの人気の投稿

VirtualBoxのスナップショット機能

Ubuntu/Colab環境でPDFファイルのページを画像化する(pdf2image、pdftoppm、pdftocairo)