Call Vision API-Produktsuche-Back-End unter Android

1. Hinweis

bd8c01b2f8013c6d

Haben Sie die Google Lens-Demo gesehen, wo Sie die Kamera Ihres Smartphones auf ein Objekt ausrichten können und herausfinden, wo Sie es online kaufen können? Wenn Sie wissen möchten, wie Sie Ihrer App dieselben Funktionen hinzufügen können, ist dieses Codelab genau das Richtige für Sie. Sie ist Teil eines Lernpfads, in dem die Funktionsweise einer Produktbildfunktion in einer mobilen App erläutert wird.

In diesem Codelab lernen Sie, wie Sie mit einer Vision API-Produktsuche ein Back-End aus einer mobilen App aufrufen. Dieses Back-End kann ein Abfragebild abrufen und nach visuell ähnlichen Produkten aus einem Produktkatalog suchen.

Weitere Informationen zum Erstellen einer visuellen Produktsuchfunktion, einschließlich der Nutzung von ML Kit Objekterkennung und Tracking, um Objekte im Abfragebild zu erkennen und Nutzern die Auswahl des Produkts zu ermöglichen, finden Sie in diesem Lernpfad.

Inhalte, die Sie erstellen werden

  • In diesem Codelab starten Sie mit der Android-App, die Objekte aus einem Eingabebild erkennen kann. Sie schreiben Code, um das vom Nutzer ausgewählte Objekt aufzunehmen, es an das Back-End der Produktsuche zu senden und das Suchergebnis auf dem Bildschirm anzuzeigen.
  • Am Ende sollte ein Bild wie das Bild auf der rechten Seite zu sehen sein.

Lerninhalte

  • Antwort der Vision API-Produktsuche-APIs über eine Android-App aufrufen und parsen

Voraussetzungen

  • Eine aktuelle Version von Android Studio (Version 4.1.2 oder höher)
  • Android Studio Emulator oder physisches Android-Gerät
  • Beispielcode
  • Grundkenntnisse der Android-Entwicklung in Kotlin

In diesem Codelab geht es um die Vision API-Produktsuche. Nicht relevante Konzepte und Codeblöcke werden nicht untersucht und können einfach kopiert und eingefügt werden.

2. Vision API-Produktsuche

Die Vision API-Produktsuche ist eine Funktion in Google Cloud, mit der Nutzer in einem Produktkatalog nach ähnlichen Produkten suchen können. Einzelhändler können Produkte mit Referenzbildern erstellen, die das Produkt aus verschiedenen Blickwinkeln beschreiben. Anschließend können Sie diese Produkte in Produktgruppen einfügen (d.h. in einem Produktkatalog). Derzeit unterstützt die Vision API-Produktsuche die folgenden Produktkategorien: Haushaltswaren, Bekleidung, Spielzeug, abgepackte Waren und allgemein.

Wenn ein Nutzer seine Produkte mit eigenen Bildern abfragen, wird die Produktsuche in der Vision API-Produktsuche mithilfe des maschinellen Lernens abgeglichen. So wird das Produkt in der Suchanfrage des Nutzers mit den Bildern aus der Produktgruppe verglichen. Anschließend wird eine Rangliste mit optisch und semantisch ähnlichen Ergebnissen zurückgegeben.

3. Start-App herunterladen und ausführen

Code herunterladen

Klicken Sie auf den folgenden Link, um den gesamten Code für dieses Codelab herunterzuladen:

Entpacken Sie die heruntergeladene ZIP-Datei. Dadurch wird ein Stammordner (odml-pathways-main) mit allen erforderlichen Ressourcen entpackt. Für dieses Codelab benötigen Sie nur die Quellen im Unterverzeichnis product-search/codelab2/android.

Das Unterverzeichnis codelab2 des Repositorys odml-pathways enthält zwei Verzeichnisse:

  • android_studio_folder.pngstarter: Startcode, auf dem Sie für dieses Codelab aufbauen.
  • android_studio_folder.pngfinal: Code für die fertige Beispiel-App abgeschlossen

Die Starter-App ist das Projekt, das Sie im Codelab entwickelt haben: Objekte in Bildern erkennen, um eine visuelle Produktsuche zu erstellen. Mit ML Kit Object Detection and Tracking werden Objekte aus einem Bild erkannt und auf dem Bildschirm angezeigt.

App in Android Studio importieren

Importieren Sie zuerst die Starter-App in Android Studio.

