Wywołaj backend interfejsu Vision API w wyszukiwarce na Androidzie

1. Zanim zaczniesz

bd8c01b2f8013c6d.png

Czy znasz wersję demonstracyjną Obiektywu Google, która polega na kierowaniu obiektywem na obiekt i kupowaniu go online? Jeśli chcesz dowiedzieć się, jak samodzielnie dodać tę samą funkcję do aplikacji, możesz wziąć udział w ćwiczeniach z programowania. Jest to część ścieżki szkoleniowej, z której dowiesz się, jak stworzyć funkcję wyszukiwania obrazów produktu w aplikacji mobilnej.

Z tego modułu dowiesz się, jak wywołać backend utworzony za pomocą wyszukiwarki produktów Vision API z aplikacji mobilnej. Może on pobrać obraz zapytania i wyszukać wizualnie podobne produkty z katalogu produktów.

Informacje o pozostałych krokach tworzenia funkcji wyszukiwania produktów wizualnych, w tym o sposobie korzystania z wykrywania i śledzenia obiektów ML Kit, pomogą Ci wykrywać obiekty w obrazie zapytania i pomagać użytkownikom wybierać produkt, którego szukają, w ścieżce szkoleniowej.

Co stworzysz

  • Na początku tego ćwiczenia z aplikacji na Androida możesz wykryć obiekty na obrazie wejściowym. Otrzymasz kod, który przeniesie obiekt wybrany przez użytkownika na serwer, wyśle go do backendu wyszukiwania produktów i wyświetli wynik na ekranie.
  • Na końcu obraz powinien wyglądać podobnie do obrazu po prawej stronie.

Czego się nauczysz:

  • Wywołanie i analiza odpowiedzi interfejsów API wyszukiwania produktów w Vision API z aplikacji na Androida

Czego potrzebujesz

  • Najnowsza wersja Androida Studio (wersja 4.1.2 lub nowsza)
  • Emulator Androida Studio lub fizyczne urządzenie z Androidem
  • Przykładowy kod
  • Podstawowa wiedza na temat rozwoju Androida w Kotlinie

To ćwiczenie skupia się na wyszukiwaniu produktów Vision API. Nieistotne koncepcje i bloki kodu nie są analizowane. Mają jedynie możliwość kopiowania i wklejania.

2. Wyszukiwanie produktów Vision API

Wyszukiwarka produktów Vision API to funkcja w Google Cloud umożliwiająca użytkownikom wyszukiwanie wizualnie podobnych produktów z katalogu produktów. Sprzedawcy mogą tworzyć produkty, z których każdy zawiera obrazy referencyjne, które wizualnie opisują produkt z punktu widzenia. Następnie możesz dodać te produkty do zestawów produktów (tj. katalogu produktów). Obecnie wyszukiwarka produktów Vision API obsługuje następujące kategorie produktów: artykuły gospodarstwa domowego, odzież, zabawki, produkty pakowane oraz ogólnie.

Gdy użytkownicy wyszukują informacje o produkcie za pomocą własnych zdjęć, wyszukiwarka produktów z interfejsem Vision API stosuje systemy uczące się do porównywania produktu ze zdjęciami użytkownika w zestawie produktów, a następnie zwraca listę wyników podobną do wizualnej i semantycznej.

3. Pobierz i uruchom aplikację startową

Pobieranie kodu

Aby pobrać cały kod do tych ćwiczeń z programowania, kliknij ten link:

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

Podkatalog codelab2 w repozytorium odml-pathways zawiera 2 katalogi:

  • folder_android_studio.pngstarter – kod uruchamiany na potrzeby tego ćwiczenia.
  • folder_android_studio.pngfinal (końcowy) – gotowy kod gotowej aplikacji.

Aplikacja startowa to aplikacja, która została przez Ciebie utworzona w ramach ćwiczenia z programowania w ramach wykrywania obiektów na obrazach, by utworzyć wizualne wyszukiwanie produktów: Android. Wykrywanie i śledzenie obiektów na podstawie obrazów odbywa się za pomocą narzędzia ML Kit Object Detection and Tracking.

Importowanie aplikacji do Android Studio

Najpierw zaimportuj aplikację starter do Android Studio.

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

7C0f27882a2698ac.png

Uruchamianie aplikacji startowej

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

(Jeśli ten przycisk jest wyłączony, zaimportuj tylko polecenie starter/app/build.gradle, a nie całe repozytorium).

Teraz aplikacja powinna pojawić się na urządzeniu z Androidem. Ma już funkcje wykrywania obiektów: wykrywania elementów mody na zdjęciu i pokazywania, gdzie się znajdują. Użyj gotowych zdjęć, aby potwierdzić czynność.

