Android で Vision API Product Search バックエンドを呼び出す

1. 始める前に

bd8c01b2f8013c6d.png

Google レンズのデモをご覧いただきましたか?デモでは、スマートフォンのカメラを対象物に向け、オンラインで購入できる場所を確認できます。 同じ機能をアプリに追加する方法については、この Codelab をご覧ください。商品画像検索機能をモバイルアプリに組み込む方法を説明する学習プログラムの一部です。

この Codelab では、Vision API Product Search で構築されたバックエンドをモバイルアプリから呼び出す方法を学びます。このバックエンドは、クエリ画像を取得し、商品カタログから視覚的に類似した商品を検索できます。

ML Kit オブジェクトの検出とトラッキングを使用してクエリ画像内のオブジェクトを検出し、検索対象の商品を選択する方法を含む、ビジュアル商品検索機能の残りの手順について学習する(学習パスウェイ)をご覧ください。

作成するアプリの概要

  • この Codelab では、入力画像からオブジェクトを検出できる Android アプリを使用します。ユーザーが選択したオブジェクトを取得し、それを商品検索バックエンドに送信して、検索結果を画面に表示するコードを記述します。
  • 右側に次のような画像が表示されます。

学習内容

  • Android アプリから Vision API Product Search API のレスポンスを呼び出して解析する方法

必要なもの

  • 最新バージョンの Android Studio(v4.1.2 以降)
  • Android Studio エミュレータまたは物理 Android デバイス
  • サンプルコード
  • Kotlin による Android 開発の基本的な知識

この Codelab では、Vision API Product Search を中心に説明します。関連のない概念やコードブロックについては説明せず、そのままコピーして貼り付けてください。

2. Vision API Product Search について

Vision API Product Search は、ユーザーが商品カタログから視覚的に類似した商品を検索できる Google Cloud の機能です。小売業者は商品を作成できます。各商品には、さまざまな視点から商品を視覚的に表す参照画像が含まれます。その後、これらの商品を商品セット(商品カタログ)に追加できます。現在 Vision API Product Search では、日用品、アパレル、玩具、パッケージ商品、総合の商品カテゴリをサポートしています。

ユーザーが独自の画像で商品セットに対してクエリを実行すると、Vision API Product Search は機械学習を適用してユーザーのクエリ画像内の商品を小売店の商品セット内の画像と比較し、視覚的および意味的に類似した結果をランク付きリストとして返します。

3. スターター アプリをダウンロードして実行する

コードをダウンロードする

次のリンクをクリックして、この Codelab のコードをすべてダウンロードします。

ダウンロードした zip ファイルを解凍すると、ルートフォルダ(odml-pathways-main)が展開され、必要なリソースがすべて揃います。この Codelab では、product-search/codelab2/android サブディレクトリ内のソースのみが必要です。

odml-pathways リポジトリの codelab2 サブディレクトリには、次の 2 つのディレクトリがあります。

  • android_studio_folder.pngstarter: この Codelab で土台として使うコードを元に、
  • android_studio_folder.pngfinal: 完成したサンプルアプリの完成したコードです。

ここでのスターター アプリは、画像内のオブジェクトを検出して視覚的な商品検索を作成する: Android Codelab で作成したアプリです。ML Kit オブジェクトの検出とトラッキングを使用して、画像からオブジェクトを検出し、画面に表示します。

Android Studio にアプリをインポートする

まず、スターター アプリを Android Studio にインポートします。

Android Studio に移動して [Import Project (Gradle, Eclipse ADT, etc.)] を選択し、前にダウンロードしたソースコードから starter フォルダを選択します。

7c0f27882a2698ac.png

スターター アプリを実行する

これで Android Studio にプロジェクトがインポートされたので、アプリを初めて実行する準備が整いました。 Android デバイスを USB 経由でホストに接続するか、Android Studio エミュレータを起動し、Android Studio ツールバーの [Run](execute.png)をクリックします。

