Za pomocą ML Kit możesz wykrywać i śledzić obiekty w kolejnych klatkach wideo.
Gdy przekazujesz obraz do ML Kit, wykrywa on maksymalnie 5 obiektów. wraz z położeniem każdego obiektu na obrazie. Podczas wykrywania obiektów w strumieni wideo, każdy obiekt ma unikalny identyfikator, którego możesz użyć do śledzenia od klatki do klatki. Możesz też opcjonalnie włączyć obiekt przybliżony klasyfikację, która oznacza etykietami obiekty o szerokim opisie kategorii.
Wypróbuj
- Wypróbuj przykładową aplikację, aby: zobaczysz przykład użycia tego interfejsu API.
- Zobacz prezentację stylu Material Design , by kompleksowo wdrożyć ten interfejs API.
Zanim zaczniesz
- W pliku Podfile umieść te pody ML Kit:
pod 'GoogleMLKit/ObjectDetection', '3.2.0'
- Po zainstalowaniu lub zaktualizowaniu podów projektu otwórz projekt Xcode za pomocą
.xcworkspace
ML Kit jest obsługiwany w Xcode w wersji 12.4 lub nowszej.
1. Konfigurowanie detektora obiektów
Aby wykrywać i śledzić obiekty, najpierw utwórz instancję
ObjectDetector
i opcjonalnie wybierz ustawienia wzorca do wykrywania treści, które chcesz
niż domyślna.
Skonfiguruj detektor obiektów na potrzeby swojego przypadku użycia za pomocą
ObjectDetectorOptions
obiekt. Możesz zmienić te ustawienia: ustawienia:Ustawienia wykrywania obiektów Tryb wykrywania .stream
(domyślna) |.singleImage
W trybie strumienia (domyślny) detektor obiektów działa z bardzo niską wydajnością czas oczekiwania, ale może dawać niepełne wyniki (np. nieokreślone) ramki ograniczające lub kategorie) na kilku pierwszych wywołaniach wzorca. Ponadto w trybie strumienia detektor przypisuje śledzenie Identyfikatory obiektów, które mogą służyć do śledzenia obiektów w ramkach. Użyj tego trybu, jeśli chcesz śledzić obiekty lub gdy małe opóźnienie ma duże znaczenie, np. podczas przetwarzania strumieni wideo w czasie rzeczywistym, obecnie się znajdujesz.
W trybie pojedynczego obrazu detektor obiektów zwraca wynik. po określeniu ramki ograniczającej obiektu. Jeśli włączysz też klasyfikacja zwraca wynik po ramce ograniczającej i . W związku z tym wykrywanie czas oczekiwania jest potencjalnie większy. Ponadto w trybie pojedynczego obrazu śledzenie Identyfikatory nie są przypisywane. Użyj tego trybu, jeśli czas oczekiwania nie jest krytyczny bo nie chcesz mieć do czynienia z częściowymi wynikami.
Wykrywanie i śledzenie wielu obiektów false
(domyślna) |true
Określa, czy można wykryć i śledzić do pięciu obiektów, czy tylko najbardziej. widoczny obiekt (domyślnie).
Klasyfikowanie obiektów false
(domyślna) |true
Określa, czy należy sklasyfikować wykryte obiekty w przybliżonych kategoriach. Gdy ta opcja jest włączona, detektor obiektów klasyfikuje obiekty w następujące kategorie: artykuły modowe, żywność, artykuły wyposażenia domu, miejsc i roślin.
Interfejs API wykrywania i śledzenia obiektów jest zoptymalizowany pod kątem tych dwóch podstawowych zastosowań przypadki:
- Wykrywanie na żywo i śledzenie najbardziej widocznego obiektu w kamerze wizjer.
- Wykrywanie wielu obiektów na obrazie statycznym.
Aby skonfigurować interfejs API pod kątem tych przypadków użycia:
Swift
// Live detection and tracking let options = ObjectDetectorOptions() options.shouldEnableClassification = true // Multiple object detection in static images let options = ObjectDetectorOptions() options.detectorMode = .singleImage options.shouldEnableMultipleObjects = true options.shouldEnableClassification = true
Objective-C
// Live detection and tracking MLKObjectDetectorOptions *options = [[MLKObjectDetectorOptions alloc] init]; options.shouldEnableClassification = YES; // Multiple object detection in static images MLKObjectDetectorOptions *options = [[MLKOptions alloc] init]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableMultipleObjects = YES; options.shouldEnableClassification = YES;
- Pobierz instancję
ObjectDetector
:
Swift
let objectDetector = ObjectDetector.objectDetector() // Or, to change the default settings: let objectDetector = ObjectDetector.objectDetector(options: options)
Objective-C
MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetector]; // Or, to change the default settings: MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];
2. Przygotowywanie obrazu wejściowego
Aby wykrywać i śledzić obiekty, wykonaj te czynności w przypadku każdego obrazu lub klatki filmu.
Jeśli masz włączony tryb strumieniowania, musisz utworzyć obiekty VisionImage
z
CMSampleBuffer
.
Utwórz obiekt VisionImage
za pomocą UIImage
lub
CMSampleBuffer
.
Jeśli używasz UIImage
, wykonaj te czynności:
- Utwórz obiekt
VisionImage
za pomocąUIImage
. Pamiętaj, by określić prawidłowy.orientation
.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Jeśli używasz CMSampleBuffer
, wykonaj te czynności:
-
Określ orientację danych zdjęć zawartych w pliku
CMSampleBuffer
Aby sprawdzić orientację obrazu:
Swift
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> UIImage.Orientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftMirrored : .right case .landscapeLeft: return cameraPosition == .front ? .downMirrored : .up case .portraitUpsideDown: return cameraPosition == .front ? .rightMirrored : .left case .landscapeRight: return cameraPosition == .front ? .upMirrored : .down case .faceDown, .faceUp, .unknown: return .up } }
Objective-C
- (UIImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored : UIImageOrientationRight; case UIDeviceOrientationLandscapeLeft: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored : UIImageOrientationUp; case UIDeviceOrientationPortraitUpsideDown: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored : UIImageOrientationLeft; case UIDeviceOrientationLandscapeRight: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored : UIImageOrientationDown; case UIDeviceOrientationUnknown: case UIDeviceOrientationFaceUp: case UIDeviceOrientationFaceDown: return UIImageOrientationUp; } }
- Utwórz obiekt
VisionImage
za pomocąCMSampleBuffer
obiekt i orientacja:Swift
let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
Objective-C
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
3. Przetwarzanie zdjęcia
PrzekażVisionImage
do jednego z procesów przetwarzania obrazu detektora obiektów
. Możesz użyć asynchronicznej metody process(image:)
lub
synchroniczną metodę results()
.
Aby asynchronicznie wykrywać obiekty:
Swift
objectDetector.process(image) { objects, error in guard error == nil else { // Error. return } guard !objects.isEmpty else { // No objects detected. return } // Success. Get object info here. // ... }
Objective-C
[objectDetector processImage:image completion:^(NSArray* _Nullable objects, NSError * _Nullable error) { if (error == nil) { return; } if (objects.count == 0) { // No objects detected. return; } // Success. Get object info here. }];
Aby synchronicznie wykrywać obiekty:
Swift
var objects: [Object] do { objects = try objectDetector.results(in: image) } catch let error { print("Failed to detect object with error: \(error.localizedDescription).") return } guard !objects.isEmpty else { print("Object detector returned no results.") return } // Success. Get object info here.
Objective-C
NSError *error; NSArray*objects = [objectDetector resultsInImage:image error:&error]; if (error == nil) { return; } if (objects.count == 0) { // No objects detected. return; } // Success. Get object info here.
4. Uzyskiwanie informacji o wykrytych obiektach
Jeśli wywołanie procesora zdjęć się powiedzie, przekazywana jest listaObject
s do modułu obsługi uzupełniania lub zwraca listę, w zależności od
niezależnie od tego, czy została użyta metoda asynchroniczna czy synchroniczna.
Każdy element Object
zawiera te właściwości:
frame |
CGRect wskazujący położenie obiektu w
. |
trackingID |
Liczba całkowita, która identyfikuje obiekt na obrazach, lub „nil” w w trybie pojedynczego obrazu. |
labels |
Tablica etykiet opisujących obiekt zwrócony przez detektor.
Właściwość jest pusta, jeśli opcja detektora jest pusta
shouldEnableClassification ma wartość false .
|
Swift
// objects contains one item if multiple object detection wasn't enabled. for object in objects { let frame = object.frame let trackingID = object.trackingID // If classification was enabled: let description = object.labels.enumerated().map { (index, label) in "Label \(index): \(label.text), \(label.confidence)" }.joined(separator:"\n") }
Objective-C
// The list of detected objects contains one item if multiple // object detection wasn't enabled. for (MLKObject *object in objects) { CGRect frame = object.frame; NSNumber *trackingID = object.trackingID; for (MLKObjectLabel *label in object.labels) { NSString *labelString = [NSString stringWithFormat: @"%@, %f, %lu", label.text, label.confidence, (unsigned long)label.index]; ... } }
Poprawa łatwości obsługi i wydajności
Aby zadbać o wygodę użytkowników, przestrzegaj tych wytycznych:
- Pomyślne wykrycie obiektu zależy od jego złożoności wizualnej. W są wykrywane, obiekty z niewielką liczbą funkcji wizualnych mogą wymagać aby zająć większą część obrazu. Należy dostarczyć użytkownikom wskazówki na temat tego, przechwytywanie danych wejściowych, które dobrze działają z rodzajami obiektów, które chcesz wykrywać.
- Gdy używasz klasyfikacji, aby wykrywać obiekty, które nie wypadają do obsługiwanych kategorii, zastosować specjalną obsługę nieznanych obiektów.
Zwróć też uwagę na interfejs Material Design, Kolekcja Wzorce funkcji opartych na systemach uczących się.
Jeśli używasz trybu strumieniowania w aplikacji działającej w czasie rzeczywistym, postępuj zgodnie z tymi wskazówkami, aby: aby uzyskać najlepszą liczbę klatek:
- Nie używaj wykrywania wielu obiektów w trybie strumieniowania, ponieważ większość urządzeń którzy są w stanie wygenerować odpowiednią liczbę klatek na sekundę.
- Wyłącz klasyfikację, jeśli jej nie potrzebujesz.
- Do przetwarzania klatek wideo używaj synchronicznego interfejsu API
results(in:)
detektora. Zadzwoń do nas tę metodę zAVCaptureVideoDataOutputSampleBufferDelegate
.captureOutput(_, didOutput:from:)
, aby synchronicznie pobierać wyniki dotyczące danego filmu ramki. ZachowajAVCaptureVideoDataOutput
:alwaysDiscardsLateVideoFrames
jakotrue
, aby ograniczyć wywołania detektora. Jeśli nowy gdy klatka wideo jest dostępna, gdy jest uruchomiony detektor, zostanie usunięta. - Jeśli użyjesz danych wyjściowych detektora do nakładania grafiki na obrazu wejściowego, najpierw pobierz wynik z ML Kit, a następnie wyrenderuj obraz i nakładanie nakładek w jednym kroku. W ten sposób renderowanie na powierzchni tylko raz na każdą przetworzoną ramkę wejściową. Zobacz updatePreviewOverlayViewWithLastFrame. znajdziesz na przykład w krótkim wprowadzeniu do korzystania z ML Kit.