Wywoływanie backendu Wyszukiwarki produktów Vision API na Androidzie

1. Zanim zaczniesz

bd8c01b2f8013c6d.png

Czy widziałeś(-aś) prezentację Obiektywu Google, w której możesz skierować aparat telefonu na obiekt i sprawdzić, gdzie można go kupić online? Jeśli chcesz się dowiedzieć, jak dodać tę samą funkcję do swojej aplikacji, ten przewodnik jest dla Ciebie. Jest to część ścieżki szkoleniowej, która uczy, jak wbudować w aplikację mobilną funkcję wyszukiwania obrazów produktów.

Z tego laboratorium dowiesz się, jak wywoływać z aplikacji mobilnej backend utworzony za pomocą Wyszukiwarki produktów Vision API. Ten backend może przyjmować obraz zapytania i wyszukiwać wizualnie podobne produkty z katalogu produktów.

Pozostałe kroki tworzenia funkcji wizualnego wyszukiwania produktów, w tym informacje o tym, jak używać wykrywania i śledzenia obiektów w ML Kit do wykrywania obiektów na obrazie zapytania i umożliwiania użytkownikom wyboru produktu, którego chcą wyszukać, znajdziesz na ścieżce szkoleniowej.

Co utworzysz

  • W tym laboratorium kodu zaczniesz od aplikacji na Androida, która może wykrywać obiekty na zdjęciu wejściowym. Napiszesz kod, który pobierze wybrany przez użytkownika obiekt, wyśle go do backendu wyszukiwania produktów i wyświetli wynik wyszukiwania na ekranie.
  • Na koniec powinna pojawić się grafika podobna do tej po prawej stronie.

Czego się nauczysz

  • Jak wywoływać interfejsy API Wyszukiwarki produktów Vision API z poziomu aplikacji na Androida i analizować ich odpowiedzi

Czego potrzebujesz

  • Najnowsza wersja Android Studio (4.1.2 lub nowsza)
  • Emulator Android Studio lub fizyczne urządzenie z Androidem
  • Przykładowy kod
  • Podstawowa wiedza na temat tworzenia aplikacji na Androida w języku Kotlin

Ten moduł dotyczy Wyszukiwarki produktów Vision API. Nieistotne koncepcje i bloki kodu nie są omawiane. Można je po prostu skopiować i wkleić.

2. Informacje o Wyszukiwarce produktów Vision API

Wyszukiwarka produktów Vision API to funkcja Google Cloud, która umożliwia użytkownikom wyszukiwanie podobnych wizualnie produktów z katalogu produktów. Sprzedawcy mogą tworzyć produkty, z których każdy zawiera obrazy referencyjne opisujące go wizualnie z różnych punktów widzenia. Możesz następnie dodać te produkty do zestawów produktów (czyli katalogu produktów). Obecnie Wyszukiwarka produktów Vision API obsługuje te kategorie produktów: artykuły gospodarstwa domowego, odzież, zabawki, produkty pakowane i ogólne.

Gdy użytkownicy wysyłają zapytania do zbioru produktów za pomocą własnych obrazów, Wyszukiwarka produktów Vision API stosuje uczenie maszynowe, aby porównać produkt na obrazie z zapytania użytkownika z obrazami w zbiorze produktów sprzedawcy, a następnie zwraca uporządkowaną listę podobnych wizualnie i semantycznie wyników.

3. Pobieranie i uruchamianie aplikacji początkowej

Pobieranie kodu

Aby pobrać cały kod do tego laboratorium, kliknij ten link:

Rozpakuj pobrany plik ZIP. Spowoduje to rozpakowanie folderu głównego (odml-pathways-main) ze wszystkimi potrzebnymi zasobami. W tym ćwiczeniu potrzebne będą tylko źródła w podkatalogu product-search/codelab2/android.

Podkatalog codelab2 w repozytorium odml-pathways zawiera 2 katalogi:

  • android_studio_folder.pngstarter – kod początkowy, na którym będziesz pracować w ramach tych ćwiczeń z programowania.
  • android_studio_folder.pngfinal – ukończony kod gotowej aplikacji przykładowej.

Aplikacja początkowa to ta, którą utworzono w ramach ćwiczeń z programowania Wykrywanie obiektów na obrazach w celu utworzenia wizualnej wyszukiwarki produktów: Android. Aplikacja korzysta z wykrywania i śledzenia obiektów w ML Kit, aby wykrywać obiekty na obrazie i wyświetlać je na ekranie.

