Postmanを利用してGoogle Document AIを試してみる
今回のゴール
レシートのデータを Google Document AI を利用して解析をして買い物した品目と値段を取得する。
事前準備
- Postman のインストール(記事作成には Version 11.37.5 (11.37.5)を使用)
- Google Cloud Platform のアカウント作成
- Google Cloud Platform のプロジェクト作成
- Document AI API の有効化
今回は上記の準備を行なった前提で進めいていきます。
参考記事
本編
Document AI のプロセッサの作成
画像で赤矢印で示している部分に「Document AI」というふうに入力すると候補に Document AI のページが出てくるのでクリックします。
次に Document AI のプロセッサーを作成します。
プロセッサを確認というボタンをクリックするとプロセッサーギャラリーが表示され、様々なプロセッサーがあることが確認できます。
汎用性の高いものや目的に特化したプロセッサーなど様々なものがありますが、今回は「Expense Parser」を利用します。
Expense Parser
の「プロセッサを作成」をクリックします。
プロセッサを作成するのに必要な入力欄が表示されるので、それぞれ入力します。
- プロセッサ名: 任意の名前を入力
- リージョン:US か EU しか選べないので、どちらかを選択
作成できるとプロセッサの詳細画面が表示されるので、予測エンドポイントという項目に表示されている URL をコピーして Postman の API 呼び出し対象の URL にペーストします。
Postman での設定
以下は公式ドキュメントより引用
"skipHumanReview": skipHumanReview, "rawDocument": { "mimeType": "MIME_TYPE", "content": "IMAGE_CONTENT" }, "fieldMask": "FIELD_MASK", "processOptions": { "individualPageSelector" { "pages": [INDIVIDUAL_PAGES] } } }
このような形式でリクエストボディをつける必要があります。
意味は以下のような感じです。
skipHumanreview: 人間がレビューをスキップするかどうかのフラグ
rawDocument/mimeType: 画像の MIME タイプ(image/jpeg や image/png など)
rawDocument/content: 画像の base64 エンコードしたもの
fieldMask: 取得したい情報のフィールドを指定する
processOptions/individualPageSelector/pages: 取得したいページを指定する
以下のようにセットしてください
SkipHumanReview | true |
mimeType | ここはエンコードする画像によって変更してください |
content | ここは base64 エンコードした値を入れてください |
fieldMask | text,entities,pages.pageNumber |
pages | 1 |
画像の base64 エンコードは以下のコマンドで実行できます。
base64 -i image.jpg | pbcopy
一旦リクエストしてみましょう。
おそらく 401 エラーが帰ってくると思います。
このエラーを見ると OAuth2.0 が必要だと言われているので、OAuth2.0 の認証をしましょう。
Postman での OAuth2.0 の認証
エラーメッセージを見ると以下のドキュメントを参照するように書いているのでこのページに移動しましょう。
このページの中の「承認認証情報を作成する」という項目があり、その中の「Credentials page」をクリックします。
以下のリンクからも移動できます。
すると認証情報の画面に移動するので、上のバーにある認証情報を作成
をクリックしてOAuthクライアントID
を選択します。
`
するとアプリケーションの種類やアプリの名前を入力する画面になるので以下のように入力してください。
- アプリケーションの種類:ウェブアプリケーション
- 名前:任意の名前
下の方にある承認済みのリダイレクトURI
の項目に Postman のリダイレクト URL であるhttps://oauth.pstmn.io/v1/callback
を入力します。
ここまで入力ができたら、作成
ボタンをクリックします。
するとクライアントの情報が示されているダイアログが表示されるのでクライアントID
とクライアントシークレット
をメモしておきます。(json でダウンロードすることもできます。)
ここからは Postman に戻って、Authorization
タブで作業を行います。
まず、認証のタイプをOAuth 2.0
に変更します。
次に以下のように設定します。
| | |
| ---- | ---- | ---- |
| Grant Type | Authorization Code |
| Callback URL | https://oauth.pstmn.io/v1/callback (ここは最初から入っていて編集できないはず) |
| Auth URL | https://accounts.google.com/o/oauth2/auth |
| Access Token URL | https://oauth2.googleapis.com/token |
| Client ID | 先ほどメモしたクライアント ID |
| Client Secret | 先ほどメモしたクライアントシークレット |
| Scope | https://www.googleapis.com/auth/cloud-platform |
| Client Authentication | Send client credentials in body |
ここまで入力ができたら、Get New Access Token
をクリックします。
するとブラウザが開いて以下のような画像が表示されて信頼できるアプリケーションかどうかの確認が表示されますが、今回は自分で作成したアプリケーションなので続行
をクリックします。
続いてアクセスの許可を与えるかどうかも聞かれますが、今回は自分で作成したアプリケーションなので続行
をクリックします。
すると Postman に戻ってきて以下のようなダイアログが表示されるので、適宜アクセストークンの名前を変更してください。
ここまでできたらもう一度リクエストを実行してみましょう。
レシートの画像を分析してみる
今回は以下のレシートの画像を利用します。
もしこの画像を利用する場合は任意の場所に保存してからそのファイルに対して以下のコマンドを実行して base64 エンコードを行なってください。(ファイル名は適宜変更してください。)
base64 -i image.jpg | pbcopy
エンコードしたデータを Postman のリクエストボディのcontent
の部分にペーストして、リクエストを実行します。
すると以下のようなレスポンスが帰ってきます。
レスポンスが長くて全部は載せられないので、途中で切っています。
レスポンス
{
"document": {
"text": "世界の\n<本社> 株式会社エスワイフード\n〒 460-0007 愛知県名古屋市中区新栄1-22-24\nTEL 052-259-2782(代表)\n西武新宿店\n03-3232-1035\n領収証\n山ちゃん\n本日はありがとうございました。\nお気付の点がございましたら\n下記の留守番電話までご連絡を\nお願い致します。\n録音専用ダイヤル:0120-592-786\n2025年3月27日 (木) 20時11分000101\n幻の手羽先\n@660x 2\n砂肝唐揚げ\n生中ジョッキ(一番搾)\n@583x\n2\n鶏皮揚げ 山椒添え\n山ちゃんコロッケ\nフレフレポテト (幻のコショウ)\n鶏皮餃子\n知多ハイボール W\n陸ハイボール W\nタコ唐揚げ\nごぼうスティック\n漬物盛り合わせ\nうずら玉子フライ\nJJ\n揚げ出し豆富\n縞ホッケ\nストーンMIXアイス\n懐かしの赤ウインナー\n伝票 No.\n小計 額\n(10%内税対象\n10%\n(消費税合計\n合計\nクレジット・\n合計点数\n¥1,320\n¥594\n¥1.166\n¥550内\n¥550内\n¥550内\n¥583 内\n¥1,078\n¥715 内\n¥704内\n¥704内\n¥583 内\n¥473内\n¥495内\n¥550内\n¥913内\n¥605\n¥473\n9 テーブルNo. 213\n¥12,606\n¥12.606)\n¥1.146)\n¥1.146)\n¥12.606\n12,606\n20\nT印は軽減税率(8%) 適用商品\n登録番号: T2180001034622\n04扱佐藤\nNo. 8872\n2\n",
"pages": [
{
"pageNumber": 1
}
],
"entities": [
{
"textAnchor": {
"textSegments": [
{
"startIndex": "191",
"endIndex": "203"
}
],
"content": "20時11分000101"
},
"type": "purchase_time",
"mentionText": "20時11分000101",
"confidence": 0.9887671,
"pageAnchor": {
"pageRefs": [
{
"boundingPoly": {
"normalizedVertices": [
{
"x": 0.51758343,
"y": 0.30467165
},
{
"x": 0.651037,
"y": 0.30467165
},
{
"x": 0.651037,
"y": 0.3195667
},
{
"x": 0.51758343,
"y": 0.3195667
}
]
}
}
]
},
"id": "0",
"normalizedValue": {
"datetimeValue": {
"hours": 20,
"minutes": 11
}
}
},
{
"textAnchor": {
"textSegments": [
{
"startIndex": "176",
"endIndex": "186"
}
],
"content": "2025年3月27日"
},
"type": "receipt_date",
"mentionText": "2025年3月27日",
"confidence": 0.9333239,
"pageAnchor": {
"pageRefs": [
{
"boundingPoly": {
"normalizedVertices": [
{
"x": 0.34355274,
"y": 0.30331755
},
{
"x": 0.4752029,
"y": 0.30331755
},
{
"x": 0.4752029,
"y": 0.31753555
},
{
"x": 0.34355274,
"y": 0.31753555
}
]
}
}
]
},
"id": "1",
"normalizedValue": {
"text": "2025-03-27",
"dateValue": {
"year": 2025,
"month": 3,
"day": 27
}
}
},
{
"textAnchor": {
"textSegments": [
{
"startIndex": "78",
"endIndex": "90"
}
],
"content": "03-3232-1035"
},
"type": "supplier_phone",
"mentionText": "03-3232-1035",
"confidence": 0.8440445,
"pageAnchor": {
"pageRefs": [
{
"boundingPoly": {
"normalizedVertices": [
{
"x": 0.5374211,
"y": 0.11916046
},
{
"x": 0.6501353,
"y": 0.11916046
},
{
"x": 0.6501353,
"y": 0.13405553
},
{
"x": 0.5374211,
"y": 0.13405553
}
]
}
}
]
},
"id": "2"
},
{
"textAnchor": {
"textSegments": [
{
"startIndex": "578",
"endIndex": "579"
}
],
"content": "¥"
},
"type": "currency",
"mentionText": "¥",
"confidence": 0.75223315,
"pageAnchor": {
"pageRefs": [
{
"boundingPoly": {
"normalizedVertices": [
{
"x": 0.5302074,
"y": 0.8124577
},
{
"x": 0.54192966,
"y": 0.8124577
},
{
"x": 0.54192966,
"y": 0.8253216
},
{
"x": 0.5302074,
"y": 0.8253216
}
]
}
}
]
},
"id": "3",
"normalizedValue": {
"text": "JPY"
}
}
]
},
"humanReviewStatus": {
"state": "SKIPPED"
}
}
しっかり認識できていることが確認できていることを確認できると思います。
最後に
作業お疲れ様でした。
わかりにくい部分や間違っている部分があれば指摘していただけると幸いです。
Discussion