Guía de segmentación de imágenes para Android

La tarea del Segmentador de imágenes de MediaPipe te permite dividir las imágenes en regiones según categorías para aplicar efectos visuales, como difuminado del fondo. Estos Las instrucciones te muestran cómo utilizar el segmentador de imágenes con aplicaciones para Android. El código ejemplo descrito en estas instrucciones está disponible en GitHub: Para obtener más información sobre las capacidades, los modelos y las opciones de configuración para completar esta tarea, consulta la Descripción general.

Ejemplo de código

El ejemplo de código de MediaPipe Tasks contiene dos implementaciones simples de una Aplicación del Segmentador de imágenes para Android:

En los ejemplos, se usa la cámara de un dispositivo Android físico para realizar una segmentación de imágenes en un feed de cámara en vivo, o bien puedes elegir imágenes y videos de la galería del dispositivo. Puedes usar las apps como punto de partida para tu propia app para Android o hacer referencia a ellos cuando modificas una app existente. El El código de ejemplo del segmentador de imágenes se aloja en GitHub:

En las siguientes secciones, se hace referencia al Segmentador de imágenes con una máscara de categoría .

Descarga el código

En las siguientes instrucciones, se muestra cómo crear una copia local del ejemplo con la herramienta de línea de comandos git.

Para descargar el código de ejemplo, haz lo siguiente:

  1. Clona el repositorio de Git con el siguiente comando:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. De forma opcional, configura tu instancia de Git para que use el resultado escaso. para que solo tengas los archivos de la app de ejemplo del Segmentador de imágenes:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_segmentation/android
    

Después de crear una versión local del código de ejemplo, puedes importar el proyecto en Android Studio y ejecutar la app. Para obtener instrucciones, consulta la Guía de configuración para Android

Componentes clave

Los siguientes archivos contienen el código esencial para esta imagen ejemplo de segmentación:

  • ImageSegmenterHelper.kt: Inicializa la tarea del Segmentador de imágenes y controla el modelo y el delegado. selección.
  • CameraFragment.kt: Proporciona la interfaz de usuario y el código de control de una cámara.
  • GalleryFragment.kt: Proporciona la interfaz de usuario y el código de control para seleccionar la imagen y el video archivos.
  • OverlayView.kt: Maneja y formatea los resultados de segmentación.

Configuración

En esta sección, se describen los pasos clave para configurar tu entorno de desarrollo y proyectos de código para usar el segmento de imágenes. Para obtener información general configurar tu entorno de desarrollo para usar tareas de MediaPipe, como de la versión de la plataforma, consulta la Guía de configuración para Android.

Dependencias

El segmento de imágenes usa la biblioteca com.google.mediapipe:tasks-vision. Agregar dependencia al archivo build.gradle de tu Proyecto de desarrollo de apps para Android. Importa las dependencias necesarias con el siguiente código:

dependencies {
    ...
    implementation 'com.google.mediapipe:tasks-vision:latest.release'
}

Modelo

La tarea del segmentador de imágenes MediaPipe requiere un modelo entrenado que sea compatible con esta tarea. Para obtener más información sobre los modelos entrenados disponibles para el segmentador de imágenes, consulta la sección Modelos de la descripción general de la tarea.

Selecciona y descarga el modelo; luego, guárdalo en el directorio de tu proyecto:

<dev-project-root>/src/main/assets

Usa el método BaseOptions.Builder.setModelAssetPath() para especificar la ruta de acceso. que usa el modelo. Este método se menciona en el ejemplo de código en la próxima sección.

En el Segmentador de imágenes código de ejemplo, el modelo se define en ImageSegmenterHelper.kt en la función setupImageSegmenter().

Crea la tarea

Puedes usar la función createFromOptions para crear la tarea. El La función createFromOptions acepta opciones de configuración que incluyen el resultado de enmascarar de tipos de datos. Para más información sobre la configuración de tareas, consulta Opciones de configuración.

