Я пытаюсь найти три угла лица человека на основе 2D-изображения .
Я использую OpenCV с HaarCascade, чтобы найти лицо, глаза, нос и рот.
Но я не нашел геометрического метода, который мог бы помочь мне найти углы X, Y и Z (Roll, Pitch и Yaw).
Может ли кто-нибудь помочь мне показать какой-то метод в C ++ или Java, который работает?
Учитывая одно изображение и никакой другой информации, не существует единого решения для углов. Рассмотрим случай просто Йоу. Проецируемая на плоскость 2d, это видно как небольшое изменение проецируемого расстояния между глазами и расположением глаз относительно носа / рта. Однако это расстояние не является постоянным от человека к человеку.
Один из типичных способов обойти это — потребовать, чтобы пользователь «откалибровал» свое лицо, глядя прямо в камеру на номинальные углы «0». Теперь у вас есть эталонные длины, с которыми вы можете сравнивать последующие изображения.
Однако длины по-прежнему являются не совсем достаточной информацией, поскольку величина изменения видимых проецируемых расстояний зависит от оптики и расстояния лица от камеры. Оптика, которую вы обычно настраиваете вручную; расстояние, которое вы можете оценить, приняв «средние» размеры лица и предположив, что «номинальное» изображение идеально соответствует этим размерам. Вы можете сделать это регулируемым, если обнаружите, что это переоценка или недооценка поворотов для конкретной грани.
Когда у вас есть все эти предположения, это довольно простая геометрия. Вы можете оценить крен от линии от глаз через нос к рту. Вы можете измерить расстояние между глазами, чтобы оценить рыскание. Наконец, вы можете оценить высоту тона, используя расстояние между глазами / ртом или глазами / носом. Имейте в виду, что эти предположения работают лучше всего, когда лицо все еще довольно близко к номинальному.
Итак, вы хотите найти ориентацию (в углах RPY) лица на основе положения носа, глаз и рта. Предполагая, что все три (четыре — два глаза) видимы, я бы использовал симметричные особенности лица для определения ориентации головы, такие как:
Линия между глазами может использоваться как ориентир для одной из осей (например, тангажа). Тогда мы можем предположить, что ось крена указывает в направлении носа — что можно измерить по позиционному смещению носа к средней точке между глазами. И, наконец, рыскание может быть измерено через отношение расстояний между средней точкой между глазами, положением носа и положением рта.
Я не знаю дистанционных отношений между четырьмя интересующими точками, и они, вероятно, различаются в отношении пола, возраста и происхождения. Однако, если вы можете найти такое соотношение, математическое определение углов должно быть довольно прямым.
Кстати, интересное приложение!
Если вы используете каскадный классификатор для определения правого глаза, левого глаза и носа, вычислите центр тяжести каждой функции (функция x / 2, функция y / 2), это даст вам три точки x-y на вашем изображении.
Вы можете обнаружить крен, посмотрев на значения Y каждого глаза, если одно выше другого, это означает, что головка наклонена в направлении наименьшего значения Y (когда один глаз движется вверх, другой движется вниз)
Вы можете обнаружить рыскание, посмотрев на значение X носа, если пользователь смотрит налево, значение X его носа будет ближе к значению X левого глаза, и то же самое, если смотреть вправо на правый глаз X значение.
Вы можете определить высоту тона, посмотрев на значение Y носа, если пользователь смотрит вверх, значение Y будет ближе к обоим значениям Y глаз, а если они смотрят вниз, значение Y будет дальше от значения глаз.
Теперь это, конечно, не очень точно и не даст вам точных углов, однако вы можете использовать эту информацию, чтобы попытаться классифицировать каждое значение в определенных группах, т. Е. (Смотреть вперед, смотреть налево, смотреть действительно оставил)
Единственное, что я могу увидеть, когда вы вычисляете все три в одном изображении, может быть, если крен довольно резкий, вычисление рыскания может быть проблематичным, поскольку ось X больше не является плоской.
Вы можете решить эту проблему, исправляя изображение с помощью 2D поворота.
Вам нужно будет найти, на сколько нужно повернуть изображение
Value = (right eye Y / 2) - (left eye Y / 2)
С помощью этой информации вы можете исправить изображение и продолжить обработку (для поворота изображения посмотрите вверх, создав 2D-матрицу вращения и используя деформацию деформации)
Извините, если это что-то вроде некро, но я нашел вышеописанный метод довольно успешным, и я надеюсь, что он кому-нибудь поможет