Может быть, вам было интересно, как можно размещать забавные объекты на лицах в видеочатах в реальном времени или обнаруживать эмоции? Здесь я покажу вам один из возможных подходов с использованием глубокого обучения, а также опущу один старый подход.

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

«Классический» метод (CLM)

Если вы были похожи на меня и у вас была потребность в отслеживании лиц (в моем случае для передачи жестов с веб-камеры анимированному персонажу), вы, вероятно, узнали, что одним из наиболее эффективных алгоритмов была ограниченная локальная модель ( CLM ), как реализовано, например, Cambridge Face Tracker или его более новая версия OpenFace. Это основано на разделении задач обнаружения на обнаружение функций вектора формы (ASM) и шаблонов изображений патчей (AAM), а также на уточнении обнаружения с помощью предварительно обученной линейной SVM.

Он работает, сначала грубо оценивая положения ключевых точек, затем применяя SVM с предварительно обученными изображениями, содержащими части лица, и регулируя положения ключевых точек. Это повторяется до тех пор, пока ошибка не станет достаточно низкой для наших целей. Также стоит упомянуть, что предполагается, что положение лица на изображении уже было оценено, например с помощью детектора Виолы-Джонса (Каскады Хаара). Однако процесс CLM довольно сложен и нетривиален, и определенно не будет реализован волшебником средней школы. Здесь вы можете увидеть общую архитектуру:

Глубокое обучение

Вместо этого мы можем использовать очень простую сверточную нейронную сеть (CNN) и выполнять обнаружение ключевых точек на частях изображений, которые, как мы ожидаем, содержат лица. Для этого нам нужен обучающий набор данных; мы можем использовать тот, который предоставлен Kaggle для их задачи по обнаружению ключевых точек лица, содержащий 15 ключевых точек, или более сложный набор данных MUCT с 76 ключевыми точками (Ура!).

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

Вот как будет выглядеть образец лица в стиле барокко и его ключевые точки в наборе данных Kaggle:

Набор данных содержит изображения в оттенках серого с разрешением 96x96 и 15 ключевыми точками, по 5 на каждый глаз и 5 для положений рта / носа.

Для произвольного изображения нам сначала нужно определить, где на изображении находятся лица; Можно использовать вышеупомянутый детектор Виолы-Джонса на основе каскадов Хаара (и если вы посмотрите, как он работает, он немного напоминает CNN). Или, если вы любите приключения, вы также можете использовать полностью сверточные сети (FCN) и выполнять сегментацию изображения с оценкой глубины.

В любом случае, с использованием OpenCV это проще простого:

Grayscale_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
face_cascade = cv2.CascadeClassifier(‘haarcascade_frontalface_default.xml’)
bounding_boxes = face_cascade.detectMultiScale(grayscale_image, 1.25, 6)

Этот фрагмент кода возвращает все возможные ограничивающие рамки лица на изображении.

Затем для каждого ограничивающего прямоугольника, возвращенного Виолой-Джонсом, мы извлекаем соответствующие фрагменты изображения, конвертируем их в оттенки серого и изменяем их размер до 96x96. И они станут входными данными для нашего законченного CNN для вывода.

Архитектура CNN супертривиальна; связка из сверточных слоев 5x5 (на самом деле 3, с 24, 36 и 48 фильтрами каждый), затем еще 2 сверточных слоя 3x3 (по 64 фильтра каждый) и 3 полностью связанных слоя (с 500, 90 и 30 узлами) в конце. Некоторое максимальное объединение для предотвращения переобучения и глобальное среднее объединение для уменьшения количества сглаживаемых параметров. На выходе будет 30 чисел с плавающей запятой, обозначающих последовательность координат x, y для каждой из 15 ключевых точек.

Вот реализация в Керасе:

model = Sequential()
model.add(BatchNormalization(input_shape=(96, 96, 1)))
model.add(Convolution2D(24, 5, 5, border_mode=”same”, init=’he_normal’, input_shape=(96, 96, 1), dim_ordering=”tf”))
model.add(Activation(“relu”))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), border_mode=”valid”))
model.add(Convolution2D(36, 5, 5))
model.add(Activation(“relu”))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), border_mode=”valid”))
model.add(Convolution2D(48, 5, 5))
model.add(Activation(“relu”))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), border_mode=”valid”))
model.add(Convolution2D(64, 3, 3))
model.add(Activation(“relu”))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), border_mode=”valid”))
model.add(Convolution2D(64, 3, 3))
model.add(Activation(“relu”))
model.add(GlobalAveragePooling2D());
model.add(Dense(500, activation=”relu”))
model.add(Dense(90, activation=”relu”))
model.add(Dense(30))

Вы можете выбрать оптимизатор Среднеквадратичное распространение (rmsprop) и Среднеквадратичную ошибку (MSE) в качестве функции потерь и показателей точности.

Всего лишь с помощью некоторых тривиальных уловок, таких как пакетная нормализация входных изображений, глобальное объединение средних значений, а также нормальная инициализация веса, вы можете получить точность проверки 80–90% и потерю

model.compile(optimizer=’rmsprop’, loss=’mse’, metrics=[‘accuracy’])
checkpointer = ModelCheckpoint(filepath=’face_model.h5', verbose=1, save_best_only=True)
epochs = 30
hist = model.fit(X_train, y_train, validation_split=0.2, shuffle=True, epochs=epochs, batch_size=20, callbacks=[checkpointer], verbose=1)

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

features = model.predict(region, batch_size=1)

ааа и все! Теперь вы овладели искусством определения ключевых точек лица!

Имейте в виду, что результатом вашего прогноза будет 15 пар координат x, y для каждой ключевой точки в порядке, показанном на следующем рисунке:

Если вы хотите добиться большего успеха, вы можете сделать дополнительную домашнюю работу:

  • поэкспериментируйте, как уменьшить количество сверточных слоев и размеры фильтров, сохраняя точность и повышая скорость вывода.
  • заменить сверточную часть на трансферное обучение (Xception - мой любимый)
  • использовать более подробный набор данных
  • выполнить некоторое расширенное увеличение изображения для повышения надежности

Вам может показаться, что все это слишком просто; Если вы хотите испытать себя, переходите в 3D и посмотрите, как Facebook и NVidia отслеживают лица.

Очевидно, вы можете использовать эту недавно изученную магию для выполнения некоторых нетривиальных вещей, которые вы, возможно, всегда хотели делать, но не знали, как:

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

Итак, теперь вы знаете, как создать свой собственный замечательный фильтр для видеочата! Как насчет того, чтобы написать прямо сейчас?