Detecta objetos en imágenes con el Kit de AA: Android

1. Antes de comenzar

El Kit de AA es un SDK para dispositivos móviles que lleva la experiencia de Google en el aprendizaje automático de los dispositivos a las apps para iOS y Android. Puedes usar las API de Vision y Natural Language para resolver desafíos comunes en tus apps o crear experiencias del usuario completamente nuevas. Todos cuentan con la tecnología de los mejores modelos de AA de Google y se ofrecen sin costo.

Todas las API del Kit de AA se ejecutan en el dispositivo, lo que permite casos de uso en tiempo real en los que quieres, por ejemplo, procesar una transmisión de cámara en vivo. Esto también significa que la funcionalidad está disponible sin conexión.

En este codelab, te guiaremos por pasos simples que te permitirán agregar la detección y el seguimiento de objetos (ODT) de una imagen determinada a tu app para Android existente. Ten en cuenta que este codelab usa algunas combinaciones de teclas para destacar el uso del ODT del Kit de AA.

Qué compilarás

En este codelab, compilarás una app para Android con el Kit de AA. Tu app usará la API de detección y seguimiento de objetos del Kit de AA para detectar objetos en una imagen determinada.Al final, deberías ver algo similar a la imagen que se muestra a la derecha.

Qué aprenderá

  • Cómo integrar el SDK del Kit de AA en tu aplicación para Android
  • API de detección y seguimiento de objetos del Kit de AA

Requisitos

  • Una versión reciente de Android Studio (v4.1.2 o posterior)
  • Android Studio Emulator o un dispositivo Android físico
  • El código de muestra
  • Conocimientos básicos sobre el desarrollo para Android en Kotlin

Este codelab está enfocado en el Kit de AA. Los conceptos que no son relevantes y los bloques de código se pasan por alto y se te brindan para que solo copies y pegues.

2. Prepárate

Descarga el código

Haz clic en el siguiente vínculo a fin de descargar todo el código de este codelab:

Descargar código fuente

Descomprime el archivo zip descargado. Esto descomprimirá una carpeta raíz (mlkit-android-main) con todos los recursos que necesitarás. Para este codelab, solo necesitarás las fuentes del subdirectorio object-detection.

El subdirectorio de detección de objetos del repositorio mlkit-android contiene los siguientes dos directorios:

  • android_studio_folder.pngstarter: Código inicial en el que se basa este codelab.
  • android_studio_folder.pngfinal: Código completo para la app de muestra finalizada.

3. Agregar la API de detección y seguimiento de objetos del Kit de AA al proyecto

Importa la app a Android Studio

Para comenzar, importa la app de inicio a Android Studio.

Abre Android Studio, selecciona Import Project (Gradle, Eclipse ADT, etc.) y elige la carpeta starter del código fuente que descargaste antes.

7c0f27882a2698ac.png

Agrega las dependencias para la detección y el seguimiento de objetos del Kit de AA

Las dependencias del Kit de AA te permiten integrar el SDK de ODT del Kit de AA en tu app. Agrega las siguientes líneas al final del archivo app/build.gradle de tu proyecto:

build.gradle

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

Cómo sincronizar tu proyecto con archivos de Gradle

A fin de asegurarte de que todas las dependencias estén disponibles para tu app, en este momento, debes sincronizar tu proyecto con archivos de Gradle.

En la barra de herramientas de Android Studio, selecciona Sync Project with Gradle Files ( b451ab2d04d835f9.png).

(Si se inhabilita este botón, importe únicamentestarter/app/build.gradle , no todo el repositorio).

4. Ejecuta la app de inicio

Ahora que importaste el proyecto a Android Studio y agregaste las dependencias para la detección y el seguimiento de objetos del Kit de AA, ya puedes ejecutar la app por primera vez.

Conecta tu dispositivo Android mediante USB a tu host o Inicia el emulador de Android Studio y haz clic en Ejecutar ( execute.png) en la barra de herramientas de Android Studio.

Cómo ejecutar y explorar la app

La app debe iniciarse en el dispositivo Android. Tiene código estándar para permitirte capturar una foto, o seleccionar una imagen predeterminada y enviarla a una canalización de detección y seguimiento de objetos que compilarás en este codelab. Exploremos la app un poco antes de escribir el código.

Primero, hay un botón ( c6d965d639c3646.png) en la parte inferior para hacer lo siguiente:

  • Abre la aplicación de la cámara integrada en tu dispositivo o emulador.
  • toma una foto en la app de la cámara
  • recibir la imagen capturada en la aplicación de inicio
  • mostrar la imagen

