Обнаружение объектов на изображениях с помощью модели, обученной 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 в файл градиента уровня приложения вашего модуля, который обычно имеет 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. Если в вашем проекте нет папки ресурсов, создайте ее, щелкнув правой кнопкой мыши app/ папку, а затем выбрав «Создать» > «Папка» > «Папка ресурсов» .
    2. Скопируйте файл модели tflite со встроенными метаданными в папку ресурсов.
  3. Добавьте следующее в файл build.gradle вашего приложения, чтобы Gradle не сжимал файл модели при сборке приложения:

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

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

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

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

Джава

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

Джава

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 на основе одного из них.

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

Джава

// 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() менеджера моделей.

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

Джава

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

Котлин

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

        }

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

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

Джава

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 :

Джава

TensorImage image = TensorImage.fromBitmap(bitmap);

Котлин

val image = TensorImage.fromBitmap(bitmap)

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

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

Чтобы обнаружить объекты на изображении, передайте объект TensorImage методу detect() ObjectDetector .

Джава

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

Котлин

val results = objectDetector.detect(image)

4. Получить информацию о помеченных объектах

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

Например:

Джава

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 .

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