OpenCV Face Detection

Feb 5, 2009 | Tags: OpenCV | del.icio.us del.icio.us | digg Digg

OpenCV has an example of Face Detection, located in the samples directory of OpenCV distribution. It uses a type of face detector called a Haar Cascade classifier. Basically it performs a simple operation. Given an image, the face detector examine each image location and classifies it as "face" or "not face".

However, I found that the example is hard to understand. So I simplify the code and add some comments for us to better understand it. I also modify the code to take the input from webcam rather than static images.

The code below displays video from webcam, detect faces and draw a surrounding box for each face found.

Listing 1: OpenCV Face Detection

  1. /**
  2.  * Display video from webcam and detect faces
  3.  */
  4. #include <stdio.h>
  5. #include "cv.h"
  6. #include "highgui.h"
  7.  
  8. CvHaarClassifierCascade *cascade;
  9. CvMemStorage            *storage;
  10.  
  11. void detectFaces( IplImage *img );
  12.  
  13. int main( int argc, char** argv )
  14. {
  15.     CvCapture *capture;
  16.     IplImage  *frame;
  17.     int       key;
  18.     char      *filename = "haarcascade_frontalface_alt.xml";
  19.  
  20.     /* load the classifier
  21.        note that I put the file in the same directory with
  22.        this code */
  23.     cascade = ( CvHaarClassifierCascade* )cvLoad( filename, 0, 0, 0 );
  24.  
  25.     /* setup memory buffer; needed by the face detector */
  26.     storage = cvCreateMemStorage( 0 );
  27.  
  28.     /* initialize camera */
  29.     capture = cvCaptureFromCAM( 0 );
  30.  
  31.     /* always check */
  32.     assert( cascade && storage && capture );
  33.  
  34.     /* create a window */
  35.     cvNamedWindow( "video", 1 );
  36.  
  37.     while( key != 'q' ) {
  38.         /* get a frame */
  39.         frame = cvQueryFrame( capture );
  40.  
  41.         /* always check */
  42.         if( !frame ) break;
  43.  
  44.         /* 'fix' frame */
  45.         cvFlip( frame, frame, -1 );
  46.         frame->origin = 0;
  47.  
  48.         /* detect faces and display video */
  49.         detectFaces( frame );
  50.  
  51.         /* quit if user press 'q' */
  52.         key = cvWaitKey( 10 );
  53.     }
  54.  
  55.     /* free memory */
  56.     cvReleaseCapture( &capture );
  57.     cvDestroyWindow( "video" );
  58.     cvReleaseHaarClassifierCascade( &cascade );
  59.     cvReleaseMemStorage( &storage );
  60.  
  61.     return 0;
  62. }
  63.  
  64. void detectFaces( IplImage *img )
  65. {
  66.     int i;
  67.  
  68.     /* detect faces */
  69.     CvSeq *faces = cvHaarDetectObjects(
  70.             img,
  71.             cascade,
  72.             storage,
  73.             1.1,
  74.             3,
  75.             0 /*CV_HAAR_DO_CANNY_PRUNNING*/,
  76.             cvSize( 40, 40 ) );
  77.  
  78.     /* for each face found, draw a red box */
  79.     for( i = 0 ; i < ( faces ? faces->total : 0 ) ; i++ ) {
  80.         CvRect *r = ( CvRect* )cvGetSeqElem( faces, i );
  81.         cvRectangle( img,
  82.                      cvPoint( r->x, r->y ),
  83.                      cvPoint( r->x + r->width, r->y + r->height ),
  84.                      CV_RGB( 255, 0, 0 ), 1, 8, 0 );
  85.     }
  86.  
  87.     /* display video */
  88.     cvShowImage( "video", img );
  89. }
  90.  

Related Articles

Recommended Books

The Downloads

68 Comments

Jin Le on Feb 23, 2009:

Hi Nash.

I am a beginner at openCV and i really like to try out your face dectection application... but the thing is that i having problems getting the application up and running..
when i try to compile it, there are no errors of any kind... but a cmd promt says (assertion failed) pointing on this line of code "assert( cascade && storage && capture );" i am using VS 2008 c++

