Difference between revisions of "ECE597 Project Interactive Pong"
(→Code) |
(→Code) |
||
| Line 17: | Line 17: | ||
/*Get the color of the hand, so that we can track the movement of the hand automatically.*/ | /*Get the color of the hand, so that we can track the movement of the hand automatically.*/ | ||
| − | void loadTemplateImage() | + | |
| + | |||
| + | |||
| + | == void loadTemplateImage() == | ||
| + | |||
{ | { | ||
| − | IplImage *tempimage = cvLoadImage("/home/dica/workspace/cvex1/sshou.bmp",1); | + | |
| + | IplImage *tempimage = cvLoadImage("/home/dica/workspace/cvex1/sshou.bmp",1); | ||
| + | |||
cvCvtColor( tempimage, hsv, CV_BGR2HSV ); | cvCvtColor( tempimage, hsv, CV_BGR2HSV ); | ||
| + | |||
int _vmin = vmin, _vmax = vmax; | int _vmin = vmin, _vmax = vmax; | ||
| Line 29: | Line 36: | ||
selection.x = 1; | selection.x = 1; | ||
| + | |||
selection.y = 1; | selection.y = 1; | ||
| + | |||
selection.width = 320-1; | selection.width = 320-1; | ||
| + | |||
selection.height= 240-1; | selection.height= 240-1; | ||
cvSetImageROI( hue, selection ); | cvSetImageROI( hue, selection ); | ||
| + | |||
cvSetImageROI( mask, selection ); | cvSetImageROI( mask, selection ); | ||
| + | |||
cvCalcHist( &hue, hist, 0, mask ); | cvCalcHist( &hue, hist, 0, mask ); | ||
| Line 40: | Line 52: | ||
cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 ); | cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 ); | ||
| + | |||
cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 ); | cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 ); | ||
| + | |||
cvResetImageROI( hue ); | cvResetImageROI( hue ); | ||
| + | |||
cvResetImageROI( mask ); | cvResetImageROI( mask ); | ||
| + | |||
track_window = selection; | track_window = selection; | ||
| + | |||
track_object = 1; | track_object = 1; | ||
cvZero( histimg ); | cvZero( histimg ); | ||
| + | |||
int bin_w = histimg->width / hdims; | int bin_w = histimg->width / hdims; | ||
| + | |||
for(int i = 0; i < hdims; i++ ) | for(int i = 0; i < hdims; i++ ) | ||
| + | |||
| + | |||
{ | { | ||
| + | |||
int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 ); | int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 ); | ||
| + | |||
CvScalar color = hsv2rgb(i*180.f/hdims); | CvScalar color = hsv2rgb(i*180.f/hdims); | ||
| + | |||
cvRectangle( histimg, cvPoint(i*bin_w,histimg->height), | cvRectangle( histimg, cvPoint(i*bin_w,histimg->height), | ||
| + | |||
cvPoint((i+1)*bin_w,histimg->height - val), | cvPoint((i+1)*bin_w,histimg->height - val), | ||
| + | |||
color, -1, 8, 0 ); | color, -1, 8, 0 ); | ||
| + | |||
} | } | ||
cvReleaseImage(&tempimage); | cvReleaseImage(&tempimage); | ||
| + | } | ||
| + | |||
| + | |||
| + | /*create window, get the color of the hand and then track the movement of the hand*/ | ||
| + | |||
| + | |||
| + | == int main( int argc, char** argv ) == | ||
| + | |||
| + | |||
| + | { | ||
| + | CvCapture* capture = 0; | ||
| + | |||
| + | if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0]))) | ||
| + | capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 ); | ||
| + | else if( argc == 2 ) | ||
| + | capture = cvCaptureFromAVI( argv[1] ); | ||
| + | |||
| + | if( !capture ) | ||
| + | { | ||
| + | fprintf(stderr,"Could not initialize capturing...\n"); | ||
| + | return -1; | ||
| + | } | ||
| + | |||
| + | cvNamedWindow( "CamShiftDemo", 1 ); | ||
| + | cvNamedWindow( "Histogram", 1 ); | ||
| + | |||
| + | for(;;) | ||
| + | { | ||
| + | IplImage* frame = 0; | ||
| + | int i, bin_w, c; | ||
| + | |||
| + | frame = cvQueryFrame( capture ); | ||
| + | if( !frame ) | ||
| + | break; | ||
| + | |||
| + | if( !image ) | ||
| + | { | ||
| + | /* allocate all the buffers */ | ||
| + | image = cvCreateImage( cvGetSize(frame), 8, 3 ); | ||
| + | image->origin = frame->origin; | ||
| + | hsv = cvCreateImage( cvGetSize(frame), 8, 3 ); | ||
| + | hue = cvCreateImage( cvGetSize(frame), 8, 1 ); | ||
| + | mask = cvCreateImage( cvGetSize(frame), 8, 1 ); | ||
| + | backproject = cvCreateImage( cvGetSize(frame), 8, 1 ); | ||
| + | hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 ); | ||
| + | histimg = cvCreateImage( cvSize(320,200), 8, 3 ); | ||
| + | cvZero( histimg ); | ||
| + | loadTemplateImage(); | ||
| + | } | ||
| + | |||
| + | cvCopy( frame, image, 0 ); | ||
| + | cvCvtColor( image, hsv, CV_BGR2HSV ); | ||
| + | |||
| + | if( track_object ) | ||
| + | { | ||
| + | int _vmin = vmin, _vmax = vmax; | ||
| + | |||
| + | cvInRangeS( hsv, cvScalar(0,smin,MIN(_vmin,_vmax),0), | ||
| + | cvScalar(180,256,MAX(_vmin,_vmax),0), mask ); | ||
| + | cvSplit( hsv, hue, 0, 0, 0 ); | ||
| + | |||
| + | if( track_object < 0 ) | ||
| + | { | ||
| + | float max_val = 0.f; | ||
| + | cvSetImageROI( hue, selection ); | ||
| + | cvSetImageROI( mask, selection ); | ||
| + | cvCalcHist( &hue, hist, 0, mask ); | ||
| + | cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 ); | ||
| + | cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 ); | ||
| + | cvResetImageROI( hue ); | ||
| + | cvResetImageROI( mask ); | ||
| + | track_window = selection; | ||
| + | track_object = 1; | ||
| + | |||
| + | cvZero( histimg ); | ||
| + | bin_w = histimg->width / hdims; | ||
| + | for( i = 0; i < hdims; i++ ) | ||
| + | { | ||
| + | int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 ); | ||
| + | CvScalar color = hsv2rgb(i*180.f/hdims); | ||
| + | cvRectangle( histimg, cvPoint(i*bin_w,histimg->height), | ||
| + | cvPoint((i+1)*bin_w,histimg->height - val), | ||
| + | color, -1, 8, 0 ); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | cvCalcBackProject( &hue, backproject, hist ); | ||
| + | cvAnd( backproject, mask, backproject, 0 ); | ||
| + | cvCamShift( backproject, track_window, | ||
| + | cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ), | ||
| + | &track_comp, &track_box ); | ||
| + | track_window = track_comp.rect; | ||
| + | |||
| + | if( backproject_mode ) | ||
| + | cvCvtColor( backproject, image, CV_GRAY2BGR ); | ||
| + | if( !image->origin ) | ||
| + | track_box.angle = -track_box.angle; | ||
| + | cvEllipseBox( image, track_box, CV_RGB(255,0,0), 3, CV_AA, 0 ); | ||
| + | } | ||
| + | |||
| + | if( select_object && selection.width > 0 && selection.height > 0 ) | ||
| + | { | ||
| + | cvSetImageROI( image, selection ); | ||
| + | cvXorS( image, cvScalarAll(255), image, 0 ); | ||
| + | cvResetImageROI( image ); | ||
| + | } | ||
| + | |||
| + | cvShowImage( "CamShiftDemo", image ); | ||
| + | cvShowImage( "Histogram", histimg ); | ||
| + | |||
| + | } | ||
| + | } | ||
| + | |||
| + | return 0; | ||
} | } | ||
Revision as of 01:39, 21 May 2010
This project is part of the ECE597 32-bit Embedded Linux class at Rose-Hulman Institute of Technology in Terre Haute, IN.
Contents |
Project Goal
The goal of this project is to implement a simple game of "Pong" on the Beagle Board that allows a user to play the game by gesturing with their hands rather than using a mouse or keyboard.
Team Members
Elliot Simon
Mitch Garvin
Matt Luke
Jian Li
Code
OpenCV
/*Get the color of the hand, so that we can track the movement of the hand automatically.*/
void loadTemplateImage()
{
IplImage *tempimage = cvLoadImage("/home/dica/workspace/cvex1/sshou.bmp",1);
cvCvtColor( tempimage, hsv, CV_BGR2HSV );
int _vmin = vmin, _vmax = vmax;
cvInRangeS( hsv, cvScalar(0,smin,MIN(_vmin,_vmax),0), cvScalar(180,256,MAX(_vmin,_vmax),0), mask );
cvSplit( hsv, hue, 0, 0, 0 );
selection.x = 1;
selection.y = 1;
selection.width = 320-1;
selection.height= 240-1;
cvSetImageROI( hue, selection );
cvSetImageROI( mask, selection );
cvCalcHist( &hue, hist, 0, mask );
float max_val = 0.f;
cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 );
cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 );
cvResetImageROI( hue );
cvResetImageROI( mask );
track_window = selection;
track_object = 1;
cvZero( histimg );
int bin_w = histimg->width / hdims;
for(int i = 0; i < hdims; i++ )
{
int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 );
CvScalar color = hsv2rgb(i*180.f/hdims);
cvRectangle( histimg, cvPoint(i*bin_w,histimg->height),
cvPoint((i+1)*bin_w,histimg->height - val),
color, -1, 8, 0 );
}
cvReleaseImage(&tempimage);
}
/*create window, get the color of the hand and then track the movement of the hand*/
int main( int argc, char** argv )
{
CvCapture* capture = 0;
if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );
else if( argc == 2 )
capture = cvCaptureFromAVI( argv[1] );
if( !capture )
{
fprintf(stderr,"Could not initialize capturing...\n");
return -1;
}
cvNamedWindow( "CamShiftDemo", 1 );
cvNamedWindow( "Histogram", 1 );
for(;;)
{
IplImage* frame = 0;
int i, bin_w, c;
frame = cvQueryFrame( capture );
if( !frame )
break;
if( !image )
{
/* allocate all the buffers */
image = cvCreateImage( cvGetSize(frame), 8, 3 );
image->origin = frame->origin;
hsv = cvCreateImage( cvGetSize(frame), 8, 3 );
hue = cvCreateImage( cvGetSize(frame), 8, 1 );
mask = cvCreateImage( cvGetSize(frame), 8, 1 );
backproject = cvCreateImage( cvGetSize(frame), 8, 1 );
hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 );
histimg = cvCreateImage( cvSize(320,200), 8, 3 );
cvZero( histimg );
loadTemplateImage();
}
cvCopy( frame, image, 0 );
cvCvtColor( image, hsv, CV_BGR2HSV );
if( track_object )
{
int _vmin = vmin, _vmax = vmax;
cvInRangeS( hsv, cvScalar(0,smin,MIN(_vmin,_vmax),0),
cvScalar(180,256,MAX(_vmin,_vmax),0), mask );
cvSplit( hsv, hue, 0, 0, 0 );
if( track_object < 0 )
{
float max_val = 0.f;
cvSetImageROI( hue, selection );
cvSetImageROI( mask, selection );
cvCalcHist( &hue, hist, 0, mask );
cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 );
cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 );
cvResetImageROI( hue );
cvResetImageROI( mask );
track_window = selection;
track_object = 1;
cvZero( histimg );
bin_w = histimg->width / hdims;
for( i = 0; i < hdims; i++ )
{
int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 );
CvScalar color = hsv2rgb(i*180.f/hdims);
cvRectangle( histimg, cvPoint(i*bin_w,histimg->height),
cvPoint((i+1)*bin_w,histimg->height - val),
color, -1, 8, 0 );
}
}
cvCalcBackProject( &hue, backproject, hist );
cvAnd( backproject, mask, backproject, 0 );
cvCamShift( backproject, track_window,
cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ),
&track_comp, &track_box );
track_window = track_comp.rect;
if( backproject_mode )
cvCvtColor( backproject, image, CV_GRAY2BGR );
if( !image->origin )
track_box.angle = -track_box.angle;
cvEllipseBox( image, track_box, CV_RGB(255,0,0), 3, CV_AA, 0 );
}
if( select_object && selection.width > 0 && selection.height > 0 )
{
cvSetImageROI( image, selection );
cvXorS( image, cvScalarAll(255), image, 0 );
cvResetImageROI( image );
}
cvShowImage( "CamShiftDemo", image );
cvShowImage( "Histogram", histimg );
} }
return 0;
}
Task List
Below is an estimated list of tasks to complete Task list will be updated as necessary
| Task | Status | Description |
|---|---|---|
| Pong on the Beagle Board | Complete | Port a simple game of classic pong onto the Beagle Board with keyboard/mouse input |
| Webcam interface with the Beagle Board and OpenCV | Complete | Get the Beagle Board to recognize the webcam and perform basic functionalities from OpenCV (connect to camera, snapshot, etc.) |
| Refactor Pong | Complete | Refactor Pong to work with a different input (camera) |
| Track hands with camera and OpenCV | Complete | Track user's hands using OpenCV library functions on the Beagle Board |
| Interface tracking camera with pong | Complete | Join the tracking and game into one system such that users can play pong with their hands |