Обнаружение лиц на изображении с помощью мобильного машинного обучения

Создание точных моделей машинного обучения, способных идентифицировать несколько лиц (или других целевых объектов) на одном изображении, остается основной проблемой компьютерного зрения, но теперь, с развитием моделей глубокого обучения и компьютерного зрения для мобильных устройств, вы можете гораздо проще определять лица. в образе.

В этой статье мы сделаем это на Android с помощью API распознавания лиц Google ML Kit.

Что такое распознавание лиц?

Обнаружение лиц - это задача компьютерного зрения, с помощью которой вы можете обнаруживать лица на изображении, а также обнаруживать различные части лица, известные как ориентиры. Ориентиры здесь - это части человеческих лиц, такие как eyes, ears, nose, cheeks, mouth, и т. Д.

Вы также можете получить контуры обнаруженных лиц - то есть, если у вас включено обнаружение контуров лица, вы также получите список точек для каждой обнаруженной черты лица, например LEFT_EYE, RIGHT_EYE, NOSE_BOTTOM для справки ниже - это изображение обнаруженного лица контуров. 👇

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

Возможные варианты использования

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

  • Добавление тегов к фотографиям
  • Проверка лица
  • Фильтры / линзы для лица
  • Подсчет толпы

Что такое комплект ML?

ML Kit - это кроссплатформенный мобильный SDK (Android и iOS), разработанный Google, который позволяет разработчикам легко получать доступ к моделям мобильного машинного обучения на устройстве.

Все API-интерфейсы ML Kit работают на устройстве, что позволяет работать как в режиме реального времени, так и в автономном режиме.

Чтобы использовать автономный SDK ML Kit на устройстве, мы можем просто реализовать его напрямую - нам не нужно создавать проект на Firebase и сопутствующий google.json файл.

Если вы используете Firebase Machine Learning, вы можете проверить эту ссылку, чтобы облегчить миграцию.

Примечание. В настоящее время это бета-версия ML Kit. Этот API может быть изменен, что означает, что изменения API могут быть добавлены до стабильной версии.

Что вы построите

В этой статье мы собираемся создать простое приложение для Android, которое покажет вам, как реализовать API распознавания лиц ML Kit на устройстве.

Есть два способа интегрировать функцию распознавания лиц в Android.

  • комплектная модель (которая является частью вашего приложения)
  • разделенная модель (зависит от сервисов Google Play)

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

К концу этого урока вы должны увидеть что-то похожее на снимок экрана ниже:

Шаг 1. Добавьте зависимость

Перво-наперво, нам нужно добавить mlkit:face-detection зависимость к нашему проекту Android в app/build.gradle файле.

Чтобы объединить модель в свое приложение:

dependencies {
      // ...
      // Use this dependency to bundle the model with your app
      implementation 'com.google.mlkit:face-detection:16.0.2'
    }

Для использования модели в сервисах Google Play:

dependencies {
      // ...
      // Use this dependency to use dynamically downloaded model in Google Play Service
      implementation 'com.google.android.gms:play-services-mlkit-face-detection:16.1.1'
    }

Примечание. На момент написания последней версией com.google.mlkit: face-detection была 16.0.2, но вы можете использовать любой из последних стабильных выпусков из Примечаний к выпуску ML Kit.

Синхронизировать проект

После успешного добавления зависимости просто синхронизируйте проект, как показано на скриншоте ниже:

Шаг 2: Настройте детектор лиц

Чтобы настроить параметры детектора лиц по умолчанию, у нас есть ряд настроек детектора лиц, которые мы можем указать с помощью объекта FaceDetectorOptions.

  • setPerformanceMode: определяет скорость или точность прогнозирования модели при обнаружении лиц, и значение по умолчанию - FAST.
  • setLandmarkMode: определяет, обнаруживать ли черты лица, например глаза, уши, нос, щеки, рот и т. д., и т. д. Значение по умолчанию - NO_LANDMARKS
  • setContourMode: определяет, определять ли контуры черт лица или нет. Значение по умолчанию - NO_CONTOURS.
  • setClassificationMode: с помощью этого параметра вы можете классифицировать лица по таким категориям, как улыбающиеся, открытые глаза и т. д. Значение по умолчанию - NO_CLASSIFICATIONS
  • setMinFaceSize: этот параметр определяет минимальный размер лица, поскольку он связан с отношением ширины головы к ширине изображения. Значение по умолчанию - 0.1f.
  • enableTracking: определяет , хотите ли вы назначать идентификатор лица, который можно использовать для отслеживания лиц на изображениях. Значение по умолчанию - false.

Теперь давайте перейдем к коду, чтобы увидеть, как эти шаги выглядят на практике:

val options = FaceDetectorOptions.Builder()
    .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE)
    .setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL)
 .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL)
    .build()

Шаг 3. Подготовьте входное изображение

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

  • Битовая карта
  • media.Image
  • ByteBuffer
  • ByteArray
  • Файл

media.Image:

Это используется при захвате изображения с камеры устройства.

val image = InputImage.fromMediaImage(mediaImage,rotation)

ByteBuffer или ByteArray

Мы также можем создать входное изображение с помощью byteBuffer или ByteArray - для этого нам нужно создать объект InputImage с буфером или массивом вместе с высотой, шириной, форматом кодировки цвета и степенью поворота изображения:

val image = InputImage.fromByteBuffer(
        byteBuffer,
        /* image width */ 480,
        /* image height */ 360,
        rotation,
        InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12
)
// Or:
val image = InputImage.fromByteArray(
        byteArray,
        /* image width */ 480,
        /* image height */ 360,
        rotation,
        InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12
)

