Après avoir entraîné votre propre modèle à l'aide d'AutoML Vision Edge , vous pouvez l'utiliser dans votre application pour étiqueter les images.
Il existe deux manières d'intégrer des modèles formés à partir d'AutoML Vision Edge. Vous pouvez regrouper le modèle en copiant les fichiers du modèle dans votre projet Xcode, ou vous pouvez le télécharger dynamiquement depuis Firebase.
Options de regroupement de modèles | |
---|---|
Intégré dans votre application |
|
Hébergé avec Firebase |
|
Avant que tu commences
Incluez les bibliothèques ML Kit dans votre Podfile :
Pour regrouper un modèle avec votre application :
pod 'GoogleMLKit/ImageLabelingCustom'
Pour télécharger dynamiquement un modèle depuis Firebase, ajoutez la dépendance
LinkFirebase
:pod 'GoogleMLKit/ImageLabelingCustom' pod 'GoogleMLKit/LinkFirebase'
Après avoir installé ou mis à jour les pods de votre projet, ouvrez votre projet Xcode à l'aide de son
.xcworkspace
. ML Kit est pris en charge dans Xcode version 12.2 ou supérieure.Si vous souhaitez télécharger un modèle , assurez-vous d'ajouter Firebase à votre projet Android , si vous ne l'avez pas déjà fait. Cela n’est pas obligatoire lorsque vous regroupez le modèle.
1. Chargez le modèle
Configurer une source de modèle locale
Pour regrouper le modèle avec votre application :
Extrayez le modèle et ses métadonnées de l'archive zip que vous avez téléchargée depuis la console Firebase dans un dossier :
your_model_directory |____dict.txt |____manifest.json |____model.tflite
Les trois fichiers doivent être dans le même dossier. Nous vous recommandons d'utiliser les fichiers tels que vous les avez téléchargés, sans modification (y compris les noms de fichiers).
Copiez le dossier dans votre projet Xcode, en prenant soin de sélectionner Créer des références de dossier lorsque vous le faites. Le fichier modèle et les métadonnées seront inclus dans l'ensemble d'applications et disponibles pour ML Kit.
Créez un objet
LocalModel
en spécifiant le chemin d'accès au fichier manifeste du modèle :Rapide
guard let manifestPath = Bundle.main.path( forResource: "manifest", ofType: "json", inDirectory: "your_model_directory" ) else { return true } let localModel = LocalModel(manifestPath: manifestPath)
Objectif c
NSString *manifestPath = [NSBundle.mainBundle pathForResource:@"manifest" ofType:@"json" inDirectory:@"your_model_directory"]; MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithManifestPath:manifestPath];
Configurer une source de modèle hébergée par Firebase
Pour utiliser le modèle hébergé à distance, créez un objet CustomRemoteModel
, en spécifiant le nom que vous avez attribué au modèle lors de sa publication :
Rapide
// 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)
Objectif 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];
Ensuite, démarrez la tâche de téléchargement du modèle, en spécifiant les conditions dans lesquelles vous souhaitez autoriser le téléchargement. Si le modèle n'est pas sur l'appareil ou si une version plus récente du modèle est disponible, la tâche téléchargera le modèle de manière asynchrone depuis Firebase :
Rapide
let downloadConditions = ModelDownloadConditions(
allowsCellularAccess: true,
allowsBackgroundDownloading: true
)
let downloadProgress = ModelManager.modelManager().download(
remoteModel,
conditions: downloadConditions
)
Objectif c
MLKModelDownloadConditions *downloadConditions =
[[MLKModelDownloadConditions alloc] initWithAllowsCellularAccess:YES
allowsBackgroundDownloading:YES];
NSProgress *downloadProgress =
[[MLKModelManager modelManager] downloadRemoteModel:remoteModel
conditions:downloadConditions];
De nombreuses applications démarrent la tâche de téléchargement dans leur code d'initialisation, mais vous pouvez le faire à tout moment avant de devoir utiliser le modèle.
Créez un étiqueteur d'image à partir de votre modèle
Après avoir configuré vos sources de modèle, créez un objet ImageLabeler
à partir de l'une d'entre elles.
Si vous disposez uniquement d'un modèle regroupé localement, créez simplement un étiqueteur à partir de votre objet LocalModel
et configurez le seuil de score de confiance que vous souhaitez exiger (voir Évaluer votre modèle ) :
Rapide
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)
Objectif 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];
Si vous disposez d'un modèle hébergé à distance, vous devrez vérifier qu'il a été téléchargé avant de l'exécuter. Vous pouvez vérifier l'état de la tâche de téléchargement de modèle à l'aide de la méthode isModelDownloaded(remoteModel:)
du gestionnaire de modèles.
Bien que vous n'ayez qu'à confirmer cela avant d'exécuter l'étiqueteur, si vous disposez à la fois d'un modèle hébergé à distance et d'un modèle regroupé localement, il peut être judicieux d'effectuer cette vérification lors de l'instanciation d' ImageLabeler
: créez un étiqueteur à partir du modèle distant s'il est été téléchargé, et à partir du modèle local dans le cas contraire.
Rapide
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)
Objectif 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];
Si vous disposez uniquement d'un modèle hébergé à distance, vous devez désactiver les fonctionnalités liées au modèle (par exemple, griser ou masquer une partie de votre interface utilisateur) jusqu'à ce que vous confirmiez que le modèle a été téléchargé.
Vous pouvez obtenir l'état de téléchargement du modèle en attachant des observateurs au centre de notifications par défaut. Assurez-vous d'utiliser une référence faible à self
dans le bloc observateur, car les téléchargements peuvent prendre un certain temps et l'objet d'origine peut être libéré à la fin du téléchargement. Par exemple:
Rapide
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]
// ...
}
Objectif 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. Préparez l'image d'entrée
Créez un objet VisionImage
à l'aide d'un UIImage
ou d'un CMSampleBufferRef
.
Si vous utilisez un UIImage
, procédez comme suit :
- Créez un objet
VisionImage
avec leUIImage
. Assurez-vous de spécifier la.orientation
correcte.Rapide
let image = VisionImage(image: uiImage) visionImage.orientation = image.imageOrientation
Objectif c
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Si vous utilisez un CMSampleBufferRef
, procédez comme suit :
Spécifiez l'orientation des données d'image contenues dans le tampon
CMSampleBufferRef
.Pour obtenir l'orientation de l'image :
Rapide
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 } }
Objectif 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; } }
- Créez un objet
VisionImage
à l'aide de l'objetCMSampleBufferRef
et de l'orientation :Rapide
let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
Objectif c
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
3. Exécutez l'étiqueteur d'images
De manière asynchrone :
Rapide
imageLabeler.process(image) { labels, error in
guard error == nil, let labels = labels, !labels.isEmpty else {
// Handle the error.
return
}
// Show results.
}
Objectif c
[imageLabeler
processImage:image
completion:^(NSArray<MLKImageLabel *> *_Nullable labels,
NSError *_Nullable error) {
if (label.count == 0) {
// Handle the error.
return;
}
// Show results.
}];
De manière synchrone :
Rapide
var labels: [ImageLabel]
do {
labels = try imageLabeler.results(in: image)
} catch let error {
// Handle the error.
return
}
// Show results.
Objectif c
NSError *error;
NSArray<MLKImageLabel *> *labels =
[imageLabeler resultsInImage:image error:&error];
// Show results or handle the error.
4. Obtenez des informations sur les objets étiquetés
Si l'opération d'étiquetage de l'image réussit, elle renvoie un tableau de ImageLabel
. Chaque ImageLabel
représente quelque chose qui a été étiqueté dans l'image. Vous pouvez obtenir la description textuelle de chaque étiquette (si disponible dans les métadonnées du fichier de modèle TensorFlow Lite), le score de confiance et l'index. Par exemple:
Rapide
for label in labels {
let labelText = label.text
let confidence = label.confidence
let index = label.index
}
Objectif c
for (MLKImageLabel *label in labels) {
NSString *labelText = label.text;
float confidence = label.confidence;
NSInteger index = label.index;
}
Conseils pour améliorer les performances en temps réel
Si vous souhaitez étiqueter des images dans une application en temps réel, suivez ces directives pour obtenir les meilleures fréquences d'images :
- Accélérez les appels au détecteur. Si une nouvelle image vidéo devient disponible pendant le fonctionnement du détecteur, supprimez l'image.
- Si vous utilisez la sortie du détecteur pour superposer des graphiques sur l'image d'entrée, obtenez d'abord le résultat, puis effectuez le rendu de l'image et la superposition en une seule étape. Ce faisant, vous effectuez le rendu sur la surface d'affichage une seule fois pour chaque image d'entrée. Consultez les classes previewOverlayView et FIRDetectionOverlayView dans l’exemple d’application de présentation pour un exemple.