Руководство по классификации изображений для Android

Задача MediaPipe Image Classifier позволяет выполнять классификацию изображений. Эту задачу можно использовать, чтобы определить, что представляет собой изображение среди набора категорий, определенных во время обучения. В этих инструкциях показано, как использовать классификатор изображений с приложениями Android. Пример кода, описанный в этой инструкции, доступен на GitHub .

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

Пример кода

Пример кода задач MediaPipe — это простая реализация приложения классификатора изображений для Android. В примере используется камера на физическом устройстве Android для непрерывной классификации объектов, а также могут использоваться изображения и видео из галереи устройства для статической классификации объектов.

Вы можете использовать это приложение в качестве отправной точки для своего собственного приложения для Android или обращаться к нему при изменении существующего приложения. Пример кода классификатора изображений размещен на GitHub .

Загрузите код

Следующие инструкции показывают, как создать локальную копию кода примера с помощью инструмента командной строки git .

Чтобы загрузить пример кода:

  1. Клонируйте репозиторий git, используя следующую команду:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. При желании настройте свой экземпляр git на использование разреженной проверки, чтобы у вас были только файлы для примера приложения классификатора изображений:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_classification/android
    

После создания локальной версии кода примера вы можете импортировать проект в Android Studio и запустить приложение. Инструкции см. в Руководстве по установке для Android .

Ключевые компоненты

Следующие файлы содержат ключевой код для этого примера приложения классификации изображений:

  • ImageClassifierHelper.kt — инициализирует классификатор изображений и обрабатывает выбор модели и делегата.
  • MainActivity.kt — реализует приложение, включая вызов ImageClassificationHelper и ClassificationResultsAdapter .
  • ClassificationResultsAdapter.kt — обрабатывает и форматирует результаты.

Настраивать

В этом разделе описаны ключевые шаги по настройке среды разработки и проектов кода для использования Image Classifier. Общие сведения о настройке среды разработки для использования задач MediaPipe, включая требования к версии платформы, см. в руководстве по настройке для Android .

Зависимости

Классификатор изображений использует библиотеку com.google.mediapipe:tasks-vision . Добавьте эту зависимость в файл build.gradle вашего проекта разработки приложения для Android. Импортируйте необходимые зависимости с помощью следующего кода:

dependencies {
    ...
    implementation 'com.google.mediapipe:tasks-vision:latest.release'
}

Модель

Для задачи классификатора изображений MediaPipe требуется обученная модель, совместимая с этой задачей. Дополнительную информацию о доступных обученных моделях для Классификатора изображений см. в разделе «Модели » обзора задач.

Выберите и загрузите модель, а затем сохраните ее в каталоге вашего проекта:

<dev-project-root>/src/main/assets

Используйте метод BaseOptions.Builder.setModelAssetPath() чтобы указать путь, используемый моделью. Этот метод упоминается в примере кода в следующем разделе.

В примере кода классификатора изображений модель определена в файле ImageClassifierHelper.kt .

Создать задачу

Вы можете использовать функцию createFromOptions для создания задачи. Функция createFromOptions принимает параметры конфигурации, включая режим работы, локаль отображаемых имен, максимальное количество результатов, порог достоверности, а также список разрешенных или запрещенных категорий. Дополнительные сведения о параметрах конфигурации см. в разделе Обзор конфигурации .

Задача «Классификатор изображений» поддерживает три типа входных данных: неподвижные изображения, видеофайлы и прямые видеопотоки. При создании задачи вам необходимо указать режим работы, соответствующий вашему типу входных данных. Выберите вкладку, соответствующую вашему типу входных данных, чтобы узнать, как создать задачу и выполнить вывод.

Изображение

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.IMAGE)
    .setMaxResults(5)
    .build();
imageClassifier = ImageClassifier.createFromOptions(context, options);
    

Видео

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.VIDEO)
    .setMaxResults(5)
    .build();
imageClassifier = ImageClassifier.createFromOptions(context, options);
    

Прямая трансляция

ImageClassifierOptions options =
  ImageClassifierOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setMaxResults(5)
    .setResultListener((result, inputImage) -> {
         // Process the classification result here.
    })
    .setErrorListener((result, inputImage) -> {
         // Process the classification errors here.
    })
    .build()
imageClassifier = ImageClassifier.createFromOptions(context, options)
    

Реализация примера кода классификатора изображений позволяет пользователю переключаться между режимами обработки. Такой подход усложняет код создания задачи и может не подойти для вашего варианта использования. Вы можете увидеть этот код в функции setupImageClassifier() файла ImageClassifierHelper.kt .

Варианты конфигурации

Эта задача имеет следующие параметры конфигурации для приложений Android:

Название опции Описание Диапазон значений Значение по умолчанию
runningMode Устанавливает режим выполнения задачи. Есть три режима:

ИЗОБРАЖЕНИЕ: Режим для ввода одного изображения.

ВИДЕО: Режим декодированных кадров видео.