Gehen Sie zu Android Studio und wählen Sie Import Project (Gradle, Eclipse ADT usw.) und den Ordner starter aus dem Quellcode aus, den Sie zuvor heruntergeladen haben.

7c0f27882a2698ac

Starter-App ausführen

Nachdem Sie das Projekt in Android Studio importiert haben, können Sie die App jetzt zum ersten Mal ausführen. Verbinden Sie Ihr Android-Gerät per USB mit Ihrem Host oder starten Sie den Android Studio Emulator und klicken Sie in der Symbolleiste von Android Studio auf Ausführen (Ausführen.png).

Wenn diese Schaltfläche deaktiviert ist, achten Sie darauf, dass nur der Auslöser/app/build.gradle, nicht das gesamte Repository importiert wird.

Die App sollte jetzt auf Ihrem Android-Gerät installiert sein. Die Kamera kann bereits Objekte erkennen. Dazu werden Modeartikel aus dem Bild erkannt und Ihnen angezeigt, wo sie sich befinden. Versuchen Sie es mit den voreingestellten Fotos, um dies zu bestätigen.

c6102a808fdfcb11

Screenshot der Starter-App, die Objekte in einem Bild erkennen kann

Als Nächstes erweitern Sie die App, um die erkannten Objekte an das Vision API-Produktsuche-Back-End zu senden und die Suchergebnisse auf dem Bildschirm anzuzeigen.

4. Objektauswahl verarbeiten

Nutzer dürfen auf ein erkanntes Objekt tippen, um es auszuwählen

Fügen Sie nun Code hinzu, damit Nutzer ein Objekt aus dem Bild auswählen und die Produktsuche starten können. Die Starter-App hat bereits die Möglichkeit, Objekte im Bild zu erkennen. Es besteht die Möglichkeit, dass im Objekt mehrere Objekte zu sehen sind oder dass das erkannte Objekt nur einen kleinen Teil des Bildes einnimmt. Der Nutzer muss also auf eines der erkannten Objekte tippen, um anzugeben, welches Objekt zur Produktsuche verwendet werden soll.

9cdfcead6d95a87.png

Ein Screenshot der erkannten Modeartikel

Damit das Codelab einfach und übersichtlich bleibt und auf maschinelles Lernen ausgerichtet ist, wurde in der Start-App ein untergeordneter Boilerplate-Code implementiert. So können Sie erkennen, auf welches Objekt der Nutzer getippt hat. Die Ansicht, bei der das Bild in der Hauptaktivität (ObjectDetectorActivity) angezeigt wird, ist eine benutzerdefinierte Ansicht (ImageClickableView), die die standardmäßige ImageView von Android erweitert. Es werden einige praktische Hilfsmethoden implementiert, z. B.:

  • fun setOnObjectClickListener(listener: ((objectImage: Bitmap) -> Unit)) Dies ist ein Callback, der ein zugeschnittenes Bild erhält. Dieses Bild enthält nur das Objekt, auf das der Nutzer getippt hat. Sie senden dieses zugeschnittene Bild an das Produktsuch-Back-End.

Fügen Sie Code hinzu, wenn ein Nutzer auf die erkannten Objekte tippen soll.

Gehen Sie in der Klasse ObjectDetectorActivity zur initViews-Methode und fügen Sie die folgenden Zeilen am Ende der Methode hinzu: (Android Studio teilt Ihnen mit, dass die Methode startProductImageSearch nicht gefunden werden kann. Keine Sorge, Sie implementieren die Funktion etwas später.)

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

onObjectClickListener wird immer dann aufgerufen, wenn der Nutzer auf eines der erkannten Objekte auf dem Bildschirm tippt. Er erhält das zugeschnittene Bild, das nur das ausgewählte Objekt enthält. Wenn der Nutzer beispielsweise auf die Person tippt, die das Kleid rechts trägt, wird der Listener wie unten ausgelöst mit objectImage ausgelöst.

9cac8458d0f326e6.png

Beispiel für das zugeschnittene Bild, das an den onObjectClickListener übergeben wurde

Zugeschnittenes Bild an die Produktsuchaktivität senden

Jetzt implementieren Sie die Logik des Sendens des Abfragebildes an das Vision API-Produktsuche-Back-End in einer separaten Aktivität (ProductSearchActivity).

Alle UI-Komponenten wurden im Voraus implementiert, sodass Sie sich auf das Schreiben des Codes konzentrieren können, um mit dem Produktsuch-Back-End zu kommunizieren.

25939f5a13eeb3c3

