Обнаружение объектов на изображениях с помощью модели, обученной 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 .

,

После обучения собственной модели с помощью 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 .