Backend de Product Search de la API de Call Vision en Android

1. Antes de comenzar

bd8c01b2f8013c6d.png

¿Ya viste la demostración de Google Lens, en la que puedes apuntar la cámara de tu teléfono hacia un objeto para encontrar dónde puedes comprarlo en línea? Si deseas aprender a agregar la misma función a tu app, este codelab es para ti. Es parte de una ruta de aprendizaje que enseña a compilar una función de búsqueda de imágenes de productos en una app para dispositivos móviles.

En este codelab, aprenderás a llamar a un backend compilado con Vision API Product Search desde una app para dispositivos móviles. Este backend puede tomar una imagen de consulta y buscar productos visualmente similares desde un catálogo de productos.

Puede obtener información sobre los pasos restantes para crear una función visual de búsqueda de productos, por ejemplo, cómo usar la detección y seguimiento de objetos del Kit de AA para detectar objetos en la imagen de consulta y permitir que los usuarios elijan qué producto quieren buscar. , en la ruta de aprendizaje.

Qué compilarás

  • En este codelab, comenzarás con la app para Android que puede detectar objetos de una imagen de entrada. Escribirás código para tomar el objeto que el usuario seleccione, enviarlo al backend de búsqueda de productos y mostrar el resultado de la búsqueda en la pantalla.
  • Al final, deberías ver algo similar a la imagen de la derecha.

Qué aprenderá

  • Cómo llamar y analizar la respuesta de las API de Vision Product Search desde una app para Android

Requisitos

  • Una versión reciente de Android Studio (v4.1.2 o posterior)
  • Android Studio Emulator o un dispositivo Android físico
  • El código de muestra
  • Conocimientos básicos sobre el desarrollo para Android en Kotlin

Este codelab se enfoca en Product Search de la API de Vision. Los conceptos y los bloques de código no relevantes no se exploran y se proporcionan para que simplemente los copies y los pegues.

2. Acerca de Product Search de la API de Vision

La API de Vision de Product Search es una función de Google Cloud que permite que los usuarios busquen productos visualmente similares desde un catálogo de productos. Los minoristas pueden crear productos, cada uno con imágenes de referencia que describen visualmente el producto desde un conjunto de puntos de vista. Luego, puede agregar estos productos a conjuntos de productos (p.ej., catálogo de productos). Por el momento, Product Search de la API de Vision admite las siguientes categorías de productos: electrodomésticos, indumentaria, juguetes, productos envasados y general.

Cuando los usuarios consultan el conjunto de productos con sus propias imágenes, Product Search de la API de Vision aplica el aprendizaje automático para comparar el producto en la imagen de consulta del usuario con las imágenes del conjunto de productos del minorista y, luego, muestra una lista de clasificaciones con resultados visualmente similares y semánticos.

3. Descarga y ejecuta la app inicial

Descarga el código

Haz clic en el siguiente vínculo a fin de descargar todo el código de este codelab:

Descargar código fuente

Descomprime el archivo zip descargado. Esto descomprimirá una carpeta raíz (odml-pathways-main) con todos los recursos que necesitarás. Para este codelab, solo necesitarás las fuentes del subdirectorio product-search/codelab2/android.

El subdirectorio codelab2 en el repositorio odml-pathways contiene dos directorios:

  • android_studio_folder.pngstarter: Código inicial en el que se basa este codelab.
  • android_studio_folder.pngfinal: Código completo para la app de muestra finalizada.

La app de inicio aquí es la que compilaste en el codelab Detect objetos en imágenes para compilar una búsqueda visual de productos: Android. Usa la detección y seguimiento de objetos del Kit de AA para detectar objetos de una imagen y mostrarlos en la pantalla.

Importa la app a Android Studio

Para comenzar, importa la app de starter a Android Studio.

Ve a Android Studio, selecciona Import Project (Gradle, Eclipse ADT, etc.) y elige la carpeta starter del código fuente que descargaste antes.

7c0f27882a2698ac.png

Cómo ejecutar la app de inicio

Ahora que importaste el proyecto a Android Studio, puedes ejecutar la app por primera vez. Conecta tu dispositivo Android mediante USB a tu host o inicia el emulador de Android Studio y haz clic en Run ( execute.png) en la barra de herramientas de Android Studio.

(Si se inhabilita este botón, asegúrate de importar solo starter/app/build.gradle, no todo el repositorio).

La app debería haberse iniciado en tu dispositivo Android. Ya tiene la capacidad de detección de objetos: puede detectar elementos de moda de la imagen y mostrarte dónde están. Prueba las fotos predeterminadas para confirmar la acción.

