Создание Android приложения для обнаружения лиц в режиме реального времени с использованием Firebase ML Kit
В начале этого года Google представил новый продукт: Firebase Machine Learning Kit. ML Kit позволяет эффективно использовать возможности машинного обучения в Android и iOS приложениях. В этом посте я буду рассказывать о том, как с его помощью создать Android приложение для обнаружения лиц в реальном времени.
Обнаружение лиц — это только одна из возможностей компьютерного зрения, которую предлагает Firebase ML Kit (или, вернее, облегчает её использование). Это функция, которая может быть полезна во многих приложениях: подписывание людей на фотографиях, работа с селфи, добавление эмоджи и других эффектов во время съёмки, фотографирование только тогда, когда все улыбаются с открытыми глазами, и т.д. Возможности безграничны.
Мы уже публиковали статьи о других функциях Firebase ML Kit:
Однако, реализовать детектор лиц в собственном приложении по-прежнему нелегко. Нужно понять, как работает API, какую информацию он предоставляет, как её обрабатывать и использовать, учитывая ориентацию устройства, источник камеры и выбранную камеру (переднюю или заднюю).
В идеале мы должны получить код вроде этого:
camera.addFrameProcessor { frame -> faceDetector.detectFaces(frame) }
Основные компоненты здесь — это camera, frame, faceDetector. Прежде чем разобраться с каждым из них, предположим, что наш layout содержит сам компонент камеры и некий оверлей, на котором мы будем рисовать квадратики вокруг обнаруженных лиц.
<FrameLayout ...> // Any other views <CameraView ... /> <husaynhakeem.io.facedetector.FaceBoundsOverlay ... /> // Any other views </FrameLayout>
Камера (Camera)
Независимо от того, какой API-интерфейс камеры мы используем, самое главное, чтобы он предоставлял способ обработки отдельных кадров. Таким образом, мы сможем обрабатывать каждый входящий кадр, идентифицировать лица в нём и отображать это пользователю.
Кадр (Frame)
Кадр представляет собой информацию, предоставленную камерой, для обнаружения лиц. Он должен содержать всё, что требуется детектору лиц для их обнаружения. Эта необходимая информация определяется ниже:
data class Frame( val data: ByteArray?, val rotation: Int, val size: Size, val format: Int, val isCameraFacingBack: Boolean) data class Size(val width: Int, val height: Int)
- data — массив байтов, содержащий информацию о том, что камера отображает;
- rotation — ориентация устройства;
- size — ширина и высота предпросмотра камеры;
- format — формат кодирования кадров;
- isCameraFacingBack — указывает, используется ли передняя камера или задняя.
Детектор лиц (Face Detector)
Детектор лиц является самым важным компонентом — он берёт кадр, обрабатывает его и затем выводит результаты пользователю. Таким образом, детектор лиц использует экземпляр FirebaseVisionFaceDetector
для обработки входящих кадров с камеры. Он также должен знать ориентацию камеры и её направление (передняя или задняя). Наконец, он должен знать на каком оверлее будут отображаться результаты. Скелет класса FaceDetector
выглядит так:
class FaceDetector(private val faceBoundsOverlay: FaceBoundsOverlay) { private val faceBoundsOverlayHandler = FaceBoundsOverlayHandler() private val firebaseFaceDetectorWrapper = FirebaseFaceDetectorWrapper() fun process(frame: Frame) { updateOverlayAttributes(frame) detectFacesIn(frame) } private fun updateOverlayAttributes(frame: Frame) { faceBoundsOverlayHandler.updateOverlayAttributes(...) } private fun detectFacesIn(frame: Frame) { firebaseFaceDetectorWrapper.process( image = convertFrameToImage(frame), onSuccess = { faceBoundsOverlay.updateFaces( /* Faces */) }, onError = { /* Display error message */ }) } }
Оверлей (Overlay)
Оверлей — это View-компонент, который находится поверх камеры. Он отображает рамки (или границы) вокруг обнаруженных лиц. Он должен знать ориентацию устройства, направление камеры (передняя или задняя) и размеры камеры (ширина и высота). Эта информация помогает определить, как рисовать границы вокруг обнаруженного лица, как масштабировать границы и следует ли их отражать.
class FaceBoundsOverlay @JvmOverloads constructor( ctx: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(ctx, attrs, defStyleAttr) { private val facesBounds: MutableList<FaceBounds> = mutableListOf() fun updateFaces(bounds: List<FaceBounds>) { facesBounds.clear() facesBounds.addAll(bounds) invalidate() } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) facesBounds.forEach { val centerX = /* Compute the center's x coordinate */ val centerY = /* Compute the center's ycoordinate */ drawBounds(it.box, canvas, centerX, centerY) } } private fun drawBounds(box: Rect, canvas: Canvas, centerX: Float, centerY: Float) { /* Compute the positions left, right, top and bottom */ canvas.drawRect( left, top, right, bottom, boundsPaint) } }
На приведённой ниже диаграмме показаны компоненты, описанные выше, и способы взаимодействия их друг с другом с момента, когда камера подаёт на вход кадр, до момента, когда результаты отображаются пользователю.
Создание приложения для обнаружения лиц в реальном времени за 3 шага
Используя библиотеку для обнаружения лиц (которая содержит код, описанный выше), создание приложения становится довольно простым.
В этом примере я выбрал следующую библиотеку камеры.
Шаг 1. Добавьте FaceBoundsOverlay
поверх камеры.
<FrameLayout ...> // Any other views <CameraView ... /> <husaynhakeem.io.facedetector.FaceBoundsOverlay ... /> // Any other views </FrameLayout>
Шаг 2. Определите экземпляр FaceDetection
и подключите его к камере.
private val faceDetector: FaceDetector by lazy { FaceDetector(facesBoundsOverlay) } cameraView.addFrameProcessor { faceDetector.process(Frame( data = it.data, rotation = it.rotation, size = Size(it.size.width, it.size.height), format = it.format)) }
Шаг 3. Настройте Firebase в проекте.
Заключение
Обнаружение лиц — это мощный функционал, а ML Kit делает его доступным и позволяет разработчикам выполнять с его помощью более сложные функции, такие как распознавание лиц, что выходит за рамки простого обнаружения: важно не только обнаружить лицо, но и определить, чьё оно.
Скоро в Ml Kit планируют добавить новую функцию — распознавание контура лица. С её помощью можно будет обнаруживать более 100 точек вокруг лица и быстро обрабатывать их. Это потенциально может быть полезно в приложениях с использованием объектов дополненной реальности или виртуальных стикеров (таких как Snapchat). Вместе функционалом обнаружения лиц можно будет создать много интересных приложений.