C6102a808fdfcb11.png

Zrzut ekranu aplikacji startowej, który wykrywa obiekty na obrazie

Następnie rozszerzysz aplikację, aby wysyłała wykryte obiekty do backendu wyszukiwania produktów w interfejsie Vision API i pokazywała wyniki na ekranie.

4. Obsługa wyboru obiektów

Zezwalanie użytkownikom na kliknięcie wykrytego obiektu

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 zdjęciu. 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, by wskazać, którego obiektu ma użyć do wyszukiwania produktów.

9cdfcead6d95a87.png

Zrzut ekranu przedstawiający produkty odzieżowe wykryte na zdjęciu

Aby ćwiczenia z programowania były proste i koncentrowały się na systemach uczących się, wdrożyliśmy stały kod na Androida w aplikacji początkowej, który pomaga wykrywać obiekty, które użytkownicy klikają. Widok, który wyświetla obraz w głównej aktywności (ObjectDetectorActivity), to w rzeczywistości widok niestandardowy (ImageClickableView), który rozszerza domyślny system operacyjny ImageView. Stosuje kilka wygodnych metod, np.:

  • fun setOnObjectClickListener(listener: ((objectImage: Bitmap) -> Unit)) To jest wywołanie zwrotne w celu otrzymania przyciętego obrazu zawierającego tylko obiekt kliknięty przez użytkownika. Przycięty obraz zostanie wysłany do backendu wyszukiwania produktów.

Dodaj kod, aby umożliwić użytkownikowi kliknięcie wykrytych obiektów.

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

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

Wywołanie onObjectClickListener następuje, gdy użytkownik kliknie dowolny wykryty obiekt na ekranie. Przyjmuje przycięty obraz, który zawiera tylko wybrany obiekt. Jeśli na przykład użytkownik kliknie osobę w sukience w prawej części ekranu, detektor zostanie aktywowany przez objectImage w podany niżej sposób.

9kac8458d0f326e6.png

Przykład przyciętego obrazu przekazanego do obiektu onObjectClickListener

Wysyłanie przyciętego zdjęcia do wyszukiwania w usłudze

Teraz wdrożysz logikę wysyłania obrazu zapytania do backendu wyszukiwania produktów interfejsu Vision API w oddzielnej aktywności (ProductSearchActivity).

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

25939f5a13eeb3c3.png

Zrzut ekranu przedstawiający komponenty interfejsu w ProductSearchActivity

Dodaj kod, aby wysyłać obraz wybrany przez użytkownika do obiektu 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 służy do 3 wykonania:

  • Przejmuje przycięty obraz i serialuje go do pliku PNG.
  • Uruchamia ProductSearchActivity, aby wykonać sekwencję wyszukiwania produktu.
  • Obejmuje identyfikator URI przyciętego obrazu w intencji aktywności początkowej, by element ProductSearchActivity mógł pobrać go później i użyć jako obrazu zapytania.

Kilka rzeczy, które warto pamiętać:

  • Logika wykrywania obiektów i wysyłania zapytań dotyczących backendu została podzielona na 2 aktywności tylko po to, aby ułatwić zrozumienie ćwiczeń z programowania. To Ty decydujesz, jak wdrożyć je w aplikacji.
  • Musisz zapisać obraz zapytania w pliku i przekazać go pomiędzy aktywnościami, ponieważ obraz zapytania może być większy niż limit 1 MB dotyczący intencji Androida.
  • Obraz zapytania można zapisać w formacie PNG, ponieważ jest to format bezstratny.

Pobierz obraz zapytania z aktywności związanej z wyszukiwaniem produktów

W kodzie ProductSearchActivity kod do pobierania obrazu zapytania i wyświetlania go na ekranie został zaimplementowany w aplikacji startowej.

Otwórz metodę onCreate i sprawdź, czy ten kod już 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))
}

Uruchamianie aplikacji

Kliknij Uruchom (wykonaj.png) na pasku narzędzi Androida Studio.

Po wczytaniu aplikacji kliknij dowolny gotowy obraz i wybierz jeden z wykrytych obiektów.

Upewnij się, że obok wyświetlonego obrazu wyświetla się ProductSearchActivity. Przycisk Szukaj jeszcze nic nie robi, ale wprowadzimy go w przyszłości.

fed40f81b8b43801.png

Gdy klikniesz jeden z wykrytych obiektów, zobaczysz podobny ekran.

5. Poznaj backend wyszukiwania produktów

Tworzenie backendu wyszukiwania obrazu produktu

