Saturday, October 2, 2010

OpenCV code for Face Detection(followed by eyes,nose & mouth detection)


In this article I will demonstrate how to perform human face and eyes detection on images using OpenCV in visualC++.

The detection is performed using Haar Cascades.There are different cascades avaliable with the opencv software to detect face and other important parts like eyes,nose and mouth.

The code takes static images from the database.First it detects the face from the input image read from the database.since opencv functions are used ,images of any format can be used.

If there is any face in the image,it is detected , then other parts like eyes,nose mouth are detected.

After we successfully detect the face, we estimate the location of the eyes and we set ROI(Region of Interest)to perform eye detection. We need to estimate the eyes location in order to reduce false detections.

Similar procedure is followed to detect nose and mouth.

Currently I am using the following cascades to detect face,eyes,nose and mouth

haarcascade_frontalface_alt2.xml
haarcascade_mcs_eyepair_big.xml
haarcascad_mcs_nose.xml
haarcascade_mcs_mouth.xml

other cascades can also be tried to get better results basing on the requirements.
like my requirement is to detect frontal face , so i used frontlface haarcascade.


/* program to detect facial features using opencv*/

/* detectFacialfeatures() is the main function that detects the face followed by Eyes,nose and mouth detection.*/

#include "stdafx.h"


/**
 * Loads static images from database and detect faces
 */
#include <stdio.h>
#include<conio.h>
#include "cv.h"
#include "highgui.h"
#include "cvaux.h"

CvHaarClassifierCascade *cascade,*cascade_e,*cascade_nose,*cascade_mouth;
CvMemStorage            *storage;
char *face_cascade="haarcascade_frontalface_alt2.xml";
char *eye_cascade="haarcascade_mcs_eyepair_big.xml";
char *nose_cascade="haarcascade_mcs_nose.xml";
char *mouth_cascade="haarcascade_mcs_mouth.xml";

/*Mouth detect ion*/
void detectMouth( IplImage *img,CvRect *r)
{
   CvSeq *mouth;
   //mouth detecetion - set ROI
   cvSetImageROI(img,/* the source image */
                 cvRect(r->x,            /* x = start from leftmost */
                        r->y+(r->height *2/3), /* y = a few pixels from the top */
                        r->width,        /* width = same width with the face */
                        r->height/3    /* height = 1/3 of face height */
                       )
                );
    mouth = cvHaarDetectObjects(img,/* the source image, with the estimated location defined */
                                cascade_mouth,      /* the eye classifier */
                                storage,        /* memory buffer */
                                1.15, 4, 0,     /* tune for your app */
                                cvSize(25, 15)  /* minimum detection scale */
                               );

        for( int i = 0; i < (mouth ? mouth->total : 0); i++ )
        {
     
          CvRect *mouth_cord = (CvRect*)cvGetSeqElem(mouth, i);
          /* draw a red rectangle */
          cvRectangle(img,
                      cvPoint(mouth_cord->x, mouth_cord->y),
                      cvPoint(mouth_cord->x + mouth_cord->width, mouth_cord->y + mouth_cord->height),
                      CV_RGB(255,255, 255),
                      1, 8, 0
                    );
        }
     //end mouth detection
         
}

/*Nose detection*/
void detectNose( IplImage *img,CvRect *r)
{
  CvSeq *nose;
 
  //nose detection- set ROI
  cvSetImageROI(img,                    /* the source image */
                cvRect(r->x,            /* x = start from leftmost */
                       r->y , /* y = a few pixels from the top */
                       r->width,        /* width = same width with the face */
                       r->height  /* height = 1/3 of face height */
                      )
               );
         

  nose = cvHaarDetectObjects(img, /* the source image, with the estimated location defined */
                             cascade_nose,      /* the eye classifier */
                             storage,        /* memory buffer */
                             1.15, 3, 0,     /* tune for your app */
                             cvSize(25, 15)  /* minimum detection scale */
                            );

  for( int i = 0; i < (nose ? nose->total : 0); i++ )
      {
          CvRect *nose_cord = (CvRect*)cvGetSeqElem(nose, i);

          /* draw a red rectangle */
          cvRectangle(img,
                      cvPoint(nose_cord->x, nose_cord->y),
                      cvPoint(nose_cord->x + nose_cord->width, nose_cord->y + nose_cord->height),
                      CV_RGB(0,255, 0),
                      1, 8, 0
                    );

      }
}

