Страницы

Поиск по вопросам

пятница, 5 июля 2019 г.

Алгоритм распознавания состояний глаз - открыты/закрыты

Добрый день. Требуется реализовать алгоритм, позволяющий определять, в каком состоянии находятся его глаза, если можно так выразиться. Нужно определять состояния Открыты, Закрыты, можно еще Закрыты на хх%. Буду признателен за подсказки, где можно про это почитать.
UPD Прошу только навести, где есть информация о распознавании глаз.


Ответ

Задача очень нетривиальна и, предваряя поиск решения, требует конкретизации условий, в которых необходимо производить детекцию моргания или просто текущего состояния глаз в кадре: открыты или закрыты.
Возьмём, к примеру, стандартный случай.
Если на исходном изображении лицо не заполняет всю видимую область, то таковую необходимо локализовать. Для решения этой задачи существует не так уж и много решений, но то, что имеется в подавляющем количестве случаев более чем удобоваримо. Речь прежде всего о каскаде Хаара. Во многих фреймворках, так или иначе касающихся тематики компьютерного зрения, имеется реализация данного инструмента, позволяющая с относительно высокой точностью локализовать местоположение лица в кадре.
После нахождения региона, содержащего лицо, уже в нём необходимо локализовать местоположение обоих глаз. Как правило, начав с каскада Хаара в случае с лицом, не останавливаются в использовании этого же инструмента и для глаз. Просто берут соответствующий файл классификатора, заранее обученный на поиск желаемого типа объекта. К слову сказать, оба типа классификаторов (для лиц, глаз, да и других объектов) имеются во многим известном фреймворке OpenCV, ориентированном как раз на решение задач, навроде той, что встала перед автором вопроса.
Не стану останавливаться на задаче, как реализовать детекторы лиц и глаз посредством каскада Хаара (метод Виолы-Джонса) в том же OpenCV, так как об этом расписано в сети, наверное, вдоль и поперёк, да и вопрос конкретно не затрагивает эту область.
Предположим, что после применения алгоритмов детекции мы получили следующие изображения, отражающие два состояния глаз: открыты и закрыты.

Изображения мною взяты исключительно для примера, но в реальности, если съёмка ведётся с обычной вебкамеры, области глаз получаются значительно меньше. Это просто в следствие того, что специально подносить собственную физиономию близко к объективу редко у кого возникает желание. Но именно в следствие этого (условий съёмки, упоминаемых мною в самом начале) как правило и начинаются расхождения в подходах к определению местоположения зрачка.
Методов по детекции зрачка разработано довольно много. От самых простых, до комплексных. Очень многие подробно расписаны (к сожалению в подавляющем большинстве случаев на английском). А для некоторых имеется и вполне свободный доступ к исходникам. На том же гитхабе можно обнаружить довольно много различных решений. Например такое или такое. Последнее, кстати, не требует локализации области глаз, только лишь лица.
Вообще, детекция зрачка кажется очевидным путём для решения поставленной задачи: зрачок есть - глаз открыт, нет зрачка - глаз закрыт. Но у многих методов, идущих этим путём, имеется проблема с детекцией в том случае, если глаз полуприкрыт или закрыт вовсе. В этом случае происходят ложные срабатывания алгоритмов и те выдают местоположение зрачка аккурат на ресницах, "лежащих" на соединении верхнего и нижнего века. То есть, искомое состояние о закрытии глаза способны выдавать далеко не все методы.
Для решения этой проблемы можно использовать машинное обучение или даже предварительно сделать образцы открытого и закрытого глаз, а затем сравнивать с этими шаблонами новые кадры. Но можно пойти и от обратного, например, применив самый простой детектор кожи. Очевидно, что если глаз закрыт, цветом кожи будет покрыто практически всё изображение глаза, а если открыт, то далеко не всё.
int main() { // Загрузить изображения открытого и закрытого глаз из файлов. cv::Mat eye_opened_mat = cv::imread("eye-opened.jpg"); cv::Mat eye_closed_mat = cv::imread("eye-closed.jpg");
// Показать, что загрузили в отдельных окошках. cv::imshow("eye-opened", eye_opened_mat); cv::imshow("eye-closed", eye_closed_mat);
// Сконвертировать цветовое пространство изображений в YCbCr. cv::Mat opened_mat, closed_mat; cv::cvtColor(eye_opened_mat, opened_mat, cv::COLOR_BGR2YCrCb); cv::cvtColor(eye_closed_mat, closed_mat, cv::COLOR_BGR2YCrCb);
// Изъять из картинок указанные диапазоны значений пикселей // для каждого из цветовых каналов YCbCr. cv::inRange(opened_mat, cv::Scalar(0,133,77), cv::Scalar(255,173,127), opened_mat); cv::inRange(closed_mat, cv::Scalar(0,133,77), cv::Scalar(255,173,127), closed_mat);
// Показать результат в отдельных окошках. cv::imshow("grd-opened", opened_mat); cv::imshow("grd-closed", closed_mat); cv::waitKey();
return 0; }
Этот код использует OpenCV. Результат будет следующий:

Разница между закрытым и открытым глазами очевидна и не составит никакого труда алгоритму выдать правильный ответ о состоянии глаза. Преимуществом данного подхода является скорость. Работает он очень быстро. Недостаток: чувствительность к перепадам освещённости, ну и конечно к неграм (без обид), для цвета кожи которых придётся подбирать иные коэффициэнты.

Комментариев нет:

Отправить комментарий