(このボタンが無効になっている場合は、リポジトリ全体ではなく starter/app/build.gradle のみをインポートしてください)。

これで、Android デバイスでアプリが起動されたはずです。オブジェクト検出機能はすでに画像からファッション アイテムを検出し、その場所を表示します。プリセットの写真で確認します。

c6102a808fdfcb11.png

画像内のオブジェクトを検出できるスターター アプリのスクリーンショット

次に、アプリを拡張して、検出されたオブジェクトを Vision API Product Search バックエンドに送信し、検索結果を画面に表示します。

4.オブジェクト選択の処理

ユーザーが検出されたオブジェクトをタップして選択できるようにする

ここでは、ユーザーが画像からオブジェクトを選択して商品検索を開始できるようにするコードを追加します。スターター アプリには、画像内のオブジェクトを検出する機能がすでに備わっています。画像内に複数のオブジェクトが存在するか、検出されたオブジェクトが画像のごく一部しか占有していない可能性があります。したがって、ユーザーが検出されたオブジェクトのいずれかをタップして、商品検索に使用するオブジェクトを示す必要があります。

9cdfcead6d95a87.png

画像から検出されたファッション アイテムのスクリーンショット

Codelab をシンプルにして、機械学習に焦点を当てるため、ボイラープレート Android コードがスターター アプリに実装され、ユーザーがタップしたオブジェクトを検出できるようになりました。メイン アクティビティ(ObjectDetectorActivity)に画像を表示するビューは、実際には Android OS のデフォルトの ImageView を拡張するカスタムビュー(ImageClickableView)です。次のような便利なユーティリティ メソッドを実装します。

  • fun setOnObjectClickListener(listener: ((objectImage: Bitmap) -> Unit)): ユーザーがタップしたオブジェクトのみを含む切り抜かれた画像を受け取るコールバックです。この切り抜いた画像を Product Search バックエンドに送信します。

検出されたオブジェクトをタップしたユーザーを処理するコードを追加します。

ObjectDetectorActivity クラスの initViews メソッドに移動し、メソッドの末尾に次の行を追加します。(Android Studio は、 startProductImageSearch メソッドを使用してください。少し後で実装できるので、心配は無用です)。

// Callback received when the user taps on any of the detected objects.
ivPreview.setOnObjectClickListener { objectImage ->
    startProductImageSearch(objectImage)
}

onObjectClickListener は、ユーザーが画面で検出されたオブジェクトをタップするたびに呼び出されます。選択したオブジェクトのみを含む切り抜き画像を受け取ります。たとえば、ユーザーが右側のドレスを着ている人をタップすると、次のように objectImage でリスナーがトリガーされます。

9CAC8458D0F326E6.PNG

onObjectClickListener に渡される切り抜き画像の例

トリミングされた画像を商品検索アクティビティに送信する

ここでは、クエリ画像を Vision API Product Search バックエンドに別のアクティビティ(ProductSearchActivity)で送信するロジックを実装します。

すべての UI コンポーネントがあらかじめ実装されているため、商品検索バックエンドと通信するためのコードを記述することに集中できます。

25939f5a13eeb3c3.png

ProductSearchActivity の UI コンポーネントのスクリーンショット

ユーザーが選択したオブジェクト画像を ProductSearchActivity に送信するコードを追加します。

Android Studio に戻り、この startProductImageSearch メソッドを ObjectDetectorActivity クラスに追加します。

private fun startProductImageSearch(objectImage: Bitmap) {
    try {
        // Create file based Bitmap. We use PNG to preserve the image quality
        val savedFile = createImageFile(ProductSearchActivity.CROPPED_IMAGE_FILE_NAME)
        objectImage.compress(Bitmap.CompressFormat.PNG, 100, FileOutputStream(savedFile))

        // Start the product search activity (using Vision Product Search API.).
        startActivity(
            Intent(
                    this,
                    ProductSearchActivity::class.java
            ).apply {
                // As the size limit of a bundle is 1MB, we need to save the bitmap to a file
                // and reload it in the other activity to support large query images.
                putExtra(
                    ProductSearchActivity.REQUEST_TARGET_IMAGE_PATH,
                    savedFile.absolutePath
                )
            })
    } catch (e: Exception) {
        // IO Exception, Out Of memory ....
        Toast.makeText(this, e.message, Toast.LENGTH_SHORT).show()
        Log.e(TAG, "Error starting the product image search activity.", e)
    }
}

