В этой статье я расскажу, как написать приложение для Android с эффектами на лицо с камеры в реальном времени. Здесь мы рассмотрим все ключевые моменты: работа с камерой, поиск лица, поиск точек на лице и результат рисования.
Работа с камерой
Первое, что нам нужно сделать, это получить изображение с камеры. Android API предоставляет нам пакет android.hardware.camera2
. Для начала вам нужно выбрать камеру, получив все доступные камеры Camera.getNumberOfCameras()
. Здесь вы должны указать, какую камеру вы хотите использовать, а затем открыть камеру:
mCamera = Camera.open(cameraIndex);
Затем вам нужно выбрать параметры предварительного просмотра:
Camera.Parameters params = mCamera.getParameters();
params.setPreviewFormat(ImageFormat.NV21);
List<Camera.Size> psize = params.getSupportedPreviewSizes();
Среди List
размеров превью выберите наиболее подходящий. Лучше выбирать с размером экрана, близким к размеру экрана.
Другой сложный момент - запустить предварительный просмотр. Вам необходимо установить буфер и обратный вызов предварительного просмотра
int size = cameraWidth * cameraHeight;
size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8;
mBuffer = new byte[size];
mCamera.addCallbackBuffer(mBuffer);
mCamera.setPreviewCallbackWithBuffer(preview);
Для предварительного просмотра нужно реализовать только один метод void onPreviewFrame(byte[] data, Camera camera)
. Где data
- это кадр предварительного просмотра с камеры, вы будете получать его в цикле всякий раз, когда предварительный просмотр рассчитывается с камеры и вы отпустили метод. Одна вещь, которую следует упомянуть, наш кадр предварительного просмотра в формате NV21
, короче это формат изображения. Где он разделен на 2 части: серое изображение и цветное. Это очень полезно, потому что следующие два шага - это поиск лица и точки, что выполняется на сером изображении, и нам не нужно выполнять дополнительные вычисления, чтобы найти серое изображение, просто получите первую часть буфера.
В поисках лица
Есть разные способы найти лицо на экране. Мы собираемся использовать самые популярные заячьи фишки.
Этот алгоритм уже реализован в OpenCV, одной из самых популярных библиотек для компьютерного зрения. Написано на C/C++
. Что касается машинного обучения, нам нужно обучить нашу модель. Для этого нам нужны тысячи фотографий с лицами и без лиц. Затем алгоритм будет обучен и создаст модель, которую можно было бы использовать. Нам не нужно этого делать, все уже сделано face_detection
методом вместе с моделью.
Нахождение точек на лице
На лице мы должны найти определенные точки, чтобы понять ориентацию лица и выражение лица. Для этого воспользуемся библиотекой dlib. Это также популярная библиотека для машинного обучения, написанная на C ++. Пример нахождения точек на лице здесь http://dlib.net/face_landmark_detection_ex.cpp.html. Как написано, вы можете использовать готовую модель http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2.
Ориентация и выражение лица
Когда у нас есть 68 точек на экране, нам нужно рассчитать ориентацию лица и выражение лица, например открытая челюсть. Для этого воспользуемся 3d моделью лица. Нам нужно иметь точки на 3D-грани и соответствующие точки среди 68 точек. Если мы хотим найти выражение лица, мы должны решить уравнение:
dst = argmin X ∥ src1⋅ X − src2∥
методом разложения СВД. Где:
- scr1–3d модель
- X - преобразования на модели, в том числе проекция на поверхность
- scr2 - найденные точки на изображении
т.е. мы пытаемся найти те X, где погрешность будет минимальной. Это будут наши коэффициенты лица.
Эффекты рисования
Зная ориентацию лица и выражение лица. Мы могли записать результат с помощью OpenGL (Open Graphics Library). Это кроссплатформенный язык для использования графических процессоров (графических процессоров) для двух- и трехмерной графики. Он может выполнять множество простых вычислений параллельно. Основной термин - шейдеры. Шейдеры - это программы, которые применяются на GPU. Есть два основных шейдера: вершинный и фрагментный. Вершинные шейдеры для вычисления точек. И фрагментирует шейдеры для обеспечения цвета для каждого пикселя. Шейдеры могли использовать текстуры. Текстура - это 2-мерное изображение для шейдера, примеры - маски для лица и превью камеры ввода, где мы применяем текстуру.
Вывод
В целом для создания этого эффекта нам пришлось использовать:
- камера - получить изображение с камеры
- OpenCV - библиотека для поиска лица и вычисления ориентации и выражения лица
- dlib - библиотека для поиска точки на грани
- OpenGL - рисование эффектов с помощью графического процессора Android
И в результате у нас есть приложение для Android, которое может все это делать.
Исходники библиотеки, выполняющей все вышеперечисленное, вы можете найти здесь https://github.com/oleg-sta/VrFace
Примеры использования библиотеки:
- Https://github.com/oleg-sta/FaceMaskExample
- Https://github.com/oleg-sta/Masks
- Https://github.com/oleg-sta/MakeUp
исходная статья опубликована здесь https://oleg-sta.github.io/site/2021/android-augmented-reality.html