Guia de classificação de imagens para Android

A tarefa do MediaPipe Image Classifier permite que você faça a classificação de imagens. É possível usar essa tarefa para identificar o que uma imagem representa entre um conjunto de categorias definidas no tempo de treinamento. Estas instruções mostram como usar o classificador de imagem com apps Android. O exemplo de código descrito nestas instruções está disponível ativado GitHub.

Para saber como essa tarefa funciona, confira a demonstração na Web. 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 código de exemplo do MediaPipe Tasks é uma implementação simples de um classificador de imagem para Android. O exemplo usa a câmera de um dispositivo Android físico para classificar continuamente objetos, e também pode usar imagens e vídeos do da galeria de dispositivos para classificar objetos estaticamente.

Você pode usar o app como ponto de partida para seu próprio app Android ou consultá-lo ao modificar um aplicativo existente. O exemplo de código do Image Classifier 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. Como opção, configure sua instância do Git para usar a finalização esparsa. então, você tem apenas os arquivos do app de exemplo do Image Classifier:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_classification/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 aplicação de exemplo de classificação:

Configuração

Esta seção descreve as principais etapas para configurar seu ambiente de desenvolvimento e projetos de código para usar o classificador de imagem. 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 Image Classificador 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 classificador de imagem do MediaPipe requer um modelo treinado que seja compatível com essa tarefa. Para mais informações sobre modelos treinados disponíveis para o classificador de imagem, 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.

Na Exemplo de código do classificador de imagem o modelo é definido em ImageClassifierHelper.kt .

Criar a tarefa

Use a função createFromOptions para criar a tarefa. A A função createFromOptions aceita opções de configuração, incluindo modo, nome de exibição, localidade, número máximo de resultados, limite de confiança, e uma lista de permissões ou de bloqueio. Para mais informações sobre configurações opções, consulte Visão geral da configuração.

A tarefa Classificador de imagem oferece suporte a três tipos de dados de entrada: imagens estáticas, arquivos de vídeo e transmissões de vídeo ao vivo. Você precisa especificar o modo de corrida correspondente o tipo de dados de entrada ao criar a tarefa. Escolha a guia correspondente ao seu tipo de dados de entrada para ver como criar a tarefa e executar a inferência.

Imagem

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.IMAGE)
    .setMaxResults(5)
    .build();
imageClassifier = ImageClassifier.createFromOptions(context, options);
    

Vídeo

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.VIDEO)
    .setMaxResults(5)
    .build();
imageClassifier = ImageClassifier.createFromOptions(context, options);
    

Transmissão ao vivo

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setMaxResults(5)
    .setResultListener((result, inputImage) -> {
         // Process the classification result here.
    })
    .setErrorListener((result, inputImage) -> {
         // Process the classification errors here.
    })
    .build()
imageClassifier = ImageClassifier.createFromOptions(context, options)
    

A implementação de código de exemplo do classificador de imagem 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 função setupImageClassifier() do ImageClassifierHelper.kt .

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
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
maxResults Define o número máximo opcional de resultados da classificação com maior pontuação como voltar. Se < 0, todos os resultados disponíveis serão retornados. Qualquer número positivo -1
scoreThreshold Define o limite de pontuação da previsão que substitui o fornecido no os metadados do modelo (se houver). Resultados abaixo desse valor são rejeitados. Qualquer flutuação Não definido
categoryAllowlist Define a lista opcional de nomes de categorias permitidos. Se não estiver vazio, resultados de classificação cujo nome de categoria não esteja neste conjunto serão que foram filtradas. Nomes de categorias duplicados ou desconhecidos são ignorados. Essa opção é mutuamente exclusiva com categoryDenylist e usando os dois resultarão em erro. Qualquer string Não definido
categoryDenylist Define a lista opcional de nomes de categorias que não são permitidos. Se não vazio, os resultados de classificação cujo nome de categoria estiver neste conjunto serão filtrados para fora. Nomes de categorias duplicados ou desconhecidos são ignorados. Essa opção é mutuamente exclusivo com categoryAllowlist e usar ambos resulta em um erro. Qualquer string Não definido
resultListener Define o listener de resultados para receber os resultados da classificação. de forma assíncrona quando o classificador de imagem está na transmissão ao vivo modo Só pode ser usado quando o modo de corrida está definido como LIVE_STREAM N/A Não definido
errorListener Define um listener de erro opcional. N/A Não definido

Preparar dados

O Image Classificador 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 com.google.mediapipe.framework.image.MPImage antes de transmiti-lo ao Classificador de imagem.

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

Na de exemplo do classificador de imagem, a preparação dos dados é processada no ImageClassifierHelper.kt .

Executar a tarefa

É possível chamar a função classify correspondente ao modo de execução para acionar inferências. A API Image Classifier retorna as categorias possíveis para o objeto na imagem de entrada ou no frame.

Imagem

ImageClassifierResult classifierResult = imageClassifier.classify(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.
ImageClassifierResult classifierResult =
    imageClassifier.classifyForVideo(image, frameTimestampMs);
    

Transmissão ao vivo

// Run inference on the frame. The classifications results will be available 
// via the `resultListener` provided in the `ImageClassifierOptions` when 
// the image classifier was created.
imageClassifier.classifyAsync(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 Classificador de imagem.
  • Ao executar no modo de imagem ou vídeo, a tarefa Classificador de imagem 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 visualização é executada no modo de transmissão ao vivo, a tarefa do classificador de imagem 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 classifyAsync for chamada quando o classificador de imagem estiver ocupada processando outro frame, a tarefa ignora o novo frame de entrada.

Na exemplo de código do classificador de imagem, as funções classify são definidas na ImageClassifierHelper.kt .

Gerenciar e exibir resultados

Ao executar a inferência, a tarefa do classificador de imagem retorna um objeto ImageClassifierResult que contém a lista de categorias possíveis para os objetos na imagem de entrada ou no frame.

Confira abaixo um exemplo dos dados de saída desta tarefa:

ImageClassifierResult:
 Classifications #0 (single classification head):
  head index: 0
  category #0:
   category name: "/m/01bwb9"
   display name: "Passer domesticus"
   score: 0.91406
   index: 671
  category #1:
   category name: "/m/01bwbt"
   display name: "Passer montanus"
   score: 0.00391
   index: 670

Esse resultado foi obtido executando o Bird Classifier em:

Na Exemplo de código do classificador de imagem, a classe ClassificationResultsAdapter na ClassificationResultsAdapter.kt gerencia os resultados:

fun updateResults(imageClassifierResult: ImageClassifierResult? = null) {
    categories = MutableList(adapterSize) { null }
    if (imageClassifierResult != null) {
        val sortedCategories = imageClassifierResult.classificationResult()
            .classifications()[0].categories().sortedBy { it.index() }
        val min = kotlin.math.min(sortedCategories.size, categories.size)
        for (i in 0 until min) {
            categories[i] = sortedCategories[i]
        }
    }
}