Detecta objetos en imágenes con un modelo entrenado en AutoML en Android

Después de entrenar tu propio modelo con AutoML Vision Edge , puedes usarlo en tu aplicación para detectar objetos en imágenes.

Hay dos formas de integrar modelos entrenados desde AutoML Vision Edge: puedes agrupar el modelo colocándolo dentro de la carpeta de recursos de tu aplicación o puedes descargarlo dinámicamente desde Firebase.

Opciones de agrupación de modelos
Incluido en su aplicación
  • El modelo es parte del APK de tu aplicación.
  • El modelo está disponible inmediatamente, incluso cuando el dispositivo Android está desconectado.
  • No es necesario un proyecto de Firebase
Alojado con Firebase
  • Aloje el modelo cargándolo en Firebase Machine Learning
  • Reduce el tamaño del APK
  • El modelo se descarga bajo demanda.
  • Actualizaciones de modelos push sin volver a publicar su aplicación
  • Pruebas A/B sencillas con Firebase Remote Config
  • Requiere un proyecto de Firebase

Antes de que empieces

  1. Si desea descargar un modelo , asegúrese de agregar Firebase a su proyecto de Android , si aún no lo ha hecho. Esto no es necesario cuando agrupa el modelo.

  2. Agregue las dependencias de la biblioteca de tareas de TensorFlow Lite al archivo gradle a nivel de aplicación de su módulo, que generalmente es app/build.gradle :

    Para agrupar un modelo con su aplicación:

    dependencies {
      // ...
      // Object detection with a bundled Auto ML model
      implementation 'org.tensorflow:tensorflow-lite-task-vision:0.0.0-nightly-SNAPSHOT'
    }
    

    Para descargar dinámicamente un modelo desde Firebase, agregue también la dependencia de Firebase ML:

    dependencies {
      // ...
      // Object detection with an Auto ML model deployed to Firebase
      implementation platform('com.google.firebase:firebase-bom:26.1.1')
      implementation 'com.google.firebase:firebase-ml-model-interpreter'
    
      implementation 'org.tensorflow:tensorflow-lite-task-vision:0.0.0-nightly'
    }
    

1. Cargue el modelo

Configurar una fuente de modelo local

Para agrupar el modelo con su aplicación:

  1. Extraiga el modelo del archivo zip que descargó de la consola de Google Cloud.
  2. Incluye tu modelo en el paquete de tu aplicación:
    1. Si no tiene una carpeta de activos en su proyecto, cree una haciendo clic derecho en la app/ carpeta y luego haciendo clic en Nuevo > Carpeta > Carpeta de activos .
    2. Copie su archivo de modelo tflite con metadatos incrustados en la carpeta de activos.
  3. Agregue lo siguiente al archivo build.gradle de su aplicación para asegurarse de que Gradle no comprima el archivo del modelo al compilar la aplicación:

    android {
        // ...
        aaptOptions {
            noCompress "tflite"
        }
    }
    

    El archivo del modelo se incluirá en el paquete de la aplicación y estará disponible como un activo sin formato.

Configurar una fuente de modelo alojada en Firebase

Para utilizar el modelo alojado de forma remota, cree un objeto RemoteModel , especificando el nombre que le asignó al modelo cuando lo publicó:

Java

// Specify the name you assigned when you deployed the model.
FirebaseCustomRemoteModel remoteModel =
        new FirebaseCustomRemoteModel.Builder("your_model").build();

Kotlin

// Specify the name you assigned when you deployed the model.
val remoteModel =
    FirebaseCustomRemoteModel.Builder("your_model_name").build()

Luego, inicie la tarea de descarga del modelo, especificando las condiciones bajo las cuales desea permitir la descarga. Si el modelo no está en el dispositivo, o si hay una versión más reciente del modelo disponible, la tarea descargará el modelo de forma asincrónica desde Firebase:

Java

DownloadConditions downloadConditions = new DownloadConditions.Builder()
        .requireWifi()
        .build();
RemoteModelManager.getInstance().download(remoteModel, downloadConditions)
        .addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(@NonNull Task<Void> task) {
                // Success.
            }
        });

Kotlin

val downloadConditions = DownloadConditions.Builder()
    .requireWifi()
    .build()
RemoteModelManager.getInstance().download(remoteModel, downloadConditions)
    .addOnSuccessListener {
        // Success.
    }

Muchas aplicaciones inician la tarea de descarga en su código de inicialización, pero puede hacerlo en cualquier momento antes de necesitar usar el modelo.

Crea un detector de objetos a partir de tu modelo.

Después de configurar las fuentes de su modelo, cree un objeto ObjectDetector a partir de una de ellas.

Si solo tiene un modelo empaquetado localmente, simplemente cree un detector de objetos a partir del archivo de su modelo y configure el umbral de puntuación de confianza que desea solicitar (consulte Evaluar su modelo ):

Java

// Initialization
ObjectDetectorOptions options = ObjectDetectorOptions.builder()
    .setScoreThreshold(0)  // Evaluate your model in the Google Cloud console
                           // to determine an appropriate value.
    .build();
