Обнаружение объектов на изображениях с помощью модели, обученной AutoML, на Android

После обучения собственной модели с помощью AutoML Vision Edge вы можете использовать ее в своем приложении для обнаружения объектов на изображениях.

Существует два способа интеграции моделей, обученных с помощью AutoML Vision Edge: вы можете упаковать модель, поместив ее в папку ресурсов вашего приложения, или вы можете динамически загрузить ее из Firebase.

Варианты комплектации моделей
Встроено в ваше приложение
  • Модель является частью APK-файла вашего приложения.
  • Данная модель доступна сразу же, даже когда устройство Android находится в автономном режиме.
  • Нет необходимости в проекте Firebase.
Размещено на Firebase
  • Разместите модель, загрузив её в Firebase Machine Learning.
  • Уменьшает размер APK-файла
  • Модель загружается по запросу.
  • Обновляйте модель приложения, не переиздавая его.
  • Простое A/B-тестирование с помощью Firebase Remote Config
  • Требуется проект Firebase.

Прежде чем начать

  1. Если вы хотите загрузить модель , убедитесь, что вы добавили Firebase в свой проект Android , если вы еще этого не сделали. Это не требуется при сборке модели.

  2. Добавьте зависимости для библиотеки TensorFlow Lite Task в файл gradle на уровне приложения вашего модуля, который обычно находится по app/build.gradle :

    Для включения модели в ваше приложение:

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

    Для динамической загрузки модели из Firebase добавьте также зависимость 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. Загрузите модель.

Настройте локальный источник модели.

Чтобы включить модель в ваше приложение:

  1. Распакуйте модель из ZIP-архива, загруженного из консоли Google Cloud .
  2. Включите свою модель в пакет приложения:
    1. Если в вашем проекте нет папки assets, создайте её, щёлкнув правой кнопкой мыши по папке app/ , а затем выбрав New > Folder > Assets Folder .
    2. Скопируйте файл модели tflite со встроенными метаданными в папку assets.
  3. Добавьте следующее в файл build.gradle вашего приложения, чтобы Gradle не сжимал файл модели при сборке приложения:

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

    Файл модели будет включен в пакет приложения и доступен в виде исходного ресурса.

Настройте источник модели, размещенный в Firebase.

Для использования удаленно размещенной модели создайте объект RemoteModel , указав имя, которое вы присвоили модели при ее публикации:

Java

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

Котлин

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

Затем запустите задачу загрузки модели, указав условия, при которых вы хотите разрешить загрузку. Если модель отсутствует на устройстве или если доступна более новая версия модели, задача асинхронно загрузит модель из 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.
            }
        });

Котлин

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

Во многих приложениях задача загрузки запускается в коде инициализации, но вы можете сделать это в любой момент до того, как вам понадобится использовать модель.

Создайте детектор объектов на основе вашей модели.

После настройки источников модели создайте объект ObjectDetector на основе одного из них.

Если у вас есть только локально упакованная модель, просто создайте детектор объектов из файла вашей модели и настройте требуемый пороговый уровень достоверности (см. раздел «Оценка вашей модели »):

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

Котлин

// 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)

Если у вас есть удаленно размещенная модель, вам необходимо убедиться, что она загружена, прежде чем запускать ее. Вы можете проверить статус задачи загрузки модели, используя метод isModelDownloaded() менеджера моделей.

Хотя подтверждение этого требуется только перед запуском детектора объектов, если у вас есть как удаленно размещенная модель, так и локально упакованная модель, имеет смысл выполнить эту проверку при создании экземпляра детектора объектов: создать детектор объектов из удаленной модели, если она была загружена, и из локальной модели в противном случае.

Java

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

Котлин

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

        }

Если у вас есть только удалённо размещённая модель, следует отключить связанные с ней функции — например, сделать часть пользовательского интерфейса неактивной или скрытой — до тех пор, пока вы не подтвердите загрузку модели. Это можно сделать, добавив обработчик событий к методу download() менеджера моделей.

После того, как вы убедитесь, что ваша модель загружена, создайте детектор объектов на основе файла модели:

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

Котлин

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

2. Подготовьте входное изображение.

Затем для каждого изображения, которое вы хотите пометить, создайте объект TensorImage из этого изображения. Вы можете создать объект TensorImage из объекта Bitmap , используя метод fromBitmap :

Java

TensorImage image = TensorImage.fromBitmap(bitmap);

Котлин

val image = TensorImage.fromBitmap(bitmap)

Если ваши данные изображения не представлены в Bitmap , вы можете загрузить массив пикселей, как показано в документации TensorFlow Lite .

3. Запустите детектор объектов.

Для обнаружения объектов на изображении передайте объект TensorImage методу detect() объекта ObjectDetector .

Java

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

Котлин

val results = objectDetector.detect(image)

4. Получите информацию об объектах с соответствующими обозначениями.

Если операция обнаружения объекта прошла успешно, она возвращает список объектов Detection . Каждый объект Detection представляет собой то, что было обнаружено на изображении. Вы можете получить ограничивающую рамку каждого объекта и его метки.

Например:

Java

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

Котлин

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

Советы по повышению производительности в режиме реального времени

Если вы хотите маркировать изображения в приложении реального времени, следуйте этим рекомендациям, чтобы добиться наилучшей частоты кадров:

  • Удерживайте вызовы функции разметки изображений. Если во время работы функции разметки изображений появляется новый видеокадр, отбросьте его. Пример можно увидеть в классе VisionProcessorBase в примере быстрого запуска приложения.
  • Если вы используете выходные данные средства разметки изображений для наложения графики на входное изображение, сначала получите результат, а затем отрендерите изображение и наложение за один шаг. Таким образом, вы будете отрендеривать изображение на поверхности дисплея только один раз для каждого входного кадра. Пример можно увидеть в классах CameraSourcePreview и GraphicOverlay в примере быстрого запуска приложения.
  • При использовании API Camera2, захватывайте изображения в формате ImageFormat.YUV_420_888 .

    Если вы используете более старую версию Camera API, захватывайте изображения в формате ImageFormat.NV21 .