Prueba el botón Tomar una foto, sigue las indicaciones para tomar una foto, acepta la foto y observa que se muestra dentro de la aplicación de inicio.

Repita esto varias veces para ver cómo funciona:

9ec541980dbe2d31.png 8312dde41425ba4b.png fa8492bfc1914ff0.png

En segundo lugar, hay 3 imágenes predeterminadas que puedes elegir. Puedes usar estas imágenes más adelante para probar el código de detección de objetos si estás ejecutando en Android Emulator.

Selecciona una de las 3 imágenes predeterminadas. Observa que la imagen aparezca en la vista más grande:

1dd41b3ec978f1d9.png

5. Cómo agregar la detección de objetos en el dispositivo

En este paso, agregarás la funcionalidad a la app de inicio para detectar objetos en imágenes. Como viste en el paso anterior, la app de inicio contiene código estándar para tomar fotos con la app de cámara del dispositivo. También hay 3 imágenes predeterminadas en la app que puedes probar con la detección de objetos si ejecutas el codelab en un emulador de Android.

Cuando seleccionas una imagen de la imagen predeterminada o tomas una foto con la app de la cámara, el código estándar decodifica esa imagen en una instancia de Bitmap, la muestra en la pantalla y llama al método runObjectDetection con el imagen.

En este paso, agregarás código al método runObjectDetection para realizar la detección de objetos.

Cómo configurar y ejecutar la detección de objetos en el dispositivo en una imagen

Existen 3 pasos sencillos con 3 API para configurar el ODT del Kit de AA:

  • prepara una imagen: InputImage
  • crea un objeto detector: ObjectDetection.getClient(options)
  • conecta los 2 objetos anteriores: process(image)

Esto se logra dentro de la función runObjectDetection(bitmap: Bitmap) en el archivo MainActivity.kt.

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

En este momento, la función está vacía. Sigue los pasos que se indican a continuación para implementar el ODT del Kit de AA. Durante el proceso, Android Studio te solicitará que agregues las importaciones necesarias:

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

Paso 1: Crea una InputImage

El Kit de AA proporciona una API simple para crear un objeto InputImage a partir de un Bitmap. Luego, puedes ingresar un InputImage a las API del Kit de AA.

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

Agrega el código anterior en la parte superior de runObjectDetection(bitmap:Bitmap).

Paso 2: Crea una instancia de detector

El Kit de AA sigue el patrón de diseño compilador. Pasarás la configuración al compilador y, luego, adquirirás un detector a partir de ella. Hay 3 opciones que debes configurar (las opciones en negrita se usan en este codelab):

  • modo de detector (imagen única o transmisión)
  • modo de detección (detección de objeto única o múltiples )
  • modo de clasificación (activado o desactivado)

Este codelab es para una sola imagen: detección y clasificación de varios objetos. Agrégalo ahora:

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

Paso 3: Feed las imágenes al detector

La detección y clasificación de objetos es un procesamiento asíncrono:

  • Envías una imagen al detector (a través de process()).
  • El detector funciona bastante bien.
  • El detector informa el resultado a través de una devolución de llamada.

El siguiente código hace precisamente eso (cópialo y agrégalo al código existente dentro de 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())
   }

Cuando finalice, el detector te notificará con lo siguiente:

  • La cantidad total de objetos detectados. Cada objeto detectado se describe de la siguiente manera:
  • trackingId: Es un valor entero que se usa para realizar un seguimiento de los fotogramas cruzados (NO se usa en este codelab).
  • boundingBox: Es el cuadro de límite del objeto.
  • labels: una lista de etiquetas para el objeto detectado (solo cuando la clasificación está habilitada):
  • index (Obtener el índice de esta etiqueta)
  • text (Obtenga el texto de esta etiqueta, incluidos "Artículos de moda", "Comidas", "Artículos para el hogar", "Lugar", "Plantas")
  • confidence ( un número de punto flotante entre 0.0 y 1.0 con 1.0 significa 100%)

Es probable que hayas notado que el código realiza un tipo de procesamiento printf para el resultado detectado con debugPrint().

Agrégalo en la clase 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}")
       }
   }
}

Ahora, estás listo para aceptar imágenes y detectarlas.

Para ejecutar el codelab, haz clic en Run ( execute.png) en la barra de herramientas de Android Studio. Intenta seleccionar una imagen predeterminada o toma una foto y luego observa la ventana de logcat(16bd6ea224cf8cf1.png) dentro del IDE.

