www.pudn.com > facedetectDLL_expressions.zip > facedetect.cpp
// facedetect.cpp : Defines the initialization routines for the DLL.
//
#include "stdafx.h"
#include "facedetect.h"
#include "classimage.h"
#include "classWTA.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//
// Note!
//
// If this DLL is dynamically linked against the MFC
// DLLs, any functions exported from this DLL which
// call into MFC must have the AFX_MANAGE_STATE macro
// added at the very beginning of the function.
//
// For example:
//
// extern "C" BOOL PASCAL EXPORT ExportedFunction()
// {
// AFX_MANAGE_STATE(AfxGetStaticModuleState());
// // normal function body here
// }
//
// It is very important that this macro appear in each
// function, prior to any calls into MFC. This means that
// it must appear as the first statement within the
// function, even before any object variable declarations
// as their constructors may generate calls into the MFC
// DLL.
//
// Please see MFC Technical Notes 33 and 58 for additional
// details.
//
/////////////////////////////////////////////////////////////////////////////
// CFacedetectApp
#define ORIG_WIN_SIZE 24
//dimensions of the classimage used to detect facial features
#define FEATURES_WIDTH 30
#define FEATURES_HEIGHT 30
#define DETECTED_EYE_WIDTH 30
#define DETECTED_EYE_HEIGHT 40
#define DETECTED_NOSE_WIDTH 10
#define DETECTED_NOSE_HEIGHT 20
#define DETECTED_MOUTH_WIDTH 20
#define DETECTED_MOUTH_HEIGHT 15
CvMemStorage* storage=NULL;
CvHidHaarClassifierCascade* hid_cascade = 0; //face classifier
IplImage* video_image[2]; //stores the scene (and previous scene)
int NoOfObjects=0; //number of faces detected
int width,height; //dimensions of the scene bitmap
int object_location[100][23]; //stores the locations of detected objects and key points on the face
int border_x,border_top,border_bottom; //border around the face in pixels
classimage *features=NULL; //used for detection of facial freatures
classimage *imgEye[2]; //used for detection of gaze direction
classimage *imgNose; //used for detection of tip of the nose
classimage *imgMouth; //used for detection of mouth
int flip=0; //used to flip between video_image array elements
int trackfeature[10][10];
bool trackingEnabled=false;
int trackingTimer=0;
Twta *orientation_classifier=NULL;
Twta *expression_classifier=NULL;
BEGIN_MESSAGE_MAP(CFacedetectApp, CWinApp)
//{{AFX_MSG_MAP(CFacedetectApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFacedetectApp construction
CFacedetectApp::CFacedetectApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
CFacedetectApp::~CFacedetectApp()
{
if (features!=NULL)
{
cvReleaseImage( &video_image[0] );
cvReleaseImage( &video_image[1] );
delete features;
delete imgEye[0];
delete imgEye[1];
delete imgNose;
delete imgMouth;
delete orientation_classifier;
}
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CFacedetectApp object
CFacedetectApp theApp;
int CFacedetectApp::RCobj_InitFaceDetect( int img_width, int img_height )
{
int i,j,retval=1;
width = img_width;
height = img_height;
if (storage==NULL) storage = cvCreateMemStorage();
//create the classifier
CvHaarClassifierCascade* cascade = cvLoadHaarClassifierCascade(
"",
cvSize( ORIG_WIN_SIZE, ORIG_WIN_SIZE ));
if( !cascade ) return 0;
hid_cascade = cvCreateHidHaarClassifierCascade( cascade );
cvReleaseHaarClassifierCascade( &cascade );
//create an image used to store the scene
cvReleaseImage( &video_image[0] );
video_image[0] = cvCreateImage( cvSize( width , height ), 8, 3 );
cvReleaseImage( &video_image[1] );
video_image[1] = cvCreateImage( cvSize( width , height ), 8, 3 );
//create an image object which may be used to search for facial features
if (features==NULL)
{
features = new classimage;
features->createImage(FEATURES_WIDTH,FEATURES_HEIGHT);
imgEye[0] = new classimage;
imgEye[0]->createImage(DETECTED_EYE_WIDTH,DETECTED_EYE_HEIGHT);
imgEye[1] = new classimage;
imgEye[1]->createImage(DETECTED_EYE_WIDTH,DETECTED_EYE_HEIGHT);
imgNose = new classimage;
imgNose->createImage(DETECTED_NOSE_WIDTH,DETECTED_NOSE_HEIGHT);
imgMouth = new classimage;
imgMouth->createImage(DETECTED_MOUTH_WIDTH,DETECTED_MOUTH_HEIGHT);
}
//initialise tracking
for (i=0;i<10;i++) trackfeature[i][0]=0;
trackingEnabled=false;
trackingTimer=0;
//classifiers
if (orientation_classifier==NULL)
{
orientation_classifier = new Twta(DETECTED_EYE_WIDTH*(DETECTED_EYE_HEIGHT+1),3);
}
for (i=0;i<100;i++)
for (j=0;j<23;j++)
object_location[i][j] = 0;
return(retval);
}
void CFacedetectApp::DetectFaces( IplImage* img )
{
int i;
CvRect r;
if( hid_cascade && img )
{
int scale = 2;
CvSize img_size = cvGetSize( img );
IplImage* temp = cvCreateImage( cvSize(img_size.width/2,img_size.height/2), 8, 3 );
cvPyrDown( img, temp );
cvClearMemStorage( storage );
if( hid_cascade )
{
CvSeq* faces = cvHaarDetectObjects( temp, hid_cascade, storage, 1.2, 2, 1 );
NoOfObjects = faces->total;
for( i = 0; i < (faces ? faces->total : 0); i++ )
{
if (i<100)
{
r = *(CvRect*)cvGetSeqElem( faces, i );
object_location[i][0] = r.x*scale;
object_location[i][1] = r.y*scale;
object_location[i][2] = (r.x+r.width)*scale;
object_location[i][3] = (r.y+r.height)*scale;
//detect key points on the face
detect_keypoints(i);
}
}
}
cvReleaseImage( &temp );
}
}
//----------------------------------------------------------------------------------------
//detect objects within the image
//----------------------------------------------------------------------------------------
int CFacedetectApp::RCobj_detectfaces(SAFEARRAY **bmp)
{
BYTE *bmp2;
int i,x,y,c,w,h;
SafeArrayLock(*bmp);
bmp2 = (BYTE *)(*bmp)->pvData;
w = 0; //width/5;
h = 0; //height/5;
i=0;
for (y=0;y=w) && (x=h) && (yimageData[i] = bmp2[i];
i++;
}
}
else
{
for (c=0;c<3;c++)
{
video_image[flip]->imageData[i] = 0;
i++;
}
}
}
}
//for (i=0;iimageData[i] = bmp2[i];
if (!trackingEnabled)
DetectFaces(video_image[flip]);
else
updateTracking();
flip = 1-flip;
SafeArrayUnlock(*bmp);
return(NoOfObjects);
}
//----------------------------------------------------------------------------------------
//return the position of a detected object
//----------------------------------------------------------------------------------------
void CFacedetectApp::RCobj_getObject(int index, int &tx, int &ty, int &bx, int &by)
{
if (indexwidth-1) bx=width-1;
if (by>height-1) by=height-1;
}
}
//----------------------------------------------------------------------------------------
//sets the border region around detected faces
//----------------------------------------------------------------------------------------
void CFacedetectApp::RCobj_setBorder(int borderX, int borderTop, int borderBottom)
{
border_x = borderX;
border_top = borderTop;
border_bottom = borderBottom;
}
//----------------------------------------------------------------------------------------
//detect facial features for the given face index
//----------------------------------------------------------------------------------------
void CFacedetectApp::RCobj_detectfeatures(int index, int &lateral_symetry, int &lefteye_x, int &righteye_x, int &lefteye_y, int &righteye_y, int &mouth_y, int &mouth_width, int &gazedirection)
{
int tx,ty,bx,by,x,y,xx,yy,n,n2,dx,dy,halfwidth,quarterwidth,symetry_x;
int halfheight,quarterheight,eyes_separation,eyes_centre;
long tot,tot_w,w,xpos;
if (!trackingEnabled)
{
//get the bounding box for the face
tx = object_location[index][0];
ty = object_location[index][1];
bx = object_location[index][2];
by = object_location[index][3];
dx = bx-tx;
dy = by-ty;
//load the bitmap into the image object
for (y=0;y0)
n = width * 3 * (ty+yy-1);
else
n = 0;
for (x=0;ximage[x][y][0] = video_image[flip]->imageData[n2+2];
features->image[x][y][1] = video_image[flip]->imageData[n2+1];
features->image[x][y][2] = video_image[flip]->imageData[n2+0];
}
}
features->updateIntegralImage();
//check symetry within the edges image
halfwidth = FEATURES_WIDTH/2;
quarterwidth = halfwidth/2;
halfheight = FEATURES_HEIGHT/2;
quarterheight = halfheight/2;
symetry_x = halfwidth;
lateral_symetry = (symetry_x * 100) / FEATURES_WIDTH;
//search for the left eye horizontal position
tot=0;
tot_w=0;
for (x=symetry_x-(FEATURES_WIDTH/3);ximage[x][quarterheight+y][0];
}
if (w>200)
{
tot_w += w;
tot += (x * w);
}
}
if (tot_w>0) tot /= tot_w; else tot=halfwidth;
xpos=tot;
lefteye_x = (xpos * 100) / FEATURES_WIDTH;
//search for the left eye vertical position
tot=0;
tot_w=0;
for (y=quarterheight;yimage[xpos+x][y][0];
if (w>200)
{
tot_w += w;
tot += y * w;
}
}
if (tot_w>0) tot /= tot_w; else tot=halfheight;
lefteye_y = (tot * 100) / FEATURES_HEIGHT;
//search for the right eye horizontal position
tot=0;
tot_w=0;
for (x=symetry_x;ximage[x][quarterheight+y][0];
}
if (w>200)
{
tot_w += w;
tot += (x * w);
}
}
if (tot_w>0) tot /= tot_w; else tot=halfwidth;
xpos=tot;
righteye_x = (xpos * 100) / FEATURES_WIDTH;
//search for the right eye vertical position
tot=0;
tot_w=0;
for (y=quarterheight;yimage[xpos+x][y][0];
if (w>200)
{
tot_w += w;
tot += y * w;
}
}
if (tot_w>0) tot /= tot_w; else tot=halfheight;
righteye_y = (tot * 100) / FEATURES_HEIGHT;
}
//mouth vertical position
eyes_separation = righteye_x - lefteye_x;
eyes_centre = lefteye_x + (eyes_separation/2);
mouth_y = ((lefteye_y + righteye_y)/2) + (int)(eyes_separation*1.4);
if (mouth_y>99) mouth_y=99;
mouth_width = eyes_separation*120/100;
//detect key points
//detect_keypoints(index);
//detect gaze direction
//RCobj_detectGazeDirection(index,lateral_symetry,lefteye_x,righteye_x,lefteye_y,righteye_y,gaze_direction);
gazedirection = 1; //gaze_direction;
}
//----------------------------------------------------------------------------------------
//detect key points on the face
//----------------------------------------------------------------------------------------
void CFacedetectApp::detect_keypoints(int index)
{
long n;
int lateral_symetry,dx,dy,tx,ty,bx,by;
int mouth_y,mouth_width;
int x,y,xx,yy,lateral,lefteye,righteye,lefteyeY,righteyeY;
int mouthY,mouthWidth,noseY,noseX,point_x,point_y,px;
float sizeScale;
int lefteye_x, righteye_x, lefteye_y, righteye_y;
int eyesY[2];
int smile,mouthOpen,minY,maxY,mouthOpenWidth;
int pxx,rightEyeCorner[2],leftEyeCorner[2],gazedirection,eyeCentre[2],eyebrow_y[2];
RCobj_getObject(index, tx, ty, bx, by);
RCobj_detectfeatures(index, lateral_symetry, lefteye_x, righteye_x, lefteye_y, righteye_y, mouth_y, mouth_width, gazedirection);
lateral = FEATURES_WIDTH * lateral_symetry / 100;
lefteye = FEATURES_WIDTH * lefteye_x / 100;
righteye = FEATURES_WIDTH * righteye_x / 100;
lefteyeY = FEATURES_HEIGHT * lefteye_y / 100;
righteyeY = FEATURES_HEIGHT * righteye_y / 100;
mouthY = FEATURES_HEIGHT * mouth_y / 100;
mouthWidth = FEATURES_WIDTH * mouth_width / 100;
noseY = FEATURES_HEIGHT / 2;
noseX = FEATURES_WIDTH / 2;
dx = bx - tx;
dy = by - ty;
//you may need to tinker with this scaling depending upon image resolution
sizeScale = (float)(dx * 3) / (float)width;
//left eye
for (y=0;yimage[x][y][0] = video_image[flip]->imageData[n+2];
imgEye[0]->image[x][y][1] = video_image[flip]->imageData[n+1];
imgEye[0]->image[x][y][2] = video_image[flip]->imageData[n+0];
}
}
//centre of left eye
imgEye[0]->CG(0, DETECTED_EYE_HEIGHT / 2, DETECTED_EYE_WIDTH - 1, DETECTED_EYE_HEIGHT - 1, 0, 0, 0, point_x, point_y, 255);
eyesY[0] = point_y;
//inner left eye
px = point_x;
imgEye[0]->CG(px, DETECTED_EYE_HEIGHT / 2, DETECTED_EYE_WIDTH - 1, DETECTED_EYE_HEIGHT - 1, 0, 0, 0, point_x, point_y, 255 * 3);
rightEyeCorner[0] = point_x;
//outer left eye
pxx = px - 1;
if (pxx < 0) pxx = 0;
imgEye[0]->CG(0, DETECTED_EYE_HEIGHT / 2, pxx, DETECTED_EYE_HEIGHT - 1, 0, 0, 0, point_x, point_y, 255 * 2);
leftEyeCorner[0] = point_x;
minY = eyesY[0] - (DETECTED_EYE_HEIGHT / 8);
maxY = eyesY[0] + (DETECTED_EYE_HEIGHT / 8);
if (minY < 0) minY = 0;
if (maxY >= DETECTED_EYE_HEIGHT) maxY = DETECTED_EYE_HEIGHT - 1;
//left eye centre
imgEye[0]->CG(leftEyeCorner[0], minY, rightEyeCorner[0], maxY, 0, 0, 0, point_x, point_y, 255);
if (point_x < leftEyeCorner[0] + 1) point_x = leftEyeCorner[0] + 1;
if (point_x > rightEyeCorner[0] - 1) point_x = rightEyeCorner[0] - 1;
eyeCentre[0] = point_x;
//left eye direction
imgEye[0]->CG(leftEyeCorner[0], minY, rightEyeCorner[0], maxY, 255, 255, 255, point_x, point_y, 200 * 3);
//centre of left eyebrow
imgEye[0]->CG(0, 0, DETECTED_EYE_WIDTH - 1, DETECTED_EYE_HEIGHT / 2, 0, 0, 0, point_x, point_y, 255);
eyebrow_y[0] = point_y;
//right eye
for (y=0;yimage[x][y][0] = video_image[flip]->imageData[n+2];
imgEye[1]->image[x][y][1] = video_image[flip]->imageData[n+1];
imgEye[1]->image[x][y][2] = video_image[flip]->imageData[n+0];
}
}
//centre of right eye
imgEye[1]->CG(0, DETECTED_EYE_HEIGHT / 2, DETECTED_EYE_WIDTH - 1, DETECTED_EYE_HEIGHT - 1, 0, 0, 0, point_x, point_y, 255);
eyesY[1] = point_y;
//inner right eye
px = point_x;
imgEye[1]->CG(0, DETECTED_EYE_HEIGHT / 2, px, DETECTED_EYE_HEIGHT - 1, 0, 0, 0, point_x, point_y, 255 * 3);
leftEyeCorner[1] = point_x;
//outer right eye
pxx = px + 1;
if (pxx >= DETECTED_EYE_WIDTH) pxx = DETECTED_EYE_WIDTH - 1;
imgEye[1]->CG(pxx, DETECTED_EYE_HEIGHT / 2, DETECTED_EYE_WIDTH - 1, DETECTED_EYE_HEIGHT - 1, 0, 0, 0, point_x, point_y, 255 * 2);
rightEyeCorner[1] = point_x;
minY = eyesY[1] - (DETECTED_EYE_HEIGHT / 8);
maxY = eyesY[1] + (DETECTED_EYE_HEIGHT / 8);
if (minY < 0) minY = 0;
if (maxY >= DETECTED_EYE_HEIGHT) maxY = DETECTED_EYE_HEIGHT - 1;
//centre of right eye
imgEye[1]->CG(leftEyeCorner[1], minY, rightEyeCorner[1], maxY, 0, 0, 0, point_x, point_y, 255);
//if (point_x == 0) point_x = (eyeCentre[0] - leftEyeCorner[0]) + leftEyeCorner[1];
if (point_x < leftEyeCorner[1] + 1) point_x = leftEyeCorner[1] + 1;
if (point_x > rightEyeCorner[1] - 1) point_x = rightEyeCorner[1] - 1;
eyeCentre[1] = point_x;
//right eye direction
imgEye[1]->CG(leftEyeCorner[1], minY, rightEyeCorner[1], maxY, 255, 255, 255, point_x, point_y, 200 * 3);
//centre of right eyebrow
imgEye[1]->CG(0, 0, DETECTED_EYE_WIDTH - 1, DETECTED_EYE_HEIGHT / 2, 0, 0, 0, point_x, point_y, 255);
eyebrow_y[1] = point_y;
//nose
for (y=0;yimage[x][y][0] = video_image[flip]->imageData[n+2];
imgNose->image[x][y][1] = video_image[flip]->imageData[n+1];
imgNose->image[x][y][2] = video_image[flip]->imageData[n+0];
}
}
//nose tip
imgNose->CG(0, DETECTED_NOSE_HEIGHT / 2, DETECTED_NOSE_WIDTH - 1, DETECTED_NOSE_HEIGHT - 1, 0, 0, 0, point_x, point_y, 255);
//mouth
for (y=0;yimage[x][y][0] = video_image[flip]->imageData[n + 2];
imgMouth->image[x][y][1] = video_image[flip]->imageData[n + 1];
imgMouth->image[x][y][2] = video_image[flip]->imageData[n + 0];
}
}
mouthOpen = imgMouth->relativeThreshold(20,DETECTED_MOUTH_WIDTH/4,0,DETECTED_MOUTH_WIDTH*3/4,DETECTED_MOUTH_HEIGHT,mouthOpenWidth);
if (mouthOpen>10)
{
smile = 0;
}
else
{
smile = imgMouth->relativeThreshold(20,DETECTED_MOUTH_WIDTH/4,0,DETECTED_MOUTH_WIDTH/2,DETECTED_MOUTH_HEIGHT,mouthOpenWidth);
smile += imgMouth->relativeThreshold(20,DETECTED_MOUTH_WIDTH*3/4,0,DETECTED_MOUTH_WIDTH,DETECTED_MOUTH_HEIGHT,mouthOpenWidth);
smile -= mouthOpen;
mouthOpen = 0;
mouthOpenWidth = 0;
if (smile<4) smile=0;
}
//calculate eyebrow elevation in the range 0-100
//object_location[index][18] = (object_location[index][18] + eyebrows_elevation)/2;
object_location[index][4] = leftEyeCorner[0];
object_location[index][5] = rightEyeCorner[0];
object_location[index][6] = eyeCentre[0];
object_location[index][7] = eyesY[0];
object_location[index][8] = eyebrow_y[0];
object_location[index][9] = rightEyeCorner[1];
object_location[index][10] = leftEyeCorner[1];
object_location[index][11] = eyeCentre[1];
object_location[index][12] = eyesY[1];
object_location[index][13] = eyebrow_y[1];
object_location[index][14] = smile*12;
object_location[index][15] = mouthOpen;
object_location[index][16] = mouthOpenWidth;
}
//----------------------------------------------------------------------------------------
//detect facial features for the given face index
//----------------------------------------------------------------------------------------
void CFacedetectApp::RCobj_getFacialFeatures(int index, int &leftEyeOuter, int &leftEyeInner, int &leftEyePupil_x, int &leftEyePupil_y, int &leftEyebrow_y, int &rightEyeOuter, int &rightEyeInner, int &rightEyePupil_x, int &rightEyePupil_y, int &rightEyebrow_y, int &smile, int &mouthOpen, int &mouthWidth)
{
leftEyeOuter = object_location[index][4];
leftEyeInner = object_location[index][5];
leftEyePupil_x = object_location[index][6];
leftEyePupil_y = object_location[index][7];
leftEyebrow_y = object_location[index][8];
rightEyeOuter = object_location[index][9];
rightEyeInner = object_location[index][10];
rightEyePupil_x = object_location[index][11];
rightEyePupil_y = object_location[index][12];
rightEyebrow_y = object_location[index][13];
smile = object_location[index][14];
mouthOpen = object_location[index][15];
mouthWidth = object_location[index][16];
}
//----------------------------------------------------------------------------------------
//detect direction of gaze by looking at eye pupils
//----------------------------------------------------------------------------------------
void CFacedetectApp::RCobj_detectGazeDirection(int index, int lateral_symetry, int lefteye_x, int righteye_x, int lefteye_y, int righteye_y, int &gazedirection)
{
int tx,ty,bx,by,dx,dy,yy,xx,x,y,halfheight,i;
float sizeScale;
long n;
//get the bounding box for the face
tx = object_location[index][0];
ty = object_location[index][1];
bx = object_location[index][2];
by = object_location[index][3];
dx = bx-tx;
dy = by-ty;
sizeScale = (float)(dx / (float)width * 3);
halfheight = DETECTED_EYE_HEIGHT/2;
//left eye
i=0;
for (y=0;yimage[x][y][0] = video_image[flip]->imageData[n + 2];
imgEye[0]->image[x][y][1] = video_image[flip]->imageData[n + 1];
imgEye[0]->image[x][y][2] = video_image[flip]->imageData[n + 0];
if (y>halfheight)
{
orientation_classifier->setInput(i,video_image[flip]->imageData[n + 2]);
i++;
}
}
}
imgEye[0]->updateIntegralImage();
//right eye
for (y=0;yimage[x][y][0] = video_image[flip]->imageData[n + 2];
imgEye[1]->image[x][y][1] = video_image[flip]->imageData[n + 1];
imgEye[1]->image[x][y][2] = video_image[flip]->imageData[n + 0];
if (y>halfheight)
{
orientation_classifier->setInput(i,video_image[flip]->imageData[n + 2]);
i++;
}
}
}
imgEye[1]->updateIntegralImage();
//classify the orientation direction
orientation_classifier->update();
gazedirection = orientation_classifier->winner;
}
//----------------------------------------------------------------------------------------
//frack facial features
//----------------------------------------------------------------------------------------
void CFacedetectApp::RCobj_trackface(int index)
{
int lateral_symetry, lefteye_x, righteye_x, lefteye_y, righteye_y, mouth_y, mouth_width;
int tx,ty,bx,by,dx,dy,w,h,gazedirection;
RCobj_detectfeatures(index, lateral_symetry, lefteye_x, righteye_x, lefteye_y, righteye_y, mouth_y, mouth_width,gazedirection);
//get the bounding box for the face
tx = object_location[index][0];
ty = object_location[index][1];
bx = object_location[index][2];
by = object_location[index][3];
dx = bx-tx;
dy = by-ty;
//tracking is active for this object
trackfeature[index][0] = 1;
//feature size
trackfeature[index][1] = dx/4;
trackfeature[index][2] = dy/4;
w = trackfeature[index][1]/2;
h = trackfeature[index][2]/2;
//nose position
trackfeature[index][3] = tx + ((lateral_symetry * dx) / 100) - w;
trackfeature[index][4] = ty + (dy/2) - h;
//left eye
trackfeature[index][5] = tx + ((lefteye_x * dx) / 100) - w;
trackfeature[index][6] = ty + ((lefteye_y * dy) / 100) - h;
//right eye
trackfeature[index][7] = tx + ((righteye_x * dx) / 100) - w;
trackfeature[index][8] = ty + ((righteye_y * dy) / 100) - h;
trackingEnabled=true;
}
//----------------------------------------------------------------------------------------
//track faces
//----------------------------------------------------------------------------------------
void CFacedetectApp::updateTracking()
{
int i,x,y,size_x,size_y,searchArea,x1,y1;
bool found=false;
for (i=0;i<10;i++)
{
if (trackfeature[i][0]==1)
{
found=true;
//get the size of the area to be tracked
size_x = trackfeature[i][1];
size_y = trackfeature[i][2];
searchArea = size_x/4;
if (searchArea<2) searchArea=2;
//track head
x = object_location[i][0];
y = object_location[i][1];
x1=x;
y1=y;
//closestMatch(x,y,object_location[i][2]-object_location[i][0],object_location[i][3]-object_location[i][1],searchArea);
object_location[i][0] += (x-x1);
object_location[i][1] += (y-y1);
object_location[i][2] += (x-x1);
object_location[i][3] += (y-y1);
if (object_location[i][0]<0) object_location[i][0]=0;
if (object_location[i][1]<0) object_location[i][1]=0;
if (object_location[i][2]>=width) object_location[i][2]=width-1;
if (object_location[i][3]>=height) object_location[i][3]=height-1;
//track nose
x = trackfeature[i][3];
y = trackfeature[i][4];
x1=x;
y1=y;
closestMatch(x,y,size_x,size_y,searchArea);
trackfeature[i][3] = x;
trackfeature[i][4] = y;
//track left eye
x = trackfeature[i][5];
y = trackfeature[i][6];
closestMatch(x,y,size_x,size_y,searchArea);
trackfeature[i][5] = x;
trackfeature[i][6] = y;
//track right eye
x = trackfeature[i][7];
y = trackfeature[i][8];
closestMatch(x,y,size_x,size_y,searchArea);
trackfeature[i][7] = x;
trackfeature[i][8] = y;
}
}
//check if tracking has timed out
trackingTimer++;
if ((trackingTimer>500) || (!found))
{
for (i=0;i<10;i++) trackfeature[i][0]=0;
trackingTimer=0;
trackingEnabled=false;
}
}
//----------------------------------------------------------------------------------------
//finds the closest match for the given region
//----------------------------------------------------------------------------------------
void CFacedetectApp::closestMatch(int &x,int &y,int size_x,int size_y,int searchArea)
{
int xx,yy,x1,y1,p[2],dp,xxx,yyy,new_x,new_y;
long diff,mindiff;
new_x=x;
new_y=y;
mindiff=size_x*size_y*50;
for (xx=x-searchArea;xx0) && (xx+size_x0) && (yy+size_yimageData[((y1+yyy)*width*3)+((x1+xxx)*3)];
p[1] = video_image[flip]->imageData[((yy+yyy)*width*3)+((xx+xxx)*3)];
dp = abs(p[0]-p[1]);
diff += dp;
y1+=2;
}
x1+=2;
}
diff += (abs(xx-x) + abs(yy-y))*4;
if (diffteach(orientationID);
}