Detectar objetos em imagens com o Kit de ML: Android

1. Antes de começar

O Kit de ML é um SDK para dispositivos móveis que leva a experiência em machine learning no dispositivo do Google para apps Android e iOS. Você pode usar as APIs Vision e Natural Language, eficientes e fáceis de usar, para resolver desafios comuns nos seus apps ou criar novas experiências do usuário. Todas são baseadas nos melhores modelos de ML do Google e oferecidas sem custo financeiro.

As APIs do Kit de ML são executadas no dispositivo, permitindo casos de uso em tempo real em que você quer processar um stream da câmera ao vivo, por exemplo. Isso também significa que a funcionalidade está disponível off-line.

Este codelab mostra etapas simples para adicionar a detecção e o rastreamento de objetos (ODT, na sigla em inglês) para uma determinada imagem ao seu app Android. Observe que este codelab usa alguns atalhos para destacar o uso do ODT do Kit de ML.

O que você vai criar

Neste codelab, você vai criar um app Android com o Kit de ML. O app vai usar a API de detecção e rastreamento de objetos do Kit de ML para detectar objetos em uma determinada imagem.No final, você verá algo semelhante à imagem à direita.

O que você aprenderá

  • Como integrar o SDK do Kit de ML ao seu app Android
  • API de detecção e rastreamento de objetos do Kit de ML

O que é necessário

  • Uma versão recente do Android Studio (v4.1.2 ou mais recente)
  • Emulador do Android Studio ou um dispositivo Android físico
  • Exemplo de código
  • Conhecimento básico de desenvolvimento Android em Kotlin

Este codelab é focado no Kit de ML. Conceitos e blocos de códigos sem relevância não serão abordados. Eles são incluídos somente para você copiar e colar.

2. 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 vai descompactar uma pasta raiz (mlkit-android-main) com todos os recursos necessários. Para este codelab, você só vai precisar das fontes no subdiretório object-detection.

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

  • android_studio_folder.pngstarter : código inicial que você vai criar para este codelab.
  • android_studio_folder.pngfinal: código concluído do app de exemplo finalizado.

3. Adicionar a API de detecção e rastreamento de objetos do Kit de ML ao projeto

Importar o app para o Android Studio

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

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

7c0f27882a2698ac.png

Adicionar as dependências da detecção e rastreamento de objetos do Kit de ML

As dependências do Kit de ML permitem integrar o SDK de ODT do Kit de ML ao seu app. Adicione as seguintes linhas ao final do arquivo app/build.gradle do seu projeto:

build.gradle

dependencies {
  // ...
  implementation 'com.google.mlkit:object-detection:16.2.4'
}

Sincronizar o projeto com arquivos do Gradle

Para garantir que todas as dependências estejam disponíveis para o app, sincronize o projeto com arquivos do Gradle neste momento.

Selecione Sync Project with Gradle Files ( b451ab2d04d835f9.png) na barra de ferramentas do Android Studio.

(Se esse botão estiver desativado, importe apenas starter/app/build.gradle , não o repositório inteiro.)

4. Executar o app inicial

Agora que você importou o projeto para o Android Studio e adicionou as dependências da detecção e rastreamento de objetos do Kit de ML, já pode executar o app pela primeira vez.

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

Executar e explorar o app

O app será iniciado no dispositivo Android. Ele tem um código boilerplate que permite capturar uma foto ou selecionar uma imagem predefinida e transmiti-la para um pipeline de detecção e rastreamento de objetos que você vai criar neste codelab. Vamos conhecer um pouco o app antes de escrever o código.

Primeiro, há um botão ( c6d965d639c3646.png) na parte de baixo para:

  • abrir o app da câmera integrado ao dispositivo/emulador
  • tirar uma foto no app da câmera
  • receber a imagem capturada no app inicial
  • mostrar a imagem

Teste o botão Take photo, siga as instruções para tirar uma foto, aceite a foto e observe-a exibida no app inicial.

Repita algumas vezes para ver como funciona:

9ec541980dbe2d31.png 8312dde41425ba4b.png fa8492bfc1914ff0.png

Em segundo lugar, há três imagens predefinidas que você pode escolher. Você pode usar essas imagens mais tarde para testar o código de detecção de objetos se estiver executando em um emulador Android.

Selecione uma das três imagens predefinidas. Observe que a imagem aparece na visualização maior:

1dd41b3ec978f1d9.png

5. Adicionar detecção de objetos no dispositivo

Nesta etapa, você vai adicionar a funcionalidade ao app inicial para detectar objetos em imagens. Como você viu na etapa anterior, o app inicial contém um código boilerplate para tirar fotos com o app da câmera no dispositivo. Há também três imagens predefinidas no app que você pode testar a detecção de objetos se estiver executando o codelab em um emulador Android.

Quando você seleciona uma imagem, seja das imagens predefinidas ou tirando uma foto com o app da câmera, o código boilerplate decodifica essa imagem em uma instância Bitmap, mostra na tela e chama o método runObjectDetection com a imagem.

