Guia de detecção de objetos para Android

A tarefa "Detector de objetos" permite detectar a presença e a localização de vários classes de objetos. Por exemplo, um detector de objetos pode localizar cães em um imagem. Estas instruções mostram como usar a tarefa "Detector de objetos" Android O exemplo de código descrito nestas instruções está disponível em GitHub. É possível conferir essa tarefa em ação visualizando este 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 detector de objetos para Android. O exemplo usa a câmera de um dispositivo Android físico para detectar objetos continuamente, e também pode usar imagens e vídeos do galeria de dispositivos para detectar 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 Object Detector está hospedado em 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 Object Detector:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/object_detection/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 o objeto Detector aplicativo de exemplo:

Configuração

Esta seção descreve as principais etapas para configurar seu ambiente de desenvolvimento e projetos de código para usar o Object Detector. 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 Object Detector 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 MediaPipe Object Detector requer um modelo treinado que seja compatível com esse tarefa. Para mais informações sobre modelos treinados disponíveis para o detector de objetos, 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. Para conferir um exemplo de código, consulte a próxima seção.

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, à lista de permissões e de bloqueio da categoria. Se uma opção de configuração não for especificada, o valor padrão será usado. Para mais informações sobre as opções de configuração, consulte Visão geral da configuração.

A tarefa Object Detector é 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. 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

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build())
    .setRunningMode(RunningMode.IMAGE)
    .setMaxResults(5)
    .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

Vídeo

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(‘model.tflite’).build())
    .setRunningMode(RunningMode.VIDEO)
    .setMaxResults(5)
    .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

Transmissão ao vivo

ObjectDetectorOptions options =
  ObjectDetectorOptions.builder()
    .setBaseOptions(BaseOptions.builder().setModelAssetPath(model.tflite).build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setMaxResults(5)
    .setResultListener((result, inputImage) -> {
      // Process the detection result here.
    })
    .setErrorListener((result, inputImage) -> {
      // Process the classification errors here.
    })
   .build();
objectDetector = ObjectDetector.createFromOptions(context, options);
    

A implementação de código de exemplo do Detector de objetos 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 ObjectDetectorHelper função setupObjectDetector() da classe.

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
displayNamesLocales 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 de detecção com maior pontuação como voltar. Qualquer número positivo -1 (todos os resultados são retornados)
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 detecçã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 detecçã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 detecção. de forma assíncrona quando o detector de objetos estiver na transmissão ao vivo modo Só é possível usar essa opção quando você define runningMode como LIVE_STREAM. Não relevante Não definido

Preparar dados

Você precisa converter a imagem ou frame de entrada para um com.google.mediapipe.framework.image.MPImage antes de transmiti-lo ao Detector de objetos.

Os exemplos a seguir explicam e mostram como preparar os dados para o processamento para cada um dos tipos de dados disponíveis:

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 values. Use these values
// 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()
MPImage mpImage = new MediaImageBuilder(mediaImage).build();
    

No código de exemplo do Detector de objetos, a preparação de dados é tratada na ObjectDetectorHelper classe em detectImage(), detectVideoFile(), detectLivestreamFrame() .

Executar a tarefa

Dependendo do tipo de dados com os quais você está trabalhando, use o Método ObjectDetector.detect...() específico para esse tipo de dados. Usar detect() para imagens individuais; detectForVideo() para frames em arquivos de vídeo detectAsync() para streams de vídeo. Quando você realiza detecções stream de vídeo, execute as detecções em uma linha de execução separada para evitar bloquear a linha de execução da interface do usuário.

Os exemplos de código a seguir mostram exemplos simples de como executar o Object Detector nesses diferentes modos de dados:

Imagem

ObjectDetectorResult detectionResult = objectDetector.detect(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.
ObjectDetectorResult detectionResult =
    objectDetector.detectForVideo(image, frameTimestampMs);
    

Transmissão ao vivo

// Run inference on the frame. The detection results will be available
// via the `resultListener` provided in the `ObjectDetectorOptions` when
// the object detector was created.
objectDetector.detectAsync(image, frameTimestampMs);
    

O exemplo de código do Object Detector mostra as implementações de cada um desses modos com mais detalhes detect(), detectVideoFile(), e detectAsync(). O código de exemplo permite que o usuário alterne entre os modos de processamento. o que pode não ser necessário para seu caso de uso.

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 à tarefa do detector de objetos.
  • Quando executada na imagem ou no modo de vídeo, a tarefa "Detector de objetos" bloquear a linha de execução atual até que ela termine de processar a imagem de entrada ou frame. Para evitar o bloqueio da linha de execução atual, execute o processamento em um linha de execução em segundo plano.
  • Quando executada no modo de transmissão ao vivo, a tarefa "Detector de objetos" 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 de detecção for chamada quando a tarefa do Detector de objetos estiver ocupado processando outro frame, o novo frame de entrada será ignorado.

Gerenciar e exibir resultados

Ao executar a inferência, a tarefa Detector de objetos retorna um Objeto ObjectDetectorResult que descreve os objetos encontrados em a imagem de entrada.

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

ObjectDetectorResult:
 Detection #0:
  Box: (x: 355, y: 133, w: 190, h: 206)
  Categories:
   index       : 17
   score       : 0.73828
   class name  : dog
 Detection #1:
  Box: (x: 103, y: 15, w: 138, h: 369)
  Categories:
   index       : 17
   score       : 0.73047
   class name  : dog

A imagem abaixo mostra uma visualização da saída da tarefa:

O código de exemplo do Object Detector demonstra como exibir a detecção resultados retornados da tarefa, consulte a OverlayView para mais detalhes.