Задача MediaPipe Image Classifier позволяет выполнять классификацию изображений. Эту задачу можно использовать, чтобы определить, что представляет собой изображение среди набора категорий, определенных во время обучения. В этих инструкциях показано, как использовать классификатор изображений с приложениями Android. Пример кода, описанный в этой инструкции, доступен на GitHub .
Вы можете увидеть эту задачу в действии, просмотрев веб-демо . Дополнительные сведения о возможностях, моделях и параметрах конфигурации этой задачи см. в разделе Обзор .
Пример кода
Пример кода задач MediaPipe — это простая реализация приложения классификатора изображений для Android. В примере используется камера на физическом устройстве Android для непрерывной классификации объектов, а также могут использоваться изображения и видео из галереи устройства для статической классификации объектов.
Вы можете использовать это приложение в качестве отправной точки для своего собственного приложения для Android или обращаться к нему при изменении существующего приложения. Пример кода классификатора изображений размещен на GitHub .
Загрузите код
Следующие инструкции показывают, как создать локальную копию кода примера с помощью инструмента командной строки git .
Чтобы загрузить пример кода:
-  Клонируйте репозиторий git, используя следующую команду: 
git clone https://github.com/google-ai-edge/mediapipe-samples
 - При желании настройте свой экземпляр git на использование разреженной проверки, чтобы у вас были только файлы для примера приложения классификатора изображений: 
cd mediapipe-samples 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]
        }
    }
}