コード スニペットは次の 3 つの処理を行います。

  • 切り抜いた画像を撮影し、PNG ファイルにシリアル化します。
  • ProductSearchActivity を開始して、商品検索シーケンスを実行します。
  • 切り取られた画像の URI を開始アクティビティ インテントに含めることで、ProductSearchActivity が後でそれを取得してクエリ画像として使用できるようにします。

次の点にご注意ください。

  • オブジェクトの検出とバックエンドへのクエリを行うためのロジックを 2 つのアクティビティに分割しました。これは、Codelab を理解しやすくするためです。アプリで実装する方法は自由に決められます。
  • クエリ画像は Android インテントのサイズ上限(1 MB)よりも大きくなる可能性があるため、クエリ画像をファイルに書き込み、アクティビティ間で画像 URI を渡す必要があります。
  • クエリ画像は可逆形式であるため、PNG で保存できます。

商品検索アクティビティのクエリ画像を取得します。

ProductSearchActivity では、クエリ画像を取得して画面に表示するコードが、スターター アプリにすでに実装されています。

onCreate メソッドに移動して、このコードがすでに存在していることを確認します。

// Receive the query image and show it on the screen
intent.getStringExtra(REQUEST_TARGET_IMAGE_PATH)?.let { absolutePath ->
    viewBinding.ivQueryImage.setImageBitmap(BitmapFactory.decodeFile(absolutePath))
}

アプリを実行する

Android Studio のツールバーで [Run](execute.png)をクリックします。

アプリが読み込まれたら、プリセットの画像をタップして、検出されたオブジェクトの 1 つを選択します。

タップした画像とともに ProductSearchActivity が表示されることを確認します。[Search] ボタンはまだ何も行いませんが、次に実装します。

fed40f81b8b43801.png

検出されたオブジェクトのいずれかをタップすると、同様の画面が表示されます。

5. Product Search バックエンドを調べる

商品画像検索バックエンドを構築する

この Codelab には、Vision API Product Search で構築された商品検索バックエンドが必要です。これには、次の 2 つの方法があります。

オプション 1: デプロイ済みのデモ バックエンドを使用する

この Codelab は、Google によってデプロイ済みの Product Search バックエンドを使用して進められます。デモのバックエンドは、Vision API Product Search のクイックスタートに沿って複製できます。

オプション 2: Vision API Product Search クイックスタートに従って独自のバックエンドを作成する

このオプションは、商品検索バックエンドの作成方法を深く学習し、独自の商品カタログ用に後で作成したい場合におすすめです。以下が必要となります。

  • 課金が有効になっている Google Cloud アカウント。(無料試用アカウントを使用してもかまいません)。
  • プロジェクト、サービス アカウントなど、Google Cloud のコンセプトに関する知識

この方法については、後で学習パスウェイをご覧ください。

重要なコンセプトについて学習する

商品検索バックエンドを操作するときは、次のことを理解します。

  • 商品セット: 商品セットとは、商品グループのシンプルなコンテナです。商品カタログは、商品セットとその商品として表すことができます。
  • 商品: 商品セットを作成したら、商品を作成して商品セットに追加できます。
  • 商品の参照画像: 商品のさまざまなビューを含む画像です。参照画像は、見た目が似ている商品を検索するために使用されます。
  • 商品を検索する: 商品セットを作成し、インデックスに登録すると、Cloud Vision API を使用して商品セットをクエリできます。

プリセットの商品カタログについて

