A tarefa do detector de objetos permite detectar a presença e a localização 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 esta demonstração na Web para conferir essa tarefa em ação. 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 código de exemplo do MediaPipe Tasks é uma implementação simples de um app de detecção de objetos para Android. O exemplo usa a câmera em um dispositivo Android físico para detectar objetos continuamente e também pode usar imagens e vídeos da galeria do dispositivo para detectar objetos de forma estática.
Você pode usar o app como ponto de partida para seu próprio app Android ou se referir a ele ao modificar um app existente. O código de exemplo do Detector de objetos 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 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ê pode importar o projeto para o Android Studio e executar o app. Para ver instruções, consulte o Guia de configuração para Android.
Principais componentes
Os arquivos abaixo contêm o código crucial para o aplicativo de exemplo do Detector de objetos:
- ObjectDetectorHelper.kt: inicializa o detector de objetos e processa a seleção do modelo e do delegado.
- MainActivity.kt: implementa o aplicativo e monta os componentes da interface do usuário.
- OverlayView.kt: processa e mostra 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 Detector de objetos. Para informações gerais sobre como configurar seu ambiente de desenvolvimento para usar as tarefas do MediaPipe, incluindo os requisitos da 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 MediaPipe Object Detector requer um modelo treinado compatível com essa tarefa. Para mais informações sobre os modelos treinados disponíveis para o Detector de objetos, consulte a seção "Modelos" da 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. Para conferir um exemplo de código, consulte a próxima seção.
Criar a tarefa
Você pode usar a função createFromOptions
para criar a tarefa. A
função createFromOptions
aceita opções de configuração, incluindo modo de
execução, localidade de nomes de exibição, número máximo de resultados, limite de confiança,
lista de permissões e de bloqueio de categorias. 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 do detector de objetos 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. É necessário especificar o modo de execução correspondente ao tipo de dados de entrada ao criar a tarefa. Escolha a guia correspondente ao seu tipo de dados de entrada para saber 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 do código de exemplo do Detector de objetos permite que o usuário alterne entre
modos de processamento. Essa abordagem torna o código de criação de tarefas mais complicado e
pode não ser adequado para seu caso de uso. Você pode conferir 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. 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, 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 serem usados para os nomes de exibição fornecidos nos metadados do modelo da tarefa, se disponível. O padrão é en para
o inglês. É possível adicionar rótulos localizados aos metadados de um modelo personalizado
usando a API Writer de metadados do TensorFlow Lite.
|
Código de localidade | en |
maxResults |
Define o número máximo opcional de resultados de detecção com a maior pontuação a serem retornados. | 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). Resultados abaixo desse valor são rejeitados. | Qualquer ponto flutuante | Não definido |
categoryAllowlist |
Define a lista opcional de nomes de categorias permitidos. Se não estiver vazio,
os resultados de detecção cujo nome da categoria não estiver neste conjunto serão
filtrados. Nomes de categorias duplicados ou desconhecidos são ignorados.
Essa opção é mutuamente exclusiva com categoryDenylist , e o uso
de ambas resulta em um erro. |
Qualquer string | Não definido |
categoryDenylist |
Define a lista opcional de nomes de categorias não permitidos. Se
não estiver vazio, os resultados de detecção cujo nome de categoria estiver neste conjunto serão filtrados. Nomes de categorias duplicados ou desconhecidos são ignorados. Essa opção é mutuamente
exclusiva de categoryAllowlist , e o uso das duas 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 está no modo de transmissão ao vivo. Só é possível usar essa opção quando você define o modo de execução como LIVE_STREAM. | Não relevante | Não definido |
Preparar dados
É necessário 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 dados para 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 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();
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 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, o preparo de dados é processado na classe
ObjectDetectorHelper
nas 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 transmissões de vídeo. Ao realizar detecções em uma
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.
Os exemplos de código a seguir mostram exemplos simples de como executar o Detector de objetos 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 Detector de objetos 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 modos de processamento
que podem não ser necessários para seu caso de uso.
Observe o seguinte:
- Ao executar no modo de vídeo ou de transmissão ao vivo, também é necessário 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 de entrada ou o frame. 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 do detector de objetos não bloqueia a linha de execução atual, mas retorna imediatamente. Ele vai invocar o listener de resultado 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 frame de entrada será ignorado.
Processar 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.
Confira a seguir 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 a seguir mostra uma visualização da saída da tarefa:
O código de exemplo do Detector de objetos demonstra como mostrar os resultados
de detecção retornados pela tarefa. Consulte a classe
OverlayView
para mais detalhes.