Nesta etapa, você vai adicionar código ao método runObjectDetection para fazer a detecção de objetos.

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

Há apenas três etapas simples com três APIs para configurar o ODT do Kit de ML:

  • preparar uma imagem: InputImage
  • criar um objeto detector: ObjectDetection.getClient(options)
  • conectar os dois objetos acima: process(image)

Você realiza essas ações na função runObjectDetection(bitmap: Bitmap) no arquivo MainActivity.kt.

/**
 * ML Kit Object Detection Function
 */
private fun runObjectDetection(bitmap: Bitmap) {
}

No momento, a função está vazia. Passe para as etapas a seguir para implementar o ODT do Kit de ML. Ao longo do caminho, o Android Studio vai pedir que você adicione as importações necessárias:

  • com.google.mlkit.vision.common.InputImage
  • com.google.mlkit.vision.objects.ObjectDetection
  • com.google.mlkit.vision.objects.defaults.ObjectDetectorOptions

Etapa 1: criar uma InputImage

O Kit de ML fornece uma API simples para criar uma InputImage de um Bitmap. Em seguida, você pode transmitir uma InputImage para as APIs do Kit de ML.

// Step 1: create ML Kit's InputImage object
val image = InputImage.fromBitmap(bitmap, 0)

Adicione o código acima à parte de cima de runObjectDetection(bitmap:Bitmap).

Etapa 2: criar uma instância do detector

O Kit de ML segue o padrão de design do builder. Você vai transmitir a configuração para o builder e, em seguida, adquirir um detector dele. Há três opções de configuração (as opções em negrito são usadas neste codelab):

  • modo de detector (imagem única ou transmissão)
  • modo de detecção (único ou múltiplo detecção de objetos)
  • modo de classificação (ativado ou desativado)

Este codelab é para detecção e classificação de vários objetos de imagem única. Adicione isso agora:

// Step 2: acquire detector object
val options = ObjectDetectorOptions.Builder()
   .setDetectorMode(ObjectDetectorOptions.SINGLE_IMAGE_MODE)
   .enableMultipleObjects()
   .enableClassification()
   .build()
val objectDetector = ObjectDetection.getClient(options)

Etapa 3: transmitir imagens ao detector

A detecção e classificação de objetos é um processamento assíncrono:

  • Você envia uma imagem para o detector (via process()).
  • O detector trabalha muito.
  • O detector informa o resultado de volta para você por um callback.

O código a seguir faz exatamente isso (copie e anexe ao código existente em fun runObjectDetection(bitmap:Bitmap)):

// Step 3: feed given image to detector and setup callback
objectDetector.process(image)
   .addOnSuccessListener {
       // Task completed successfully
        debugPrint(it)
   }
   .addOnFailureListener {
       // Task failed with an exception
       Log.e(TAG, it.message.toString())
   }

Após a conclusão, o detector notifica você com:

  • O número total de objetos detectados. Cada objeto detectado é descrito com:
  • trackingId: um número inteiro usado para rastrear quadros cruzados (NÃO usado neste codelab).
  • boundingBox: a caixa delimitadora do objeto.
  • labels: uma lista de rótulos para o objeto detectado (somente quando a classificação está ativada):
  • index (recebe o índice desse rótulo)
  • text (recebe o texto desse rótulo, incluindo "Fashion Goods", "Food", "Home Goods", "Place", "Plant")
  • confidence ( um ponto flutuante entre 0,0 e 1,0, com 1,0 significando 100%)

Você provavelmente percebeu que o código faz um tipo de processamento printf para o resultado detectado com debugPrint().

Adicione-o à classe MainActivity:

private fun debugPrint(detectedObjects: List<DetectedObject>) {
   detectedObjects.forEachIndexed { index, detectedObject ->
       val box = detectedObject.boundingBox

       Log.d(TAG, "Detected object: $index")
       Log.d(TAG, " trackingId: ${detectedObject.trackingId}")
       Log.d(TAG, " boundingBox: (${box.left}, ${box.top}) - (${box.right},${box.bottom})")
       detectedObject.labels.forEach {
           Log.d(TAG, " categories: ${it.text}")
           Log.d(TAG, " confidence: ${it.confidence}")
       }
   }
}

Agora você já pode aceitar imagens para detecção.

Vamos executar o codelab clicando em Run ( execute.png) na barra de ferramentas do Android Studio. Selecione uma imagem predefinida ou tire uma foto e, em seguida, observe a janela logcat( 16bd6ea224cf8cf1.png) no ambiente de desenvolvimento integrado.

Você verá algo como:

D/MLKit Object Detection: Detected object: 0
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (481, 2021) - (2426,3376)
D/MLKit Object Detection:  categories: Food
D/MLKit Object Detection:  confidence: 0.90234375
D/MLKit Object Detection: Detected object: 1
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (2639, 2633) - (3058,3577)
D/MLKit Object Detection: Detected object: 2
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (3, 1816) - (615,2597)
D/MLKit Object Detection:  categories: Home good
D/MLKit Object Detection:  confidence: 0.75390625