Importowanie aplikacji do Android Studio

Zacznij od zaimportowania aplikacji starter do Android Studio.

W Android Studio wybierz Importuj projekt (Gradle, Eclipse ADT itp.) i wskaż folder starter z pobranego wcześniej kodu źródłowego.

7c0f27882a2698ac.png

Uruchom aplikację startową

Po zaimportowaniu projektu do Android Studio możesz po raz pierwszy uruchomić aplikację. Podłącz urządzenie z Androidem do hosta za pomocą kabla USB lub uruchom emulator Androida Studio i kliknij Uruchom ( execute.png) na pasku narzędzi Androida Studio.

(Jeśli ten przycisk jest wyłączony, upewnij się, że importujesz tylko plik starter/app/build.gradle, a nie całe repozytorium).

Aplikacja powinna się teraz uruchomić na urządzeniu z Androidem. Ma już funkcję wykrywania obiektów: wykrywa elementy mody na obrazie i pokazuje, gdzie się znajdują. Aby potwierdzić, wypróbuj gotowe zdjęcia.

c6102a808fdfcb11.png

Zrzut ekranu aplikacji startowej, która może wykrywać obiekty na obrazie

Następnie rozszerzysz aplikację, aby wysyłać wykryte obiekty do backendu Wyszukiwarki produktów Vision API i wyświetlać wyniki wyszukiwania na ekranie.

4. Obsługa wyboru obiektu

Zezwalaj użytkownikom na klikanie wykrytego obiektu w celu jego wybrania

Teraz dodasz kod, który umożliwi użytkownikom wybranie obiektu z obrazu i rozpoczęcie wyszukiwania produktu. Aplikacja startowa ma już możliwość wykrywania obiektów na obrazie. Możliwe, że na obrazie znajduje się wiele obiektów lub wykryty obiekt zajmuje tylko niewielką część obrazu. Dlatego użytkownik musi kliknąć jeden z wykrytych obiektów, aby wskazać, którego chce użyć do wyszukiwania produktu.

9cdfcead6d95a87.png

zrzut ekranu przedstawiający wykryte na zdjęciu elementy odzieży;

Aby ćwiczenie było proste i skupione na uczeniu maszynowym, w aplikacji początkowej zaimplementowano pewien kod Androida, który pomoże Ci wykryć, który obiekt został kliknięty przez użytkownika. Widok, który wyświetla obraz w głównym działaniu (ObjectDetectorActivity), jest w rzeczywistości widokiem niestandardowym (ImageClickableView), który rozszerza domyślny widok ImageView systemu operacyjnego Android. Zawiera kilka przydatnych metod narzędziowych, m.in.:

  • fun setOnObjectClickListener(listener: ((objectImage: Bitmap) -> Unit)) Jest to wywołanie zwrotne, które umożliwia otrzymanie przyciętego obrazu zawierającego tylko obiekt, który użytkownik kliknął. Przycięte zdjęcie zostanie wysłane do backendu wyszukiwania produktów.

Dodaj kod obsługujący kliknięcie wykrytych obiektów przez użytkownika.

Otwórz metodę initViews w klasie ObjectDetectorActivity i dodaj na końcu te wiersze: (Android Studio poinformuje Cię, że nie może znaleźć metody startProductImageSearch . Nie martw się, zrobisz to później).

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

Funkcja onObjectClickListener jest wywoływana, gdy użytkownik kliknie dowolny wykryty obiekt na ekranie. Otrzymuje wykadrowany obraz, który zawiera tylko wybrany obiekt. Jeśli na przykład użytkownik kliknie osobę w sukience po prawej stronie, odbiornik zostanie uruchomiony z parametrem objectImage, jak poniżej.

9cac8458d0f326e6.png

Przykład przyciętego obrazu przekazanego do onObjectClickListener

Wysyłanie przyciętego obrazu do aktywności wyszukiwania produktu

Teraz zaimplementujesz logikę wysyłania obrazu zapytania do backendu Wyszukiwarki produktów Vision API w osobnej aktywności (ProductSearchActivity).

Wszystkie komponenty interfejsu zostały zaimplementowane z wyprzedzeniem, dzięki czemu możesz skupić się na pisaniu kodu do komunikacji z backendem wyszukiwania produktów.

25939f5a13eeb3c3.png

