Sie können ML Kit verwenden, um Objekte über Videoframes hinweg zu erkennen und zu 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. Beim Erkennen von Objekten in Videostreams hat jedes Objekt eine ID, mit der Sie das Objekt über Bilder hinweg verfolgen können. Sie können optional auch die grobe Objektklassifizierung aktivieren, die Objekte mit breiten Kategoriebeschreibungen kennzeichnet.
Bevor Sie beginnen
- Wenn Sie Ihrer App Firebase noch nicht hinzugefügt haben, befolgen Sie dazu die Schritte im Leitfaden „Erste Schritte“ .
- Schließen Sie die ML Kit-Bibliotheken in Ihre Poddatei ein:
pod 'Firebase/MLVision', '6.25.0' pod 'Firebase/MLVisionObjectDetection', '6.25.0'
Nachdem Sie die Pods Ihres Projekts installiert oder aktualisiert haben, müssen Sie Ihr Xcode-Projekt mit seiner.xcworkspace
. - Importieren Sie in Ihrer App Firebase:
Schnell
import Firebase
Ziel c
@import Firebase;
1. Konfigurieren Sie den Objektdetektor
Um mit dem Erkennen und Verfolgen von Objekten zu beginnen, erstellen Sie zunächst eine Instanz von VisionObjectDetector
, und geben Sie optional alle Detektoreinstellungen an, die Sie von der Standardeinstellung ändern möchten.
Konfigurieren Sie den Objektdetektor für Ihren Anwendungsfall mit einem
VisionObjectDetectorOptions
Objekt. Sie können die folgenden Einstellungen ändern:Objektdetektor-Einstellungen Erkennungsmodus .stream
(Standard) |.singleImage
Im Stream-Modus (Standard) wird der Objektdetektor mit sehr geringer Latenz ausgeführt, kann jedoch bei den ersten Aufrufen des Detektors unvollständige Ergebnisse (z. B. nicht angegebene Begrenzungsrahmen oder Kategorien) liefern. Außerdem weist der Detektor im Stream-Modus Objekten Tracking-IDs zu, die Sie verwenden können, um Objekte über Frames hinweg zu verfolgen. Verwenden Sie diesen Modus, wenn Sie Objekte verfolgen möchten oder wenn eine niedrige Latenz wichtig ist, z. B. bei der Verarbeitung von Videostreams in Echtzeit.
Im Einzelbildmodus wartet der Objektdetektor, bis der Begrenzungsrahmen eines erkannten Objekts und (falls Sie die Klassifizierung aktiviert haben) die Kategorie verfügbar sind, bevor er ein Ergebnis zurückgibt. Folglich 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 nicht mit Teilergebnissen arbeiten möchten.
Erkennen und verfolgen Sie mehrere Objekte false
(Standard) |true
Ob bis zu fünf Objekte oder nur das auffälligste Objekt (Standard) erkannt und verfolgt werden sollen.
Objekte klassifizieren false
(Standard) |true
Ob erkannte Objekte in grobe Kategorien eingeteilt werden sollen oder nicht. Wenn aktiviert, klassifiziert der Objektdetektor Objekte in die folgenden Kategorien: Modewaren, Lebensmittel, Haushaltswaren, Orte, Pflanzen und Unbekannt.
Die Objekterkennungs- und Tracking-API 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
Rufen Sie 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 Videoeinzelbild 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 Eigenschaft
imageOrientation
.up
. - 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 eine
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 Eigenschaft
Übergeben Sie das
VisionImage
an eine der Bildverarbeitungsmethoden des Objektdetektors. Sie können entweder die asynchroneprocess(image:)
Methode oder die synchroneresults()
Methode 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. // ... }];
Objekte synchron erkennen:
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 Abschlusshandler oder gibt die Liste zurück, je nachdem, ob Sie die asynchrone oder die synchrone Methode aufgerufen haben.Jedes
VisionObject
enthält die folgenden Eigenschaften:frame
Ein CGRect
, der die Position des Objekts im Bild angibt.trackingID
Eine ganze Zahl, die das Objekt bildübergreifend identifiziert. Null im Einzelbildmodus. classificationCategory
Die grobe Kategorie des Objekts. Wenn der Objektdetektor keine Klassifizierung aktiviert hat, ist dies immer .unknown
.confidence
Der Konfidenzwert der Objektklassifikation. Wenn der Objektdetektor keine Klassifizierung aktiviert hat 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
Befolgen Sie für die beste Benutzererfahrung 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 zu erkennenden Bildes einnehmen. Sie sollten den Benutzern Anleitungen zum Erfassen von Eingaben geben, die gut mit der Art von Objekten funktionieren, die Sie erkennen möchten.
- Wenn Sie bei Verwendung der Klassifizierung Objekte erkennen möchten, die nicht eindeutig in die unterstützten Kategorien fallen, implementieren Sie eine spezielle Behandlung für unbekannte Objekte.
Sehen Sie sich auch die [ML Kit Material Design Showcase App][showcase-link]{: .external } und die Material Design Patterns for Machine Learning-gestützte Funktionssammlung 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 keine Mehrfachobjekterkennung, da die meisten Geräte keine angemessenen Frameraten erzeugen können.
Deaktivieren Sie die Klassifizierung, wenn Sie sie nicht benötigen.
- Drosselrufe an den Detektor. Wenn ein neuer Videoframe verfügbar wird, während der Detektor läuft, löschen Sie den Frame.
- Wenn Sie die Ausgabe des Detektors verwenden, um Grafiken auf das Eingabebild zu legen, rufen Sie zuerst das Ergebnis von ML Kit ab, rendern Sie dann das Bild und überlagern Sie es in einem einzigen Schritt. Dadurch rendern Sie für jeden Eingabeframe nur einmal auf der Anzeigeoberfläche. Ein Beispiel finden Sie in den Klassen previewOverlayView und FIRDetectionOverlayView in der Showcase-Beispiel-App.