Wenn Sie ein Bild an ML Kit übergeben, werden bis zu fünf Objekte im Bild sowie die Position der einzelnen Objekte im Bild erkannt. Bei der Objekterkennung in Videostreams hat jedes Objekt eine eindeutige ID, mit der Sie das Objekt von Frame zu Frame verfolgen können.
Sie können ein benutzerdefiniertes Bildklassifizierungsmodell verwenden, um die erkannten Objekte zu klassifizieren. Unter Benutzerdefinierte Modelle mit ML Kit finden Sie Informationen zu den Anforderungen an die Modellkompatibilität, zu vortrainierten Modellen und dazu, wie Sie eigene Modelle trainieren.
Es gibt zwei Möglichkeiten, ein benutzerdefiniertes Modell einzubinden. Sie können das Modell bündeln, indem Sie es in den Asset-Ordner Ihrer App einfügen, oder Sie können es dynamisch aus Cloud Storage herunterladen. In der folgenden Tabelle werden die beiden Optionen verglichen.
| Gebündeltes Modell | Gehostetes Modell |
|---|---|
Das Modell ist Teil der .ipa-Datei Ihrer App, wodurch die Größe der Datei zunimmt. |
Das Modell ist nicht Teil der .ipa-Datei Ihrer App. Es wird
gehostet, indem es in Cloud Storage hochgeladen wird. Wir empfehlen die Verwendung von
Cloud Storage for
Firebase. |
| Das Modell ist sofort verfügbar, auch wenn das Android-Gerät offline ist. | Ihre App muss Code enthalten, um das Modell bei Bedarf herunterzuladen. |
| Kein Firebase-Projekt erforderlich | Firebase-Projekt erforderlich (bei Verwendung von Cloud Storage for Firebase) |
| Sie müssen Ihre App noch einmal veröffentlichen, um das Modell zu aktualisieren. | Modellaktualisierungen pushen, ohne die App noch einmal zu veröffentlichen |
| Keine integrierten A/B-Tests | A/B-Tests mit Firebase Remote Config |
Jetzt ausprobieren
- In der Vision-Kurzanleitung finden Sie ein Beispiel für die Verwendung des gebündelten Modells und in der AutoML-Kurzanleitung ein Beispiel für die Verwendung des gehosteten Modells.
- In der Material Design-Showcase App finden Sie eine End-to-End-Implementierung dieser API.
Hinweis
Fügen Sie die ML Kit-Bibliotheken in Ihre Podfile ein:
pod 'GoogleMLKit/ObjectDetectionCustom', '8.0.0'Nachdem Sie die Pods Ihres Projekts installiert oder aktualisiert haben, öffnen Sie Ihr Xcode-Projekt mit der Datei
.xcworkspace. ML Kit wird in Xcode Version 13.2.1 oder höher unterstützt.Wenn Sie ein Modell mit Cloud Storage for Firebase herunterladen möchten, stellen Sie sicher, dass Sie Firebase zu Ihrem iOS-Projekt hinzufügen, falls Sie das noch nicht getan haben. Das ist nicht erforderlich, wenn Sie das Modell bündeln.
1. Modell laden
Lokale Modellquelle konfigurieren
So bündeln Sie das Modell mit Ihrer App:
Kopieren Sie die Modelldatei (endet normalerweise auf
.tfliteoder.lite) in Ihr Xcode-Projekt und wählen Sie dabeiCopy bundle resourcesaus. Die Modelldatei wird in das App-Bundle aufgenommen und ist für ML Kit verfügbar.Erstellen Sie ein
LocalModel-Objekt und geben Sie den Pfad zur Modelldatei an:Swift
let localModel = LocalModel(path: localModelFilePath)
Objective-C
MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithPath:localModelFilePath];
Remote gehostete Modellquelle konfigurieren
Wenn Sie das remote gehostete Modell verwenden möchten, müssen Sie die Modelldatei mit Ihrer eigenen App-Logik in den lokalen Speicher des Geräts herunterladen und sie dann als lokales Modell laden. Wir empfehlen, Cloud Storage for Firebase zum Hosten eines Modells zu verwenden. Implementierungsdetails finden Sie in der Migrationsanleitung von Firebase ML zu Cloud Storage.
2. Objektdetektor konfigurieren
Nachdem Sie Ihre Modellquellen konfiguriert haben, konfigurieren Sie den Objektdetektor für Ihren Anwendungsfall mit einem CustomObjectDetectorOptions-Objekt. Sie können die folgenden Einstellungen ändern:
| Einstellungen für den Objektdetektor | |
|---|---|
| Erkennungsmodus |
STREAM_MODE (Standard) | SINGLE_IMAGE_MODE
In In |
| Mehrere Objekte erkennen und verfolgen |
false (Standard) | true
Gibt an, ob bis zu fünf Objekte oder nur das wichtigste Objekt erkannt und verfolgt werden sollen (Standard). |
| Objekte klassifizieren |
false (Standard) | true
Gibt an, ob erkannte Objekte mit dem bereitgestellten
benutzerdefinierten Klassifikatormodell klassifiziert werden sollen. Wenn Sie Ihr benutzerdefiniertes Klassifizierungs
modell verwenden möchten, müssen Sie diese Option auf |
| Konfidenzwert für die Klassifizierung |
Mindestkonfidenzwert für erkannte Labels. Wenn nicht festgelegt, wird ein beliebiger Klassifikatorschwellenwert verwendet, der in den Metadaten des Modells angegeben ist. Wenn das Modell keine Metadaten enthält oder in den Metadaten kein Klassifikatorschwellenwert angegeben ist, wird ein Standardschwellenwert von 0,0 verwendet. |
| Maximale Anzahl von Labels pro Objekt |
Maximale Anzahl von Labels pro Objekt, die der Detektor zurückgibt. Wenn nicht festgelegt, wird der Standardwert 10 verwendet. |
Wenn Sie nur ein lokal gebündeltes Modell haben, erstellen Sie einfach einen Objektdetektor aus Ihrem LocalModel-Objekt:
Swift
let options = CustomObjectDetectorOptions(localModel: localModel) options.detectorMode = .singleImage options.shouldEnableClassification = true options.shouldEnableMultipleObjects = true options.classificationConfidenceThreshold = NSNumber(value: 0.5) options.maxPerObjectLabelCount = 3
Objective-C
MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableClassification = YES; options.shouldEnableMultipleObjects = YES; options.classificationConfidenceThreshold = @(0.5); options.maxPerObjectLabelCount = 3;
Wenn Sie ein remote gehostetes Modell haben, müssen Sie prüfen, ob es heruntergeladen wurde, bevor Sie es ausführen.
Sie müssen dies zwar nur vor dem Ausführen des Objektdetektors bestätigen, aber wenn Sie sowohl ein remote gehostetes als auch ein lokal gebündeltes Modell haben, ist es möglicherweise sinnvoll, diese Prüfung beim Instanziieren des ObjectDetector durchzuführen: Erstellen Sie einen Detektor aus dem Remote-Modell, wenn es heruntergeladen wurde, und andernfalls aus dem lokalen Modell.
Swift
// Path where your download logic saves the model let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let localModelURL = documentDirectory.appendingPathComponent("my_remote_model.tflite") let model: LocalModel if FileManager.default.fileExists(atPath: localModelURL.path) { // Use the downloaded model model = LocalModel(path: localModelURL.path) } else { // Fall back to bundled model guard let bundledModelPath = Bundle.main.path(forResource: "model", ofType: "tflite") else { return } model = LocalModel(path: bundledModelPath) } let options = CustomObjectDetectorOptions(localModel: model) options.detectorMode = .singleImage options.shouldEnableClassification = true options.shouldEnableMultipleObjects = true options.classificationConfidenceThreshold = NSNumber(value: 0.5) options.maxPerObjectLabelCount = 3 let objectDetector = ObjectDetector.objectDetector(options: options)
Objective-C
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; NSString *localModelPath = [documentsDirectory stringByAppendingPathComponent:@"my_remote_model.tflite"]; MLKLocalModel *model; if ([NSFileManager.defaultManager fileExistsAtPath:localModelPath]) { // Use the downloaded model model = [[MLKLocalModel alloc] initWithPath:localModelPath]; } else { // Fall back to bundled model NSString *bundledModelPath = [NSBundle.mainBundle pathForResource:@"model" ofType:@"tflite"]; model = [[MLKLocalModel alloc] initWithPath:bundledModelPath]; } MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:model]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableClassification = YES; options.shouldEnableMultipleObjects = YES; options.classificationConfidenceThreshold = @(0.5); options.maxPerObjectLabelCount = 3; MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];
Wenn Sie nur ein remote gehostetes Modell haben, sollten Sie modellbezogene Funktionen deaktivieren, z. B. Teile der Benutzeroberfläche ausblenden oder ausgrauen, bis Sie bestätigen, dass das Modell heruntergeladen wurde.
Swift
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let localModelURL = documentDirectory.appendingPathComponent("my_remote_model.tflite") if FileManager.default.fileExists(atPath: localModelURL.path) { // Model is already cached, initialize immediately self.initializeDetector(with: localModelURL) } else { // Model is not yet available, show loading UI and start download self.showLoadingUI() let storage = Storage.storage() let modelRef = storage.reference(forURL: "gs://YOUR_BUCKET/path/to/model.tflite") modelRef.write(toFile: localModelURL) { url, error in self.hideLoadingUI() if let error = error { // Handle download error self.showErrorUI() } else if let modelURL = url { // Download success, initialize detector self.initializeDetector(with: modelURL) } } } func initializeDetector(with modelURL: URL) { let localModel = LocalModel(path: modelURL.path) let options = CustomObjectDetectorOptions(localModel: localModel) options.detectorMode = .singleImage options.shouldEnableClassification = true options.shouldEnableMultipleObjects = true self.objectDetector = ObjectDetector.objectDetector(options: options) // Enable ML features in UI self.enableMLFeatures() }
Objective-C
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; NSString *localModelPath = [documentsDirectory stringByAppendingPathComponent:@"my_remote_model.tflite"]; NSURL *localModelURL = [NSURL fileURLWithPath:localModelPath]; if ([NSFileManager.defaultManager fileExistsAtPath:localModelPath]) { // Model is already cached, initialize immediately [self initializeDetectorWithURL:localModelURL]; } else { // Model is not yet available, show loading UI and start download [self showLoadingUI]; FIRStorage *storage = [FIRStorage storage]; FIRStorageReference *modelRef = [storage referenceForURL:@"gs://YOUR_BUCKET/path/to/model.tflite"]; [modelRef writeToFile:localModelURL completion:^(NSURL * _Nullable URL, NSError * _Nullable error) { [self hideLoadingUI]; if (error != nil) { // Handle download error [self showErrorUI]; } else { // Download success, initialize detector [self initializeDetectorWithURL:URL]; } }]; } - (void)initializeDetectorWithURL:(NSURL *)modelURL { MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithPath:modelURL.path]; MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableClassification = YES; options.shouldEnableMultipleObjects = YES; self.objectDetector = [MLKObjectDetector objectDetectorWithOptions:options]; // Enable ML features in UI [self enableMLFeatures]; }
Die API für Objekterkennung und -tracking ist für diese beiden Hauptanwendungsfälle optimiert:
- Live-Erkennung und -Tracking des wichtigsten Objekts im Sucher der Kamera.
- Erkennung mehrerer Objekte aus einem statischen Bild.
So konfigurieren Sie die API für diese Anwendungsfälle:
Swift
// Live detection and tracking let options = CustomObjectDetectorOptions(localModel: localModel) options.shouldEnableClassification = true options.maxPerObjectLabelCount = 3 // Multiple object detection in static images let options = CustomObjectDetectorOptions(localModel: localModel) options.detectorMode = .singleImage options.shouldEnableMultipleObjects = true options.shouldEnableClassification = true options.maxPerObjectLabelCount = 3
Objective-C
// Live detection and tracking MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.shouldEnableClassification = YES; options.maxPerObjectLabelCount = 3; // Multiple object detection in static images MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableMultipleObjects = YES; options.shouldEnableClassification = YES; options.maxPerObjectLabelCount = 3;
3. Eingabebild vorbereiten
Erstellen Sie ein VisionImage-Objekt mit einem UIImage oder einem
CMSampleBuffer.
Wenn Sie ein UIImage verwenden, gehen Sie so vor:
- Erstellen Sie ein
VisionImage-Objekt mit demUIImage. Geben Sie die richtige.orientationan.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Wenn Sie einen CMSampleBuffer verwenden, gehen Sie so vor:
-
Geben Sie die Ausrichtung der Bilddaten im
CMSampleBufferan.So rufen Sie die Bildausrichtung ab:
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; } }
- Erstellen Sie ein
VisionImage-Objekt mit demCMSampleBuffer-Objekt und der Ausrichtung: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];
4. Objektdetektor erstellen und ausführen
Erstellen Sie einen neuen Objektdetektor:
Swift
let objectDetector = ObjectDetector.objectDetector(options: options)
Objective-C
MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];
Verwenden Sie dann den Detektor:
Asynchron:
Swift
objectDetector.process(image) { objects, error in guard error == nil, let objects = objects, !objects.isEmpty else { // Handle the error. return } // Show results. }
Objective-C
[objectDetector processImage:image completion:^(NSArray
*_Nullable objects, NSError *_Nullable error) { if (objects.count == 0) { // Handle the error. return; } // Show results. }]; Synchron:
Swift
var objects: [Object] do { objects = try objectDetector.results(in: image) } catch let error { // Handle the error. return } // Show results.
Objective-C
NSError *error; NSArray
*objects = [objectDetector resultsInImage:image error:&error]; // Show results or handle the error.
5. Informationen zu gelabelten Objekten abrufen
Wenn der Aufruf des Bildprozessors erfolgreich ist, wird entweder eine Liste von Object-Objekten an den Completion-Handler übergeben oder die Liste wird zurückgegeben, je nachdem, ob Sie die asynchrone oder synchrone Methode aufgerufen haben.
Jedes Object enthält die folgenden Properties:
frame |
Ein CGRect das die Position des Objekts im
Bild angibt. |
||||||
trackingID |
Eine Ganzzahl, die das Objekt in verschiedenen Bildern identifiziert, oder `nil` im SINGLE_IMAGE_MODE. | ||||||
labels |
|
Swift
// objects contains one item if multiple object detection wasn't enabled. for object in objects { let frame = object.frame let trackingID = object.trackingID let description = object.labels.enumerated().map { (index, label) in "Label \(index): \(label.text), \(label.confidence), \(label.index)" }.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]; } }
Für eine optimale Nutzererfahrung sorgen
Für eine optimale Nutzererfahrung sollten Sie in Ihrer App die folgenden Richtlinien beachten:
- Die erfolgreiche Objekterkennung hängt von der visuellen Komplexität des Objekts ab. Damit Objekte mit wenigen visuellen Merkmalen erkannt werden können, müssen sie möglicherweise einen größeren Teil des Bildes einnehmen. Sie sollten Nutzern eine Anleitung zum Erfassen von Eingaben geben, die gut zu den Objekten passen, die Sie erkennen möchten.
- Wenn Sie die Klassifizierung verwenden und Objekte erkennen möchten, die nicht eindeutig in die unterstützten Kategorien fallen, implementieren Sie eine spezielle Verarbeitung für unbekannte Objekte.
Sehen Sie sich auch die ML Kit Material Design-Showcase-App und die Material Design Muster für Funktionen mit maschinellem Lernen an.
Leistungsoptimierung
Wenn Sie die Objekterkennung in einer Echtzeitanwendung verwenden möchten, beachten Sie diese Richtlinien, um die besten Frameraten zu erzielen:Verwenden Sie im Streamingmodus in einer Echtzeitanwendung keine Objekterkennung für mehrere Objekte, da die meisten Geräte keine angemessenen Frameraten erzeugen können.
- Verwenden Sie für die Verarbeitung von Videoframes die synchrone API
results(in:)des Detektors. Rufen Sie diese Methode über dieAVCaptureVideoDataOutputSampleBufferDelegate'scaptureOutput(_, didOutput:from:)Funktion auf, um synchron Ergebnisse aus dem angegebenen Video frame abzurufen. Lassen SieAVCaptureVideoDataOutput'salwaysDiscardsLateVideoFramesauftruegesetzt, um Aufrufe an den Detektor zu drosseln. Wenn ein neuer Videoframe verfügbar wird, während der Detektor ausgeführt wird, wird er verworfen. - Wenn Sie die Ausgabe des Detektors verwenden, um Grafiken auf das Eingabebild zu legen, rufen Sie zuerst das Ergebnis von ML Kit ab und rendern Sie dann das Bild und das Overlay in einem Schritt. So rendern Sie die Anzeigeoberfläche nur einmal für jeden verarbeiteten Eingabeframe. Ein Beispiel finden Sie unter updatePreviewOverlayViewWithLastFrame im ML Kit-Schnellstartbeispiel.