Criar e implantar um modelo de detecção de objetos personalizado com o TensorFlow Lite (Android)

1. Antes de começar

Neste codelab, você aprenderá a treinar um modelo personalizado de detecção de objetos usando um conjunto de imagens de treinamento comCriador de modelos do TFLite e implantar o modelo em um app Android usandoBiblioteca de tarefas TFLite de dados. Você vai:

  • Crie um app Android que detecte ingredientes em imagens de refeições.
  • Integre um modelo de detecção de objetos pré-treinado do TFLite e veja o limite do que o modelo pode detectar.
  • Treine um modelo personalizado de detecção de objetos para detectar os ingredientes/componentes de uma refeição usando um conjunto de dados personalizado chamado salad e o TFLite Model Maker.
  • Implante o modelo personalizado no app Android usando a biblioteca de tarefas TFLite.

No final, você criará algo semelhante à imagem abaixo:

b9705235366ae162.png

Pré-requisitos

Este codelab foi projetado para desenvolvedores móveis experientes que querem ganhar experiência com machine learning. Você precisa:

  • Desenvolvimento para Android usando Kotlin e Android Studio
  • Sintaxe básica do Python

O que você aprenderá

  • Como treinar um modelo personalizado de detecção de objetos usando o TFLite Model Maker.
  • Como implantar um modelo de detecção de objetos do TFLite usando a Biblioteca de tarefas do TFLite.

Pré-requisitos

  • Uma versão recente do Android Studio (v4.2+)
  • Android Studio Emulator ou um dispositivo Android físico
  • Código de amostra
  • Conhecimento básico de desenvolvimento Android no Kotlin.

2. Detecção de objetos

A detecção de objetos é um conjunto de tarefas de visão computacional que pode detectar e localizar objetos em uma imagem digital. Dado uma imagem ou um stream de vídeo, um modelo de detecção de objetos pode identificar quais objetos conhecidos podem estar presentes e fornecer informações sobre as posições deles na imagem.

O TensorFlow oferece modelos pré-treinados e otimizados para dispositivos móveis que detectam objetos comuns, como carros, laranjas etc. É possível integrar esses modelos pré-treinados ao app para dispositivos móveis com apenas algumas linhas de código. No entanto, talvez você queira ou precise detectar objetos em categorias mais distintas ou incomuns. Isso requer a coleta das próprias imagens de treinamento, o treinamento e a implantação do próprio modelo de detecção de objetos.

TensorFlow Lite

O TensorFlow Lite é uma biblioteca de machine learning multiplataforma otimizada para executar modelos de machine learning em dispositivos de borda, incluindo dispositivos móveis Android e iOS.

O TensorFlow Lite é o mecanismo principal usado no Kit de ML para executar modelos de machine learning. O ecossistema do TensorFlow Lite tem dois componentes que facilitam o treinamento e a implantação de modelos de machine learning em dispositivos móveis:

  • O Model Maker é uma biblioteca Python que facilita o treinamento de modelos do TensorFlow Lite usando seus próprios dados com apenas algumas linhas de código, sem precisar de conhecimento em machine learning.
  • A Biblioteca de tarefas é uma biblioteca multiplataforma que facilita a implantação de modelos do TensorFlow Lite em apenas algumas linhas de código nos apps para dispositivos móveis.

Este codelab se concentra no TFLite. Conceitos e blocos de código que não são relevantes para o TFLite e a detecção de objetos não são explicados e são fornecidos para que você apenas os copie e cole.

3. Começar a configuração

Fazer o download do código

Clique no link abaixo para fazer o download de todo o código para este codelab:

Descompacte o arquivo ZIP transferido por download. Isso descompactará uma pasta raiz (odml-pathways-main) com todos os recursos necessários. Neste codelab, você só precisará das origens no subdiretório object-detection/codelab2/android.

O subdiretório android no repositório object-detection/codelab2/android contém dois diretórios:

  • android_studio_folder.pngstarter: o código inicial que você usará como base para este codelab.
  • android_studio_folder.pngfinal: o código concluído do app de exemplo finalizado.

Importar o app inicial

Vamos começar importando o app inicial para o Android Studio.

  1. Abra o Android Studio e selecione Import Project (Gradle, Eclipse ADT, etc.)
  2. Abra a pasta starter no código-fonte que você transferiu por download anteriormente.

7c0f27882a2698ac.png