Zrzut ekranu komponentów interfejsu w ProductSearchActivity

Dodaj kod, aby wysłać obraz obiektu wybranego przez użytkownika do ProductSearchActivity.

Wróć do Android Studio i dodaj tę metodę startProductImageSearch do klasy 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)
    }
}

Fragment kodu wykonuje 3 czynności:

  • Przekształca przycięty obraz w plik PNG.
  • Uruchamia ProductSearchActivity, aby wykonać sekwencję wyszukiwania produktu.
  • Zawiera w intencji rozpoczęcia aktywności identyfikator URI przyciętego obrazu, aby ProductSearchActivity mogła go później pobrać i użyć jako obrazu zapytania.

Trzeba jednak pamiętać o kilku kwestiach:

  • Logika wykrywania obiektów i wysyłania zapytań do backendu została podzielona na 2 aktywności tylko po to, aby ułatwić zrozumienie tego laboratorium. Od Ciebie zależy, jak je wdrożysz w aplikacji.
  • Obraz zapytania musisz zapisać w pliku i przekazać identyfikator URI obrazu między działaniami, ponieważ obraz zapytania może być większy niż limit rozmiaru 1 MB w przypadku intencji Androida.
  • Obraz zapytania możesz przechowywać w formacie PNG, ponieważ jest to format bezstratny.

Pobierz obraz zapytania w aktywności wyszukiwania produktów.

ProductSearchActivity kod do pobierania obrazu zapytania i wyświetlania go na ekranie został już zaimplementowany w aplikacji początkowej.

Przejdź do metody onCreate i sprawdź, czy ten kod już tam jest:

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

Uruchom aplikację

Teraz na pasku narzędzi Android Studio kliknij Uruchom ( execute.png).

Po wczytaniu aplikacji kliknij dowolne gotowe zdjęcie i wybierz jeden z wykrytych obiektów.

Sprawdź, czy przy zdjęciu, które zostało kliknięte, wyświetla się symbol ProductSearchActivity. Przycisk Szukaj jeszcze nie działa, ale wkrótce go wdrożymy.

fed40f81b8b43801.png

Po kliknięciu jednego z wykrytych obiektów powinien pojawić się podobny ekran.

5. Poznaj backend wyszukiwania produktów

Tworzenie backendu wyszukiwania obrazów produktów

Te ćwiczenia z programowania wymagają backendu wyszukiwania produktów utworzonego za pomocą Wyszukiwarki produktów Vision API. Możesz to zrobić na 2 sposoby:

Opcja 1. Użyj backendu wersji demonstracyjnej, który został wdrożony na Twoim koncie

Możesz przejść do tego laboratorium, korzystając z backendu wyszukiwania produktów, który Google już dla Ciebie wdrożył. Działanie demonstracyjnego backendu można odtworzyć, postępując zgodnie z przewodnikiem Wyszukiwarki produktów Vision API.

Opcja 2. Utwórz własny backend, korzystając z samouczka wprowadzającego do Wyszukiwarki produktów Vision API

Ta opcja jest zalecana dla osób, które chcą szczegółowo poznać sposób tworzenia backendu wyszukiwarki produktów, aby później móc utworzyć własny backend dla swojego katalogu produktów. Potrzebne są:

  • Konto Google Cloud z włączonymi płatnościami. (Może to być bezpłatne konto próbne).
  • Podstawowa wiedza o koncepcjach Google Cloud, w tym o projektach, kontach usługi itp.

Więcej informacji o tym, jak to zrobić, znajdziesz w ścieżce szkoleniowej.

Poznaj ważne pojęcia

Podczas korzystania z backendu wyszukiwania produktów możesz spotkać się z tymi pojęciami:

  • Zestaw produktów: zestaw produktów to prosty kontener na grupę produktów. Katalog produktów może być reprezentowany jako zestaw produktów i jego produkty.
  • Produkt: po utworzeniu zestawu produktów możesz utworzyć produkty i dodać je do zestawu.
  • Obrazy referencyjne produktu: są to zdjęcia przedstawiające różne widoki produktów. Obrazy referencyjne służą do wyszukiwania produktów o podobnym wyglądzie.
  • Wyszukiwanie produktów: po utworzeniu zbioru produktów i zindeksowaniu go możesz wysyłać do niego zapytania za pomocą interfejsu Cloud Vision API.

Informacje o wstępnie ustawionym katalogu produktów