La tarea del Segmentador de imágenes admite los siguientes tipos de datos de entrada: imágenes fijas, archivos de video y transmisiones de video en vivo. Debes especificar el modo de ejecución correspondiente a tu tipo de datos de entrada cuando crees la tarea. Elige la pestaña para tu tipo de datos de entrada para ver cómo crear esa tarea.

Imagen

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.IMAGE)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .build();
imagesegmenter = ImageSegmenter.createFromOptions(context, options);
    

Video

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.VIDEO)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .build();
imagesegmenter = ImageSegmenter.createFromOptions(context, options);
    

Transmisión en vivo

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .setResultListener((result, inputImage) -> {
         // Process the segmentation result here.
    })
    .setErrorListener((result, inputImage) -> {
         // Process the segmentation errors here.
    })
    .build()
imagesegmenter = ImageSegmenter.createFromOptions(context, options)
    

La implementación de código de ejemplo del segmento de imágenes permite al usuario alternar entre modos de procesamiento. Este enfoque hace que el código de creación de tareas sea más complicado y pueden no ser adecuados para tu caso de uso. Puedes ver este código en la ImageSegmenterHelper con la función setupImageSegmenter().

Opciones de configuración

Esta tarea tiene las siguientes opciones de configuración para apps para Android:

Nombre de la opción Descripción Rango de valores Valor predeterminado
runningMode Establece el modo de ejecución de la tarea. Existen tres modos:

IMAGE: Es el modo para entradas de una sola imagen.

VIDEO: es el modo de los fotogramas decodificados de un video.

LIVE_STREAM: Es el modo para una transmisión en vivo de entradas. datos, como los de una cámara. En este modo, resultListener debe se llama para configurar un objeto de escucha que reciba resultados de forma asíncrona.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
outputCategoryMask Si se establece en True, el resultado incluirá una máscara de segmentación. como una imagen de uint8, en la que cada valor de píxel indica la categoría ganadora valor. {True, False} False
outputConfidenceMasks Si se establece en True, el resultado incluirá una máscara de segmentación. como una imagen de valor flotante, donde cada valor flotante representa la confianza mapa de puntuaciones de la categoría. {True, False} True
displayNamesLocale Configura el idioma de las etiquetas que se usarán para los nombres visibles que se proporcionan en la metadatos del modelo de la tarea, si están disponibles. El valor predeterminado es en para Inglés. Puedes agregar etiquetas localizadas a los metadatos de un modelo personalizado con la API de Metadata Writer de TensorFlow Lite Código de configuración regional en
resultListener Configura el objeto de escucha de resultados para recibir los resultados de la segmentación. de forma asíncrona cuando el segmento de imágenes está en el modo LIVE_STREAM. Solo se puede usar cuando el modo de ejecución está establecido en LIVE_STREAM N/A N/A
errorListener Configura un objeto de escucha de errores opcional. N/A Sin establecer

Preparar los datos

El segmento de imágenes funciona con imágenes, archivos de video y videos de transmisión en vivo. La tarea Controla el procesamiento previo de la entrada de datos, incluidos el cambio de tamaño, la rotación y el valor. normalización.

Debes convertir la imagen o marco de entrada en un com.google.mediapipe.framework.image.MPImage antes de pasarlo al Segmentador de imágenes.

Imagen

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Load an image on the users device as a Bitmap object using BitmapFactory.

// Convert an Androids Bitmap object to a MediaPipes Image object.
Image mpImage = new BitmapImageBuilder(bitmap).build();
    

Video

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Load a video file on the user's device using MediaMetadataRetriever

// From the videos metadata, load the METADATA_KEY_DURATION and
// METADATA_KEY_VIDEO_FRAME_COUNT value. Youll need them
// to calculate the timestamp of each frame later.

// Loop through the video and load each frame as a Bitmap object.

