В этой статье я расскажу, как написать приложение для 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://oleg-sta.github.io/site/2021/android-augmented-reality.html