Guia de segmentação de imagens para iOS

A tarefa "Segmentação de imagens" permite dividir imagens em regiões com base em e aplicar efeitos visuais como o desfoque do plano de fundo. Esses mostram como usar o segmentador de imagens com aplicativos para iOS.

O exemplo de código descrito nestas instruções está disponível em GitHub.

Para ver essa tarefa em ação, visualizando o demonstração. 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 uma implementação simples de uma Aplicativo de segmentação de imagens para iOS.

O exemplo implementa um segmento de imagens que gera máscaras de categoria. Ela usa a câmera de um dispositivo iOS físico para realizar a segmentação de imagens em um feed da câmera 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 consultá-lo ao modificar um aplicativo existente. O exemplo de código do segmentador de imagens está hospedado GitHub.

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. Opcionalmente, configure sua instância git para usar a finalização esparsa. Assim, você terá somente os arquivos do aplicativo de exemplo do Segmentador de imagens:

    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, você pode instalar o MediaPipe, abrir o projeto usando Xcode e executar o app. Para instruções, consulte o Guia de configuração do iOS.

Principais componentes

Os arquivos a seguir contêm o código essencial para o exemplo do segmentador de imagens aplicativo:

  • ImageSegmenterService.swift: Inicializa o segmentador de imagens, processa a seleção do modelo e executa inferência nos dados de entrada.
  • CameraViewController.swift: Implementa a interface para o modo de entrada de transmissão da câmera em tempo real e visualiza a resultados.
  • MediaLibraryViewController.swift Implementa a interface para o modo de entrada de arquivo de vídeo e imagem estática 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 sua ambiente de desenvolvimento para usar tarefas do MediaPipe, incluindo a versão da plataforma , consulte o Guia de configuração para iOS.

Dependências

O segmentador de imagens usa a biblioteca MediaPipeTasksVision, que precisa ser instalada usando o CocoaPods. A biblioteca é compatível com aplicativos Swift e Objective-C e não requer configuração específica do idioma.

Para instruções sobre como instalar o CocoaPods no macOS, consulte a documentação do CocoaPods guia de instalação (em inglês). Para instruções sobre como criar um Podfile com os pods necessários para aplicativo, consulte Usar CocoaPods.

Adicione o pod do 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 do iOS para mais informações sobre a configuração seu Podfile.

Modelo

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

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 seu projeto Xcode, consulte Como gerenciar arquivos e pastas no seu Xcode projeto.

Use a propriedade BaseOptions.modelAssetPath para especificar o caminho para o modelo. no seu pacote de apps. Para conferir um exemplo de código, consulte a próxima seção.

Criar a tarefa

É possível criar a tarefa "Segmento de imagem" chamando um dos inicializadores. O O inicializador ImageSegmenter(options:) aceita valores para a configuração. .

Se você não precisa que um segmento de imagem seja inicializado com configuração personalizada você pode usar o inicializador ImageSegmenter(modelPath:) para criar um Segmentação de imagens com as opções padrão. Para mais informações sobre configurações opções, 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 e arquivos de vídeo. e transmissões de vídeo ao vivo. Por padrão, ImageSegmenter(modelPath:) inicializa uma para imagens estáticas. Se você quiser que sua tarefa seja inicializada para processar vídeos arquivos ou streams de vídeo ao vivo, use ImageSegmenter(options:) para especificar o ou no modo de corrida ao vivo. O modo de transmissão ao vivo também requer imageSegmenterLiveStreamDelegate, que ativa O segmentador de imagens para fornecer resultados de segmentação de imagens ao delegado de forma assíncrona.

Escolha a guia correspondente ao modo de corrida para saber como criar a tarefa e executar 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 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.

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. 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, ImageSegmenterLiveStreamDelegate precisa ser definido como uma instância de uma classe que implemente o ImageSegmenterLiveStreamDelegate para receber a segmentação. resultados de forma assíncrona.
{RunningMode.image, RunningMode.video, RunningMode.liveStream} RunningMode.image
shouldOutputCategoryMask 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
shouldOutputConfidenceMasks 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 os 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
result_callback 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

Quando o modo de execução é definido como LIVE_STREAM, o segmentador de imagem exige o 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 deve implementar o método imageSegmenter(_:didFinishSegmentation:timestampInMilliseconds:error:), que o segmentador de imagens chama depois de processar os resultados da execução em cada frame.

