2010-05-12 01:44:00 +08:00
|
|
|
|
|
|
|
#include <OpenCV/OpenCV.h>
|
|
|
|
#include <cassert>
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
|
|
|
|
const char * WINDOW_NAME = "Face Tracker";
|
|
|
|
const CFIndex CASCADE_NAME_LEN = 2048;
|
|
|
|
char CASCADE_NAME[CASCADE_NAME_LEN] = "~/opencv/data/haarcascades/haarcascade_frontalface_alt2.xml";
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
2012-10-17 15:12:04 +08:00
|
|
|
int main (int argc, char * const argv[])
|
2010-05-12 01:44:00 +08:00
|
|
|
{
|
|
|
|
const int scale = 2;
|
|
|
|
|
|
|
|
// locate haar cascade from inside application bundle
|
|
|
|
// (this is the mac way to package application resources)
|
|
|
|
CFBundleRef mainBundle = CFBundleGetMainBundle ();
|
|
|
|
assert (mainBundle);
|
|
|
|
CFURLRef cascade_url = CFBundleCopyResourceURL (mainBundle, CFSTR("haarcascade_frontalface_alt2"), CFSTR("xml"), NULL);
|
|
|
|
assert (cascade_url);
|
2012-10-17 15:12:04 +08:00
|
|
|
Boolean got_it = CFURLGetFileSystemRepresentation (cascade_url, true,
|
2010-05-12 01:44:00 +08:00
|
|
|
reinterpret_cast<UInt8 *>(CASCADE_NAME), CASCADE_NAME_LEN);
|
|
|
|
if (! got_it)
|
|
|
|
abort ();
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
// create all necessary instances
|
|
|
|
cvNamedWindow (WINDOW_NAME, CV_WINDOW_AUTOSIZE);
|
|
|
|
CvCapture * camera = cvCreateCameraCapture (CV_CAP_ANY);
|
|
|
|
CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*) cvLoad (CASCADE_NAME, 0, 0, 0);
|
|
|
|
CvMemStorage* storage = cvCreateMemStorage(0);
|
|
|
|
assert (storage);
|
|
|
|
|
|
|
|
// you do own an iSight, don't you ?!?
|
|
|
|
if (! camera)
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
// did we load the cascade?!?
|
|
|
|
if (! cascade)
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
// get an initial frame and duplicate it for later work
|
|
|
|
IplImage * current_frame = cvQueryFrame (camera);
|
|
|
|
IplImage * draw_image = cvCreateImage(cvSize (current_frame->width, current_frame->height), IPL_DEPTH_8U, 3);
|
|
|
|
IplImage * gray_image = cvCreateImage(cvSize (current_frame->width, current_frame->height), IPL_DEPTH_8U, 1);
|
|
|
|
IplImage * small_image = cvCreateImage(cvSize (current_frame->width / scale, current_frame->height / scale), IPL_DEPTH_8U, 1);
|
|
|
|
assert (current_frame && gray_image && draw_image);
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
// as long as there are images ...
|
|
|
|
while (current_frame = cvQueryFrame (camera))
|
|
|
|
{
|
|
|
|
// convert to gray and downsize
|
|
|
|
cvCvtColor (current_frame, gray_image, CV_BGR2GRAY);
|
|
|
|
cvResize (gray_image, small_image, CV_INTER_LINEAR);
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
// detect faces
|
|
|
|
CvSeq* faces = cvHaarDetectObjects (small_image, cascade, storage,
|
|
|
|
1.1, 2, CV_HAAR_DO_CANNY_PRUNING,
|
|
|
|
cvSize (30, 30));
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
// draw faces
|
|
|
|
cvFlip (current_frame, draw_image, 1);
|
|
|
|
for (int i = 0; i < (faces ? faces->total : 0); i++)
|
|
|
|
{
|
|
|
|
CvRect* r = (CvRect*) cvGetSeqElem (faces, i);
|
|
|
|
CvPoint center;
|
|
|
|
int radius;
|
|
|
|
center.x = cvRound((small_image->width - r->width*0.5 - r->x) *scale);
|
|
|
|
center.y = cvRound((r->y + r->height*0.5)*scale);
|
|
|
|
radius = cvRound((r->width + r->height)*0.25*scale);
|
|
|
|
cvCircle (draw_image, center, radius, CV_RGB(0,255,0), 3, 8, 0 );
|
|
|
|
}
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
// just show the image
|
|
|
|
cvShowImage (WINDOW_NAME, draw_image);
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
// wait a tenth of a second for keypress and window drawing
|
|
|
|
int key = cvWaitKey (100);
|
|
|
|
if (key == 'q' || key == 'Q')
|
|
|
|
break;
|
|
|
|
}
|
2012-10-17 15:12:04 +08:00
|
|
|
|
2010-05-12 01:44:00 +08:00
|
|
|
// be nice and return no error
|
|
|
|
return 0;
|
|
|
|
}
|