To ćwiczenie programowania wymaga backendu usługi wyszukiwania produktów utworzonego za pomocą Vision API Search. Możesz to zrobić na 2 sposoby:

Opcja 1. Użyj backendu backendu, który został wdrożony

Z tych ćwiczeń z programowania możesz skorzystać, korzystając z zaplecza wyszukiwarki produktów, który został już wdrożony przez Google. Backend demonstracyjny można zreplikować, postępując zgodnie z krótkim wprowadzeniem do usługi Product Vision API.

Opcja 2. Utworzenie własnego backendu zgodnie z krótkim przewodnikiem po wyszukiwaniu produktów w interfejsie Vision API

Ta opcja jest zalecana dla tych, którzy chcą się dowiedzieć więcej o tworzeniu systemu wyszukiwania produktów, tak by móc później utworzyć własny katalog. Potrzebne są:

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

Możesz to zrobić później w ścieżce szkoleniowej.

Poznaj ważne pojęcia

Podczas korzystania z backendu wyszukiwarki produktów natrafisz na następujące zagadnienia:

  • Zestaw produktów: prosty kontener dla grupy produktów. Katalog produktów może być reprezentowany jako zbiór produktów i jego produkty.
  • Produkt: po utworzeniu zestawu produktów możesz utworzyć produkty i dodać je do zestawu.
  • Obrazy referencyjne produktu: to zdjęcia zawierające różne widoki Twoich produktów. Obrazy referencyjne służą do wyszukiwania produktów, które są wizualnie podobne.
  • Wyszukiwanie produktów: po utworzeniu zestawu produktów i jego zindeksowaniu możesz wysyłać do niego zapytania za pomocą interfejsu Cloud Vision API.

Omówienie gotowego katalogu produktów

Backend demonstracyjny wyszukiwania produktów użyty w tym ćwiczeniu z programowania został utworzony przy użyciu Vision API Product Search oraz katalogu produktów z około setkami zdjęć butów i sukienek. Oto niektóre obrazy z katalogu:

4F1a8507b74ab178.png 79a5fc6c829eca77.png 3528c872f813826e.png

Przykłady z gotowego katalogu produktów

Wywołanie backendu demonstracji wyszukiwania produktu

Funkcja wyszukiwania produktów w interfejsie API Vision API może zostać wywoływana bezpośrednio z aplikacji mobilnej. Aby to zrobić, skonfiguruj klucz interfejsu API Google Cloud i ogranicz dostęp do klucza interfejsu API tylko do swojej aplikacji.

Aby ułatwić sobie ćwiczenia z programowania, skonfiguruj punkt końcowy proxy, który pozwala uzyskać dostęp do backendu demonstracyjnego bez martwienia się o klucz interfejsu API i uwierzytelnianie. Odbiera żądanie HTTP z aplikacji mobilnej, dołącza klucz interfejsu API i przekazuje żądanie do backendu Vision API Product Search. Następnie serwer proxy odbiera odpowiedź z backendu i zwraca ją do aplikacji mobilnej.

W tym ćwiczeniu wykorzystasz 2 interfejsy API Vision API Search:

6. Wdrażanie klienta interfejsu API

Proces wyszukiwania produktów

Wykonaj te czynności, aby przeprowadzić wyszukiwanie produktu za pomocą backendu:

Implementowanie klasy klienta interfejsu API

Teraz zaimplementujesz kod wywołujący backend wyszukiwania produktów w osobnej klasie o nazwie ProductSearchAPIClient. W aplikacji startowej masz zaimplementowany kilka stałych elementów kodu:

  • class ProductSearchAPIClient: te zajęcia są obecnie prawie puste, ale istnieją pewne metody, które wdrożysz później w tym ćwiczeniu.
  • fun convertBitmapToBase64(bitmap: Bitmap): przekonwertuj instancję Bitmap na jej reprezentację base64, aby wysłać ją do backendu wyszukiwania produktu
  • fun annotateImage(image: Bitmap): Task<List<ProductSearchResult>>: wywołaj interfejs projects.locations.images.annotate i przeanalizuj odpowiedź.
  • fun fetchReferenceImage(searchResult: ProductSearchResult): Task<ProductSearchResult>: wywołaj interfejs projects.locations.products.referenceImages.get i przeanalizuj odpowiedź.
  • SearchResult.kt: ten plik zawiera kilka klas danych reprezentujących typy zwracane przez backend usługi wyszukiwania produktów Vision API.

Określanie konfiguracji interfejsu API

Po otwarciu klasy ProductSearchAPIClient zobaczysz kilka konfiguracji backendu wyszukiwania produktów:

// 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 API Cloud Vision. Gdy będziesz korzystać z backendu demonstracyjnego, ustaw ten punkt końcowy serwera proxy. Jeśli jednak wdrożysz własny backend, musisz zmienić go na punkt końcowy Cloud Vision API. https://vision.googleapis.com/v1.
  • VISION_API_KEY to klucz interfejsu API Twojego projektu Cloud. Ponieważ serwer proxy obsługuje już uwierzytelnianie, możesz pozostawić to pole puste.
  • VISION_API_PROJECT_ID to identyfikator projektu Cloud. odml-codelabs to projekt Cloud, w którym wdrożono backend demonstracyjny.
  • VISION_API_LOCATION_ID to lokalizacja Cloud, w której wdrożone jest backend wyszukiwania produktów. us-east1 to miejsce, w którym wdrożyliśmy wersję demonstracyjną.
  • VISION_API_PRODUCT_SET_ID to identyfikator katalogu produktów (określany też jako Vision API), w którym chcesz wyszukać podobne produkty. Możesz mieć wiele katalogów w jednym projekcie Cloud. product_set0 to gotowy katalog usługi backendu demonstracyjnego.

7. Wywoływanie interfejsu Product Search API

Zapoznaj się z formatem żądania i odpowiedzi API

Możesz znaleźć podobne produkty do danego obrazu, przekazując do identyfikatora produktu Vision API identyfikator URI Google Cloud Storage, internetowy adres URL lub ciąg zakodowany w standardzie base64. W tym ćwiczeniu wykorzystamy opcję ciągu zakodowanego w standardzie base64, ponieważ nasz obraz zapytania istnieje tylko na urządzeniu użytkownika.

Wyślij żądanie POST do punktu końcowego projects.locations.images.annotate z tym obiektem JSON żądania:

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

Trzeba podać kilka parametrów:

  • Obraz zakodowany w formacie base64: reprezentacja obrazu binarnego obrazu w standardzie base64 (ciąg ASCII).
  • project-id: identyfikator projektu GCP.
  • location-id: prawidłowy identyfikator lokalizacji.
  • product-set-id: identyfikator zestawu produktów, na którym chcesz wykonać działanie.

Katalog produktów zawiera tylko zdjęcia butów i sukienek, więc atrybut productCategory powinien mieć wartość apparel-v2. v2 oznacza, że korzystamy z wersji 2 modelu systemów uczących się opracowanych przez markę odzieży.

Jeśli żądanie zostanie zrealizowane, serwer zwróci kod stanu HTTP 200 OK i odpowiedź w formacie JSON. Plik JSON z odpowiedziami zawiera 2 typy wyników:

  • productSearchResults – zawiera listę pasujących produktów dla całego zdjęcia.
  • productGroupedResults – zawiera współrzędne ramki ograniczającej i pasujące produkty w przypadku każdego produktu wskazanego na zdjęciu.

Ponieważ produkt został już przycięty z oryginalnego zdjęcia, jego wyniki znajdziesz na liście productSearchResults.

Oto kilka ważnych pól obiektu wyników wyszukiwania produktów:

  • product.name: unikalny identyfikator produktu w formacie projects/{project-id}/locations/{location-id}/products/{product_id}
  • product.score: wartość określająca poziom podobieństwa wyniku wyszukiwania do obrazu zapytania. Wyższe wartości oznaczają większe podobieństwo.
  • product.image: unikalny identyfikator zdjęcia referencyjnego produktu w formacie projects/{project-id}/locations/{location-id}/products/{product_id}/referenceImages/{image_id}. Aby uzyskać adres URL tego obrazu referencyjnego, który będzie widoczny na ekranie, musisz wysłać kolejne żądanie do interfejsu projects.locations.products.referenceImages.get.
  • product.labels: lista wstępnie zdefiniowanych tagów produktu. Jest to przydatne, gdy chcesz przefiltrować wyniki wyszukiwania tak, aby pokazywały tylko jedną kategorię ubrań, np. sukienki.

Konwertuj obraz zapytania na base64

Musisz przekonwertować obraz zapytania w jego reprezentację ciągu Base64 i dołączyć go do obiektu JSON w treści żądania.

Otwórz klasę 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)
}

Implementowanie wywołania interfejsu API

Następnie utwórz żądanie do interfejsu API wyszukiwania produktów i wyślij je do backendu. Użyjesz interfejsu API Volley, aby wysłać żądanie API i zwrócić wynik 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świetlanie wyniku wyszukiwania w interfejsie

Teraz kod interfejsu API ProductSearchAPIClient jest gotowy. Wróć do czynności ProductSearchActivity, aby zaimplementować kod interfejsu użytkownika.