Backend wersji demonstracyjnej wyszukiwania produktów użyty w tym ćwiczeniu w Codelabs został utworzony przy użyciu Wyszukiwarki produktów Vision API i katalogu produktów zawierającego około stu zdjęć butów i sukienek. Oto kilka zdjęć z katalogu:

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

Przykłady z wstępnie ustawionego katalogu produktów

Wywołaj backend wersji demonstracyjnej wyszukiwania produktów

Możesz wywoływać interfejs Vision API Product Search bezpośrednio z aplikacji mobilnej, konfigurując klucz interfejsu API Google Cloud i ograniczając dostęp do niego tylko do Twojej aplikacji.

Aby uprościć ten przewodnik, skonfigurowaliśmy punkt końcowy proxy, który umożliwia dostęp do backendu wersji demonstracyjnej bez konieczności martwienia się o klucz interfejsu API i uwierzytelnianie. Otrzymuje żądanie HTTP z aplikacji mobilnej, dołącza klucz interfejsu API i przekazuje żądanie do backendu Wyszukiwarki produktów w Vision API. Następnie serwer proxy odbiera odpowiedź z backendu i zwraca ją do aplikacji mobilnej.

W tym ćwiczeniu z programowania użyjesz 2 interfejsów API Wyszukiwarki produktów Vision API:

6. Implementowanie klienta interfejsu API

Informacje o procesie wyszukiwania produktów

Aby przeprowadzić wyszukiwanie produktów za pomocą backendu, wykonaj te czynności:

Wdrażanie klasy klienta interfejsu API

Teraz zaimplementujesz kod, który będzie wywoływać backend wyszukiwania produktów w specjalnej klasie o nazwie ProductSearchAPIClient. W aplikacji startowej zaimplementowano już ten kod:

  • class ProductSearchAPIClient: ta klasa jest obecnie w większości pusta, ale zawiera kilka metod, które zaimplementujesz w dalszej części tych ćwiczeń z programowania.
  • fun convertBitmapToBase64(bitmap: Bitmap): przekształcanie instancji Bitmap w jej reprezentację w formacie base64 w celu wysłania do backendu wyszukiwania produktów.
  • fun annotateImage(image: Bitmap): Task<List<ProductSearchResult>>: wywołaj interfejs API projects.locations.images.annotate i przeanalizuj odpowiedź.
  • fun fetchReferenceImage(searchResult: ProductSearchResult): Task<ProductSearchResult>: wywołaj interfejs API projects.locations.products.referenceImages.get i przeanalizuj odpowiedź.
  • SearchResult.kt: ten plik zawiera kilka klas danych reprezentujących typy zwracane przez backend wyszukiwania produktów w interfejsie Vision API.

Określ konfiguracje interfejsu API

Przejdź do klasy ProductSearchAPIClient. Zobaczysz, że niektóre konfiguracje backendu wyszukiwania produktów są już zdefiniowane:

// 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 to punkt końcowy interfejsu Cloud Vision API. Podczas korzystania z demonstracyjnego backendu ustaw ten adres na punkt końcowy serwera proxy. Jeśli jednak wdrożysz własny backend, musisz zmienić go na punkt końcowy interfejsu Cloud Vision API. https://vision.googleapis.com/v1
  • VISION_API_KEY to klucz interfejsu API Twojego projektu w Cloud. Serwer proxy obsługuje już uwierzytelnianie, więc możesz pozostawić to pole puste.
  • VISION_API_PROJECT_ID to identyfikator projektu Cloud. odml-codelabs to projekt Cloud, w którym wdrożono zaplecze wersji demonstracyjnej.
  • VISION_API_LOCATION_ID to lokalizacja w chmurze, w której wdrożono backend wyszukiwania produktów. us-east1 to miejsce, w którym wdrożyliśmy demonstracyjny backend.
  • VISION_API_PRODUCT_SET_ID to identyfikator katalogu produktów (w terminologii Vision API „zbiór produktów”), w którym chcesz wyszukiwać wizualnie podobne produkty. W jednym projekcie Cloud możesz mieć wiele katalogów. product_set0 to gotowy katalog produktów w demonstracyjnym backendzie.

7. Wywoływanie interfejsu Product Search API

Poznaj format żądań i odpowiedzi interfejsu API