Screenshot der UI-Komponenten in ProductSearchActivity

Fügen Sie Code hinzu, um das vom Nutzer ausgewählte Objektbild an ProductSearchActivity zu senden.

Kehren Sie zu Android Studio zurück und fügen Sie der Klasse ObjectDetectorActivity die folgende startProductImageSearch-Methode hinzu:

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

Das Code-Snippet hat drei Möglichkeiten:

  • Zeichnet das zugeschnittene Bild auf und serialisiert es in eine PNG-Datei.
  • Startet die ProductSearchActivity, um die Produktsuchsequenz auszuführen.
  • Enthält den Start-Aktivitäts-Intent durch den zugeschnittenen Bild-URI, damit ProductSearchActivity ihn später als Abfragebild abrufen kann.

Hier sind einige Hinweise dazu:

  • Die Logik für die Erkennung von Objekten und die Abfrage des Back-Ends wurde in zwei Aktivitäten unterteilt, damit das Codelab leichter verständlich ist. Sie entscheiden, wie sie in Ihrer App implementiert werden.
  • Sie müssen das Abfragebild in eine Datei schreiben und den Bild-URI zwischen den Aktivitäten übergeben, da das Abfragebild die Größenbeschränkung von 1 MB für einen Android-Intent überschreiten kann.
  • Sie können das Abfragebild im PNG-Format speichern, da es ein verlustfreies Format hat.

Suchanfrage in der Produktsuchaktivität abrufen

In ProductSearchActivity wurde der Code zum Abrufen des Abfragebildes und zum Anzeigen auf dem Bildschirm bereits in der Starter-App implementiert.

Rufen Sie die Methode onCreate auf und prüfen Sie, ob dieser Code bereits vorhanden ist:

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

App ausführen

Klicken Sie in der Android Studio Symbolleiste auf Ausführen (Ausführen.png).

Tippen Sie nach dem Laden der App auf alle voreingestellten Bilder und wählen Sie eines der erkannten Objekte aus.

Überprüfen Sie, ob die ProductSearchActivity mit dem Bild angezeigt wird, das Sie angetippt haben. Über die Schaltfläche Suchen gibt es noch nichts. Wir werden es aber als Nächstes implementieren.

fed40f81b8b43801

Nachdem Sie auf eines der erkannten Objekte getippt haben, sollte ein ähnlicher Bildschirm angezeigt werden.

5. Back-End der Produktsuche entdecken

Produkt-Back-End für die Produktsuche erstellen

Für dieses Codelab ist ein Back-End für die Produktsuche erforderlich, das mit der Vision API-Produktsuche erstellt wurde. Es gibt zwei Möglichkeiten, dies zu erreichen:

Option 1: Bereitgestelltes Demo-Back-End verwenden

Sie können mit diesem Codelab fortfahren. Dazu verwenden Sie das Produktsuch-Back-End, das Google bereits für Sie bereitgestellt hat. Sie können mithilfe der Kurzanleitung der Vision API-Produktsuche das Demo-Back-End replizieren.

Option 2: Mit der Kurzanleitung für die Vision API-Produktsuche ein eigenes Back-End erstellen

Diese Option eignet sich für Nutzer, die detaillierte Informationen zum Erstellen eines Back-Ends einer Produktsuche benötigen. So können sie später einen eigenen Produktkatalog erstellen. Sie benötigen Folgendes:

  • Google Cloud-Konto mit aktivierter Abrechnung. Es kann sich auch um ein kostenloses Probeabo handeln.
  • Einige Kenntnisse über Google Cloud-Konzepte, einschließlich Projekten, Dienstkonten usw.

Wie das geht, erfahren Sie im Lernpfad.

Wichtige Konzepte

Ihnen werden diese Konzepte bei der Interaktion mit dem Produktsuch-Back-End begegnen:

  • Produktgruppe: Eine Produktgruppe ist ein einfacher Container für eine Produktgruppe. Ein Produktkatalog kann als Produktgruppe und dessen Produkte dargestellt werden.
  • Produkt: Nachdem Sie eine Produktgruppe erstellt haben, können Sie Produkte erstellen und sie der Produktgruppe hinzufügen.
  • Referenzbilder für Produkte: Bilder mit verschiedenen Ansichten Ihrer Produkte. Referenzbilder werden zur Suche nach visuell ähnlichen Produkten verwendet.
  • Nach Produkten suchen: Nachdem Sie die Produktgruppe erstellt und indexiert haben, können Sie sie mit der Cloud Vision API abfragen.

