Przewodnik umieszczania obrazów w przypadku Androida

Zadanie MediaPipe Image Embedder umożliwia konwertowanie danych obrazu na reprezentację liczbową np. do porównywania podobieństwo dwóch obrazów. Z tych instrukcji dowiesz się, jak korzystać z Umieszczanie obrazów w aplikacjach na Androida

Więcej informacji o funkcjach, modelach i opcjach konfiguracji zapoznaj się z Przeglądem.

Przykładowy kod

Przykładowy kod MediaPipe Tasks to prosta implementacja mechanizmu do umieszczania obrazów na stronie na Androida. W tym przykładzie użyliśmy aparatu w fizycznym urządzeniu z Androidem, stale osadzać obrazy, a także uruchamiać mechanizm umieszczania na plikach graficznych przechowywanych na urządzeniu.

Możesz użyć tej aplikacji jako punktu wyjścia dla własnej aplikacji na Androida lub odnieść się do niej podczas modyfikowania istniejącej aplikacji. Przykładowy kod komponentu do umieszczania obrazów na stronie jest hostowany GitHub

Pobieranie kodu

Poniżej znajdziesz instrukcje tworzenia lokalnej kopii przykładu. za pomocą narzędzia wiersza poleceń git.

Aby pobrać przykładowy kod:

  1. Sklonuj repozytorium git za pomocą tego polecenia:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Opcjonalnie możesz skonfigurować instancję git tak, aby wykorzystywała rozproszony proces płatności, aby tylko pliki przykładowej aplikacji Image Embedder:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_embedder/android
    

Po utworzeniu lokalnej wersji przykładowego kodu możesz zaimportować projekt w Android Studio i uruchom aplikację. Odpowiednie instrukcje znajdziesz w Przewodniku po konfiguracji dla na urządzeniu z Androidem.

Kluczowe elementy

Poniższe pliki zawierają kluczowy kod tego przykładowego narzędzia do umieszczania obrazów aplikacja:

Konfiguracja

W tej sekcji opisujemy najważniejsze czynności związane z konfigurowaniem środowiska programistycznego oraz w projektach kodu, w których można używać elementu Image Embedder. Ogólne informacje o konfigurowaniu środowisko programistyczne do używania zadań MediaPipe, w tym wersja platformy należy zapoznać się z wymaganiami opisanymi w przewodniku po konfiguracji na urządzeniu z Androidem.

Zależności

Umieszczanie obrazów korzysta z biblioteki com.google.mediapipe:tasks-vision. Dodaj to zależności od pliku build.gradle projektu programowania aplikacji na Androida. Zaimportuj wymagane zależności za pomocą tego kodu:

dependencies {
    ...
    implementation 'com.google.mediapipe:tasks-vision:latest.release'
}

Model

Zadanie MediaPipe Image Embedder wymaga wytrenowanego modelu zgodnego z tym zadanie. Więcej informacji o dostępnych wytrenowanych modelach narzędzia do dodawania obrazów znajdziesz w materiałach na temat zapoznaj się z omówieniem zadania sekcją Modele.

Wybierz i pobierz model, a następnie zapisz go w katalogu projektu:

<dev-project-root>/src/main/assets

Określ ścieżkę modelu w parametrze ModelAssetPath. W przykładowego kodu, model jest zdefiniowany w funkcji setupImageEmbedder() w ImageEmbedderHelper.kt plik:

Użyj metody BaseOptions.Builder.setModelAssetPath(), aby podać ścieżkę używane przez model. Tę metodę przywołaliśmy w przykładzie kodu w następnym .

Tworzenie zadania

Do utworzenia zadania możesz użyć funkcji createFromOptions. Funkcja createFromOptions akceptuje opcje konfiguracji, aby ustawić umieszczony element . Więcej informacji o opcjach konfiguracji znajdziesz w sekcji Konfiguracja Przegląd.

Zadanie dodawania obrazów obsługuje 3 typy danych wejściowych: obrazy, pliki wideo i transmisje wideo na żywo. Musisz określić tryb działania odpowiadający parametrowi typ danych wejściowych podczas tworzenia zadania. Wybierz kartę odpowiadającą typ danych wejściowych, aby zobaczyć, jak utworzyć zadanie i uruchomić wnioskowanie.

Obraz

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.IMAGE)
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

Wideo

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.VIDEO)
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

Transmisja na żywo

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setResultListener((result, inputImage) -> {
         // Process the embedding result here.
    })
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

Przykładowa implementacja kodu pozwala użytkownikowi przełączać się między przetwarzaniem danych i trybów wyświetlania. To podejście sprawia, że kod tworzenia zadań jest bardziej skomplikowany i może nie być w Twoim przypadku użycia. Możesz zobaczyć ten kod w setupImageEmbedder() w ImageEmbedderHelper.kt .

Opcje konfiguracji

To zadanie zawiera te opcje konfiguracji aplikacji na Androida:

Nazwa opcji Opis Zakres wartości Wartość domyślna
runningMode Ustawia tryb działania zadania. Są trzy tryby:

IMAGE: tryb wprowadzania pojedynczego obrazu.

WIDEO: tryb zdekodowanych klatek filmu.

