A tarefa Detector de objetos permite detectar a presença e o local de várias classes de objetos. Por exemplo, um detector de objetos pode localizar cães em uma imagem. Estas instruções mostram como usar a tarefa do detector de objetos no Android. O exemplo de código descrito nestas instruções está disponível no GitHub. Confira essa tarefa em ação nesta demonstração na Web. 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 código de exemplo do MediaPipe Tasks é uma implementação simples de um app do Object Detector para Android. O exemplo usa a câmera de um dispositivo Android físico para detectar objetos continuamente, podendo também usar imagens e vídeos da galeria do dispositivo para detectar objetos estaticamente.
Use o app como ponto de partida para seu próprio app Android ou consulte-o ao modificar um app atual. O código de exemplo do Detector de objetos está hospedado no GitHub (em inglês).
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 do git para usar o checkout esparso,
para que você tenha apenas os arquivos do app de exemplo do Detector de objetos:
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ê 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 o aplicativo de exemplo do Detector de objetos:
- ObjectDetectorHelper.kt: inicializa o detector de objetos, processa o modelo e delega a seleção.
- MainActivity.kt: implementa o aplicativo e monta os componentes da interface do usuário
- OverlayView.kt: processa e mostra os resultados.
Configuração
Nesta seção, descrevemos as principais etapas para configurar seu ambiente de desenvolvimento e projetos de código para usar o Object Detector. 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 detector de objetos 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 Detector de objetos do MediaPipe requer um modelo treinado compatível com ela. Para mais informações sobre os modelos treinados disponíveis para o Object Detector, 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. Confira um exemplo de código na próxima seção.
Criar a tarefa
Use a função createFromOptions
para criar a tarefa. A
função createFromOptions
aceita opções de configuração, incluindo o modo de
execução, a localidade dos nomes de exibição, o número máximo de resultados, o limite de confiança,
a lista de permissões da categoria e a lista de bloqueio. Se nenhuma opção de configuraçã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 Detector de objetos oferece suporte a três tipos de dados de entrada: imagens estáticas, arquivos de vídeo e streams de vídeo ao vivo. Ao criar a tarefa, é necessário especificar o modo de execução correspondente ao tipo de dados de entrada. Escolha a guia correspondente ao tipo de dados de entrada para conferir 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);
Video
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
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 ver esse código na função setupObjectDetector()
da classe ObjectDetectorHelper
.
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 |
displayNamesLocales |
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 |
maxResults |
Define o número máximo opcional de resultados de detecção com a melhor pontuação a ser retornado. | Qualquer número positivo | -1 (todos os resultados são retornados) |
scoreThreshold |
Define o limite de pontuação de previsão que substitui o fornecido nos metadados do modelo (se houver). Os resultados abaixo desse valor são rejeitados. | Qualquer ponto flutuante | Não definido |
categoryAllowlist |
Define a lista opcional de nomes de categorias permitidas. Se não estiver vazio, os resultados da detecção com o nome de categoria que não estiver nesse conjunto serão filtrados. Nomes de categoria duplicados ou desconhecidos são ignorados.
Essa opção é mutuamente exclusiva com categoryDenylist , e o uso
de ambos resulta em um erro. |
Qualquer string | Não definido |
categoryDenylist |
Define a lista opcional de nomes de categorias que não são permitidos. Se não estiver vazio, os resultados de detecção com o nome de categoria nesse conjunto serão filtrados. Nomes de categoria duplicados ou desconhecidos são ignorados. Essa opção é mutuamente
exclusiva com categoryAllowlist , e o uso de ambos resulta em um erro. |
Qualquer string | Não definido |
resultListener |
Define o listener de resultados para receber os resultados de detecção de forma assíncrona quando o detector de objetos estiver no modo de transmissão ao vivo. Você só pode usar essa opção quando definir runningMode como LIVE_STREAM. | Não relevante | Não definido |
preparar dados
É preciso converter a imagem ou o frame de entrada em um objeto 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 de 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 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 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 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() MPImage mpImage = new MediaImageBuilder(mediaImage).build();
No código de exemplo do detector de objetos, a preparação de dados é processada na classe ObjectDetectorHelper
dentro das funções detectImage()
, detectVideoFile()
e detectLivestreamFrame()
.
Executar a tarefa
Dependendo do tipo de dados com que você está trabalhando, use o
método ObjectDetector.detect...()
específico para esse tipo de dados. Use
detect()
para imagens individuais,
detectForVideo()
para frames em arquivos de vídeo e
detectAsync()
para streams de vídeo. Ao realizar detecções em um
stream de vídeo, execute as detecções em uma linha de execução separada para evitar
o bloqueio da linha de execução da interface do usuário.
Nos exemplos de código a seguir, mostramos exemplos simples de como executar o Detector de objetos nesses diferentes modos de dados:
Imagem
ObjectDetectorResult detectionResult = objectDetector.detect(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. 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 Detector de objetos mostra as implementações de cada um desses modos em 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 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 Detector de objetos.
- Quando executada no modo de imagem ou vídeo, a tarefa do Detector de objetos 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.
- Quando executada no modo de transmissão ao vivo, a tarefa Detector de objetos 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 de detecção for chamada quando a tarefa do Detector de objetos estiver ocupada processando outro frame, o novo quadro de entrada será ignorado.
Gerenciar e mostrar resultados
Ao executar a inferência, a tarefa do detector de objetos retorna um
objeto ObjectDetectorResult
que descreve os objetos encontrados na
imagem de entrada.
Veja a seguir um exemplo dos dados de saída dessa 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 Detector de objetos demonstra como exibir os resultados da detecção retornados da tarefa. Consulte a classe OverlayView
para mais detalhes.