Zadanie wykrywania obiektów pozwala wykrywać obecność i lokalizację wielu klas obiektów. Detektor obiektów może na przykład zlokalizować psy na zdjęciu. W tych instrukcjach pokazujemy, jak korzystać z zadania Wykrywacz obiektów w iOS. Przykładowy kod opisany w tych instrukcjach jest dostępny na GitHub.
Działanie tego zadania możesz zobaczyć w tej wersji demonstracyjnej. 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 podstawowa implementacja aplikacji do wykrywania obiektów na iOS. W tym przykładzie użyto kamery w fizycznym urządzeniu z iOS do ciągłego wykrywania obiektów, a także do statycznego wykrywania obiektów za pomocą obrazów i filmów z galerii urządzenia.
Możesz użyć aplikacji jako punktu wyjścia dla własnej aplikacji na iOS 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/ios/
Po utworzeniu lokalnej wersji przykładowego kodu możesz zainstalować bibliotekę zadań MediaPipe, otworzyć projekt za pomocą Xcode i uruchomić aplikację. Instrukcje znajdziesz w przewodniku po konfiguracji na iOS.
Kluczowe elementy
Poniższe pliki zawierają najważniejszy kod przykładowej aplikacji do wykrywania obiektów:
- ObjectDetectorService.swift: inicjuje detektor, wybiera model i uruchamia wnioskowanie na danych wejściowych.
- CameraViewController.swift: implementuje interfejs użytkownika w trybie przesyłania obrazu na żywo z kamery i wizualizuje wyniki wykrywania.
- MediaLibraryViewController.swift: implementuje interfejs użytkownika w trybie wprowadzania plików ze zdjęciami i filmami oraz wizualizuje wyniki wykrywania.
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 dla iOS.
Zależności
Detektor obiektów korzysta z biblioteki MediaPipeTasksVision
, którą należy zainstalować za pomocą CocoaPods. Biblioteka jest zgodna z aplikacjami Swift i Objective-C i nie wymaga dodatkowej konfiguracji pod kątem określonego języka.
Instrukcje instalowania CocoaPods w systemie macOS znajdziesz w przewodniku instalacji CocoaPods.
Instrukcje tworzenia Podfile
z podami niezbędnymi do działania aplikacji znajdziesz w artykule Korzystanie z CocoaPods.
Dodaj pod MediaPipeTasksVision w narzędziu Podfile
za pomocą tego kodu:
target 'MyObjectDetectorApp' do
use_frameworks!
pod 'MediaPipeTasksVision'
end
Jeśli aplikacja zawiera cele testu jednostkowego, dodatkowe informacje o konfigurowaniu Podfile
znajdziesz w przewodniku konfiguracji na iOS.
Model
Zadanie wykrywania obiektów MediaPipe wymaga wytrenowanego modelu, który jest zgodny z tym zadaniem. Więcej informacji o dostępnych wytrenowanych modelach służących do wykrywania obiektów znajdziesz w sekcji poświęconej modelom zadania.
Wybierz i pobierz model, a potem dodaj go do katalogu projektów za pomocą Xcode. Instrukcje dodawania plików do projektu Xcode znajdziesz w artykule Zarządzanie plikami i folderami w projekcie Xcode.
Aby określić ścieżkę do modelu w pakiecie aplikacji, użyj właściwości BaseOptions.modelAssetPath
. Przykładowy kod znajdziesz w następnej sekcji.
Tworzenie zadania
Możesz utworzyć zadanie Wykrywacz obiektów, wywołując jeden z jego inicjatorów. Inicjator ObjectDetector(options:)
ustawia wartości opcji konfiguracji, w tym trybu działającego, ustawień regionalnych nazw wyświetlanych, maksymalnej liczby wyników, progu ufności, listy dozwolonych kategorii i listy odrzuconych.
Jeśli nie potrzebujesz detektora obiektów zainicjowanego z niestandardowymi opcjami konfiguracji, możesz użyć inicjatora ObjectDetector(modelPath:)
, aby utworzyć detektor obiektów z opcjami domyślnymi. 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. Domyślnie ObjectDetector(modelPath:)
inicjuje zadanie dotyczące nieruchomych obrazów. Jeśli chcesz zainicjować zadanie na potrzeby przetwarzania plików wideo lub strumieni wideo na żywo, użyj funkcji ObjectDetector(options:)
, aby określić tryb transmisji wideo lub transmisji na żywo. Tryb transmisji na żywo wymaga też dodatkowej opcji konfiguracji objectDetectorLiveStreamDelegate
, która umożliwia detektorowi obiektów asynchronicznie dostarczanie wyników wykrywania do delegata.
Wybierz kartę odpowiadającą Twojemu trybowi biegowemu, aby zobaczyć, jak utworzyć zadanie i uruchomić wnioskowanie.
Swift
Obraz
import MediaPipeTasksVision let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite") let options = ObjectDetectorOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .image options.maxResults = 5 let objectDetector = try ObjectDetector(options: options)
Wideo
import MediaPipeTasksVision let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite") let options = ObjectDetectorOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .video options.maxResults = 5 let objectDetector = try ObjectDetector(options: options)
transmisja na żywo
import MediaPipeTasksVision // Class that conforms to the `ObjectDetectorLiveStreamDelegate` protocol and // implements the method that the object detector calls once it // finishes performing detection on each input frame. class ObjectDetectorResultProcessor: NSObject, ObjectDetectorLiveStreamDelegate { func objectDetector( _ objectDetector: ObjectDetector, didFinishDetection objectDetectionResult: ObjectDetectorResult?, timestampInMilliseconds: Int, error: Error?) { // Process the detection result or errors here. } } let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite") let options = ObjectDetectorOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .liveStream options.maxResults = 5 // Assign an object of the class to the `objectDetectorLiveStreamDelegate` // property. let processor = ObjectDetectorResultProcessor() options.objectDetectorLiveStreamDelegate = processor let objectDetector = try ObjectDetector(options: options)
Objective-C
Obraz
@import MediaPipeTasksVision; NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model" ofType:@"tflite"]; MPPObjectDetectorOptions *options = [[MPPObjectDetectorOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeImage; options.maxResults = 5; MPPObjectDetector *objectDetector = [[MPPObjectDetector alloc] initWithOptions:options error:nil];
Wideo
@import MediaPipeTasksVision; NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model" ofType:@"tflite"]; MPPObjectDetectorOptions *options = [[MPPObjectDetectorOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeVideo; options.maxResults = 5; MPPObjectDetector *objectDetector = [[MPPObjectDetector alloc] initWithOptions:options error:nil];
transmisja na żywo
@import MediaPipeTasksVision; // Class that conforms to the `ObjectDetectorLiveStreamDelegate` protocol and // implements the method that the object detector calls once it // finishes performing detection on each input frame. @interface APPObjectDetectorResultProcessor : NSObject@end @implementation MPPObjectDetectorResultProcessor - (void)objectDetector:(MPPObjectDetector *)objectDetector didFinishDetectionWithResult:(MPPObjectDetectorResult *)ObjectDetectorResult timestampInMilliseconds:(NSInteger)timestampInMilliseconds error:(NSError *)error { // Process the detection result or errors here. } @end NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model" ofType:@"tflite"]; MPPObjectDetectorOptions *options = [[MPPObjectDetectorOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeLiveStream; options.maxResults = 5; // Assign an object of the class to the `objectDetectorLiveStreamDelegate` // property. APPObjectDetectorResultProcessor *processor = [APPObjectDetectorResultProcessor new]; options.objectDetectorLiveStreamDelegate = processor; MPPObjectDetector *objectDetector = [[MPPObjectDetector alloc] initWithOptions:options error:nil];
Opcje konfiguracji
To zadanie ma te opcje konfiguracji w przypadku aplikacji na iOS:
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. |
{RunningMode.image, RunningMode.video, RunningMode.liveStream } |
RunningMode.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 |
Konfiguracja transmisji na żywo
Gdy tryb działania jest ustawiony na transmisję na żywo, detektor obiektów wymaga dodatkowej opcji konfiguracji objectDetectorLiveStreamDelegate
, co umożliwia asynchroniczne dostarczanie wyników wykrywania. Delegat wdraża metodę objectDetector(_objectDetector:didFinishDetection:timestampInMilliseconds:error:)
, która jest wywoływana przez detektor obiektów po przetworzeniu wyniku wykrywania dla każdej ramki.
Nazwa opcji | Opis | Zakres wartości | Wartość domyślna |
---|---|---|---|
objectDetectorLiveStreamDelegate |
Umożliwia detektorowi obiektów asynchroniczne otrzymywanie wyników wykrywania w trybie transmisji na żywo. Klasa, której instancja jest ustawiona na tę właściwość, musi implementować metodę objectDetector(_:didFinishDetection:timestampInMilliseconds:error:) . |
Nie dotyczy | Nie ustawiono |
Przygotuj dane
Zanim prześlesz obraz lub ramkę do detektora obiektów, musisz przekonwertować go na obiekt MPImage
. MPImage
obsługuje różne typy formatów obrazów na iOS i może ich używać w każdym trybie działania, aby wnioskować. Więcej informacji na temat MPImage
znajdziesz w interfejsie MPImage API
Wybierz format obrazu na iOS zależnie od swojego przypadku użycia i trybu uruchamiania, którego wymaga Twoja aplikacja.MPImage
akceptuje formaty obrazów UIImage
, CVPixelBuffer
i CMSampleBuffer
(iOS).
UIImage
Format UIImage
dobrze sprawdza się w tych trybach biegania:
Obrazy: obrazy z pakietu aplikacji, galerii użytkownika lub systemu plików sformatowane jako obrazy
UIImage
można przekonwertować na obiektMPImage
.Filmy: użyj narzędzia AVAssetImageGenerator, aby wyodrębnić klatki wideo do formatu CGImage, a następnie przekonwertuj je na obrazy
UIImage
.
Swift
// Load an image on the user's device as an iOS `UIImage` object. // Convert the `UIImage` object to a MediaPipe's Image object having the default // orientation `UIImage.Orientation.up`. let image = try MPImage(uiImage: image)
Objective-C
// Load an image on the user's device as an iOS `UIImage` object. // Convert the `UIImage` object to a MediaPipe's Image object having the default // orientation `UIImageOrientationUp`. MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
W tym przykładzie inicjuje się MPImage
z domyślną orientacją UIImage.Orientation.Up. Możesz zainicjować MPImage
przy użyciu dowolnej z obsługiwanych wartości UIImage.Orientation. Detektor obiektów nie obsługuje odbicia lustrzanego orientacji, takich jak .upMirrored
,
.downMirrored
, .leftMirrored
, .rightMirrored
.
Więcej informacji na temat UIImage
znajdziesz w dokumentacji dla programistów Apple dotyczącej UIImage (w języku angielskim).
CVPixelBuffer
Format CVPixelBuffer
dobrze sprawdza się w aplikacjach, które generują ramki i wykorzystują do przetwarzania platformę CoreImage w systemie iOS.
Format CVPixelBuffer
dobrze sprawdza się w tych trybach biegania:
Obrazy: aplikacje, które po przetworzeniu niektórych obrazów przy użyciu platformy
CoreImage
systemu iOS generują obrazyCVPixelBuffer
, mogą być wysyłane do detektora obiektów w trybie działania obrazów.Filmy: klatki wideo można przekonwertować na format
CVPixelBuffer
w celu przetworzenia, a następnie wysłać do wzorca do wykrywania obiektów w trybie wideo.transmisja na żywo: aplikacje korzystające z kamery w iOS do generowania klatek można skonwertować do formatu
CVPixelBuffer
w celu przetworzenia, zanim zostaną wysłane do wzorca do wykrywania obiektów w trybie transmisji na żywo.
Swift
// Obtain a CVPixelBuffer. // Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the default // orientation `UIImage.Orientation.up`. let image = try MPImage(pixelBuffer: pixelBuffer)
Objective-C
// Obtain a CVPixelBuffer. // Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the // default orientation `UIImageOrientationUp`. MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
Więcej informacji na temat CVPixelBuffer
znajdziesz w dokumentacji dla programistów Apple CVPixelBuffer.
CMSampleBuffer
Format CMSampleBuffer
przechowuje próbki multimediów jednolitego typu i dobrze sprawdza się w trybie transmisji na żywo. Klatki na żywo z kamer na iOS są przesyłane asynchronicznie w formacie CMSampleBuffer
przez system iOS AVCaptureVideoDataOutput.
Swift
// Obtain a CMSampleBuffer. // Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the default // orientation `UIImage.Orientation.up`. let image = try MPImage(sampleBuffer: sampleBuffer)
Objective-C
// Obtain a `CMSampleBuffer`. // Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the // default orientation `UIImageOrientationUp`. MPImage *image = [[MPPImage alloc] initWithSampleBuffer:sampleBuffer error:nil];
Więcej informacji na temat CMSampleBuffer
znajdziesz w dokumentacji dla programistów Apple CMSampleBuffer.
Uruchamianie zadania
Aby uruchomić wykrywanie obiektów, użyj metody detect()
odpowiedniej dla przypisanego trybu uruchamiania:
- Nieruchomy obraz:
detect(image:)
- Film:
detect(videoFrame:timestampInMilliseconds:)
- transmisja na żywo:
detectAsync(image:)
Poniższe przykłady kodu pokazują podstawowe przykłady uruchamiania wykrywania obiektów w różnych trybach działania:
Swift
Obraz
let objectDetector.detect(image:image)
Wideo
let objectDetector.detect(videoFrame:image)
transmisja na żywo
let objectDetector.detectAsync(image:image)
Objective-C
Obraz
MPPObjectDetectorResult *result = [objectDetector detectInImage:image error:nil];
Wideo
MPPObjectDetectorResult *result = [objectDetector detectInVideoFrame:image timestampInMilliseconds:timestamp error:nil];
transmisja na żywo
BOOL success = [objectDetector detectAsyncInImage:image timestampInMilliseconds:timestamp error:nil];
W przykładowym kodzie wykrywania obiektów znajdziesz bardziej szczegółowe implementacje każdego z tych trybów: detect(image:)
, detect(videoFrame:)
i detectAsync(image:)
. Przykładowy kod pozwala użytkownikowi przełączać się między trybami przetwarzania, które mogą nie być wymagane w Twoim przypadku użycia.
Uwaga:
W trybie wideo lub transmisji na żywo musisz też do zadania wykrywania obiektów podać sygnaturę czasową ramki wejściowej.
W trybie obrazu lub filmu zadanie wykrywania obiektów blokuje bieżący wątek do momentu zakończenia przetwarzania obrazu lub klatki wejściowej. Aby uniknąć zablokowania bieżącego wątku, wykonaj przetwarzanie w wątku w tle za pomocą platform Dispatch lub NSOperation w systemie iOS.
W trybie transmisji na żywo zadanie wykrywania obiektów jest natychmiast zwracane i nie blokuje bieżącego wątku. Po przetworzeniu każdej ramki wejściowej wywołuje metodę
objectDetector(_objectDetector:didFinishDetection:timestampInMilliseconds:error:)
z wynikiem wykrywania. Detektor obiektów wywołuje tę metodę asynchronicznie w dedykowanej szeregowej kolejce wysyłki. W przypadku wyświetlania wyników w interfejsie po ich przetworzeniu wysyłaj do głównej kolejki. Jeśli funkcjadetectAsync
zostanie wywołana, gdy zadanie wykrywania obiektów jest zajęte przetwarzaniem innej ramki, detektor obiektów ignoruje nową ramkę wejściową.
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świetlić wyniki wykrywania zwrócone z zadania. Szczegółowe informacje znajdziesz w przykładowym kodzie.