Разработка интерактивных систем

на OpenFrameworks

7. Распознавание лиц;
использование буфера рисования

лекции и объявления:
www.uralvision.blogspot.com

вопросы отправляйте на адрес
perevalovds@gmail.com

УрГУ / ИММ весна 2010

Распознавание лиц
http://opencv.willowgarage.com/wiki/FaceDetection

A recognition process can be much more efficient if it is based on the detection of features that encode some information about
the class to be detected. This is the case of Haar-like features that encode the existence of oriented contrasts between regions
in the image. A set of these features can be used to encode the contrasts exhibited by a human face and their spacial
relationships. Haar-like features are so called because they are computed similar to the coefficients in Haar wavelet transforms.
The object detector of OpenCV has been initially proposed by Paul Viola and improved by Rainer Lienhart. First, a classifier
(namely a cascade of boosted classifiers working with haar-like features) is trained with a few hundreds of sample views of a
particular object (i.e., a face or a car), called positive examples, that are scaled to the same size (say, 20x20), and negative
examples - arbitrary images of the same size.
After a classifier is trained, it can be applied to a region of interest (of the same size as used during the training) in an input
image. The classifier outputs a "1" if the region is likely to show the object (i.e., face/car), and "0" otherwise. To search for the
object in the whole image one can move the search window across the image and check every location using the classifier. The
classifier is designed so that it can be easily "resized" in order to be able to find the objects of interest at different sizes, which is
more efficient than resizing the image itself. So, to find an object of an unknown size in the image the scan procedure should be
done several times at different scales.
The word "cascade" in the classifier name means that the resultant classifier consists of several simpler classifiers (stages) that
are applied subsequently to a region of interest until at some stage the candidate is rejected or all the stages are passed. The
word "boosted" means that the classifiers at every stage of the cascade are complex themselves and they are built out of basic
classifiers using one of four different boosting techniques (weighted voting). Currently Discrete Adaboost, Real Adaboost, Gentle
Adaboost and Logitboost are supported. The basic classifiers are decision-tree classifiers with at least 2 leaves. Haar-like
features are the input to the basic classifers.The feature used in a particular classifier is specified by its shape , position within
the region of interest and the scale (this scale is not the same as the scale used at the detection stage, though these two scales
are multiplied).

Распознавание лиц
Признаки Хаара, используемые в алгоритме,
реализованном в OpenCV:

http://www710.univ-lyon1.fr/~bouakaz/OpenCV-0.9.5/docs/ref/pics/haarfeatures.png

Распознавание лиц
http://www710.univ-lyon1.fr/~bouakaz/OpenCV-0.9.5/docs/ref/OpenCVRef_Experimental.
htm#decl_cvGetHaarClassifierCascadeScale
The object detector described below has been initially proposed by Paul Viola [Viola01] and improved by Rainer Lienhart
[Lienhart02]. First, a classifier (namely a cascade of boosted classifiers working with haar-like features ) is trained with a few
hundreds of sample views of a particular object (i.e., a face or a car), called positive examples, that are scaled to the same size
(say, 20x20), and negative examples - arbitrary images of the same size.
After a classifier is trained, it can be applied to a region of interest (of the same size as used during the training) in an input
image. The classifier outputs a "1" if the region is likely to show the object (i.e., face/car), and "0" otherwise. To search for the
object in the whole image one can move the search window across the image and check every location using the classifier. The
classifier is designed so that it can be easily "resized" in order to be able to find the objects of interest at different sizes, which is
more efficient than resizing the image itself. So, to find an object of an unknown size in the image the scan procedure should be
done several times at different scales.
The word "cascade" in the classifier name means that the resultant classifier consists of several simpler classifiers (stages) that
are applied subsequently to a region of interest until at some stage the candidate is rejected or all the stages are passed. The
word "boosted" means that the classifiers at every stage of the cascade are complex themselves and they are built out of basic
classifiers using one of four different boosting techniques (weighted voting). Currently Discrete Adaboost, Real Adaboost, Gentle
Adaboost and Logitboost are supported. The basic classifiers are decision-tree classifiers with at least 2 leaves. Haar-like
features are the input to the basic classifers, and are calculated as described below. The current algorithm uses the following
Haar-like features:
The feature used in a particular classifier is specified by its shape (1a, 2b etc.), position within the region of interest and the scale
(this scale is not the same as the scale used at the detection stage, though these two scales are multiplied). For example, in
case of the third line feature (2c) the response is calculated as the difference between the sum of image pixels under the
rectangle covering the whole feature (including the two white stripes and the black stripe in the middle) and the sum of the image
pixels under the black stripe multiplied by 3 in order to compensate for the differences in the size of areas. The sums of pixel
values over a rectangular regions are calculated rapidly using integral images (see below and cvIntegral description).
To see the object detector at work, have a look at HaarFaceDetect demo.
The following reference is for the detection part only. There is a separate application called haartraining that can train a cascade
of boosted classifiers from a set of samples. See opencv/apps/haartraining for details.