please give me a pointer..
i am looking forward for your reply ...
best regards

Jin le

Nash on Feb 24, 2009:

Hi,
It looks like the program cannot find any webcam attached to your computer, since it takes the input from webcam. To take the input from static images, replace main() with this:

int main( int argc, char** argv )
{
  CvCapture *capture;
  IplImage  *img;
  int       key;
  char      *filename = "haarcascade_frontalface_alt.xml";

  cascade = ( CvHaarClassifierCascade* )cvLoad( filename, 0, 0, 0 );
  storage = cvCreateMemStorage( 0 );
  img     = cvLoadImage( argv[1], 1 );

  assert( cascade && storage && img );

  cvNamedWindow( "video", 1 );
  detectFaces( img );
  cvWaitKey( 0 );
  cvDestroyWindow( "video" );
  cvReleaseImage( &img );
  cvReleaseHaarClassifierCascade( &cascade );
  cvReleaseMemStorage( &storage );

  return 0;
}
Run the program from your DOS box with command like: facedetect myphoto.jpg.

Also make sure that you have copied haarcascade_frontalface_alt.xml to the same directory with the code above.

ABHAY SHANKAR on Feb 27, 2009:

Hi Nash,
I am studying on the face detection algorithm (my research is on face recognition and comparison) using the haar like features by openCV. I wish to know the XML file used by the facedetect.c code.

My questions are:-

1. What are these threshold values n where are these values coming from?

2. Are the threshold value in the XML file directly compared with the haar features values calculated by the cvIntegeral?

3. What are "stage threshold" and "left value" and "right value"?

4. Can I use Phase Correlation technique for face recognition and comparison?

Nash on Feb 27, 2009:

Hi Abhay,
There is a good tutorial about finding faces with OpenCV that explains the parameters in cvHaarDetectObjects. Maybe we can find the answers there

atzu on Mar 3, 2009:

Hi Nash, great work.
I'd like to try your code but I have the same problem as the first comment. The line that says assertion failed "assert( cascade && storage && capture );" is getting the code crazy. I tried the script to see the video from my webcam and works fine so I can't understand why this doesn't... Any idea?

atzu on Mar 3, 2009:

Hi Nash, great work.
Works fine thanks. Just solved, was just the name of the haarcascade file name that was twice named as .xml... Didn't load properly, maybe the first comment is having the same problem because I downloaded from the wiki.

fuzy on Mar 19, 2009:

hi nash , really good work , but i have a problem with this code , when i compile it i find an error in a black prompt "assert( haarface , .... )" , i found that assert is working fine with img but with capture this error takes place , and i am sure my web cam is fine , i run it with your program "Display Video from Webcam" and it works fine , so can u help me plzzz , thx in advance

Kamardin on Apr 22, 2009:

Salam,

Congratz! Bro...
You have done a really good work to share with others. I do hope the good deed regain the good reciproration, dude!.

Eak on Apr 22, 2009:

If we will be used Kalman filter for tracking object then Haar detection. Will we be written code? Help me, please.

Aaron on May 14, 2009:

Hi, i have been trying your source code out, however there's a problem.

MFC Application will show
facetest3 MFC Application has encountered a problem and needs to close. We are sorry for the inconvenience.

I wish to ask why? did I miss out something?
I have already included library files, copied haarcascade_frontalface_alt.xml into same folder. You have any idea what when wrong? or is it my webcam cannot be detected with OPENCV?

Nash on May 15, 2009:

Hi,
I don't have VC++ so I'm afraid I cannot help. But I suggest you to use gcc compiler. We're using it and it works very well.

Jaideep on May 15, 2009:

Hi Nash,
I am working on the face detection algorithm (my research is on face recognition and comparison) by openCV.

I want to know that is there any limitation for comparison.

Is there any limitation for width and height?
Is there any limitation for size in KB?

Please reply.
Thanks in advance

Nash on May 15, 2009:

Hi,
You're doing face recognition. That's cool. Only one thing, I know nothing about it

felix on May 21, 2009:

This your "Display video from webcam and detect faces" code is a great welldone job. But I have the following problem with the codes:
1. It did not automatically take the picture of the face detected.
2. The dispalyed video output is upside down.
3. I need some codes to save picture taken by the codes.

