Início rápido para Android

Esta página mostra como criar um aplicativo Android com o TensorFlow Lite para analisar uma transmissão de câmera ao vivo e identificar objetos. Este caso de uso de aprendizado de máquina é chamado de detecção de objetos . O aplicativo de exemplo usa a biblioteca de tarefas do TensorFlow Lite para visão por meio do Google Play Services para permitir a execução do modelo de aprendizado de máquina de detecção de objetos, que é a abordagem recomendada para criar um aplicativo de ML com o TensorFlow Lite.

Demonstração animada de detecção de objetos

Configure e execute o exemplo

Para a primeira parte deste exercício, baixe o código de exemplo do GitHub e execute-o usando o Android Studio . As seções a seguir deste documento exploram as seções relevantes do exemplo de código, para que você possa aplicá-las aos seus próprios aplicativos Android. Você precisa das seguintes versões dessas ferramentas instaladas:

  • Android Studio 4.2 ou superior
  • Android SDK versão 21 ou superior

Obtenha o código de exemplo

Crie uma cópia local do código de exemplo para poder compilá-lo e executá-lo.

Para clonar e configurar o código de exemplo:

  1. Clone o repositório git
    git clone https://github.com/tensorflow/examples.git
    
  2. Configure sua instância git para usar checkout esparso, para que você tenha apenas os arquivos do aplicativo de exemplo de detecção de objetos:
    cd examples
    git sparse-checkout init --cone
    git sparse-checkout set lite/examples/object_detection/android_play_services
    

Importe e execute o projeto

Use o Android Studio para criar um projeto a partir do código de exemplo baixado, compilar o projeto e executá-lo.

Para importar e criar o projeto de código de exemplo:

  1. Inicie o Android Studio .
  2. Na página de boas-vindas do Android Studio, escolha Import Project ou selecione File > New > Import Project .
  3. Navegue até o diretório de código de exemplo que contém o arquivo build.gradle ( ...examples/lite/examples/object_detection/android_play_services/build.gradle ) e selecione esse diretório.

Depois de selecionar esse diretório, o Android Studio cria um novo projeto e o compila. Quando a compilação for concluída, o Android Studio exibirá uma mensagem BUILD SUCCESSFUL no painel de status Build Output .

Para executar o projeto:

  1. No Android Studio, execute o projeto selecionando Run > Run… e MainActivity .
  2. Selecione um dispositivo Android conectado com uma câmera para testar o aplicativo.

Como funciona o aplicativo de exemplo

O aplicativo de exemplo usa um modelo de detecção de objetos pré-treinado, como mobilenetv1.tflite , no formato TensorFlow Lite para procurar objetos em um stream de vídeo ao vivo da câmera de um dispositivo Android. O código para esse recurso está principalmente nestes arquivos:

  • ObjectDetectorHelper.kt – Inicializa o ambiente de tempo de execução, habilita a aceleração de hardware e executa o modelo de ML de detecção de objetos.
  • CameraFragment.kt – Cria o fluxo de dados de imagem da câmera, prepara dados para o modelo e exibe os resultados da detecção de objetos.

As próximas seções mostram os principais componentes desses arquivos de código, para que você possa modificar um aplicativo Android para adicionar essa funcionalidade.

Crie o aplicativo

As seções a seguir explicam as principais etapas para criar seu próprio aplicativo Android e executar o modelo mostrado no aplicativo de exemplo. Estas instruções usam o aplicativo de exemplo mostrado anteriormente como ponto de referência.

Adicionar dependências do projeto

No seu aplicativo Android básico, adicione as dependências do projeto para executar modelos de machine learning do TensorFlow Lite e acessar funções de utilitário de dados de ML. Essas funções utilitárias convertem dados como imagens em um formato de dados tensor que pode ser processado por um modelo.

O aplicativo de exemplo usa a biblioteca TensorFlow Lite Task para visão do Google Play Services para permitir a execução do modelo de aprendizado de máquina de detecção de objetos. As instruções a seguir explicam como adicionar as dependências de biblioteca necessárias ao seu próprio projeto de aplicativo Android.