Распознавание лиц в
OpenFrameworks
//Пример - на основе описания и кода для C:
//http://opencv.willowgarage.com/wiki/FaceDetection
//Дело в том, что в примерах к OpenCV 2.0 - только facedetect для C++,
//а к OpenFrameworks (0061) прикреплен вариант для C (вероятно, OpenCV 1.x?)
Делаем снова на основе примера использования OpenCV в OpenFramework OpenFrameworks\apps\addonsExamples\opencvExample

Распознавание лиц в
OpenFrameworks
#include "ofxOpenCv.h"
//захват кадров
ofVideoGrabber
int w = 320;
int h = 240;

vidGrabber;

//изображение с камеры в формате OpenCV
ofxCvColorImage
colorImg;
ofxCvGrayscaleImage grayImage;
vector<ofRectangle> faceList;

//список найденных локализаций лиц

Распознавание лиц в
OpenFrameworks
CvMemStorage* storage = 0;

// хранилище для проведения вычислений OpenCV

CvHaarClassifierCascade* cascade = 0;
IplImage *frame_copy = 0;

// классификатор Хаара

//Временная картинка

//Путь к файлу с классификатором
const char* cascade_name =
//смотрящие вперед лица
"D:
\\Perevalov\\_OpenFrameworks\\apps\\speckurs\\FaceRecognition\\bin\\data\\haarcascade
s\\haarcascade_frontalface_alt.xml";
//развернутые влево лица
//"D:
\\Perevalov\\_OpenFrameworks\\apps\\speckurs\\FaceRecognition\\bin\\data\\haarcascade
s\\haarcascade_profileface.xml";
//Обратите внимание - нужно скопировать из OpenCV результаты обучения
классификаторов Хаара в свою папку, и прописать в ней полный путь

Распознавание лиц в
OpenFrameworks
//Настройка распознавателя
bool faceSetup()
{
//Загрузка классификатора из файла
cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
//Если не загрузился - написать ошибку
if( !cascade ) {
fprintf( stderr, "ERROR: Could not load classifier cascade\n" );
return false;
}
//Создание хранилища для проведения вычислений
storage = cvCreateMemStorage(0);
return true;
}

Распознавание лиц в
OpenFrameworks
//Распознавание
void faceUpdate( IplImage *frame, vector<ofRectangle> &faceList )
{
faceList.clear();
//Очистка списка ранее найденных лиц
//Очистка памяти хранилища от прошлых вычислений
cvClearMemStorage( storage );
//Поиск лиц
CvSeq* faces = cvHaarDetectObjects( img, cascade, storage,
1.1, 2, CV_HAAR_DO_CANNY_PRUNING,
cvSize(40, 40) );
//Записываем найденные прямоугольники в список
for( int i = 0; i < (faces ? faces->total : 0); i++ ) {
CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
ofRectangle rect( r->x, r->y, r->width, r->height );
faceList.push_back( rect );
}
}

Распознавание лиц в
OpenFrameworks
void testApp::setup(){
vidGrabber.initGrabber(320,240);
colorImg.allocate( w, h );
grayImage.allocate( w, h );
bool result = faceSetup(); //пробуем загрузить распознаватель лиц
if ( !result ) {
OF_EXIT_APP(1); //если не удалось - выйти
}
}