Please Nash, i will really appreciate it further if you could help me out with the above issues.

Thanks a lot in advance.

Nash on May 22, 2009:

To fix the upside down frame, try to replace:

cvFlip(frame, frame, -1);

with this:

cvFlip(frame, frame, 0);

---

To save the detected faces into separate images, here's a quick and dirty code:

char *filename = "";
if (cvWaitKey(1) == 's') {
  for(i = 0 ; i < (faces ? faces->total : 0); i++) {
    sprintf(filename, "%d.jpg", (i+1));
    CvRect *r = (CvRect*)cvGetSeqElem(faces, i);
    cvSetImageROI(img, cvRect(r->x, r->y, r->width, r->height));
    cvSaveImage(filename, img);
    cvResetImageROI(img);
  }
}
The code above will save the detected faces to 1.jpg, 2.jpg, ..., n.jpg when you press the 's' button. Put the code at the end of detectFaces().

Felix Okoye on May 22, 2009:

Thanks a lot for the codes and your prompt response to my questions.

I was able to correct the upside down frame based on your kind clue but for the saving of the detected faces, i receive this error "Unhandled exception at 0x10228567 (msvcr80d.dll) in det.exe: 0xC0000005: Access violation writing location 0x00415643" immediately I press the letter "s"(det is my file's name).

I'm sorry to disturb you again, but your kind assistance will be more highly appreciated.

Many thanks in advance.

Nash on May 23, 2009:

It looks like VC++ doesn't like the sprintf() part. Maybe you have to format filename in VC++'s way. Since I don't have VC++, I cannot help you to figure it out.

Btw, when you have solved your problem, consider to put the solution in this forum.

Gabriel on Jun 24, 2009:

Hi, I discovered what is happening with the, "assert( cascade && storage && capture );" problem.

The problem is that the program doesn´t load the Harr cascade correctly. I discover it adding this to verify the output. It was giving always error.

capture = cvCaptureFromCAM( CV_CAP_ANY );
if( !capture ) {
    fprintf( stderr, "ERROR: capture is NULL n" );
    getchar();
    return -1;
}


The solution can be find it here:

http://www.openframeworks.cc/forum/viewtopic.php?f=10&t=1853

By the way, what a great blog!! Thanks man!!
Peace from Spain

Gabriel on Jun 24, 2009:

Hi there!

I just soved the problem!

The version I had was buggy, I just installed the opencv libraries from the repositories of Ubuntu 8.10 and it worked. The versión is 1.0.0.6-1

The problem was at this line

cascade = (CvHaarClassifierCascade*)cvLoad( "haarcascade_frontalface_alt.xml", 0, 0, 0 );

Thanks again and keep sharing so great tutorials, they are really helpful.

Tim on Jul 1, 2009:

@Nash

look at these two lines:

1. char *filename = "";
4. sprintf(filename, "%d.jpg", (i+1));

for me it seems, that's not a VC++ problem, it's a problem putting at least 6 bytes in a 1 byte buffer.

Nash on Jul 1, 2009:

Man, you're right! I forgot to initialize the variable. So here's the correct version:

char filename[6];
if (cvWaitKey(1) == 's') {
  for(i = 0 ; i < (faces ? faces->total : 0); i++) {
    sprintf(filename, "%d.jpg", (i+1));
    CvRect *r = (CvRect*)cvGetSeqElem(faces, i);
    cvSetImageROI(img, cvRect(r->x, r->y, r->width, r->height));
    cvSaveImage(filename, img);
    cvResetImageROI(img);
  }
}
It will save the subimage to 1.jpg, ..., n.jpg. Thanks.

felix on Jul 12, 2009:

Hi Nash,

i think the above codes still need some adjustments. It's able to store the first image but instead of storing subsequent images, it replaces the firstly stored one. Hence it could only store only one(1) image.

Can u try out something ?

TQ

abyadh on Jul 21, 2009:

Hi Nash,

I actually working on the same coding as yours, i tried to save every single image detected from the program. it works, but right now i'm not satisfied with the outcome since the filename is printed according to the value of k..here is the code

for( i = 0; i < (faces ? faces->total : 0); i++ )
{
   /* extract the rectanlges only */
   CvRect face_rect = *(CvRect*)cvGetSeqElem( faces, i);

   IplImage* clone = cvCreateImage (cvSize(img->width, img->height),
                                    IPL_DEPTH_8U, img->nChannels );
  
   cvCopy (img, clone, 0);
   cvNamedWindow ("ROI", CV_WINDOW_AUTOSIZE);
   cvSetImageROI ( clone, face_rect);
   face_rect = cvGetImageROI ( clone );
   cvShowImage ("ROI", clone);
   k = (int) cvGetTickCount();
   char *name=0;
   name=(char*) calloc(255, 1);
   sprintf(name, "Image %d.jpg", k);
   cvSaveImage(name, clone);
}

Nash on Jul 22, 2009:

Then give it a filename you like. What's the problem?

Luis on Aug 20, 2009:

can you tell me if there are a version of this library for c#?

Nash on Aug 20, 2009:

Here it is:

http://www.emgu.com

Jason on Aug 29, 2009:

Hey Nash
great tutorial..
i have compiled ur program . But i'm getting an error message when script prompt to show my webcam then a box show

Null pointer (Invalid classifier cascade)

Please help me out..

Nash on Aug 29, 2009:

The code above needs the haar classifier xml file. I didn't include it in the zip file, since you already have the file in your disk. If you installed OpenCV in:

C:/OpenCV

then the xml file is located at:

C:/OpenCV/data/haarcascades/haarcascade_frontalface_alt.xml

So all you have to do is copy the xml file to your working dir, and the code above should work just fine.

raj on Sep 12, 2009:

hey nash i'm doing hand recognition right now and for that i intend to use the haar classifier -but i am not sure about how to go about doing it as i'm still pretty new to opencv . If you could please explain to me how to train classifier and stuff like how to create .xml file and use it in the detction code i'l be very grateful .you dont have to give me the code just please explain me the steps involved and what to watch out for

also i have heard tht training a classifier takes about 3-5 days to train is this true?
thanks in adv

Nash on Sep 13, 2009:

Hi,

I've no experience on building classifiers, but here's the howto. It looks like it does take a lot of time to build one.

Note: if you've managed to build the classifier, consider to upload the xml file in this forum

Anju on Sep 14, 2009:

hi Nash,
Is it necessary to train the classifier for a generic object detection. My aim is to detect all the objects in a video. Is it possible to do the same without training the classifier? I mean is there any algorithm for this?

Nash on Sep 14, 2009:

Yes you can train classifiers for the objects. But why would you do that? you can track the objects using motion or color detection.

Anju on Sep 14, 2009:

Thanks a lot. Just wanted to confirm this.

Felipe on Oct 16, 2009:

Nash, good afternoon.

I found this very interesting topic and I wonder if there is such a library for Delphi 7.
Whether you have the package with the files .Pas and the dll to the examples cited above.
And also like to know what function that detects the characteristics of the face, because I saw some examples and the examples only detects the face and not his features.

Thank

Felipe Carnevali

Nash on Oct 17, 2009:

Hi,

I don't know if there is an OpenCV wrapper to Delphi. But IMHO, Delphi isn't suitable for computer vision tasks.

There are some papers out there that describe face features, but I haven't implement any yet.

watachi on Oct 30, 2009:

super thanks, the sample code from opencv was really complicated your is a bless,, opencv 2.0-visual 2008

Tony on Nov 18, 2009:

Thanks for uploading this tutorial. Was really a great help to me! Was just wondering, would it be possible to alter this code to take input from a video rather than webcam/static image. Im quite new to opencv, so your help will be much appreciated.

Thanks

Greg on Dec 17, 2009:

Nash,

Greate work!!

I'm learning OpenCV, and I was playing a video, and when I apply cvPyrDown to get a smood image, the video turned upside down, with your suggestion of the cvFlip(source, destination, 0); the problem was corrected and now everything looks perfect!!

Thanks alot!

Mohamed Alkaduhimi on Jan 28, 2010:

Nice example Nash, keep up the good work. What is wrong with some people here can't they write c code? They ask some very basic questions :S, my advice is to learn basic c and then study openCV.

Lideman on Feb 3, 2010:

Does anybody know how can i make a robot head that can follow the faces using Basic Stamp?
Thanks
best regards for all.

alex on Feb 14, 2010:

Try it at : http://www.progisma.com/face_detection/submit. If you need any help with face detection with OpenCV, contact me.

john on Feb 20, 2010:

Hi Nash...
My code on face detection works perfectly on VS 2008..
But i need to know how to make this code for multi threading... can you help me out

Dileep S.P on Mar 8, 2010:

Hi nash,

Im a newbie to openCV

I tried out your code but, There is a delay for the cam output, even though i changed the values for cvWaitKey there is too much delay, I am working with very limited hardware resources so is there a way to reduce the resolution of the img and still be able to detect faces, or some other approach to optimize the program ?

Nash on Mar 9, 2010:

Try to resize the frames taken from the camera:

capture = cvCaptureFromCAM(0);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 240);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 160);

