Puedes usar ML Kit para detectar objetos y hacerles seguimiento en fotogramas sucesivos de video.
Cuando pasas una imagen al Kit de AA, este detecta hasta cinco objetos junto con la posición de cada objeto en la imagen. Al detectar objetos en transmisiones de video por Internet, cada objeto tiene un ID único que puedes usar para seguir el objeto de un fotograma a otro. También tienes la opción de habilitar objetos de clasificación, que etiqueta objetos con descripciones de categorías amplias.
Probar
- Prueba la app de ejemplo para ver un ejemplo de uso de esta API.
- Visita la vitrina de Material Design app para una implementación de extremo a extremo de esta API.
Antes de comenzar
- Incluye los siguientes pods del ML Kit en tu Podfile:
pod 'GoogleMLKit/ObjectDetection', '3.2.0'
- Después de instalar o actualizar los Pods de tu proyecto, abre el proyecto de Xcode a través de su
.xcworkspace
El Kit de AA es compatible con Xcode 12.4 o versiones posteriores.
1. Configura el detector de objetos
Para detectar objetos y hacerles seguimiento, primero crea una instancia de
ObjectDetector
y, de manera opcional, especifica cualquier configuración del detector que quieras
cambian de la configuración predeterminada.
Configura el detector de objetos para tu caso de uso con un
ObjectDetectorOptions
. Puedes cambiar las siguientes opciones 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 un puede generar resultados incompletos (p. ej., cuadros delimitadores o categorías) en las primeras invocaciones del el detector. Además, en el modo de transmisión, el detector asigna el seguimiento IDs de objetos, que puedes usar para hacer un seguimiento de objetos en los fotogramas. Usa este modo cuando quieras hacer un seguimiento de objetos o cuando haya latencia baja es importante, como cuando se procesan transmisiones de video tiempo.
En el modo de imagen única, el detector de objetos muestra el resultado luego de determinar el cuadro delimitador del objeto. Si también habilitas clasificación, devuelve el resultado después del cuadro delimitador y están disponibles las dos etiquetas de categoría. Como consecuencia, la detección la latencia es potencialmente mayor. Además, en el modo de imagen única, el seguimiento No se asignaron los IDs. Usa este modo si la latencia no es crítica no debes ocuparte de resultados parciales.
Detecta varios objetos y hazles un seguimiento false
(predeterminado) |true
Ya sea para detectar y rastrear hasta cinco objetos o solo los más objeto destacado (predeterminado).
Clasifica objetos false
(predeterminado) |true
Indica si se deben clasificar o no los objetos detectados en categorías generales. Cuando se habilita, el detector de objetos clasifica los objetos las siguientes categorías: artículos de moda, comida, artículos para el hogar, lugares y plantas.
La API de detección y seguimiento de objetos está optimizada para estos dos usos principales casos:
- Detección y seguimiento en vivo del objeto más prominente de la cámara visor.
- Es la detección de varios objetos en una imagen estática.
Si deseas configurar la API para estos casos de uso, sigue estos pasos:
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;
- Obtén una instancia de
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 la imagen de entrada
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
CMSampleBuffer
Crea un objeto VisionImage
con un objeto UIImage
o
CMSampleBuffer
Si usas un UIImage
, sigue estos pasos:
- Crea un objeto
VisionImage
conUIImage
. Asegúrate de especificar el.orientation
correcto.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Si usas un CMSampleBuffer
, sigue estos pasos:
-
Especificar la orientación de los datos de imagen que se incluyen en la
CMSampleBuffer
Para obtener la orientación de la imagen, haz lo siguiente:
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 objeto
VisionImage
con el elemento ObjetoCMSampleBuffer
y orientación: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. Procesa la imagen
Pasa elVisionImage
a uno de los procesamientos de imágenes del detector de objetos.
. Puedes usar el método process(image:)
asíncrono o
método síncrono results()
.
Para detectar objetos de manera asíncrona, haz lo siguiente:
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. }];
Para detectar objetos de manera síncrona, haz lo siguiente:
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. Obtén información sobre los objetos detectados
Si la llamada al procesador de imágenes se ejecuta correctamente, este pasa una lista deObject
al controlador de finalización o muestra la lista, según lo siguiente:
sin importar si llama al método
asíncrono o síncrono.
Cada Object
contiene las siguientes propiedades:
frame |
Un CGRect que indica la posición del objeto en el
imagen. |
trackingID |
Un número entero que identifica el objeto en las imágenes, o "nil" en modo de imagen única. |
labels |
Un array de etiquetas que describen el objeto que muestra el detector.
La propiedad está vacía si la opción del detector
shouldEnableClassification se configura como 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]; ... } }
Mejora la usabilidad y el rendimiento
Para obtener la mejor experiencia del usuario, sigue estos lineamientos en tu app:
- La detección correcta de objetos depende de la complejidad visual del objeto. En ser detectados, los objetos con un número reducido de características visuales podrían necesitar ocupe una parte más grande de la imagen. Debes brindar orientación a los usuarios sobre y capturar entradas que funcionen bien con el tipo de objetos que quieres detectar.
- Cuando usas la clasificación, si deseas detectar objetos que no caen de forma clara en las categorías admitidas, implementa un manejo especial para los objetos.
Consulta también el Material Design Colección de patrones para atributos con tecnología de aprendizaje automático.
Cuando uses el modo de transmisión en una aplicación en tiempo real, sigue estos lineamientos para lograr la mejor velocidad de fotogramas:
- No uses la detección de múltiples objetos en el modo de transmisión, ya que la mayoría de los dispositivos no lo hace. producir una velocidad de fotogramas adecuada.
- Inhabilita la clasificación si no la necesitas.
- Para procesar fotogramas de video, usa la API síncrona
results(in:)
del detector. Llamada este método desde el DeAVCaptureVideoDataOutputSampleBufferDelegate
La funcióncaptureOutput(_, didOutput:from:)
para obtener resultados de un video determinado de forma síncrona marco. Mantener deAVCaptureVideoDataOutput
alwaysDiscardsLateVideoFrames
comotrue
para limitar las llamadas al detector Si un nuevo cliente El fotograma estará disponible mientras se ejecute el detector, que se descartará. - Si usas la salida del detector para superponer gráficos la imagen de entrada, primero obtén el resultado del Kit de AA y, luego, renderiza la imagen y superponerla en un solo paso. De esta manera, renderizas en la superficie de visualización. solo una vez por cada trama de entrada procesada. Consulta updatePreviewOverlayViewWithLastFrame. en la muestra de inicio rápido del Kit de AA para ver un ejemplo.