Puoi utilizzare ML Kit per rilevare e monitorare gli oggetti nei frame video successivi.
Quando passi un'immagine a ML Kit, rileva fino a cinque oggetti nell'immagine insieme alla posizione di ciascun oggetto nell'immagine. Quando vengono rilevati oggetti nei flussi video, ogni oggetto ha un ID univoco che puoi utilizzare per monitorare l'oggetto da un frame all'altro. Facoltativamente, puoi abilitare la classificazione approssimativa degli oggetti, che etichetta gli oggetti con descrizioni di categorie ampie.
Prova subito
- Prova l'app di esempio per vedere un esempio di utilizzo di questa API.
- Consulta l'app Material Design Showcase per un'implementazione end-to-end di questa API.
Prima di iniziare
- Includi i seguenti pod di ML Kit nel tuo podfile:
pod 'GoogleMLKit/ObjectDetection', '3.2.0'
- Dopo aver installato o aggiornato i pod del progetto, apri il progetto Xcode utilizzando
.xcworkspace
. ML Kit è supportato in Xcode versione 12.4 o successiva.
1. Configura il rilevatore di oggetti
Per rilevare e monitorare gli oggetti, crea prima un'istanza di
ObjectDetector
e, facoltativamente, specifica le impostazioni del rilevatore che vuoi
modificare rispetto all'impostazione predefinita.
Configura il rilevatore di oggetti per il tuo caso d'uso con un oggetto
ObjectDetectorOptions
. Puoi modificare le seguenti impostazioni:Impostazioni del rilevatore di oggetti Modalità di rilevamento .stream
(valore predefinito) |.singleImage
In modalità flusso (impostazione predefinita), il rilevatore di oggetti viene eseguito con una latenza molto bassa, ma potrebbe produrre risultati incompleti (ad esempio categorie o riquadri di delimitazione non specificati) sulle prime chiamate del rilevatore. Inoltre, in modalità flusso, il rilevatore assegna gli ID monitoraggio agli oggetti, che puoi utilizzare per monitorare gli oggetti nei frame. Usa questa modalità quando vuoi monitorare gli oggetti o quando è importante una bassa latenza, ad esempio durante l'elaborazione in tempo reale dei flussi video.
In modalità immagine singola, il rilevatore di oggetti restituisce il risultato dopo aver stabilito il riquadro di delimitazione dell'oggetto. Se abiliti anche la classificazione, restituisce il risultato dopo che il riquadro di delimitazione e l'etichetta della categoria sono entrambi disponibili. Di conseguenza, la latenza di rilevamento è potenzialmente più elevata. Inoltre, in modalità immagine singola non vengono assegnati gli ID monitoraggio. Usa questa modalità se la latenza non è critica e non vuoi gestire risultati parziali.
Rilevamento e monitoraggio di più oggetti false
(valore predefinito) |true
Indica se rilevare e monitorare fino a cinque oggetti o solo l'oggetto più in evidenza (impostazione predefinita).
Classifica oggetti false
(valore predefinito) |true
Indica se classificare o meno gli oggetti rilevati in categorie approssimative. Se abilitato, il rilevatore di oggetti classifica gli oggetti nelle seguenti categorie: articoli di moda, cibo, prodotti per la casa, luoghi e piante.
L'API di rilevamento e monitoraggio degli oggetti è ottimizzata per questi due casi d'uso principali:
- Rilevamento in tempo reale e monitoraggio dell'oggetto più in evidenza nel mirino della fotocamera.
- Il rilevamento di più oggetti in un'immagine statica.
Per configurare l'API per questi casi d'uso:
Swift
// Live detection and tracking let options = ObjectDetectorOptions() options.shouldEnableClassification = true // Multiple object detection in static images let options = ObjectDetectorOptions() options.detectorMode = .singleImage options.shouldEnableMultipleObjects = true options.shouldEnableClassification = true
Objective-C
// Live detection and tracking MLKObjectDetectorOptions *options = [[MLKObjectDetectorOptions alloc] init]; options.shouldEnableClassification = YES; // Multiple object detection in static images MLKObjectDetectorOptions *options = [[MLKOptions alloc] init]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableMultipleObjects = YES; options.shouldEnableClassification = YES;
- Ottieni un'istanza di
ObjectDetector
:
Swift
let objectDetector = ObjectDetector.objectDetector() // Or, to change the default settings: let objectDetector = ObjectDetector.objectDetector(options: options)
Objective-C
MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetector]; // Or, to change the default settings: MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];
2. Prepara l'immagine di input
Per rilevare e monitorare gli oggetti, procedi nel seguente modo per ogni immagine o frame del video.
Se hai abilitato la modalità flusso, devi creare oggetti VisionImage
da
CMSampleBuffer
s.
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. Elabora immagine
PassaVisionImage
a uno dei metodi di elaborazione delle immagini del rilevatore di oggetti. Puoi usare il metodo asincrono process(image:)
o results()
sincrono.
Per rilevare gli oggetti in modo asincrono:
Swift
objectDetector.process(image) { objects, error in guard error == nil else { // Error. return } guard !objects.isEmpty else { // No objects detected. return } // Success. Get object info here. // ... }
Objective-C
[objectDetector processImage:image completion:^(NSArray* _Nullable objects, NSError * _Nullable error) { if (error == nil) { return; } if (objects.count == 0) { // No objects detected. return; } // Success. Get object info here. }];
Per rilevare gli oggetti in modo sincrono:
Swift
var objects: [Object] do { objects = try objectDetector.results(in: image) } catch let error { print("Failed to detect object with error: \(error.localizedDescription).") return } guard !objects.isEmpty else { print("Object detector returned no results.") return } // Success. Get object info here.
Objective-C
NSError *error; NSArray*objects = [objectDetector resultsInImage:image error:&error]; if (error == nil) { return; } if (objects.count == 0) { // No objects detected. return; } // Success. Get object info here.
4. Ottieni informazioni sugli oggetti rilevati
Se la chiamata al processore di immagini ha esito positivo, trasmette un elenco diObject
al gestore di completamento o restituisce l'elenco, a seconda che tu abbia chiamato il metodo asincrono o sincrono.
Ogni Object
contiene le seguenti proprietà:
frame |
CGRect che indica la posizione dell'oggetto nell'immagine. |
trackingID |
Un numero intero che identifica l'oggetto tra le immagini o "nil" in modalità immagine singola. |
labels |
Un array di etichette che descrivono l'oggetto restituito dal rilevatore.
La proprietà è vuota se l'opzione del rilevatore
shouldEnableClassification è impostata su false .
|
Swift
// objects contains one item if multiple object detection wasn't enabled. for object in objects { let frame = object.frame let trackingID = object.trackingID // If classification was enabled: let description = object.labels.enumerated().map { (index, label) in "Label \(index): \(label.text), \(label.confidence)" }.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]; ... } }
Migliorare l'usabilità e le prestazioni
Per un'esperienza utente ottimale, segui queste linee guida nella tua app:
- Il rilevamento riuscito degli oggetti dipende dalla complessità visiva dell'oggetto. Per poter essere rilevati, gli oggetti con un numero ridotto di funzionalità visive potrebbero occupare una parte più grande dell'immagine. Devi fornire agli utenti indicazioni sull'acquisizione degli input che funzionino bene con il tipo di oggetti che vuoi rilevare.
- Se utilizzi la classificazione, se vuoi rilevare oggetti che non rientrano nelle categorie supportate, implementa la gestione speciale degli oggetti sconosciuti.
Dai anche un'occhiata alla raccolta di pattern di Material Design per il machine learning di Material Design.
Quando utilizzi la modalità streaming in un'applicazione in tempo reale, segui queste linee guida per ottenere la migliore frequenza fotogrammi:
- Non utilizzare il rilevamento di più oggetti in modalità flusso, poiché la maggior parte dei dispositivi non sarà in grado di produrre frequenze di fotogrammi adeguate.
- Disattiva la classificazione se non ti serve.
- 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.