Распознавание лиц по методу Виолы-Джонса. Программа SqFace.
Автор текста и программы: Александр Лубягин (г.Киров, обл.)
Текст написан в стиле FidoNet/MS DOS - чтобы вам было удобней читать.
Опубликован под лицензией Creative Commons SA-BY-NC 3.0.
1. Что мы делаем
Этим летом один английский коллега попросил меня написать ему программную
библиотеку для обнаружения лиц на фотографиях. Ему это нужно для Интернет-
магазина одежды. Я написал эту программу на основе OpenCV.
Спустя месяц, эта программа пригодилась. Один питерский предприниматель
заказал мне исследовать код OpenCV, и сделать отчет. Исследования я решил
продолжить, и сейчас ищу потенциального заказчика на доработку и модификацию
этой программы.
Метод называется - "метод Виолы-Джонса" (по фамилиям двух его авторов).
Предназначен для обнаружения объектов на изображениях в реальном времени
(например, на кадрах видео-потока). Метод отвечает на вопросы: "есть ли
на изображении лица людей?", и "где они, предположительно, находятся?".
Метод реализован в проектах: HxMarilena, OpenClooVision, "MATLAB: Viola-
Jones Object Detection", OpenCV, и других.
Качество работы OpenCV'шной реализации можно оценить по видеороликам:
http://video.yandex.ru/users/lubyagin/view/4/#http://video.yandex.ru/users/lubyagin/view/9/#
Моя реализация на том же уровне по качеству:
В Интернете есть много статей, поверхностно описывающих метод Виолы-Джонса
по части распознавания. Часть обучения (так называемый метод AdaBoost) описан
три дня назад в статье на "Хабр" неизвестным автором:
http://habrahabr.ru/blogs/algorithm/133826/
Таким образом, если учесть ещё и мою статью, сейчас в Интернете метод Виолы-
Джонса описан более-менее полностью (на русском языке).
2. Ещё раз о скорости и "ложных срабатываниях"
Моя программа обрабатывала кадр 512x512 пикселей за 0.19 секунды. В то время,
как OpenCV делала то же самое за 0.03 секунды. Одна из целей, которые можно
поставить на ближайшее будущее (декабрь 2011 - весна 2012 года), это -
ускорение программы, устранение множественности обнаружения (вместе
с уменьшением числа "ложных срабатываний"), выпуск кода как в виде отдельной
программы, так и в виде программной библиотеки. Вот как программа обнаруживает
лица на стандартных, типичных фотографиях:
Для работы в режиме real-time моей программе надо приблизиться к уровню OpenCV.
Реализации других исследователей были такими:
Viola, Jones, 2001: 384x288 пикс - 15 кадров/сек на Intel Pentium III, 700 MHz
Viola, Jones, 2001: 2 кадра/сек на Strong Arm, 200 MIPS
R.Lienhart, J.Maydt: 320x240 пикс - 15 кадров/сек на Intel P4, 2 GHz
"Ложные срабатывания", которые вы видели на видео (по приведенным выше ссылкам),
кореллируют в рамках метода Виолы-Джонса с долей правильных ответов:
То есть, повышая долю правильных ответов, мы вносим лишние "ложные срабатывания".
3. Общая схема метода Виолы-Джонса
Алгоритм распознавания по методу Виолы-Джонса основан на "суммировании" пикселов
(с определенными весовыми коэффициентами) под скользящим [по растру] окном.
Распознавание в этом методе осуществляется по "прецедентам". В помощью
"обучающей выборки" строится набор "сильных классификаторов", каждый из которых
для квадратного окна говорит: "предположительно, в окне - лицо", или -
"определенно, не лицо". Таким образом, для того, чтобы алгоритм признал
картинку в окне за лицо, необходимо, чтобы все "сильные классификаторы" (stages)
ответили: "да, лицо предположительно есть". Если хотя бы один из них отверг
окно (сказал, что "лица определенно нет"), то алгоритм сразу же отвергает
данное окно, другие "сильные классификаторы" не использует, и переходит
к следующему окну.
4. Немного математики
В методе Виолы-Джонса используются функции, основанные на вейвлетах Хаара.
По-английски, эти функции называются "Haar wavelet-like features".
Вейвлеты Хаара - это одиночные "волны" прямоугольного вида (один интервал
"высокого" уровня, и один - "низкого"). На плоскости - это два прилегающих
квадрата. Комбинации таких форм - вейвлетами Хаара не являются. Эти Haar-like
features показаны на рисунке:
Именно свёртка двумерного функционала интенсивности пикселов с такими функциями,
с определенными весами, и представляет собой упомянутое выше "суммирование".
Все Haar-like features (или просто, features) для одного каскада изображены
на большой картинке:
Как работает "сильный классификатор".
Для выбранной позиции скользящего окна, перебираются все "сильные
классификаторы" (stages) / "хааро-подобные функции" (features). Для каждой
feature считается сумма интенсивностей пикселов с определенным весовым
коэффициентом по "белой" области feature (см. рисунки выше), и вычитается сумма
по "тёмной" области, с другим весовым коэффициентом. Полученная сумма
умножается на величину inv (см. ниже формулы в алгоритме), и сравнивается
с порогом "feature threshold", умноженным на величину stddev. Если первое -
меньше второго, то к сумме по stage ("сильному классификатору") добавляется
величина left_val данного feature, иначе - добавляется величина right_val.
Для ускорения "суммирования" используется "интегральная матрица" (Summed
area table, см. на Википедии). За счёт неё у меня программа ускорилась в 35 раз.
Чтобы представлять, где и как брать значения left_val и т.п., приведу часть
первого stage из стандартного каскада:
<opencv_storage>
<haarcascade_frontalface_alt type_id="opencv-haar-classifier">
<size>20 20</size> # вначале задается размер «окна» в пикселах
<stages>
<_> # затем описываются этапы каскада: от 0 до 21
<!-- stage 0 -->
<trees>
<_> # на каждом этапе несколько «деревьев»
<!-- tree 0 -->
<_> # в данном случае, каждое дерево — это один «корень»
<!-- root node -->
<feature> # «корню» принадлежит один признак (feature)
<rects> # в нашем случае — несколько прямоугольников (x,y,w,h) с заданными весами (w,)
<_>3 7 14 4 -1.</_>
<_>3 9 14 2 2.</_></rects>
<tilted>0</tilted></feature> # поворот признака (в нашем случае, alt — не используется)
# см. также correction_ratio на github.com
<threshold>4.0141958743333817e-003</threshold> # порог, с которым сравнивается разн. Ч-Б
<left_val>0.0337941907346249</left_val>
<right_val>0.8378106951713562</right_val></_></_>
<_>
<!-- tree 1 -->
<_>
<!-- root node -->
<feature>
<rects>
<_>1 2 18 4 -1.</_>
<_>7 2 6 4 3.</_></rects>
<tilted>0</tilted></feature>
<threshold>0.0151513395830989</threshold>
<left_val>0.1514132022857666</left_val>
<right_val>0.7488812208175659</right_val></_></_>
….
# после всех признаков (деревьев) ...
<stage_threshold>6.9566087722778320</stage_threshold>
<parent>0</parent>
<next>-1</next></_>
Структура данных XML-каскада изображена также на следующей схеме:
Значения left_val и right_val для данного каскада - неотрицательны:
5. Алгоритм
def Sum(x,y,w,h):
for x,y in [w,h]:
S += pixel_intensivity
return S/256.0
def SumSq(x,y,w,h):
for x,y in [w,h]:
S += pixel_intensivity^2
return S/(256.0*256.0)
factor = 1.2
dscale = 1.0
цикл
window_w = window_w_base * dscale
window_h = window_h_base * dscale
x_step = max(1, min(4, window_w/8)) # определено эмпирически
y_step = max(1, min(4, window_h/8)) # от 1 до 4 пикс
inv = 1/float(window_w*window_h)
цикл по y1 = 0 ... h1-1-window_h с шагом y_step
цикл по x1 = 0 ... w1-1-window_w с шагом x_step
mean = Sum(x1,y1,window_w, window_h)*inv
var = SumSq(x1,y1,window_w, window_h)*inv - mean*mean
если var >= 0, то stddev = sqrt(var)
иначе stddev = 1.0
цикл по stages (сильным классификаторам)
sum_stage = 0.0
цикл по features (функциям Хаара)
sum_feature = 0.0
цикл по rects (прямоугольникам)
sum_feature += Sum(x1+rect.x*dscale, y1+rect.y*dscale,
rect.w*dscale+2, rect.h*dscale+2)*rect.weight
sum_feature *= inv
если sum_feature < feature_threshold*stddev, то sum_stage += feature.left_val
иначе sum_stage += feature.right_val
если sum_stage < stage_threshold, то f_failed = 1; break;
если (!failed) нарисовать [x1,y1,x2,y2]
dscale *= factor
6. Программа
Архив с полным исходным кодом программы и всеми необходимыми данными:
Лицензия на исходный код sqface.cpp - AGPLv3+:
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see http://www.gnu.org/licenses/
Также, вы можете изучить алгоритм распознавания по другим реализациям:
- Проект HxMarilena - HxMarilena: ObjectDetector.hx
- Скрипт на языке MATLAB - MATLAB: Viola-Jones Object Detection
- Проект OpenClooVision (Viola-Jones) - http://opencloovision.codeplex.com/
- Проект корпорации Intel, OpenCV - OpenCVWiki
----
Если кому-то нужна консультация по этому алгоритму, обращайтесь:
E-mail: lubyagin@yandex.ru
Jabber: lubyagin@jabber.ru
ICQ: 386-551-505
Дата публикации: 06 декабря 2011 года.
Автор: Александр Лубягин aka pacify, http://pacify.ru/
Дополнение от 06.12.2011:
Спустя несколько часов после публикации анонса на Linux.Org.Ru,
исходный код проекта был выложен пользователем tommy2001 на github.com
с целью его дальнейшего развития: "sqface на github"
Дополнение от 28.03.2012:
Во время написания работы я решил поискать диссертации по теме распознавания лиц в базе диссертаций РГБ.
Одну такую диссертацию нашел: "Алгоритмы обнаружения лица человека для решения прикладных задач анализа
и обработки изображений" (Кудряшов, Павел Павлович), Волгоград, 2007.
Библиография
[64] Lienhart R., Kuranov A., Pisarevsky V. An extended set of Haar-like features for rapid
object detection, IEEE ICIP, p.900-903, Rochester, NY, Sep.2002.
[131] Yang M.H., Kriegman D., Ahuja N. Detecting faces in images: A survey. PAMI, 24(1), p.34-58, Jan.2002.
[143] Вежневец А.П. Методы классификации с обучением по прецедентам в задаче распознавания
объектов на изображениях, 2006. (см. на graphicon.ru)
В упомянутой диссертации действительно содержательная часть - это про
удаление красных глаз. Также, по подобному алгоритму можно удалять
"белые глаза", "желтые глаза" и проч. (на фотографиях животных)