c6102a808fdfcb11.png

Captura de pantalla de la app de inicio que puede detectar objetos en una imagen

A continuación, extenderás la app para enviar los objetos detectados al backend de Product Search de la API de Vision y se mostrarán los resultados de la búsqueda en la pantalla.

4. Cómo controlar la selección de objetos

Permite que los usuarios presionen un objeto detectado para seleccionarlo

Ahora agregará código para permitir que los usuarios seleccionen un objeto de la imagen y comiencen la búsqueda de productos. La app de inicio ya tiene la capacidad de detectar objetos en la imagen. Es posible que haya varios objetos en la imagen o que el objeto detectado solo ocupe una pequeña parte de la imagen. Por lo tanto, debes pedirle al usuario que presione uno de los objetos detectados para indicar qué objeto quiere usar en la búsqueda de productos.

9cdfcead6d95a87.png

Una captura de pantalla de los artículos de moda que se detectaron de la imagen

A fin de que el codelab sea sencillo y se centre en el aprendizaje automático, se implementó código estándar de Android en la app de inicio para ayudarte a detectar los objetos que el usuario presionó. La vista que muestra la imagen en la actividad principal (ObjectDetectorActivity) es, de hecho, una vista personalizada (ImageClickableView) que extiende el elemento ImageView predeterminado del SO Android. Implementa métodos de utilidad convenientes, como los siguientes:

  • fun setOnObjectClickListener(listener: ((objectImage: Bitmap) -> Unit)) Esta es una devolución de llamada para recibir la imagen recortada que contiene solo el objeto que el usuario presionó. Enviará esta imagen recortada al backend de Product Search.

Agregar código para controlar cómo un usuario presiona los objetos detectados

Ve al método initViews en la clase ObjectDetectorActivity y agrega estas líneas al final del método: (Android Studio te indicará que no puede encontrar el startProductImageSearch . No se preocupe, ya que lo implementará más adelante.

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

Se llama a onObjectClickListener cada vez que el usuario presiona cualquiera de los objetos detectados en la pantalla. Recibe la imagen recortada que contiene solo el objeto seleccionado. Por ejemplo, si el usuario presiona la persona que usa el vestido a la derecha, el objeto de escucha se activará con objectImage como se muestra a continuación.

9cac8458d0f326e6.png

Ejemplo de la imagen recortada que se pasó a onObjectClickListener

Cómo enviar la imagen recortada a la actividad de búsqueda de productos

Ahora, implementarás la lógica de enviar la imagen de consulta al backend de Product Search de la API de Vision en una actividad separada (ProductSearchActivity).

Todos los componentes de la IU se implementaron de forma anticipada para que puedas enfocarte en escribir el código a fin de comunicarte con el backend de búsqueda de productos.

25939f5a13eeb3c3.png

Una captura de pantalla de los componentes de la IU en ProductSearchActivity

Agrega código a fin de enviar la imagen del objeto que el usuario seleccionó a ProductSearchActivity.

Regresa a Android Studio y agrega este método startProductImageSearch a la clase 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)
    }
}

El fragmento de código realiza 3 acciones:

  • Toma la imagen recortada y la serializa a un archivo PNG.
  • Inicia el ProductSearchActivity para ejecutar la secuencia de búsqueda de productos.
  • Incluye el URI de la imagen recortada en el intent de la actividad de inicio a fin de que ProductSearchActivity pueda recuperarlo más tarde para usarlo como imagen de consulta.

Debe tener en cuenta lo siguiente:

  • La lógica para detectar objetos y consultar el backend se dividió en 2 actividades a fin de facilitar el entendimiento del codelab. Tú decides cómo implementarlas en tu app.
  • Debes escribir la imagen de consulta en un archivo y pasar el URI de imagen entre actividades porque la imagen puede superar el límite de tamaño de 1 MB de un intent de Android.
  • Puede almacenar la imagen de la consulta en PNG porque es un formato sin pérdidas.

Recuperar la imagen de la búsqueda en la actividad de búsqueda de productos

En ProductSearchActivity, el código para recuperar la imagen de la consulta y mostrarla en la pantalla ya se implementó en la app de inicio.

Ve al método onCreate y confirma que este código ya está allí:

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

Ejecuta la app

Ahora, haz clic en Run ( execute.png) en la barra de herramientas de Android Studio.

Una vez que se cargue la app, presiona las imágenes predeterminadas y selecciona uno de los objetos detectados.

