Detecta objetos en imágenes con ML Kit: Android

1. Antes de comenzar

ML Kit es un SDK para dispositivos móviles que lleva la experiencia de aprendizaje automático integrado en el dispositivo de Google a las apps para iOS y Android. Puedes usar las potentes APIs de Vision y Natural Language, que son fáciles de usar, para resolver desafíos comunes en tus apps o crear experiencias del usuario completamente nuevas. Todos están potenciados por los mejores modelos de AA de Google y se ofrecen sin costo.

Todas las APIs de ML Kit se ejecutan en el dispositivo, lo que permite casos de uso en tiempo real en los que deseas 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, se te guiará por pasos sencillos para agregar la detección y el seguimiento de objetos (ODT) para una imagen determinada a tu app para Android existente. Ten en cuenta que este codelab toma algunos atajos para destacar el uso de la ODT de 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 de 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 de ML Kit en tu aplicación para Android
  • API de ML Kit para la detección y el seguimiento de objetos

Requisitos

  • Una versión reciente de Android Studio (v4.1.2 o posterior)
  • Emulador de Android Studio 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 ML Kit. Los conceptos y los bloques de código no relacionados con esos temas se abordan superficialmente 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. 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 object-detection del repositorio mlkit-android contiene dos directorios:

  • android_studio_folder.pngstarter: Código inicial que usarás como base para compilar en este codelab
  • android_studio_folder.pngfinal: Código completo para la app de ejemplo finalizada

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

Importa la app a Android Studio

Comencemos por importar 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 de ML Kit

Las dependencias de ML Kit te permiten integrar el SDK de ODT de 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 los archivos de Gradle en este punto.

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 todo el repositorio).

4. Ejecuta la app de partida

Ahora que importaste el proyecto en Android Studio y agregaste las dependencias para la detección y el seguimiento de objetos de ML Kit, tienes todo listo para ejecutar la app por primera vez.

Conecta tu dispositivo Android a través de 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 un poco la app antes de escribir código.

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

  • Abre la app de cámara integrada en tu dispositivo o emulador.
  • tomar una foto dentro de la app de cámara
  • Recibe la imagen capturada en la app de inicio.
  • muestra la imagen

Prueba el botón Tomar foto, sigue las instrucciones para tomar una foto, acéptala 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, hay 3 imágenes predeterminadas entre las 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 imagen de las 3 imágenes predeterminadas. Comprueba que la imagen aparezca en la vista más grande:

1dd41b3ec978f1d9.png

5. Agrega la detección de objetos integrada 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 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 predeterminadas o tomando 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 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 integrada en el dispositivo en una imagen

Solo hay 3 pasos sencillos con 3 APIs para configurar el ODT de ML Kit:

  • Prepara una imagen: InputImage
  • Crea un objeto detector: ObjectDetection.getClient(options)
  • Conecta los 2 objetos anteriores: process(image)

Lograrás esto 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 el ODT de ML Kit. En el camino, Android Studio te pedirá 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 un InputImage

ML Kit proporciona una API simple para crear un InputImage a partir de un Bitmap. Luego, puedes ingresar un InputImage en las APIs de ML Kit.

// 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 del detector

ML Kit sigue el patrón de diseño Builder. Pasarás la configuración al compilador y, luego, adquirirás un detector de él. Hay 3 opciones para 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 un solo objeto o varios objetos)
  • Modo de clasificación (activado o desactivado)

Este codelab es para la detección y clasificación de varios objetos en una sola imagen. Agrega eso 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: Proporciona imágenes al detector

La detección y clasificación de objetos son procesos asíncronos:

  • Envías una imagen al detector (a través de process()).
  • El Detector trabaja bastante en ello.
  • El detector te informa el resultado a través de una devolución de llamada.

El siguiente código hace exactamente 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 se completa, el detector te notifica lo siguiente:

  • Es la cantidad total de objetos detectados. Cada objeto detectado se describe con lo siguiente:
  • trackingId: Es un número entero que usas para hacer 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, incluidos "Artículos de moda", "Comida", "Artículos para el hogar", "Lugar" y "Planta")
  • confidence ( un número de punto flotante entre 0.0 y 1.0, en el que 1.0 significa el 100%)

Probablemente notaste que el código realiza un procesamiento de tipo printf para el resultado detectado con debugPrint().

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

Ahora puedes aceptar imágenes para la detección.

Hagamos clic en Run ( execute.png) en la barra de herramientas de Android Studio para ejecutar el codelab. Intenta seleccionar una imagen predeterminada o tomar una foto y, luego, mira 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

…lo que significa que el detector vio 3 objetos:

  • Las categorías son Alimentos y Artículos para el hogar.
  • No se devolvió ninguna categoría para el 2º 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 confianza en que la 1ª es Comida (90% de confianza: era ensalada).

Técnicamente, eso es todo lo que necesitas para que funcione la detección de objetos de ML Kit. ¡Ya tienes todo en este momento! ¡Felicitaciones!

En el lado de la IU, aún estás en la etapa en la que comenzaste, pero podrías usar los resultados detectados en la IU, como dibujar el cuadro delimitador para crear una mejor experiencia. Vayamos al siguiente paso: el posprocesamiento de los resultados detectados.

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

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

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

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

Información sobre las utilidades de visualización

Hay algo de código estándar dentro del codelab para ayudarte 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) Es una clase de datos para almacenar un resultado de detección de objetos para la visualización. box es el cuadro de límite en el que se ubica el objeto, y text es la cadena del resultado de la detección que se muestra 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 sobre el bitmap de entrada y devuelve la copia modificada.

A continuación, se muestra un ejemplo de un resultado del método de utilidad drawDetectionResult:

58c6f1d4ddb00dfa.png

Visualiza el resultado de la detección de ML Kit

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

Ve al lugar 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)
}
  • Comienzas analizando el DetectedObject de ML Kit y creando 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 con el método de utilidad drawDetectionResult y muéstralo 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 app, presiona el botón con el ícono de la cámara, apunta la cámara hacia un objeto, toma una foto, acepta la foto (en la app de Cámara) o presiona 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 el proceso varias veces y probar la ODT más reciente de ML Kit.

a03109cb30d5014d.png

7. ¡Felicitaciones!

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

  • 3 pasos con 3 APIs
  • Crea una imagen de entrada
  • Crea un detector
  • Enviar imagen al detector

¡Eso es todo lo que necesitas para que funcione!

A medida que avances, es posible que desees mejorar el modelo, ya que puedes ver que el modelo predeterminado solo puede reconocer 5 categorías, y ni siquiera conoce el cuchillo, el tenedor y la botella. Consulta el otro codelab de nuestra ruta de aprendizaje de aprendizaje automático 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 de ML Kit a tu app para Android
  • Cómo usar la detección y el seguimiento de objetos en el dispositivo en ML Kit para detectar objetos en imágenes

Próximos pasos

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

Más información