...o que significa que o detector viu três objetos:

  • As categorias são Food e Home good.
  • Nenhuma categoria é retornada para a segunda porque é uma classe desconhecida.
  • Nenhum trackingId (porque esse é o modo de detecção de imagem única).
  • A posição dentro do retângulo boundingBox (por exemplo, (481, 2021) – (2426, 3376))
  • O detector está bastante confiante de que o primeiro é um Food (90% de confiança—era salada).

Tecnicamente, isso é tudo o que você precisa para que a detecção de objetos do Kit de ML funcione: você tem tudo neste momento. Parabéns!

No lado da interface, você ainda está no estágio em que começou, mas pode usar os resultados detectados na interface, como desenhar a caixa delimitadora para criar uma experiência melhor. Vamos para a próxima etapa: pós-processar os resultados detectados.

6. Pós-processamento dos resultados da detecção

Nas etapas anteriores, você imprimiu o resultado detectado no logcat: simples e rápido.

Nesta seção, você vai usar o resultado na imagem:

  • desenhar a caixa delimitadora na imagem
  • desenhar o nome da categoria e a confiança dentro da caixa delimitadora

Entender os utilitários de visualização

Há um código boilerplate no codelab para ajudar a visualizar o resultado da detecção. Aproveite esses utilitários para simplificar nosso código de visualização:

  • data class BoxWithText(val box: Rect, val text: String): essa é uma classe de dados para armazenar um resultado de detecção de objetos para visualização. box é a caixa delimitadora em que o objeto está localizado, e text é a string de resultado da detecção a ser exibida junto com a caixa delimitadora do objeto.
  • fun drawDetectionResult(bitmap: Bitmap, detectionResults: List<BoxWithText>): Bitmap Esse método desenha os resultados da detecção de objetos em detectionResults na bitmap de entrada e retorna a cópia modificada dela.

Confira um exemplo de saída do método utilitário drawDetectionResult:

58c6f1d4ddb00dfa.png

Visualizar o resultado da detecção do Kit de ML

Use os utilitários de visualização para desenhar o resultado da detecção de objetos do Kit de ML na imagem de entrada.

Acesse o local em que você chama debugPrint() e adicione o seguinte snippet de código abaixo dele:

// Parse ML Kit's DetectedObject and create corresponding visualization data
val detectedObjects = it.map { obj ->
    var text = "Unknown"

    // We will show the top confident detection result if it exist
    if (obj.labels.isNotEmpty()) {
        val firstLabel = obj.labels.first()
        text = "${firstLabel.text}, ${firstLabel.confidence.times(100).toInt()}%"
    }
    BoxWithText(obj.boundingBox, text)
}

// Draw the detection result on the input bitmap
val visualizedResult = drawDetectionResult(bitmap, detectedObjects)

// Show the detection result on the app screen
runOnUiThread {
    inputImageView.setImageBitmap(visualizedResult)
}
  • Comece analisando o DetectedObject do Kit de ML e criando uma lista de objetos BoxWithText para mostrar o resultado da visualização.
  • Em seguida, desenhe o resultado da detecção na imagem de entrada usando o método utilitário drawDetectionResult e mostre-o na tela.

Executar

Agora clique em Run ( execute.png) na barra de ferramentas do Android Studio.

Depois que o app for carregado, pressione o botão com o ícone da câmera, aponte a câmera para um objeto, tire uma foto, aceite a foto (no app da câmera) ou toque em qualquer imagem predefinida. Você verá os resultados da detecção. Pressione o botão novamente ou selecione outra imagem para repetir algumas vezes e experimentar o ODT mais recente do Kit de ML.

a03109cb30d5014d.png

7. Parabéns!

Você usou o Kit de ML para adicionar recursos de detecção de objetos ao seu app:

  • 3 etapas com 3 APIs
  • Criar imagem de entrada
  • Criar detector
  • Enviar imagem para o detector

Isso é tudo o que você precisa para começar a usar.

À medida que você avança, talvez queira melhorar o modelo. Como você pode ver, o modelo padrão só pode reconhecer cinco categorias. O modelo nem sequer conhece faca, garfo e garrafa. Confira o outro codelab no nosso programa de cursos de machine learning no dispositivo: detecção de objetos para saber como treinar um modelo personalizado.

O que vimos

  • Como adicionar a detecção e o rastreamento de objetos do Kit de ML ao seu app Android
  • Como usar a detecção e o rastreamento de objetos no dispositivo no Kit de ML para detectar objetos em imagens

Próximas etapas

  • Descoberta avançada com o ODT do Kit de ML com mais imagens e vídeo ao vivo para experimentar a precisão e o desempenho da detecção e classificação
  • Confira o programa de cursos de machine learning no dispositivo: detecção de objetos para saber como treinar um modelo personalizado
  • Aplicar o ODT do Kit de ML no seu próprio app Android

Saiba mais