Zadanie wykrywania obiektów pozwala wykrywać obecność i lokalizację wielu klas obiektów. Detektor obiektów może na przykład zlokalizować psy w obrazie. Poniżej znajdziesz instrukcje korzystania z zadania Wykrywacz obiektów na Androidzie. Przykładowy kod opisany w tych instrukcjach jest dostępny na GitHub. Możesz zobaczyć, jak działa to zadanie, oglądając tę prezentację internetową. 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 aplikacji do wykrywania obiektów na Androida. W tym przykładzie użyto kamery na fizycznym urządzeniu z Androidem, aby stale wykrywać obiekty, a także używać obrazów i filmów z galerii urządzenia do ich statycznego wykrywania.
Możesz użyć aplikacji jako punktu wyjścia dla własnej aplikacji na Androida lub skorzystać z niej podczas modyfikowania istniejącej aplikacji. Przykładowy kod detektora obiektó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:
- Sklonuj repozytorium git za pomocą tego polecenia:
git clone https://github.com/google-ai-edge/mediapipe-samples
- Opcjonalnie skonfiguruj instancję git tak, aby używała rozproszonego procesu płatności, aby mieć tylko pliki dla przykładowej aplikacji do wykrywania obiektów:
cd mediapipe git sparse-checkout init --cone git sparse-checkout set examples/object_detection/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
Poniższe pliki zawierają najważniejszy kod przykładowej aplikacji do wykrywania obiektów:
- ObjectDetectorHelper.kt – inicjuje detektor obiektów i obsługuje model oraz wybór delegacji
- MainActivity.kt – implementowanie aplikacji i tworzenie komponentów interfejsu użytkownika.
- OverlayView.kt – obsługuje i wyświetla wyniki
Konfiguracja
W tej sekcji opisujemy najważniejsze czynności, jakie należy wykonać, aby skonfigurować środowisko programistyczne i projekty kodu, w których będzie używany detektor obiektów. 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
Detektor obiektów używa 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 wykrywania obiektów MediaPipe wymaga wytrenowanego modelu, który jest zgodny z tym zadaniem. Więcej informacji o dostępnych wytrenowanych modelach dotyczących wykrywania obiektów znajdziesz w sekcji poświęconej modelom – omówieniem zadania.
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()
. Przykładowy kod znajdziesz w następnej sekcji.
Tworzenie zadania
Aby utworzyć zadanie, możesz użyć funkcji createFromOptions
. Funkcja createFromOptions
akceptuje opcje konfiguracji, w tym tryb działania, język wyświetlanych nazw, maksymalną liczbę wyników, próg ufności, listę dozwolonych kategorii i listę odrzuconych. Jeśli opcja konfiguracji nie zostanie określona, zostanie użyta wartość domyślna. Więcej informacji o opcjach konfiguracji znajdziesz w artykule Omówienie konfiguracji.
Zadanie wykrywania obiektów obsługuje 3 typy danych wejściowych: obrazy, pliki wideo i strumienie wideo na żywo. Podczas tworzenia zadania musisz określić tryb działania odpowiadający typowi danych wejściowych. Wybierz kartę odpowiadającą typowi danych wejściowych, aby zobaczyć, jak utworzyć zadanie i uruchomić wnioskowanie.
Obraz
ObjectDetectorOptions options = ObjectDetectorOptions.builder() .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build()) .setRunningMode(RunningMode.IMAGE) .setMaxResults(5) .build(); objectDetector = ObjectDetector.createFromOptions(context, options);
Wideo
ObjectDetectorOptions options = ObjectDetectorOptions.builder() .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build()) .setRunningMode(RunningMode.VIDEO) .setMaxResults(5) .build(); objectDetector = ObjectDetector.createFromOptions(context, options);
Transmisja na żywo
ObjectDetectorOptions options = ObjectDetectorOptions.builder() .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build()) .setRunningMode(RunningMode.LIVE_STREAM) .setMaxResults(5) .setResultListener((result, inputImage) -> { // Process the detection result here. }) .setErrorListener((result, inputImage) -> { // Process the classification errors here. }) .build(); objectDetector = ObjectDetector.createFromOptions(context, options);
Przykładowa implementacja kodu do wykrywania obiektów pozwala użytkownikowi przełączać się między trybami przetwarzania. Takie podejście zwiększa złożoność kodu tworzenia zadania i może nie być odpowiednie w Twoim przypadku. Ten kod znajdziesz w funkcji setupObjectDetector()
klasy ObjectDetectorHelper
.
Opcje konfiguracji
To zadanie ma te opcje konfiguracji aplikacji na Androida:
Nazwa opcji | Opis | Zakres wartości | Wartość domyślna |
---|---|---|---|
runningMode |
Ustawia tryb działania zadania. Są 3 tryby: IMAGE: tryb wprowadzania pojedynczych obrazów. WIDEO: tryb dekodowanych klatek filmu. TRANSMISJA NA ŻYWO: tryb transmisji danych wejściowych na żywo, np. z kamery. W tym trybie należy wywołać metodę resultListener, aby skonfigurować odbiornik, który będzie odbierał wyniki asynchronicznie. |
{IMAGE, VIDEO, LIVE_STREAM } |
IMAGE |
displayNamesLocales |
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 |
maxResults |
Określa opcjonalną maksymalną liczbę wyników wykrywania o najwyższych wynikach do zwrócenia. | Dowolne liczby dodatnie | -1 (zwracane są wszystkie wyniki) |
scoreThreshold |
Ustawia próg wyniku prognozy, który zastępuje próg podany w metadanych modelu (jeśli istnieją). Wyniki poniżej tej wartości zostały odrzucone. | Dowolna liczba zmiennoprzecinkowa | Nie ustawiono |
categoryAllowlist |
Ustawia opcjonalną listę dozwolonych nazw kategorii. Jeśli pole nie jest puste, wyniki wykrywania, których nazwy kategorii nie ma w tym zbiorze, zostaną odfiltrowane. Zduplikowane i nieznane nazwy kategorii są ignorowane.
Ta opcja wzajemnie się wyklucza, categoryDenylist i ich użycie kończy się błędem. |
Dowolne ciągi | Nie ustawiono |
categoryDenylist |
Ustawia opcjonalną listę niedozwolonych nazw kategorii. Jeśli pole nie jest puste, wyniki wykrywania, których nazwa kategorii znajduje się w tym zbiorze, zostaną odfiltrowane. Zduplikowane i nieznane nazwy kategorii są ignorowane. Ta opcja wzajemnie się wyklucza z categoryAllowlist , a korzystanie z obu daje błąd. |
Dowolne ciągi | Nie ustawiono |
resultListener |
Konfiguruje detektor wyników, aby asynchronicznie otrzymywać wyniki wykrywania, gdy detektor obiektów działa w trybie transmisji na żywo. Możesz użyć tej opcji tylko wtedy, gdy ustawisz tryb biegania na LIVE_STREAM. | Nie dotyczy | Nie ustawiono |
Przygotuj dane
Zanim prześlesz obraz lub ramkę do wykrywania obiektów, musisz przekonwertować go na obiekt com.google.mediapipe.framework.image.MPImage
.
Poniższe przykłady wyjaśniają i pokazują, jak przygotować dane do przetwarzania w przypadku każdego z dostępnych typów danych:
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 values. Use these values // 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() MPImage mpImage = new MediaImageBuilder(mediaImage).build();
W przykładowym kodzie detektora obiektów przygotowanie danych jest przeprowadzane w klasie ObjectDetectorHelper
w funkcjach detectImage()
, detectVideoFile()
i detectLivestreamFrame()
.
Uruchamianie zadania
W zależności od typu danych, z którymi pracujesz, użyj metody ObjectDetector.detect...()
odpowiedniej dla tego typu danych. Użyj detect()
w przypadku pojedynczych obrazów, detectForVideo()
– klatek w plikach wideo i detectAsync()
w przypadku strumieni wideo. Podczas wykrywania strumienia wideo pamiętaj o uruchamianiu wykrywania w osobnym wątku, aby uniknąć zablokowania wątku interfejsu.
Poniższe przykłady kodu pokazują proste przykłady uruchamiania detektora obiektów w różnych trybach danych:
Obraz
ObjectDetectorResult detectionResult = objectDetector.detect(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. ObjectDetectorResult detectionResult = objectDetector.detectForVideo(image, frameTimestampMs);
Transmisja na żywo
// Run inference on the frame. The detection results will be available // via the `resultListener` provided in the `ObjectDetectorOptions` when // the object detector was created. objectDetector.detectAsync(image, frameTimestampMs);
W przykładowym kodzie detektora obiektów znajdziesz bardziej szczegółowe opisy każdego z tych trybów: detect()
, detectVideoFile()
i detectAsync()
.
Przykładowy kod pozwala użytkownikowi przełączać się między trybami przetwarzania, które mogą nie być wymagane w Twoim przypadku.
Uwaga:
- Gdy działasz w trybie wideo lub w trybie transmisji na żywo, musisz też podać sygnaturę czasową klatki wejściowej do zadania wykrywania obiektów.
- W trybie obrazu lub wideo zadanie wykrywania obiektów zablokuje bieżący wątek do momentu zakończenia przetwarzania obrazu wejściowego lub klatki. Aby uniknąć zablokowania bieżącego wątku, wykonaj przetwarzanie w wątku w tle.
- W trybie transmisji na żywo zadanie Wykrywacz obiektów nie blokuje bieżącego wątku, ale zwraca je natychmiast. Wywołuje on detektor wyników z wynikiem wykrywania za każdym razem, gdy zakończy przetwarzanie ramki wejściowej. Jeśli funkcja wykrywania zostanie wywołana, gdy zadanie wykrywania obiektów jest zajęte przetwarzaniem innej ramki, nowa ramka wejściowa zostanie zignorowana.
Obsługa i wyświetlanie wyników
Po uruchomieniu wnioskowania zadanie wykrywania obiektów zwraca obiekt ObjectDetectorResult
, który opisuje obiekty znalezione na obrazie wejściowym.
Poniżej znajdziesz przykład danych wyjściowych z tego zadania:
ObjectDetectorResult:
Detection #0:
Box: (x: 355, y: 133, w: 190, h: 206)
Categories:
index : 17
score : 0.73828
class name : dog
Detection #1:
Box: (x: 103, y: 15, w: 138, h: 369)
Categories:
index : 17
score : 0.73047
class name : dog
Poniższy obraz przedstawia wizualizację wyników zadania:
Przykładowy kod detektora obiektów pokazuje, jak wyświetlać wyniki wykrywania zwrócone przez zadanie. Więcej informacji znajdziesz w klasie OverlayView
.