Detecta objetos en imágenes con ML Kit: 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 en el dispositivo a las apps para iOS y Android. Puedes usar las APIs potentes pero fáciles de usar de Vision y Natural Language para resolver desafíos comunes en tus apps o crear experiencias del usuario totalmente nuevas. Todos cuentan con la tecnología de los mejores modelos de AA de Google y se ofrecen sin costo.

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

En este codelab, te explicaremos pasos sencillos 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 en este codelab se usan algunas combinaciones de teclas para destacar el uso de la ODT del ML Kit.

Qué compilarás

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

Qué aprenderás

  • Cómo integrar el SDK del ML Kit 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 y versiones posteriores)
  • Android Studio Emulator o un dispositivo Android físico
  • El código de muestra
  • Conocimientos básicos sobre el desarrollo de Android en Kotlin

Este codelab se enfoca en el ML Kit. Los conceptos y los bloques de código no relevantes se pasan por alto y se proporcionan para que simplemente los 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:

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

El subdirectorio de detección de objetos en el repositorio mlkit-android contiene 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 ejemplo finalizada

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

Importa la app a Android Studio

Comencemos por importar la app de partida 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.

8c0f27882a2698ac.png

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

Las dependencias del ML Kit te permiten integrar el SDK de ODT del ML Kit 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'
}

Sincroniza tu proyecto con archivos de Gradle

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

Selecciona Sync Project with Gradle Files ( b451ab2d04d835f9.png) en la barra de herramientas de Android Studio.

(Si este botón está inhabilitado, asegúrate de importar solo starter/app/build.gradle , no el repositorio completo).

4. Ejecuta la app de partida

Ahora que importaste el proyecto a Android Studio y agregaste las dependencias para la detección y el seguimiento de objetos del ML Kit, 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 Run ( execute.png) en la barra de herramientas de Android Studio.

Ejecuta y explora la app

La app debería iniciarse en tu dispositivo Android. Tiene código estándar que te permite 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.

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

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

Prueba el botón Tomar foto, sigue las indicaciones para tomar una foto, aceptala y observa cómo se muestra dentro de la app de inicio.

Repite el proceso varias veces para ver cómo funciona:

9ec541980dbe2d31.png 8312dde41425ba4b.png fa8492bfc1914ff0.png

En segundo lugar, existen 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 ejecutas un emulador de Android.

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

1dd41b3ec978f1d9.png

5. Agrega la detección de objetos en el dispositivo

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

Cuando seleccionas una imagen, ya sea de las imágenes preestablecidas o de tomar una foto con la app de 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 la imagen.

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

Configura y ejecuta la detección de objetos en el dispositivo en una imagen

Para configurar la ODT del ML Kit, solo hay 3 pasos sencillos con 3 APIs:

  • preparar 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. Continúa con los siguientes pasos para implementar la ODT del ML Kit. 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 InputImage a partir de un Bitmap. Luego, puedes ingresar un InputImage en las APIs del ML Kit.

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

Agrega el código anterior a 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 de Builder. Pasarás la configuración al compilador y, luego, adquirirás un detector. Existen 3 opciones que puedes configurar (en este codelab, se usan las que aparecen en negrita):

  • modo detector (imagen única o transmisión)
  • modo de detección (detección de un solo objeto o varios objetos)
  • modo de clasificación (activado o desactivado)

Este codelab es para una sola imagen, la detección de varios objetos y clasificación. Agrégala 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: Envía 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 se esfuerza bastante en esto.
  • que te informará el resultado mediante 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 con lo siguiente:
  • trackingId: Es un número entero que usas para hacerle un seguimiento entre fotogramas (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 (obtén el índice de esta etiqueta)
  • text (obtén el texto de esta etiqueta, incluido "Artículos de moda", "Comida", "Artículos para el hogar", "Lugar", "Planta")
  • 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 de printf para el resultado detectado con debugPrint().

Agrégala a 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}")
       }
   }
}

Ya está todo listo para que aceptes imágenes para la detección.

Para ejecutar el codelab, haz clic en Run ( execute.png) en la barra de herramientas de Android Studio. Selecciona una imagen predeterminada o toma una foto. Luego, observa la ventana de logcat( 16bd6ea224cf8cf1.png) en el 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

...lo que significa que el detector vio 3 objetos:

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

Técnicamente, eso es todo lo que necesitas para hacer que la detección de objetos del ML Kit funcione. ¡Ya puedes hacerlo! ¡Felicitaciones!

En el lado de la IU, todavía estás en la etapa cuando comenzaste, pero puedes usar los resultados detectados en la IU, como dibujar el cuadro delimitador para crear una mejor experiencia. Pasemos al siguiente paso: ¡procesa posteriormente los resultados detectados!

6. Procesamiento posterior de los resultados de la detección

En los 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 delimitador en la imagen
  • dibuja el nombre de la categoría y la confianza dentro del cuadro delimitador

Comprende las utilidades de visualización

El codelab incluye código estándar 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 para almacenar un resultado de detección de objetos con fines de visualización. box es el cuadro de límite donde se ubica el objeto y text es la cadena del resultado de la 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 obtiene los resultados de la detección de objetos en detectionResults en el bitmap de entrada y muestra la copia modificada.

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

58c6f1d4ddb00dfa.png

Visualiza el resultado de la detección del ML Kit

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

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

// 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)
}
  • Comienza por analizar el DetectedObject del Kit de AA y crear una lista de objetos BoxWithText para mostrar el resultado de la visualización.
  • Luego, dibuja el resultado de la detección sobre la imagen de entrada, usando el método de utilidad drawDetectionResult, y lo muestras en la pantalla.

Ejecución

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

Una vez que se cargue la aplicación, presiona el Botón con el ícono de la cámara, apunta la cámara hacia un objeto, toma una foto y acepta la foto (en la app de Cámara) o presiona fácilmente cualquier imagen preestablecida. Deberías ver los resultados de la detección. Vuelve a presionar el botón o selecciona otra imagen y repite el proceso algunas veces para experimentar la ODT más reciente del ML Kit.

a03109cb30d5014d.png

7. ¡Felicitaciones!

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

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

Eso es todo lo que necesitas para empezar a usarlo.

A medida que avanzas, es posible que quieras mejorar el modelo, ya que puedes ver que el modelo predeterminado solo puede reconocer 5 categorías; el modelo ni siquiera sabe cuchillo, tenedor y botella. Consulta el otro codelab de nuestra ruta de aprendizaje Aprendizaje automático integrado en el dispositivo: detección de objetos para aprender a entrenar un modelo personalizado.

Temas abordados

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

Próximos pasos

  • Explora más con la ODT del ML Kit, que incluye más imágenes y video en vivo para experimentar la detección y la exactitud y el rendimiento de la clasificación
  • Consulta la ruta de aprendizaje de detección de objetos de aprendizaje automático integrado en el dispositivo para aprender a entrenar un modelo personalizado.
  • Aplica la ODT del Kit de AA en tu propia app para Android

Más información