When the user initially clicks the eye feature, a box is drawn around the square and the subimage within this square is cropped out of the image frame. The cropped image is used as a template to find the position of the feature in subsequent frames. The system determines the position of the feature using Sum of Square Differences (SQD) method. To reduce extensive computation, the system tracks the feature in a "search window", a small area around the position of the feature in previous frame.
Listing 1: OpenCV Eye Tracking
-
-
-
-
-
-
-
-
-
- #include <stdio.h>
- #include "cv.h"
- #include "highgui.h"
-
- #define TPL_WIDTH 12 /* template width */
- #define TPL_HEIGHT 12 /* template height */
- #define WINDOW_WIDTH 24 /* search window width */
- #define WINDOW_HEIGHT 24 /* search window height */
- #define THRESHOLD 0.3
-
- IplImage *frame, *tpl, *tm;
- int object_x0, object_y0, is_tracking = 0;
-
- void mouseHandler( int event, int x, int y, int flags, void *param );
- void trackObject();
-
-
- int main( int argc, char** argv )
- {
- CvCapture *capture;
- int key;
-
-
- capture = cvCaptureFromCAM( 0 );
-
-
- if( !capture ) return 1;
-
-
- frame = cvQueryFrame( capture );
- if ( !frame ) return 1;
-
-
- tpl = cvCreateImage( cvSize( TPL_WIDTH, TPL_HEIGHT ),
- frame->depth, frame->nChannels );
-
-
- tm = cvCreateImage( cvSize( WINDOW_WIDTH - TPL_WIDTH + 1,
- WINDOW_HEIGHT - TPL_HEIGHT + 1 ),
- IPL_DEPTH_32F, 1 );
-
-
- cvNamedWindow( "video", CV_WINDOW_AUTOSIZE );
- cvSetMouseCallback( "video", mouseHandler, NULL );
-
- while( key != 'q' ) {
-
- frame = cvQueryFrame( capture );
-
-
- if( !frame ) break;
-
-
- cvFlip( frame, frame, -1 );
- frame->origin = 0;
-
-
- if( is_tracking ) trackObject();
-
-
- cvShowImage( "video", frame );
-
-
- key = cvWaitKey( 1 );
- }
-
-
- cvDestroyWindow( "video" );
- cvReleaseCapture( &capture );
- cvReleaseImage( &tpl );
- cvReleaseImage( &tm );
-
- return 0;
- }
-
-
- void mouseHandler( int event, int x, int y, int flags, void *param )
- {
-
- if( event == CV_EVENT_LBUTTONUP ) {
- object_x0 = x - ( TPL_WIDTH / 2 );
- object_y0 = y - ( TPL_HEIGHT / 2 );
-
- cvSetImageROI( frame,
- cvRect( object_x0,
- object_y0,
- TPL_WIDTH,
- TPL_HEIGHT ) );
- cvCopy( frame, tpl, NULL );
- cvResetImageROI( frame );
-
-
- fprintf( stdout, "Template selected. Start tracking... \n" );
- is_tracking = 1;
- }
- }
-
-
- void trackObject()
- {
- CvPoint minloc, maxloc;
- double minval, maxval;
-
-
- int win_x0 = object_x0 - ( ( WINDOW_WIDTH - TPL_WIDTH ) / 2 );
- int win_y0 = object_y0 - ( ( WINDOW_HEIGHT - TPL_HEIGHT ) / 2 );
-
-
-
-
-
-
-
-
-
-
-
- cvSetImageROI( frame,
- cvRect( win_x0,
- win_y0,
- WINDOW_WIDTH,
- WINDOW_HEIGHT ) );
- cvMatchTemplate( frame, tpl, tm, CV_TM_SQDIFF_NORMED );
- cvMinMaxLoc( tm, &minval, &maxval, &minloc, &maxloc, 0 );
- cvResetImageROI( frame );
-
-
- if( minval <= THRESHOLD ) {
-
- object_x0 = win_x0 + minloc.x;
- object_y0 = win_y0 + minloc.y;
-
-
- cvRectangle( frame,
- cvPoint( object_x0, object_y0 ),
- cvPoint( object_x0 + TPL_WIDTH,
- object_y0 + TPL_HEIGHT ),
- cvScalar( 0, 0, 255, 0 ), 1, 0, 0 );
- } else {
-
- fprintf( stdout, "Lost object.\n" );
- is_tracking = 0;
- }
- }
Notice line 117-124, you should add some code to make sure that the search window is still within the frame. If the search window exceed the frame boundaries, it will trigger errors. I will leave this as an exercise for you, dear reader.
Some features to add for the next version:
- Automatic eye detection
- Save the video to file
- Head movement for User Interface
原文:http://nashruddin.com/eyetracking-track-user-eye.html
(Nash ) |