ObjectDetector objectDetector = ObjectDetector.createFromFileAndOptions(context, modelFile, options);

Kotlin

// Initialization
val options = ObjectDetectorOptions.builder()
    .setScoreThreshold(0)  // Evaluate your model in the Google Cloud console
                           // to determine an appropriate value.
    .build()
val objectDetector = ObjectDetector.createFromFileAndOptions(context, modelFile, options)

Si tiene un modelo alojado de forma remota, deberá comprobar que se haya descargado antes de ejecutarlo. Puede verificar el estado de la tarea de descarga del modelo utilizando el método isModelDownloaded() del administrador de modelos.

Aunque solo tiene que confirmar esto antes de ejecutar el detector de objetos, si tiene un modelo alojado de forma remota y un modelo empaquetado localmente, podría tener sentido realizar esta verificación al crear una instancia del detector de objetos: cree un detector de objetos desde el control remoto. modelo si se ha descargado, y del modelo local en caso contrario.

Java

FirebaseModelManager.getInstance().isModelDownloaded(remoteModel)
        .addOnSuccessListener(new OnSuccessListener<Boolean>() {
            @Override
            public void onSuccess(Boolean isDownloaded) {
            }
        });

Kotlin

FirebaseModelManager.getInstance().isModelDownloaded(remoteModel)
        .addOnSuccessListener { success ->

        }

Si solo tiene un modelo alojado de forma remota, debe desactivar la funcionalidad relacionada con el modelo (por ejemplo, atenuar u ocultar parte de su interfaz de usuario) hasta que confirme que el modelo se ha descargado. Puede hacerlo adjuntando un oyente al método download() del administrador de modelos.

Una vez que sepa que su modelo ha sido descargado, cree un detector de objetos a partir del archivo del modelo:

Java

FirebaseModelManager.getInstance().getLatestModelFile(remoteModel)
        .addOnCompleteListener(new OnCompleteListener<File>() {
            @Override
            public void onComplete(@NonNull Task<File> task) {
                File modelFile = task.getResult();
                if (modelFile != null) {
                    ObjectDetectorOptions options = ObjectDetectorOptions.builder()
                            .setScoreThreshold(0)
                            .build();
                    objectDetector = ObjectDetector.createFromFileAndOptions(
                            getApplicationContext(), modelFile.getPath(), options);
                }
            }
        });

Kotlin

FirebaseModelManager.getInstance().getLatestModelFile(remoteModel)
        .addOnSuccessListener { modelFile ->
            val options = ObjectDetectorOptions.builder()
                    .setScoreThreshold(0f)
                    .build()
            objectDetector = ObjectDetector.createFromFileAndOptions(
                    applicationContext, modelFile.path, options)
        }

2. Prepare la imagen de entrada

Luego, para cada imagen que desee etiquetar, cree un objeto TensorImage a partir de su imagen. Puedes crear un objeto TensorImage a partir de un Bitmap usando el método fromBitmap :

Java

TensorImage image = TensorImage.fromBitmap(bitmap);

Kotlin

val image = TensorImage.fromBitmap(bitmap)

Si los datos de su imagen no están en un Bitmap , puede cargar una matriz de píxeles como se muestra en los documentos de TensorFlow Lite .

3. Ejecute el detector de objetos.

Para detectar objetos en una imagen, pase el objeto TensorImage al método detect() de ObjectDetector .

Java

List<Detection> results = objectDetector.detect(image);

Kotlin

val results = objectDetector.detect(image)

4. Obtener información sobre objetos etiquetados.

Si la operación de detección de objetos tiene éxito, devuelve una lista de objetos Detection . Cada objeto Detection representa algo que se detectó en la imagen. Puede obtener el cuadro delimitador de cada objeto y sus etiquetas.

Por ejemplo:

Java

for (Detection result : results) {
    RectF bounds = result.getBoundingBox();
    List<Category> labels = result.getCategories();
}

Kotlin

for (result in results) {
    val bounds = result.getBoundingBox()
    val labels = result.getCategories()
}

Consejos para mejorar el rendimiento en tiempo real

Si desea etiquetar imágenes en una aplicación en tiempo real, siga estas pautas para lograr las mejores velocidades de fotogramas:

  • Acelera las llamadas al etiquetador de imágenes. Si hay un nuevo cuadro de video disponible mientras se ejecuta el etiquetador de imágenes, suelte el cuadro. Consulte la clase VisionProcessorBase en la aplicación de muestra de inicio rápido para ver un ejemplo.
  • Si está utilizando la salida del etiquetador de imágenes para superponer gráficos en la imagen de entrada, primero obtenga el resultado, luego renderice la imagen y superpóngala en un solo paso. Al hacerlo, renderiza en la superficie de visualización solo una vez por cada cuadro de entrada. Consulte las clases CameraSourcePreview y GraphicOverlay en la aplicación de muestra de inicio rápido para ver un ejemplo.
  • Si utiliza la API Camera2, capture imágenes en formato ImageFormat.YUV_420_888 .

    Si utiliza la API de cámara anterior, capture imágenes en formato ImageFormat.NV21 .