/*Eyes detection*/
void detectEyes( IplImage *img,CvRect *r)
{
    char *eyecascade;
    CvSeq *eyes;
    int eye_detect=0;
   

   //eye detection starts
  /* Set the Region of Interest: estimate the eyes' position */
   
    cvSetImageROI(img,                    /* the source image */
          cvRect
          (
              r->x,            /* x = start from leftmost */
              r->y + (r->height/5.5), /* y = a few pixels from the top */
              r->width,        /* width = same width with the face */
              r->height/3.0    /* height = 1/3 of face height */
          )
      );

      /* detect the eyes */
      eyes = cvHaarDetectObjects( img,            /* the source image, with the estimated location defined */
                                  cascade_e,      /* the eye classifier */
                                  storage,        /* memory buffer */
                                  1.15, 3, 0,     /* tune for your app */
                                  cvSize(25, 15)  /* minimum detection scale */
                                );
   
      printf("\no of eyes detected are %d",eyes->total);
   
     
        /* draw a rectangle for each detected eye */
        for( int i = 0; i < (eyes ? eyes->total : 0); i++ )
          {
              eye_detect++;
              /* get one eye */
              CvRect *eye = (CvRect*)cvGetSeqElem(eyes, i);
              /* draw a red rectangle */
                        cvRectangle(img,
                                    cvPoint(eye->x, eye->y),
                                    cvPoint(eye->x + eye->width, eye->y + eye->height),
                                    CV_RGB(0, 0, 255),
                                    1, 8, 0
                                   );
           }

           
}
void detectFacialFeatures( IplImage *img,IplImage *temp_img,int img_no)
{
   
    char image[100],msg[100],temp_image[100];
    float m[6];
    double factor = 1;
    CvMat M = cvMat( 2, 3, CV_32F, m );
    int w = (img)->width;
    int h = (img)->height;
    CvSeq* faces;
    CvRect *r;

    m[0] = (float)(factor*cos(0.0));
    m[1] = (float)(factor*sin(0.0));
    m[2] = w*0.5f;
    m[3] = -m[1];
    m[4] = m[0];
    m[5] = h*0.5f;
   
    cvGetQuadrangleSubPix(img, temp_img, &M);
    CvMemStorage* storage=cvCreateMemStorage(0);
    cvClearMemStorage( storage );
   
    if( cascade )
        faces = cvHaarDetectObjects(img,cascade, storage, 1.2, 2, CV_HAAR_DO_CANNY_PRUNING, cvSize(20, 20));
    else
        printf("\nFrontal face cascade not loaded\n");

    printf("\n no of faces detected are %d",faces->total);
   

    /* for each face found, draw a red box */
    for(int i = 0 ; i < ( faces ? faces->total : 0 ) ; i++ )
    {       
        r = ( CvRect* )cvGetSeqElem( faces, i );
        cvRectangle( img,cvPoint( r->x, r->y ),cvPoint( r->x + r->width, r->y + r->height ),
                     CV_RGB( 255, 0, 0 ), 1, 8, 0 );   
   
        printf("\n face_x=%d face_y=%d wd=%d ht=%d",r->x,r->y,r->width,r->height);
       
        detectEyes(img,r);
        /* reset region of interest */
        cvResetImageROI(img);
        detectNose(img,r);
        cvResetImageROI(img);
        detectMouth(img,r);
        cvResetImageROI(img);
    }
    /* reset region of interest */
      cvResetImageROI(img);

      if(faces->total>0)
        {
            sprintf(image,"D:\\face_output\\%d.jpg",img_no);
            cvSaveImage( image, img );
        }
}

