Detecte objetos em imagens com um modelo treinado em AutoML no Android

Depois de treinar seu próprio modelo usando o AutoML Vision Edge , você poderá usá-lo em seu aplicativo para detectar objetos em imagens.

Há duas maneiras de integrar modelos treinados no AutoML Vision Edge: você pode agrupar o modelo colocando-o na pasta de ativos do seu aplicativo ou baixá-lo dinamicamente do Firebase.

Opções de agrupamento de modelos
Incluído em seu aplicativo
  • O modelo faz parte do APK do seu app
  • O modelo está disponível imediatamente, mesmo quando o dispositivo Android está offline
  • Não há necessidade de um projeto Firebase
Hospedado com Firebase
  • Hospede o modelo fazendo upload dele para o Firebase Machine Learning
  • Reduz o tamanho do APK
  • O modelo é baixado sob demanda
  • Envie atualizações de modelo sem republicar seu aplicativo
  • Teste A/B fácil com o Firebase Remote Config
  • Requer um projeto Firebase

Antes de você começar

  1. Se você deseja baixar um modelo , certifique-se de adicionar o Firebase ao seu projeto Android , caso ainda não tenha feito isso. Isso não é necessário quando você agrupa o modelo.

  2. Adicione as dependências da biblioteca de tarefas do TensorFlow Lite ao arquivo gradle no nível do aplicativo do seu módulo, que geralmente é app/build.gradle :

    Para agrupar um modelo com seu aplicativo:

    dependencies {
      // ...
      // Object detection with a bundled Auto ML model
      implementation 'org.tensorflow:tensorflow-lite-task-vision:0.0.0-nightly-SNAPSHOT'
    }
    

    Para baixar dinamicamente um modelo do Firebase, adicione também a dependência do Firebase ML:

    dependencies {
      // ...
      // Object detection with an Auto ML model deployed to Firebase
      implementation platform('com.google.firebase:firebase-bom:26.1.1')
      implementation 'com.google.firebase:firebase-ml-model-interpreter'
    
      implementation 'org.tensorflow:tensorflow-lite-task-vision:0.0.0-nightly'
    }
    

1. Carregue o modelo

Configurar uma origem de modelo local

Para agrupar o modelo com seu aplicativo:

  1. Extraia o modelo do arquivo zip baixado do console do Google Cloud.
  2. Inclua seu modelo no pacote do seu aplicativo:
    1. Se você não tiver uma pasta de ativos em seu projeto, crie uma clicando com o botão direito na pasta app/ e clicando em Novo > Pasta > Pasta de ativos .
    2. Copie seu arquivo de modelo tflite com metadados incorporados para a pasta de ativos.
  3. Adicione o seguinte ao arquivo build.gradle do seu aplicativo para garantir que o Gradle não compacte o arquivo de modelo ao criar o aplicativo:

    android {
        // ...
        aaptOptions {
            noCompress "tflite"
        }
    }
    

    O arquivo de modelo será incluído no pacote do aplicativo e disponível como um ativo bruto.

Configurar uma origem de modelo hospedado no Firebase

Para usar o modelo hospedado remotamente, crie um objeto RemoteModel , especificando o nome que você atribuiu ao modelo quando o publicou:

Java

// Specify the name you assigned when you deployed the model.
FirebaseCustomRemoteModel remoteModel =
        new FirebaseCustomRemoteModel.Builder("your_model").build();

Kotlin

// Specify the name you assigned when you deployed the model.
val remoteModel =
    FirebaseCustomRemoteModel.Builder("your_model_name").build()

Em seguida, inicie a tarefa de download do modelo, especificando as condições sob as quais deseja permitir o download. Se o modelo não estiver no dispositivo ou se uma versão mais recente do modelo estiver disponível, a tarefa fará o download assíncrono do modelo do Firebase:

Java

DownloadConditions downloadConditions = new DownloadConditions.Builder()
        .requireWifi()
        .build();
RemoteModelManager.getInstance().download(remoteModel, downloadConditions)
        .addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(@NonNull Task<Void> task) {
                // Success.
            }
        });

Kotlin

val downloadConditions = DownloadConditions.Builder()
    .requireWifi()
    .build()
RemoteModelManager.getInstance().download(remoteModel, downloadConditions)
    .addOnSuccessListener {
        // Success.
    }

Muitos aplicativos iniciam a tarefa de download em seu código de inicialização, mas você pode fazer isso a qualquer momento antes de usar o modelo.

Crie um detector de objetos a partir do seu modelo

Depois de configurar as origens do modelo, crie um objeto ObjectDetector a partir de uma delas.

Se você tiver apenas um modelo empacotado localmente, basta criar um detector de objetos a partir do arquivo do modelo e configurar o limite de pontuação de confiança que deseja exigir (consulte Avaliar seu modelo ):

Java

// Initialization
ObjectDetectorOptions options = ObjectDetectorOptions.builder()
    .setScoreThreshold(0)  // Evaluate your model in the Google Cloud console
                           // to determine an appropriate value.
    .build();
