#include "cv.h"
#include "highgui.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "assert.h"
#include "math.h"
#include "float.h"
#include "limits.h"
#include "time.h"
#include "ctype.h"
#ifdef _EiC
#define WIN32
#endif
/*There are three parts in which first of all the program is divided ..
In the first part the program checks whether the Camera is connected and is it able to return frames to the program
If yes it detects the face from the camera/video file (or it also loads from a video file if you have specified) ...
If no
Then it checks for Lena.jpg if found it detects the face in the same....
If no
It checks for a file a text file where it can find the file names of each and every picture in which
The faces are to be detected..The text file should have the names of the pictures along with the extensions */
/*about CvMemStorage==>
typedef struct CvMemStorage
{
struct CvMemBlock* bottom;/* first allocated block */
/* struct CvMemBlock* top; /* the current memory block - top of the stack */
/* struct CvMemStorage* parent; /* borrows new blocks from */
/*int block_size; /* block size */
/*int free_space; /* free space in the top block (in bytes) */
/*} CvMemStorage;*/
/*CvMemStorage is a dynamic data structure used to store dynamically growing
data structures such as sequences contours Graphs..*/
static CvMemStorage* storage = 0;
static CvHaarClassifierCascade* cascade = 0;
/*This is the function which is going detect and draw the circle round the face..
For the Moment lets forget about the function*/
void detect_and_draw( IplImage* image );
/*WE assign the .xml file name which is the main basic thing which allows us to detect objects
and depending upon this file the object is realized..As I Said lets speak about xml file in some other post*/
const char* cascade_name =
"haarcascade_frontalface_alt.xml";
/* "haarcascade_profileface.xml";*/
/*This .xml file is available by default in the \root..\openCV\data folder and you may verify the same..*/
int main( int argc, char** argv )
{
CvCapture* capture = 0;
IplImage *frame, *frame_copy = 0;/*Another frame for Operations..frame_copy*/
int optlen = strlen("--cascade=");/*You will understamd this line afterwards*/
const char* input_name;
/*If you want to understand the below line then you have to first study about
the arguments the main function has..*/
/*Explanation of strncmp
int strncmp ( const char * str1, const char * str2, size_t num );
str1
C string to be compared.
str2
C string to be compared.
num
Maximim number of characters to compare.
See this link for more information
http://www.cplusplus.com/reference/clibrary/cstring/strncmp.html*/
if( argc > 1 && strncmp( argv[1], "--cascade=", optlen ) == 0 )
/*This line means that we compare the argument we got from the command line to that of the "--cascade"*/
/*We are comparing argc until the lenght optlen*/
{
/*If cascade name given in the command line then use it else go to the default..you can give the path to
the cascade to cascade name as given in the above line...*/
cascade_name = argv[1] + optlen;
input_name = argc > 2 ? argv[2] : 0;
/*If you know about arguments the main has and how they work then you should
be able to get this line by now..*/
}
else
{/*If you are running the program elsewhere other than the folder in which the program facedetect.c is
present by default then put the full path to the .xml file in the inverted commmas"
and replace "forward slash by a backslash" in the below line*/
/* try to comment this below line and then please use the command line for this program because the program does not
terminate after the execution and follow the same trick for many things*/
cascade_name = "C:/Program Files/OpenCV/data/haarcascades/haarcascade_frontalface_alt2.xml";
input_name = argc > 1 ? argv[1] : 0;/*Use of this line comes down..
If input name not given in the command line then load Zero
Ponder about this above line for sometime
Give some time to this program,..Once again if you have read about arguments the main function has then
you should be able to get this line*/
}
/*Here the use of cascade_name comes in..The previous lines involving the cascade_name were just
to ensure that a valid cascade name is passed to the function..other wise the program will give bad results*/
cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );/*Type conversion*/
/*Please see Cvload in documentation there is no space for text in this blog*/
/*If unable to load cascade then print the errors and quit */
if( !cascade )/*This loop is easy*/
{
fprintf( stderr, "ERROR: Could not load classifier cascade\n" );
fprintf( stderr,
"Usage: facedetect --cascade=\"\" [filename|camera_index]\n" );
return -1;
}
/*Else proceed here*/
storage = cvCreateMemStorage(0);
if( !input_name || (isdigit(input_name[0]) && input_name[1] == '\0') )
/*If input name is zero then capture from cam else it must be a
video file and load it with the help of capture from cam*/
capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' );
else
capture = cvCaptureFromAVI( input_name );
cvNamedWindow( "result", 1 );
/*The part where the capture from the camera starts */
if( capture )
{
for(;;)/*Infinite loop until we hit the escape buttom*/
{
if( !cvGrabFrame( capture ))/*If no frame break off just from this loop*/
break;
frame = cvRetrieveFrame( capture );/*If no frame break off just from this loop*/
if( !frame )
break;
if( !frame_copy )/*here frame copy =0 ==> !0=1 and hence it enters the loop*/
frame_copy = cvCreateImage( cvSize(frame->width,frame->height),
IPL_DEPTH_8U, frame->nChannels );
/*Copy the frame*/
if( frame->origin == IPL_ORIGIN_TL )/*if the origin is top left then procees else
flip the frame and then copy by using cvFlip*/
cvCopy( frame, frame_copy, 0 );
else
cvFlip( frame, frame_copy, 0 );
detect_and_draw( frame_copy );/*Send this frame to the function which wil detect
and dram the circle*/
if( cvWaitKey( 10 ) >= 0 )/*If you hit the escape key you will exit*/
break;
}
cvReleaseImage( &frame_copy );
cvReleaseCapture( &capture );
}
/*This part loads the image from the command line if image not found in the command line it loads the lena.jpg ..*/
else
{
const char* filename = input_name ? input_name : (char*)"lena.jpg";
IplImage* image = cvLoadImage( filename, 1 );
if( image )/*If image =0 then does not enter else enters and gives the frames for processing*/
{
detect_and_draw( image );
cvWaitKey(0);
cvReleaseImage( &image );
}
else
{
/* assume it is a text file containing the
list of the image filenames to be processed - one per line */
/* You may commment this part of the code as it is not always required
right from the opening brace of else to its closing brace*/
FILE* f = fopen( filename, "rt" );
if( f )/*i f!=0 enters the loop*/
{
char buf[1000+1];/*This part is really easy try to figure it out */
while( fgets( buf, 1000, f ))
{
/*This part consists of loading of the images by just loading the filename from the
textfile and one name per line
It requires the knowledge of C++ rather than OpenCV*/
int len = (int)strlen(buf);
while( len > 0 && isspace(buf[len-1]) )
len--;
buf[len] = '\0';
image = cvLoadImage( buf, 1 );/*Loads the image sends it as the argument */
if( image )
{
detect_and_draw( image );
cvWaitKey(0);
cvReleaseImage( &image );
}
}
fclose(f);/*Closing the file pointer*/
}
}
}
cvDestroyWindow("result");
return 0;
}
void detect_and_draw( IplImage* img )
{
static CvScalar colors[] =
{/*For the moment forget about this array*/
{{0,0,255}},
{{0,128,255}},
{{0,255,255}},
{{0,255,0}},
{{255,128,0}},
{{255,255,0}},
{{255,0,0}},
{{255,0,255}}
};
double scale = 0.6;/*Change this value and you can chang the color of the circle which detects the face*/
IplImage* gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );/*Gray is the same as the image
(Actually pointer to the image) which is sent from program main whenever this funciton is called.*/
IplImage* small_img = cvCreateImage( cvSize( cvRound (img->width/scale),
cvRound (img->height/scale)),
8, 1 );
/* here cvRound is just rounding off the double to an integer so that we have a perfect integer values
with good accuracy*/
int i;
cvCvtColor( img, gray, CV_BGR2GRAY );
/*The image is converted to GRAY because Haar training works only on grayscale or binary images*/
cvResize( gray, small_img, CV_INTER_LINEAR );
cvEqualizeHist( small_img, small_img );/*I feel we equlize because we want to get good results*/
cvClearMemStorage( storage );
if( cascade )
{
/*here lets leave about cvgetickcount and some other arithmetic calculations invoving time*/
double t = (double)cvGetTickCount();
CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
1.1, 2, 0/*CV_HAAR_DO_CANNY_PRUNING*/,
cvSize(30, 30) );/*CV_HAAR_DO_CANNY_PRUNING is the only
method supported right now*/
/*This one line detects objects*/
t = (double)cvGetTickCount() - t;/*Let us just leave about detection time for the moment*/
/*Lets concentrate on detection first.*/
printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
for( i = 0; i < (faces ? faces->total : 0); i++ )/*This condition in the condition field of the for loop is
once again for safety
/* If faces=0 then zero is assigned and if not the "total "is assigned to compare with 'i' .See the
cvseqstructure in the documentation for more details..*/
/*total is a member of cvseq- ITs the total number of elements"*/
{
CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
CvPoint center;
/*CvPoint is a structure which has just two members they store x coordinate and the y coordinate*/
int radius;
center.x = cvRound((r->x + r->width*0.5)*scale);/*CvRound explained above.
This line has more of Arithmetic and the following lines...
You can also try and change the numerical values to see the change*/
center.y = cvRound((r->y + r->height*0.5)*scale);
radius = cvRound((r->width + r->height)*0.25*scale);
cvCircle( img, center, radius, colors[i%8], 3, 8, 0 );
/*Think over the 'colors[i%8]' remember % means Remainder*/
/*Explanation of cvCircle
void cvCircle( CvArr* img, CvPoint center, int radius, CvScalar color,
int thickness=1, int line_type=8, int shift=0 );
*/
}
}
cvShowImage( "result", img );
cvReleaseImage( &gray );
cvReleaseImage( &small_img );
}
//End
http://myopencv.blogspot.com/2008/05/facedetectc.html