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

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

Пример кода

Пример кода задач MediaPipe содержит две простые реализации приложения Image Segmenter для Android:

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

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

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

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

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

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

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

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

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

  • ImageSegmenterHelper.kt — инициализирует задачу сегментации изображений и обрабатывает выбор модели и делегата.
  • CameraFragment.kt — предоставляет пользовательский интерфейс и код управления камерой.
  • GalleryFragment.kt — предоставляет пользовательский интерфейс и код управления для выбора изображений и видеофайлов.
  • OverlayView.kt — обрабатывает и форматирует результаты сегментации.

Настраивать

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

Зависимости

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

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

Модель

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

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

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

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

В примере кода Image Segmenter модель определяется в классе ImageSegmenterHelper.kt в функции setupImageSegmenter() .

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

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

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

Изображение

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.IMAGE)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .build();
imagesegmenter = ImageSegmenter.createFromOptions(context, options);
    

Видео

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.VIDEO)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .build();
imagesegmenter = ImageSegmenter.createFromOptions(context, options);
    

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

ImageSegmenterOptions options =
  ImageSegmenterOptions.builder()
    .setBaseOptions(
      BaseOptions.builder().setModelAssetPath("model.tflite").build())
    .setRunningMode(RunningMode.LIVE_STREAM)
    .setOutputCategoryMask(true)
    .setOutputConfidenceMasks(false)
    .setResultListener((result, inputImage) -> {
         // Process the segmentation result here.
    })
    .setErrorListener((result, inputImage) -> {
         // Process the segmentation errors here.
    })
    .build()
imagesegmenter = ImageSegmenter.createFromOptions(context, options)
    

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

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

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

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

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

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

LIVE_STREAM: режим прямой трансляции входных данных, например, с камеры. В этом режиме необходимо вызвать resultListener, чтобы настроить прослушиватель на асинхронное получение результатов.
{ IMAGE, VIDEO, LIVE_STREAM } IMAGE
outputCategoryMask Если установлено значение True , выходные данные включают маску сегментации в виде изображения uint8, где каждое значение пикселя указывает значение выигрышной категории. { True, False } False
outputConfidenceMasks Если установлено значение True , выходные данные включают маску сегментации в виде изображения значения с плавающей запятой, где каждое значение с плавающей запятой представляет карту оценки достоверности категории. { True, False } True
displayNamesLocale Задает язык меток, которые будут использоваться для отображаемых имен, представленных в метаданных модели задачи, если они доступны. По умолчанию en английский язык. Вы можете добавить локализованные метки к метаданным пользовательской модели с помощью API записи метаданных TensorFlow Lite. Код региона ru
resultListener Настраивает прослушиватель результатов на асинхронное получение результатов сегментации, когда сегментатор изображений находится в режиме LIVE_STREAM . Может использоваться только в том случае, если для режима работы установлено значение LIVE_STREAM Н/Д Н/Д
errorListener Устанавливает дополнительный прослушиватель ошибок. Н/Д Не установлено

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

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

Вам необходимо преобразовать входное изображение или кадр в объект 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 users device as a Bitmap object using BitmapFactory.

// Convert an Androids Bitmap object to a MediaPipes 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 videos metadata, load the METADATA_KEY_DURATION and
// METADATA_KEY_VIDEO_FRAME_COUNT value. Youll need them
// to calculate the timestamp of each frame later.

// Loop through the video and load each frame as a Bitmap object.

// Convert the Androids Bitmap object to a MediaPipes Image object.
Image mpImage = new BitmapImageBuilder(frame).build();
    

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

import com.google.mediapipe.framework.image.MediaImageBuilder;
import com.google.mediapipe.framework.image.MPImage;

// Create a CameraXs ImageAnalysis to continuously receive frames
// from the devices camera. Configure it to output frames in RGBA_8888
// format to match with what is required by the model.

// For each Androids ImageProxy object received from the ImageAnalysis,
// extract the encapsulated Androids Image object and convert it to
// a MediaPipes Image object.
android.media.Image mediaImage = imageProxy.getImage()
Image mpImage = new MediaImageBuilder(mediaImage).build();
    

В примере кода Image Segmenter подготовка данных выполняется в классе ImageSegmenterHelper с помощью функции segmentLiveStreamFrame() .

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

Вы вызываете другую функцию segment в зависимости от используемого режима работы. Функция Image Segmenter возвращает идентифицированные области сегментов внутри входного изображения или кадра.

Изображение

ImageSegmenterResult segmenterResult = imagesegmenter.segment(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.
ImageSegmenterResult segmenterResult =
    imagesegmenter.segmentForVideo(image, frameTimestampMs);
    

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

// Run inference on the frame. The segmentations results will be available via
// the `resultListener` provided in the `ImageSegmenterOptions` when the image
// segmenter was created.
imagesegmenter.segmentAsync(image, frameTimestampMs);
    

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

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

В примере кода Image Segmenter функции segment определены в файле ImageSegmenterHelper.kt .

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

После выполнения вывода задача Image Segmenter возвращает объект ImageSegmenterResult , который содержит результаты задачи сегментации. Содержимое выходных данных зависит от outputType , который вы установили при настройке задачи.

В следующих разделах показаны примеры выходных данных этой задачи:

Категория доверия

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

Вывод исходного изображения и маски достоверности категории. Исходное изображение из набора данных Pascal VOC 2012 .

Значение категории

На следующих изображениях показана визуализация выходных данных задачи для маски значения категории. Диапазон маски категории — [0, 255] , и каждое значение пикселя представляет индекс выигрышной категории выходных данных модели. Индекс выигрышной категории имеет наивысший балл среди категорий, которые может распознать модель.

Вывод исходного изображения и маски категории. Исходное изображение из набора данных Pascal VOC 2012 .