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:
- Sklonuj repozytorium git za pomocą tego polecenia:
git clone https://github.com/google-ai-edge/mediapipe-samples
- 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:
- ImageEmbedderHelper.kt: inicjuje komponent do umieszczania obrazu i obsługuje model oraz deleguje wyboru.
- MainActivity.kt: implementuje aplikację i montuje komponenty interfejsu.
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));