/facedetect.c
C | 280 lines | 152 code | 61 blank | 67 comment | 27 complexity | e7da176d7ccb8206a5c1261b5e324c98 MD5 | raw file
- // OpenCV Sample Application: facedetect.c
- // Include header files
- #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>
- // Create memory for calculations
- static CvMemStorage* storage = 0;
- // Create a new Haar classifier
- static CvHaarClassifierCascade* cascade = 0;
- // Function prototype for detecting and drawing an object from an image
- void detect_and_draw( IplImage* image );
- // Create a string that contains the cascade name
- const char* cascade_name =
- "haarcascade_frontalface_alt.xml";
- /* "haarcascade_profileface.xml";*/
- // Main function, defines the entry point for the program.
- int main( int argc, char** argv )
- {
- // Structure for getting video from camera or avi
- CvCapture* capture = 0;
- // Images to capture the frame from video or camera or from file
- IplImage *frame, *frame_copy = 0;
- // Used for calculations
- int optlen = strlen("--cascade=");
- // Input file name for avi or image file.
- const char* input_name;
- // Check for the correct usage of the command line
- if( argc > 1 && strncmp( argv[1], "--cascade=", optlen ) == 0 )
- {
- cascade_name = argv[1] + optlen;
- input_name = argc > 2 ? argv[2] : 0;
- }
- else
- {
- fprintf( stderr,
- "Usage: facedetect --cascade=\"<cascade_path>\" [filename|camera_index]\n" );
- return -1;
- /*input_name = argc > 1 ? argv[1] : 0;*/
- }
- // Load the HaarClassifierCascade
- cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
-
- // Check whether the cascade has loaded successfully. Else report and error and quit
- if( !cascade )
- {
- fprintf( stderr, "ERROR: Could not load classifier cascade\n" );
- return -1;
- }
-
- // Allocate the memory storage
- storage = cvCreateMemStorage(0);
-
- // Find whether to detect the object from file or from camera.
- if( !input_name || (isdigit(input_name[0]) && input_name[1] == '\0') )
- capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' );
- else
- capture = cvCaptureFromAVI( input_name );
- // Create a new named window with title: result
- cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH, 640 );
- cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT, 480 );
- cvNamedWindow( "result", 3 );
- // Define Resolution
- // Find if the capture is loaded successfully or not.
- // If loaded succesfully, then:
- if( capture )
- {
- // Capture from the camera.
- for(;;)
- {
- // Capture the frame and load it in IplImage
- if( !cvGrabFrame( capture ))
- break;
- frame = cvRetrieveFrame( capture );
- // If the frame does not exist, quit the loop
- if( !frame )
- break;
-
- // Allocate framecopy as the same size of the frame
- if( !frame_copy )
- frame_copy = cvCreateImage( cvSize(frame->width,frame->height),
- IPL_DEPTH_8U, frame->nChannels );
- // Check the origin of image. If top left, copy the image frame to frame_copy.
- if( frame->origin == IPL_ORIGIN_TL )
- cvCopy( frame, frame_copy, 0 );
- // Else flip and copy the image
- else
- cvFlip( frame, frame_copy, 0 );
-
- // Call the function to detect and draw the face
- detect_and_draw( frame_copy );
- // Wait for a while before proceeding to the next frame
- if( cvWaitKey( 10 ) >= 0 )
- break;
- }
- // Release the images, and capture memory
- cvReleaseImage( &frame_copy );
- cvReleaseCapture( &capture );
- }
- // If the capture is not loaded succesfully, then:
- else
- {
- // Assume the image to be lena.jpg, or the input_name specified
- const char* filename = input_name ? input_name : (char*)"lena.jpg";
- // Load the image from that filename
- IplImage* image = cvLoadImage( filename, 1 );
- // If Image is loaded succesfully, then:
- if( image )
- {
- // Detect and draw the face
- detect_and_draw( image );
- // Wait for user input
- cvWaitKey(0);
- // Release the image memory
- cvReleaseImage( &image );
- }
- else
- {
- /* assume it is a text file containing the
- list of the image filenames to be processed - one per line */
- FILE* f = fopen( filename, "rt" );
- if( f )
- {
- char buf[1000+1];
- // Get the line from the file
- while( fgets( buf, 1000, f ) )
- {
- // Remove the spaces if any, and clean up the name
- int len = (int)strlen(buf);
- while( len > 0 && isspace(buf[len-1]) )
- len--;
- buf[len] = '\0';
- // Load the image from the filename present in the buffer
- image = cvLoadImage( buf, 1 );
- // If the image was loaded succesfully, then:
- if( image )
- {
- // Detect and draw the face from the image
- detect_and_draw( image );
-
- // Wait for the user input, and release the memory
- cvWaitKey(0);
- cvReleaseImage( &image );
- }
- }
- // Close the file
- fclose(f);
- }
- }
- }
-
- // Destroy the window previously created with filename: "result"
- cvDestroyWindow("result");
- // return 0 to indicate successfull execution of the program
- return 0;
- }
- void cvOverlayImage(IplImage* src, IplImage* overlay, CvPoint location, CvScalar S, CvScalar D)
- {
- int x,y,i;
- for(x=0;x < overlay->width -10;x++)
- {
- if(x+location.x>=src->width) continue;
- for(y=0;y < overlay->height -10;y++)
- {
- if(y+location.y>=src->height) continue;
- CvScalar source = cvGet2D(src, y+location.y, x+location.x);
- CvScalar over = cvGet2D(overlay, y, x);
- CvScalar merged;
- for(i=0;i<4;i++)
- merged.val[i] = (S.val[i]*source.val[i]+D.val[i]*over.val[i]);
- cvSet2D(src, y+location.y, x+location.x, merged);
- }
- }
- }
- // Function to detect and draw any faces that is present in an image
- void detect_and_draw( IplImage* img )
- {
- IplImage *vee = 0;
- int scale = 1;
- // Create a new image based on the input image
- IplImage* temp = cvCreateImage( cvSize(img->width/scale,img->height/scale), 8, 3 );
- // Load Vee Mask
- vee = cvLoadImage( "v_mask.png", CV_LOAD_IMAGE_COLOR );
- // 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( img, 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*1.1;
- pt2.y = (r->y+r->height*0.6)*scale;
- // Draw the rectangle in the input image
- cvRectangle( img, pt1, pt2, CV_RGB(0,0,0), -3, 8, 0 );
- // cvOverlayImage(img, vee, cvPoint(pt1.x, pt1.y), cvScalar(1,1,1,1), cvScalar(1,1,1,1));
- }
- }
- // Show the image in the window named "result"
- //cvSetWindowProperty("result", CV_WINDOW_FULLSCREEN, 1);
- // cvOverlayImage(img, vee, cvPoint(10, 10), cvScalar(0.5,0.5,0.5,0.5), cvScalar(0.5,0.5,0.5,0.5));
- cvShowImage( "result", img );
- //cvShowImage( "result", vee );
- // Release the temp image created.
- cvReleaseImage( &temp );
- }