Saturday, October 22, 2011

Face Recognition using OpenCV2 and HaarCascade an Intro Part 2

After learning theory a bit in part1 now we lear how we can detect face in an image. Later we will extend this to detecting face from web cam and avi file. The code is very simple. We will load a image of a person in  IplImage structure. We also need to load haarcascader of frontal face will which enable us to detect the face in image. Opencv 2 provides many haar cascades of face, eye , nose etc which ever you want use. If you have installed openCV v2 in "C:/OpenCV2.0" ,you  find it in "C:/OpenCV2.0/data/haarcascades/ Location. Now will need to call "cvHaarDetectObjects" OpenCV Function to detect the faces.

Here is the program -

#include "cv.h"
#include "highgui.h"


#ifdef _EiC
#define WIN32

static CvMemStorage* storage_face = 0; //Memory Storage to Sore faces

static CvHaarClassifierCascade* cascade_face = 0; 

void detect_and_draw( IplImage* image );

//Haar cascade - if your openc CV is installed at location C:/OpenCV2.0/
const char* cascade_name_face ="C:/OpenCV2.0/data/haarcascades/haarcascade_frontalface_alt.xml";


int main()
 IplImage  *image =0;
 image = cvLoadImage("viv6v.jpg",1);
         printf("Error loading image\n");
         return -1;
    cascade_face = (CvHaarClassifierCascade*)cvLoad( cascade_name_face, 0, 0, 0 );
    if( !cascade_face )
        printf("ERROR: Could not load classifier of face  cascade\n" );
        return -1;

    storage_face = cvCreateMemStorage(0);
    cvNamedWindow( "result", 1 );
    // Call function to detect and Draw rectagle around face
    detect_and_draw( image);

    // Wait for key event. 
    // release resourses
    cvReleaseImage( &image );
 cvReleaseHaarClassifierCascade(&cascade_face );
 cvReleaseMemStorage( &storage_face);

    return 0;

////////////////////////////  Function To detect face //////////////////////////

void detect_and_draw( IplImage* img )

    double scale = 2;
    // create a gray image for the input image
    IplImage* gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );
    // Scale down the ie. make it small. This will increase the detection speed
    IplImage* small_img = cvCreateImage( cvSize( cvRound (img->width/scale),cvRound (img->height/scale)),8, 1 );
    int i;

    cvCvtColor( img, gray, CV_BGR2GRAY );
 cvResize( gray, small_img, CV_INTER_LINEAR );
 // Equalise contrast by eqalizing histogram of image
    cvEqualizeHist( small_img, small_img );
 cvClearMemStorage( storage_face);

    if( cascade_face )
         // Detect object defined in Haar cascade. IN our case it is face
         CvSeq* faces = cvHaarDetectObjects( small_img, cascade_face, storage_face,
                                            1.1, 2, 0/*CV_HAAR_DO_CANNY_PRUNING*/,
                                            cvSize(30, 30) );
        // Draw a rectagle around all detected face 
        for( i = 0; i < (faces ? faces->total : 0); i++ )
            CvRect r = *(CvRect*)cvGetSeqElem( faces, i );
   cvRectangle( img, cvPoint(r.x*scale,r.y*scale),cvPoint((r.x+r.width)*scale,(r.y+r.height)*scale),CV_RGB(255,0,0),3,8,0 );

    cvShowImage( "result", img );
    cvReleaseImage( &gray );
    cvReleaseImage( &small_img );


Output - Image with 1 Face -

Output - Image with multiple Faces -

Face Recognition using OpenCV2 and HaarCascade an Intro Part 1

In this series of tutorial we will learn how to detect human face. OpenCV library provides very effictive method of object detection including face detection using  Haar Cascades.
The function -
CvSeq* cvHaarDetectObjects(const CvArr* image,CvHaarClassifierCascade* cascade,CvMemStorage* storage,double scale factor=1.1,int min neighbors=3,int flags=0,CvSize min size=cvSize(0,0) );

can detect objects in input image by using HaarCascade structure. But before we jump directly to program we first need to understand about it a bit.

Many approaches have been proposed for detecting and recognizing faces. One of them is a color based approach to face detection. Indeed, color is a low-level cue that can be implemented in a computationally fast and effective way for locating objects. Among the advantages of using color is the computational efficiency and robustness against some geometric changes, when the scene is observed under a uniform illumination field.

