Puoi utilizzare ML Kit per rilevare e tracciare oggetti attraverso i fotogrammi del video.
Quando passi le immagini ML Kit, ML Kit restituisce per ogni immagine un elenco rilevati fino a cinque oggetti e la loro posizione nell'immagine. Quando vengono rilevati oggetti negli stream video, ogni oggetto ha un ID che puoi utilizzare per monitorarlo nelle immagini. Se vuoi, puoi anche attivare la classificazione approssimativa degli oggetti, che etichetta gli oggetti con descrizioni di categorie generali.
Prima di iniziare
- Se non hai già aggiunto Firebase alla tua app, puoi farlo seguendo le istruzioni riportate in passaggi nella Guida introduttiva.
- Includi le librerie del kit ML nel tuo podfile:
Dopo aver installato o aggiornato i pod del progetto, assicurati di aprire il progetto Xcode utilizzando il relativopod 'Firebase/MLVision', '6.25.0' pod 'Firebase/MLVisionObjectDetection', '6.25.0'
.xcworkspace
. - Nell'app, importa Firebase:
import Firebase
@import Firebase;
1. configura il rilevatore di oggetti
Per iniziare a rilevare e monitorare gli oggetti, crea innanzitutto un'istanza di
VisionObjectDetector
, specificando facoltativamente le impostazioni del rilevatore che vuoi
modificare quello predefinito.
Configura il rilevatore di oggetti per il tuo caso d'uso con un
VisionObjectDetectorOptions
oggetto. Puoi modificare le seguenti opzioni: impostazioni:Impostazioni del rilevatore di oggetti Modalità di rilevamento .stream
(valore predefinito) |.singleImage
In modalità flusso (impostazione predefinita), il rilevatore di oggetti funziona con un ma potrebbe produrre risultati incompleti (ad esempio, riquadri di delimitazione o categoria) alle prime chiamate di il rilevatore. Inoltre, in modalità stream, il rilevatore assegna agli oggetti ID di monitoraggio che puoi utilizzare per monitorarli nei fotogrammi. Utilizza questa modalità quando vuoi monitorare oggetti o quando è importante una bassa latenza, ad esempio durante l'elaborazione di stream video in tempo reale.
In modalità immagine singola, il rilevatore di oggetti attende che venga rilevato riquadro di delimitazione dell'oggetto e (se hai abilitato la classificazione) disponibili prima di restituire un risultato. Di conseguenza, la latenza del rilevamento è potenzialmente più elevata. Inoltre, in un'immagine singola , gli ID monitoraggio non vengono assegnati. Usa questa modalità in caso di latenza non è fondamentale e non vuoi gestire che consentono di analizzare i dati e visualizzare i risultati.
Rilevamento e tracciamento di più oggetti false
(predefinito) |true
Indica se rilevare e tracciare fino a cinque oggetti o solo il più ben visibile (impostazione predefinita).
Classificare gli 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 nell'intervallo seguenti categorie: articoli di moda, cibo, casalinghi, luoghi, piante e sconosciuti.
L'API di rilevamento e monitoraggio degli oggetti è ottimizzata per questi due usi principali casi:
- Rilevamento e tracciamento in tempo reale dell'oggetto più in evidenza nella videocamera mirino
- Rilevamento di più oggetti in un'immagine statica
Per configurare l'API per questi casi d'uso:
// Live detection and tracking let options = VisionObjectDetectorOptions() options.detectorMode = .stream options.shouldEnableMultipleObjects = false options.shouldEnableClassification = true // Optional // Multiple object detection in static images let options = VisionObjectDetectorOptions() options.detectorMode = .singleImage options.shouldEnableMultipleObjects = true options.shouldEnableClassification = true // Optional
// Live detection and tracking FIRVisionObjectDetectorOptions *options = [[FIRVisionObjectDetectorOptions alloc] init]; options.detectorMode = FIRVisionObjectDetectorModeStream; options.shouldEnableMultipleObjects = NO; options.shouldEnableClassification = YES; // Optional // Multiple object detection in static images FIRVisionObjectDetectorOptions *options = [[FIRVisionObjectDetectorOptions alloc] init]; options.detectorMode = FIRVisionObjectDetectorModeSingleImage; options.shouldEnableMultipleObjects = YES; options.shouldEnableClassification = YES; // Optional
Ottieni un'istanza di
FirebaseVisionObjectDetector
:let objectDetector = Vision.vision().objectDetector() // Or, to change the default settings: let objectDetector = Vision.vision().objectDetector(options: options)
FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetector]; // Or, to change the default settings: FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetectorWithOptions:options];
2. Esegui il rilevatore di oggetti
Per rilevare e tracciare oggetti, procedi nel seguente modo per ogni immagine o fotogramma del video.
Se hai abilitato la modalità flusso di dati, devi creare VisionImage
oggetti da
CMSampleBufferRef
Crea un oggetto
VisionImage
utilizzando unUIImage
o unCMSampleBufferRef
.Per usare un
UIImage
:- Se necessario, ruota l'immagine in modo che
imageOrientation
è.up
. - Crea un oggetto
VisionImage
utilizzando l'oggetto ruotato correttamenteUIImage
. Non specificare alcun metadato di rotazione (l'impostazione predefinita) è necessario utilizzare il valore.topLeft
.let image = VisionImage(image: uiImage)
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
Per usare un
CMSampleBufferRef
:-
Crea un oggetto
VisionImageMetadata
che specifichi l'orientamento dei dati dell'immagine contenuti bufferCMSampleBufferRef
.Per ottenere l'orientamento dell'immagine:
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> VisionDetectorImageOrientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftTop : .rightTop case .landscapeLeft: return cameraPosition == .front ? .bottomLeft : .topLeft case .portraitUpsideDown: return cameraPosition == .front ? .rightBottom : .leftBottom case .landscapeRight: return cameraPosition == .front ? .topRight : .bottomRight case .faceDown, .faceUp, .unknown: return .leftTop } }
- (FIRVisionDetectorImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationLeftTop; } else { return FIRVisionDetectorImageOrientationRightTop; } case UIDeviceOrientationLandscapeLeft: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationBottomLeft; } else { return FIRVisionDetectorImageOrientationTopLeft; } case UIDeviceOrientationPortraitUpsideDown: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationRightBottom; } else { return FIRVisionDetectorImageOrientationLeftBottom; } case UIDeviceOrientationLandscapeRight: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationTopRight; } else { return FIRVisionDetectorImageOrientationBottomRight; } default: return FIRVisionDetectorImageOrientationTopLeft; } }
Quindi, crea l'oggetto dei metadati:
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init]; AVCaptureDevicePosition cameraPosition = AVCaptureDevicePositionBack; // Set to the capture device you used. metadata.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
- Crea un oggetto
VisionImage
utilizzando il metodo OggettoCMSampleBufferRef
e metadati di rotazione:let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- Se necessario, ruota l'immagine in modo che
Passa
VisionImage
a uno dei sistemi di elaborazione delle immagini del rilevatore di oggetti di machine learning. Puoi utilizzare il metodoprocess(image:)
asincrono oppure metodoresults()
sincrono.Per rilevare gli oggetti in modo asincrono:
objectDetector.process(image) { detectedObjects, error in guard error == nil else { // Error. return } guard let detectedObjects = detectedObjects, !detectedObjects.isEmpty else { // No objects detected. return } // Success. Get object info here. // ... }
[objectDetector processImage:image completion:^(NSArray<FIRVisionObject *> * _Nullable objects, NSError * _Nullable error) { if (error == nil) { return; } if (objects == nil | objects.count == 0) { // No objects detected. return; } // Success. Get object info here. // ... }];
Per rilevare gli oggetti in modo sincrono:
var results: [VisionObject]? = nil do { results = try objectDetector.results(in: image) } catch let error { print("Failed to detect object with error: \(error.localizedDescription).") return } guard let detectedObjects = results, !detectedObjects.isEmpty else { print("Object detector returned no results.") return } // ...
NSError *error; NSArray<FIRVisionObject *> *objects = [objectDetector resultsInImage:image error:&error]; if (error == nil) { return; } if (objects == nil | objects.count == 0) { // No objects detected. return; } // Success. Get object info here. // ...
Se la chiamata al processore di immagini ha esito positivo, passa un elenco di
VisionObject
al gestore del completamento o restituisce l'elenco, a seconda del a seconda che tu abbia chiamato il metodo asincrono o sincrono.Ogni
VisionObject
contiene le seguenti proprietà:frame
Un elemento CGRect
che indica la posizione dell'oggetto nell'intervallo dell'immagine.trackingID
Un numero intero che identifica l'oggetto attraverso le immagini. Nil in modalità di immagine singola. classificationCategory
La categoria approssimativa dell'oggetto. Se il rilevatore di oggetti non ha attivato la classificazione, questo valore è sempre .unknown
.confidence
Il valore di confidenza della classificazione dell'oggetto. Se il rilevatore di oggetti non ha la classificazione abilitata o se l'oggetto è classificato come sconosciuto, il valore è nil
.// detectedObjects contains one item if multiple object detection wasn't enabled. for obj in detectedObjects { let bounds = obj.frame let id = obj.trackingID // If classification was enabled: let category = obj.classificationCategory let confidence = obj.confidence }
// The list of detected objects contains one item if multiple // object detection wasn't enabled. for (FIRVisionObject *obj in objects) { CGRect bounds = obj.frame; if (obj.trackingID) { NSInteger id = obj.trackingID.integerValue; } // If classification was enabled: FIRVisionObjectCategory category = obj.classificationCategory; float confidence = obj.confidence.floatValue; }
Migliorare l'usabilità e le prestazioni
Per una migliore esperienza utente, segui queste linee guida nella tua app:
- Il successo del rilevamento degli oggetti dipende dalla complessità visiva dell'oggetto. Oggetti con un numero ridotto di caratteristiche visive, potrebbe dover occupare una parte dell'immagine da rilevare. Devi fornire agli utenti indicazioni su come acquisire che funzioni bene con il tipo di oggetti che vuoi rilevare.
- Quando usi la classificazione, se vuoi rilevare gli oggetti che non cadono nelle categorie supportate, implementare una gestione speciale per di oggetti strutturati.
Consulta anche [App vetrina ML Kit Material Design][showcase-link]{: .external } e i Material design Raccolta di pattern per le funzionalità basate sul machine learning.
Quando utilizzi la modalità flusso di dati in un'applicazione in tempo reale, segui queste linee guida per ottenere le migliori frequenze fotogrammi:
Non utilizzare il rilevamento di più oggetti in modalità flusso di dati, perché la maggior parte dei dispositivi non essere in grado di produrre frequenze fotogrammi adeguate.
Disabilita la classificazione se non ti serve.
- Limita le chiamate al rilevatore. Se un nuovo fotogramma disponibili mentre il rilevatore è in esecuzione, abbandona il frame.
- Se utilizzi l'output del rilevatore per sovrapporre gli elementi grafici l'immagine di input, occorre prima ottenere il risultato da ML Kit, quindi eseguire il rendering dell'immagine e la sovrapposizione in un solo passaggio. In questo modo, puoi visualizzare i contenuti solo una volta per ogni frame di input. Guarda previewOverlayView. e FIRDetectionOverlayView nell'app di esempio Showcase.