LIVE_STREAM: режим прямой трансляции входных данных, например, с камеры. В этом режиме необходимо вызвать resultListener, чтобы настроить прослушиватель на асинхронное получение результатов.
{ IMAGE, VIDEO, LIVE_STREAM } IMAGE
displayNamesLocale Задает язык меток, которые будут использоваться для отображаемых имен, представленных в метаданных модели задачи, если они доступны. По умолчанию en английский язык. Вы можете добавить локализованные метки к метаданным пользовательской модели с помощью API записи метаданных TensorFlow Lite. Код региона ru
maxResults Устанавливает необязательное максимальное количество возвращаемых результатов классификации с наивысшим баллом. Если < 0, будут возвращены все доступные результаты. Любые положительные числа -1
scoreThreshold Устанавливает порог оценки прогноза, который переопределяет тот, который указан в метаданных модели (если таковые имеются). Результаты ниже этого значения отклоняются. Любой плавающий Не установлено
categoryAllowlist Устанавливает необязательный список разрешенных имен категорий. Если поле не пусто, результаты классификации, имя категории которых отсутствует в этом наборе, будут отфильтрованы. Повторяющиеся или неизвестные названия категорий игнорируются. Эта опция является взаимоисключающей с categoryDenylist , и использование обеих приводит к ошибке. Любые строки Не установлено
categoryDenylist Устанавливает необязательный список запрещенных имен категорий. Если значение не пустое, результаты классификации, имя категории которых находится в этом наборе, будут отфильтрованы. Повторяющиеся или неизвестные названия категорий игнорируются. Этот параметр является взаимоисключающим с categoryAllowlist , и использование обоих приводит к ошибке. Любые строки Не установлено
resultListener Настраивает прослушиватель результатов на асинхронное получение результатов классификации, когда классификатор изображений находится в режиме прямого потока. Может использоваться только в том случае, если для режима работы установлено значение LIVE_STREAM Н/Д Не установлено
errorListener Устанавливает дополнительный прослушиватель ошибок. Н/Д Не установлено

Подготовьте данные

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

Вам необходимо преобразовать входное изображение или кадр в объект com.google.mediapipe.framework.image.MPImage перед передачей его в классификатор изображений.

Изображение

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

Видео

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 value. You’ll need them
// 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();
    

Прямая трансляция

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()
Image mpImage = new MediaImageBuilder(mediaImage).build();
    

В примере кода классификатора изображений подготовка данных выполняется в файле ImageClassifierHelper.kt .

Запустить задачу

Вы можете вызвать функцию classify , соответствующую вашему режиму работы, чтобы инициировать выводы. API классификатора изображений возвращает возможные категории объекта во входном изображении или фрейме.

Изображение

ImageClassifierResult classifierResult = imageClassifier.classify(image);
    

Видео

// 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.
ImageClassifierResult classifierResult =
    imageClassifier.classifyForVideo(image, frameTimestampMs);
    

Прямая трансляция


// Run inference on the frame. The classifications results will be available 
// via the `resultListener` provided in the `ImageClassifierOptions` when 
// the image classifier was created.
imageClassifier.classifyAsync(image, frameTimestampMs);
    

Обратите внимание на следующее:

  • При работе в режиме видео или режиме прямой трансляции вы также должны предоставить метку времени входного кадра задаче классификатора изображений.
  • При работе в режиме изображения или видео задача «Классификатор изображений» блокирует текущий поток до тех пор, пока он не завершит обработку входного изображения или кадра. Чтобы избежать блокировки пользовательского интерфейса, выполняйте обработку в фоновом потоке.
  • При работе в режиме прямой трансляции задача «Классификатор изображений» не блокирует текущий поток, а немедленно возвращается. Он будет вызывать прослушиватель результатов с результатом обнаружения каждый раз, когда завершает обработку входного кадра. Если функция classifyAsync вызывается, когда задача классификатора изображений занята обработкой другого кадра, задача игнорирует новый входной кадр.

В примере кода классификатора изображений функции classify определены в файле ImageClassifierHelper.kt .

Обработка и отображение результатов

После выполнения вывода задача «Классификатор изображений» возвращает объект ImageClassifierResult , который содержит список возможных категорий для объектов во входном изображении или кадре.

Ниже показан пример выходных данных этой задачи:

ImageClassifierResult:
 Classifications #0 (single classification head):
  head index: 0
  category #0:
   category name: "/m/01bwb9"
   display name: "Passer domesticus"
   score: 0.91406
   index: 671
  category #1:
   category name: "/m/01bwbt"
   display name: "Passer montanus"
   score: 0.00391
   index: 670

Этот результат был получен путем запуска Классификатора птиц на:

В примере кода классификатора изображений класс ClassificationResultsAdapter в файле ClassificationResultsAdapter.kt обрабатывает результаты:

fun updateResults(imageClassifierResult: ImageClassifierResult? = null) {
    categories = MutableList(adapterSize) { null }
    if (imageClassifierResult != null) {
        val sortedCategories = imageClassifierResult.classificationResult()
            .classifications()[0].categories().sortedBy { it.index() }
        val min = kotlin.math.min(sortedCategories.size, categories.size)
        for (i in 0 until min) {
            categories[i] = sortedCategories[i]
        }
    }
}