Confirma que se muestre la ProductSearchActivity con la imagen que presionaste. El botón Search todavía no hace nada, pero lo implementaremos a continuación.

fed40f81b8b43801.png

Deberías ver una pantalla similar después de presionar uno de los objetos detectados.

5. Explora el backend de búsqueda de productos

Compile el backend de búsqueda de imágenes de productos.

Este codelab requiere un backend de búsqueda de productos compilado con Vision Product Search de la API. Hay dos opciones para lograrlo:

Opción 1: Use el backend de demostración que se implementó para usted

Para continuar con este codelab, usa el backend de Product Search que Google ya implementó por ti. El backend de demostración se puede replicar mediante la guía de inicio rápido de Product Search de la API de Vision.

Opción 2: Crea tu propio backend siguiendo la guía de inicio rápido de Product Search de la API de Vision

Esta opción se recomienda para quienes desean obtener información detallada sobre cómo crear un backend de búsqueda de productos, de modo que luego puedas crear uno para tu propio catálogo de productos. Debe tener lo siguiente:

  • Una cuenta de Google Cloud con facturación habilitada (puede ser una cuenta de prueba gratuita).
  • Conocimiento sobre los conceptos de Google Cloud, como los proyectos, las cuentas de servicio, etcétera

Puedes aprender a hacerlo más adelante en la ruta de aprendizaje.

Aprende los conceptos importantes

Encontrará estos conceptos cuando interactúe con el backend de Product Search:

  • Conjunto de productos: Un conjunto de productos es un contenedor simple para un grupo de productos. Un catálogo de productos se puede representar como un conjunto de productos y sus productos.
  • Producto: Después de crear un conjunto de productos, puedes crear productos y agregarlos al conjunto.
  • Las imágenes de referencia de los productos son imágenes que contienen varias vistas de estos. Las imágenes de referencia se usan para buscar productos visualmente similares.
  • Buscar productos: Una vez que haya creado su conjunto de productos y que este se haya indexado, puede consultarlo con la API de Cloud Vision.

Comprende el catálogo de productos predeterminado

El backend de demostración de búsqueda de productos que se usó en este codelab se creó con la API de Vision para Product Search y un catálogo de productos con alrededor de cien zapatos e imágenes de vestir. Estas son algunas imágenes del catálogo:

4f1a8507b74ab178.png 79a5fc6c829eca77.png 3528c872f813826e.png

Ejemplos del catálogo de productos predeterminado

Llamar al backend de demostración de búsqueda de productos

Puede llamar a Product Search de la API de Vision directamente desde una aplicación para dispositivos móviles si configura una clave de API de Google Cloud y restringe el acceso a la clave de API solo a su aplicación.

Para simplificar este codelab, se configuró un extremo de proxy que te permite acceder al backend de demostración sin preocuparte por la clave de API ni la autenticación. Recibe la solicitud HTTP de la aplicación para dispositivos móviles, agrega la clave de API y reenvía la solicitud al backend de Product Search de la API de Vision. Luego, el proxy recibe la respuesta del backend y la muestra en la aplicación para dispositivos móviles.

En este codelab, usarás dos API de Vision API Product Search:

6. Implementa el cliente de la API

Comprende el flujo de trabajo de Product Search

Sigue este flujo de trabajo para realizar búsquedas de productos con el backend:

Cómo implementar la clase de cliente de API

Ahora, implementarás el código para llamar al backend de búsqueda de productos en una clase dedicada llamada ProductSearchAPIClient. Se implementó parte del código estándar en la app de inicio:

  • class ProductSearchAPIClient: Esta clase está mayormente vacía, pero tiene algunos métodos que implementarás más adelante en este codelab.
  • fun convertBitmapToBase64(bitmap: Bitmap): Convierte una instancia de mapa de bits en su representación base64 para enviarla al backend de búsqueda de productos.
  • fun annotateImage(image: Bitmap): Task<List<ProductSearchResult>>: Llama a la API projects.locations.images.annotation y analiza la respuesta.
  • fun fetchReferenceImage(searchResult: ProductSearchResult): Task<ProductSearchResult>: Llama a la API de projects.locations.products.referenceImages.get y analiza la respuesta.
  • SearchResult.kt: Este archivo contiene varias clases de datos para representar los tipos que muestra el backend de Product Search de la API de Vision.

Especifique los parámetros de configuración de la API

Ve a la clase ProductSearchAPIClient y verás algunas opciones de configuración del backend de Product Search ya definidas:

