1. 始める前に
Google レンズのデモをご覧になったことはありますか?スマートフォン カメラを被写体に向けると、オンラインで購入できる場所を検索できるというものです。アプリに同じ機能を追加する方法を学びたい場合は、この Codelab をご覧ください。これは、商品画像検索機能をモバイルアプリに組み込む方法を学ぶ学習プログラムの一部です。
この Codelab では、モバイルアプリから Vision API Product Search で構築されたバックエンドを呼び出す方法を学習します。このバックエンドは、クエリ画像を取得し、商品カタログから視覚的に類似した商品を検索できます。
ML Kit のオブジェクト検出とトラッキングを使用してクエリ画像内のオブジェクトを検出し、ユーザーが検索する商品を選択できるようにする方法など、ビジュアル商品検索機能の構築の残りの手順については、学習コースをご覧ください。
作成するアプリの概要
|
学習内容
- 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 は ML を適用してユーザーの画像内の商品と小売業者の商品セット内の画像を比較し、視覚的および意味的に類似した結果をランク付きリストとして返します。
3. スターター アプリをダウンロードして実行する
コードをダウンロードする
次のリンクをクリックして、この Codelab のコードをすべてダウンロードします。
ダウンロードした zip ファイルを解凍すると、必要なすべてのリソースを含むルートフォルダ(odml-pathways-main
)が展開されます。この Codelab では、product-search/codelab2/android
サブディレクトリ内のソースのみが必要です。
odml-pathways
リポジトリの codelab2
サブディレクトリには、次の 2 つのディレクトリが含まれています。
starter - この Codelab で作成する開始コード。
final - 完成したサンプルアプリのコード。
ここで使用するスターター アプリは、画像内のオブジェクトを検出してビジュアル商品検索を構築する: Android Codelab で作成したものです。ML Kit のオブジェクト検出とトラッキングを使用して、画像からオブジェクトを検出し、画面に表示します。
Android Studio にアプリをインポートする
まず、スターター アプリを Android Studio にインポートします。
Android Studio に移動し、[Import Project (Gradle, Eclipse ADT, etc.)] を選択して、先ほどダウンロードしたソースコードから starter
フォルダを選択します。
スターター アプリを実行する
Android Studio にプロジェクトをインポートしたので、アプリを初めて実行する準備ができました。USB 経由で Android デバイスをホストに接続するか、Android Studio エミュレータを起動して、Android Studio ツールバーの [実行]()をクリックします。
(このボタンが無効になっている場合は、リポジトリ全体ではなく、starter/app/build.gradle のみをインポートしていることを確認してください)。
Android デバイスでアプリが起動します。すでにオブジェクト検出機能が搭載されており、画像からファッション アイテムを検出して、そのアイテムがどこにあるかを表示できます。プリセットの写真で確認してみてください。
画像内のオブジェクトを検出できるスターター アプリのスクリーンショット
次に、検出されたオブジェクトを Vision API Product Search バックエンドに送信し、検索結果を画面に表示するようにアプリを拡張します。
4. オブジェクトの選択を処理する
検出されたオブジェクトをタップして選択できるようにする
次に、ユーザーが画像からオブジェクトを選択して商品検索を開始できるようにするコードを追加します。スターター アプリには、画像内のオブジェクトを検出する機能がすでに備わっています。画像内に複数のオブジェクトが存在する場合や、検出されたオブジェクトが画像のごく一部しか占めていない可能性があります。そのため、検出されたオブジェクトのいずれかをタップして、商品検索に使用するオブジェクトを指定する必要があります。
画像から検出されたファッション アイテムのスクリーンショット
この Codelab をシンプルにして機械学習に集中できるように、ユーザーがタップしたオブジェクトを検出するのに役立つボイラープレート Android コードがスターター アプリに実装されています。メイン アクティビティ(ObjectDetectorActivity
)で画像を表示するビューは、実際には Android OS のデフォルトの ImageView
を拡張するカスタムビュー(ImageClickableView
)です。これには、次のような便利なユーティリティ メソッドが実装されています。
fun setOnObjectClickListener(listener: ((objectImage: Bitmap) -> Unit))
これは、ユーザーがタップしたオブジェクトのみを含む切り抜き画像を受け取るためのコールバックです。この切り抜き画像を商品検索バックエンドに送信します。
検出されたオブジェクトをユーザーがタップしたときの処理を行うコードを追加します。
ObjectDetectorActivity
クラスの initViews
メソッドに移動し、メソッドの末尾に次の行を追加します。(Android Studio で startProductImageSearch
メソッドが見つからないというメッセージが表示されます。これは後で実装します。
// Callback received when the user taps on any of the detected objects.
ivPreview.setOnObjectClickListener { objectImage ->
startProductImageSearch(objectImage)
}
onObjectClickListener
は、ユーザーが画面上の検出されたオブジェクトのいずれかをタップするたびに呼び出されます。選択したオブジェクトのみを含む切り抜き画像を受け取ります。たとえば、ユーザーが右側のドレスを着ている人物をタップすると、リスナーは次のように objectImage
でトリガーされます。
onObjectClickListener に渡される切り抜き画像の例
切り抜いた画像を商品検索アクティビティに送信する
次に、クエリ画像を Vision API Product Search バックエンドに送信するロジックを別のアクティビティ(ProductSearchActivity
)に実装します。
すべての UI コンポーネントは事前に実装されているため、商品検索バックエンドと通信するコードの作成に集中できます。
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 を start-activity インテントに含めます。これにより、
ProductSearchActivity
が後で取得してクエリ画像として使用できるようになります。
ただし、気を付けていただきたい点がいくつかあります。
- オブジェクトの検出とバックエンドのクエリのロジックは、この Codelab をわかりやすくするために 2 つのアクティビティに分割されています。アプリに実装する方法は、デベロッパーが自由に決めることができます。
- クエリ画像は 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 のツールバーで [実行]()をクリックします。
アプリが読み込まれたら、プリセット画像をタップして、検出されたオブジェクトのいずれかを選択します。
タップした画像とともに ProductSearchActivity
が表示されることを確認します。[Search] ボタンはまだ機能していませんが、次はこれを実装します。
検出されたオブジェクトのいずれかをタップすると、同様の画面が表示されます。
5. 商品検索バックエンドを調べる
商品画像検索のバックエンドをビルドする
この Codelab では、Vision API Product Search で構築された商品検索バックエンドが必要です。これには 2 つの方法があります。
オプション 1: デプロイ済みのデモ バックエンドを使用する
この Codelab は、Google がすでにデプロイしている商品検索バックエンドを使用して進めることができます。デモ バックエンドは、Vision API Product Search のクイックスタートに沿って複製できます。
オプション 2: Vision API Product Search のクイックスタートに沿って独自のバックエンドを作成する
このオプションは、商品検索バックエンドの構築方法を詳しく学び、後で独自の商品カタログ用に構築したい方におすすめします。以下が必要となります。
- 課金が有効になっている Google Cloud アカウント。(無料トライアル アカウントでも構いません)。
- プロジェクトやサービス アカウントなど、Google Cloud のコンセプトに関する知識があること。
この方法については、後ほどラーニング パスで学習します。
重要なコンセプトを学ぶ
商品検索バックエンドを操作する際に、次のコンセプトに遭遇します。
- 商品セット: 商品セットは、商品のグループを格納するためのシンプルなコンテナです。商品カタログは、商品セットとその商品として表すことができます。
- 商品: 商品セットを作成したら、商品を作成して商品セットに追加できます。
- 商品の参照画像: 商品のさまざまなビューを含む画像です。参照画像は、見た目が類似した商品を検索するために使用されます。
- 商品を検索する: 商品セットを作成してインデックスを登録すると、Cloud Vision API を使用して商品セットをクエリできます。
プリセットの商品カタログについて
この Codelab で使用されている商品検索デモのバックエンドは、Vision API Product Search と、約 100 個の靴とドレスの画像の商品カタログを使用して作成されました。カタログの画像は次のとおりです。
プリセットのプロダクト カタログの例
商品検索デモのバックエンドを呼び出す
Google Cloud API キーを設定し、API キーへのアクセスをアプリのみに制限することで、モバイルアプリから Vision API Product Search を直接呼び出すことができます。
この Codelab を簡素化するため、API キーと認証を気にすることなくデモ バックエンドにアクセスできるプロキシ エンドポイントが設定されています。モバイルアプリから HTTP リクエストを受信し、API キーを追加して、Vision API Product Search バックエンドにリクエストを転送します。プロキシはバックエンドからレスポンスを受信し、モバイルアプリに返します。
- プロキシ エンドポイント:
https://us-central1-odml-codelabs.cloudfunctions.net/productSearch
- プロキシの動作: 適切な認証ヘッダーを追加し、API リクエストを Vision API Product Search バックエンドに転送します。たとえば、
https://us-central1-odml-codelabs.cloudfunctions.net/productSearch/images:annotate
への API 呼び出しはhttps://vision.googleapis.com/v1/images:annotate
に転送されます。
この Codelab では、Vision API Product Search の次の 2 つの API を使用します。
- projects.locations.images.annotate: クエリ画像をサーバーに送信し、クエリ画像と視覚的に類似する商品のリストをプリセットされた商品カタログから受け取ります。
- projects.locations.products.referenceImages.get: 上記の API 呼び出しで返された商品画像の URI を取得して、ユーザーに表示します。
6. API クライアントを実装する
商品検索のワークフローを理解する
バックエンドで商品検索を行うには、次のワークフローに従います。
- クエリ画像を base64 文字列としてエンコードする
- クエリ画像を使用して projects.locations.images.annotate エンドポイントを呼び出す
- 前の API 呼び出しから商品画像 ID を受け取り、projects.locations.products.referenceImages.get エンドポイントに送信して、検索結果の商品画像の URI を取得します。
API クライアント クラスを実装する
次に、ProductSearchAPIClient
という専用のクラスで商品検索バックエンドを呼び出すコードを実装します。スターター アプリには、いくつかのボイラープレート コードが実装されています。
class ProductSearchAPIClient
: このクラスは現在ほとんど空ですが、この Codelab の後半で実装するメソッドがいくつか含まれています。fun convertBitmapToBase64(bitmap: Bitmap)
: Bitmap インスタンスを base64 表現に変換して、商品検索バックエンドに送信します。fun annotateImage(image: Bitmap): Task<List<ProductSearchResult>>
: projects.locations.images.annotate 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 は、プロダクト検索バックエンドがデプロイされている Cloud ロケーションです。
us-east1
は、デモ バックエンドをデプロイした場所です。 - VISION_API_PRODUCT_SET_ID は、視覚的に類似した商品を検索する商品カタログ(Vision API の用語では「商品セット」)の ID です。1 つの Cloud プロジェクトに複数のカタログを設定できます。
product_set0
は、デモ バックエンドのプリセット商品カタログです。
7. 商品検索 API を呼び出す
API リクエストとレスポンスの形式を確認する
指定された画像に類似する商品を検索するには、画像の Google Cloud Storage URI、ウェブ URL、または base64 でエンコードされた文字列を Vision API Product Search に渡します。この Codelab では、クエリ画像がユーザーのデバイスにのみ存在するため、base64 エンコードされた文字列オプションを使用します。
このリクエスト JSON 本文を使用して、projects.locations.images.annotate エンドポイントに POST リクエストを送信する必要があります。
{
"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-encoded-image: クエリ画像のバイナリデータの base64 表現(ASCII 文字列)。
- project-id: GCP プロジェクト ID。
- location-id: 有効なロケーション識別子。
- product-set-id: 操作を行う商品セットの ID。
商品カタログには靴とドレスの画像のみが含まれているため、productCategories を apparel-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}
です。この参照画像の URL を取得して画面に表示するには、projects.locations.products.referenceImages.get に別の API リクエストを送信する必要があります。 - 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 呼び出しを実装する
次に、商品検索 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 のツールバーで [実行]()をクリックします。アプリが読み込まれたら、プリセット画像のいずれかをタップし、検出されたオブジェクトを選択して、[検索] ボタンをタップすると、バックエンドから返された検索結果が表示されます。次のような出力が表示されます。
商品検索結果画面のスクリーンショット
バックエンドは、プリセットされた商品カタログから視覚的に類似する商品のリストをすでに返しています。ただし、商品画像はまだ空のままです。これは、projects.locations.images.annotate エンドポイントが projects/odml-codelabs/locations/us-east1/products/product_id77/referenceImages/image77
などの商品画像 ID のみを返すためです。projects.locations.products.referenceImages.get エンドポイントに対して別の API 呼び出しを行い、このリファレンス画像の URL を取得して画面に表示する必要があります。
8. 商品の参照画像を取得する
API リクエストとレスポンスの形式を確認する
projects.locations.products.referenceImages.get エンドポイントに空のリクエスト本文を含む GET HTTP リクエストを送信して、商品検索エンドポイントから返された商品画像の 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: 参照画像の識別子
- uri: Google Cloud Storage(GCS)上の画像の URI。
デモ商品検索バックエンドの参照画像は、public-read 権限を持つように設定されています。そのため、GCS URI を HTTP URL に簡単に変換して、アプリの UI に表示できます。gs://
接頭辞を https://storage.googleapis.com/
に置き換えるだけで済みます。
API 呼び出しを実装する
次に、商品検索 API リクエストを作成してバックエンドに送信します。Volley と Task API は、商品検索 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
}
このメソッドは、商品検索エンドポイントから返された searchResult: ProductSearchResult
オブジェクトを受け取り、次の手順を実行します。
- 参照画像エンドポイントを呼び出して、参照画像の GCS URI を取得します。
- GCS URI を HTTP URL に変換します。
- この HTTP URL を使用して、
searchResult
オブジェクトのhttpUri
プロパティを更新します。
2 つの API リクエストを接続する
annotateImage
に戻り、すべての参照画像の HTTP URL を取得してから、呼び出し元に ProductSearchResult
リストを返すように変更します。
次に示す行を探します。
// 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 のツールバーで [実行]()をクリックします。アプリが読み込まれたら、プリセットされた画像をタップし、検出されたオブジェクトを選択して、[検索] ボタンをタップすると、今度は商品の画像とともに検索結果が表示されます。
商品検索の結果は適切ですか?
9. 完了
Vision API Product Search バックエンドを呼び出して、Android アプリに商品画像検索機能を追加する方法を学びました。これで、アプリを起動して実行できます。
必要に応じて、商品カタログを使用して独自のバックエンドを構築することもできます。商品画像検索の学習パスの次の Codelab では、独自のバックエンドを構築し、モバイルアプリから呼び出すための API キーを設定する方法について説明します。
学習した内容
- Android アプリから Vision API Product Search バックエンドを呼び出す方法
次のステップ
- 独自のバックエンドを構築する方法については、Vision API Product Search を使用して商品画像検索バックエンドを構築する Codelab をご覧ください。
- オンデバイス機械学習のウェブサイトで、その他の学習プログラムを確認する
- 独自の Android アプリに商品検索機能を組み込む