www.pudn.com > eyetracking.zip > main.c


/* 
 * EyeTracking 1.0 - Display video from webcam and track user's eye with 
 * manually selected template. 
 * 
 * This program is free software: you can redistribute it and/or modify 
 * it under the terms of the GNU 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 General Public License for more details. 
 *  
 * You should have received a copy of the GNU General Public License 
 * along with this program.  If not, see . 
 * 
 * @author 	  Nashruddin Amin  
 * @copyright Nashruddin Amin 2008 
 * @license	  GNU General Public License 3.0 
 * @version   1.0 
 * @website	  http://www.nashruddin.com 
 */ 
 
 #include "main.h" 
 
int main( int argc, char** argv ) 
{ 
	CvCapture	*capture; 
	int			key; 
 
	display_info(); 
	 
	/* initialize webcam */ 
	capture = cvCaptureFromCAM( 0 ); 
 
	/* always check */ 
	if( !capture ) { 
		fprintf( stderr, "Cannot initialize webcam!\n" ); 
		return 1; 
	} 
	 
	/* test camera */ 
	if( !cvGrabFrame( capture ) ) { 
		fprintf( stderr, "Could not grab a frame!\n" ); 
		return 1;  
	} 
 
	/* get a frame to get video properties, needed by template image */ 
	frame = cvRetrieveFrame( capture ); 
	 
	/* create template image */ 
	tpl = cvCreateImage( cvSize( TPL_WIDTH, TPL_HEIGHT ),  
						 frame->depth, frame->nChannels ); 
 
	/* image for template matching result */ 
	match_res = cvCreateImage( cvSize( 2 * SEARCH_RANGE_X + 1, 
									   2 * SEARCH_RANGE_Y + 1 ), 
							   IPL_DEPTH_32F, 1 ); 
 
	/* create GUI */ 
	cvNamedWindow( "video", CV_WINDOW_AUTOSIZE ); 
	cvShowImage( "video", frame ); 
 
	/* install mouse hander */ 
	cvSetMouseCallback( "video", mouse_handler, NULL ); 
 
	while( TRUE ) {	/* display forever */ 
		if( !cvGrabFrame( capture ) ) { 
			fprintf( stderr, "Could not grab a frame!\n" ); 
			return 1;  
		} 
 
		/* get a frame */ 
		frame = cvRetrieveFrame( capture ); 
 
		/* 'fix' frame */ 
		cvFlip( frame, frame, -1 ); 
		frame->origin = 0; 
 
		/* track object if template has been selected */ 
		if( state == STATE_TRACKING ) { 
			track_object(); 
		} 
		 
		/* display video */ 
		cvShowImage( "video", frame ); 
 
		/* exit if user press a key */ 
		if( ( key = cvWaitKey( 1 ) ) >= 0 ) { 
			goto done; 
		} 
	} 
 
done: 
	/* free memory */ 
	cvDestroyWindow( "video" ); 
	cvReleaseCapture( &capture ); 
 
	return 0; 
} 
 
/** 
 * mouse handler 
 */ 
void mouse_handler( 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 );	 
		object_x0_ini = object_x0; 
		object_y0_ini = object_y0; 
 
		/* extract template from frame */ 
		cvSetImageROI( frame, cvRect( object_x0,  
									  object_y0,  
									  TPL_WIDTH,  
									  TPL_HEIGHT ) ); 
		cvCopy( frame, tpl, NULL ); 
		cvResetImageROI( frame ); 
 
		/* template has been extracted, start tracking! */ 
		state = STATE_TRACKING; 
	} 
} 
 
/** 
 * function to track object 
 */ 
void track_object() 
{ 
	int		win_x0, win_y0, win_x1, win_y1; 
	CvPoint	minloc, maxloc; 
	double	minval, maxval; 
 
	/* setup search window */ 
	win_x0 = object_x0 - SEARCH_RANGE_X; 
	win_y0 = object_y0 - SEARCH_RANGE_Y; 
	win_x1 = win_x0 + TPL_WIDTH  + ( 2 * SEARCH_RANGE_X ); 
	win_y1 = win_y0 + TPL_HEIGHT + ( 2 * SEARCH_RANGE_Y ); 
 
	/* make sure the window still inside the frame */ 
	if( win_x0 < 0 ) { 
		win_x0 = 0; 
		win_x1 = TPL_WIDTH + ( 2 * SEARCH_RANGE_X ); 
	} 
	 
	if( win_y0 < 0 ) { 
		win_y0 = 0; 
		win_y1 = TPL_HEIGHT + ( 2 * SEARCH_RANGE_Y ); 
	} 
 
	if( win_x1 > frame->width ) { 
		win_x1 = frame->width; 
		win_x0 = frame->width - TPL_WIDTH - ( 2 * SEARCH_RANGE_X ); 
	} 
 
	if( win_y1 > frame->height ) { 
		win_y1 = frame->height; 
		win_y0 = frame->height - TPL_HEIGHT - ( 2 * SEARCH_RANGE_Y ); 
	} 
 
	/* draw window */ 
	/* 
	cvRectangle( frame, 
				 cvPoint( win_x0, win_y0 ), 
				 cvPoint( win_x1, win_y1 ), 
				 cvScalar( 0, 255, 0, 0 ),  
				 1, 0, 0 ); 
	*/ 
	 
	/* apply window to frame */ 
	cvSetImageROI( frame, cvRect( win_x0,  
								  win_y0,  
								  win_x1 - win_x0,  
								  win_y1 - win_y0 ) ); 
 
	/* search for matching object */ 
	cvMatchTemplate( frame, tpl, match_res, CV_TM_SQDIFF_NORMED ); 
	cvMinMaxLoc( match_res, &minval, &maxval, &minloc, &maxloc, 0 ); 
 
	/* clear window */ 
	cvResetImageROI( frame ); 
 
	/* if object found... */ 
	if( minval <= THRESHOLD ) { 
		/* save object's current location */ 
		object_x0 = object_x0 - SEARCH_RANGE_X + minloc.x; 
		object_y0 = object_y0 - SEARCH_RANGE_Y + minloc.y; 
 
		/* and draw a box there */ 
		cvRectangle( frame, 
					 cvPoint( object_x0, object_y0 ), 
					 cvPoint( object_x0 + TPL_WIDTH, object_y0 + TPL_HEIGHT ), 
					 cvScalar( 0, 0, 255, 0 ), 1, 0, 0 ); 
	} 
	/* if not found... */ 
	else { 
		/* search around initialization area */ 
		object_x0 = object_x0_ini; 
		object_y0 = object_y0_ini; 
	} 
} 
 
void display_info() 
{ 
	fprintf( stdout, "EyeTracking 1.0 - Track user's eye with manually selected template\n" ); 
	fprintf( stdout, "Author:  Nashruddin Amin (me@nashruddin.com)\n" ); 
	fprintf( stdout, "Website: http://www.nashruddin.com\n\n" ); 
	fprintf( stdout, "Enjoy!\n" ); 
}