Aktywność zawiera już powtarzalny kod, który aktywuje metodę searchByImage(queryImage: Bitmap). Dodaj kod, aby wywołać backend i pokazać wyniki w interfejsie użytkownika do tej pustej metody.

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ź API i pokazuje ją na ekranie.

Uruchom

Kliknij Uruchom (wykonaj.png) na pasku narzędzi Androida Studio. Po załadowaniu aplikacji kliknij dowolny gotowy obraz, wybierz wykryty obiekt, kliknij przycisk Szukaj i zobacz wyniki wyszukiwania z backendu. Zobaczysz coś takiego:

bb5e7c27c283a2fe.png

Zrzut ekranu ekranu z wynikami wyszukiwania produktu

Backend zwraca już listę podobnych wizualnie produktów z gotowego katalogu produktów. Widać jednak, że zdjęcie produktu jest nadal puste. Dzieje się tak dlatego, że punkt końcowy projects.locations.images.annotate zwraca tylko identyfikatory obrazów produktów, takie jak projects/odml-codelabs/locations/us-east1/products/product_id77/referenceImages/image77. Aby wyświetlić obraz na ekranie, musisz wysłać kolejne wywołanie interfejsu API do punktu końcowego projects.locations.products.referenceImages.get i uzyskać jego adres URL.

8. Pobieranie zdjęć referencyjnych produktów

Zapoznaj się z formatem żądania i odpowiedzi API

Aby wysłać identyfikatory URI obrazów produktów zwróconych przez punkt końcowy wyszukiwania produktów, wyślesz żądanie HTTP GET HTTP z pustym treścią żądania 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 w następujący sposób:

{
  "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 backendu backendu wyszukiwania produktu zostały skonfigurowane tak, aby miały uprawnienia do odczytu publicznego. Dlatego możesz łatwo przekonwertować identyfikator URI GCS na adres URL HTTP i wyświetlić go w interfejsie aplikacji. Prefiks gs:// musisz zastąpić jedynie kodem https://storage.googleapis.com/.

Implementowanie wywołania interfejsu API

Następnie utwórz żądanie do interfejsu API wyszukiwania produktów i wyślij je do backendu. Interfejsu Volley and Task API będziesz używać podobnie jak wywołanie interfejsu API wyszukiwania produktów.

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 pobiera obiekt searchResult: ProductSearchResult zwrócony przez punkt końcowy wyszukiwania produktów i wykonuje te czynności:

  1. Wywołuje punkt końcowy obrazu referencyjnego, by pobrać identyfikator URI GCS dotyczący obrazu referencyjnego.
  2. Konwertuje identyfikator URI GCS na adres URL HTTP.
  3. Aktualizuje właściwość httpUri obiektu searchResult o ten adres URL HTTP.

Łączenie 2 żądań interfejsu API

Wróć do strony annotateImage i zmień ją, by pobrać wszystkie obrazy referencyjne z adresem HTTP przed zwróceniem listy ProductSearchResult do jego wywołania.

Znajdź ten wiersz:

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

Zastąp go tą implementacją:

// 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 stały, który powoduje wyświetlanie obrazów referencyjnych na ekranie, jest już zaimplementowany w klasie ProductSearchAdapter, możesz więc ponownie uruchomić aplikację.

Uruchom

Kliknij Uruchom ( wykonaj.png) na pasku narzędzi Androida Studio. Po załadowaniu aplikacji kliknij dowolne gotowe ustawienia, wybierz wykrytych obiektów i kliknij przycisk Szukaj, by zobaczyć wyniki wyszukiwania, tym razem z zdjęciami produktu.

Czy wyniki wyszukiwania produktów są dla Ciebie przydatne?

25939f5a13eeb3c3.png

9. Gratulacje!

Wiesz już, jak wywołać interfejs API wyszukiwania produktów w interfejsie Vision, aby dodać funkcję wyszukiwania obrazów produktu do aplikacji na Androida. To wszystko, czego potrzebujesz, aby zacząć korzystać z usługi.

Możesz kontynuować tworzenie własnego backendu, korzystając z katalogu produktów. Zapoznaj się z następnym ćwiczeniami z programowania w ścieżce szkoleniowej dotyczącej Wyszukiwarki grafiki produktów, aby dowiedzieć się, jak utworzyć własny backend, oraz skonfigurować klucz interfejsu API do wywoływania go z aplikacji mobilnej.

Omawiane zagadnienia

  • Jak wywołać backend usługi Vision API w aplikacji na Androida

Następne kroki

Więcej informacji