Vordefinierter Produktkatalog

Das in diesem Codelab verwendete Produkt-Demo-Back-End wurde mit der Vision API-Produktsuche und einem Produktkatalog mit etwa 100 Schuhen und Kleidern erstellt. Hier sind einige Bilder aus dem Katalog:

4f1a8507b74ab178 79a5fc6c829eca77 3528c872f813826e.pngs

Beispiele aus dem voreingestellten Produktkatalog

Demo-Back-End der Produktsuche aufrufen

Sie können die Vision API-Produktsuche direkt von einer mobilen App aus aufrufen. Richten Sie dazu einen Google Cloud API-Schlüssel ein und beschränken Sie den Zugriff darauf auf nur Ihre App.

Um dieses Codelab einfach zu gestalten, wurde ein Proxy-Endpunkt eingerichtet, mit dem Sie auf das Demo-Back-End zugreifen können, ohne sich über den API-Schlüssel und die Authentifizierung Gedanken machen zu müssen. Er empfängt die HTTP-Anfrage von der mobilen App, hängt den API-Schlüssel an und leitet die Anfrage an das Vision API-Produktsuch-Back-End weiter. Anschließend erhält der Proxy die Antwort vom Back-End und gibt diese an die mobile App zurück.

In diesem Codelab nutzen Sie zwei APIs der Vision API-Produktsuche:

6. API-Client implementieren

Grundlegendes zur Produktsuche

Folge diesem Workflow, um die Produktsuche mit dem Back-End durchzuführen:

API-Clientklasse implementieren

Jetzt implementieren Sie Code, um das Back-End der Produktsuche in einer eigenen Klasse namens ProductSearchAPIClient aufzurufen. In der Starter-App wurde ein Boilerplate-Code implementiert:

  • class ProductSearchAPIClient: Diese Klasse ist derzeit weitgehend leer, aber es gibt einige Methoden, die Sie später in diesem Codelab implementieren werden.
  • fun convertBitmapToBase64(bitmap: Bitmap): Bitmap-Instanz in die base64-Darstellung umwandeln, um sie an das Produktsuch-Back-End zu senden
  • fun annotateImage(image: Bitmap): Task<List<ProductSearchResult>>: Rufen Sie die API projects.locations.images.Annotation auf und parsen Sie die Antwort.
  • fun fetchReferenceImage(searchResult: ProductSearchResult): Task<ProductSearchResult>: Rufen Sie die API projects.locations.products.referenceImages.get auf und parsen Sie die Antwort.
  • SearchResult.kt: Diese Datei enthält mehrere Datenklassen zur Darstellung der vom Back-End der Vision API-Produktsuche zurückgegebenen Typen.

API-Konfigurationen angeben

Rufen Sie die Klasse ProductSearchAPIClient auf. Sie sehen einige Konfigurationen des Back-Ends der Produktsuche:

// 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 ist der API-Endpunkt der Cloud Vision API. Legen Sie während des Demo-Back-Ends den Proxy-Endpunkt fest. Wenn Sie jedoch Ihr eigenes Back-End bereitstellen, müssen Sie es auf den Cloud Vision API-Endpunkt umstellen. https://vision.googleapis.com/v1.
  • VISION_API_KEY ist der API-Schlüssel Ihres Cloud-Projekts. Da der Proxy bereits die Authentifizierung durchführt, können Sie dieses Feld leer lassen.
  • VISION_API_PROJECT_ID ist die Cloud-Projekt-ID. odml-codelabs ist das Cloud-Projekt, in dem das Demo-Back-End bereitgestellt wird.
  • VISION_API_LOCATION_ID ist der Cloud-Standort, an dem das Produktsuch-Back-End bereitgestellt ist. Unter us-east1 wurde das Demo-Back-End bereitgestellt.
  • VISION_API_PRODUCT_SET_ID ist die ID des Produktkatalogs (auch „Set“ genannt), in dem Sie nach optisch ähnlichen Produkten suchen möchten. Sie können mehrere Kataloge in einem Cloud-Projekt haben. product_set0 ist der voreingestellte Produktkatalog des Demo-Back-Ends.

7. Produktsuche-API aufrufen

API-Anfrage- und Antwortformat ansehen

Sie können ähnliche Produkte zu einem bestimmten Bild finden, indem Sie den Google Cloud Storage-URI, die Web-URL oder den Base64-codierten String des Bilds an die Vision API-Produktsuche übergeben. In diesem Codelab verwenden Sie die base64-codierte Stringoption, weil unser Abfragebild nur auf dem Gerät des Nutzers vorhanden ist.

