Это расширение моей последней статьи Compose CameraX для Android. Если вы хотите узнать, как настроить предварительный просмотр с помощью Jetpack compose и CameraX, вы можете прочитать мою предыдущую статью здесь. В этом посте будет описано, как использовать функцию захвата и анализа изображений с библиотекой машинного обучения (ML) для создания смарт-камеры CameraX. Пользователь может использовать жест руки, чтобы запустить действие захвата изображения и отобразить захваченное изображение.

вступление

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

В этой статье я добавлю эту функцию с помощью распознавания жестов рук. Существует несколько библиотек машинного обучения, которые вы можете использовать на Android для распознавания жестов рук, например Tensor flow lite, Huawei ML Kit или Pytorch Mobile. Я буду использовать комплект Huawei ML в этой демонстрации, так как он имеет модель жестов, уже интегрированную в библиотеку жестов рук, но код и идею можно легко адаптировать к другим библиотекам машинного обучения.

Подготовка

Вот краткий обзор изменений, которые я внес с момента публикации предыдущей статьи.

  • Сначала я добавил анализатор жестов, который использует API распознавания жестов для обнаружения жеста руки большой палец вверх.
  • Чтобы использовать вариант использования захвата изображения, я создал ViewModle для обработки настройки варианта использования захвата изображения и обратного вызова распознавания жестов.
  • Чтобы отобразить захваченное изображение, создается составное представление изображения, которое уведомляет MediaScannerConnection о добавлении нового захваченного изображения поставщику мультимедийного контента.

Настроить библиотеку Huawei ML очень просто, так как обучающая модель уже включена в библиотеку, вам просто нужно добавить адрес центра maven и зависимости библиотеки жестов ML. Вы можете найти более подробную информацию здесь и о зависимостях, установленных здесь.

Если вы хотите ознакомиться с изменениями, вы можете посмотреть репо здесь. Вы также можете проверить код из этого репо, если хотите следовать ему самостоятельно.

Реализация обнаружения жестов

Сначала я начну определение жестов для кадра камеры.

Использовать анализатор ML действительно просто: создайте экземпляр и вызовите метод анализа для анализа MLFrame. Есть несколько способов создать MLFrame из изображений, таких как растровое изображение, байтовый буфер или Android Image. В этой демонстрации изображение Android используется для создания MLFrame, поскольку ImageProxy уже обертывает его. Но вам нужно добавить аннотацию UnsafeExperimentalUsageError, поскольку этот метод все еще находится в стадии эксперимента и может возвращать значение null, если ImageProxy не может обернуть изображение Android.

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

Поскольку процесс анализа изображения может быть медленнее, чем вызов analyze метода, используется простой флаг, чтобы избежать одновременного анализа нескольких изображений. После анализа, независимо от успеха или неудачи, вы должны закрыть ссылку на прокси-сервер изображения, чтобы избежать исключения. Как только жест рукой будет обнаружен, будет задействован обратный вызов onGestureDected, чтобы проверить, является ли это жестом поднятого вверх большого пальца, и начать действие захвата изображения.

Реализация захвата изображения

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

  • CaptureMode: вы можете выбрать CAPTURE_MODE_MINIMIZE_LATENCY, чтобы минимизировать задержку, или CAPTURE_MODE_MAXIMIZE_QUALITY, чтобы оптимизировать качество. Здесь мы сначала используем задержку, чтобы захватить изображение сразу после обнаружения жеста.
  • TargetRotation: это должно быть то же самое для конфигурации отображения или предварительного просмотра. Вы можете легко получить значение из view.display.rotation. Более подробную информацию о вращении в CameraX вы можете найти здесь.
val imageCapture = ImageCapture.Builder()
    .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
    .setTargetRotation(rotation)
    .build()

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

Вы можете сохранить захваченные изображения либо в буфере памяти, либо в локальном файле, в зависимости от используемого вами метода. Мы будем использовать опцию локального файла, чтобы мы могли также просмотреть захваченное изображение в галерее изображений. Чтобы сохранить файл изображения локально, вам необходимо указать расположение папки, имя файла и формат для настройки OutputFileOptions. Прямо сейчас JPEG полностью поддерживается. Если вы хотите сохранить в другом формате, вы можете проверить конвертер YUV в RGB здесь. OutputFileResults вернет savedUri при сохранении изображения, которое мы можем использовать позже для отображения и уведомления поставщика мультимедиа.

Показать захваченное изображение

Запустив приложение в этом состоянии, вы увидите, что действие захвата изображения может быть запущено с помощью жеста из приложения. Это здорово, но было бы неплохо, если бы мы автоматически отображали захваченное изображение на несколько секунд после того, как оно сохранено локально. Давайте соединим все вместе и создадим цикл обновления состояния / события, который выглядит следующим образом:

Составное Изображение не имеет удобного способа отображения локального изображения с файлом Uri прямо сейчас. Но вы можете использовать аккомпаниатор - библиотеку утилит для Jetpack Compose, в которую интегрированы популярные библиотеки загрузки изображений. Здесь используется библиотека Glide. Как только Uri файла изображения станет доступным, GlidePainter начнет загружать изображение в Image составной объект, и MediaScannerConnection получит уведомление.

Вот и все! Мы реализовали простую камеру с жестами рук, используя Jetpack compose, CameraX и комплект Huawei ML.

Резюме

В этой статье я добавил функцию захвата изображений с помощью Jetpack Compose и CameraX. При распознавании жеста приложение запускает захват изображения и отображает захваченное изображение, если обнаружен жест большой палец вверх. Эту концепцию можно легко адаптировать для видеозаписи, для чего вам просто нужно изменить захват изображения на захват видео (startRecording и stopRecording, в значительной степени экспериментальный) из CameraX. Распознавание жеста руки также может быть расширено до положения тела, распознавания объектов или даже голосовой команды (вы можете найти мою другую статью про игру 2048 с голосом здесь). Бесплатно бесплатно форк репо и создай свой умный CameraX. Я хотел бы услышать о том, что вы построили!