askl on Mar 23, 2010:

can someone please post the full source code that has been modified and corrected? that would help a lot.

newbie

Kit on Apr 20, 2010:

Nash

I use the code

for( i = 0; i < (faces ? faces->total : 0); i++ )
{
   /* extract the rectanlges only */
   CvRect face_rect = *(CvRect*)cvGetSeqElem( faces, i);

   IplImage* clone = cvCreateImage (cvSize(img->width, img->height),
                                    IPL_DEPTH_8U, img->nChannels );
   
   cvCopy (img, clone, 0);
   cvNamedWindow ("ROI", CV_WINDOW_AUTOSIZE);
   cvSetImageROI ( clone, face_rect);
   face_rect = cvGetImageROI ( clone );
   cvShowImage ("ROI", clone);
   k = (int) cvGetTickCount();
   char *name=0;
   name=(char*) calloc(255, 1);
   sprintf(name, "Image %d.jpg", k);
   cvSaveImage(name, clone);
}
to save the image

but i want the saving image to have same szie for example(92X112)

how to correct the code???

Rustam Rakhimov on Apr 22, 2010:

Hi everybody, cvFlip( frame, frame, 0); didn't work in my case, but when I put cvFlip( frame, frame, 1); is ok

jasm on May 21, 2010:

HI
my research about detect face like eye ,nose and mouse (when person sleep) i want person help me in the code. also code determine the angle of the tilting(can send code in my e-mail)