LIVE_STREAM: tryb transmisji danych wejściowych na przykład z kamery. W tym trybie detektor wyników musi mieć wartość wywołano, aby skonfigurować detektor i otrzymywać wyniki asynchronicznie.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
l2_normalize Określa, czy znormalizować zwrócony wektor cech z normą L2. Użyj tej opcji tylko wtedy, gdy model nie zawiera jeszcze reklamy natywnej L2_NORMALIZATION TFLite Op. W większości przypadków tak jest i tak, Normalizacja L2 jest więc osiągana przez wnioskowanie TFLite i nie ma potrzeby dla tej opcji. Boolean False
quantize Określa, czy zwrócony wektor dystrybucyjny powinien być skwantyzowany na bajty za pomocą kwantyzacji skalarnej. Odtwarzacze domyślnie przyjmuje się, że są zgodne z normą jednostkową, w związku z tym każdy wymiar będzie miał wartość w zakresie [-1,0; 1,0]. Używaj wybierz opcję l2_normalize. Boolean False
resultListener Konfiguruje detektor wyników, który otrzymuje wyniki wektora dystrybucyjnego asynchronicznie, gdy komponent Image Embedder jest w transmisji na żywo. i trybu uzyskiwania zgody. Tej opcji można używać tylko wtedy, gdy tryb działania jest ustawiony na LIVE_STREAM Nie dotyczy Nie ustawiono
errorListener Ustawia opcjonalny detektor błędów. Nie dotyczy Nie ustawiono

Przygotuj dane

Umieszczanie obrazów działa z obrazami, plikami wideo i transmisjami wideo na żywo. Zadanie obsługuje wstępne przetwarzanie danych wejściowych, w tym zmianę rozmiaru, obrót i wartość z normalizacją.

Musisz przekonwertować obraz lub klatkę wejściową do com.google.mediapipe.framework.image.MPImage obiekt przed przekazaniem do Zadanie umieszczania obrazów.

Obraz

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Load an image on the user’s device as a Bitmap object using BitmapFactory.

// Convert an Android’s Bitmap object to a MediaPipe’s Image object.
Image mpImage = new BitmapImageBuilder(bitmap).build();
    

Wideo

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Load a video file on the user's device using MediaMetadataRetriever

// From the video’s metadata, load the METADATA_KEY_DURATION and
// METADATA_KEY_VIDEO_FRAME_COUNT value. You’ll need them
// to calculate the timestamp of each frame later.

// Loop through the video and load each frame as a Bitmap object.

// Convert the Android’s Bitmap object to a MediaPipe’s Image object.
Image mpImage = new BitmapImageBuilder(frame).build();
    

Transmisja na żywo

import com.google.mediapipe.framework.image.MediaImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Create a CameraX’s ImageAnalysis to continuously receive frames
// from the device’s camera. Configure it to output frames in RGBA_8888
// format to match with what is required by the model.

// For each Android’s ImageProxy object received from the ImageAnalysis,
// extract the encapsulated Android’s Image object and convert it to
// a MediaPipe’s Image object.
android.media.Image mediaImage = imageProxy.getImage()
Image mpImage = new MediaImageBuilder(mediaImage).build();
    

W przykładowym kodzie przygotowanie danych odbywa się w sekcji ImageEmbedderHelper.kt .

Uruchamianie zadania

Aby aktywować funkcję, możesz wywołać funkcję embed odpowiadającą Twojemu trybowi biegowemu danych. Interfejs Image Embedder API zwraca wektory dystrybucyjne dla danych wejściowych obrazu lub ramki.

Obraz

ImageEmbedderResult embedderResult = imageEmbedder.embed(image);
    

Wideo

// Calculate the timestamp in milliseconds of the current frame.
long frame_timestamp_ms = 1000 * video_duration * frame_index / frame_count;

// Run inference on the frame.
ImageEmbedderResult embedderResult =
    imageEmbedder.embedForVideo(image, frameTimestampMs);
    

Transmisja na żywo


// Run inference on the frame. The embedding results will be available
// via the `resultListener` provided in the `ImageEmbedderOptions` when
// the image embedder was created.
imageEmbedder.embedAsync(image, frameTimestampMs);
    

Pamiętaj:

  • Gdy pracujesz w trybie wideo lub w trybie transmisji na żywo, musisz też podaj sygnaturę czasową ramki wejściowej zadania do umieszczania obrazu na stronie.
  • W trybie obrazu lub filmu zadanie umieszczania obrazu zablokuj bieżący wątek do czasu zakończenia przetwarzania obrazu wejściowego lub ramki. Aby uniknąć zablokowania bieżącego wątku, wykonaj przetwarzanie w w wątku w tle.
  • W trybie transmisji na żywo zadanie umieszczania obrazów nie blokuje w bieżącym wątku, ale wraca natychmiast. Wywoła swój wynik detektor z wynikiem wykrywania za każdym razem, gdy zakończy przetwarzanie ramki wejściowej. Jeśli funkcja embedAsync jest wywoływana przy użyciu narzędzia do umieszczania obrazów zadanie jest zajęte przetwarzaniem innej ramki, zadanie zignoruje nową ramkę wejściową.

W przykładowym kodzie funkcja embed jest zdefiniowana w sekcji ImageEmbedderHelper.kt .

Obsługa i wyświetlanie wyników

Po uruchomieniu wnioskowania zadanie umieszczania obrazów zwraca wartość ImageEmbedderResult. obiekt zawierający listę reprezentacji właściwościowych (zmiennoprzecinkowych lub poddanych kwantyzacji skalarnej) dla obrazu wejściowego.

Poniżej znajdziesz przykładowe dane wyjściowe tego zadania:

ImageEmbedderResult:
  Embedding #0 (sole embedding head):
    float_embedding: {0.0, 0.0, ..., 0.0, 1.0, 0.0, 0.0, 2.0}
    head_index: 0

Ten wynik udało się uzyskać przez umieszczenie tego obrazu:

Możesz porównać podobieństwo dwóch wektorów dystrybucyjnych za pomocą funkcji ImageEmbedder.cosineSimilarity. Poniżej znajdziesz kod dla przykład.

// Compute cosine similarity.
double similarity = ImageEmbedder.cosineSimilarity(
  result.embeddingResult().embeddings().get(0),
  otherResult.embeddingResult().embeddings().get(0));