Nome da opção Descrição Intervalo de valor Valor padrão
imageSegmenterLiveStreamDelegate Permite que o segmentador de imagens receba os resultados da imagem de performance a segmentação de maneira assíncrona no modo de transmissão ao vivo. A classe cuja instância é definida nessa propriedade precisa implementar o 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 passando-a para o segmentador de imagens. MPImage oferece suporte a diferentes tipos de imagens do iOS formatos e pode usá-los em qualquer modo em execução para inferência. Para mais informações sobre MPImage, consulte API MPImage

Escolha um formato de imagem iOS com base no seu caso de uso e no modo de execução que seu exigido pelo aplicativo.MPImage aceita UIImage, CVPixelBuffer e CMSampleBuffer formatos de imagem do iOS.

UIImage

O formato UIImage é adequado para os seguintes modos de execução:

  • Imagens: imagens de um pacote de apps, galeria do usuário ou sistema de arquivos formatados como UIImage imagens podem ser convertidas em um objeto MPImage.

  • Vídeos: use AVAssetImageGenerator para extrair frames de vídeo CGImage formato e converta-as 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 o UIImage.Orientation.Up orientação. É possível inicializar um MPImage com qualquer um dos UIImage.Orientation e a distribuição dos valores dos dados. O segmentador de imagem não oferece suporte a orientações espelhadas como .upMirrored, .downMirrored, .leftMirrored e .rightMirrored.

Para mais informações sobre o UIImage, consulte a página do desenvolvedor de imagens de usuário Documentação.

CVPixelBuffer

O formato CVPixelBuffer é adequado para aplicativos que geram frames e usar a interface CoreImage do iOS para processamento.

O formato CVPixelBuffer é adequado para os seguintes modos de execução:

  • Imagens: apps que geram imagens de CVPixelBuffer após algum processamento. usando a estrutura CoreImage do iOS podem ser enviadas ao segmentador de imagens na modo de execução de imagem.

  • Vídeos: os quadros podem ser convertidos para o formato CVPixelBuffer para e enviados ao segmentador de imagens no modo de vídeo.

  • Transmissão ao vivo: apps que usam a câmera do iOS para gerar frames podem ser convertidos no formato CVPixelBuffer para processamento antes de ser enviado ao Segmentação 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 o CVPixelBuffer, consulte a documentação da Apple CVPixelBuffer Desenvolvedor Documentação.

CMSampleBuffer

O formato CMSampleBuffer armazena amostras de mídia de um tipo uniforme de mídia e é adequado para o modo de transmissão ao vivo. Os frames ao vivo das câmeras do iOS são enviados de forma assíncrona no formato CMSampleBuffer pelo iOS AVCaptureVideoDataOutput.

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 o CMSampleBuffer, consulte a documentação da Apple do CMSampleBuffer Desenvolvedor Documentação.

Executar a tarefa

Para executar o segmentador de imagens, use o método segment() específico do modo de corrida:

  • 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 no estes 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 em 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 os carimbo de data/hora do frame de entrada para a tarefa do Segmentador de imagens.

  • Ao ser executada no modo de imagem ou vídeo, a tarefa Segmentador de imagem bloqueia linha de execução atual até terminar de processar a imagem ou frame de entrada. Para evite o bloqueio da linha de execução atual, execute o processamento em segundo plano conversa usando iOS Dispatch ou NSOperation frameworks.

  • Quando executada no modo de transmissão ao vivo, a tarefa do segmentador de imagens retorna imediatamente e não bloqueia a linha de execução atual. Ele invoca imageSegmenter(_:didFinishSegmentation:timestampInMilliseconds:error:) com o segmentador de imagens depois de processar cada frame de entrada. O O segmentador de imagem invoca esse método de forma assíncrona em um número de série dedicado fila de despacho. Para exibir resultados na interface do usuário, envie o para a fila principal após o processamento dos resultados. Se o A função segmentAsync é chamada quando a tarefa do segmentador de imagens está ocupada. processar outro frame, o segmentador de imagens ignora o novo frame de entrada.

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 depende do tipo de saída que você definiu ao configurado a tarefa.

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.

O código de exemplo do segmentador de imagens demonstra como exibir o segmentador de imagens resultados, consulte o código exemplo para mais detalhes.