Aby znaleźć produkty podobne do danego obrazu, przekaż do Wyszukiwarki produktów Vision API identyfikator URI obrazu w Google Cloud Storage, adres URL lub ciąg z kodowaniem Base64. W tym ćwiczeniu w Codelabs użyjesz opcji ciągu zakodowanego w formacie base64, ponieważ obraz zapytania znajduje się tylko na urządzeniu użytkownika.

Musisz wysłać żądanie POST do punktu końcowego projects.locations.images.annotate z tym żądaniem w treści 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"
          ],
        }
      }
    }
  ]
}

Musisz podać te parametry:

  • base64-encoded-image: reprezentacja base64 (ciąg tekstowy ASCII) danych binarnych obrazu zapytania.
  • project-id: identyfikator projektu GCP.
  • location-id: prawidłowy identyfikator lokalizacji.
  • product-set-id: identyfikator zestawu produktów, na którym chcesz wykonać operację.

Katalog produktów zawiera tylko buty i sukienki, więc ustaw wartość productCategories na apparel-v2. v2 oznacza, że używamy wersji 2 modelu uczenia maszynowego do wyszukiwania produktów odzieżowych.

Jeśli żądanie zakończy się powodzeniem, serwer zwróci kod stanu HTTP 200 OK i odpowiedź w formacie JSON. Odpowiedź JSON zawiera 2 typy wyników:

  • productSearchResults – zawiera listę pasujących produktów dla całego obrazu.
  • productGroupedResults – zawiera współrzędne ramek ograniczających i pasujące produkty dla każdego produktu zidentyfikowanego na obrazie.

Produkt został już wycięty z oryginalnego obrazu, więc wyniki znajdziesz na liście productSearchResults.

Oto kilka ważnych pól w obiekcie wyniku wyszukiwania produktu:

  • product.name: unikalny identyfikator produktu w formacie projects/{project-id}/locations/{location-id}/products/{product_id}
  • product.score: wartość wskazująca, jak podobny jest wynik wyszukiwania do obrazu w zapytaniu. Wyższe wartości oznaczają większe podobieństwo.
  • product.image: unikalny identyfikator obrazu referencyjnego produktu w formacie projects/{project-id}/locations/{location-id}/products/{product_id}/referenceImages/{image_id}. Aby uzyskać adres URL tego obrazu referencyjnego i wyświetlić go na ekranie, musisz wysłać kolejne żądanie interfejsu API do projects.locations.products.referenceImages.get.
  • product.labels: lista predefiniowanych tagów produktu. Jest to przydatne, jeśli chcesz filtrować wyniki wyszukiwania, aby wyświetlać tylko jedną kategorię odzieży, np. sukienki.

Konwertowanie obrazu zapytania na format base64

Musisz przekonwertować obraz zapytania na ciąg tekstowy z kodowaniem Base64 i dołączyć go do obiektu JSON w treści żądania.

Przejdź do klasy ProductSearchAPIClient, znajdź pustą metodę convertBitmapToBase64 i zastąp ją tą implementacją:

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

Wdrażanie wywołania interfejsu API

Następnie utwórz żądanie do interfejsu Product Search API i wyślij je do backendu. Do wysłania żądania do interfejsu API użyjesz biblioteki Volley, a wynik zwrócisz za pomocą interfejsu Task API.

Wróć do klasy ProductSearchAPIClient, znajdź pustą metodę annotateImage i zastąp ją tą implementacją:

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
}

Wyświetl wynik wyszukiwania w interfejsie

Kod interfejsu API w klasie ProductSearchAPIClient jest gotowy. Wróć do aktywności ProductSearchActivity, aby wdrożyć kod interfejsu.

Aktywność zawiera już kod standardowy, który wywołuje metodę searchByImage(queryImage: Bitmap). Dodaj do tej pustej obecnie metody kod, który będzie wywoływać backend i wyświetlać wyniki w interfejsie.

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

Metoda showSearchResult zawiera powtarzalny kod, który analizuje odpowiedź interfejsu API i wyświetla ją na ekranie.

Uruchom

Teraz na pasku narzędzi Android Studio kliknij Uruchom ( execute.png). Po wczytaniu aplikacji kliknij dowolny obraz z gotowych ustawień, wybierz wykryty obiekt, kliknij przycisk Wyszukaj i sprawdź wyniki wyszukiwania zwrócone z backendu. Zobaczysz coś takiego:

bb5e7c27c283a2fe.png

Zrzut ekranu z wynikami wyszukiwania produktów

