Vision APIのBatchAnnotateImagesメソッド(画像からの同期特徴抽出)を少し深堀りする

Vision APIの利用には、クライアントライブラリの利用が推奨されていますが、クライアントライブラリの理解を深めるためにも、まずはVision APIが提供するメソッドの基本的な仕様を押さえておきたいと思います。

本記事では、『Vision API クライアントライブラリの概要(Python編)』に続いて、 Vision APIの RPCで定義されているImageAnnotatorサービスのBatchAnnotateImagesメソッド(画像からの同期特徴抽出)について少し深堀します。なお、内容的にはREST/HTTP APIのimages.annotateメソッドも同様かと思います。

【目次】

[1]BatchAnnotateImagesメソッドの概要

画像(JPEG、PNGなど)から同期処理で特徴検出を行うメソッドです。

BatchAnnotateImagesメソッドは、Vision APIのRPCで定義されるImageAnnotatorサービスが提供する4つのメソッドのうちの1つす。(『Vision API クライアントライブラリの概要(Python編)』も参照してください。)

(1)特徴

  • 画像形式は、JPEG、PNG、GIF、BMP、WEBP、RAW、ICOです。(但し、アニメーションGIFは最初のフレームのみ)
    • PDFファイル、TIFFファイルを送信するとエラーになります。
  • 検出できる特徴は、Vision APIの機能リストにあるもの全てです。一つの画像に対して同時に複数の特徴を検出できます。
  • 一回のメソッド呼び出しで、16枚まで画像の特徴検出ができます。
  • 同期処理のため、メソッドの戻り値として指定した特徴検出の結果を得ることができます。このため、非同期版に比べて手軽に利用できます。

なお、iPhoneで撮影した画像など、拡張子が.HEICになっている画像ファイルを利用する場合はJPEGファイルなどに変換する必要があります。『Colaboratory環境で拡張子が.HEICの画像ファイルを扱う(libheif,pyheif)』を参照してみてください。

(2)メソッド定義

rpc BatchAnnotateImages( BatchAnnotateImagesRequest ) returns (BatchAnnotateImagesResponse)

対応するRESTでのメソッドはimages.annotateメソッドになります。

(3)動作イメージ

動作の流れを大雑把に図で表すと以下のようになります。

Vision API:ImageAnnotatorサービス:BatchAnnotateImagesメソッドの動作イメージ

  1. 画像情報と検出したい特徴(複数指定可能)を1つのリクエスト(AnnotateImageRequest)として、これをバッチ(BatchAnnotateImageRequest)にまとめてBatchAnnotateImagesメソッドを呼び出します。
  2. 同期処理され、BatchAnnotateImagesメソッドのレスポンス(戻り値)として検出結果(BatchAnnotateImagesResponse)が得られます。
  3. BatchAnnotateImagesResponseには、AnnotateImageRequestと同じ順序で、検出結果(AnnotateImageResponse)が格納されています。

[2]リクエストデータ:BatchAnnotateImagesRequest

リクエスト(入力)データであるBatchAnnotateImagesRequestの構造を図にしてみました。

Vision API:BatchAnnotateImagesRequestのデータ構造

1枚の画像に対する特徴検出リクエストをAnnotateImageRequestで定義します。これは3つのフィールドを持ちます。
  • image:(必須)解析したい1つの画像を指定します。
  • features:(必須)検出したい特徴タイプを指定します。(複数指定可能)
  • image_context:(オプション)検出したい特徴タイプ固有のパラメータ
例えば、一枚の画像からランドマーク、ロゴ、文字認識などの複数の特徴検出を同時に指定できます。

そして、BatchAnnotateImagesRequestは、requestsフィールドにAnnotateImageRequestを16個まで格納できます。

これらにより、BatchAnnotateImagesメソッドは、複数の画像から複数の特徴を一括して検出できることになります。

以下にAnnotateImageRequestの各フィールドを見ていきます。

(1)画像の指定(Image)

解析対象の画像情報は、AnnotateImageRequestのimageフィールド(Image型)で指定します。

指定できる画像形式は、JPEG、PNG、GIF、BMP、WEBP、RAW、ICOです。(但し、アニメーションGIFは最初のフレームのみ)

PDFファイルやTIFFファイルを指定するとエラーになります。PDFファイルやTIFFファイルの解析には、BatchAnnotateFilesまたはAsyncBatchAnnotateFilesメソッドを利用します。