Sie müssen eine POST-Anfrage mit dem folgenden JSON-Texttext an den Endpunkt projects.locations.images.Annotation senden:

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

Einige Parameter müssen angegeben werden:

  • base64-encoded-image: die Base64-Darstellung (ASCII-String) der Binärdaten des Abfragebilds.
  • project-id: Die ID Ihres GCP-Projekts.
  • location-id: Eine gültige Standortkennzeichnung.
  • product-set-id: ID der Produktgruppe, für die der Vorgang ausgeführt werden soll.

Da Ihr Produktkatalog nur Bilder von Schuhen und Kleider enthält, geben Sie productcategories als apparel-v2 an. Version 2 bedeutet hier, dass wir Version 2 des Modells für maschinelles Lernen für Bekleidungsprodukte verwenden.

Wenn die Anfrage erfolgreich ist, gibt der Server den HTTP-Statuscode 200 OK und die Antwort im JSON-Format zurück. Der JSON-Antwortcode enthält die folgenden zwei Ergebnistypen:

  • productSearchResults – Enthält eine Liste übereinstimmender Produkte für das gesamte Bild.
  • productGroupedResults – Enthält Begrenzungsrahmen und übereinstimmende Elemente für jedes im Bild identifizierte Produkt.

Da das Produkt bereits aus dem Originalbild zugeschnitten ist, parsen Sie die Ergebnisse in der Liste productSearchResults.

Im Folgenden sind einige wichtige Felder des Produktsuchobjekts aufgeführt:

  • product.name: Die eindeutige Kennzeichnung eines Produkts im Format projects/{project-id}/locations/{location-id}/products/{product_id}.
  • product.score: Ein Wert, der angibt, wie ähnlich das Suchergebnis dem Anfragebild ist. Je höher die Werte, desto mehr Ähnlichkeiten sind vorhanden.
  • product.image: Das ist die eindeutige Kennzeichnung des Referenzbilds eines Produkts im Format projects/{project-id}/locations/{location-id}/products/{product_id}/referenceImages/{image_id}. Sie müssen eine weitere API-Anfrage an projects.locations.products.referenceImages.get senden, um die URL dieses Referenzbilds abzurufen, damit sie auf dem Bildschirm angezeigt wird.
  • product.labels: Eine Liste vordefinierter Tags für das Produkt. Dies ist hilfreich, wenn Sie die Suchergebnisse so filtern möchten, dass nur eine Kleiderkategorie angezeigt wird, z. B. Kleider.

Abfragebild in base64 konvertieren

Sie müssen das Abfragebild in die base64-Stringdarstellung konvertieren und den String im JSON-Objekt im Anfragetext anhängen.

Rufen Sie die ProductSearchAPIClient-Klasse auf, suchen Sie nach der leeren convertBitmapToBase64-Methode und ersetzen Sie sie durch diese Implementierung:

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-Aufruf implementieren

Erstellen Sie als Nächstes eine API für die Produktsuche und senden Sie sie an das Back-End. Sie verwenden Volley, um die API-Anfrage zu senden, und geben das Ergebnis über die Task API zurück.

Kehren Sie zur Klasse ProductSearchAPIClient zurück, suchen Sie die leere annotateImage-Methode und ersetzen Sie sie durch diese Implementierung:

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
}

Suchergebnis auf der Benutzeroberfläche anzeigen

Der API-Code in ProductSearchAPIClient ist jetzt bereit. Gehen Sie zurück zur Aktivität „ProductSearchActivity“, um den UI-Code zu implementieren.

Die Aktivität hat bereits einen Boilerplate-Code, durch den die Methode searchByImage(queryImage: Bitmap) ausgelöst wird. Fügen Sie Code hinzu, um das Back-End aufzurufen und Ergebnisse auf der UI in diese derzeit leere Methode anzuzeigen.

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

Die Methode showSearchResult enthält Textbausteine, mit denen die API-Antwort geparst wird und diese auf dem Bildschirm angezeigt werden.

Ausführen

Klicken Sie in der Android Studio Symbolleiste auf Ausführen (Ausführen.png). Sobald die App geladen ist, tippen Sie auf eines der voreingestellten Bilder, wählen Sie ein erkanntes Objekt aus und tippen Sie auf die Schaltfläche Suchen. Sie sehen dann die Suchergebnisse, die vom Back-End zurückgegeben wurden. Die Ansicht sieht ungefähr so aus:

