Nachdem Sie Ihr eigenes Modell mit AutoML Vision Edge trainiert haben, können Sie es in Ihrer App verwenden, um Bilder mit Labels zu versehen.
Es gibt zwei Möglichkeiten, mit AutoML Vision Edge trainierte Modelle zu integrieren. Sie können das Modell bündeln, indem Sie die Modelldateien in Ihr Xcode-Projekt kopieren oder dynamisch von Firebase herunterladen.
Optionen für die Modellkombination | |
---|---|
In Ihrer App gebündelt |
|
Mit Firebase gehostet |
|
Hinweis
Fügen Sie die ML Kit-Bibliotheken in Ihre Podfile-Datei ein:
So bündeln Sie ein Modell mit Ihrer App:
pod 'GoogleMLKit/ImageLabelingCustom'
Wenn Sie ein Modell dynamisch von Firebase herunterladen möchten, fügen Sie die
LinkFirebase
-Abhängigkeit hinzu:pod 'GoogleMLKit/ImageLabelingCustom' pod 'GoogleMLKit/LinkFirebase'
Nachdem Sie die Pods Ihres Projekts installiert oder aktualisiert haben, öffnen Sie Ihr Xcode-Projekt mit der
.xcworkspace
. ML Kit wird in Xcode Version 12.2 und höher unterstützt.Wenn Sie ein Modell herunterladen möchten, müssen Sie Ihrem Android-Projekt Firebase 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:
Extrahieren Sie das Modell und seine Metadaten aus dem ZIP-Archiv, das Sie von der Firebase-Konsole heruntergeladen haben, in einen Ordner:
your_model_directory |____dict.txt |____manifest.json |____model.tflite
Alle drei Dateien müssen sich im selben Ordner befinden. Wir empfehlen, die Dateien unverändert (einschließlich der Dateinamen) zu verwenden.
Kopieren Sie den Ordner in Ihr Xcode-Projekt und wählen Sie dabei Ordnerreferenzen erstellen aus. Die Modelldatei und die Metadaten sind im App Bundle enthalten und sind für ML Kit verfügbar.
Erstellen Sie ein
LocalModel
-Objekt und geben Sie den Pfad zur Manifestdatei des Modells an:Swift
guard let manifestPath = Bundle.main.path( forResource: "manifest", ofType: "json", inDirectory: "your_model_directory" ) else { return true } let localModel = LocalModel(manifestPath: manifestPath)
Objective-C
NSString *manifestPath = [NSBundle.mainBundle pathForResource:@"manifest" ofType:@"json" inDirectory:@"your_model_directory"]; MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithManifestPath:manifestPath];
Von Firebase gehostete Modellquelle konfigurieren
Wenn Sie das remote gehostete Modell verwenden möchten, erstellen Sie ein CustomRemoteModel
-Objekt und geben Sie den Namen an, den Sie dem Modell bei der Veröffentlichung zugewiesen haben:
Swift
// Initialize the model source with the name you assigned in
// the Firebase console.
let remoteModelSource = FirebaseModelSource(name: "your_remote_model")
let remoteModel = CustomRemoteModel(remoteModelSource: remoteModelSource)
Objective-C
// Initialize the model source with the name you assigned in
// the Firebase console.
MLKFirebaseModelSource *firebaseModelSource =
[[MLKFirebaseModelSource alloc] initWithName:@"your_remote_model"];
MLKCustomRemoteModel *remoteModel =
[[MLKCustomRemoteModel alloc] initWithRemoteModelSource:firebaseModelSource];
Starten Sie dann den Modelldownload und geben Sie die Bedingungen an, unter denen Sie das Herunterladen erlauben möchten. Wenn das Modell nicht auf dem Gerät installiert ist oder eine neuere Version des Modells verfügbar ist, wird das Modell durch die Aufgabe asynchron von Firebase heruntergeladen:
Swift
let downloadConditions = ModelDownloadConditions(
allowsCellularAccess: true,
allowsBackgroundDownloading: true
)
let downloadProgress = ModelManager.modelManager().download(
remoteModel,
conditions: downloadConditions
)
Objective-C
MLKModelDownloadConditions *downloadConditions =
[[MLKModelDownloadConditions alloc] initWithAllowsCellularAccess:YES
allowsBackgroundDownloading:YES];
NSProgress *downloadProgress =
[[MLKModelManager modelManager] downloadRemoteModel:remoteModel
conditions:downloadConditions];
Viele Apps starten die Downloadaufgabe in ihrem Initialisierungscode, Sie können dies aber auch jederzeit tun, bevor Sie das Modell verwenden müssen.
Labelersteller für Bilder aus Ihrem Modell erstellen
Nachdem Sie Ihre Modellquellen konfiguriert haben, erstellen Sie ein ImageLabeler
-Objekt aus einer der Quellen.
Wenn Sie nur ein lokal gebündeltes Modell haben, erstellen Sie einfach aus dem LocalModel
-Objekt einen Labelersteller und konfigurieren Sie den erforderlichen Schwellenwert für den Konfidenzwert (siehe Modell bewerten):
Swift
let options = CustomImageLabelerOptions(localModel: localModel)
options.confidenceThreshold = NSNumber(value: 0.0) // Evaluate your model in the Cloud console
// to determine an appropriate value.
let imageLabeler = ImageLabeler.imageLabeler(options)
Objective-C
CustomImageLabelerOptions *options =
[[CustomImageLabelerOptions alloc] initWithLocalModel:localModel];
options.confidenceThreshold = @(0.0f); // Evaluate your model in the Cloud console
// to determine an appropriate value.
MLKImageLabeler *imageLabeler =
[MLKImageLabeler imageLabelerWithOptions:options];
Wenn Sie ein extern gehostetes Modell haben, müssen Sie prüfen, ob es heruntergeladen wurde, bevor Sie es ausführen. Sie können den Status der Aufgabe zum Modelldownload mit der Methode isModelDownloaded(remoteModel:)
des Modellmanagers prüfen.
Sie müssen dies zwar nur vor dem Ausführen des Labels bestätigen, wenn Sie jedoch sowohl ein remote gehostetes Modell als auch ein lokal gebündeltes Modell haben, kann es sinnvoll sein, diese Prüfung bei der Instanziierung des ImageLabeler
durchzuführen: Erstellen Sie einen Labels aus dem Remote-Modell, wenn es heruntergeladen wurde, andernfalls aus dem lokalen Modell.
Swift
var options: CustomImageLabelerOptions
if (ModelManager.modelManager().isModelDownloaded(remoteModel)) {
options = CustomImageLabelerOptions(remoteModel: remoteModel)
} else {
options = CustomImageLabelerOptions(localModel: localModel)
}
options.confidenceThreshold = NSNumber(value: 0.0) // Evaluate your model in the Firebase console
// to determine an appropriate value.
let imageLabeler = ImageLabeler.imageLabeler(options: options)
Objective-C
MLKCustomImageLabelerOptions *options;
if ([[MLKModelManager modelManager] isModelDownloaded:remoteModel]) {
options = [[MLKCustomImageLabelerOptions alloc] initWithRemoteModel:remoteModel];
} else {
options = [[MLKCustomImageLabelerOptions alloc] initWithLocalModel:localModel];
}
options.confidenceThreshold = @(0.0f); // Evaluate your model in the Firebase console
// to determine an appropriate value.
MLKImageLabeler *imageLabeler =
[MLKImageLabeler imageLabelerWithOptions:options];
Wenn Sie nur ein extern gehostetes Modell haben, sollten Sie modellverwandte Funktionen deaktivieren, z. B. einen Teil der Benutzeroberfläche grau ausblenden oder ausblenden, bis Sie bestätigen, dass das Modell heruntergeladen wurde.
Sie können den Downloadstatus des Modells abrufen, indem Sie Beobachter an das standardmäßige Benachrichtigungscenter anhängen. Achten Sie darauf, im Beobachterblock einen schwachen Verweis auf self
zu verwenden, da Downloads einige Zeit dauern können und das ursprüngliche Objekt bis zum Abschluss des Downloads freigegeben werden kann. Beispiel:
Swift
NotificationCenter.default.addObserver(
forName: .mlkitMLModelDownloadDidSucceed,
object: nil,
queue: nil
) { [weak self] notification in
guard let strongSelf = self,
let userInfo = notification.userInfo,
let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue]
as? RemoteModel,
model.name == "your_remote_model"
else { return }
// The model was downloaded and is available on the device
}
NotificationCenter.default.addObserver(
forName: .mlkitMLModelDownloadDidFail,
object: nil,
queue: nil
) { [weak self] notification in
guard let strongSelf = self,
let userInfo = notification.userInfo,
let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue]
as? RemoteModel
else { return }
let error = userInfo[ModelDownloadUserInfoKey.error.rawValue]
// ...
}
Objective-C
__weak typeof(self) weakSelf = self;
[NSNotificationCenter.defaultCenter
addObserverForName:MLKModelDownloadDidSucceedNotification
object:nil
queue:nil
usingBlock:^(NSNotification *_Nonnull note) {
if (weakSelf == nil | note.userInfo == nil) {
return;
}
__strong typeof(self) strongSelf = weakSelf;
MLKRemoteModel *model = note.userInfo[MLKModelDownloadUserInfoKeyRemoteModel];
if ([model.name isEqualToString:@"your_remote_model"]) {
// The model was downloaded and is available on the device
}
}];
[NSNotificationCenter.defaultCenter
addObserverForName:MLKModelDownloadDidFailNotification
object:nil
queue:nil
usingBlock:^(NSNotification *_Nonnull note) {
if (weakSelf == nil | note.userInfo == nil) {
return;
}
__strong typeof(self) strongSelf = weakSelf;
NSError *error = note.userInfo[MLKModelDownloadUserInfoKeyError];
}];
2. Eingabebild vorbereiten
Erstellen Sie ein VisionImage
-Objekt mit einem UIImage
oder einem CMSampleBufferRef
.
Wenn du ein UIImage
verwendest, gehe so vor:
- Erstellen Sie ein
VisionImage
-Objekt mit demUIImage
. Achten Sie darauf, die richtige.orientation
anzugeben.Swift
let image = VisionImage(image: uiImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Wenn Sie ein CMSampleBufferRef
verwenden, gehen Sie so vor:
-
Geben Sie die Ausrichtung der Bilddaten im Zwischenspeicher
CMSampleBufferRef
an.So rufen Sie die Bildausrichtung auf:
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 position == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored : UIImageOrientationRight; case UIDeviceOrientationLandscapeLeft: return position == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored : UIImageOrientationUp; case UIDeviceOrientationPortraitUpsideDown: return position == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored : UIImageOrientationLeft; case UIDeviceOrientationLandscapeRight: return position == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored : UIImageOrientationDown; case UIDeviceOrientationUnknown: case UIDeviceOrientationFaceUp: case UIDeviceOrientationFaceDown: return UIImageOrientationUp; } }
- Erstellen Sie ein
VisionImage
-Objekt mit demCMSampleBufferRef
-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];
3. Bildlabeler ausführen
Asynchron:
Swift
imageLabeler.process(image) { labels, error in
guard error == nil, let labels = labels, !labels.isEmpty else {
// Handle the error.
return
}
// Show results.
}
Objective-C
[imageLabeler
processImage:image
completion:^(NSArray<MLKImageLabel *> *_Nullable labels,
NSError *_Nullable error) {
if (label.count == 0) {
// Handle the error.
return;
}
// Show results.
}];
Synchron:
Swift
var labels: [ImageLabel]
do {
labels = try imageLabeler.results(in: image)
} catch let error {
// Handle the error.
return
}
// Show results.
Objective-C
NSError *error;
NSArray<MLKImageLabel *> *labels =
[imageLabeler resultsInImage:image error:&error];
// Show results or handle the error.
4. Informationen zu gekennzeichneten Objekten abrufen
Wenn der Vorgang zum Beschriften von Bildern erfolgreich war, wird ein Array von ImageLabel
zurückgegeben. Jedes ImageLabel
steht für etwas, das im Bild mit einem Label versehen war. Sie können die Textbeschreibung jedes Labels (falls in den Metadaten der TensorFlow Lite-Modelldatei verfügbar), den Konfidenzwert und den Index abrufen.
Beispiel:
Swift
for label in labels {
let labelText = label.text
let confidence = label.confidence
let index = label.index
}
Objective-C
for (MLKImageLabel *label in labels) {
NSString *labelText = label.text;
float confidence = label.confidence;
NSInteger index = label.index;
}
Tipps zur Verbesserung der Echtzeitleistung
Wenn du Bilder in einer Echtzeitanwendung mit Labels versehen möchtest, beachte die folgenden Richtlinien, um die besten Framerates zu erzielen:
- Aufrufe an den Detektor drosseln Wenn während der Laufzeit des Detektors ein neuer Videoframe verfügbar wird, legen Sie ihn ab.
- Wenn Sie die Ausgabe des Detektors verwenden, um Grafiken über das Eingabebild einzublenden, rufen Sie zuerst das Ergebnis ab und rendern Sie dann das Bild und das Overlay in einem Schritt. So wird für jeden Eingabeframe nur einmal auf die Displayoberfläche gerendert. Ein Beispiel finden Sie in den Klassen previewOverlayView und FIRDetectionOverlayView in der Showcase-Beispiel-App.