int main( int argc, char** argv )
{
    CvCapture *capture;
    IplImage  *img,*temp_img;
    int       key;

    char image[100],temp_image[100];
   

    /* load the classifier
       note that I put the file in the same directory with
       this code */
    storage = cvCreateMemStorage( 0 );
        cascade = ( CvHaarClassifierCascade* )cvLoad( face_cascade, 0, 0, 0 );
    cascade_e = ( CvHaarClassifierCascade* )cvLoad( eye_cascade, 0, 0, 0 );
    cascade_nose = ( CvHaarClassifierCascade* )cvLoad( nose_cascade, 0, 0, 0 );
    cascade_mouth = ( CvHaarClassifierCascade* )cvLoad( mouth_cascade, 0, 0, 0 );


   
    if( !(cascade || cascade_e ||cascade_nose||cascade_mouth) )
        {
        fprintf( stderr, "ERROR: Could not load classifier cascade\n" );
        return -1;
        }
   
    for(int j=20;j<27;j++)
    {

         sprintf(image,"D:\\ptz images\\%d.jpg",j);
       
        img=cvLoadImage(image);
        temp_img=cvLoadImage(image);
       
        if(!img)
        {
        printf("Could not load image file and trying once again: %s\n",image);
        }
        printf("\n curr_image = %s",image);
     
        detectFacialFeatures(img,temp_img,j);
    }
 

    cvReleaseHaarClassifierCascade( &cascade );
    cvReleaseHaarClassifierCascade( &cascade_e );
   
    cvReleaseHaarClassifierCascade( &cascade_nose );
    cvReleaseHaarClassifierCascade( &cascade_mouth );
    cvReleaseMemStorage( &storage );
   
     cvReleaseImage(&img);
     cvReleaseImage(&temp_img);
   

    return 0;
}

 set of sample images on which i have tested my code.



