Guia de segmentação de imagens para Android

A tarefa "Segmento de imagem do MediaPipe" permite dividir imagens em regiões com base em categorias para aplicar efeitos visuais, como desfoque de plano de fundo. Esses mostram como usar o segmentador de imagens com apps Android. O código descrito nestas instruções está disponível em GitHub. Para mais informações sobre recursos, modelos e opções de configuração, desta tarefa, consulte a Visão geral.

Exemplo de código

O exemplo de código do MediaPipe Tasks contém duas implementações simples de um Aplicativo segmentado de imagens para Android:

Os exemplos usam a câmera de um dispositivo Android físico para realizar a segmentação de imagens em um feed de câmera em tempo real, ou escolher imagens e vídeos da galeria do dispositivo. Use os aplicativos como ponto de partida para seu próprio app Android ou se referir a elas ao modificar um app existente. A O código de exemplo do segmentador de imagens está hospedado em GitHub.

As seções a seguir se referem à Segmentação de imagens com uma máscara de categoria app.

Fazer o download do código

As instruções a seguir mostram como criar uma cópia local do exemplo. usando a ferramenta de linha de comando git.

Para fazer o download do código de exemplo:

  1. Clone o repositório git usando o seguinte comando:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Como opção, configure sua instância do Git para usar a finalização esparsa. Assim, você tem apenas os arquivos do aplicativo de exemplo do Segmentador de imagens:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_segmentation/android
    

Depois de criar uma versão local do código de exemplo, você pode importar o projeto no Android Studio e executar o app. Para instruções, consulte a Guia de configuração para Android.

Principais componentes

Os arquivos a seguir contêm o código crucial para esta imagem Exemplo de aplicativo de segmentação:

  • ImageSegmenterHelper.kt: Inicializa a tarefa do segmentador de imagens e manipula o modelo e o delegado
  • CameraFragment.kt: Fornece a interface do usuário e o código de controle de uma câmera.
  • GalleryFragment.kt: Fornece a interface do usuário e o código de controle para selecionar imagem e vídeo .
  • OverlayView.kt: Processa e formata os resultados da segmentação.

Configuração

Esta seção descreve as principais etapas para configurar seu ambiente de desenvolvimento e projetos de código para usar o segmentador de imagens. Para informações gerais a configuração do seu ambiente de desenvolvimento para usar tarefas do MediaPipe, incluindo requisitos de versão da plataforma, consulte Guia de configuração para Android.

Dependências

O segmentador de imagens usa a biblioteca com.google.mediapipe:tasks-vision. Adicionar dependência do arquivo build.gradle da Projeto de desenvolvimento de apps Android. Importe as dependências necessárias com o seguinte código:

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

Modelo

A tarefa do segmentador de imagens do MediaPipe requer um modelo treinado que seja compatível com essa tarefa. Para mais informações sobre modelos treinados disponíveis para o segmentador de imagens, consulte na seção de visão geral da tarefa Modelos.

Selecione e faça o download do modelo e armazene-o no diretório do projeto:

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

Use o método BaseOptions.Builder.setModelAssetPath() para especificar o caminho. usados pelo modelo. Esse método é mencionado no exemplo de código nos próximos nesta seção.

No segmentador de imagens exemplo de código, o modelo é definido em ImageSegmenterHelper.kt classe na função setupImageSegmenter().

Criar a tarefa

Use a função createFromOptions para criar a tarefa. A A função createFromOptions aceita opções de configuração, incluindo a saída de máscara tipos Para mais informações sobre a configuração de tarefas, consulte Opções de configuração.

A tarefa Segmentador de imagens suporta os seguintes tipos de dados de entrada: imagens estáticas, arquivos de vídeo e streams de vídeo ao vivo. É preciso especificar o modo de corrida correspondente ao seu tipo de dados de entrada ao criar a tarefa. Escolha a guia para seu tipo de dados de entrada para ver como criar essa tarefa.

Imagem

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

Vídeo

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

Transmissão ao 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)
    

A implementação de código de exemplo do segmentador de imagens permite que o usuário alterne entre os modos de processamento. A abordagem torna o código de criação da tarefa mais complicado podem não ser adequados para seu caso de uso. Confira esse código ImageSegmenterHelper classe pela função setupImageSegmenter().

Opções de configuração

Esta tarefa tem as seguintes opções de configuração para apps Android:

Nome da opção Descrição Intervalo de valor Valor padrão
runningMode Define o modo de execução da tarefa. Existem três modos:

IMAGEM: o modo para entradas de imagem única.

VÍDEO: o modo para frames decodificados de um vídeo.

LIVE_STREAM: o modo de transmissão ao vivo da entrada dados de uma câmera, por exemplo. Neste modo, resultListener deve ser chamado para configurar um listener e receber resultados de forma assíncrona.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
outputCategoryMask Se definido como True, a saída incluirá uma máscara de segmentação como uma imagem uint8, em que cada valor de pixel indica a categoria vencedora . {True, False} False
outputConfidenceMasks Se definido como True, a saída incluirá uma máscara de segmentação como uma imagem de valor flutuante, em que cada valor flutuante representa a confiança mapa de pontuação da categoria. {True, False} True
displayNamesLocale Define o idioma dos rótulos a serem usados para nomes de exibição fornecidos no metadados do modelo da tarefa, se disponíveis. O padrão é en para inglês. É possível adicionar rótulos localizados aos metadados de um modelo personalizado usando a API Metadata Writer do TensorFlow Lite; Código da localidade en
resultListener Define o listener de resultados para receber os resultados da segmentação. de forma assíncrona quando o segmentador de imagens está no modo LIVE_STREAM. Só pode ser usado quando o modo de corrida está definido como LIVE_STREAM N/A N/A
errorListener Define um listener de erro opcional. N/A Não definido

Preparar dados

O segmentador de imagens funciona com imagens, arquivos de vídeo e streaming de vídeo ao vivo. A tarefa lida com o pré-processamento de entrada de dados, incluindo redimensionamento, rotação e valor. normalização.

Você precisa converter a imagem ou frame de entrada para um com.google.mediapipe.framework.image.MPImage antes de transmiti-lo ao Segmentação de imagens.

Imagem

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();
    

Vídeo

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();
    

Transmissão ao 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();
    

No exemplo de código do Segmentador de imagens, a preparação de dados é tratada na ImageSegmenterHelper classe pela função segmentLiveStreamFrame().

Executar a tarefa

Chame uma função segment diferente com base no modo de corrida usado. A função do segmentador de imagens retorna as regiões de segmento identificadas dentro do imagem ou frame de entrada.

Imagem

ImageSegmenterResult segmenterResult = imagesegmenter.segment(image);
    

Vídeo

// 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);
    

Transmissão ao 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);
    

Observe o seguinte:

  • Ao executar nos modos de vídeo ou de transmissão ao vivo, você também precisa forneça o carimbo de data/hora do frame de entrada para a tarefa do Segmentador de imagens.
  • Ao executar nos modos de imagem ou vídeo, a tarefa bloqueia a linha de execução atual até terminar de processar a imagem de entrada ou frame. Para evitar o bloqueio da interface do usuário, execute o processamento em um linha de execução em segundo plano.
  • Quando a exibição é feita no modo de transmissão ao vivo, a tarefa "Segmentação de imagens" não bloqueia thread atual, mas retorna imediatamente. Ele vai invocar seu resultado com o resultado da detecção sempre que ele terminar de processar um erro. frame de entrada. Se a função segmentAsync for chamada quando o segmentador de imagem estiver ocupada processando outro frame, a tarefa ignora o novo frame de entrada.

No código de exemplo do segmentador de imagens, as funções segment são definidas no ImageSegmenterHelper.kt .

Gerenciar e exibir resultados

Ao executar a inferência, a tarefa do segmentador de imagens retorna um ImageSegmenterResult. que contém os resultados da tarefa de segmentação. O conteúdo do saída depende do outputType definido ao configurou a tarefa.

As seções abaixo mostram exemplos dos dados de saída desta tarefa:

Confiança da categoria

As imagens a seguir mostram uma visualização da saída da tarefa para uma categoria máscara de confiança. A saída da máscara de confiança contém valores flutuantes entre [0, 1]:

Imagem original e saída de máscara de confiança de categoria. Imagem de origem do Pascal VOC 2012 (em inglês) no conjunto de dados.

Valor da categoria

As imagens a seguir mostram uma visualização da saída da tarefa para uma categoria máscara de valor. O intervalo da máscara de categoria é [0, 255], e cada valor de pixel representa o índice de categoria vencedora da saída do modelo. A categoria vencedora tem a pontuação mais alta entre as categorias que o modelo pode reconhecer.

Imagem original e saída de máscara de categoria. Imagem de origem do Pascal VOC 2012 (em inglês) no conjunto de dados.