// 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 es el extremo de la API de Cloud Vision. Cuando continúes con el backend de demostración, configúralo en el extremo del proxy. Sin embargo, si implementa su propio backend, deberá cambiarlo al extremo de la API de Cloud Vision. https://vision.googleapis.com/v1.
  • VISION_API_KEY es la clave de API de tu proyecto de Cloud. Como el proxy ya controla la autenticación, puedes dejar este campo en blanco.
  • VISION_API_PROJECT_ID es el ID del proyecto de Cloud. odml-codelabs es el proyecto de Cloud en el que se implementa el backend de demostración.
  • VISION_API_LOCATION_ID es la ubicación de Cloud en la que se implementa el backend de búsqueda de productos. us-east1 es donde implementamos el backend de demostración.
  • VISION_API_PRODUCT_SET_ID es el ID del catálogo de productos (también llamado “conjunto de productos” en el término de la API de Vision) en el que desea buscar productos visualmente similares. Puedes tener varios catálogos en un proyecto de Cloud. product_set0 es el catálogo de productos predeterminado del backend de demostración.

7. Llama a la API de Product Search

Explore el formato de solicitud y respuesta de la API

Puedes encontrar productos similares a una imagen determinada si pasas el URI de Google Cloud Storage, la URL web o la string codificada en base 64 a Product Search de la API de Vision. En este codelab, usarás la opción de string codificada en Base 64, ya que nuestra imagen de consulta solo existe en el dispositivo del usuario.

Debe enviar una solicitud POST al extremo projects.locations.images.annotation con este cuerpo de JSON de solicitud:

{
  "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"
          ],
        }
      }
    }
  ]
}

Se deben especificar algunos parámetros:

  • base64-encoded-image: es la representación en base64 (string ASCII) de los datos binarios de la imagen de consulta.
  • project-id: Es el ID de tu proyecto de GCP.
  • location-id: Es un identificador de ubicación válido.
  • product-set-id: Es el ID del conjunto de productos en el que deseas ejecutar la operación.

Dado que tu catálogo de productos solo contiene imágenes de calzado y vestido, especifica que las Categorías de productos sean apparel-v2. En este caso, v2 significa que usamos la versión 2 del modelo de aprendizaje automático de búsquedas de productos de indumentaria.

Si la solicitud se realiza correctamente, el servidor muestra un código de estado HTTP 200 OK y la respuesta en formato JSON. El JSON de respuesta incluye los siguientes dos tipos de resultados:

  • productSearchResults: Contiene una lista de productos coincidentes para toda la imagen.
  • productGroupedResults: Contiene coordenadas de cuadro de límite y elementos coincidentes para cada producto identificado en la imagen.

Debido a que el producto ya se recortó a partir de la imagen original, analizará los resultados en la lista productSearchResults.

Estos son algunos campos importantes del objeto de los resultados de la búsqueda de productos:

  • product.name: El identificador único de un producto con el formato projects/{project-id}/locations/{location-id}/products/{product_id}
  • product.score: un valor que indica qué tan similar es el resultado de la búsqueda a la imagen de la consulta. Los valores más altos significan más similitud.
  • product.image: es el identificador único de la imagen de referencia de un producto en el formato projects/{project-id}/locations/{location-id}/products/{product_id}/referenceImages/{image_id}. Deberás enviar otra solicitud de API a projects.locations.products.referenceImages.get para obtener la URL de esta imagen de referencia a fin de que se muestre en la pantalla.
  • product.labels: Una lista de etiquetas predefinidas del producto. Esto resulta útil si deseas filtrar los resultados de la búsqueda para mostrar solo una categoría de ropa, como vestidos.

Convierta la imagen de consulta en base64

Debe convertir la imagen de la consulta en su representación de string base64 y adjuntar la string al objeto JSON en el cuerpo de la solicitud.

Ve a la clase ProductSearchAPIClient, busca el método convertBitmapToBase64 vacío y reemplázalo por esta implementación:

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)
}

Cómo implementar la llamada a la API

A continuación, crea una solicitud a la API de búsqueda de productos y envíala al backend. Usarás Volley para realizar la solicitud a la API y mostrar el resultado con la API de Task.

Regresa a la clase ProductSearchAPIClient, busca el método annotateImage vacío y reemplázalo por esta implementación:

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
}

Cómo mostrar el resultado de la búsqueda en la IU

El código de API en ProductSearchAPIClient ya está listo. Regresa a la actividad ProductSearchActivity para implementar el código de IU.

