Analisar imagens

O caso de uso de análise de imagens oferece ao seu app uma imagem acessível por CPU para realizar processamento de imagens, visão computacional ou inferência de aprendizagem de máquina. O aplicativo implementa um método de análise executado em cada frame.

Implementação

As imagens são processadas pela transmissão de um executor em que a análise da imagem é executada e de um parâmetro ImageAnalysis.Analyzer para o método setAnalyzer().

O exemplo de código neste tópico mostra como fazer isso e como vincular o caso de uso de análise de imagens e um caso de uso de visualização ao LifecycleOwner. Para ler sobre a criação de casos de usos de visualização, consulte Implementar uma visualização.

A análise de imagem pode ser feita de duas maneiras: com ou sem bloqueio. O modo de bloqueio é ativado chamando setBackpressureStrategy() com STRATEGY_BLOCK_PRODUCER. Nesse modo, o executor recebe frames da câmera em ordem sequencial. Isso significa que, se o método analyze() levar mais tempo do que a latência de um único frame na taxa atual, os frames poderão não estar mais atualizados porque os novos serão impedidos de entrar no pipeline até o retorno do método.

O modo sem bloqueio é ativado ao chamar setBackpressureStrategy() com STRATEGY_KEEP_ONLY_LATEST. Neste modo, o executor recebe o último frame disponível da câmera no momento em que o método analyze() é chamado. Se o método demorar mais do que a latência de um único frame na taxa atual, alguns frames poderão ser ignorados para que, na próxima vez em que analyze() receber dados, ele tenha o último frame disponível no pipeline da câmera.

Antes de retornar de analyze(), feche a referência da imagem chamando image.close() para evitar o bloqueio da produção de outras imagens (fazendo com que a visualização pare) e evitar imagens que podem ser descartadas. O método precisa concluir a análise ou fazer uma cópia em vez de transmitir a referência da imagem além do método de análise.

Kotlin

val imageAnalysis = ImageAnalysis.Builder()
    .setTargetResolution(Size(1280, 720))
    .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
    .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)
        .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);

O CameraX produz imagens no formato YUV_420_888.

Outros recursos

Para saber mais sobre o CameraX, consulte os seguintes recursos.

Codelab

  • Introdução ao CameraX
  • Exemplo de código

  • App de amostra oficial do CameraX (link em inglês)