Puedes usar el Kit de AA para detectar objetos y hacerles seguimiento en todos los fotogramas de video.
Cuando pasas imágenes del Kit de AA, este muestra, para cada imagen, una lista de hasta cinco objetos detectados y su posición en la imagen. Cuando detectas objetos en transmisiones de video por Internet, cada uno de ellos tiene un ID que puedes usar para seguirlo en las imágenes. De manera opcional, puedes habilitar la clasificación ordinaria de objetos, que etiqueta los objetos con descripciones de categorías amplias.
Antes de comenzar
- Si aún no agregaste Firebase a tu app, sigue los pasos en la guía de introducción para hacerlo.
- Incluye las bibliotecas del ML Kit en tu Podfile:
pod 'Firebase/MLVision', '6.25.0' pod 'Firebase/MLVisionObjectDetection', '6.25.0'
Después de instalar o actualizar los Pods de tu proyecto, asegúrate de abrir el proyecto de Xcode con su.xcworkspace
. - En tu app, importa Firebase:
Swift
import Firebase
Objective-C
@import Firebase;
1. Configura el detector de objetos
Para comenzar a detectar objetos y hacerles seguimiento, primero debes crear una instancia de VisionObjectDetector
que, de manera opcional, especifique cualquier configuración del detector que quieras cambiar de la configuración predeterminada.
Configura el detector de objetos para tu caso práctico con un objeto
VisionObjectDetectorOptions
. Puedes cambiar las siguientes opciones de configuración:Configuración del detector de objetos Modo de detección .stream
(predeterminado) |.singleImage
En el modo de transmisión (predeterminado), el detector de objetos se ejecuta con baja latencia, pero podría generar resultados incompletos (como cuadros de límite o categoría no especificados) en las primeras invocaciones del detector. Además, en el modo de transmisión, el detector asigna ID de seguimiento a los objetos, que puedes usar para hacer seguimiento de objetos a través de los fotogramas. Usa este modo cuando quieras hacer seguimiento de objetos o cuando la baja latencia sea importante, como cuando procesas transmisiones de video en Internet en tiempo real.
En el modo de imagen individual, el detector de objetos espera hasta que el cuadro de límite y (si habilitaste la clasificación) la categoría de un objeto detectado estén disponibles antes de mostrar un resultado. En consecuencia, la latencia de detección es potencialmente más alta. Además, en el modo de imagen individual, no se asignan ID de seguimiento. Usa este modo si la latencia no es importante y no quieres lidiar con resultados parciales.
Detecta varios objetos y hazles seguimiento false
(predeterminado) |true
Ya sea para detectar y hacer seguimiento de hasta cinco objetos o solo al más prominente (predeterminado).
Clasifica objetos false
(predeterminado) |true
Ya sea para clasificar o no objetos detectados en categorías ordinarias. Cuando se encuentra habilitado, el detector de objetos clasifica los objetos en las siguientes categorías: productos de moda, comida, productos para el hogar, lugares, plantas y desconocidos.
La API de detección y seguimiento de objetos está optimizada para estos dos casos prácticos principales:
- Detección y seguimiento en vivo del objeto más prominente en el visor de la cámara
- Detección de múltiples objetos de una imagen estática
Con el fin de configurar la API para estos casos prácticos, sigue estos pasos:
Swift
// 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
Objective-C
// 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
Obtén una instancia de
FirebaseVisionObjectDetector
:Swift
let objectDetector = Vision.vision().objectDetector() // Or, to change the default settings: let objectDetector = Vision.vision().objectDetector(options: options)
Objective-C
FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetector]; // Or, to change the default settings: FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetectorWithOptions:options];
2. Ejecuta el detector de objetos
Para detectar objetos y hacerles seguimiento, haz lo siguiente con cada imagen o fotograma de video.
Si habilitaste el modo de transmisión, debes crear objetos VisionImage
a partir de varias CMSampleBufferRef
.
Crea un objeto
VisionImage
mediante unaUIImage
oCMSampleBufferRef
.Para usar una
UIImage
, debes hacer lo siguiente:- Si es necesario, rota la imagen para que la propiedad
imageOrientation
sea.up
. - Crea un objeto
VisionImage
mediante unaUIImage
que se haya rotado adecuadamente. No especifiques los metadatos de rotación. Se debe usar el valor predeterminado.topLeft
.Swift
let image = VisionImage(image: uiImage)
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
Para usar una
CMSampleBufferRef
, debes hacer lo siguiente:-
Crea un objeto
VisionImageMetadata
que especifique la orientación de los datos de la imagen contenidos en el búferCMSampleBufferRef
.Para obtener la orientación de la imagen, haz lo siguiente:
Swift
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 } }
Objective-C
- (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; } }
Luego crea el objeto de metadatos de esta manera:
Swift
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
Objective-C
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 objeto
VisionImage
a través del objetoCMSampleBufferRef
y los metadatos de rotación:Swift
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- Si es necesario, rota la imagen para que la propiedad
Pasa la
VisionImage
a uno de los métodos de procesamiento de imágenes del detector de objetos. Puedes usar el método asíncronoprocess(image:)
o el método síncronoresults()
.Haz lo siguiente para detectar objetos de manera asíncrona:
Swift
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. // ... }
Objective-C
[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. // ... }];
Haz lo siguiente para detectar objetos de manera síncrona:
Swift
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 } // ...
Objective-C
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. // ...
Si la llamada al procesador de imágenes se ejecuta correctamente, este pasa una lista de
VisionObject
al controlador de finalización o la muestra, dependiendo de si llamaste a un método asíncrono o a uno síncrono.Cada
VisionObject
contiene las siguientes propiedades:frame
Un CGRect
que indica la posición del objeto en la imagen.trackingID
Un número entero que identifica el objeto en las imágenes. Nil en el modo de imagen individual. classificationCategory
La categoría ordinaria del objeto. Si el detector de objetos no tiene habilitada la clasificación, esto es siempre .unknown
.confidence
El valor de confianza de la clasificación del objeto. Si el detector de objetos no tiene habilitada la clasificación, o el objeto se clasifica como desconocido, esto es nil
.Swift
// 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 }
Objective-C
// 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; }
Mejora la usabilidad y el rendimiento
Para obtener la mejor experiencia del usuario, sigue estos lineamientos en tu aplicación:
- La detección exitosa de objetos depende de la complejidad visual del objeto. Es posible que los objetos con una pequeña cantidad de características visuales deban ocupar un espacio mayor en la imagen para ser detectados. Debes proporcionar a los usuarios una orientación sobre cómo capturar información que funcione bien con el tipo de objetos que deseas detectar.
- Cuando uses la clasificación, si deseas detectar objetos que no se incluyen de forma clara en las categorías compatibles, implementa un manejo especial para objetos desconocidos.
Además, consulta la [app de muestra de Material Design del Kit de AA][showcase-link]{: .external} y la colección de patrones para las funciones con tecnología de aprendizaje automático de Material Design.
Cuando uses el modo de transmisión en una aplicación en tiempo real, sigue estos lineamientos para lograr los mejores fotogramas:
No utilices la detección de múltiples objetos en el modo de transmisión, ya que la mayoría de los dispositivos no podrán producir fotogramas adecuados.
Inhabilita la clasificación si no la necesitas.
- Regula las llamadas al detector. Si hay un fotograma de video nuevo disponible mientras se ejecuta el detector, ignora ese fotograma.
- Si estás usando la salida del detector para superponer gráficos en la imagen de entrada, primero obtén el resultado de la detección de ML Kit y, luego, procesa la imagen y la superposición en un solo paso. De esta manera, procesas la superficie de visualización solo una vez por cada fotograma de entrada. Consulta las clases previewOverlayView y FIRDetectionOverlayView en la app de muestra para ver un ejemplo.