Deberías ver un resultado similar a este:

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

Esto significa que el detector detectó 3 objetos:

  • Las categorías son Comida y Bueno para el hogar.
  • No se muestra ninguna categoría para la segunda porque es una clase desconocida.
  • No hay trackingId (porque este es el modo de detección de una sola imagen).
  • La posición dentro del rectángulo boundingBox (p.ej., (481, 2021) - (2426, 3376))
  • El detector está bastante seguro de que el primero es Food (90% de confianza: era ensalada).

Técnicamente, eso es todo lo que necesita para que la detección de objetos del Kit de AA funcione. ¡Puede lograrlo! ¡Felicitaciones!

En el lado de la IU, todavía estás en la etapa de inicio, pero puedes usar los resultados detectados en la IU, como dibujar el cuadro de límite para crear una mejor experiencia. Pasemos al siguiente paso, posterior al proceso los resultados detectados

6. Posprocesamiento de los resultados de detección

En pasos anteriores, imprimes el resultado detectado en logcat: simple y rápido.

En esta sección, usarás el resultado en la imagen:

  • dibujar el cuadro de límite en la imagen
  • dibujar el nombre de la categoría y la confianza dentro del cuadro de límite

Información sobre las utilidades de visualización

Hay código estándar dentro del codelab que te ayudará a visualizar el resultado de la detección. Aprovecha estas utilidades para simplificar nuestro código de visualización:

  • data class BoxWithText(val box: Rect, val text: String) Esta es una clase de datos a fin de almacenar un resultado de detección de objetos para su visualización. box es el cuadro de límite en el que se ubica el objeto, y text es la string de resultado de detección que se mostrará junto con el cuadro de límite del objeto.
  • fun drawDetectionResult(bitmap: Bitmap, detectionResults: List<BoxWithText>): Bitmap Este método dibuja los resultados de la detección de objetos en detectionResults en la entrada bitmap y muestra la copia modificada.

Este es un ejemplo de un resultado del método de utilidad drawDetectionResult:

58c6f1d4ddb00dfa.png

Visualizar el resultado de detección del Kit de AA

Usa las utilidades de visualización para dibujar el resultado de la detección de objetos del Kit de AA sobre la imagen de entrada.

Ve a donde llamas a debugPrint() y agrega el siguiente fragmento de código:

// 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 comenzar, analiza el DetectedObject del Kit de AA y crea una lista de objetos BoxWithText a fin de mostrar el resultado de visualización.
  • Luego, dibuja el resultado de la detección sobre la imagen de entrada con el método de utilidad drawDetectionResult y muéstralo en la pantalla.

Ejecuta el código

Ahora, haz clic en Run ( execute.png) en la barra de herramientas de Android Studio.

Una vez que se cargue la app, presiona el botón con el ícono de la cámara, apunta la cámara a un objeto, toma una foto o acepta la foto (en la app de Cámara) o puedes presionar fácilmente cualquier imagen predeterminada. Deberías ver los resultados de la detección. vuelve a presionar el botón o selecciona otra imagen para repetir un par de veces a fin de disfrutar la versión más reciente del Kit de AA.

a03109cb30d5014d.png

7. ¡Felicitaciones!

Usaste el Kit de AA para agregar capacidades de detección de objetos a la app:

  • 3 pasos con 3 API
  • Crear imagen de entrada
  • Crear detector
  • Enviar imagen al detector

¡Eso es todo lo que necesitas para ponerte en marcha!

A medida que avanzas, es posible que desees mejorar el modelo, ya que puedes ver que el modelo predeterminado solo puede reconocer 5 categorías: el modelo ni siquiera conoce un cuchillo, un tenedor y una botella. Consulta el otro codelab de nuestra ruta de aprendizaje de Aprendizaje automático en el dispositivo: Detección de objetos para obtener información sobre cómo entrenar un modelo personalizado.

Temas abordados

  • Cómo agregar la detección y el seguimiento de objetos del Kit de AA a tu app para Android
  • Cómo usar la detección y el seguimiento de objetos en el dispositivo con el Kit de AA para detectar objetos en imágenes

Próximos pasos

  • Explora más con ML Kit ODT con más imágenes y video en vivo para experimentar la detección y clasificación del rendimiento y la clasificación
  • Revisa el aprendizaje automático en el dispositivo: Ruta de aprendizaje de detección de objetos para aprender a entrenar un modelo personalizado.
  • Aplicar el ODT del Kit de AA en tu propia app para Android

Más información