54 comments:

  1. how to include stdafx.h file of opencv in visual c++

    ReplyDelete
    Replies
    1. http://stackoverflow.com/questions/5545641/error-c1083-cannot-open-include-file-stdafx-h-no-such-file-or-directory-in

      Delete
  2. you are my hero.^^"
    from Thailand Fanclub

    ReplyDelete
  3. Hi
    It is very nice piece of code and worked in first go itself.
    There is no option to see the output like cvShowImage or some option to save the output to disk for later viewing purpose.
    It was suitably added after
    detectFacialFeatures(img,temp_img,j);

    Thank you

    with regards,
    Ramana

    ReplyDelete
  4. very good piece of code.
    thanks
    Lalit

    ReplyDelete
  5. Fantastic code, thank you!... Just wondering if it would be possible to adapt this code to detect face, eyes, mouth and nose from camera input instead of static images? Any tips would be great.

    ReplyDelete
    Replies
    1. You can try CvCameraCapture, but doing this in real time might be harder. Haven't tested though

      Delete
  6. ya we could make use of this algorithm for face detection in real time.If you have a program which captures images from webcam , then Insert this piece of code in that.Instead of reading image from hard disc , give the captured image directly to the function doing face detection.

    ReplyDelete
  7. This comment has been removed by the author.

    ReplyDelete
  8. This comment has been removed by the author.

    ReplyDelete
  9. This comment has been removed by the author.

    ReplyDelete
  10. This comment has been removed by the author.

    ReplyDelete
  11. how to include stdafx.h file of opencv in codeblock c++

    ReplyDelete
    Replies
    1. how to open and work with classifiers.. can yu help me... plz..

      Delete
  12. error LNK2001: unresolved external symbol _cvHaarDetectObjects
    error LNK2001: unresolved external symbol _cvReleaseHaarClassifierCascade

    i am getting these two errors and i have been trying to fix it since two weeks . any one plz help me out . ??

    ReplyDelete
    Replies
    1. unresolved external symbol means you didn't include the libs which contains the above two functions. Find out the lib and include those libs in the visual studio

      Delete
  13. Aditya Kumar..
    Shift from Microsoft Visual Studio 2010 to Kubuntu ;)

    ReplyDelete
  14. Couldn't find haar cascade xml file for nose anywhere on net. For rest it is working fine. Any help?

    ReplyDelete
    Replies
    1. download the SVN repo @ http://code.opencv.org/svn/opencv/trunk to get all the cascades you want.

      Delete
  15. please can someone help me in order to complie this program

    ReplyDelete
  16. Hi, do you know how to detect mouth region with C# using haarcascade_mcs_mouth.xml. I try but i got nothing

    ReplyDelete
  17. hey.can you tell me how to solve these?
    1.error C2440: '=' : cannot convert from 'errno_t' to
    'const char *' : in FN = strcat_s(tmp,N); from cvvidsurv.hpp
    2. warning C4244: 'argument' : conversion from 'double' to 'int', possible loss of data
    thnx.

    ReplyDelete
  18. can u give me an example for realtime mouth,eye, and facial gesture ...i need for my final project T,T huhuhuhuhu,,,,,

    ReplyDelete
  19. Hi what is the use of m, M and temp_iamge. it seams those are useless here.

    ReplyDelete
  20. sorry for distrubing you, but i just want to share the article about face detection,
    let's check this link http://repository.gunadarma.ac.id/bitstream/123456789/3365/1/Automed%20Face%20Detection%20and%20Feature%20Extraction%20Using%20Color%20Feret%20Image%20Database.pdf
    i wish that article can be usefull

    ReplyDelete
  21. I am getting segmentation fault error and frontal face not detected error...can anyone help me with this

    ReplyDelete
  22. Thank you so much for your nice code :)

    ReplyDelete
  23. Hi, does your algorith detects multiple eyes when testing with more complicated images?

    I have this problem, where testing with different databases, eye detector sometimes detects 0, 1, 2, 3 or even 4.

    Im not using your code, but using the same cascade file for eye detection and same parameters.

    Thanks :)

    ReplyDelete
  24. Hi
    I am getting error "unresolved external symbol _cvHaarDetectObjects referenced in function "void __cdecl detectMouth(struct _IplImage *,struct CvRect *)" (?detectMouth@@YAXPAU_IplImage@@PAUCvRect@@@Z)"

    Also how to get all the xml file listed above.

    ReplyDelete
  25. Hi, I'm also doing face detection using OpenCV. May I know up to how many faces can we detect? Kindly email me at lavenderziyi@hotmail.com

    ReplyDelete
  26. I am getting a segmentation fault for the following code..
    void MainWindow::on_actionDetect_triggered()
    {
    int scale = 1;
    cvGrabFrame(_capture );

    _img= cvRetrieveFrame(_capture );

    // Create a new image based on the input image
    IplImage* temp = cvCreateImage( cvSize(_img->width/scale,_img->height/scale),IPL_DEPTH_8U,1 );

    // Create two points to represent the face locations
    CvPoint pt1, pt2;
    int i;

    // Clear the memory storage which was used before
    cvClearMemStorage( storage );

    // Find whether the cascade is loaded, to find the faces. If yes, then:
    if(_cascade )
    {

    // There can be more than one face in an image. So create a growable sequence of faces.
    // Detect the objects and store them in the sequence
    CvSeq* faces = cvHaarDetectObjects(temp,_cascade, storage,
    1.1, 2, CV_HAAR_DO_CANNY_PRUNING,
    cvSize(40, 40) );

    // Loop the number of faces found.
    for( i = 0; i < (faces ? faces->total : 0); i++ )
    {
    // Create a new rectangle for drawing the face
    CvRect* r = (CvRect*)cvGetSeqElem( faces, i );

    // Find the dimensions of the face,and scale it if necessary
    pt1.x = r->x*scale;
    pt2.x = (r->x+r->width)*scale;
    pt1.y = r->y*scale;
    pt2.y = (r->y+r->height)*scale;

    // Draw the rectangle in the input image
    cvRectangle(_img, pt1, pt2, CV_RGB(255,0,0), 3, 8, 0 );
    }
    }
    cvNamedWindow( "result", 1 );

    // Show the image in the window named "result"
    cvShowImage( "result",_img );

    cvWaitKey();
    // Release the temp image created.
    cvReleaseImage( &temp );
    }

    ReplyDelete
  27. i am getting memory exception error..how to handle it

    ReplyDelete
  28. which version of OpenCv did you use ? thanx

    ReplyDelete
  29. hi.
    I want to detect side face. In case of haarcascade_frontalface_alt2.xml file it only able to detect face with front view. Not good for side view face. Is there have any .xml file which is good for side face.

    ReplyDelete
  30. can any one tell about gender classification using svm
    send to sreenivassonga@gmail.com ,pnaveen299@gmail.com

    ReplyDelete
  31. Thanks for sharing a great work. Am looking at detecting the neck (center point) but am unable to. Is there any source for OpenCV neck detection. Thanks

    ReplyDelete
  32. hey i am getting error as follows:

    OpenCV Error: Unspecified error (The node does not represent a user object (unknown type?)) in cvRead, file /Users/alexandershishkov/Downloads/opencv-2.4.8/modules/core/src/persistence.cpp, line 4991

    Can any one tell me how it can be rectified..

    ReplyDelete
  33. Please guide me how to do this coding in Android. Further I would appreciate if there's any replacement of this code in java.

    ReplyDelete
  34. Please, How can I save the separate detection of face, eyes, nose and mouth ?

    Can somebody tell me how can I solve ?
    Thanks a lot.

    ReplyDelete
  35. Please send me code for iOS mohit.gupta7860@gmail.com

    ReplyDelete
  36. Wonderful article!

    Sorry to be asking it :) - Would it be possible to post this code in python as well?

    ReplyDelete
  37. This comment has been removed by the author.

    ReplyDelete
  38. Hi,
    Can I contact you in the personal message or via email etc?
    If you can do this favor to me, That will be very very great from you.

    ReplyDelete
  39. Where Can I download : haarcascade_frontalface_alt2.xml and other xml.Else impossible to use this source code.
    Thx,

    ReplyDelete
  40. can you provide this code in java

    ReplyDelete
  41. i am getting error as unable to find include file CV.h
    what should i do

    ReplyDelete
  42. Hey, thanks for the code. Question is, how do I extract the skin from the face without extracting the eyes and lips and eyebrows? Any advice?

    ReplyDelete
  43. Hi, I gotten this error. Can someone advise how to resolve this error for haarcascade_mcs_nose.xml? OpenCV(3.4.1) Error: Unknown error code -49 (Input file is empty) in cvOpenFileStorage, file C:\build\master_winpack-build-win64-vc15\opencv\modules\core\src\persistence_c.cpp, line 384

    ReplyDelete
  44. from where i can download nose xml file

    ReplyDelete
  45. planet win 365 planet win 365 카지노사이트 카지노사이트 william hill william hill 카지노사이트 카지노사이트 m88 m88 starvegad starvegad betway login betway login 메리트카지노 메리트카지노 クイーンカジノ クイーンカジノ 959

    ReplyDelete
  46. Pragmatic Play launches its first ever live casino game
    Pragmatic Play, the 남원 출장안마 leading provider of Live Casino solutions, recently launched its latest 양산 출장마사지 live 상주 출장샵 casino 안산 출장안마 game 전주 출장샵 - Big Bash. The game has been

    ReplyDelete