Interaktywny przewodnik po segmentacji obrazu na Androidzie

Zadanie MediaPipe Interactive Image Segmenter pobiera lokalizację na obrazie, szacuje granice obiektu w tej lokalizacji i zwraca segmentację obiektu jako dane obrazu. Z tych instrukcji dowiesz się, jak używać interaktywnego podziału obrazów na segmenty w przypadku aplikacji na Androida. Przykładowy kod opisany w tych instrukcjach jest dostępny na GitHub. Więcej informacji o możliwościach, modelach i opcjach konfiguracji tego zadania znajdziesz w sekcji Omówienie.

Przykładowy kod

Przykładowy kod MediaPipe Tasks to prosta implementacja interaktywnej aplikacji do segmentacji obrazów na Androida. W tym przykładzie działają obrazy wybrane z galerii urządzenia.

Możesz użyć aplikacji jako punktu wyjścia dla własnej aplikacji na Androida lub odwołać się do niej podczas jej modyfikowania. Przykładowy kod interaktywnego narzędzia do segmentacji obrazów jest hostowany na GitHub.

Pobieranie kodu

Z instrukcji poniżej dowiesz się, jak utworzyć lokalną kopię przykładowego kodu 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 skonfiguruj instancję git tak, aby używała rozproszonego procesu płatności, aby mieć tylko pliki dla przykładowej aplikacji do interaktywnego segmentowania obrazów:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/interactive_segmentation/android
    

Po utworzeniu lokalnej wersji przykładowego kodu możesz zaimportować projekt do Android Studio i uruchomić aplikację. Instrukcje znajdziesz w przewodniku konfiguracji na Androida.

Kluczowe elementy

Te pliki zawierają kluczowy kod tej przykładowej aplikacji do podziału obrazów na segmenty:

Konfiguracja

W tej sekcji znajdziesz najważniejsze czynności, jakie należy wykonać, aby skonfigurować środowisko programistyczne i projekty kodu pod kątem korzystania z interaktywnego podziału obrazów na segmenty. Ogólne informacje o konfigurowaniu środowiska programistycznego na potrzeby zadań MediaPipe, w tym o wymaganiach dotyczących wersji platformy, znajdziesz w przewodniku konfiguracji na Androida.

Zależności

Interaktywny podział obrazów korzysta z biblioteki com.google.mediapipe:tasks-vision. Dodaj tę zależność do pliku build.gradle swojego projektu na Androida. Zaimportuj wymagane zależności za pomocą tego kodu:

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

Model

Zadanie MediaPipe Interactive Image Segmenter wymaga wytrenowanego modelu zgodnego z tym zadaniem. Więcej informacji o dostępnych wytrenowanych modelach do interaktywnego segmentowania obrazów znajdziesz w sekcji poświęconej modelom na temat zadań.

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

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

Aby określić ścieżkę używaną przez model, użyj metody BaseOptions.Builder.setModelAssetPath(). Tę metodę pokazujemy w przykładowym kodzie w następnej sekcji.

W przykładowym kodzie interaktywnego narzędzia do segmentacji obrazów model jest zdefiniowany w klasie InteractiveSegmenterHelper.kt w funkcji setupInteractiveSegmenter().

Tworzenie zadania

Aby utworzyć zadanie, możesz użyć funkcji createFromOptions. Funkcja createFromOptions akceptuje opcje konfiguracji, w tym typy danych wyjściowych maski. Więcej informacji o opcjach konfiguracji znajdziesz w artykule Omówienie konfiguracji.

InteractiveSegmenterOptions options =
  InteractiveSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .setResultListener((result, inputImage) -> {
         // Process the segmentation result here.
    })
    .setErrorListener((result, inputImage) -> {
         // Process the segmentation errors here.
    })    .build();
interactivesegmenter = InteractiveSegmenter.createFromOptions(context, options);