Para adicionar dependências de módulo:

  1. No módulo do aplicativo Android que usa o TensorFlow Lite, atualize o arquivo build.gradle do módulo para incluir as dependências a seguir. No código de exemplo, este arquivo está localizado aqui: ...examples/lite/examples/object_detection/android_play_services/app/build.gradle

    ...
    dependencies {
    ...
        // Tensorflow Lite dependencies
        implementation 'org.tensorflow:tensorflow-lite-task-vision-play-services:0.4.2'
        implementation 'com.google.android.gms:play-services-tflite-gpu:16.1.0'
    ...
    }
    
  2. No Android Studio, sincronize as dependências do projeto selecionando: File > Sync Project with Gradle Files .

Inicialize os serviços do Google Play

Ao usar o Google Play Services para executar modelos do TensorFlow Lite, você deve inicializar o serviço antes de poder usá-lo. Se quiser usar o suporte de aceleração de hardware com o serviço, como aceleração de GPU, você também habilita esse suporte como parte dessa inicialização.

Para inicializar o TensorFlow Lite com o Google Play Services:

  1. Crie um objeto TfLiteInitializationOptions e modifique-o para ativar o suporte de GPU:

    val options = TfLiteInitializationOptions.builder()
        .setEnableGpuDelegateSupport(true)
        .build()
    
  2. Use o método TfLiteVision.initialize() para permitir o uso do tempo de execução do Play Services e defina um ouvinte para verificar se ele foi carregado com êxito:

    TfLiteVision.initialize(context, options).addOnSuccessListener {
        objectDetectorListener.onInitialized()
    }.addOnFailureListener {
        // Called if the GPU Delegate is not supported on the device
        TfLiteVision.initialize(context).addOnSuccessListener {
            objectDetectorListener.onInitialized()
        }.addOnFailureListener{
            objectDetectorListener.onError("TfLiteVision failed to initialize: "
                    + it.message)
        }
    }
    

Inicialize o interpretador do modelo de ML

Inicialize o interpretador do modelo de machine learning do TensorFlow Lite carregando o arquivo do modelo e definindo os parâmetros do modelo. Um modelo do TensorFlow Lite inclui um arquivo .tflite contendo o código do modelo. Você deve armazenar seus modelos no diretório src/main/assets do seu projeto de desenvolvimento, por exemplo:

