Puoi utilizzare ML Kit per riconoscere le entità in un'immagine ed etichettarle. Questa API supporta un'ampia gamma di modelli di classificazione delle immagini personalizzati. Consulta Modelli personalizzati con ML Kit per indicazioni sui requisiti di compatibilità dei modelli, dove trovare modelli preaddestrati e come addestrare i tuoi modelli.
Esistono due modi per integrare un modello personalizzato. Puoi raggruppare il modello inserendolo nella cartella degli asset dell'app oppure scaricarlo da Firebase. La tabella seguente mette a confronto le due opzioni.
Modello in bundle | Modello in hosting |
---|---|
Il modello fa parte dell'APK della tua app, che aumenta le sue dimensioni. | Il modello non fa parte dell'APK. È ospitato tramite il caricamento su Firebase Machine Learning. |
Il modello è disponibile immediatamente, anche quando il dispositivo Android è offline. | Il modello viene scaricato on demand |
Non è necessario un progetto Firebase | Richiede un progetto Firebase |
Per aggiornare il modello, devi ripubblicare l'app | Esegui il push degli aggiornamenti del modello senza ripubblicare l'app |
Nessun test A/B integrato | Facile test A/B con Firebase Remote Config |
Prova subito
- Consultate l'app della guida rapida di Vision per un esempio di utilizzo del modello in bundle e l'app Guida rapida di AutoML per un esempio di utilizzo del modello ospitato.
Prima di iniziare
Includi le librerie del ML Kit nel tuo podfile:
Per raggruppare un modello con la tua app:
pod 'GoogleMLKit/ImageLabelingCustom', '3.2.0'
Per scaricare in modo dinamico un modello da Firebase, aggiungi la dipendenza
LinkFirebase
:pod 'GoogleMLKit/ImageLabelingCustom', '3.2.0' pod 'GoogleMLKit/LinkFirebase', '3.2.0'
Dopo aver installato o aggiornato i pod del progetto, apri il progetto Xcode utilizzando
.xcworkspace
. ML Kit è supportato in Xcode versione 13.2.1 o successive.Se vuoi scaricare un modello, assicurati di aggiungere Firebase al tuo progetto iOS, se non l'hai già fatto. Questa operazione non è necessaria quando raggruppa il modello.
1. Carica il modello
Configura un'origine modello locale
Per raggruppare il modello con la tua app:
Copia il file del modello (che in genere termina con
.tflite
o.lite
) nel tuo progetto Xcode, assicurandoti di selezionareCopy bundle resources
quando lo fai. Il file del modello verrà incluso nell'app bundle e disponibile per ML Kit.Crea l'oggetto
LocalModel
, specificando il percorso del file del modello:Swift
let localModel = LocalModel(path: localModelFilePath)
Objective-C
MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithPath:localModelFilePath];
Configura un'origine modello ospitata da Firebase
Per utilizzare il modello ospitato da remoto, crea un oggetto RemoteModel
, specificando il nome assegnato al modello al momento della pubblicazione:
Swift
let firebaseModelSource = FirebaseModelSource( name: "your_remote_model") // The name you assigned in // the Firebase console. let remoteModel = CustomRemoteModel(remoteModelSource: firebaseModelSource)
Objective-C
MLKFirebaseModelSource *firebaseModelSource = [[MLKFirebaseModelSource alloc] initWithName:@"your_remote_model"]; // The name you assigned in // the Firebase console. MLKCustomRemoteModel *remoteModel = [[MLKCustomRemoteModel alloc] initWithRemoteModelSource:firebaseModelSource];
Avvia l'attività di download del modello, specificando le condizioni in base alle quali vuoi consentire il download. Se il modello non è sul dispositivo o se è disponibile una versione più recente del modello, l'attività scaricherà in modo asincrono il modello da Firebase:
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] downloadModel:remoteModel conditions:downloadConditions];
Molte app avviano l'attività di download nel proprio codice di inizializzazione, tuttavia è possibile farlo in qualsiasi momento prima di dover utilizzare il modello.
Configura l'etichettatore di immagini
Dopo aver configurato le origini dei modelli, crea un oggetto ImageLabeler
da una di queste.
Sono disponibili le seguenti opzioni:
Opzioni | |
---|---|
confidenceThreshold
|
Punteggio di confidenza minimo delle etichette rilevate. Se non viene impostata, verrà utilizzata qualsiasi soglia di classificazione specificata dai metadati del modello. Se il modello non contiene metadati o se i metadati non specificano una soglia di classificazione, verrà utilizzata una soglia predefinita di 0,0. |
maxResultCount
|
Numero massimo di etichette da restituire. Se non viene impostato, verrà utilizzato il valore predefinito 10. |
Se hai solo un modello in bundle locale, crea un etichettatore dall'oggetto LocalModel
:
Swift
let options = CustomImageLabelerOptions(localModel: localModel) options.confidenceThreshold = NSNumber(value: 0.0) let imageLabeler = ImageLabeler.imageLabeler(options: options)
Objective-C
MLKCustomImageLabelerOptions *options = [[MLKCustomImageLabelerOptions alloc] initWithLocalModel:localModel]; options.confidenceThreshold = @(0.0); MLKImageLabeler *imageLabeler = [MLKImageLabeler imageLabelerWithOptions:options];
Se hai un modello ospitato da remoto, devi controllare che sia stato scaricato prima di eseguirlo. Puoi verificare lo stato dell'attività di download del modello utilizzando il metodo isModelDownloaded(remoteModel:)
del gestore dei modelli.
Anche se devi confermare questa operazione solo prima di eseguire l'etichettatore, se hai sia un modello ospitato in remoto che un modello in bundle a livello locale, potrebbe essere utile eseguire questo controllo per l'istanza di ImageLabeler
: crea un etichettatore dal modello remoto, se scaricato, oppure dal modello locale.
Swift
var options: CustomImageLabelerOptions! if (ModelManager.modelManager().isModelDownloaded(remoteModel)) { options = CustomImageLabelerOptions(remoteModel: remoteModel) } else { options = CustomImageLabelerOptions(localModel: localModel) } options.confidenceThreshold = NSNumber(value: 0.0) 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.0); MLKImageLabeler *imageLabeler = [MLKImageLabeler imageLabelerWithOptions:options];
Se hai solo un modello ospitato in remoto, devi disattivare la funzionalità relativa al modello (ad esempio, disattivare o nascondere parte della tua UI) fino a quando non confermi il download del modello.
Puoi verificare lo stato di download del modello collegando gli osservatori al Centro notifiche predefinito. Assicurati di utilizzare un riferimento debole a self
nel blocco osservatore, poiché i download possono richiedere del tempo e l'oggetto di origine può essere liberato al termine del download. Ad esempio:
Swift
NotificationCenter.default.addObserver( forName: .mlkitModelDownloadDidSucceed, 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: .mlkitModelDownloadDidFail, 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. Prepara l'immagine di input
Crea un oggetto VisionImage
utilizzando un UIImage
o un
CMSampleBuffer
.
Se utilizzi un UIImage
, segui questi passaggi:
- Crea un oggetto
VisionImage
con ilUIImage
. Assicurati di specificare il.orientation
corretto.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Se utilizzi un CMSampleBuffer
, segui questi passaggi:
-
Specifica l'orientamento dei dati dell'immagine contenuti in
CMSampleBuffer
.Per ottenere l'orientamento dell'immagine:
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; } }
- Crea un oggetto
VisionImage
utilizzando l'oggetto e l'orientamentoCMSampleBuffer
: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. Esegui l'etichettatore di immagini
Per etichettare gli oggetti in un'immagine, passa l'oggetto image
al metodo process()
di ImageLabeler
.
In modo asincrono:
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*_Nullable labels, NSError *_Nullable error) { if (label.count == 0) { // Handle the error. return; } // Show results. }];
Contemporaneamente:
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*labels = [imageLabeler resultsInImage:image error:&error]; // Show results or handle the error.
4. Informazioni sulle entità etichettate
Se l'operazione di etichettatura delle immagini ha esito positivo, restituisce un array diImageLabel
. Ogni ImageLabel
rappresenta qualcosa che è stato etichettato nell'immagine. Puoi ottenere la descrizione testuale di ogni etichetta (se disponibile nei metadati del file modello TensorFlow Lite), il punteggio di affidabilità e l'indice.
Ad esempio:
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; }
Suggerimenti per migliorare il rendimento in tempo reale
Se vuoi etichettare le immagini in un'applicazione in tempo reale, segui queste linee guida per ottenere la migliore frequenza fotogrammi:
- Per l'elaborazione dei frame video, utilizza l'API sincrona
results(in:)
del rilevatore. Richiama questo metodo dalla funzionecaptureOutput(_, didOutput:from:)
diAVCaptureVideoDataOutputSampleBufferDelegate
per ottenere in modo sincrono i risultati dal frame video specificato. MantienialwaysDiscardsLateVideoFrames
diAVCaptureVideoDataOutput
cometrue
per limitare le chiamate al rilevatore. Se un nuovo video diventa disponibile mentre il rilevatore è in esecuzione, viene eliminato. - Se utilizzi l'output del rilevatore per sovrapporre la grafica all'immagine di input, prima ottieni il risultato da ML Kit, quindi visualizza l'immagine e l'overlay in un solo passaggio. In questo modo, visualizzerai nella piattaforma display solo una volta per ogni frame di input elaborato. Guarda un esempio di updateAnteprimaOverlayViewWithLastFrame nell'esempio della guida rapida di ML Kit.