この Codelab で使用される商品検索デモのバックエンドは、Vision API Product Search と、約 100 件の靴とドレスの画像の商品カタログを使用して作成されました。カタログからの画像です。

4F1a8507b74ab178.png 79a5fc6c829eca77.png Google

既定の商品カタログの例

Product Search のデモ バックエンドの呼び出し

Google Cloud API キーを設定し、API キーへのアクセスを自分のアプリのみに制限することで、モバイルアプリから直接 Vision API Product Search を呼び出すことができます。

この Codelab はシンプルにするために、API キーと認証を気にせずにデモ バックエンドにアクセスできるプロキシ エンドポイントが設定されています。モバイルアプリから HTTP リクエストを受け取り、API キーを追加し、そのリクエストを Vision API Product Search バックエンドに転送します。次に、プロキシはバックエンドからレスポンスを受信し、モバイルアプリに返します。

この Codelab では、Vision API Product Search の 2 つの API を使用します。

6. API クライアントを実装する

Product Search のワークフローを理解する

このワークフローに従って、バックエンドを使用して商品検索を行います。

API クライアント クラスを実装する

ここでは、ProductSearchAPIClient という専用のクラスに Product Search バックエンドを呼び出すコードを実装します。なんらかのボイラープレート コードがスターター アプリに実装されています。

  • class ProductSearchAPIClient: このクラスは現在空になっていますが、この Codelab の後半で実装するメソッドがいくつかあります。
  • fun convertBitmapToBase64(bitmap: Bitmap): Bitmap インスタンスをその Base64 表現に変換して、商品検索バックエンドに送信します。
  • fun annotateImage(image: Bitmap): Task<List<ProductSearchResult>>: projects.locations.images.annotation API を呼び出し、レスポンスを解析します。
  • fun fetchReferenceImage(searchResult: ProductSearchResult): Task<ProductSearchResult>: projects.locations.products.referenceImages.get API を呼び出してレスポンスを解析します。
  • SearchResult.kt: このファイルには、Vision API Product Search バックエンドによって返されるタイプを表す複数のデータクラスが含まれています。

API 構成を指定する

ProductSearchAPIClient クラスに移動すると、商品検索バックエンドのいくつかの構成ファイルがすでに定義されています。

// Define the product search backend
// Option 1: Use the demo project that we have already deployed for you
const val VISION_API_URL =
    "https://us-central1-odml-codelabs.cloudfunctions.net/productSearch"
const val VISION_API_KEY = ""
const val VISION_API_PROJECT_ID = "odml-codelabs"
const val VISION_API_LOCATION_ID = "us-east1"
const val VISION_API_PRODUCT_SET_ID = "product_set0"
  • VISION_API_URL は Cloud Vision API の API エンドポイントです。デモ バックエンドを進めるときは、これをプロキシ エンドポイントに設定します。ただし、独自のバックエンドをデプロイする場合は、Cloud Vision API エンドポイントに変更する必要があります。 https://vision.googleapis.com/v1
  • VISION_API_KEY は Cloud プロジェクトの API キーです。プロキシはすでに認証を処理しているため、空白のままにしてかまいません。
  • VISION_API_PROJECT_ID は Cloud プロジェクト ID です。odml-codelabs は、デモ バックエンドがデプロイされている Cloud プロジェクトです。
  • VISION_API_LOCATION_ID は、Product Search バックエンドがデプロイされている Cloud のロケーションです。us-east1 はデモ バックエンドをデプロイした場所です。
  • VISION_API_PRODUCT_SET_ID は、視覚的に類似した商品を検索する商品カタログの ID です(Vision API の用語では「商品セット」とも呼ばれます)。1 つの Cloud プロジェクトに複数のカタログを設定できます。product_set0 は、デモ バックエンドのプリセット プロダクト カタログです。

7. Product Search API を呼び出す

API のリクエストとレスポンスの形式を確認する