.../src/main/assets/mobilenetv1.tflite`

Para inicializar o modelo:

  1. Adicione um arquivo de modelo .tflite ao diretório src/main/assets do seu projeto de desenvolvimento, como ssd_mobilenet_v1 .
  2. Defina a variável modelName para especificar o nome do arquivo do seu modelo de ML:

    val modelName = "mobilenetv1.tflite"
    
  3. Defina as opções do modelo, como o limite de previsão e o tamanho do conjunto de resultados:

    val optionsBuilder =
        ObjectDetector.ObjectDetectorOptions.builder()
            .setScoreThreshold(threshold)
            .setMaxResults(maxResults)
    
  4. Habilite a aceleração de GPU com as opções e permita que o código falhe normalmente se a aceleração não for suportada no dispositivo:

    try {
        optionsBuilder.useGpu()
    } catch(e: Exception) {
        objectDetectorListener.onError("GPU is not supported on this device")
    }
    
    
  5. Use as configurações deste objeto para construir um objeto ObjectDetector do TensorFlow Lite que contém o modelo:

    objectDetector =
        ObjectDetector.createFromFileAndOptions(
            context, modelName, optionsBuilder.build())
    

Para obter mais informações sobre como usar delegados de aceleração de hardware com o TensorFlow Lite, consulte Delegados do TensorFlow Lite .

Preparar dados para o modelo

Você prepara os dados para interpretação pelo modelo, transformando dados existentes, como imagens, no formato de dados do Tensor , para que possam ser processados ​​pelo seu modelo. Os dados em um Tensor devem ter dimensões ou formatos específicos que correspondam ao formato dos dados usados ​​para treinar o modelo. Dependendo do modelo usado, pode ser necessário transformar os dados para que se ajustem ao que o modelo espera. O aplicativo de exemplo usa um objeto ImageAnalysis para extrair quadros de imagem do subsistema de câmera.

Para preparar dados para processamento pelo modelo:

  1. Crie um objeto ImageAnalysis para extrair imagens no formato necessário:

    imageAnalyzer =
        ImageAnalysis.Builder()
            .setTargetAspectRatio(AspectRatio.RATIO_4_3)
            .setTargetRotation(fragmentCameraBinding.viewFinder.display.rotation)
            .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
            .setOutputImageFormat(OUTPUT_IMAGE_FORMAT_RGBA_8888)
            .build()
            ...
    
  2. Conecte o analisador ao subsistema da câmera e crie um buffer de bitmap para conter os dados recebidos da câmera:

            .also {
            it.setAnalyzer(cameraExecutor) { image ->
                if (!::bitmapBuffer.isInitialized) {
                    bitmapBuffer = Bitmap.createBitmap(
                        image.width,
                        image.height,
                        Bitmap.Config.ARGB_8888
                    )
                }
                detectObjects(image)
            }
        }
    
  3. Extraia os dados de imagem específicos necessários ao modelo e passe as informações de rotação da imagem:

    private fun detectObjects(image: ImageProxy) {
        // Copy out RGB bits to the shared bitmap buffer
        image.use { bitmapBuffer.copyPixelsFromBuffer(image.planes[0].buffer) }
        val imageRotation = image.imageInfo.rotationDegrees
        objectDetectorHelper.detect(bitmapBuffer, imageRotation)
    }    
    
  4. Conclua todas as transformações finais de dados e adicione os dados da imagem a um objeto TensorImage , conforme mostrado no método ObjectDetectorHelper.detect() do aplicativo de exemplo:

    val imageProcessor = ImageProcessor.Builder().add(Rot90Op(-imageRotation / 90)).build()
    
    // Preprocess the image and convert it into a TensorImage for detection.
    val tensorImage = imageProcessor.process(TensorImage.fromBitmap(image))
    

Executar previsões

Depois de criar um objeto TensorImage com dados de imagem no formato correto, você pode executar o modelo nesses dados para produzir uma previsão ou inferência . No aplicativo de exemplo, esse código está contido no método ObjectDetectorHelper.detect() .

Para executar o modelo e gerar previsões a partir de dados de imagem:

  • Execute a previsão passando os dados da imagem para sua função de previsão:

    val results = objectDetector?.detect(tensorImage)
    

Lidar com a saída do modelo

Depois de executar dados de imagem no modelo de detecção de objetos, ele produz uma lista de resultados de previsão que o código do seu aplicativo deve manipular executando lógica de negócios adicional, exibindo resultados ao usuário ou executando outras ações. O modelo de detecção de objetos no aplicativo de exemplo produz uma lista de previsões e caixas delimitadoras para os objetos detectados. No aplicativo de exemplo, os resultados da previsão são passados ​​para um objeto ouvinte para processamento adicional e exibição ao usuário.

Para lidar com os resultados da previsão do modelo:

  1. Use um padrão de listener para transmitir resultados ao código do aplicativo ou aos objetos da interface do usuário. O aplicativo de exemplo usa esse padrão para transmitir resultados de detecção do objeto ObjectDetectorHelper para o objeto CameraFragment :

    objectDetectorListener.onResults( // instance of CameraFragment
        results,
        inferenceTime,
        tensorImage.height,
        tensorImage.width)
    
  2. Aja de acordo com os resultados, como exibir a previsão ao usuário. O aplicativo de exemplo desenha uma sobreposição no objeto CameraPreview para mostrar o resultado:

    override fun onResults(
      results: MutableList<Detection>?,
      inferenceTime: Long,
      imageHeight: Int,
      imageWidth: Int
    ) {
        activity?.runOnUiThread {
            fragmentCameraBinding.bottomSheetLayout.inferenceTimeVal.text =
                String.format("%d ms", inferenceTime)
    
            // Pass necessary information to OverlayView for drawing on the canvas
            fragmentCameraBinding.overlay.setResults(
                results ?: LinkedList<Detection>(),
                imageHeight,
                imageWidth
            )
    
            // Force a redraw
            fragmentCameraBinding.overlay.invalidate()
        }
    }
    

Próximos passos