Mit dem ML Kit können Sie Objekte über Videobilder hinweg erkennen und verfolgen.
Wenn Sie ML Kit-Bilder übergeben, gibt ML Kit für jedes Bild eine Liste mit bis zu fünf erkannten Objekten und deren Position im Bild zurück. Bei der Erkennung von Objekten in Videostreams verfügt jedes Objekt über eine ID, mit der Sie das Objekt bildübergreifend verfolgen können. Optional können Sie auch die grobe Objektklassifizierung aktivieren, die Objekte mit breiten Kategoriebeschreibungen kennzeichnet.
Bevor Sie beginnen
- Wenn Sie Firebase noch nicht zu Ihrer App hinzugefügt haben, befolgen Sie dazu die Schritte im Leitfaden „Erste Schritte“ .
- Fügen Sie die ML-Kit-Bibliotheken in Ihre Pod-Datei ein:
pod 'Firebase/MLVision', '6.25.0' pod 'Firebase/MLVisionObjectDetection', '6.25.0'
Nachdem Sie die Pods Ihres Projekts installiert oder aktualisiert haben, stellen Sie sicher, dass Sie Ihr Xcode-Projekt mit seinem.xcworkspace
öffnen. - Importieren Sie Firebase in Ihre App:
Schnell
import Firebase
Ziel c
@import Firebase;
1. Konfigurieren Sie den Objektdetektor
Um mit der Erkennung und Verfolgung von Objekten zu beginnen, erstellen Sie zunächst eine Instanz von VisionObjectDetector
und geben Sie optional alle Detektoreinstellungen an, die Sie gegenüber den Standardeinstellungen ändern möchten.
Konfigurieren Sie den Objektdetektor für Ihren Anwendungsfall mit einem
VisionObjectDetectorOptions
Objekt. Sie können die folgenden Einstellungen ändern:Objektdetektoreinstellungen Erkennungsmodus .stream
(Standard) |.singleImage
Im Stream-Modus (Standard) läuft der Objektdetektor mit sehr geringer Latenz, kann jedoch bei den ersten Aufrufen des Detektors unvollständige Ergebnisse liefern (z. B. nicht spezifizierte Begrenzungsrahmen oder Kategorien). Außerdem weist der Detektor im Stream-Modus den Objekten Tracking-IDs zu, mit denen Sie Objekte über Frames hinweg verfolgen können. Verwenden Sie diesen Modus, wenn Sie Objekte verfolgen möchten oder wenn eine geringe Latenz wichtig ist, beispielsweise bei der Verarbeitung von Videostreams in Echtzeit.
Im Einzelbildmodus wartet der Objektdetektor, bis der Begrenzungsrahmen und (sofern Sie die Klassifizierung aktiviert haben) die Kategorie eines erkannten Objekts verfügbar sind, bevor er ein Ergebnis zurückgibt. Infolgedessen ist die Erkennungslatenz möglicherweise höher. Außerdem werden im Einzelbildmodus keine Tracking-IDs zugewiesen. Verwenden Sie diesen Modus, wenn die Latenz nicht kritisch ist und Sie sich nicht mit Teilergebnissen befassen möchten.
Erkennen und verfolgen Sie mehrere Objekte false
(Standard) |true
Ob bis zu fünf Objekte oder nur das auffälligste Objekt erkannt und verfolgt werden sollen (Standard).
Objekte klassifizieren false
(Standard) |true
Ob erkannte Objekte in grobe Kategorien eingeteilt werden sollen oder nicht. Wenn der Objektdetektor aktiviert ist, klassifiziert er Objekte in die folgenden Kategorien: Modeartikel, Lebensmittel, Haushaltswaren, Orte, Pflanzen und Unbekannt.
Die API zur Objekterkennung und -verfolgung ist für diese beiden Kernanwendungsfälle optimiert:
- Live-Erkennung und Verfolgung des markantesten Objekts im Kamerasucher
- Erkennung mehrerer Objekte in einem statischen Bild
So konfigurieren Sie die API für diese Anwendungsfälle:
Schnell
// 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
Ziel 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
Holen Sie sich eine Instanz von
FirebaseVisionObjectDetector
:Schnell
let objectDetector = Vision.vision().objectDetector() // Or, to change the default settings: let objectDetector = Vision.vision().objectDetector(options: options)
Ziel c
FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetector]; // Or, to change the default settings: FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetectorWithOptions:options];
2. Führen Sie den Objektdetektor aus
Um Objekte zu erkennen und zu verfolgen, gehen Sie für jedes Bild oder Videobild wie folgt vor. Wenn Sie den Stream-Modus aktiviert haben, müssen Sie VisionImage
Objekte aus CMSampleBufferRef
s erstellen.
Erstellen Sie ein
VisionImage
Objekt mit einemUIImage
oder einemCMSampleBufferRef
.So verwenden Sie ein
UIImage
:- Drehen Sie das Bild bei Bedarf so, dass seine
imageOrientation
Eigenschaft.up
hat. - Erstellen Sie ein
VisionImage
Objekt mit dem korrekt gedrehtenUIImage
. Geben Sie keine Rotationsmetadaten an – der Standardwert.topLeft
muss verwendet werden.Schnell
let image = VisionImage(image: uiImage)
Ziel c
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
So verwenden Sie ein
CMSampleBufferRef
:Erstellen Sie ein
VisionImageMetadata
Objekt, das die Ausrichtung der imCMSampleBufferRef
Puffer enthaltenen Bilddaten angibt.So erhalten Sie die Bildausrichtung:
Schnell
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 } }
Ziel 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; } }
Erstellen Sie dann das Metadatenobjekt:
Schnell
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
Ziel 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];
- Erstellen Sie ein
VisionImage
Objekt mit demCMSampleBufferRef
-Objekt und den Rotationsmetadaten:Schnell
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Ziel c
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- Drehen Sie das Bild bei Bedarf so, dass seine
Übergeben Sie das
VisionImage
an eine der Bildverarbeitungsmethoden des Objektdetektors. Sie können entweder die asynchrone Methodeprocess(image:)
oder die synchrone Methoderesults()
verwenden.So erkennen Sie Objekte asynchron:
Schnell
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. // ... }
Ziel 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. // ... }];
So erkennen Sie Objekte synchron:
Schnell
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 } // ...
Ziel 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. // ...
Wenn der Aufruf des Bildprozessors erfolgreich ist, übergibt er entweder eine Liste von
VisionObject
s an den Completion-Handler oder gibt die Liste zurück, je nachdem, ob Sie die asynchrone oder synchrone Methode aufgerufen haben.Jedes
VisionObject
enthält die folgenden Eigenschaften:frame
Ein CGRect
, das die Position des Objekts im Bild angibt.trackingID
Eine Ganzzahl, die das Objekt bildübergreifend identifiziert. Nichts im Einzelbildmodus. classificationCategory
Die grobe Kategorie des Objekts. Wenn für den Objektdetektor keine Klassifizierung aktiviert ist, ist dies immer .unknown
.confidence
Der Konfidenzwert der Objektklassifizierung. Wenn für den Objektdetektor keine Klassifizierung aktiviert ist oder das Objekt als unbekannt klassifiziert ist, ist dies nil
.Schnell
// 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 }
Ziel 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; }
Verbesserung der Benutzerfreundlichkeit und Leistung
Um die beste Benutzererfahrung zu erzielen, befolgen Sie diese Richtlinien in Ihrer App:
- Eine erfolgreiche Objekterkennung hängt von der visuellen Komplexität des Objekts ab. Objekte mit wenigen visuellen Merkmalen müssen möglicherweise einen größeren Teil des Bildes einnehmen, um erkannt zu werden. Sie sollten Benutzern Anleitungen zum Erfassen von Eingaben geben, die gut mit der Art von Objekten funktionieren, die Sie erkennen möchten.
- Wenn Sie bei der Klassifizierung Objekte erkennen möchten, die nicht eindeutig in die unterstützten Kategorien fallen, implementieren Sie eine spezielle Behandlung für unbekannte Objekte.
Schauen Sie sich auch die [ML Kit Material Design Showcase-App][showcase-link]{: .external } und die Sammlung von Material Design Patterns für maschinelles Lernen an.
Wenn Sie den Streaming-Modus in einer Echtzeitanwendung verwenden, befolgen Sie diese Richtlinien, um die besten Frameraten zu erzielen:
Verwenden Sie im Streaming-Modus nicht die Erkennung mehrerer Objekte, da die meisten Geräte keine ausreichenden Bildraten erzeugen können.
Deaktivieren Sie die Klassifizierung, wenn Sie sie nicht benötigen.
- Gasrufe an den Detektor. Wenn ein neues Videobild verfügbar wird, während der Detektor läuft, löschen Sie das Bild.
- Wenn Sie die Ausgabe des Detektors verwenden, um Grafiken auf dem Eingabebild zu überlagern, rufen Sie zunächst das Ergebnis vom ML Kit ab und rendern Sie dann das Bild und überlagern Sie es in einem einzigen Schritt. Auf diese Weise rendern Sie für jeden Eingaberahmen nur einmal auf der Anzeigeoberfläche. Ein Beispiel finden Sie in den Klassen „previewOverlayView“ und „FIRDetectionOverlayView“ in der Showcase-Beispiel-App.