A tarefa MediaPipe Image Segmenter permite dividir imagens em regiões com base em categorias predefinidas para aplicar efeitos visuais, como o desfoque do 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 dessa 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 Segmentador de imagem para Android:
- Segmentação de imagem com uma máscara de categoria
- Segmentação de imagem com uma máscara de confiança
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. Também é possível escolher imagens e vídeos da galeria do dispositivo. Você pode usar os apps como ponto de partida para seu próprio app Android ou se referir a eles ao modificar um app existente. O código de exemplo do Segmenter de imagem está hospedado no GitHub (em inglês).
As seções a seguir se referem ao app Segmentação de imagem 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 git usando o seguinte comando:
git clone https://github.com/google-ai-edge/mediapipe-samples
- Como opção, configure sua instância git para usar a finalização da compra esparsa
para que você tenha apenas os arquivos do app de exemplo do Segmenter de imagem:
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ê poderá importar o projeto para o Android Studio e executar o app. Para conferir instruções, consulte o Guia de configuração para Android.
Principais componentes
Os arquivos a seguir contêm o código essencial para este exemplo de aplicativo de segmentação de imagens:
- ImageSegmenterHelper.kt: inicializa a tarefa de segmento de imagem, processa o modelo e delega a seleção.
- 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 Segmentador de imagem. Para ter informações gerais sobre como configurar seu ambiente de desenvolvimento para usar tarefas do MediaPipe, incluindo requisitos de 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 Segmenter de imagem do MediaPipe requer um modelo treinado compatível com ela. Para mais informações sobre os modelos treinados disponíveis para o Image Segmenter, consulte a seção Modelos de 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 imagem, o modelo é definido na classe ImageSegmenterHelper.kt
na função setupImageSegmenter()
.
Criar a tarefa
Use 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 da tarefa, consulte
Opções de configuração.
A tarefa Segmentador de imagem é compatível com os seguintes tipos de dados de entrada: imagens estáticas, arquivos de vídeo e streams de vídeo ao vivo. Ao criar a tarefa, especifique o modo de execução correspondente ao tipo de dados de entrada. 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);
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);
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)
Com a implementação de código de exemplo do Segmenter de imagem, o usuário pode alternar entre os modos de processamento. A abordagem torna o código de criação da tarefa mais complicado e
pode não ser apropriada para seu caso de uso. É possível conferir esse código na classe
ImageSegmenterHelper
da 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. VIDEO: o modo para frames decodificados de um vídeo. LIVE_STREAM: é o modo para 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 incluirá 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 incluirá 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 ser usado para nomes de exibição fornecidos nos
metadados do modelo da tarefa, se disponível. O padrão é en para
inglês. É possível adicionar rótulos localizados aos metadados de um modelo personalizado
usando a API TensorFlow Lite Metadata Writer
| Código da localidade | en |
resultListener |
Define o listener de resultados para receber os resultados da segmentação
de forma assíncrona quando o segmento de imagem está no modo de transmissão ao vivo.
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 transmissões de vídeo ao vivo. A tarefa lida com o pré-processamento da entrada de dados, incluindo redimensionamento, rotação e normalização de valores.
É necessário converter a imagem de entrada ou o frame em um objeto
com.google.mediapipe.framework.image.MPImage
antes de transmiti-lo ao
segmentador de imagem.
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();
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 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 imagem, a preparação de dados é processada na classe ImageSegmenterHelper
pela função segmentLiveStreamFrame()
.
Executar a tarefa
Você chama uma função segment
diferente com base no modo de corrida que está usando.
A função "Segmento de imagem" retorna as regiões de segmentos identificadas na imagem ou frame de entrada.
Imagem
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);
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, você também precisa fornecer o carimbo de data/hora do frame de entrada para a tarefa do Segmentador de imagem.
- Quando executada no modo de imagem ou vídeo, a tarefa Segmentador de imagem bloqueia a linha de execução atual até que ela termine de processar a imagem ou o frame de entrada. 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 imagem não bloqueia
a linha de execução atual, mas retorna imediatamente. Ele vai invocar o listener de
resultados 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 imagem estiver ocupada processando outro frame, a tarefa ignorará o novo frame de entrada.
No código de exemplo do Segmentador de imagem, as funções segment
são definidas no arquivo ImageSegmenterHelper.kt
.
Gerenciar e mostrar resultados
Ao executar a inferência, a tarefa Segmentador de imagem retorna um objeto ImageSegmenterResult
que contém os resultados da tarefa de segmentação. O conteúdo da
saída depende do outputType
definido quando você
configurou a tarefa.
As seções abaixo mostram exemplos dos dados de saída dessa tarefa:
Confiança da categoria
As imagens abaixo 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 categoria e da imagem original. 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 da categoria vencedora da saída do modelo. O índice de categorias
vencedor tem a pontuação mais alta entre as categorias que o modelo consegue reconhecer.
Saída original da máscara de imagem e categoria. Imagem de origem do conjunto de dados Pascal VOC 2012.