A tarefa "Segmento de imagens" permite dividir imagens em regiões com base em categorias predefinidas e aplicar efeitos visuais, como o desfoque do plano de fundo. Estas instruções mostram como usar o Segmentador de imagens com apps para iOS.
O exemplo de código descrito nestas instruções está disponível no GitHub.
Confira esta tarefa em ação na demonstração da Web. 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 uma implementação simples de um app de segmentação de imagens para iOS.
O exemplo implementa um segmento de imagens que gera máscaras de categoria. Ele usa a câmera em um dispositivo iOS físico para realizar a segmentação de imagens em um feed de câmera ao vivo ou em imagens e vídeos da galeria do dispositivo.
Você pode usar o app como ponto de partida para seu próprio app iOS ou se referir a ele ao modificar um app existente. O código de exemplo do segmentador de imagens está hospedado no GitHub.
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/ios/
Depois de criar uma versão local do código de exemplo, é possível instalar a biblioteca de tarefas do MediaPipe, abrir o projeto usando o Xcode e executar o app. Para instruções, consulte o Guia de configuração para iOS.
Principais componentes
Os arquivos a seguir contêm o código crucial para o exemplo de aplicativo Image Segmenter:
- ImageSegmenterService.swift: inicializa o segmentador de imagens, processa a seleção do modelo e executa a inferência nos dados de entrada.
- CameraViewController.swift: implementa a interface do modo de entrada de feed de câmera ao vivo e visualiza os resultados.
- MediaLibraryViewController.swift Implementa a interface para o modo de entrada de imagens estáticas e arquivos de vídeo e visualiza os resultados.
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 sobre como configurar seu ambiente de desenvolvimento para usar tarefas do MediaPipe, incluindo os requisitos de versão da plataforma, consulte o Guia de configuração para iOS.
Dependências
O Image Segmenter usa a biblioteca MediaPipeTasksVision
, que precisa ser instalada
usando o CocoaPods. A biblioteca é compatível com apps Swift e Objective-C
e não requer nenhuma configuração específica da linguagem.
Para instruções sobre como instalar o CocoaPods no macOS, consulte o Guia de instalação
do CocoaPods.
Para instruções sobre como criar um Podfile
com os pods necessários para seu
app, consulte Como usar
CocoaPods.
Adicione o pod MediaPipeTasksVision no Podfile
usando o seguinte código:
target 'MyImageSegmenterApp' do
use_frameworks!
pod 'MediaPipeTasksVision'
end
Se o app incluir destinos de teste de unidade, consulte o Guia de configuração para
iOS para mais informações sobre como configurar
o Podfile
.
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 segmentador de imagens, consulte a seção de modelos da visão geral da tarefa.
Selecione e faça o download de um modelo e adicione-o ao diretório do projeto usando o Xcode. Para instruções sobre como adicionar arquivos ao projeto do Xcode, consulte Como gerenciar arquivos e pastas no projeto do Xcode.
Use a propriedade BaseOptions.modelAssetPath
para especificar o caminho para o modelo
no app bundle. Para conferir um exemplo de código, consulte a próxima seção.
Criar a tarefa
É possível criar a tarefa de segmentação de imagens chamando um dos inicializadores dela. O
inicializador ImageSegmenter(options:)
aceita valores para as opções de
configuração.
Se você não precisar de um segmentador de imagens inicializado com opções de configuração
personalizadas, use o inicializador ImageSegmenter(modelPath:)
para criar um
segmentador de imagens com as opções padrão. Para mais informações sobre as opções de configuração, consulte Visão geral da configuração.
A tarefa Segmentador de imagens é compatível com três tipos de dados de entrada: imagens estáticas, arquivos de vídeo e streams de vídeo ao vivo. Por padrão, ImageSegmenter(modelPath:)
inicializa uma tarefa de imagens estáticas. Se você quiser que a tarefa seja inicializada para processar arquivos
de vídeo ou transmissões de vídeo ao vivo, use ImageSegmenter(options:)
para especificar o modo de execução
do vídeo ou da transmissão ao vivo. O modo de transmissão ao vivo também exige a opção de configuração
adicional imageSegmenterLiveStreamDelegate
, que permite que o
segmentador de imagens envie resultados de segmentação de imagem para o delegado
de forma assíncrona.
Escolha a guia correspondente ao modo de execução para saber como criar a tarefa e executar a inferência.
Swift
Imagem
import MediaPipeTasksVision let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite") let options = ImageSegmenterOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .image options.shouldOutputCategoryMask = true options.shouldOutputConfidenceMasks = false let imageSegmenter = try ImageSegmenter(options: options)
Vídeo
import MediaPipeTasksVision let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite") let options = ImageSegmenterOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .video options.shouldOutputCategoryMask = true options.shouldOutputConfidenceMasks = false let imageSegmenter = try ImageSegmenter(options: options)
Transmissão ao vivo
import MediaPipeTasksVision // Class that conforms to the `imageSegmenterLiveStreamDelegate` protocol and // implements the method that the image segmenter calls once it finishes // performing segmentation of each input frame. class ImageSegmenterResultProcessor: NSObject, ImageSegmenterLiveStreamDelegate { func imageSegmenter( _ imageSegmenter: ImageSegmenter, didFinishSegmentation result: ImageSegmenterResult?, timestampInMilliseconds: Int, error: Error?) { // Process the image segmentation result or errors here. } } let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite") let options = ImageSegmenterOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .liveStream options.shouldOutputCategoryMask = true options.shouldOutputConfidenceMasks = false // Set `imageSegmenterLiveStreamDelegate` to the object of the class that // confirms to the `ImageSegmenterLiveStreamDelegate` protocol. let processor = ImageSegmenterResultProcessor() options.imageSegmenterLiveStreamDelegate = processor let imageSegmenter = try ImageSegmenter(options: options)
Objective-C
Imagem
@import MediaPipeTasksVision; NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model" ofType:@"tflite"]; MPPImageSegmenterOptions *options = [[MPPImageSegmenterOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeImage; options.shouldOutputCategoryMask = YES; options.shouldOutputConfidenceMasks = NO; MPPImageSegmenter *imageSegmenter = [[MPPImageSegmenter alloc] initWithOptions:options error:nil];
Vídeo
@import MediaPipeTasksVision; NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model" ofType:@"tflite"]; MPPImageSegmenterOptions *options = [[MPPImageSegmenterOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeVideo; options.shouldOutputCategoryMask = YES; options.shouldOutputConfidenceMasks = NO; MPPImageSegmenter *imageSegmenter = [[MPPImageSegmenter alloc] initWithOptions:options error:nil];
Transmissão ao vivo
@import MediaPipeTasksVision; // Class that conforms to the `MPPImageSegmenterLiveStreamDelegate` protocol // and implements the method that the image segmenter calls once it finishes // performing segmentation of each input frame. @interface APPImageSegmenterResultProcessor : NSObject@end @implementation APPImageSegmenterResultProcessor - (void)imageSegmenter:(MPPImageSegmenter *)imageSegmenter didFinishSegmentationWithResult:(MPPImageSegmenterResult *)imageSegmenterResult timestampInMilliseconds:(NSInteger)timestampInMilliseconds error:(NSError *)error { // Process the image segmentation result or errors here. } @end NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model" ofType:@"tflite"]; MPPImageSegmenterOptions *options = [[MPPImageSegmenterOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeLiveStream; options.shouldOutputCategoryMask = YES; options.shouldOutputConfidenceMasks = NO; // Set `imageSegmenterLiveStreamDelegate` to the object of the class that // confirms to the `MPPImageSegmenterLiveStreamDelegate` protocol. APPImageSegmenterResultProcessor *processor = [APPImageSegmenterResultProcessor new]; options.imageSegmenterLiveStreamDelegate = processor; MPPImageSegmenter *imageSegmenter = [[MPPImageSegmenter alloc] initWithOptions:options error:nil];
A implementação do 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 e pode não ser apropriada para seu caso de uso.
Opções de configuração
Esta tarefa tem as seguintes opções de configuração para apps iOS:
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: IMAGEM: 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, ImageSegmenterLiveStreamDelegate
precisa ser definido como uma instância de uma classe que implementa o
ImageSegmenterLiveStreamDelegate para receber os resultados
de segmentação de forma assíncrona.
|
{RunningMode.image, RunningMode.video, RunningMode.liveStream } |
RunningMode.image |
shouldOutputCategoryMask |
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 |
shouldOutputConfidenceMasks |
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 nos nomes de exibição fornecidos nos
metadados do modelo da tarefa, se disponíveis. O padrão é en para
o 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 |
result_callback |
Define o listener de resultados para receber os resultados de segmentação de forma assíncrona quando o segmento de imagem está no modo LIVE_STREAM .
Só pode ser usado quando o modo de execução está definido como LIVE_STREAM . |
N/A | N/A |
Quando o modo de execução está definido como LIVE_STREAM
, o segmentador de imagens exige a
opção de configuração imageSegmenterLiveStreamDelegate
adicional, que
permite que o segmentador de imagens forneça resultados de segmentação de imagens de forma assíncrona.
O delegado precisa implementar o
método imageSegmenter(_:didFinishSegmentation:timestampInMilliseconds:error:)
,
que o Segmentador de imagem chama após processar os resultados da segmentação
em cada frame.
Nome da opção | Descrição | Intervalo de valor | Valor padrão |
---|---|---|---|
imageSegmenterLiveStreamDelegate |
Permite que o Image Segmenter receba os resultados da segmentação de imagens de forma assíncrona no modo de transmissão ao vivo. A classe que tem a instância definida
para essa propriedade precisa implementar o
método
imageSegmenter(_:didFinishSegmentation:timestampInMilliseconds:error:) . |
Não relevante | Não definido |
Preparar dados
É necessário converter a imagem ou o frame de entrada em um objeto MPImage
antes de transmiti-lo ao segmentador de imagens. MPImage
oferece suporte a diferentes tipos de formatos de imagem
do iOS e pode usá-los em qualquer modo em execução para inferência. Para mais
informações sobre MPImage
, consulte a
API MPImage.
Escolha um formato de imagem do iOS com base no seu caso de uso e no modo de execução
exigido pelo aplicativo.MPImage
aceita os formatos de imagem UIImage
, CVPixelBuffer
e
CMSampleBuffer
do iOS.
UIImage
O formato UIImage
é adequado para os seguintes modos de execução:
Imagens: as imagens de um pacote de apps, galeria de usuários ou sistema de arquivos formatadas como
UIImage
podem ser convertidas em um objetoMPImage
.Vídeos: use o AVAssetImageGenerator para extrair frames de vídeo para o formato CGImage e os converter em imagens
UIImage
.
Swift
// Load an image on the user's device as an iOS `UIImage` object. // Convert the `UIImage` object to a MediaPipe's Image object having the default // orientation `UIImage.Orientation.up`. let image = try MPImage(uiImage: image)
Objective-C
// Load an image on the user's device as an iOS `UIImage` object. // Convert the `UIImage` object to a MediaPipe's Image object having the default // orientation `UIImageOrientationUp`. MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
O exemplo inicializa um MPImage
com a orientação
padrão UIImage.Orientation.Up. É possível inicializar uma MPImage
com qualquer um dos valores
UIImage.Orientation
compatíveis. O Image Segmenter não oferece suporte a orientações espelhadas, como .upMirrored
, .downMirrored
, .leftMirrored
e .rightMirrored
.
Para mais informações sobre UIImage
, consulte a documentação para desenvolvedores da Apple
de UIImage (em inglês).
CVPixelBuffer
O formato CVPixelBuffer
é adequado para aplicativos que geram frames
e usam o framework CoreImage
do iOS para processamento.
O formato CVPixelBuffer
é adequado para os seguintes modos de execução:
Imagens: apps que geram imagens
CVPixelBuffer
após algum processamento usando o frameworkCoreImage
do iOS podem ser enviados ao segmentador de imagens no modo de execução de imagens.Vídeos: os frames de vídeo podem ser convertidos para o formato
CVPixelBuffer
para processamento e, em seguida, enviados para o segmentador de imagens no modo de vídeo.Transmissão ao vivo: os apps que usam uma câmera do iOS para gerar frames podem ser convertidos para o formato
CVPixelBuffer
para processamento antes de serem enviados ao segmentador de imagens no modo de transmissão ao vivo.
Swift
// Obtain a CVPixelBuffer. // Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the default // orientation `UIImage.Orientation.up`. let image = try MPImage(pixelBuffer: pixelBuffer)
Objective-C
// Obtain a CVPixelBuffer. // Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the // default orientation `UIImageOrientationUp`. MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
Para mais informações sobre CVPixelBuffer
, consulte a Documentação do desenvolvedor
da Apple CVPixelBuffer (em inglês).
CMSampleBuffer
O formato CMSampleBuffer
armazena amostras de mídia de um tipo uniforme e é
adequado para o modo de execução de transmissões ao vivo. Os frames ao vivo das câmeras do iOS são
enviados de forma assíncrona no formato CMSampleBuffer
pelo
AVCaptureVideoDataOutput do iOS.
Swift
// Obtain a CMSampleBuffer. // Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the default // orientation `UIImage.Orientation.up`. let image = try MPImage(sampleBuffer: sampleBuffer)
Objective-C
// Obtain a `CMSampleBuffer`. // Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the // default orientation `UIImageOrientationUp`. MPImage *image = [[MPPImage alloc] initWithSampleBuffer:sampleBuffer error:nil];
Para mais informações sobre CMSampleBuffer
, consulte a documentação
para desenvolvedores da Apple
CMSampleBuffer (em inglês).
Executar a tarefa
Para executar o segmentador de imagens, use o método segment()
específico para o modo de execução
atribuído:
- Imagem estática:
segment(image:)
- Vídeo:
segment(videoFrame:timestampInMilliseconds:)
- Transmissão ao vivo:
segmentAsync(image:timestampInMilliseconds:)
Os exemplos de código a seguir mostram exemplos simples de como executar o segmentador de imagens nesses diferentes modos de execução:
Swift
Imagem
let result = try imageSegmenter.segment(image: image)
Vídeo
let result = try imageSegmenter.segment( videoFrame: image, timestampInMilliseconds: timestamp)
Transmissão ao vivo
try imageSegmenter.segmentAsync( image: image, timestampInMilliseconds: timestamp)
Objective-C
Imagem
MPPImageSegmenterResult *result = [imageSegmenter segmentImage:image error:nil];
Vídeo
MPPImageSegmenterResult *result = [imageSegmenter segmentVideoFrame:image timestampInMilliseconds:timestamp error:nil];
Transmissão ao vivo
BOOL success = [imageSegmenter segmentAsyncImage:image timestampInMilliseconds:timestamp error:nil];
O exemplo de código do segmentador de imagens mostra as implementações de cada um desses modos
com mais detalhes segment(image:)
,
segment(videoFrame:timestampInMilliseconds:)
e
segmentAsync(image:timestampInMilliseconds:)
.
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 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 ou o frame de entrada. Para evitar o bloqueio da linha de execução atual, execute o processamento em uma linha de execução em segundo plano usando os frameworks Dispatch ou NSOperation do iOS.
Quando executada no modo de transmissão ao vivo, a tarefa do segmentador de imagens é retornada imediatamente e não bloqueia a linha de execução atual. Ele invoca o método
imageSegmenter(_:didFinishSegmentation:timestampInMilliseconds:error:)
com o segmentador de imagens após o processamento de cada frame de entrada. O ImageSegmenter invoca esse método de forma assíncrona em uma fila de envio serial dedicada. Para mostrar os resultados na interface do usuário, envie os resultados para a fila principal depois de processá-los. Se a funçãosegmentAsync
for chamada quando a tarefa do segmentador de imagem estiver ocupada processando outro frame, o segmentador de imagem vai ignorar o novo frame de entrada.
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 tipo de saída definido ao
configurar
a tarefa.
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 categoria e da imagem original. Imagem de origem do conjunto de dados Pascal VOC 2012.
O código de exemplo do segmentador de imagens demonstra como exibir os resultados do segmentador. Consulte o exemplo de código para mais detalhes.