However, the main limitation with the use of color lies in its sensitivity to illumination changes. To overcome the limitations of the color based approach, well-known face detection algorithm was proposed by Paul Viola and Michel J.Jhones in 2001 (Paul Viola and Michel J.Jhones “Rapid Object Detection Using Haar-like Features with Cascade of Boosted Classifiers”,IEEE CVPR 2001.)

 It uses Haar-like features and AdaBoost learning algorithm. The Haar-like features are extracted using the notion of integral image which allows very fast feature extraction at different scales, while AdaBoost is used to select the most prominent features among a large number of extracted features and construct a strong classifier from boosting a set of weak classifiers. The use of a cascade of classifiers made this approach one of the first real-time frontal-view face detection methods.
First, a classifier (namely a cascade of boosted classifiers working with haar-like features) is trained with a few hundreds of sample views of a particular object (i.e., a face or a car), called positive examples, that are scaled to the same size (say, 20x20), and negative examples - arbitrary images of the same size.

After a classifier is trained, it can be applied to a region of interest (of the same size as used during the training) in an input image. The classifier gives outputs as "1" if the region is likely to show the object (i.e., face/car), and "0" otherwise. To search for the object in the whole image one can move the search window across the image and check every location using the classifier. The classifier is designed so that it can be easily "resized" in order to be able to find the objects of interest at different sizes, which is more efficient than resizing the image itself. So, to find an object of an unknown size in the image the scan procedure should be done several times at different scales.

The word "cascade" in the classifier name means that the resultant classifier consists of several simpler classifiers (stages) that are applied subsequently to a region of interest until at some stage the candidate is rejected or all the stages are passed. The word "boosted" means that the classifiers at every stage of the cascade are complex themselves and they are built out of basic classifiers using one of four different boosting techniques (weighted voting). Currently Discrete Adaboost, Real Adaboost, Gentle Adaboost and Logitboost are supported. The basic classifiers are decision-tree classifiers with at least 2 leaves. Haar-like features are the input to the basic classifers, and are calculated as described below. The current algorithm uses the following Haar-like features:

In part 2 we will write a C program to detect faces in an image.

Monday, August 1, 2011

Linking OpenCV 2 library in DEVC++

In my earlier post I have discussed how to link OpenCV 1.x with devC++. But with latest release of OpenCV version ie. OpenCV 2 or higher the earlier method will not work. This because, OpenCV have changed the directory structure. So lets learn how to link OpenCV 2 or higher library version in DevC++ IDE.
  • Goto Tools -> Compiler option 
  • In the pop up click on the plus button. This means you are adding new compiler setting. Add your fav. name eg - OpenCV2
  • Now you need to add compiler commands. Add -L"C:\OpenCV2.X\lib" -lcxcore2X0 -lcv2X0 -lcvaux2X0 -lhighgui2X0 -lml2X0  where X stands for version. Eg For open CV 2.0 add --L"C:\OpenCV2.0\lib" -lcxcore200 -lcv200 -lcvaux200 -lhighgui200 -lml200 . Similarly for OpenCV2.1 add -L"C:\OpenCV2.1\lib" -lcxcore210 -lcv210 -lcvaux210 -lhighgui210 -lml210
  • Add linker command similarly as above. -lcxcore2X0 -lcv2X0 -lcvaux2X0 -lhighgui2X0 -lml2X0 For open CV 2.0 add --L"C:\OpenCV2.0\lib" -lcxcore200 -lcv200 -lcvaux200 -lhighgui200 -lml200 . Similarly for OpenCV2.1 add -L"C:\OpenCV2.1\lib" -lcxcore210 -lcv210 -lcvaux210 -lhighgui210 -lml210
  • Goto Directories -> C includes. Add  C:\OpenCV2.0\include or C:\OpenCV2.1\include or C:\OpenCV2.2\include what ever version you have. I assume that you have installed openCV in C:\
  •  Goto Directories -> Library. Add  C:\OpenCV2.0\lib or C:\OpenCV2.1\libor C:\OpenCV2.2\lib what ever version you have.
  • Goto Directories -> Library. Add  C:\OpenCV2.0\bin or C:\OpenCV2.1\bin or C:\OpenCV2.2\bin what ever version you have. 
  • Now lets write a sample project for OpenCV. Open New project window  and select "Console Application".
  • Non in Project Option > Compiler chose "OpenCV2".
