Zadanie MediaPipe Image segmenter umożliwia podział obrazów na regiony na podstawie wstępnie zdefiniowanych kategorii, w których można zastosować efekty wizualne, np. rozmycie tła. Te jak używać segmentacji obrazów w aplikacjach na Androida. Kod przykład opisany w tych instrukcjach jest dostępny na GitHub Więcej informacji o funkcjach, modelach i opcjach konfiguracji zapoznaj się z Przeglądem.
Przykładowy kod
Przykładowy kod MediaPipe Tasks zawiera dwie proste implementacje interfejsu Aplikacja do segmentowania obrazów na Androida:
Aparatem w fizycznym urządzeniu z Androidem jest aparat, segmentacji obrazu w kamerze lub wybrać obrazy i z galerii na urządzeniu. Możesz ich używać jako punktu wyjścia Twoją własną aplikację na Androida lub przywoływać się do nich podczas modyfikowania istniejącej aplikacji. Przykładowy kod segmentacji obrazów jest hostowany GitHub
W sekcjach poniżej Segmenter obrazów z maską kategorii .
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,
masz więc tylko pliki przykładowej aplikacji Image Segmenter:
cd mediapipe git sparse-checkout init --cone git sparse-checkout set examples/image_segmentation/android
Po utworzeniu lokalnej wersji przykładowego kodu możesz zaimportować projekt w Android Studio i uruchom aplikację. Instrukcje znajdziesz w Przewodnik po konfiguracji na Androida
Kluczowe elementy
Te pliki zawierają kluczowy kod dla tego obrazu przykładowa aplikacja do podziału na segmenty:
- ImageSegmenterHelper.kt – Inicjuje zadanie segmentacji obrazów oraz obsługuje model i przekazuje dostęp do niego wyboru.
- CameraFragment.kt – Zawiera interfejs użytkownika i kod sterujący kamery.
- GalleryFragment.kt – Zawiera interfejs użytkownika i kod sterujący do wyboru obrazów i filmów .
- OverlayView.kt – Obsługuje i formatuje wyniki segmentacji.
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ć segmentowania obrazów. Ogólne informacje na temat: skonfigurować środowisko programistyczne do korzystania z zadań MediaPipe, w tym wymagań wersji platformy, patrz Przewodnik po konfiguracji na Androida
Zależności
Segmentacja obrazów korzysta z biblioteki com.google.mediapipe:tasks-vision
. Dodaj to
zależności od pliku build.gradle
Projekt tworzenia aplikacji na Androida. Zaimportuj wymagane zależności za pomocą:
ten kod:
dependencies {
...
implementation 'com.google.mediapipe:tasks-vision:latest.release'
}
Model
Zadanie MediaPipe Image segmenter wymaga wytrenowanego modelu zgodnego z tym zadanie. Więcej informacji na temat dostępnych wytrenowanych modeli dla narzędzia do segmentowania obrazów znajdziesz w artykule 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
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
.
W segmentatorze obrazów
przykładowy kod,
model jest zdefiniowany w ImageSegmenterHelper.kt
w funkcji setupImageSegmenter()
.
Tworzenie zadania
Do utworzenia zadania możesz użyć funkcji createFromOptions
.
Funkcja createFromOptions
akceptuje opcje konfiguracji, w tym dane wyjściowe maski
. Więcej informacji o konfigurowaniu zadań znajdziesz w artykule
Opcje konfiguracji:
Zadanie segmentacji obrazów obsługuje te typy danych wejściowych: obrazy, plików wideo i transmisji wideo na żywo. Musisz określić tryb uruchamiania odpowiadający typowi danych wejściowych podczas tworzenia zadania. Wybierz kartę dla typu danych wejściowych, aby zobaczyć, jak utworzyć to zadanie.
Obraz
ImageSegmenterOptions options = ImageSegmenterOptions.builder() .setBaseOptions( BaseOptions.builder().setModelAssetPath("model.tflite").build()) .setRunningMode(RunningMode.IMAGE) .setOutputCategoryMask(true) .setOutputConfidenceMasks(false) .build(); imagesegmenter = ImageSegmenter.createFromOptions(context, options);
Wideo
ImageSegmenterOptions options = ImageSegmenterOptions.builder() .setBaseOptions( BaseOptions.builder().setModelAssetPath("model.tflite").build()) .setRunningMode(RunningMode.VIDEO) .setOutputCategoryMask(true) .setOutputConfidenceMasks(false) .build(); imagesegmenter = ImageSegmenter.createFromOptions(context, options);
Transmisja na żywo
ImageSegmenterOptions options = ImageSegmenterOptions.builder() .setBaseOptions( BaseOptions.builder().setModelAssetPath("model.tflite").build()) .setRunningMode(RunningMode.LIVE_STREAM) .setOutputCategoryMask(true) .setOutputConfidenceMasks(false) .setResultListener((result, inputImage) -> { // Process the segmentation result here. }) .setErrorListener((result, inputImage) -> { // Process the segmentation errors here. }) .build() imagesegmenter = ImageSegmenter.createFromOptions(context, options)
Przykładowa implementacja kodu segmentacji obrazów pozwala użytkownikowi przełączać się między
i przetwarzania danych. Takie podejście sprawia, że kod tworzenia zadań jest bardziej skomplikowany,
może nie być odpowiednia w Twoim przypadku użycia. Możesz zobaczyć ten kod w
ImageSegmenterHelper
przez funkcję setupImageSegmenter()
.
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 |
outputCategoryMask |
Jeśli ma wartość True , dane wyjściowe będą zawierały maskę podziału na segmenty.
jako obraz uint8, gdzie każda wartość w pikselach wskazuje zwycięską kategorię
. |
{True, False } |
False |
outputConfidenceMasks |
Jeśli ma wartość True , dane wyjściowe będą zawierały maskę podziału na segmenty.
jako obraz wartości zmiennoprzecinkowej, gdzie każda wartość zmiennoprzecinkowa odzwierciedla poziom ufności
punktację danej kategorii. |
{True, False } |
True |
displayNamesLocale |
Ustawia język etykiet, które mają być używane w przypadku nazw wyświetlanych w kolumnie
metadane modelu zadania, jeśli są dostępne. Wartość domyślna to en dla
Angielski. Do metadanych modelu niestandardowego możesz dodać zlokalizowane etykiety
za pomocą interfejsu TensorFlow Lite Metadata Writer API. |
Kod języka | en |
resultListener |
Konfiguruje detektor wyników, który ma otrzymywać wyniki segmentacji
asynchronicznie, gdy segmenter obrazów działa w trybie LIVE_STREAM .
Tej opcji można używać tylko wtedy, gdy tryb działania jest ustawiony na LIVE_STREAM |
Nie dotyczy | Nie dotyczy |
errorListener |
Ustawia opcjonalny detektor błędów. | Nie dotyczy | Nie ustawiono |
Przygotuj dane
Narzędzie do podziału 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ść ich normalizację.
Musisz przekonwertować obraz lub klatkę wejściową do
com.google.mediapipe.framework.image.MPImage
obiekt przed przekazaniem do
Segmentowanie 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 segmentacji obrazów przygotowanie danych odbywa się w sekcji
ImageSegmenterHelper
przez funkcję segmentLiveStreamFrame()
.
Uruchamianie zadania
W zależności od używanego trybu uruchamiania wywołasz inną funkcję segment
.
Funkcja segmentowania obrazów zwraca zidentyfikowane regiony segmentu w obrębie argumentu
obrazu lub ramki.
Obraz
ImageSegmenterResult segmenterResult = imagesegmenter.segment(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. ImageSegmenterResult segmenterResult = imagesegmenter.segmentForVideo(image, frameTimestampMs);
Transmisja na żywo
// Run inference on the frame. The segmentations results will be available via // the `resultListener` provided in the `ImageSegmenterOptions` when the image // segmenter was created. imagesegmenter.segmentAsync(image, frameTimestampMs);
Pamiętaj:
- Gdy pracujesz w trybie wideo lub w trybie transmisji na żywo, musisz też podaj sygnaturę czasową ramki wejściowej zadania segmentacji obrazów.
- W trybie obrazu lub wideo zadanie segmentacji obrazów blokuje bieżący wątek do czasu zakończenia przetwarzania obrazu wejściowego lub ramki. Aby uniknąć blokowania interfejsu użytkownika, wykonaj przetwarzanie w w wątku w tle.
- W trybie transmisji na żywo zadanie segmentacji 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
segmentAsync
jest wywoływana podczas segmentowania obrazów zadanie jest zajęte przetwarzaniem innej ramki, zadanie zignoruje nową ramkę wejściową.
W przykładowym kodzie segmentacji obrazów funkcje segment
są zdefiniowane w sekcji
ImageSegmenterHelper.kt
.
.
Obsługa i wyświetlanie wyników
Po przeprowadzeniu wnioskowania zadanie segmentacji obrazów zwraca wartość ImageSegmenterResult
.
który zawiera wyniki zadania segmentacji. Zawartość
dane wyjściowe zależą od parametru outputType
ustawionego podczas
skonfigurowano zadanie.
W sekcjach poniżej znajdziesz przykłady danych wyjściowych z tego zadania:
Poziom ufności kategorii
Te obrazy przedstawiają wizualizację danych wyjściowych zadania dla kategorii
maską ufności. Dane wyjściowe maski ufności zawierają wartości zmiennoprzecinkowe między
[0, 1]
Oryginalny obraz i maska zaufania kategorii. Obraz źródłowy z Pascal VOC 2012 w zbiorze danych.
Wartość kategorii
Te obrazy przedstawiają wizualizację danych wyjściowych zadania dla kategorii
maską wartości. Zakres maski kategorii wynosi [0, 255]
i każda wartość piksela
reprezentuje indeks zwycięskiej kategorii danych wyjściowych modelu. Zwycięska kategoria
indeks ma najwyższy wynik spośród kategorii, które model może rozpoznać.
Oryginalny obraz i maska kategorii. Obraz źródłowy z Pascal VOC 2012 w zbiorze danych.