La actividad ya tiene código estándar que activa el método searchByImage(queryImage: Bitmap). Se agregó código para llamar al backend y mostrar los resultados en la IU en este método actualmente vacío.

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

El método showSearchResult contiene código estándar que analiza la respuesta de la API y los muestra en la pantalla por ti.

Ejecuta el código

Ahora, haz clic en Run ( execute.png) en la barra de herramientas de Android Studio. Cuando se cargue la app, presiona las imágenes preestablecidas, selecciona un objeto detectado, presiona el botón Buscar y verás los resultados que se muestran desde el backend. Verá un resultado similar al que se detalla a continuación:

bb5e7c27c283a2fe.png

Captura de pantalla de la pantalla de resultados de la búsqueda de productos

El backend ya muestra una lista de productos visualmente similares del catálogo de productos predeterminado. Sin embargo, puedes ver que la imagen del producto aún está vacía. Esto se debe a que el extremo projects.locations.images.annotation solo muestra los ID de la imagen del producto, como projects/odml-codelabs/locations/us-east1/products/product_id77/referenceImages/image77. Deberás realizar otra llamada a la API para el extremo projects.locations.products.referenceImages.get y obtener la URL de esta imagen de referencia a fin de mostrarla en la pantalla.

8. Obtenga las imágenes de referencia del producto

Explore el formato de solicitud y respuesta de la API

Enviará una solicitud GET HTTP con un cuerpo de solicitud vacío al extremo projects.locations.products.referenceImages.get para obtener los URI de las imágenes del producto que muestra el extremo de búsqueda de productos.

La solicitud HTTP luce de la siguiente manera:

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

Si la solicitud se realiza correctamente, el servidor muestra un código de estado HTTP 200 OK y la respuesta en formato JSON, como se muestra a continuación:

{
  "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: Identificador de la imagen de referencia
  • uri: Es el URI de la imagen en Google Cloud Storage (GCS).

Las imágenes de referencia del backend de búsqueda de productos de demostración se configuraron para tener permiso de lectura pública. Por lo tanto, puedes convertir fácilmente el URI de GCS en una URL HTTP y mostrarla en la IU de la app. Solo debes reemplazar el prefijo gs:// por https://storage.googleapis.com/.

Cómo implementar la llamada a la API

A continuación, crea una solicitud a la API de búsqueda de productos y envíala al backend. Usarás Volley y la API de tareas de manera similar a la llamada a la API de Product Search.

Regresa a la clase ProductSearchAPIClient, busca el método fetchReferenceImage vacío y reemplázalo por esta implementación:

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
}

Este método toma un objeto searchResult: ProductSearchResult que mostró el extremo de búsqueda de productos y, luego, sigue estos pasos:

  1. Llama al extremo de la imagen de referencia para obtener el URI de GCS de la imagen de referencia.
  2. Convierte el URI de GCS en una URL HTTP.
  3. Actualiza la propiedad httpUri del objeto searchResult con esta URL HTTP.

Conecta las dos solicitudes a la API

Regresa a annotateImage y modifícala para obtener todas las URL HTTP de las imágenes de referencia antes de mostrar la lista ProductSearchResult a su emisor.

Busca esta línea:

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

Luego, reemplácelo por esta implementación:

// 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) }

El código estándar para mostrar las imágenes de referencia en la pantalla ya está implementado en la clase ProductSearchAdapter. De esta manera, podrás volver a ejecutar la app.

Ejecuta el código

Ahora, haz clic en Run ( execute.png) en la barra de herramientas de Android Studio. Una vez que se cargue la app, presiona las imágenes preestablecidas, selecciona un objeto detectado y presiona el botón Buscar para ver los resultados de la búsqueda, pero con las imágenes del producto.

¿Considera que los resultados de la búsqueda de productos son útiles?

25939f5a13eeb3c3.png

9. ¡Felicitaciones!

Aprendiste a llamar a un backend de Product Search de la API de Vision a fin de agregar la función de búsqueda de imágenes del producto a tu app para Android. ¡Eso es todo lo que necesitas para ponerte en marcha!

A medida que avanzas, puedes compilar tu propio backend usando tu catálogo de productos. Consulta el siguiente codelab en la ruta de aprendizaje de Product Image Search para aprender a compilar tu propio backend y configurar la clave de API a fin de llamarlo desde una app para dispositivos móviles.

Temas abordados

  • Cómo llamar al backend de Product Search de la API de Vision desde una app para Android

Próximos pasos

Más información