// Convert the Androids Bitmap object to a MediaPipes Image object.
Image mpImage = new BitmapImageBuilder(frame).build();
    

Transmisión en vivo

import com.google.mediapipe.framework.image.MediaImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Create a CameraXs ImageAnalysis to continuously receive frames
// from the devices camera. Configure it to output frames in RGBA_8888
// format to match with what is required by the model.

// For each Androids ImageProxy object received from the ImageAnalysis,
// extract the encapsulated Androids Image object and convert it to
// a MediaPipes Image object.
android.media.Image mediaImage = imageProxy.getImage()
Image mpImage = new MediaImageBuilder(mediaImage).build();
    

En el código de ejemplo del Segmentador de imágenes, la preparación de los datos se controla en el ImageSegmenterHelper con la función segmentLiveStreamFrame().

Ejecuta la tarea

Llamas a una función segment diferente según el modo de ejecución que usas. La función del Segmento de imágenes devuelve las regiones del segmento identificadas dentro del imagen o marco de entrada.

Imagen

ImageSegmenterResult segmenterResult = imagesegmenter.segment(image);
    

Video

// Calculate the timestamp in milliseconds of the current frame.
long frame_timestamp_ms = 1000 * video_duration * frame_index / frame_count;

// Run inference on the frame.
ImageSegmenterResult segmenterResult =
    imagesegmenter.segmentForVideo(image, frameTimestampMs);
    

Transmisión en vivo

// Run inference on the frame. The segmentations results will be available via
// the `resultListener` provided in the `ImageSegmenterOptions` when the image
// segmenter was created.
imagesegmenter.segmentAsync(image, frameTimestampMs);
    

Ten en cuenta lo siguiente:

  • Cuando se ejecuta en el modo de video o de transmisión en vivo, también debes Proporcionan la marca de tiempo del fotograma de entrada a la tarea del Segmentador de imágenes.
  • Cuando se ejecuta en el modo de imagen o video, la tarea del Segmentador de imágenes bloquea el subproceso actual hasta que termine de procesar la imagen de entrada o marco. Para evitar bloquear la interfaz de usuario, ejecuta el procesamiento en un subproceso en segundo plano.
  • Cuando se ejecuta en el modo de transmisión en vivo, la tarea del segmento de imágenes no bloquea el subproceso actual, pero se muestra inmediatamente. Invocará su resultado con el resultado de la detección cada vez que haya terminado de procesar una marco de entrada. Si se llama a la función segmentAsync cuando se usa el segmentador de imágenes la tarea está ocupada procesando otro fotograma, la tarea ignora el nuevo marco de entrada.

En el código de ejemplo del segmento de imágenes, las funciones segment se definen en el ImageSegmenterHelper.kt .

Cómo controlar y mostrar resultados

Después de ejecutar la inferencia, la tarea del segmento de imágenes muestra un ImageSegmenterResult. que contiene los resultados de la tarea de segmentación. El contenido del el resultado depende del objeto outputType que establezcas cuando configuró la tarea.

En las siguientes secciones, se muestran ejemplos de los datos de salida de esta tarea:

Confianza de la categoría

En las siguientes imágenes, se muestra una visualización del resultado de la tarea para una categoría máscara de confianza. El resultado de la máscara de confianza contiene valores flotantes entre [0, 1]

Resultado de la máscara de confianza de imagen y categoría original. Imagen de origen de Pascal VOC 2012 conjunto de datos.

Valor de categoría

En las siguientes imágenes, se muestra una visualización del resultado de la tarea para una categoría de valor. El rango de máscara de categoría es [0, 255] y cada valor de píxel representa el índice de la categoría ganadora del resultado del modelo. La categoría ganadora índice tiene la puntuación más alta entre las categorías que el modelo puede reconocer.

Resultado de imagen original y máscara de categoría. Imagen de origen de Pascal VOC 2012 conjunto de datos.