Кликбейт
Кликбейт

Лицевые анимации - часть общей анимации модели, описывающая движения частей лица модели. Хотя развитие компьютерной графики методов лицевой анимации началось в начале 1970-х годов, основные достижения в этой области являются более поздними и произошло с конца 1980 - х годов. Однако по сей день, существующие способы анимации не являются совершенными и часто требуют дополнительных конструкций или маркеров для достижения необходимого качества анимации.

Давайте попробуем собрать что-нибудь на колене так, чтобы оно ещё и ожило. Статья о том, как я лицевые анимации костылил, что из этого вышло или не вышло.

Введение

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

По моему маленьку расследованию, в настоящее время чуществуют следующие методы:

  • Создание маркеров на основе захвата движения по точкам или отметинам на лице исполнителя 

    • Методы, использующие камеры, размещенные вокруг объекта и точки, нанесённые на лицо актёра или естественные отметины на коже для точного определения положения лица в пространстве 

  • Безмаркерные методы с использованием различных типов камер

    • Методы, использующие различные способы создания карты глубин, такие, как камеры Kinect или Intel Real Sense

  • Звуко-управляемые методы 

    • Методы, использующие скрытые марковские модели или нейронные сети для преобразования звуковых параметров в поток управляющих параметров для модели лица.

  • Анимация по ключевым кадрам

    • Методы, использующие классический способ анимации, при котором различные части модели лица смещаются вручную 

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

  1. Автоматизированность

  2. Отсутствие необходимости в использовании дорогостоящего оборудования

  3. Относительная точность передачи положения лица в пространства

  4. Отсутствие необходимости использования дополнительных маркеров

Выборка

Чтобы собрать что-то дельное, необходимо составить математическую модель того, что мы собираемся делать. Ну или хотя бы понять, как вообще мы будем определять качество итогового результата? Поэтому

Благо лиц в интернете достаточно. Так что в качестве тестовых данных я выбрал четырёх популярных персонажей. Важное замечание: все видео сохранены в 2х различных форматах, имеют различные условия освещения.

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

Так выглядят три последовательных кадра и параметры, которые мы оцениваем на них. Данные собираются автоматически в процессе построения опорных точек. Основные параметры, которые я собрал включают в себя:

  • Rele - расстояние между левым и правым глазом, показывающее искажение верхней части лица 

  • Ren - расстояние между правым глазом и носом, показывающее искажение правой скулы

  • Len - расстояние между левым глазом и носом, показывающее искажение левой скулы

  • Chin 1-8 - набор расстояний, состоящих из расстояний между левой и правой частью лица, показывающий общее искажение лица 

Поговорим о том, что эти параметры собой представляют.

Параметр rele

Пусть (x,y,z) координаты центра левого и правого глаза вычисляются последовательно для каждого кадра по следующим формулам:

x =  \frac{\sum_{i=m}^{n}{a_{i_0}+a} }{n+1}\\y =  \frac{\sum_{i=m}^{n}{a_{i_1}+a} }{n+1}\\ z =  \frac{\sum_{i=m}^{n}{a_{i_2}+a} }{n+1}

Список значений rele хранит в себе длину вектора AB, где A-координата центра левого глаза, B-координата центра правого глаза соответственно, а равно, расстояние между центрами левого и правого глаза. Пусть каждое значение списка rele вычисляется по следующей формуле для каждого кадра:

rele_i =  \sqrt{(x_{left}-x_{right})^2+(y_{left}-y_{right})^2+(z_{left}-z_{right})^2}

Тогда значение rele для всех кадров, пропорционально их количеству будем вычислять по следующей формуле, где - количество кадров анимации:

rele = \frac{ \sum_{i=m}^{n}{\frac{rele_i}{rele_0}} }{a}

Значение rele показывает среднее изменение длины вектора AB - расстояния между центрами правого и левого глаза. Из чего можем провести следующую зависимость:

“Чем меньше значение функции rele для видеофайла, тем меньше изменялись основные пропорции лица, а равно, тем (предположительно) лучше качество конечной анимации”

