Zadanie MediaPipe Image Embedder umożliwia konwertowanie danych obrazu na postać liczbową, aby wykonywać zadania związane z przetwarzaniem obrazu za pomocą uczenia maszynowego, takie jak porównywanie podobieństwa 2 obrazów.
Przykładowy kod opisany w tych instrukcjach jest dostępny na GitHubzie. Aby zobaczyć, jak to zadanie działa w praktyce, obejrzyj to demo. 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 Image Embedder na iOS. W przykładzie do ciągłego umieszczania obrazów używana jest kamera na fizycznym urządzeniu z iOS. Można też uruchomić narzędzie do umieszczania w pliku z obrazami z galerii urządzenia.
Możesz użyć tej aplikacji jako punktu wyjścia do tworzenia własnej aplikacji na iOS lub skorzystać z niej podczas modyfikowania istniejącej aplikacji. Przykładowy kod Image Embedder jest hostowany na GitHub.
Pobieranie kodu
Z tych instrukcji 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, aby używać rzadkiego sprawdzania, dzięki czemu będziesz mieć tylko pliki przykładowej aplikacji Image Embedder:
cd mediapipe git sparse-checkout init --cone git sparse-checkout set examples/image_embedder/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 konfiguracji dla iOS.
Kluczowe komponenty
Te pliki zawierają kluczowy kod aplikacji przykładowej Image Embedder:
- ImageEmbedderService.swift: inicjuje komponent do umieszczania obrazów, obsługuje wybór modelu i uruchamia wnioskowanie na danych wejściowych.
- CameraViewController.swift: implementuje interfejs użytkownika w trybie wejścia z obrazu na żywo z kamery i wizualizuje wyniki.
- MediaLibraryViewController.swift implementuje interfejs użytkownika dla trybu wprowadzania statycznych obrazów i wizualizuje wyniki.
Konfiguracja
W tej sekcji znajdziesz najważniejsze czynności, które musisz wykonać, aby skonfigurować środowisko programistyczne i projekty kodu pod kątem korzystania z narzędzia do umieszczania obrazów. Ogólne informacje o konfigurowaniu środowiska programistycznego do korzystania z zadań MediaPipe, w tym wymagania dotyczące wersji platformy, znajdziesz w przewodniku konfiguracji dla iOS.
Zależności
Image Embedder korzysta z biblioteki MediaPipeTasksVision
, którą trzeba zainstalować za pomocą CocoaPods. Biblioteka jest zgodna z aplikacją w języku Swift i Objective-C i nie wymaga dodatkowej konfiguracji językowej.
Instrukcje instalacji CocoaPods na macOS znajdziesz w przewodniku instalacji CocoaPods.
Instrukcje tworzenia Podfile
z podstawowymi komponentami potrzebnymi do działania aplikacji znajdziesz w artykule Korzystanie z CocoaPods.
Dodaj blok MediaPipeTasksVision
w Podfile
za pomocą tego kodu:
target 'MyImageEmbedderApp' do
use_frameworks!
pod 'MediaPipeTasksVision'
end
Jeśli Twoja aplikacja zawiera cele testów jednostkowych, dodatkowe informacje o konfigurowaniu Podfile
znajdziesz w przewodniku konfiguracji na iOS.
Model
Zadanie MediaPipe Image Embedder wymaga wytrenowanego modelu, który jest zgodny z tym zadaniem. Więcej informacji o dostępnych wytrenowanych modelach Image Embedder znajdziesz w sekcji Modele.
Wybierz i pobierz model, a potem dodaj go do katalogu projektu za pomocą Xcode. Instrukcje dodawania plików do projektu Xcode znajdziesz w artykule Zarządzanie plikami i folderami w projekcie Xcode.
Użyj właściwości BaseOptions.modelAssetPath
, aby określić ścieżkę do modelu w pakiecie aplikacji.
Tworzenie zadania
Zadanie Wstawianie obrazu możesz utworzyć, wywołując jedną z jego funkcji inicjującej. Inicjalizator ImageEmbedder(options:)
może przyjmować wartości opcji konfiguracji.
Jeśli nie potrzebujesz modułu Image Embedder zainicjowanego za pomocą niestandardowych opcji konfiguracji, możesz użyć modyfikatora ImageEmbedder(modelPath:)
, aby utworzyć moduł Image Embedder z opcjami domyślnymi. Więcej informacji o opcjach konfiguracji znajdziesz w artykule Omówienie konfiguracji.
Zadanie Wstawianie obrazów obsługuje 3 typy danych wejściowych: obrazy, pliki wideo i strumienie wideo na żywo. Domyślnie ImageEmbedder(modelPath:)
inicjuje zadanie dotyczące obrazów statycznych. Jeśli chcesz, aby zadanie zostało zainicjowane w celu przetwarzania plików wideo lub transmisji na żywo, użyj parametru ImageEmbedder(options:)
, aby określić tryb działania związany z odtwarzaniem filmów lub transmisji na żywo. Tryb transmisji na żywo wymaga też dodatkowej opcji konfiguracji imageEmbedderLiveStreamDelegate
, która umożliwia dodatkowi Image Embedder dostarczanie wyników umieszczania obrazów do delegowanego elementu asynchronicznie.
Aby dowiedzieć się, jak utworzyć zadanie i przeprowadzić wnioskowanie, wybierz kartę odpowiadającą trybowi działania.
Swift
Obraz
import MediaPipeTasksVision let modelPath = Bundle.main.path( forResource: "model", ofType: "tflite") let options = ImageEmbedderOptions() options.baseOptions.modelAssetPath = modelPath options.quantize = true options.l2Normalize = true let imageEmbedder = try ImageEmbedder(options: options)
Wideo
import MediaPipeTasksVision let modelPath = Bundle.main.path( forResource: "model", ofType: "tflite") let options = ImageEmbedderOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .video options.quantize = true options.l2Normalize = true let imageEmbedder = try ImageEmbedder(options: options)
Transmisja na żywo
import MediaPipeTasksVision // Class that conforms to the `ImageEmbedderLiveStreamDelegate` protocol and // implements the method that the image embedder calls once it finishes // embedding each input frame. class ImageEmbedderResultProcessor: NSObject, ImageEmbedderLiveStreamDelegate { func imageEmbedder( _ imageEmbedder: ImageEmbedder, didFinishEmbedding result: ImageEmbedderResult?, timestampInMilliseconds: Int, error: Error?) { // Process the image embedder result or errors here. } } let modelPath = Bundle.main.path( forResource: "model", ofType: "tflite") let options = ImageEmbedderOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .liveStream options.quantize = true options.l2Normalize = true // Assign an object of the class to the `imageEmbedderLiveStreamDelegate` // property. let processor = ImageEmbedderResultProcessor() options.imageEmbedderLiveStreamDelegate = processor let imageEmbedder = try ImageEmbedder(options: options)
Objective-C
Obraz
@import MediaPipeTasksVision; NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model" ofType:@"tflite"]; MPPImageEmbedderOptions *options = [[MPPImageEmbedderOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeImage; options.quantize = YES; options.l2Normalize = YES; MPPImageEmbedder *imageEmbedder = [[MPPImageEmbedder alloc] initWithOptions:options error:nil];
Wideo
@import MediaPipeTasksVision; NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model" ofType:@"tflite"]; MPPImageEmbedderOptions *options = [[MPPImageEmbedderOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeVideo; options.quantize = YES; options.l2Normalize = YES; MPPImageEmbedder *imageEmbedder = [[MPPImageEmbedder alloc] initWithOptions:options error:nil];
Transmisja na żywo
@import MediaPipeTasksVision; // Class that conforms to the `MPPImageEmbedderLiveStreamDelegate` protocol // and implements the method that the image embedder calls once it finishes // embedding each input frame. @interface APPImageEmbedderResultProcessor : NSObject@end @implementation APPImageEmbedderResultProcessor - (void)imageEmbedder:(MPPImageEmbedder *)imageEmbedder didFinishEmbeddingWithResult:(MPPImageEmbedderResult *)imageEmbedderResult timestampInMilliseconds:(NSInteger)timestampInMilliseconds error:(NSError *)error { // Process the image embedder result or errors here. } @end NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model" ofType:@"tflite"]; MPPImageEmbedderOptions *options = [[MPPImageEmbedderOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeLiveStream; options.quantize = YES; options.l2Normalize = YES; // Assign an object of the class to the `imageEmbedderLiveStreamDelegate` // property. APPImageEmbedderResultProcessor *processor = [APPImageEmbedderResultProcessor new]; options.imageEmbedderLiveStreamDelegate = processor; MPPImageEmbedder *imageEmbedder = [[MPPImageEmbedder alloc] initWithOptions:options error:nil];
Opcje konfiguracji
W tym zadaniu dostępne są te opcje konfiguracji aplikacji na iOS:
Nazwa opcji | Opis | Zakres wartości | Wartość domyślna |
---|---|---|---|
runningMode |
Ustawia tryb działania zadania. Narzędzie do wklejania obrazów ma 3 tryby: OBRAZ: tryb do wklejania pojedynczych obrazów. WIDEO: tryb zdekodowanych klatek w filmie. LIVE_STREAM: tryb transmisji na żywo danych wejściowych, np. z kamery. W tym trybie parametr imageEmbedderLiveStreamDelegate musi być ustawiony na instancję klasy implementującej interfejs ImageEmbedderLiveStreamDelegate , aby asynchronicznie otrzymywać wyniki wstawiania ramek obrazu.
|
{RunningMode.image, RunningMode.video, RunningMode.liveStream} | {RunningMode.image} |
l2Normalize |
Określa, czy zwrócony wektor cech ma być znormalizowany za pomocą normy L2. Użyj tej opcji tylko wtedy, gdy model nie zawiera natywnego operatora L2_NORMALIZATION TFLite. W większości przypadków tak jest, więc normalizację L2 można osiągnąć dzięki wnioskowaniu TFLite bez konieczności korzystania z tej opcji. | Wartość logiczna | fałsz |
quantize |
Określa, czy zwrócony wektor dystrybucyjny ma być zaokrąglony do bajtów za pomocą kwantyzacji skalarnej. Zakłada się, że wektory mają długość 1, a dlatego każdy wymiar ma wartość z zakresu [-1,0, 1,0]. W przeciwnym razie użyj opcji l2Normalize. | Wartość logiczna | fałsz |
Gdy tryb działania jest ustawiony na transmisję na żywo, moduł do umieszczania obrazów wymaga dodatkowej opcji konfiguracji imageEmbedderLiveStreamDelegate
, która umożliwia asynchroniczne dostarczanie wyników umieszczania obrazów. Delegat musi implementować metodę imageEmbedder(_:didFinishEmbedding:timestampInMilliseconds:error:)
, którą Image Embedder wywołuje po przetworzeniu wyników umieszczania każdego kadru obrazu wejściowego.
Nazwa opcji | Opis | Zakres wartości | Wartość domyślna |
---|---|---|---|
imageEmbedderLiveStreamDelegate |
Umożliwia wtyczce Image Embedder asynchroniczne otrzymywanie wyników umieszczania obrazów w trybie transmisji na żywo. Klasa, której instancja jest ustawiona w tej właściwości, musi implementować metodę imageEmbedder(_:didFinishEmbedding:timestampInMilliseconds:error:) . |
Nie dotyczy | Nie ustawiono |
Przygotuj dane
Musisz przekonwertować obraz lub ramkę wejściową na obiekt MPImage
, zanim przekażesz go do narzędzia do dodawania obrazów. MPImage
obsługuje różne typy formatów obrazów iOS i może używać ich w dowolnym trybie działania w celu wnioskowania. Więcej informacji o MPImage
znajdziesz w dokumentacji interfejsu MPImage API.
Wybierz format obrazu iOS na podstawie przypadku użycia i trybułu działania wymaganego przez aplikację. MPImage
obsługuje formaty obrazów iOS UIImage
, CVPixelBuffer
i CMSampleBuffer
.
UIImage
Format UIImage
jest odpowiedni do tych trybów działania:
Obrazy: obrazy z pakietu aplikacji, galerii użytkownika lub systemu plików sformatowane jako obrazy
UIImage
można przekształcić w obiektMPImage
.Filmy: za pomocą narzędzia AVAssetImageGenerator wyodrębnij klatki wideo do formatu CGImage, a potem przekonwertuj je na
UIImage
obrazy.
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];
Ten przykład inicjuje obiekt MPImage
z domyślną orientacją UIImage.Orientation.Up. Możesz zainicjować MPImage
dowolną z obsługiwanych wartości UIImage.Orientation. Narzędzie do umieszczania obrazów nie obsługuje orientacji lustrzanej, takiej jak .upMirrored
, .downMirrored
, .leftMirrored
, .rightMirrored
.
Więcej informacji o UIImage
znajdziesz w dokumentacji UIImage dla deweloperów Apple.
CVPixelBuffer
Format CVPixelBuffer
sprawdza się w aplikacjach, które generują ramki i wykorzystują do przetwarzania platformę CoreImage na iOS.
Format CVPixelBuffer
jest odpowiedni do tych trybów działania:
Obrazy: aplikacje, które generują obrazy
CVPixelBuffer
po przetworzeniu ich za pomocą interfejsuCoreImage
w iOS, mogą wysyłać je do Image Embedder w trybie uruchamiania obrazu.Filmy: ramki wideo można przekonwertować do formatu
CVPixelBuffer
na potrzeby przetwarzania, a następnie wysłać do modułu Image Embedder w trybie wideo.transmisja na żywo: aplikacje korzystające z kamery iOS do generowania klatek mogą zostać przekonwertowane do formatu
CVPixelBuffer
w celu przetwarzania, zanim zostaną wysłane do modułu wstawiania obrazó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 o CVPixelBuffer
znajdziesz w dokumentacji dla deweloperów Apple dotyczącej CVPixelBuffer.
CMSampleBuffer
Format CMSampleBuffer
przechowuje próbki multimediów w ramach jednolitego typu multimediów i sprawdza się w trybie biegu transmisji na żywo. Klatki na żywo z kamer z iOS są asynchronicznie dostarczane w formacie CMSampleBuffer
przez AVCaptureVideoDataOutput w systemie iOS.
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 o właściwości CMSampleBuffer
znajdziesz w dokumentacji dla programistów Apple CMSampleBuffer.
Uruchamianie zadania
Aby uruchomić mechanizm umieszczania obrazów, użyj metody embed()
specyficznej dla przypisanego trybu uruchamiania:
- Statyczny obraz:
embed(image:)
- Film:
embed(videoFrame:timestampInMilliseconds:)
- Transmisja na żywo:
embedAsync(image:timestampInMilliseconds:)
Poniżej znajdziesz przykładowy kod pokazujący, jak uruchomić narzędzie do dodawania obrazów w różnych trybach działania:
Swift
Obraz
let result = try imageEmbedder.embed(image: image)
Wideo
let result = try imageEmbedder.embed( videoFrame: image, timestampInMilliseconds: timestamp)
Transmisja na żywo
try imageEmbedder.embedAsync( image: image, timestampInMilliseconds: timestamp)
Objective-C
Obraz
MPPImageEmbedderResult *result = [imageEmbedder embedImage:image error:nil];
Wideo
MPPImageEmbedderResult *result = [imageEmbedder embedVideoFrame:image timestampInMilliseconds:timestamp error:nil];
Transmisja na żywo
BOOL success = [imageEmbedder embedAsyncImage:image timestampInMilliseconds:timestamp error:nil];
Przykładowy kod Image Embedder pokazuje szczegółowo implementację każdego z tych trybów: embed(image:)
, embed(videoFrame:timestampInMilliseconds:)
i embedAsync(image:timestampInMilliseconds:)
. Przykładowy kod pozwala użytkownikowi przełączać się między trybami przetwarzania, co może nie być wymagane w Twoim przypadku użycia.
Pamiętaj:
W trybie wideo lub transmisji na żywo musisz też podać zadaniu Image Embedder sygnaturę czasową ramki wejściowej.
Gdy działa w trybie obrazu lub filmu, zadanie osadzania obrazu blokuje bieżący wątek, dopóki nie przetworzy podawanego obrazu lub kadru. Aby uniknąć zablokowania bieżącego wątku, wykonaj przetwarzanie w wątku w tle za pomocą struktur systemu iOS Dispatch lub NSOperation. Jeśli aplikacja została utworzona w Swift, możesz też użyć makro Swifta dotyczącym współbieżności do wykonywania wątków w tle.
W trybie transmisji na żywo zadanie Image Embedder zwraca wynik natychmiast i nie blokuje bieżącego wątku. Wywołuje metodę
imageEmbedder(_:didFinishEmbedding:timestampInMilliseconds:error:)
z wynikami po umieszczeniu każdej ramki wejściowej. Wstawiacz obrazu wywołuje tę metodę asynchronicznie w dedykowanej kolejce wysyłania sekwencyjnego. Aby wyświetlać wyniki w interfejsie, po przetworzeniu wyników prześlij je do kolejki głównej. Jeśli funkcjaembedAsync
jest wywoływana, gdy zadanie Image Embedder jest zajęte przetwarzaniem innego kadru, zadanie Image Embedder zignoruje nowy klatka wejściowa.
Obsługa i wyświetlanie wyników
Po przeprowadzeniu wnioskowania Image Embedder zwraca obiekt ImageEmbedderResult
, który zawiera listę elementów zaimplementowanych (zmiennych typu float lub skali kwantyzowanej) 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 został uzyskany dzięki umieszczeniu tego obrazu:
Za pomocą funkcji ImageEmbedder.cosineSimilarity
możesz porównać podobieństwo 2 wkładników.
Swift
let similarity = try ImageEmbedder.cosineSimilarity( embedding1: result.embeddingResult.embeddings[0], embedding2: otherResult.embeddingResult.embeddings[0])
Objective-C
NSNumber *similarity = [MPPImageEmbedder cosineSimilarityBetweenEmbedding1:result.embeddingResult.embeddings[0] andEmbedding2:otherResult.embeddingResult.embeddings[0] error:nil];