指定された画像に類似する商品を検索するには、画像の Google Cloud Storage URI、ウェブ URL、または Base64 でエンコードされた文字列を Vision API Product Search に渡します。この Codelab では、クエリ画像がユーザーのデバイス内にのみ存在するため、この Codelab では base64 でエンコードされた文字列オプションを使用します。

POST リクエストを projects.locations.images.annotation エンドポイントに、次の JSON 本文とともに送信する必要があります。

{
  "requests": [
    {
      "image": {
        "content": {base64-encoded-image}
      },
      "features": [
        {
          "type": "PRODUCT_SEARCH",
          "maxResults": 5
        }
      ],
      "imageContext": {
        "productSearchParams": {
          "productSet": "projects/{project-id}/locations/{location-id}/productSets/{product-set-id}",
          "productCategories": [
               "apparel-v2"
          ],
        }
      }
    }
  ]
}

次のパラメータを指定する必要があります。

  • base64 でエンコードされた画像: クエリ画像のバイナリデータの base64 表現(ASCII 文字列)。
  • project-id: GCP プロジェクト ID。
  • location-id: 有効なロケーション ID。
  • product-set-id: 操作を実行する商品セットの ID。

商品カタログには靴とドレスの画像のみが含まれているため、productCategoriesapparel-v2 に指定します。ここで、v2 は、アパレル商品検索の機械学習モデルのバージョン 2 を使用することを意味します。

リクエストが成功すると、サーバーは 200 OK HTTP ステータス コードと JSON 形式のレスポンスを返します。レスポンスの JSON は次のようになります。

  • productSearchResults - 画像全体で一致する商品のリストが含まれます。
  • productGroupedResults - 画像内で識別される各商品の境界ボックスの座標および一致するアイテムが含まれます。

商品はすでに元の画像から切り抜かれているので、productSearchResults リストで結果を解析します。

商品検索結果オブジェクトの重要なフィールドは次のとおりです。

  • product.name: 商品の一意の識別子(形式は projects/{project-id}/locations/{location-id}/products/{product_id}
  • product.score: 検索結果がクエリ画像とどの程度類似しているかを示す値。値が大きいほど、類似性が高くなります。
  • product.image: 商品の参照画像の一意の識別子(projects/{project-id}/locations/{location-id}/products/{product_id}/referenceImages/{image_id} 形式)。projects.locations.products.referenceImages.get に別の API リクエストを送信して、この参照画像の URL を取得し、画面に表示されるようにします。
  • product.labels: 商品の事前定義されたタグのリスト。これは、「ドレス」など、1 つのカテゴリの衣服のみを表示するように検索結果を絞り込む場合に便利です。

クエリ画像を base64 に変換する

クエリ画像を base64 の文字列表現に変換し、リクエスト本文の JSON オブジェクトに文字列を添付する必要があります。

ProductSearchAPIClient クラスに移動し、空の convertBitmapToBase64 メソッドを見つけて、次の実装に置き換えます。

private fun convertBitmapToBase64(bitmap: Bitmap): String {
    val byteArrayOutputStream = ByteArrayOutputStream()
    bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream)
    val byteArray: ByteArray = byteArrayOutputStream.toByteArray()
    return Base64.encodeToString(byteArray, Base64.DEFAULT)
}

API 呼び出しを実装する

次に、Product Search API リクエストを作成し、バックエンドに送信します。Volley を使用して API リクエストを作成し、Task API を使用して結果を返します。

ProductSearchAPIClient クラスに戻り、空の annotateImage メソッドを見つけて、次の実装に置き換えます。