ObjectDetector objectDetector = ObjectDetector.createFromFileAndOptions(context, modelFile, options);

Kotlin

// Initialization
val options = ObjectDetectorOptions.builder()
    .setScoreThreshold(0)  // Evaluate your model in the Google Cloud console
                           // to determine an appropriate value.
    .build()
val objectDetector = ObjectDetector.createFromFileAndOptions(context, modelFile, options)

Se você tiver um modelo hospedado remotamente, precisará verificar se ele foi baixado antes de executá-lo. Você pode verificar o status da tarefa de download do modelo usando o método isModelDownloaded() do gerenciador de modelo.

Embora você só precise confirmar isso antes de executar o detector de objetos, se você tiver um modelo hospedado remotamente e um modelo empacotado localmente, pode fazer sentido realizar esta verificação ao instanciar o detector de objetos: crie um detector de objetos a partir do remoto model se tiver sido baixado e do modelo local caso contrário.

Java

FirebaseModelManager.getInstance().isModelDownloaded(remoteModel)
        .addOnSuccessListener(new OnSuccessListener<Boolean>() {
            @Override
            public void onSuccess(Boolean isDownloaded) {
            }
        });

Kotlin

FirebaseModelManager.getInstance().isModelDownloaded(remoteModel)
        .addOnSuccessListener { success ->

        }

Se você tiver apenas um modelo hospedado remotamente, desative a funcionalidade relacionada ao modelo (por exemplo, esmaecer ou ocultar parte da interface do usuário) até confirmar que o download do modelo foi feito. Você pode fazer isso anexando um ouvinte ao método download() do gerenciador de modelo.

Depois de saber que seu modelo foi baixado, crie um detector de objetos a partir do arquivo do modelo:

Java

FirebaseModelManager.getInstance().getLatestModelFile(remoteModel)
        .addOnCompleteListener(new OnCompleteListener<File>() {
            @Override
            public void onComplete(@NonNull Task<File> task) {
                File modelFile = task.getResult();
                if (modelFile != null) {
                    ObjectDetectorOptions options = ObjectDetectorOptions.builder()
                            .setScoreThreshold(0)
                            .build();
                    objectDetector = ObjectDetector.createFromFileAndOptions(
                            getApplicationContext(), modelFile.getPath(), options);
                }
            }
        });

Kotlin

FirebaseModelManager.getInstance().getLatestModelFile(remoteModel)
        .addOnSuccessListener { modelFile ->
            val options = ObjectDetectorOptions.builder()
                    .setScoreThreshold(0f)
                    .build()
            objectDetector = ObjectDetector.createFromFileAndOptions(
                    applicationContext, modelFile.path, options)
        }

2. Prepare a imagem de entrada

Em seguida, para cada imagem que você deseja rotular, crie um objeto TensorImage a partir da sua imagem. Você pode criar um objeto TensorImage a partir de um Bitmap usando o método fromBitmap :

Java

TensorImage image = TensorImage.fromBitmap(bitmap);

Kotlin

val image = TensorImage.fromBitmap(bitmap)

Se os dados da imagem não estiverem em um Bitmap , você poderá carregar uma matriz de pixels conforme mostrado na documentação do TensorFlow Lite .

3. Execute o detector de objetos

Para detectar objetos em uma imagem, passe o objeto TensorImage para o método detect() do ObjectDetector .

Java

List<Detection> results = objectDetector.detect(image);

Kotlin

val results = objectDetector.detect(image)

4. Obtenha informações sobre objetos rotulados

Se a operação de detecção de objetos for bem-sucedida, ela retornará uma lista de objetos Detection . Cada objeto Detection representa algo que foi detectado na imagem. Você pode obter a caixa delimitadora de cada objeto e seus rótulos.

Por exemplo:

Java

for (Detection result : results) {
    RectF bounds = result.getBoundingBox();
    List<Category> labels = result.getCategories();
}

Kotlin

for (result in results) {
    val bounds = result.getBoundingBox()
    val labels = result.getCategories()
}

Dicas para melhorar o desempenho em tempo real

Se você deseja rotular imagens em um aplicativo em tempo real, siga estas diretrizes para obter as melhores taxas de quadros:

  • Limite as chamadas para o rotulador de imagens. Se um novo quadro de vídeo ficar disponível enquanto o rotulador de imagens estiver em execução, descarte o quadro. Consulte a classe VisionProcessorBase no aplicativo de exemplo de início rápido para ver um exemplo.
  • Se você estiver usando a saída do rotulador de imagens para sobrepor gráficos na imagem de entrada, primeiro obtenha o resultado e, em seguida, renderize a imagem e sobreponha em uma única etapa. Ao fazer isso, você renderiza na superfície de exibição apenas uma vez para cada quadro de entrada. Consulte as classes CameraSourcePreview e GraphicOverlay no aplicativo de exemplo de início rápido para ver um exemplo.
  • Se você usar a API Camera2, capture imagens no formato ImageFormat.YUV_420_888 .

    Se você usar a API Camera mais antiga, capture imagens no formato ImageFormat.NV21 .