Параметр len

Пусть (x,y,z) координаты центра левого глаза вычисляются последовательно для каждого кадра по следующим формулам:

x =  \frac{\sum_{i=m}^{n}{a_{i_0}+a} }{n+1}\\y =  \frac{\sum_{i=m}^{n}{a_{i_1}+a} }{n+1}\\ z =  \frac{\sum_{i=m}^{n}{a_{i_2}+a} }{n+1}

Список значений len хранит в себе длину вектораAB, где A-координата центра левого глаза, B-координата конца носа, а равно, расстояние между центром левого глаза и концом носа. Пусть каждое значение списка len вычисляется по следующей формуле для каждого кадра:

len_i =  \sqrt{(x_{left}-x_{nose})^2+(y_{left}-y_{nose})^2+(z_{left}-z_{nose})^2}

Тогда значение len для всех кадров, пропорционально их количеству будем вычислять по следующей формуле, где - количество кадров анимации:

len = \frac{ \sum_{i=m}^{n}{\frac{len_i}{len_0}} }{a}

Значение len показывает среднее изменение длины вектора AB - расстояния между центром левого глаза и носом. Из чего можем провести следующую зависимость:

“Чем меньше значение функции len для видеофайла, тем меньше изменялось расстояние между левым глазом и носом, а равно один из основных параметров лица, тем (предположительно) лучше качество конечной анимации”

Параметр ren будем вычислять по тем же формулам, внеся соответсвующие изменения.

Список параметров chin0-chin7

Список параметров chin0 - chin7 показывает изменение длины вектора AB между каждыми двумя точками, относящимися к нижней дуги лица (точки 0-16).

Список значений chini хранит в себе длины векторов AB, где A-точка лежащая на левой полудуге, B-точка лежащая на правой полудуге соответственно, а равно, расстояние левой и правой стороной лица в точке i. Пусть каждое значение списка chini вычисляется по следующей формуле для каждого кадра:

chin_i =  \sqrt{(x_{chin-left}-x_{chin-right})^2+(y_{chin-left}-y_{chin-right})^2+(z_{chin-left}-z_{chin-right})^2}

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

chin = \frac{ \sum_{i=m}^{n}{\frac{chin_i}{n}} }{a}

Значение chin показывает среднее изменение длины вектора AB - расстояния между двумя точками на левой и правой стороне нижней дуги лица. Из чего можем провести следующую зависимость:

“Чем меньше значение функции chin{0-7} для видеофайла, тем меньше изменялось расстояние между двумя половинами лица, а равно один из основных параметров лица, тем (предположительно) лучше качество конечной анимации”

Все эти метрики позволяют относительно точно отследить качество итоговой анимации не только по итогу, но ещё и покадрово как-то вот так:

Так как конечной целью было собрать скрипт/плагин для Blender, визуализация естественно проводилась в нём же. Так выглядят этапы формирования итоговых косточек для перемещения мэша лица :

Этапы формаирования косточек и анимации
Этапы формаирования косточек и анимации

Результаты работы скрипта

Кошмар раз
Кошмар раз

Кошмар два
Кошмар два

Кошмар три
Кошмар три
Нормальная табличка сюда не влезла, наслаждайтесь 10/10 шакалов
Нормальная табличка сюда не влезла, наслаждайтесь 10/10 шакалов

Давайте подробнее рассмотрим "Кошмар три"

Алгоритм не обрезает фотографию, оставляя на ней только лицо, а сохраняет кадр целиком. Время обработки такой анимации увеличилась в 2-3 раза, однако, это позволило избежать неточностей и достоверно передать все выражения лица. Присутствуют необходимые для достоверной анимации циклы кадров. Помимо этого, она значительно превосходит своих предшественниц и показывает на сколько алгоритм был усовершенствован после проведения исследования, его настройки.

Ну и вот итог всего пути, который мы прошли. От точек в пространстве, до сносной анимации:

Подводим итоги

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

Да и исполнение занимает значительное количество времени, что в сравнении с некоторыми из способов недопустимо