Início rápido para Android

Esta página mostra como criar um aplicativo Android com o TensorFlow Lite para analisar um feed de câmera ao vivo e identificar objetos. Esse 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 que você possa 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 do git para usar check-out esparso, para que você tenha apenas os arquivos para o aplicativo de exemplo de detecção de objeto:
    cd examples
    git sparse-checkout init --cone
    git sparse-checkout set lite/examples/object_detection/android_play_services
    

Importar e executar o projeto

Use o Android Studio para criar um projeto a partir do código de exemplo baixado, compile o projeto e execute-o.

Para importar e construir 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 o aplicativo de exemplo funciona

O aplicativo de exemplo usa um modelo de detecção de objetos pré-treinado, como mobilenetv1.tflite , no formato TensorFlow Lite, procure objetos em um fluxo de vídeo ao vivo da câmera de um dispositivo Android. O código para este 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 da imagem da câmera, prepara os dados para o modelo e exibe os resultados da detecção do objeto.

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.

Construir 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. Essas 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 os modelos de aprendizado de máquina do TensorFlow Lite e acessar as funções do utilitário de dados de ML. Essas funções de utilitário convertem dados como imagens em um formato de dados de tensor que pode ser processado por um modelo.

O aplicativo de exemplo usa a biblioteca de tarefas do TensorFlow Lite 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 de 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 os serviços do Google Play para executar modelos do TensorFlow Lite, você deve inicializar o serviço antes de usá-lo. Se você quiser usar o suporte de aceleração de hardware com o serviço, como aceleração de GPU, também habilite esse suporte como parte dessa inicialização.

Para inicializar o TensorFlow Lite com os serviços do Google Play:

  1. Crie um objeto TfLiteInitializationOptions e modifique-o para habilitar o suporte a GPU:

    val options = TfLiteInitializationOptions.builder()
        .setEnableGpuDelegateSupport(true)
        .build()
    
  2. Use o método TfLiteVision.initialize() para habilitar 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 de modelo de ML

Inicialize o interpretador de modelo de aprendizado de máquina do TensorFlow Lite carregando o arquivo de modelo e definindo os parâmetros do modelo. Um modelo do TensorFlow Lite inclui um arquivo .tflite que contém 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 para o modelo, como o limite de previsão e o tamanho do conjunto de resultados:

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

    try {
        optionsBuilder.useGpu()
    } catch(e: Exception) {
        objectDetectorListener.onError("GPU is not supported on this device")
    }
    
    
  5. Use as configurações desse objeto para construir um objeto ObjectDetector do TensorFlow Lite que contenha 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 formas específicas que correspondam ao formato de dados usado para treinar o modelo. Dependendo do modelo que você usa, pode ser necessário transformar os dados para ajustá-los ao que o modelo espera. O aplicativo de exemplo usa um objeto ImageAnalysis para extrair quadros de imagem do subsistema da 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 para o 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 de dados finais 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 um 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 aplicativo deve processar executando lógica de negócios adicional, exibindo resultados para o usuário ou realizando 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 para o usuário.

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

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

    objectDetectorListener.onResults( // instance of CameraFragment
        results,
        inferenceTime,
        tensorImage.height,
        tensorImage.width)
    
  2. Aja sobre os resultados, como exibir a previsão para o 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