Распознавание лиц в
OpenFrameworks
void testApp::update(){
vidGrabber.grabFrame();
if ( vidGrabber.isFrameNew() ){
//получение изображения
colorImg.setFromPixels( vidGrabber.getPixels(), w, h );
grayImage = colorImg;
//поиск лиц
faceUpdate( grayImage.getCvImage(), faceList );
}
}

Распознавание лиц в
OpenFrameworks
void testApp::draw(){
ofBackground(255,255,255);
//кадр с камеры
ofSetColor( 255, 255, 255, 255);
vidGrabber.draw( 0, 0 );
//найденные лица
ofSetColor( 255, 0, 0 );
ofNoFill();
for (int i=0; i<faceList.size(); i++) {
ofRectangle rect = faceList[i];
ofRect( rect.x, rect.y, rect.width, rect.height );
}
}

Пример

Как нарисовать путь движения
маятника
Задача: в проект с качающимся маятником добавить, чтобы рисовалось, где побывал
центр маятника. То есть как будто в маятнике в центре стоит карандаш, который
чертит на бумаге.
Как это сделать? Если запоминать траекторию в виде ломаной и каждый раз ее
выводить на экран - постепенно программа будет работать все медленней.
Лучший способ решения - рисовать траекторию маятника в некоторый буфер вне
экрана, а потом выдавать содержимое буфера на экран.
Этот буфер - как бы экран, который мы не видим. В отличие от экрана, буфер не
будет чиститься при каждом рисовании экрана.
FBO - Frame Buffer Object.
В такой буфер можно рисовать как на экране, а затем использовать результат как
текстуру - т.е. выводить ее а экран или рисовать ей в других буферах.
Можно делать сложные многослойные изображения, позволяющие делать эффекты
типа "следа" от движущихся объектов. Для этого нужно рисовать один буфер в
другом с разной прозрачностью.

Как нарисовать путь движения
маятника
Тогда алгоритм рисования в
draw() будет такой:
1. в буфере рисуется
прямая, соединяющая текущее
положение маятника с
предыдущим,
2. буфер выводится на экран
3. на экране рисуется сам маятник

Работа с буфером рисования
Для работы с буфером рисования в OpenFrameworks лучше всего
использовать аддон ofxFBOTexture.
Он состоит из двух файлов - ofxFBOTexture.h и ofxFBOTexture.cpp.
http://addons.openframeworks.cc/projects/list_files/ofxfbotexture

Эти файлы нужно добавить в проект, например, так:
1. Скопировать их в src проекта
2. в VisualStudio ткнуть правой кнопкой по проекту, в меню - Add Existing
Items и добавить их оба.
Правильней копировать все аддоны в папку openframeworks/addons, но
это может быть неудобно, если проект должен быть мобильным, то есть
собираться на разных компьютерах.

Работа с буфером рисования
...
#include "ofxFBOTexture.h"
...
ofxFBOTexture buffer; //буфер для рисования вне экрана

в setup()
//создание буфера
buffer.allocate( ofGetWidth(), ofGetHeight(),
false
//без автоочистки при каждом рисовании - т.к. будем там
накапливать картинки
);
buffer.clear( 0, 0, 0, 255 );

//очистка черным цветом

//нужно заметить, что если ставить не черный цвет, то буфер может окраситься в
первый используемый вами цвет. Как устранить проблему?

Работа с буфером рисования
в draw()
buffer.begin();

//начало рисования в буфер

// процедуры рисования в буфер - оформляется так же, как на экран
... ofSetColor, ofLine, ...

buffer.end();

//конец рисования в буфер

buffer.draw( 0, 0 );

//вывод буфера на экран

// остальное рисование
...
В этом случае процедуры рисования в буфер будут оставаться от кадра к кадру
(путь: который прошел маятник), а процедуры остального рисования - показываться
только в одном кадре (сам маятник с резинкой).

Проект "база данных лиц"

Sign up to vote on this title
UsefulNot useful