Análisis de imágenes

El caso de uso de análisis de imágenes le proporciona a tu app una imagen a la que se puede acceder desde la CPU para realizar procesamiento de imágenes, visión artificial o inferencia de aprendizaje automático. La aplicación implementa un método analyze() que se ejecuta en cada fotograma.

Implementación

Las imágenes se procesan cuando se pasa un ejecutor en el que se ejecuta el análisis de imágenes y también un parámetro ImageAnalysis.Analyzer al método setAnalyzer(). Solo se puede registrar un analizador a la vez: registrar uno nuevo reemplaza al existente.

En el ejemplo de código de este tema, se muestra cómo hacerlo, además de cómo vincular el caso de uso para analizar imágenes y uno de vista previa a LifecycleOwner. Para leer sobre la creación de casos de uso de vista previa, consulta Cómo implementar una vista previa.

El análisis de imágenes puede funcionar en dos modos: con bloqueo y sin bloqueo. El modo de bloqueo se habilita llamando a setBackpressureStrategy() con STRATEGY_BLOCK_PRODUCER. En este modo, el ejecutor recibe fotogramas de la cámara en orden secuencial. Eso significa que, si el método analyze() tarda más que la latencia de un solo fotograma en la velocidad actual, es posible que los fotogramas dejen de estar vigentes, ya que se bloquea la entrada de los fotogramas nuevos a la canalización hasta que se muestra el método.

El modo sin bloqueo se habilita llamando a setBackpressureStrategy() con STRATEGY_KEEP_ONLY_LATEST. En este modo, el ejecutor recibe el último fotograma disponible de la cámara en el momento en que se llama al método analyze(). Si el método lleva más tiempo que la latencia de un solo fotograma en la velocidad actual, es posible que se omitan algunos fotogramas; de este modo, la próxima vez que analyze() reciba datos, obtendrá el último fotograma disponible en la canalización de la cámara.

Antes de regresar de analyze(), llama a image.close() para cerrar la referencia de imagen y evitar el bloqueo de la producción de más imágenes (y la demora de la vista previa), y evitar la posible caída de imágenes. El método debe completar el análisis o hacer una copia en lugar de pasar la referencia de la imagen más allá del método de análisis.

Kotlin

val imageAnalysis = ImageAnalysis.Builder()
    .setTargetResolution(Size(1280, 720))
    .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
    .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888)
    .build()

imageAnalysis.setAnalyzer(executor, ImageAnalysis.Analyzer { image ->
    val rotationDegrees = image.imageInfo.rotationDegrees
    // insert your code here.
})

cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, imageAnalysis, preview)

Java

ImageAnalysis imageAnalysis =
    new ImageAnalysis.Builder()
        .setTargetResolution(new Size(1280, 720))
        .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
        .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888)
        .build();

imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() {
    @Override
    public void analyze(@NonNull ImageProxy image) {
        int rotationDegrees = image.getImageInfo().getRotationDegrees();
            // insert your code here.
        }
    });

cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, imageAnalysis, preview);

De manera predeterminada, CameraX establece imágenes en formato OUTPUT_IMAGE_FORMAT_YUV_420_888.

La aplicación puede verificar el espacio de color del ImageProxy que pasó CameraX con la función ImageProxy::getFormat(). Si muestra ImageFormat.YUV_420_888, significa que la imagen está en el espacio de color YUV. Si muestra PixelFormat.RGBA_8888, significa que está en RGBA.

El formato de salida YUV está disponible para todas las versiones de camera-core. RGBA está disponible para camera-core:1.1.0-alpha09 y versiones posteriores, solo para casos de uso de análisis de imágenes.

Cuando configuras un formato de salida RGBA, CameraX convierte internamente imágenes del espacio YUV a RGBA, y almacena bits de imagen en el ByteBuffer del primer plano del ImageProxy (no se usan otros planos) con la siguiente secuencia:

ImageProxy::planes[0].buffer[0]: alpha
ImageProxy::planes[1].buffer[1]: red
ImageProxy::planes[2].buffer[2]: green
ImageProxy::planes[3].buffer[3]: blue
...

La conversión de color es un paso adicional al formato de salida YUV, y el período de conversión es parte del tiempo total del análisis de imágenes. La aplicación tendrá menos tiempo de procesamiento por fotograma cuando realice un análisis en tiempo real. Debes usarlo cuando tu aplicación necesite un resultado RGBA.

Recursos adicionales

Para obtener más información acerca de CameraX, consulta los siguientes recursos adicionales.

Codelab

  • Comienza a usar CameraX
  • Muestra de código

  • App de muestra de CameraX oficial