bb5e7c27c283a2fe

Screenshot des Produktsuchergebnisses

Das Back-End gibt bereits eine Liste visuell ähnlicher Produkte aus dem voreingestellten Produktkatalog zurück. Sie sehen jedoch, dass das Produktbild noch leer ist. Das liegt daran, dass der Endpunkt projects.locations.images.Annotation nur Produkt-Image-IDs wie projects/odml-codelabs/locations/us-east1/products/product_id77/referenceImages/image77 zurückgibt. Sie müssen einen weiteren API-Aufruf an den Endpunkt projects.locations.products.referenceImages.get ausführen und die URL dieses Referenzbilds abrufen, um es auf dem Bildschirm anzuzeigen.

8. Produktreferenzbilder abrufen

API-Anfrage- und Antwortformat ansehen

Sie senden eine GET-HTTP-Anfrage mit einem leeren Anfragetext an den Endpunkt projects.locations.products.referenceImages.get, um die URIs der Produkt-Images abzurufen, die vom Endpunkt der Produktsuche zurückgegeben werden.

Die HTTP-Anfrage sieht so aus:

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

Wenn die Anfrage erfolgreich ist, gibt der Server den HTTP-Statuscode 200 OK und die Antwort im JSON-Format zurück:

{
  "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: Die Referenzbildkennung.
  • uri: Der URI des Bildes in Google Cloud Storage (GCS).

Die Referenzbilder des Demoprodukts zur Produktsuche wurden so konfiguriert, dass sie die Leseberechtigung haben. Daher lässt sich der GCS-URI problemlos in eine HTTP-URL konvertieren und auf der App-Benutzeroberfläche anzeigen lassen. Sie müssen das Präfix gs:// nur durch https://storage.googleapis.com/ ersetzen.

API-Aufruf implementieren

Erstellen Sie als Nächstes eine API für die Produktsuche und senden Sie sie an das Back-End. Sie verwenden Volley und Task API auf ähnliche Weise wie der API-Aufruf für die Produktsuche.

Kehren Sie zur Klasse ProductSearchAPIClient zurück, suchen Sie die leere fetchReferenceImage-Methode und ersetzen Sie sie durch diese Implementierung:

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
}

Diese Methode verwendet ein searchResult: ProductSearchResult-Objekt, das vom Produktsuchendpunkt zurückgegeben wurde, und führt dann die folgenden Schritte aus:

  1. Ruft den Referenzbildendpunkt ab, um den GCS-URI des Referenzbilds abzurufen.
  2. Konvertiert den GCS-URI in eine HTTP-URL.
  3. Aktualisiert die httpUri-Property des searchResult-Objekts mit dieser HTTP-URL.

Beide API-Anfragen verbinden

Gehen Sie zurück zu annotateImage und ändern Sie ihn, um alle Referenzbilder und HTTP-URLs abzurufen, bevor Sie die Liste ProductSearchResult an den Aufrufer zurückgeben.

Suchen Sie diese Zeile:

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

Ersetzen Sie sie anschließend durch diese Implementierung:

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

Der Boilerplate-Code zum Anzeigen der Referenzbilder auf dem Bildschirm ist in der Klasse ProductSearchAdapter bereits implementiert, sodass Sie die App noch einmal ausführen können.

Ausführen

Klicken Sie in der Android Studio Symbolleiste auf Ausführen (Ausführen.png). Tippen Sie nach dem Laden der App auf ein voreingestelltes Bild, wählen Sie ein erkanntes Objekt aus und tippen Sie auf die Schaltfläche Suchen, um die Suchergebnisse aufzurufen – diesmal mit den Produktbildern.

Sind die Ergebnisse der Produktsuche für Sie sinnvoll?

25939f5a13eeb3c3

9. Glückwunsch!

Sie haben nun gelernt, wie Sie eine Vision API-Produktsuche aufrufen, um Ihrer Android-App Funktionen für die Produktsuche hinzuzufügen. Sie müssen dann nur noch damit loslegen.

Nun können Sie mit Ihrem Produktkatalog ein eigenes Back-End erstellen. Im nächsten Codelab im Lernpfad Produktbildsuche erfahren Sie, wie Sie Ihr eigenes Back-End erstellen und den API-Schlüssel für den Aufruf aus einer mobilen App einrichten.

Behandelte Themen

  • Back-End der Vision API-Produktsuche aus einer Android-App aufrufen

Nächste Schritte

Weitere Informationen