Analisar imagens

O caso de uso de análise de imagem 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 um parâmetro ImageAnalysis.Analyzer para o método setAnalyzer().

O exemplo de código neste tópico mostra como fazer isso, bem como vincular o caso de uso de análise de imagem 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 chamando 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 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
  • Amostra de código

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