Para garantir que todas as dependências estejam disponíveis para seu app, sincronize o projeto com arquivos do Gradle quando o processo de importação for concluído.

  1. Selecione Sync Project with Gradle Files ( b451ab2d04d835f9.png) na barra de ferramentas do Android Studio. Importe starter/app/build.gradle

Executar o app inicial

Agora que você importou o projeto para o Android Studio, está pronto para executar o app pela primeira vez.

Conecte o dispositivo Android via USB ao computador ou inicie o emulador do Android Studio e clique em Run ( execute.png) na barra de ferramentas do Android Studio.

4. Entender o app inicial

Para manter este codelab simples e focado nos bits de machine learning, o app inicial contém alguns códigos boilerplate que fazem algumas coisas para você:

  • Ele pode tirar fotos usando a câmera do dispositivo.
  • Ela contém algumas fotos de bancos de imagens para você testar a detecção de objetos em um Android Emulator.
  • Ela tem um método conveniente para desenhar o resultado da detecção de objetos no bitmap de entrada.

Você interagirá principalmente com estes métodos no esqueleto do app:

  • fun runObjectDetection(bitmap: Bitmap) Esse método é chamado quando você escolhe uma imagem predefinida ou tira uma foto. bitmap é a imagem de entrada para detecção de objetos. Mais adiante neste codelab, você adicionará um código de detecção de objetos a esse método.
  • data class DetectionResult(val boundingBoxes: Rect, val text: String): é uma classe de dados que representa um resultado de detecção de objetos para visualização. boundingBoxes é o retângulo em que o objeto está localizado, e text é a string de resultado da detecção a ser exibida com a caixa delimitadora do objeto.
  • fun drawDetectionResult(bitmap: Bitmap, detectionResults: List<DetectionResult>): Bitmap Esse método exibe os resultados da detecção de objetos no detectionResults na entrada bitmap e retorna a cópia modificada dele.

Veja um exemplo de saída do método utilitário drawDetectionResult.

f6b1e6dad726e129.png

5. Adicionar detecção de objetos no dispositivo

Agora, você criará um protótipo integrando um modelo TFLite pré-treinado que pode detectar objetos comuns no app inicial.

Fazer o download de um modelo pré-treinado do TFLite para detecção de objetos

Há vários modelos de detectores de objetos no TensorFlow Hub que você pode usar. Para este codelab, você fará o download do modelo de detecção de objetos Eficiência Lite, treinado no conjunto de dados COCO 2017, otimizado para TFLite e projetado para desempenho em CPU para dispositivos móveis e GPU e EdgeTPU.

Em seguida, use a biblioteca TFLite Task para integrar o modelo TFLite pré-treinado ao seu app inicial. A biblioteca de tarefas do TFLite facilita a integração de modelos de machine learning otimizados para dispositivos móveis a um app. Ele é compatível com muitos casos de uso conhecidos de machine learning, incluindo detecção de objetos, classificação de imagens e classificação de texto. Você pode carregar o modelo TFLite e executá-lo com apenas algumas linhas de código.

Adicionar o modelo ao app inicial

  1. Copie o modelo que você acabou de salvar para a pasta assets do app inicial. Você pode encontrar a pasta no painel de navegação Project do Android Studio.

c2609599b7d22641.png

  1. Nomeie o arquivo model.tflite.

c83e9397177c4561.png

Atualizar as dependências da biblioteca de tarefas de arquivos do Gradle

Acesse o arquivo app/build.gradle e adicione esta linha à configuração do dependencies:

implementation 'org.tensorflow:tensorflow-lite-task-vision:0.3.1'

Sincronizar seu projeto com arquivos do Gradle

Para garantir que todas as dependências estejam disponíveis para seu app, nesse ponto, você deve sincronizar seu projeto com arquivos do Gradle. Selecione Sync Project with Gradle Files ( b451ab2d04d835f9.png) na barra de ferramentas do Android Studio.

Se esse botão estiver desativado, importe apenas o inicializador/app/build.gradle, e não todo o repositório.

Configurar e executar a detecção de objetos no dispositivo em uma imagem

Há três etapas simples com três APIs para carregar e executar um modelo de detecção de objetos:

  • preparar uma imagem / um stream: TensorImage
  • crie um objeto detector: ObjectDetector
  • Conecte os dois objetos acima: detect(image)

Isso é feito dentro da função runObjectDetection(bitmap: Bitmap) no arquivo MainActivity.kt.

/**
* TFLite Object Detection Function
*/
private fun runObjectDetection(bitmap: Bitmap) {
    //TODO: Add object detection code here
}