Backend zwraca już listę podobnych wizualnie produktów z wstępnie ustawionego katalogu produktów. Możesz jednak zauważyć, że obraz produktu jest nadal pusty. Dzieje się tak, ponieważ punkt końcowy projects.locations.images.annotate zwraca tylko identyfikatory zdjęć produktów, takie jak projects/odml-codelabs/locations/us-east1/products/product_id77/referenceImages/image77. Musisz wykonać kolejne wywołanie interfejsu API do punktu końcowego projects.locations.products.referenceImages.get i pobrać adres URL tego obrazu referencyjnego, aby wyświetlić go na ekranie.

8. Uzyskiwanie referencyjnych zdjęć produktu

Poznaj format żądań i odpowiedzi interfejsu API

Aby uzyskać identyfikatory URI obrazów produktów zwróconych przez punkt końcowy wyszukiwania produktów, wyślij żądanie GET HTTP z pustą treścią do punktu końcowego projects.locations.products.referenceImages.get.

Żądanie HTTP wygląda tak:

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

Jeśli żądanie zostanie zrealizowane, serwer zwróci kod stanu HTTP 200 OK i odpowiedź w formacie JSON, jak poniżej:

{
  "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: identyfikator obrazu referencyjnego.
  • uri: identyfikator URI obrazu w Google Cloud Storage (GCS).

Obrazy referencyjne zaplecza wyszukiwania produktów demonstracyjnych zostały skonfigurowane tak, aby miały uprawnienia do odczytu publicznego. Dlatego możesz łatwo przekonwertować URI GCS na adres URL HTTP i wyświetlić go w interfejsie aplikacji. Wystarczy, że zastąpisz prefiks gs:// prefiksem https://storage.googleapis.com/.

Wdrażanie wywołania interfejsu API

Następnie utwórz żądanie do interfejsu Product Search API i wyślij je do backendu. Będziesz używać interfejsów Volley i Task API podobnie jak w przypadku wywołania interfejsu Product Search API.

Wróć do klasy ProductSearchAPIClient, znajdź pustą metodę fetchReferenceImage i zastąp ją tą implementacją:

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
}

Ta metoda przyjmuje obiekt searchResult: ProductSearchResult zwrócony przez punkt końcowy wyszukiwania produktów, a następnie wykonuje te czynności:

  1. Wywołuje punkt końcowy obrazu referencyjnego, aby uzyskać identyfikator URI GCS obrazu referencyjnego.
  2. Konwertuje identyfikator URI GCS na adres URL HTTP.
  3. Aktualizuje właściwość httpUri obiektu searchResult tym adresem URL HTTP.

Połącz dwa żądania do interfejsu API

Wróć do annotateImage i zmodyfikuj go, aby uzyskać wszystkie adresy URL HTTP obrazów referencyjnych, a następnie zwróć listę ProductSearchResult do wywołującego.

Znajdź ten wiersz:

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

Następnie zastąp go tym kodem:

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

Kod standardowy do wyświetlania obrazów referencyjnych na ekranie jest już zaimplementowany w klasie ProductSearchAdapter, więc możesz ponownie uruchomić aplikację.

Uruchom

Teraz na pasku narzędzi Android Studio kliknij Uruchom ( execute.png). Po wczytaniu aplikacji kliknij dowolny obraz z ustawień wstępnych, wybierz wykryty obiekt i kliknij przycisk Wyszukaj, aby wyświetlić wyniki wyszukiwania, tym razem z obrazami produktów.

Czy wyniki wyszukiwania produktów są dla Ciebie zrozumiałe?

25939f5a13eeb3c3.png

9. Gratulacje!

Wiesz już, jak wywołać backend Wyszukiwarki produktów Vision API, aby dodać do aplikacji na Androida funkcję wyszukiwania obrazów produktów. To wszystko, czego potrzebujesz, aby zacząć korzystać z tej funkcji.

W miarę postępów możesz utworzyć własny backend, korzystając z katalogu produktów. Zapoznaj się z kolejnymi ćwiczeniami z programowania na ścieżce szkoleniowej Wyszukiwanie obrazów produktów, aby dowiedzieć się, jak utworzyć własny backend i skonfigurować klucz interfejsu API, aby wywoływać go z aplikacji mobilnej.

Omówione zagadnienia

  • Jak wywołać backend Wyszukiwarki produktów Vision API z poziomu aplikacji na Androida

Następne kroki

Więcej informacji