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); 
}