Za pomocą ML Kit możesz wykrywać i śledzić obiekty w klatkach wideo.
Gdy prześlesz obrazy ML Kit, ML Kit zwróci dla każdego obrazu listę maksymalnie 5 wykrytych obiektów i ich położenie na zdjęciu. Podczas wykrywania obiektów w strumieniach wideo, każdy z nich ma identyfikator, który pozwala śledzić obiekt na obrazach. Możesz też opcjonalnie włączyć obiekt przybliżony klasyfikację, która oznacza etykietami obiekty o szerokim opisie kategorii.
Zanim zaczniesz
- Jeśli nie masz jeszcze w aplikacji dodanej Firebase, wykonaj czynności podane w przewodniku dla początkujących.
- Umieść biblioteki ML Kit w pliku Podfile:
pod 'Firebase/MLVision', '6.25.0' pod 'Firebase/MLVisionObjectDetection', '6.25.0'
Po zainstalowaniu lub zaktualizowaniu podów projektu otwórz Xcode projektu za pomocą jego.xcworkspace
. - W aplikacji zaimportuj Firebase:
Swift
import Firebase
Objective-C
@import Firebase;
1. Konfigurowanie detektora obiektów
Aby rozpocząć wykrywanie i śledzenie obiektów, najpierw utwórz instancję
VisionObjectDetector
, opcjonalnie określając wszelkie ustawienia detektora, które chcesz
niż domyślna.
Skonfiguruj detektor obiektów na potrzeby swojego przypadku użycia za pomocą
VisionObjectDetectorOptions
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) ramek ograniczających lub kategorii) 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 czeka, aż ramki ograniczającej obiektu i kategorię (jeśli masz włączoną klasyfikację) są dostępne przed zwróceniem wyniku. W związku z tym opóźnienie wykrywania jest potencjalnie większe. Także na jednym obrazie identyfikatorów śledzenia nie są przypisywane. Użyj tego trybu w przypadku opóźnień jest kluczowe i nie chcesz mieć do czynienia z częściowymi wyników.
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: moda, żywność, AGD, miejsc, roślin i nieznanych miejsc.
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 = VisionObjectDetectorOptions() options.detectorMode = .stream options.shouldEnableMultipleObjects = false options.shouldEnableClassification = true // Optional // Multiple object detection in static images let options = VisionObjectDetectorOptions() options.detectorMode = .singleImage options.shouldEnableMultipleObjects = true options.shouldEnableClassification = true // Optional
Objective-C
// Live detection and tracking FIRVisionObjectDetectorOptions *options = [[FIRVisionObjectDetectorOptions alloc] init]; options.detectorMode = FIRVisionObjectDetectorModeStream; options.shouldEnableMultipleObjects = NO; options.shouldEnableClassification = YES; // Optional // Multiple object detection in static images FIRVisionObjectDetectorOptions *options = [[FIRVisionObjectDetectorOptions alloc] init]; options.detectorMode = FIRVisionObjectDetectorModeSingleImage; options.shouldEnableMultipleObjects = YES; options.shouldEnableClassification = YES; // Optional
Pobierz instancję
FirebaseVisionObjectDetector
:Swift
let objectDetector = Vision.vision().objectDetector() // Or, to change the default settings: let objectDetector = Vision.vision().objectDetector(options: options)
Objective-C
FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetector]; // Or, to change the default settings: FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetectorWithOptions:options];
2. Uruchom detektor obiektów
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
CMSampleBufferRef
.
Utwórz obiekt
VisionImage
za pomocąUIImage
lubCMSampleBufferRef
.Aby użyć karty
UIImage
:- W razie potrzeby obróć zdjęcie, tak by jego
imageOrientation
właściwość to.up
. - Utwórz obiekt
VisionImage
przy użyciu prawidłowo wykonanej rotacjiUIImage
Nie określaj żadnych metadanych rotacji – są to metadane domyślne..topLeft
.Swift
let image = VisionImage(image: uiImage)
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
Aby użyć karty
CMSampleBufferRef
:-
Utwórz obiekt
VisionImageMetadata
, który określa orientacji danych zdjęć zawartych w BuforCMSampleBufferRef
.Aby sprawdzić orientację obrazu:
Swift
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> VisionDetectorImageOrientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftTop : .rightTop case .landscapeLeft: return cameraPosition == .front ? .bottomLeft : .topLeft case .portraitUpsideDown: return cameraPosition == .front ? .rightBottom : .leftBottom case .landscapeRight: return cameraPosition == .front ? .topRight : .bottomRight case .faceDown, .faceUp, .unknown: return .leftTop } }
Objective-C
- (FIRVisionDetectorImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationLeftTop; } else { return FIRVisionDetectorImageOrientationRightTop; } case UIDeviceOrientationLandscapeLeft: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationBottomLeft; } else { return FIRVisionDetectorImageOrientationTopLeft; } case UIDeviceOrientationPortraitUpsideDown: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationRightBottom; } else { return FIRVisionDetectorImageOrientationLeftBottom; } case UIDeviceOrientationLandscapeRight: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationTopRight; } else { return FIRVisionDetectorImageOrientationBottomRight; } default: return FIRVisionDetectorImageOrientationTopLeft; } }
Następnie utwórz obiekt metadanych:
Swift
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
Objective-C
FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init]; AVCaptureDevicePosition cameraPosition = AVCaptureDevicePositionBack; // Set to the capture device you used. metadata.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
- Utwórz obiekt
VisionImage
za pomocą ObiektCMSampleBufferRef
i metadane rotacji:Swift
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- W razie potrzeby obróć zdjęcie, tak by jego
Przekaż
VisionImage
do jednego z procesów przetwarzania obrazu detektora obiektów . Możesz użyć asynchronicznej metodyprocess(image:)
lub synchroniczną metodęresults()
.Aby asynchronicznie wykrywać obiekty:
Swift
objectDetector.process(image) { detectedObjects, error in guard error == nil else { // Error. return } guard let detectedObjects = detectedObjects, !detectedObjects.isEmpty else { // No objects detected. return } // Success. Get object info here. // ... }
Objective-C
[objectDetector processImage:image completion:^(NSArray<FIRVisionObject *> * _Nullable objects, NSError * _Nullable error) { if (error == nil) { return; } if (objects == nil | objects.count == 0) { // No objects detected. return; } // Success. Get object info here. // ... }];
Aby synchronicznie wykrywać obiekty:
Swift
var results: [VisionObject]? = nil do { results = try objectDetector.results(in: image) } catch let error { print("Failed to detect object with error: \(error.localizedDescription).") return } guard let detectedObjects = results, !detectedObjects.isEmpty else { print("Object detector returned no results.") return } // ...
Objective-C
NSError *error; NSArray<FIRVisionObject *> *objects = [objectDetector resultsInImage:image error:&error]; if (error == nil) { return; } if (objects == nil | objects.count == 0) { // No objects detected. return; } // Success. Get object info here. // ...
Jeśli wywołanie procesora zdjęć się powiedzie, przekazywana jest lista
VisionObject
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
VisionObject
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. Nil w singlu trybu obrazu. classificationCategory
Przybliżona kategoria obiektu. Jeśli detektor obiektów nie mają włączoną klasyfikację, zawsze to .unknown
.confidence
Wartość ufności klasyfikacji obiektu. Jeśli obiekt detektor nie ma włączonej klasyfikacji lub obiekt jest sklasyfikowane jako nieznane, to nil
.Swift
// detectedObjects contains one item if multiple object detection wasn't enabled. for obj in detectedObjects { let bounds = obj.frame let id = obj.trackingID // If classification was enabled: let category = obj.classificationCategory let confidence = obj.confidence }
Objective-C
// The list of detected objects contains one item if multiple // object detection wasn't enabled. for (FIRVisionObject *obj in objects) { CGRect bounds = obj.frame; if (obj.trackingID) { NSInteger id = obj.trackingID.integerValue; } // If classification was enabled: FIRVisionObjectCategory category = obj.classificationCategory; float confidence = obj.confidence.floatValue; }
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. Obiekty z niewielką liczbą funkcji wizualnych mogą zajmować większą część który ma być wykrywany. Należy zapewnić użytkownikom wskazówki dotyczące rejestrowania takich jak dane wejściowe do wykrywania obiektów.
- Jeśli chcesz wykrywać obiekty, które nie wypadają podczas klasyfikacji, do obsługiwanych kategorii, zastosować specjalną obsługę nieznanych obiektów.
Zapoznaj się też z [ML Kit Material Design][showcase-link]{: .external } oraz 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.
- Ogranicz wywołania do detektora. Jeśli nowa klatka wideo dostępnych, gdy detektor jest uruchomiony, upuść ramkę.
- Jeśli używasz 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ą ramkę wejściową. Zobacz previewOverlayView. i FIRDetectionOverlayView w aplikacji z funkcją prezentacji.