fun annotateImage(image: Bitmap): Task<List<ProductSearchResult>> {
    // Initialization to use the Task API
    val apiSource = TaskCompletionSource<List<ProductSearchResult>>()
    val apiTask = apiSource.task

    // Convert the query image to its Base64 representation to call the Product Search API.
    val base64: String = convertBitmapToBase64(image)

    // Craft the request body JSON.
    val requestJson = """
        {
          "requests": [
            {
              "image": {
                "content": """".trimIndent() + base64 + """"
              },
              "features": [
                {
                  "type": "PRODUCT_SEARCH",
                  "maxResults": $VISION_API_PRODUCT_MAX_RESULT
                }
              ],
              "imageContext": {
                "productSearchParams": {
                  "productSet": "projects/${VISION_API_PROJECT_ID}/locations/${VISION_API_LOCATION_ID}/productSets/${VISION_API_PRODUCT_SET_ID}",
                  "productCategories": [
                       "apparel-v2"
                     ]
                }
              }
            }
          ]
        }
    """.trimIndent()

    // Add a new request to the queue
    requestQueue.add(object :
        JsonObjectRequest(
            Method.POST,
            "$VISION_API_URL/images:annotate?key=$VISION_API_KEY",
            JSONObject(requestJson),
            { response ->
                // Parse the API JSON response to a list of ProductSearchResult object/
                val productList = apiResponseToObject(response)

                // Return the list.
                apiSource.setResult(productList)
            },
            // Return the error
            { error -> apiSource.setException(error) }
        ) {
        override fun getBodyContentType() = "application/json"
    }.apply {
        setShouldCache(false)
    })

    return apiTask
}

UI で検索結果を表示する

これで ProductSearchAPIClient の API コードが完成しました。アクティビティ ProductSearchActivity に戻り、UI コードを実装します。

アクティビティには、searchByImage(queryImage: Bitmap) メソッドをトリガーするボイラープレート コードがすでに含まれています。バックエンドを呼び出すコードを追加し、この空のメソッドに UI で結果を表示します。

apiClient.annotateImage(queryImage)
    .addOnSuccessListener { showSearchResult(it) }
    .addOnFailureListener { error ->
        Log.e(TAG, "Error calling Vision API Product Search.", error)
        showErrorResponse(error.localizedMessage)
    }

showSearchResult メソッドには、API レスポンスを解析し、画面に表示するボイラープレート コードが含まれています。

実行

Android Studio のツールバーで [Run](execute.png)をクリックします。アプリが読み込まれると、プリセットの画像をタップし、検出されたオブジェクトを選択して、[検索] ボタンをタップすると、バックエンドから返された検索結果が表示されます。次のような出力が表示されます。

bb5e7c27c283a2fe.png

商品検索結果画面のスクリーンショット

バックエンドは、あらかじめ設定された商品カタログから視覚的に類似する商品のリストを返します。しかしながら、商品画像がまだ空であることはわかります。これは、projects.locations.images.annotation エンドポイントが返す商品イメージ ID(projects/odml-codelabs/locations/us-east1/products/product_id77/referenceImages/image77 など)のみであるためです。projects.locations.products.referenceImages.get エンドポイントに別の API 呼び出しを行い、この参照画像の URL を取得して画面に表示する必要があります。

8. 商品参照画像を取得する

API のリクエストとレスポンスの形式を確認する

空のリクエスト本文を含む GET HTTP リクエストを projects.locations.products.referenceImages.get エンドポイントに送信し、商品検索エンドポイントによって返された商品画像の URI を取得します。

HTTP リクエストは次のようになります。

GET $VISION_API_URL/projects/odml-codelabs/locations/us-east1/products/product_id77/referenceImages/image77?key=$VISION_API_KEY

リクエストが成功すると、サーバーは 200 OK HTTP ステータス コードと次のような JSON 形式のレスポンスを返します。

{
  "name":"projects/odml-codelabs/locations/us-east1/products/product_id77/referenceImages/image77",
  "uri":"gs://cloud-ai-vision-data/product-search-tutorial/images/46991e7370ba11e8a1bbd20059124800.jpg"
}
  • name: 参照画像 ID
  • uri: Google Cloud Storage(GCS)上の画像の URI。

