]> rtime.felk.cvut.cz Git - opencv.git/blob - opencv/samples/c/facedetect.c
a30e3ee23647c164adaf78a7fb8e06796afe9e3b
[opencv.git] / opencv / samples / c / facedetect.c
1 #define CV_NO_BACKWARD_COMPATIBILITY
2
3 #include "cv.h"
4 #include "highgui.h"
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <assert.h>
10 #include <math.h>
11 #include <float.h>
12 #include <limits.h>
13 #include <time.h>
14 #include <ctype.h>
15
16 #ifdef _EiC
17 #define WIN32
18 #endif
19
20 static CvMemStorage* storage = 0;
21 static CvHaarClassifierCascade* cascade = 0;
22 static CvHaarClassifierCascade* nested_cascade = 0;
23 int use_nested_cascade = 0;
24
25 void detect_and_draw( IplImage* image );
26
27 const char* cascade_name =
28     "../../data/haarcascades/haarcascade_frontalface_alt.xml";
29 /*    "haarcascade_profileface.xml";*/
30 const char* nested_cascade_name =
31     "../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";
32 //    "../../data/haarcascades/haarcascade_eye.xml";
33 double scale = 1;
34
35 int main( int argc, char** argv )
36 {
37     CvCapture* capture = 0;
38     IplImage *frame, *frame_copy = 0;
39     IplImage *image = 0;
40     const char* scale_opt = "--scale=";
41     int scale_opt_len = (int)strlen(scale_opt);
42     const char* cascade_opt = "--cascade=";
43     int cascade_opt_len = (int)strlen(cascade_opt);
44     const char* nested_cascade_opt = "--nested-cascade";
45     int nested_cascade_opt_len = (int)strlen(nested_cascade_opt);
46     int i;
47     const char* input_name = 0;
48
49     for( i = 1; i < argc; i++ )
50     {
51         if( strncmp( argv[i], cascade_opt, cascade_opt_len) == 0 )
52             cascade_name = argv[i] + cascade_opt_len;
53         else if( strncmp( argv[i], nested_cascade_opt, nested_cascade_opt_len ) == 0 )
54         {
55             if( argv[i][nested_cascade_opt_len] == '=' )
56                 nested_cascade_name = argv[i] + nested_cascade_opt_len + 1;
57             nested_cascade = (CvHaarClassifierCascade*)cvLoad( nested_cascade_name, 0, 0, 0 );
58             if( !nested_cascade )
59                 fprintf( stderr, "WARNING: Could not load classifier cascade for nested objects\n" );
60         }
61         else if( strncmp( argv[i], scale_opt, scale_opt_len ) == 0 )
62         {
63             if( !sscanf( argv[i] + scale_opt_len, "%lf", &scale ) || scale < 1 )
64                 scale = 1;
65         }
66         else if( argv[i][0] == '-' )
67         {
68             fprintf( stderr, "WARNING: Unknown option %s\n", argv[i] );
69         }
70         else
71             input_name = argv[i];
72     }
73
74     cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
75
76     if( !cascade )
77     {
78         fprintf( stderr, "ERROR: Could not load classifier cascade\n" );
79         fprintf( stderr,
80         "Usage: facedetect [--cascade=\"<cascade_path>\"]\n"
81         "   [--nested-cascade[=\"nested_cascade_path\"]]\n"
82         "   [--scale[=<image scale>\n"
83         "   [filename|camera_index]\n" );
84         return -1;
85     }
86     storage = cvCreateMemStorage(0);
87
88     if( !input_name || (isdigit(input_name[0]) && input_name[1] == '\0') )
89         capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' );
90     else if( input_name )
91     {
92         image = cvLoadImage( input_name, 1 );
93         if( !image )
94             capture = cvCaptureFromAVI( input_name );
95     }
96     else
97         image = cvLoadImage( "lena.jpg", 1 );
98
99     cvNamedWindow( "result", 1 );
100
101     if( capture )
102     {
103         for(;;)
104         {
105             frame = cvQueryFrame( capture );
106             if( !frame )
107                 break;
108             if( !frame_copy )
109                 frame_copy = cvCreateImage( cvSize(frame->width,frame->height),
110                                             IPL_DEPTH_8U, frame->nChannels );
111             if( frame->origin == IPL_ORIGIN_TL )
112                 cvCopy( frame, frame_copy, 0 );
113             else
114                 cvFlip( frame, frame_copy, 0 );
115
116             detect_and_draw( frame_copy );
117
118             if( cvWaitKey( 10 ) >= 0 )
119                 goto _cleanup_;
120         }
121
122         cvWaitKey(0);
123 _cleanup_:
124         cvReleaseImage( &frame_copy );
125         cvReleaseCapture( &capture );
126     }
127     else
128     {
129         if( image )
130         {
131             detect_and_draw( image );
132             cvWaitKey(0);
133             cvReleaseImage( &image );
134         }
135         else if( input_name )
136         {
137             /* assume it is a text file containing the
138                list of the image filenames to be processed - one per line */
139             FILE* f = fopen( input_name, "rt" );
140             if( f )
141             {
142                 char buf[1000+1];
143                 while( fgets( buf, 1000, f ) )
144                 {
145                     int len = (int)strlen(buf), c;
146                     while( len > 0 && isspace(buf[len-1]) )
147                         len--;
148                     buf[len] = '\0';
149                     printf( "file %s\n", buf );
150                     image = cvLoadImage( buf, 1 );
151                     if( image )
152                     {
153                         detect_and_draw( image );
154                         c = cvWaitKey(0);
155                         if( c == 27 || c == 'q' || c == 'Q' )
156                             break;
157                         cvReleaseImage( &image );
158                     }
159                 }
160                 fclose(f);
161             }
162         }
163     }
164
165     cvDestroyWindow("result");
166
167     if (storage)
168     {
169         cvReleaseMemStorage(&storage);
170     }
171     if (cascade)
172     {
173         cvReleaseHaarClassifierCascade(&cascade);
174     }
175
176     return 0;
177 }
178
179 void detect_and_draw( IplImage* img )
180 {
181     static CvScalar colors[] =
182     {
183         {{0,0,255}},
184         {{0,128,255}},
185         {{0,255,255}},
186         {{0,255,0}},
187         {{255,128,0}},
188         {{255,255,0}},
189         {{255,0,0}},
190         {{255,0,255}}
191     };
192
193     IplImage *gray, *small_img;
194     int i, j;
195
196     gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );
197     small_img = cvCreateImage( cvSize( cvRound (img->width/scale),
198                          cvRound (img->height/scale)), 8, 1 );
199
200     cvCvtColor( img, gray, CV_BGR2GRAY );
201     cvResize( gray, small_img, CV_INTER_LINEAR );
202     cvEqualizeHist( small_img, small_img );
203     cvClearMemStorage( storage );
204
205     if( cascade )
206     {
207         double t = (double)cvGetTickCount();
208         CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
209                                             1.1, 2, 0
210                                             //|CV_HAAR_FIND_BIGGEST_OBJECT
211                                             //|CV_HAAR_DO_ROUGH_SEARCH
212                                             |CV_HAAR_DO_CANNY_PRUNING
213                                             //|CV_HAAR_SCALE_IMAGE
214                                             ,
215                                             cvSize(30, 30) );
216         t = (double)cvGetTickCount() - t;
217         printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
218         for( i = 0; i < (faces ? faces->total : 0); i++ )
219         {
220             CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
221             CvMat small_img_roi;
222             CvSeq* nested_objects;
223             CvPoint center;
224             CvScalar color = colors[i%8];
225             int radius;
226             center.x = cvRound((r->x + r->width*0.5)*scale);
227             center.y = cvRound((r->y + r->height*0.5)*scale);
228             radius = cvRound((r->width + r->height)*0.25*scale);
229             cvCircle( img, center, radius, color, 3, 8, 0 );
230             if( !nested_cascade )
231                 continue;
232             cvGetSubRect( small_img, &small_img_roi, *r );
233             nested_objects = cvHaarDetectObjects( &small_img_roi, nested_cascade, storage,
234                                         1.1, 2, 0
235                                         //|CV_HAAR_FIND_BIGGEST_OBJECT
236                                         //|CV_HAAR_DO_ROUGH_SEARCH
237                                         //|CV_HAAR_DO_CANNY_PRUNING
238                                         //|CV_HAAR_SCALE_IMAGE
239                                         ,
240                                         cvSize(0, 0) );
241             for( j = 0; j < (nested_objects ? nested_objects->total : 0); j++ )
242             {
243                 CvRect* nr = (CvRect*)cvGetSeqElem( nested_objects, j );
244                 center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);
245                 center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);
246                 radius = cvRound((nr->width + nr->height)*0.25*scale);
247                 cvCircle( img, center, radius, color, 3, 8, 0 );
248             }
249         }
250     }
251
252     cvShowImage( "result", img );
253     cvReleaseImage( &gray );
254     cvReleaseImage( &small_img );
255 }
256