Javier on May 26, 2010:

Hi
im new to opencv and im using the program just as specified above, but in the part to saves images

for( i = 0; i < (faces ? faces->total : 0); i++ )
{
   /* extract the rectangles only */
   CvRect face_rect = *(CvRect*)cvGetSeqElem( faces, i);

   IplImage* clone = cvCreateImage(
      cvSize(img->width, img->height),
      IPL_DEPTH_8U,
      img->nChannels
   );
   
   cvCopy (img, clone, 0);
   cvNamedWindow ("ROI", CV_WINDOW_AUTOSIZE);
   cvSetImageROI ( clone, face_rect);
   face_rect = cvGetImageROI ( clone );
   cvShowImage ("ROI", clone);
   k = (int) cvGetTickCount();
   char *name=0;
   name=(char*) calloc(255, 1);
   sprintf(name, "Image %d.jpg", k);
   cvSaveImage(name, clone);
}
i get an unexpected crash

Unhandled exception at 0x610ca189 in frames.exe: 0xC0000005: Access violation writing location 0x001c5954.

dont know what to do, i know its a memory error but dont know how to fix it

thnks in advanced

amira on Jun 3, 2010:

hi Nash
i new on opencv and ask to know what the simple way to learn it

Nash on Jun 4, 2010:

1. Visit OpenCV wiki
2. Try OpenCV examples in the sample directory
3. Read Learning OpenCV
4. Write a project

Thumbu on Jun 4, 2010:

hello there i need to know whether the above codings are to be executed in .net? please help me...

Shervin Emami on Jun 8, 2010:

I also wrote a tutorial showing Face Detection, and also how to extend it with Face Recognition from a webcam:

http://www.shervinemami.co.cc/openCV.html

Cheers,
Shervin Emami.

RAVI on Jun 16, 2010:

man you rock.....!!!!! The code is excellent and running great.... thanks a lot....thank you very much

vibin on Jun 17, 2010:

hey

am geting an error when am using the cvSaveimage(name,clone).
it says that cvSaveimage has too few arguments.

am using ubuntu 10.04

Nash on Jun 18, 2010:

Try cvSaveImage(name, clone, NULL);

Mamdouh on Jul 1, 2010:

hello
i'm using facedetect code to find object in picture and the code work done and get 100% from result on machine but on another machine get 60% from result
i'm using same code at two machines and same version of openCV "2.0" and visualStudio "2005"

thanks

Robert on Jul 11, 2010:

Great example!
The camera videos display is working and detecting a face except I am getting a

ERROR: SampleCB() - buffer sizes do not match

message on my DOS window command line box.
Anyone has this problem?

Rezaei on Oct 27, 2010:

I SOLVED IT!

Every body should apply these correctiones:

1- Add include "stdafx.h" in the first line not 2nd or later!
2- The main problem is the location of haarcascade classifier
if you do not copied the .xml file into the project directory you need to add the path of xml. file such as below:

char *filename = "C:/opencv2.1/data/haarcascades/haarcascade_frontalface_alt.xml";

Cheers

Rezaei on Oct 27, 2010:

Hi Nash,

I have no problem to work with your code. its great and works.
Could you please add some code to save the showing video and detected face in a .avi video (instead of saving results in .jpg files)?

Thanks

Nash on Oct 27, 2010:

That's the bad news. OpenCV's function for writing videos is still buggy.

Rezaei on Oct 27, 2010:

Really? Unbelievable!
You mean there is now way to save the sequences as a video?
So, what do you advise me if I want to save the outcome of the face detection program for a presentation?
You can see a lots of face detection videos on Youtube. how did they do?

Thanks

Rezaei on Oct 28, 2010:

Hi Nash,
Could you please place a code to detect face in separate positive & negative files located in a folder (1.jpg, 2.jpg,...), and then show them one be one. I have one code that uses a classifier called Qtracker not Haar-like features. Qtracker is not so accurate.

I appreciate for your kind considerations.

Thank you!

Mahdi

Squally on Nov 2, 2010:

@Rezaei
there are programs for screencapturing like fraps, camstudio or several other - so you can create youtubevideos by capturing the program working

the other question - quite not sure what you mean by negative images, but imagine that you mean, when no face was detected

did not used codetags because i am not the one who was asked for and realy not sure whether i got your problem ^^

global variables:
int posCounter = 1;
int negCounter = 1;

code in "detectFaces(IplImage* img)":

char* filename = "";
if (i==0)
{
   sprintf(filename, "negative/%d.jpg", (negCounter));
   negCounter++;
}
else
{
   sprintf(filename, "positive/%d.jpg", (posCounter));
   posCounter++;
}
cvSaveImage(filename, img);
so this should save the images in a folder in your projectfolder, numbered
i didn't test it - just my quick thoughts
for output i am quite sure you can initialize a loop by yourself

hope this will be helpful

by the way
@nash
nice site =)

Rezaei on Nov 14, 2010:

Thanks Nash.
Yes, your site is nice

Prasad on Nov 21, 2010:

Hello Nash,
Thanks for the tutorial.

I tried to execute your code but ending up at this error.
libdc1394 error: Failed to initialize libdc1394 This is not opening my camera itself.
I tried https://bugs.launchpad.net/ubuntu/+source/libdc1394-22/+bug/462453
but seems nothing work out!

Any help you could provide?
Prasad

Squally on Nov 25, 2010:

maybe try this

http://www.ngohaibac.com/how-to-fix-libdc1394-error-failed-to-initialize-libdc1394/

seems you have to change your permissions. hope this helps - good luck =)

lg Squally

Abhishek on Dec 1, 2010:

sir please tell me from where i get the .xml file .................

Leave a comment

Name (required)
Email (will not be published) (required)
Website

Characters left = 1000