Bardziej szczegółowy przykład konfigurowania tego zadania znajdziesz w opisie funkcji setupInteractiveSegmenter() klasy InteractiveSegmenterHelper.

Opcje konfiguracji

To zadanie ma te opcje konfiguracji aplikacji na Androida:

Nazwa opcji Opis Zakres wartości Wartość domyślna
outputCategoryMask Jeśli ustawisz wartość True, dane wyjściowe będą zawierały maskę segmentacji w postaci obrazu uint8, w którym każda wartość piksela wskazuje, czy piksel jest częścią obiektu znajdującego się w ciekawym obszarze. {True, False} False
outputConfidenceMasks Jeśli ma wartość True, dane wyjściowe zawierają maskę podziału w postaci obrazu z wartościami zmiennoprzecinkowymi, w których każda wartość zmiennoprzecinkowa reprezentuje stopień pewności, że piksel jest częścią obiektu znajdującego się w ciekawym obszarze. {True, False} True
displayNamesLocale Ustawia język etykiet, które mają być używane w przypadku nazw wyświetlanych w metadanych modelu zadania (jeśli są dostępne). Wartość domyślna w języku angielskim to en. Za pomocą TensorFlow Lite MetadataWriter API możesz dodawać zlokalizowane etykiety do metadanych modelu niestandardowego. Kod języka en
errorListener Ustawia opcjonalny detektor błędów. Nie dotyczy Nie ustawiono

Przygotuj dane

Interaktywny podział obrazów na segmenty obsługuje obrazy, a zapewnia wstępne przetwarzanie danych wejściowych, w tym zmianę rozmiaru, obrót i normalizację wartości. Przed przekazaniem obrazu wejściowego do zadania musisz go przekonwertować na obiekt com.google.mediapipe.framework.image.MPImage.

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();

W przykładowym kodzie interaktywnego narzędzia do segmentacji obrazów przygotowywanie danych jest obsługiwane w klasie InteractiveSegmenterHelper przez funkcję segment().

Uruchamianie zadania

Wywołaj funkcję segment, aby uruchomić prognozę i wygenerować segmenty. Zadanie interaktywnego segmentowania obrazów zwraca zidentyfikowane regiony segmentów w obrazie wejściowym.

RegionOfInterest roi = RegionOfInterest.create(
    NormalizedKeypoint.create(
        normX * it.width,
        normY * it.height
    )
);

ImageSegmenterResult segmenterResult = interactivesegmenter.segment(image, roi);

W przykładowym kodzie interaktywnego narzędzia do segmentacji obrazów funkcje segment są zdefiniowane w pliku InteractiveSegmenterHelper.kt.

Obsługa i wyświetlanie wyników

Po uruchomieniu wnioskowania zadanie Interaktywny podział obrazów na segmenty zwraca obiekt ImageSegmenterResult zawierający wyniki zadania podziału na segmenty. Dane wyjściowe mogą zawierać maskę kategorii, maskę ufności lub oba te elementy w zależności od tego, co zostało ustawione podczas konfigurowania zadania.

W sekcjach poniżej objaśniamy szczegółowo dane wyjściowe z tego zadania:

Maska kategorii

Na poniższych obrazach pokazano wizualizację wyników zadania w przypadku maski wartości kategorii ze wskazanym ważnym obszarem. Każdy piksel to wartość uint8 wskazująca, czy jest on częścią obiektu znajdującego się w danym obszarze. Czarno-białe kółko na drugim zdjęciu wskazuje wybrany obszar zainteresowań.

Oryginalny obraz i maska kategorii. Obraz źródłowy ze zbioru danych Pascal VOC 2012.

Maska ufności

Dane wyjściowe maski ufności zawierają wartości zmiennoprzecinkowe między [0, 1] dla każdego kanału wejściowego obrazu. Wyższe wartości oznaczają większą pewność, że piksel obrazu jest częścią obiektu znajdującego się w ciekawym obszarze.