デモ商品検索バックエンドの参照画像は、公開読み取りの権限を持つように設定されています。そのため、GCS URI を HTTP URL に簡単に変換して、アプリの UI に表示できます。gs:// プレフィックスを https://storage.googleapis.com/ に置き換えるだけですみます。

API 呼び出しを実装する

次に、Product Search API リクエストを作成し、バックエンドに送信します。Volley と Task API は、Product Search API の呼び出しと同様に使用します。

ProductSearchAPIClient クラスに戻り、空の fetchReferenceImage メソッドを見つけて、次の実装に置き換えます。

private fun fetchReferenceImage(searchResult: ProductSearchResult): Task<ProductSearchResult> {
    // Initialization to use the Task API
    val apiSource = TaskCompletionSource<ProductSearchResult>()
    val apiTask = apiSource.task

    // Craft the API request to get details about the reference image of the product
    val stringRequest = object : StringRequest(
        Method.GET,
        "$VISION_API_URL/${searchResult.imageId}?key=$VISION_API_KEY",
        { response ->
            val responseJson = JSONObject(response)
            val gcsUri = responseJson.getString("uri")

            // Convert the GCS URL to its HTTPS representation
            val httpUri = gcsUri.replace("gs://", "https://storage.googleapis.com/")

            // Save the HTTPS URL to the search result object
            searchResult.imageUri = httpUri

            // Invoke the listener to continue with processing the API response (eg. show on UI)
            apiSource.setResult(searchResult)
        },
        { error -> apiSource.setException(error) }
    ) {

        override fun getBodyContentType(): String {
            return "application/json; charset=utf-8"
        }
    }
    Log.d(ProductSearchActivity.TAG, "Sending API request.")

    // Add the request to the RequestQueue.
    requestQueue.add(stringRequest)

    return apiTask
}

このメソッドは、Product Search エンドポイントから返された searchResult: ProductSearchResult オブジェクトを使って、次の手順に従います。

  1. 参照画像エンドポイントを呼び出して、参照画像の GCS URI を取得します。
  2. GCS URI を HTTP URL に変換します。
  3. searchResult オブジェクトの httpUri プロパティをこの HTTP URL で更新します。

2 つの API リクエストを接続します。

annotateImage に戻り、ProductSearchResult リストを呼び出し元に返す前に変更を行い、すべての参照画像の HTTP URL を取得します。

次に示す行を探します。

// Return the list.
apiSource.setResult(productList)

これを次の実装に置き換えます。

// Loop through the product list and create tasks to load reference images.
// We will call the projects.locations.products.referenceImages.get endpoint
// for each product.
val fetchReferenceImageTasks = productList.map { fetchReferenceImage(it) }

// When all reference image fetches have completed,
// return the ProductSearchResult list
Tasks.whenAllComplete(fetchReferenceImageTasks)
    // Return the list of ProductSearchResult with product images' HTTP URLs.
    .addOnSuccessListener { apiSource.setResult(productList) }
    // An error occurred so returns it to the caller.
    .addOnFailureListener { apiSource.setException(it) }

画面に参照画像を表示するためのボイラープレート コードが ProductSearchAdapter クラスにすでに実装されているため、アプリを再実行できます。

実行

Android Studio のツールバーで [Run](execute.png)をクリックします。アプリが読み込まれると、プリセットの画像をタップし、検出されたオブジェクトを選択して [検索] ボタンをタップすると、今回は商品画像を使用して検索結果が表示されます。

商品の検索結果は合っていますか。

25939f5a13eeb3c3.png

9. 完了

Vision API Product Search バックエンドを呼び出して、商品画像検索機能を Android アプリに追加する方法を学習しました。セットアップは完了です。

さらに、商品カタログを使用して独自のバックエンドを構築することもできます。商品画像検索の学習プログラムにある次の Codelab で、独自のバックエンドを構築し、モバイルアプリから呼び出すように API キーを設定する方法をご確認ください。

学習した内容

  • Android アプリから Vision API Product Search バックエンドを呼び出す方法

次の手順

詳細