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

Задача MediaPipe Image Embedder позволяет преобразовывать данные изображения в числовое представление для выполнения задач обработки изображений, связанных с машинным обучением, таких как сравнение сходства двух изображений. В этих инструкциях показано, как использовать Image Embedder с приложениями Android.

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

Пример кода

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

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

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

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

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

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

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

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

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

  • ImageEmbedderHelper.kt : инициализирует средство внедрения изображений и обрабатывает выбор модели и делегата.
  • MainActivity.kt : реализует приложение и собирает компоненты пользовательского интерфейса.

Настраивать

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

Зависимости

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

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

Модель

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

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

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

Укажите путь к модели в параметре ModelAssetPath . В примере кода модель определяется в функции setupImageEmbedder() в файле ImageEmbedderHelper.kt :

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

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

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

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

Изображение

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.IMAGE)
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

видео

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.VIDEO)
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

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

ImageEmbedderOptions options =
  ImageEmbedderOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setQuantize(true)
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setResultListener((result, inputImage) -> {
         // Process the embedding result here.
    })
    .build();
imageEmbedder = ImageEmbedder.createFromOptions(context, options);
    

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

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

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

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

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

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

LIVE_STREAM: режим прямой трансляции входных данных, например, с камеры. В этом режиме необходимо вызвать resultListener, чтобы настроить прослушиватель на асинхронное получение результатов.
{ IMAGE, VIDEO, LIVE_STREAM } IMAGE
l2_normalize Нормализовать ли возвращенный вектор признаков по норме L2. Используйте эту опцию, только если модель еще не содержит встроенный L2_NORMALIZATION TFLite Op. В большинстве случаев это уже так, и нормализация L2, таким образом, достигается посредством вывода TFLite без необходимости использования этой опции. Boolean False
quantize Следует ли квантовать возвращенное внедрение в байты посредством скалярного квантования. Неявно предполагается, что вложения имеют единичную норму, и поэтому любое измерение гарантированно имеет значение в [-1.0, 1.0]. Если это не так, используйте опцию l2_normalize. Boolean False
resultListener Настраивает прослушиватель результатов на асинхронное получение результатов внедрения, когда Image Embedder находится в режиме прямого потока. Может использоваться только в том случае, если для режима работы установлено значение LIVE_STREAM Н/Д Не задано
errorListener Устанавливает дополнительный прослушиватель ошибок. Н/Д Не задано

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

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

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

Изображение

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

В примере кода подготовка данных осуществляется в файле ImageEmbedderHelper.kt .

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

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

Изображение

ImageEmbedderResult embedderResult = imageEmbedder.embed(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.
ImageEmbedderResult embedderResult =
    imageEmbedder.embedForVideo(image, frameTimestampMs);
    

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


// Run inference on the frame. The embedding results will be available
// via the `resultListener` provided in the `ImageEmbedderOptions` when
// the image embedder was created.
imageEmbedder.embedAsync(image, frameTimestampMs);
    

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

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

В примере кода функция embed определена в файле ImageEmbedderHelper.kt .

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

После выполнения вывода задача Image Embedder возвращает объект ImageEmbedderResult , который содержит список внедрений (с плавающей запятой или скалярно-квантованных) для входного изображения.

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

ImageEmbedderResult:
  Embedding #0 (sole embedding head):
    float_embedding: {0.0, 0.0, ..., 0.0, 1.0, 0.0, 0.0, 2.0}
    head_index: 0

Этот результат был получен путем встраивания следующего изображения:

Вы можете сравнить сходство двух вложений, используя функцию ImageEmbedder.cosineSimilarity . Пример см. в следующем коде.

// Compute cosine similarity.
double similarity = ImageEmbedder.cosineSimilarity(
  result.embeddingResult().embeddings().get(0),
  otherResult.embeddingResult().embeddings().get(0));