Thus you have successfully integrated OpenCV with DevC++.

Monday, June 21, 2010

Open CV Tutorial - Advanced operations on images ' Filter color in Image'

In this tutorial we will learn to filter images, and separate the color. For this I am using Opencv library. In my earlier posts I have discussed how to link opencv in devC++ (here) and in Visual Studio (here). Here I suppose that you know the basic of image processing and programing using opencv.

Here I have given a very basic algo to filter color which will not work with real life images, but will give a insight how to loop through each and every pixel of a image. In this code we will loop through each pixel, find the value of each component ( RGB) and for a specific condition we will determine that pixel is of which color. Here I have Used two functions

CvScalar cvGet2D( const CvArr* arr, int idx0, int idx1 )
void cvSet2D( CvArr* arr, int idx0, int idx1, CvScalar value );
-> Note that cvSet*D function can be used safely for both single-channel and multiple-channel arrays though they are a bit slower.

/******************** CODE TO FILTER COLORS ****************/

int main()
 // Decleare image variables
    IplImage* img=0; // original image
    IplImage* white;
    IplImage* blue;     
    IplImage* green;     
    IplImage* red;     
    //load original image
    img = cvLoadImage("test.jpg",-1);
              printf(" ERORR IN LOADING IMAGE !!");
    // get height and width for image
    int height=img->height;
 int width=img->width;
    // create four images
    // Two scalar variable to store a pixle data.
    // wt -> white 
    CvScalar s,wt;
    // A very simple filter operation
    // This loops through each and every pixle of image and filter accordingly
    for(int i=0;i100 && s.val[1]>100 && s.val[2]>100) // filter white
        else if(s.val[0]>100 && s.val[1]<100 && s.val[2]<100) // filter blue
        else if(s.val[0]<100 && s.val[1]>100 && s.val[2]<100) // filter green
        else if(s.val[0]<100 && s.val[1]<100 && s.val[2]>100) // filter red

    // Create windows and show them
 cvNamedWindow("img", 1);
 cvShowImage( "img", img );

    cvNamedWindow("white", 1);
 cvShowImage( "white", white );
    cvNamedWindow("blue", 1);
 cvShowImage( "blue",blue);
 cvNamedWindow("green", 1);
 cvShowImage( "green",green);
 cvNamedWindow("red", 1);
 cvShowImage( "red",red);

 // Wait for any to be pressed      

 // Detroy all created windows

 // Release the memory occupied by images
    cvReleaseImage( &img );
 cvReleaseImage( &white);
 cvReleaseImage( &blue);
 cvReleaseImage( &green);
 cvReleaseImage( &red);

 return 0;

 test.jpg :-                                       red image:-                       blue image :-                                            
        Green Image                                                                    White Image


Sunday, June 20, 2010

Open CV Tutorial - Basic operations for images Rotate and Scale

In this tutorials of OpenCV we will do some basic but interesting operartion on images. We rotate the image and scale it down.

For this we will use a matrix and rotate it. 


#include "cv.h"
#include "highgui.h"
#include "math.h"
int main()
IplImage* src;
IplImage* dst;
int delta;
int angle;
src = cvLoadImage("apple.bmp", 1);
dst = cvCloneImage( src );
delta = 1; angle = 0;
cvNamedWindow( "src", 1 );
cvShowImage( "src", src );
float m[6];
double factor = (cos(angle*CV_PI/180.) + 1.1)*3;
CvMat M = cvMat( 2, 3, CV_32F, m );
int w = src->width;
int h = src->height;
m[0] = (float)(factor*cos(-angle*2*CV_PI/180.));
m[1] = (float)(factor*sin(-angle*2*CV_PI/180.));
m[2] = w*0.5f;
m[3] = -m[1];
m[4] = m[0];
m[5] = h*0.5f;
cvGetQuadrangleSubPix( src, dst, &M, 1, cvScalarAll(0));
cvNamedWindow( "dst", 1 ); cvShowImage( "dst", dst );
if( cvWaitKey(5) == 27 )
angle = (angle + delta) % 360;
return 0;