source: foam/trunk/simple-faceident/src/main.cpp @ 1

Revision 1, 9.3 KB checked in by nik, 11 years ago (diff)

reseeding

Line 
1// Copyright (C) 2009 foam
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation; either version 2 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program; if not, write to the Free Software
15// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16
17// this is a hacked version of the opencv face detection sample code
18
19#include "cv.h"
20#include "highgui.h"
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <assert.h>
26#include <math.h>
27#include <float.h>
28#include <limits.h>
29#include <time.h>
30#include <ctype.h>
31
32#include "FaceBank.h"
33#include "ImageUtils.h"
34
35using namespace std;
36
37#ifdef _EiC
38#define WIN32
39#endif
40
41static CvMemStorage* storage = 0;
42static CvHaarClassifierCascade* cascade = 0;
43static CvHaarClassifierCascade* nested_cascade = 0;
44int use_nested_cascade = 0;
45
46void detect_and_draw( IplImage* image );
47
48const char* cascade_name =
49    "/usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt.xml";
50/*    "haarcascade_profileface.xml";*/
51const char* nested_cascade_name =
52    "/usr/local/share/opencv/haarcascades/haarcascade_eye_tree_eyeglasses.xml";
53//    "../../data/haarcascades/haarcascade_eye.xml";
54double scale = 1;
55
56//////////////////////////////////////////////////////////
57// These are the tweakable bits - see comments in FaceBank.h
58
59const int nfaces = 3;
60FaceBank facebank(nfaces, 30, 40, 0.05);
61
62// number of frames to detect new faces for
63int calibrate_frames = 100;
64
65// show all faces currently detected
66//#define SHOW_FACES
67
68//#define SAVE_FRAMES
69
70// globals
71int frame=0;
72bool learn=true;
73
74//////////////////////////////////////////////////////////
75
76int main( int argc, char** argv )
77{
78    CvCapture* capture = 0;
79    IplImage *frame, *frame_copy = 0;
80    IplImage *image = 0;
81    const char* scale_opt = "--scale=";
82    int scale_opt_len = (int)strlen(scale_opt);
83    const char* cascade_opt = "--cascade=";
84    int cascade_opt_len = (int)strlen(cascade_opt);
85    const char* nested_cascade_opt = "--nested-cascade";
86    int nested_cascade_opt_len = (int)strlen(nested_cascade_opt);
87    int i;
88    const char* input_name = 0;
89
90    for( i = 1; i < argc; i++ )
91    {
92        if( strncmp( argv[i], cascade_opt, cascade_opt_len) == 0 )
93            cascade_name = argv[i] + cascade_opt_len;
94        else if( strncmp( argv[i], nested_cascade_opt, nested_cascade_opt_len ) == 0 )
95        {
96            if( argv[i][nested_cascade_opt_len] == '=' )
97                nested_cascade_name = argv[i] + nested_cascade_opt_len + 1;
98            nested_cascade = (CvHaarClassifierCascade*)cvLoad( nested_cascade_name, 0, 0, 0 );
99            if( !nested_cascade )
100                fprintf( stderr, "WARNING: Could not load classifier cascade for nested objects\n" );
101        }
102        else if( strncmp( argv[i], scale_opt, scale_opt_len ) == 0 )
103        {
104            if( !sscanf( argv[i] + scale_opt_len, "%lf", &scale ) || scale < 1 )
105                scale = 1;
106        }
107        else if( argv[i][0] == '-' )
108        {
109            fprintf( stderr, "WARNING: Unknown option %s\n", argv[i] );
110        }
111        else
112            input_name = argv[i];
113    }
114
115    cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
116
117    if( !cascade )
118    {
119        fprintf( stderr, "ERROR: Could not load classifier cascade\n" );
120        fprintf( stderr,
121        "Usage: facedetect [--cascade=\"<cascade_path>\"]\n"
122        "   [--nested-cascade[=\"nested_cascade_path\"]]\n"
123        "   [--scale[=<image scale>\n"
124        "   [filename|camera_index]\n" );
125        return -1;
126    }
127    storage = cvCreateMemStorage(0);
128   
129    if( !input_name || (isdigit(input_name[0]) && input_name[1] == '\0') )
130        capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' );
131    else if( input_name )
132    {
133        image = cvLoadImage( input_name, 1 );
134        if( !image )
135            capture = cvCaptureFromAVI( input_name );
136    }
137    else
138        image = cvLoadImage( "lena.jpg", 1 );
139
140    cvNamedWindow( "result", 1 );
141       
142        #ifdef SHOW_FACES
143        char name[256];
144        for (i=0; i<nfaces; i++)
145        {
146                sprintf(name,"face%i",i);
147        cvNamedWindow(name, 1);
148        }
149        #endif
150       
151    if( capture )
152    {
153        for(;;)
154        {
155            if( !cvGrabFrame( capture ))
156                break;
157            frame = cvRetrieveFrame( capture );
158            if( !frame )
159                break;
160            if( !frame_copy )
161                frame_copy = cvCreateImage( cvSize(frame->width,frame->height),
162                                            IPL_DEPTH_8U, frame->nChannels );
163            if( frame->origin == IPL_ORIGIN_TL )
164                cvCopy( frame, frame_copy, 0 );
165            else
166                cvFlip( frame, frame_copy, 0 );
167           
168            detect_and_draw( frame_copy );
169
170            if( cvWaitKey( 10 ) >= 0 )
171                goto _cleanup_;
172        }
173
174        cvWaitKey(0);
175_cleanup_:
176        cvReleaseImage( &frame_copy );
177        cvReleaseCapture( &capture );
178    }
179    else
180    {
181        if( image )
182        {
183            detect_and_draw( image );
184            cvWaitKey(0);
185            cvReleaseImage( &image );
186        }
187        else if( input_name )
188        {
189            // assume it is a text file containing the
190            //   list of the image filenames to be processed - one per line
191            FILE* f = fopen( input_name, "rt" );
192            if( f )
193            {
194                char buf[1000+1];
195                while( fgets( buf, 1000, f ) )
196                {
197                    int len = (int)strlen(buf), c;
198                    while( len > 0 && isspace(buf[len-1]) )
199                        len--;
200                    buf[len] = '\0';
201                    printf( "file %s\n", buf );
202                    image = cvLoadImage( buf, 1 );
203                    if( image )
204                    {
205                        detect_and_draw( image );
206                        c = cvWaitKey(0);
207                        if( c == 27 || c == 'q' || c == 'Q' )
208                            break;
209                        cvReleaseImage( &image );
210                    }
211                }
212                fclose(f);
213            }
214        }
215    }
216   
217    cvDestroyWindow("result");
218        #ifdef SHOW_FACES
219        for (i=0; i<nfaces; i++)
220        {
221                sprintf(name,"face%i",i);
222        cvDestroyWindow(name);
223        }
224        #endif
225
226    return 0;
227}
228
229
230void detect_and_draw( IplImage* img )
231{
232    static CvScalar colors[] =
233    {
234        {{0,0,255}},
235        {{0,128,255}},
236        {{0,255,255}},
237        {{0,255,0}},
238        {{255,128,0}},
239        {{255,255,0}},
240        {{255,0,0}},
241        {{255,0,255}}
242    };
243
244    IplImage *gray, *small_img;
245    int j;
246
247    gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );
248    small_img = cvCreateImage( cvSize( cvRound (img->width/scale),
249                         cvRound (img->height/scale)), 8, 1 );
250
251    cvCvtColor( img, gray, CV_BGR2GRAY );
252    cvResize( gray, small_img, CV_INTER_LINEAR );
253    cvEqualizeHist( small_img, small_img );
254    cvClearMemStorage( storage );
255
256        CvFont font;
257    cvInitFont( &font, CV_FONT_HERSHEY_PLAIN, 2, 2, 0, 1, CV_AA );
258       
259    if( cascade )
260    {
261        double t = (double)cvGetTickCount();
262        CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
263                                            1.1, 2, 0
264                                            //|CV_HAAR_FIND_BIGGEST_OBJECT
265                                            //|CV_HAAR_DO_ROUGH_SEARCH
266                                            |CV_HAAR_DO_CANNY_PRUNING
267                                            //|CV_HAAR_SCALE_IMAGE
268                                            ,
269                                            cvSize(30, 30) );
270        t = (double)cvGetTickCount() - t;
271        //printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
272               
273                if (frame==calibrate_frames)
274                {
275                        learn=false;
276                        cerr<<"finished learning new faces"<<endl;
277                }
278               
279                frame++;
280               
281        for(int i = 0; i < (faces ? faces->total : 0); i++ )
282        {
283            CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
284            CvMat small_img_roi;
285                       
286                        unsigned int ID=999;
287                        // get the face area as a sub image
288                        IplImage *face = SubImage(img, *r);
289                        // pass it into the face bank
290                        facebank.Identify(face,ID,learn);
291                        cvReleaseImage(&face);
292                       
293                        // if it's recognised the face (should really check the confidence)
294                        if (ID!=999)
295                        {
296                                char s[32];
297                                sprintf(s,"%d",ID);
298                                cvPutText(img, s, cvPoint(r->x,r->y+25), &font, CV_RGB(1,1,1));
299                        }
300
301            CvScalar color = colors[ID%8];
302                        cvRectangle(img, cvPoint(r->x,r->y), cvPoint(r->x+r->width,r->y+r->height), color);
303        }
304    }
305
306    cvShowImage( "result", img );
307
308        #ifdef SAVE_FRAMES
309        char name[256];
310        sprintf(name,"out-%0.4d.jpg",frame);
311        cvSaveImage(name,img);
312        #endif
313       
314        #ifdef SHOW_FACES
315        char name[256];
316        int i=0;
317        for(list<Face*>::iterator ii=facebank.GetFaceList().begin();
318                ii!=facebank.GetFaceList().end(); ++ii)
319        {
320                sprintf(name,"face%i",i);
321        cvShowImage(name,(*ii)->m_Image);
322                i++;
323        }
324        #endif
325   
326        cvReleaseImage( &gray );
327    cvReleaseImage( &small_img );
328}
Note: See TracBrowser for help on using the repository browser.