No momento, a função está vazia. Siga as etapas abaixo para implementar o detector de objetos do TFLite. O Android Studio solicitará que você adicione as importações necessárias:

  • org.tensorflow.lite.support.image.TensorImage
  • org.tensorflow.lite.task.vision.detector.ObjectDetector

Criar objeto de imagem

As imagens que você usará para este codelab virão da câmera no dispositivo ou de imagens predefinidas que você selecionar na IU do app. A imagem de entrada é decodificada no formato Bitmap e transmitida para o método runObjectDetection.

O TFLite fornece uma API simples para criar um TensorImage a partir de Bitmap. Adicione o código abaixo à parte superior do runObjectDetection(bitmap:Bitmap):

// Step 1: create TFLite's TensorImage object
val image = TensorImage.fromBitmap(bitmap)

Criar uma instância do detector

A biblioteca de tarefas TFLite segue o padrão de design do Builder. Você passa a configuração para um builder e adquire um detector com base nele. Há várias opções para configurar, incluindo as de ajustar a sensibilidade do detector de objetos:

  • resultado máximo (o número máximo de objetos que o modelo deve detectar)
  • limite de pontuação (qual é a confiança do detector de objetos para retornar um objeto detectado)
  • lista de permissões/negação de rótulos (permitir/negar os objetos em uma lista predefinida)

Inicialize a instância do detector de objetos especificando o nome do arquivo de modelo do TFLite e as opções de configuração:

// Step 2: Initialize the detector object
val options = ObjectDetector.ObjectDetectorOptions.builder()
    .setMaxResults(5)
    .setScoreThreshold(0.5f)
    .build()
val detector = ObjectDetector.createFromFileAndOptions(
    this, // the application context
    "model.tflite", // must be same as the filename in assets folder
    options
)

Feed de imagens para o detector

Adicione o seguinte código a fun runObjectDetection(bitmap:Bitmap). Isso alimentará suas imagens para o detector.

// Step 3: feed given image to the model and print the detection result
val results = detector.detect(image)

Após a conclusão, o detector retornará uma lista de Detection, cada um contendo informações sobre um objeto que o modelo encontrou na imagem. Cada objeto é descrito com:

  • boundingBox: o retângulo que declara a presença de um objeto e o local dele na imagem
  • categories: o tipo de objeto e a confiança do modelo no resultado da detecção. O modelo retorna várias categorias, e a mais confiável é a primeira.
  • label: o nome da categoria de objeto.
  • classificationConfidence:uma vírgula flutuando de 0,0 a 1,0, em que 1,0 representa 100%

Adicione o seguinte código a fun runObjectDetection(bitmap:Bitmap). Esse método chama um método para exibir os resultados da detecção de objetos no Logcat.

// Step 4: Parse the detection result and show it
debugPrint(results)

Em seguida, adicione este método debugPrint() à classe MainActivity:

private fun debugPrint(results : List<Detection>) {
    for ((i, obj) in results.withIndex()) {
        val box = obj.boundingBox

        Log.d(TAG, "Detected object: ${i} ")
        Log.d(TAG, "  boundingBox: (${box.left}, ${box.top}) - (${box.right},${box.bottom})")

        for ((j, category) in obj.categories.withIndex()) {
            Log.d(TAG, "    Label $j: ${category.label}")
            val confidence: Int = category.score.times(100).toInt()
            Log.d(TAG, "    Confidence: ${confidence}%")
        }
    }
}

Agora, o detector de objetos está pronto! Compile e execute o app clicando em Run ( execute.png) na barra de ferramentas do Android Studio. Quando o app aparecer no dispositivo, toque em qualquer uma das imagens predefinidas para iniciar o detector de objetos. Em seguida, observe a janela Logcat*(*) 16bd6ea224cf8cf1.png.*)* no ambiente de desenvolvimento integrado, e você verá algo parecido com isto:

D/TFLite-ODT: Detected object: 0
D/TFLite-ODT:   boundingBox: (0.0, 15.0) - (2223.0,1645.0)
D/TFLite-ODT:     Label 0: dining table
D/TFLite-ODT:     Confidence: 77%
D/TFLite-ODT: Detected object: 1
D/TFLite-ODT:   boundingBox: (702.0, 3.0) - (1234.0,797.0)
D/TFLite-ODT:     Label 0: cup
D/TFLite-ODT:     Confidence: 69%

