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 aprendizado de máquina do Google para apps Android e iOS. Você pode usar as APIs Vision e Natural Language para resolver desafios comuns nos seus apps ou criar novas experiências de usuário. Todas elas usam a tecnologia dos melhores modelos de ML do Google e são oferecidas a você sem custo financeiro.

Todas as APIs do Kit de ML são executadas no dispositivo, o que permite casos de uso em tempo real em que você quer processar uma transmissão de 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 detecção e rastreamento de objetos (ODT, na sigla em inglês) a uma determinada imagem ao seu app Android. Este codelab usa alguns atalhos para destacar o uso de ODT do kit de ML.

O que você vai criar

Neste codelab, você criará um app Android com o Kit de ML. Seu app vai usar a API ML Kit Object Detection and Tracking para detectar objetos em uma determinada imagem.No final, você vai encontrar algo semelhante à imagem à direita.

O que você vai aprender

  • Como integrar o SDK do kit de ML ao seu aplicativo Android
  • API ML Kit Object Detection and Tracking

O que é necessário

  • Uma versão recente do Android Studio (v4.1.2+)
  • Emulador do Android Studio ou um dispositivo Android físico
  • Código de amostra
  • Conhecimento básico de desenvolvimento para 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ê precisará apenas das origens no subdiretório object-detection.

O subdiretório de detecção de objetos no repositório mlkit-android contém dois diretórios:

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

3. Adicionar a API ML Kit Object Detection and Tracking 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 para detecção e rastreamento de objetos do Kit de ML

As dependências do Kit de ML permitem que você integre o SDK ODT do kit de ML ao seu app. Adicione as linhas abaixo ao final do arquivo app/build.gradle do seu projeto:

build.gradle

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

Sincronizar seu projeto com arquivos do Gradle

Para garantir que todas as dependências estejam disponíveis para o app, sincronize o projeto com os 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 , e 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 para detecção e rastreamento de objetos do kit de ML, já pode executar o app pela primeira vez.

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

Executar e conhecer o app

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

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

  • abra o app de câmera integrado ao dispositivo/emulador
  • tirar uma foto dentro do app de 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, aceitar a foto e observe-a ser exibida dentro do app inicial.

Repita algumas vezes para ver como funciona:

9ec541980dbe2d31.png 8312dde41425ba4b.png fa8492bfc1914ff0.png

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

Selecione uma das três imagens predefinidas. Observe que a imagem aparece em uma 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 código boilerplate para tirar fotos com o app de câmera do dispositivo. Há também três imagens predefinidas no app que você pode testar na detecção de objetos se estiver executando o codelab em um Android Emulator.

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

Nesta etapa, você vai adicionar código ao método runObjectDetection para detectar 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 a ODT do Kit de ML:

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

É possível fazer isso dentro da 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. Siga as etapas a seguir para implementar a ODT do Kit de ML. Ao longo do caminho, o Android Studio solicitará 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 um InputImage usando um Bitmap. Em seguida, é possível alimentar um InputImage nas 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 superior do runObjectDetection(bitmap:Bitmap).

Etapa 2: criar uma instância de detector

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

  • modo detector (imagem única ou stream)
  • o modo de detecção (detecção de um ou múltiplos objetos)
  • modo de classificação (ativado ou desativado)

Este codelab é para uma imagem - detecção de vários objetos e classificação. Adicione 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: enviar imagens do feed para o detector

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

  • Você envia uma imagem para o detector (via process()).
  • O Detector funciona bastante nisso.
  • O detector relata o resultado a você por meio de um callback.

O código abaixo faz exatamente isso (copie e anexe o código ao código já 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 que você usa para rastreá-lo entre frames (NÃO é usado neste codelab).
  • boundingBox: caixa delimitadora do objeto.
  • labels: uma lista de rótulos do objeto detectado (somente quando a classificação está ativada):
  • index (receba o índice deste rótulo)
  • text (Use o texto desse rótulo, incluindo "Artigos de moda", "Comida", "Artigos para casa", "Local", "Planta")
  • confidence ( um ponto flutuante entre 0,0 e 1,0 com 1,0 significa 100%)

Você provavelmente percebeu que o código faz um tipo de processamento de 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 está tudo pronto para aceitar imagens para detecção.

Para executar o codelab, clique em Run ( execute.png) na barra de ferramentas do Android Studio. Selecione uma imagem predefinida ou tire uma foto e olhe para a janela do 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

Isso significa que o detector detectou três objetos:

  • As categorias são Comida e Casa boa.
  • Nenhuma categoria é retornada para a segunda porque se trata de uma classe desconhecida.
  • Sem 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 tem certeza de que o primeiro é um Comida (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ê já sabe tudo! 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. O 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
  • desenhe o nome da categoria e a confiança dentro da caixa delimitadora

Noções básicas sobre os utilitários de visualização

Há um código boilerplate no codelab para ajudar você a visualizar o resultado da detecção. Use estes utilitários para simplificar o código de visualização:

  • data class BoxWithText(val box: Rect, val text: String) Esta é uma classe de dados para armazenar um resultado da detecção de um objeto para visualização. box é a caixa delimitadora em que o objeto é 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<BoxWithText>): Bitmap Esse método desenha os resultados da detecção de objetos em detectionResults na entrada bitmap e retorna a cópia modificada dele.

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.

Vá até o local onde 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)
}
  • Para começar, analise o DetectedObject do Kit de ML e crie uma lista de objetos BoxWithText para exibir 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 o mostre na tela.

Executar

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

Quando 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 Câmera) ou toque facilmente em qualquer imagem predefinida. Os resultados da detecção serão exibidos. pressione o botão novamente ou selecione outra imagem para repetir algumas vezes e acessar a 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 ao detector

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

À medida que você prossegue, talvez queira melhorar o modelo: como você pode notar que o modelo padrão só reconhece cinco categorias, o modelo nem mesmo conhece faca, garfo e garrafa. Confira o outro codelab no nosso Programa de treinamentos "Machine learning no dispositivo: detecção de objetos" para aprender a 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

Saiba mais