画像データは、以下の3つの方法から1つを選んで指定します。
  • バイナリデータを送信する方法
    • contentフィールドに、画像ファイルのバイナリデータを設定します。(画像データそのものを送信する方法です。)
    • なお、JSON APIでは画像データをbase64で表現する必要がありますが、PythonクライアントライブラリはRPCを利用しているため、バイナリデータを指定します。
  • Google Cloud Storageのパスを指定する方法
    • sourceフィールドに、image_uriフィールドをもつオブジェクト(ImageSource)を設定します。
    • image_uriフィールドには、Google Cloud Storage URI形式(gs://bucket_name/object_name)で、画像オブジェクトのパスを指定します。
  • Web上で公開されている画像のURLを指定する方法
    • sourceフィールドに、image_uriフィールドをもつオブジェクト(ImageSource)を設定します。
    • image_uriフィールドには、公開されている画像のHTTP / HTTPS URLを指定します。
    • 但し、この方法は、Googleが他のサイトへ画像を取りに行くことになり、セキュリティその他の様々な理由で画像の取得に失敗する可能性があるため、本番アプリケーションでの利用は非推奨となっています。

なお、contentフィールドとsourceフィールドが同時に指定された場合は、contentフィールドが優先されるとされています(送った画像が優先される)。

(2)検出したい特徴の指定(Feature)

解析対象の画像から検出したい特徴は、AnnotateImageRequestのfeaturesフィールドで複数指定できます(Feature型オブジェクトのリストで指定します)。

Featureオブジェクトは3つのフィールドを持ちます。
  • type:(必須)検出する特徴。機能リストに対応する定数を1つ指定します。
    • FACE_DETECTION = 1
    • LANDMARK_DETECTION = 2
    • LOGO_DETECTION = 3
    • LABEL_DETECTION = 4
    • TEXT_DETECTION = 5
    • DOCUMENT_TEXT_DETECTION = 11
    • SAFE_SEARCH_DETECTION = 6
    • IMAGE_PROPERTIES = 7
    • CROP_HINTS = 9
    • WEB_DETECTION = 10
    • PRODUCT_SEARCH = 12
    • OBJECT_LOCALIZATION = 19
  • max_results:(オプション)typeで指定した特徴検出の最大数を指定します。
    • なお、TEXT_DETECTION、DOCUMENT_TEXT_DETECTION、CROP_HINTSには適用されないとされています。
  • model:(オプション)typeで指定した特徴検出のモデルを指定します。

(3)特徴タイプ固有のパラメータ(ImageContext)

指定した特徴(Feature)のタイプ固有のパラメータをオプションで指定することができます。(特徴タイプがPRODUCT_SEARCH以外は省略可能です。)

[3]レスポンス:BatchAnnotateImagesResponse

レスポンス(検出結果)データであるBatchAnnotateImagesResponseの構造を図にしてみました。
Vision API:BatchAnnotateImagesResponseのデータ構造


BatchAnnotateImagesResponseのresponsesフィールドに、AnnotateImageRequest(1つの画像に対する特徴検出リクエスト)に対応する検出結果(AnnotateImageResponse)がリクエストと同じ順序で格納されています。

なお、エラーが発生して解析できなかった画像リクエストに対しては、errorフィールドにエラー情報が設定されたAnnotateImageResponseが格納されますので、リクエストの数とレスポンスの数は同じです。

以下にAnnotateImageResponseの各フィールドを見ていきます。

(1)指定した特徴に対応する検出結果フィールド

AnnotateImageRequestのfeaturesフィールドで指定した特徴タイプに応じて、AnnotateImageResponseに設定されるフィールドが決まります。特徴タイプと結果フィールドの対応は以下のようになります。(なお、特徴タイプを複数指定した場合も、対応する複数のフィールドに結果が設定されます。)

特徴タイプ 結果フィールド
FACE_DETECTION face_annotations
LANDMARK_DETECTION landmark_annotations
LOGO_DETECTION logo_annotations
LABEL_DETECTION label_annotations
TEXT_DETECTION text_annotations と full_text_annotation
DOCUMENT_TEXT_DETECTION text_annotations と full_text_annotation
SAFE_SEARCH_DETECTION safe_search_annotation
IMAGE_PROPERTIES image_properties_annotation
CROP_HINTS crop_hints_annotation
WEB_DETECTION web_detection
PRODUCT_SEARCH product_search_results
OBJECT_LOCALIZATION localized_object_annotations

(追記:2020/10/27)
OCR関連のレスポンスデータ(fulTextAnnotationとtextAnnotatins)については、以下の記事を書きましたので参考にしてください。

(2)errorフィールド(エラー情報)

対応するAnnotateImageRequestの処理で発生したエラー情報は、errorフィールド(Status型)で得られます。(Status型については、『[4]Status型のエラー情報』を参照してください。)

例えば、リクエストの画像にPDFファイルを指定した場合は、レスポンスのerrorフィールドに、code=3、message=Bad image data が設定されます。

なお、BatchAnnotateImagesResponseには処理全体を表すエラー情報はありません。しかし、データ構造の問題やRPCの問題により、BatchAnnotateImagesメソッド呼び出し全体がエラーとなり、クライアントライブラリレベルで例外がスローされる場合はあります。(この場合は、BatchAnnotateImagesResponseが得られません。)

例えば、画像を17枚以上指定してBatchAnnotateImagesメソッドを呼び出した場合、RPCの例外(status = StatusCode.INVALID_ARGUMENT、details = "Too many images per request")がスローされます。

(3)contextフィールド

contextフィールドは、画像を対象としたBatchAnnotateImagesでは利用されません。(PDFファイルなどのファイルリクエストに固有の情報です。)

[4]Status型のエラー情報

エラー情報を表すStatus型は、3つのフィールドを持っています。
  • code:整数のステータスコード
  • message:エラーメッセージ文字列
    • エラーがある場合に設定される英語の文字列です。
  • details:エラーの詳細情報。(今回は説明を省略)

なお、Status型を用いたエラー情報の扱いは、GoogleのAPI設計ガイドにそったエラーモデルとなっています。

[5]モデルのバージョンアップへの対応

Featureのmodelフィールドは(特徴検出機能ごとに)Googleの機械学習モデルのバージョンを指定するもののようです。通常はmodelフィールドを設定する必要性はないと思いますが(省略時は「builtin/stable」と設定するのと同じ)、モデルのバージョンアップに関連して、明示的に設定する必要が生じる場合が考えられます。

(例)リリースノート:2020 年 6 月 11 日(https://cloud.google.com/vision/docs/release-notes?hl=ja#June_11_2020

  • OCR legacy model access extension

  • Based on customer feedback, we have decided to extend support of the legacy TEXT_DETECTION and DOCUMENT_TEXT_DETECTION models. These legacy models are accessed by specifying "builtin/legacy_20190601" in the model of a Feature object.
  • These models will now be accessible until November 15, 2020 (6 months from launch date) to give customers more time to adapt and migrate to the new model.

これは、以前OCRの「builtin/stable」モデルを最新版にアップデートしたけど、2020年11月15日までは、modelに「builtin/legacy_20190601」を設定すれば従来のモデルを利用した検出ができるという内容でした。

一般的にはモデルのアップデートにより認識精度の向上が見込めるので歓迎すべきことではあります。しかし、検出結果をプラグラムで解釈しているような場合は、検出結果の変化によるアプリケーションへの影響も懸念されます。このような場合は、modelフィールドに過去のモデルを設定して、新モデルへの移行期間を設ける必要があるかもしれません。

ちなみに、過去のモデルのアップデートに関するリリースノートを見ると、modelに「builtin/legacy」を設定する形で同様の対応が行われたようです。(上記とはモデル名が異なる。)

別のパターンとして、「builtin/stable」を置き換える前に、先行して「builtin/latest」がリリースされて、一定期間経過後に「builtin/stable」に置き換わるという対応もあるようです。この場合は、事前に「builtin/latest」を設定して影響調査を行って対応することになります。(「builtin/latest」は仕様に明記されている名前のため、このパターンが本来の運用のように思えます。)

[6]Protocol BuffersによるAPI定義

Vision APIのRPCサービスのメソッドやデータ構造(メッセージ)は、Protocol Buffersを使って定義されています。(Vision APIに限らず、多くのGoogle APIがそうです。)

そして、Vision APIのProtocol Buffersの定義ファイル(.proto)は、クライアントライブラリのソースコードとともに公開されています。(以下はPythonクライアントライブラリの場合。)

コメント

このブログの人気の投稿

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

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

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