Isso informa que o detector detectou dois objetos. A primeira é:

  • Um objeto está dentro do retângulo de (0, 15) a (2223, 1645)
  • O rótulo é tabela de jantar
  • o modelo tem certeza de que a primeira é uma tabela de refeições (77%);

Tecnicamente, isso é tudo que você precisa para fazer a biblioteca de tarefas do TFLite funcionar: você tem tudo isso no momento. Parabéns!

No entanto, no lado da IU, você ainda está no ponto de partida. Agora você precisa usar os resultados detectados na IU após o processamento.

6. Desenhar o resultado da detecção na imagem de entrada

Nas etapas anteriores, você exibiu o resultado da detecção em logcat: simples e rápido. Nesta etapa, você usará o método utilitário já implementado no app inicial para:

  • desenhar uma caixa delimitadora em uma imagem
  • desenhar um nome de categoria e uma porcentagem de confiança dentro da caixa delimitadora
  1. Substitua a chamada debugPrint(results) pelo snippet de código a seguir:
val resultToDisplay = results.map {
    // Get the top-1 category and craft the display text
    val category = it.categories.first()
    val text = "${category.label}, ${category.score.times(100).toInt()}%"

    // Create a data object to display the detection result
    DetectionResult(it.boundingBox, text)
}
// Draw the detection result on the bitmap and show it.
val imgWithResult = drawDetectionResult(bitmap, resultToDisplay)
runOnUiThread {
    inputImageView.setImageBitmap(imgWithResult)
}
  1. Agora, clique em Run ( execute.png) na barra de ferramentas do Android Studio.
  2. Depois que o app for carregado, toque em uma das imagens predefinidas para ver o resultado da detecção.

Quer tentar com sua própria foto? Toque no botão Tirar foto e tire algumas fotos de objetos ao seu redor.

8b024362b15096a6.png

7. Treinar um modelo de detecção de objetos personalizado

Na etapa anterior, você integrou um modelo pré-treinado do TFLite ao app Android e viu que pode detectar objetos comuns, como tigelas ou mesas de jantar, em imagens de amostra. No entanto, seu objetivo é detectar os ingredientes dos pratos na imagem, por isso a detecção geral de objetos não é adequada ao seu caso de uso. Você quer treinar um modelo personalizado de detecção de objetos usando um conjunto de dados de treinamento com os ingredientes que queremos detectar.

Veja um conjunto de dados com imagens e rótulos que podem ser usados para treinar seu próprio modelo personalizado. Ele foi criado com base em imagens do Open Images Dataset V4.

Colaboratory

Agora vamos acessar o Google Colab para treinar o modelo personalizado.

O treinamento do modelo personalizado levará cerca de 30 minutos.

Se você estiver com pressa, poderá fazer o download de um modelo que pré-treinamos para você no conjunto de dados fornecido e avançar para a próxima etapa.

8. Integrar o modelo TFLite personalizado ao app Android

Agora que você treinou um modelo de detecção de salada, integre-o e transforme seu app de um detector de objetos comum para um detector de salada especificamente.

  1. Copie o modelo de salada TFLite para a pasta assets. Nomeie o novo modelo como salad.tflite.

91e8d37c4f78eddb.png

  1. Abra o arquivo MainActivity.kt e localize o código de inicialização ObjectDetector.
  2. Substitua o modelo eficiente Det-Lite (model.tflite) pelo modelo de salada (salad.tflite)
val detector = ObjectDetector.createFromFileAndOptions(
    this, // the application context
    "salad.tflite", // must be same as the filename in assets folder
    options
)
  1. Clique em Run ( execute.png) na barra de ferramentas do Android Studio para executar o app novamente com o novo modelo. Voilà! Agora o app pode reconhecer queijos, saladas e assados.

b9705235366ae162.png

9. Parabéns!

Você usou o TFLite para treinar um modelo personalizado e adicionar recursos de detecção de objetos ao app. Isso é tudo o que você precisa para começar a usar.

O que vimos

  • Como encontrar modelos de detecção de objetos TFLite pré-treinados no TensorFlow Hub
  • Como integrar modelos de detecção de objeções ao app Android usando a biblioteca de tarefas TFLite
  • Como treinar o modelo personalizado de detecção de objetos com o TFLite Model Maker

Próximas etapas

  • Usar o Firebase para aprimorar a implantação do modelo TFLite
  • Colete dados de treinamento para treinar seu próprio modelo
  • Aplicar a detecção de objetos no seu próprio app Android

Saiba mais