A tarefa do segmentador de imagens do MediaPipe permite dividir imagens em regiões com base em categorias predefinidas para aplicar efeitos visuais, como desfoque de plano de fundo. Estas instruções mostram como usar o Segmentador de imagens com apps Android. O exemplo de código descrito nestas instruções está disponível no GitHub. Para mais informações sobre os 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 app de segmentação de imagens para Android:
- Segmentador de imagens com uma máscara de categoria
- Segmentador de imagens com uma máscara de confiança
Os exemplos usam a câmera em um dispositivo Android físico para realizar a segmentação de imagens em um feed de câmera ao vivo. Você também pode escolher imagens e vídeos na galeria do dispositivo. Você pode usar os apps como ponto de partida para o seu próprio app Android ou consultá-los ao modificar um app existente. O código de exemplo do segmentador de imagens está hospedado no GitHub.
As seções a seguir se referem ao app Image Segmenter com uma máscara de categoria.
Fazer o download do código
As instruções a seguir mostram como criar uma cópia local do código de exemplo usando a ferramenta de linha de comando git.
Para fazer o download do código de exemplo:
- Clone o repositório do Git usando o seguinte comando:
git clone https://github.com/google-ai-edge/mediapipe-samples
- Opcionalmente, configure sua instância do Git para usar o checkout esparso,
para que você tenha apenas os arquivos do app de exemplo do Image Segmenter:
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 para o Android Studio e executar o app. Para ver instruções, consulte o Guia de configuração para Android.
Principais componentes
Os arquivos a seguir contêm o código crucial para este exemplo de aplicativo de segmentação de imagens:
- ImageSegmenterHelper.kt: inicializa a tarefa do segmentador de imagens e processa a seleção do modelo e do 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 arquivos de 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 Image Segmenter. Para informações gerais sobre como configurar seu ambiente de desenvolvimento para usar as tarefas do MediaPipe, incluindo os requisitos da versão da plataforma, consulte o Guia de configuração para Android.
Dependências
O segmentador de imagens usa a biblioteca com.google.mediapipe:tasks-vision
. Adicione essa
dependência ao arquivo build.gradle
do
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 imagem do MediaPipe exige um modelo treinado compatível com essa tarefa. Para mais informações sobre os modelos treinados disponíveis para o Image Segmenter, consulte a seção "Modelos" da visão geral da tarefa.
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
usado pelo modelo. Esse método é mencionado no exemplo de código na próxima
seção.
No código de exemplo do segmentador de imagens,
o modelo é definido na classe ImageSegmenterHelper.kt
na função setupImageSegmenter()
.
Criar a tarefa
Você pode usar a função createFromOptions
para criar a tarefa. A
função createFromOptions
aceita opções de configuração, incluindo tipos de saída de
máscara. Para mais informações sobre a configuração de tarefas, consulte
Opções de configuração.
A tarefa do segmentador de imagens oferece suporte aos seguintes tipos de dados de entrada: imagens estáticas, arquivos de vídeo e transmissões de vídeo ao vivo. É necessário especificar o modo de execução correspondente ao tipo de dados de entrada ao criar a tarefa. Escolha a guia do tipo de dados de entrada para saber 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 do código de exemplo do segmentador de imagens permite que o usuário alterne entre
os modos de processamento. Essa abordagem torna o código de criação de tarefas mais complicado e
pode não ser adequado para seu caso de uso. Você pode conferir esse código na classe
ImageSegmenterHelper
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. Há três
modos: IMAGE: o modo para entradas de imagem única. VÍDEO: o modo para quadros decodificados de um vídeo. LIVE_STREAM: o modo de uma transmissão ao vivo de dados de entrada, como de uma câmera. Nesse modo, o resultListener precisa ser chamado para configurar um listener para receber resultados de forma assíncrona. |
{IMAGE, VIDEO, LIVE_STREAM } |
IMAGE |
outputCategoryMask |
Se definido como True , a saída inclui uma máscara de segmentação
como uma imagem uint8, em que cada valor de pixel indica o valor da categoria
vencedora. |
{True, False } |
False |
outputConfidenceMasks |
Se definido como True , a saída inclui uma máscara de segmentação
como uma imagem de valor flutuante, em que cada valor flutuante representa o mapa de pontuação de confiança da categoria. |
{True, False } |
True |
displayNamesLocale |
Define o idioma dos rótulos a serem usados para os nomes de exibição fornecidos nos metadados do modelo da tarefa, se disponível. O padrão é en para
o inglês. É possível adicionar rótulos localizados aos metadados de um modelo personalizado
usando a API Writer de metadados do TensorFlow Lite. |
Código de localidade | en |
resultListener |
Define o listener de resultado 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 execução 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 vídeos de transmissão ao vivo. A tarefa processa a entrada de dados, incluindo redimensionamento, rotação e normalização de valores.
É necessário converter a imagem ou o frame de entrada em um
objeto com.google.mediapipe.framework.image.MPImage
antes de transmiti-lo ao
segmentador de imagens.
Imagem
import com.google.mediapipe.framework.image.BitmapImageBuilder; import com.google.mediapipe.framework.image.MPImage; // Load an image on the user’s device as a Bitmap object using BitmapFactory. // Convert an Android’s Bitmap object to a MediaPipe’s 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 video’s metadata, load the METADATA_KEY_DURATION and // METADATA_KEY_VIDEO_FRAME_COUNT value. You’ll need them // to calculate the timestamp of each frame later. // Loop through the video and load each frame as a Bitmap object. // Convert the Android’s Bitmap object to a MediaPipe’s 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 CameraX’s ImageAnalysis to continuously receive frames // from the device’s camera. Configure it to output frames in RGBA_8888 // format to match with what is required by the model. // For each Android’s ImageProxy object received from the ImageAnalysis, // extract the encapsulated Android’s Image object and convert it to // a MediaPipe’s Image object. android.media.Image mediaImage = imageProxy.getImage() Image mpImage = new MediaImageBuilder(mediaImage).build();
No código de exemplo do segmentador de imagens, o preparo de dados é processado na classe
ImageSegmenterHelper
pela função segmentLiveStreamFrame()
.
Executar a tarefa
Você chama uma função segment
diferente com base no modo de execução que está usando.
A função Image Segmenter retorna as regiões de segmento identificadas na
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 no modo de vídeo ou de transmissão ao vivo, também é necessário fornecer o carimbo de data/hora do frame de entrada para a tarefa do segmentador de imagens.
- Quando executada no modo de imagem ou vídeo, a tarefa do segmentador de imagem bloqueia a linha de execução atual até que ela termine de processar a imagem de entrada ou o frame. Para evitar o bloqueio da interface do usuário, execute o processamento em uma linha de execução em segundo plano.
- Quando executada no modo de transmissão ao vivo, a tarefa do segmentador de imagens não bloqueia
a linha de execução atual, mas retorna imediatamente. Ele vai invocar o listener
de resultado com o resultado da detecção sempre que terminar de processar um
frame de entrada. Se a função
segmentAsync
for chamada quando a tarefa do segmentador de imagens estiver ocupada processando outro frame, a tarefa vai ignorar o novo frame de entrada.
No código de exemplo do segmentador de imagens, as funções segment
são definidas no arquivo
ImageSegmenterHelper.kt
.
Processar e mostrar resultados
Ao executar a inferência, a tarefa do segmentador de imagens retorna um objeto ImageSegmenterResult
que contém os resultados da tarefa de segmentação. O conteúdo da
saída depende do outputType
que você definiu ao
configurar a tarefa.
As seções a seguir 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 máscara de confiança
de categoria. A saída da máscara de confiança contém valores flutuantes entre
[0, 1]
.
Saída da máscara de confiança da imagem original e da categoria. Imagem de origem do conjunto de dados Pascal VOC 2012.
Valor da categoria
As imagens a seguir mostram uma visualização da saída da tarefa para uma máscara de valor de categoria. O intervalo da máscara de categoria é [0, 255]
, e cada valor de pixel representa o índice de categoria vencedor da saída do modelo. O índice da categoria vencedora
tem a maior pontuação entre as categorias que o modelo pode reconhecer.
Saída da máscara de imagem original e categoria. Imagem de origem do conjunto de dados Pascal VOC 2012.