Файл

Чтобы создать экземпляр входного изображения, нам нужно передать контекст приложения и URI файла в InputImage.fromFilePath

val image: InputImage
try {
    image = InputImage.fromFilePath(context, uri)
} catch (e: IOException) {
    e.printStackTrace()
}

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

val bitmap = (imageView.drawable as BitmapDrawable).bitmap
val image = InputImage.fromBitmap(bitmap, 0)

Примечание: входное изображение должно иметь размер не менее 480x360 пикселей для распознавания лиц.

Шаг 4. Создайте экземпляр детектора лица.

На шаге 4 мы создаем экземпляр детектора лиц, используя метод FaceDetection.getClient, и передаем экземпляр FaceDetectorOptions в качестве параметра. Или, если вы хотите использовать настройки по умолчанию, тогда нет необходимости передавать экземпляр FaceDetectorOptions в качестве параметра.

Теперь давайте перейдем к коду, чтобы увидеть, как эти шаги выглядят на практике:

С FaceDetectorOptions

val detector = FaceDetection.getClient(options)

Без FaceDetectorOptions:

// Or, to use the default option:
// val detector = FaceDetection.getClient();

Шаг 5: отправьте изображение в детектор лиц и обработайте изображение

На шаге 5 нам нужно передать изображение в детектор лиц через process().

После этого мы вызываем process на детекторе лиц, который передает входное изображение в качестве параметра. Мы также используем onSuccessListener, чтобы определить, когда обнаружение лица завершено. В случае успеха мы можем получить доступ к списку Faces и нарисовать Rect (ограничивающую рамку) на обнаруженных лицах.

Мы также добавляем OnFailureListener - если обработка изображения завершится неудачно, мы сможем показать пользователю ошибку.

Теперь давайте перейдем к коду, чтобы увидеть, как эти шаги выглядят на практике:

detector.process(image)
    .addOnSuccessListener { faces ->
  // call draw canvas class
      
    }
    .addOnFailureListener { e ->
        // Task failed with an exception
        Toast.makeText(baseContext, "Oops, something went wrong!",
            Toast.LENGTH_SHORT).show()
    }

Нарисуйте холст на обнаруженных лицах:

Чтобы нарисовать холст на обнаруженных лицах, нам нужно сначала создать класс со списком <Face> в качестве конструктора и расширить этот класс с помощью View.

В методе onDraw нам нужно сначала создать объект Paint, а затем выполнить итерацию по списку объекта Face. На этой итерации нам нужно установить такие параметры рисования, как цвет, ширину штриха и стиль, а после этого нам нужно просто передать координаты ограничивающего прямоугольника и объект Paint в метод canvas.drawRect.

Вот класс DrawRect.kt, чтобы увидеть, как эти шаги выглядят на практике:

class DrawRect(context: Context, var faceObject: List<Face>) : View(context) {
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        val pen = Paint()
        for (item in faceObject) {
            // draw bounding box
            pen.color = Color.RED
            pen.strokeWidth = 8F
            pen.style = Paint.Style.STROKE
            val box = item.boundingBox
            canvas.drawRect(box, pen)
        }
    }
}

Вызов класса DrawRect для рисования холста:

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

Сначала в методе onSuccessListener нам нужно создать экземпляр нашего класса DrawRect, вызвать метод draw и передать растровое изображение, которое мы создали ранее. После этого нам нужно установить наше обнаруженное изображение лица как растровое изображение.

Теперь давайте перейдем к коду, чтобы увидеть, как эти шаги выглядят на практике:

detector.process(image)
    .addOnSuccessListener { faces ->
        // Task completed successfully
        val drawingView = DrawRect(applicationContext, faces)
        drawingView.draw(Canvas(bitmap))
        runOnUiThread { sampleImage.setImageBitmap(bitmap) }
  
    }

Результат

Давайте создадим и запустим приложение, чтобы увидеть нашу модель распознавания лиц на практике:

Вывод

Из этой статьи вы узнали, как реализовать API распознавания лиц ML Kit на устройстве на Android. Для этого мы узнали, как настроить FaceDetectorOptions, подготовить входное изображение, создать экземпляр FaceDetector и, наконец, обработать выбранное изображение.

Мы также создали простое приложение, которое может извлекать изображения локально из папки ресурсов, то есть (папка с возможностью рисования), и передавать это растровое изображение в InputImage.fromBitmap(bitmap, 0). После обнаружения лиц из API мы затем показали список лиц, и из этого списка мы смогли провести точную границу.

Если вы хотите изучить обнаружение лиц более подробно, ознакомьтесь с официальной документацией:



Надеюсь, эта статья была полезной. Если вы думаете, что чего-то не хватает, у вас есть вопросы или вы хотите высказать свои мысли или предложения, оставьте комментарий ниже. Буду признателен за отзыв.

Я написал другой контент, связанный с Android, и если вам понравилось то, что вы здесь прочитали, вам, вероятно, понравится и этот:







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

Независимая редакция, Heartbeat спонсируется и публикуется Comet, платформой MLOps, которая позволяет специалистам по обработке данных и группам машинного обучения отслеживать, сравнивать, объяснять и оптимизировать свои эксперименты. Мы платим участникам и не продаем рекламу.

Если вы хотите внести свой вклад, отправляйтесь на наш призыв к участникам. Вы также можете подписаться на наши еженедельные информационные бюллетени (Deep Learning Weekly и Comet Newsletter), присоединиться к нам в » «Slack и подписаться на Comet в Twitter и LinkedIn для получения ресурсов, событий и гораздо больше, что поможет вам быстрее и лучше строить модели машинного обучения.