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

Revision 64, 10.7 KB checked in by iolanda, 12 years ago (diff)

changed a few things to work on both on windows and linux

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#include <yarp/os/all.h>
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <assert.h>
27#include <math.h>
28#include <float.h>
29#include <limits.h>
30#include <time.h>
31#include <ctype.h>
32
33//#include <unistd.h>  -iolanda commented this
34
35#include "FaceBank.h"
36#include "ImageUtils.h"
37#include "SceneState.h"
38
39using namespace std;
40using namespace yarp::os;
41
42#ifdef _EiC
43#define WIN32
44#endif
45
46#ifdef WIN32
47#include <string>
48#define snprintf _snprintf
49#else
50#include <unistd.h>
51#endif
52
53static CvMemStorage* storage = 0;
54static CvHaarClassifierCascade* cascade = 0;
55static CvHaarClassifierCascade* nested_cascade = 0;
56int use_nested_cascade = 0;
57
58void detect_and_draw( IplImage* image );
59
60const char* cascade_name = "haarcascade_frontalface_alt.xml";
61// "/usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt.xml";
62/*    "haarcascade_profileface.xml";*/
63const char* nested_cascade_name = "haarcascade_eye_tree_eyeglasses.xml";
64//"/usr/local/share/opencv/haarcascades/haarcascade_eye_tree_eyeglasses.xml";
65//    "../../data/haarcascades/haarcascade_eye.xml";
66double scale = 1;
67
68//////////////////////////////////////////////////////////
69// These are the tweakable bits - see comments in FaceBank.h
70FaceBank facebank(30, 40, 0.15);
71SceneState scenestate;
72
73// show all faces currently detected
74#define SHOW_FACES
75//#define SAVE_FRAMES
76
77// globals
78bool learn=false;
79bool idle=false;
80int facenum=0;
81int framenum=0;
82
83BufferedPort<Bottle> ctrlport;   
84
85//////////////////////////////////////////////////////////
86
87int main( int argc, char** argv )
88{
89        CvCapture* capture = 0;
90        IplImage *frame, *frame_copy = 0;
91        IplImage *image = 0;
92        const char* scale_opt = "--scale=";
93        int scale_opt_len = (int)strlen(scale_opt);
94        const char* cascade_opt = "--cascade=";
95        int cascade_opt_len = (int)strlen(cascade_opt);
96        const char* nested_cascade_opt = "--nested-cascade";
97        int nested_cascade_opt_len = (int)strlen(nested_cascade_opt);
98        int i;
99        const char* input_name = 0;
100
101        /////////////////////////
102        // yarp bit, would like to move this somewhere else
103
104        ctrlport.open("/faceident-ctrl");     
105
106        /////////////////////////
107
108        for( i = 1; i < argc; i++ )
109        {
110                if( strncmp( argv[i], cascade_opt, cascade_opt_len) == 0 )
111                        cascade_name = argv[i] + cascade_opt_len;
112                else if( strncmp( argv[i], nested_cascade_opt, nested_cascade_opt_len ) == 0 )
113                {
114                        if( argv[i][nested_cascade_opt_len] == '=' )
115                                nested_cascade_name = argv[i] + nested_cascade_opt_len + 1;
116                        nested_cascade = (CvHaarClassifierCascade*)cvLoad( nested_cascade_name, 0, 0, 0 );
117                        if( !nested_cascade )
118                                fprintf( stderr, "WARNING: Could not load classifier cascade for nested objects\n" );
119                }
120                else if( strncmp( argv[i], scale_opt, scale_opt_len ) == 0 )
121                {
122                        if( !sscanf( argv[i] + scale_opt_len, "%lf", &scale ) || scale < 1 )
123                                scale = 1;
124                }
125                else if( argv[i][0] == '-' )
126                {
127                        fprintf( stderr, "WARNING: Unknown option %s\n", argv[i] );
128                }
129                else
130                        input_name = argv[i];
131        }
132
133        cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
134
135        if( !cascade )
136        {
137                fprintf( stderr, "ERROR: Could not load classifier cascade\n" );
138                fprintf( stderr,
139                        "Usage: facedetect [--cascade=\"<cascade_path>\"]\n"
140                        "   [--nested-cascade[=\"nested_cascade_path\"]]\n"
141                        "   [--scale[=<image scale>\n"
142                        "   [filename|camera_index]\n" );
143                return -1;
144        }
145        storage = cvCreateMemStorage(0);
146
147        if( !input_name || (isdigit(input_name[0]) && input_name[1] == '\0') )
148                capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' );
149        else if( input_name )
150        {
151                image = cvLoadImage( input_name, 1 );
152                if( !image )
153                        capture = cvCaptureFromAVI( input_name );
154        }
155        else
156                image = cvLoadImage( "lena.jpg", 1 );
157
158        cvNamedWindow( "result", 1 );
159
160        if( capture )
161        {
162                for(;;)
163                {
164                        if( !cvGrabFrame( capture ))
165                                break;
166                        frame = cvRetrieveFrame( capture );
167                        if( !frame )
168                                break;
169                        if( !frame_copy )
170                                frame_copy = cvCreateImage( cvSize(frame->width,frame->height),
171                                IPL_DEPTH_8U, frame->nChannels );
172                        if( frame->origin == IPL_ORIGIN_TL )
173                                cvCopy( frame, frame_copy, 0 );
174                        else
175                                cvFlip( frame, frame_copy, 0 );
176
177                        detect_and_draw( frame_copy );
178                }
179
180_cleanup_:
181                cvReleaseImage( &frame_copy );
182                cvReleaseCapture( &capture );
183        }
184        else
185        {
186                if( image )
187                {
188                        detect_and_draw( image );
189                        cvReleaseImage( &image );
190                }
191                else if( input_name )
192                {
193                        // assume it is a text file containing the
194                        //   list of the image filenames to be processed - one per line
195                        FILE* f = fopen( input_name, "rt" );
196                        if( f )
197                        {
198                                char buf[1000+1];
199                                while( fgets( buf, 1000, f ) )
200                                {
201                                        int len = (int)strlen(buf), c;
202                                        while( len > 0 && isspace(buf[len-1]) )
203                                                len--;
204                                        buf[len] = '\0';
205                                        printf( "file %s\n", buf );
206                                        image = cvLoadImage( buf, 1 );
207                                        if( image )
208                                        {
209                                                detect_and_draw( image );                       
210                                                cvReleaseImage( &image );
211                                        }
212                                }
213                                fclose(f);
214                        }
215                }
216        }
217
218        cvDestroyWindow("result");
219        return 0;
220}
221
222void detect_and_draw( IplImage* img )
223{
224        static CvScalar colors[] =
225        {
226                {{0,0,255}},
227                {{0,128,255}},
228                {{0,255,255}},
229                {{0,255,0}},
230                {{255,128,0}},
231                {{255,255,0}},
232                {{255,0,0}},
233                {{255,0,255}}
234        };
235
236        IplImage *small_img;
237        int j;
238
239        small_img = cvCreateImage( cvSize( cvRound (img->width/scale),
240                cvRound (img->height/scale)), 8, 3 );
241        CvSize imgsize = cvGetSize(small_img);
242        cvResize( img, small_img, CV_INTER_LINEAR );
243        cvClearMemStorage( storage );
244
245        CvFont font;
246        cvInitFont( &font, CV_FONT_HERSHEY_PLAIN, 2, 2, 0, 1, CV_AA );
247
248        CvFont infofont;
249        cvInitFont( &infofont, CV_FONT_HERSHEY_PLAIN, 1, 1, 0, 1, CV_AA );
250
251        CvFont helpfont;
252        cvInitFont( &helpfont, CV_FONT_HERSHEY_PLAIN, 0.5, 0.5, 0, 1, CV_AA );
253
254        if( cascade )
255        {
256                double t = (double)cvGetTickCount();
257                CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
258                        1.1, 2, 0
259                        //|CV_HAAR_FIND_BIGGEST_OBJECT
260                        //|CV_HAAR_DO_ROUGH_SEARCH
261                        //|CV_HAAR_DO_CANNY_PRUNING
262                        //|CV_HAAR_SCALE_IMAGE
263                        ,
264                        cvSize(30, 30) );
265                t = (double)cvGetTickCount() - t;
266                //printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
267
268                /*framenum++;
269                if (framenum==100)
270                {
271                cerr<<"next face"<<endl;
272                facenum++;
273                }
274
275                if (framenum==220)
276                {
277                cerr<<"stopped learning"<<endl;
278                cerr<<facebank.GetFaceMap().size()<<" faces recorded"<<endl;
279                learn=false; 
280                }*/
281
282                ///////////////////////////////////
283                // dispatch from input
284
285                int key=cvWaitKey(10);
286
287                switch (key)
288                {
289                case 'd': learn=false; break;
290                case '1': facenum=1; learn=true; break;
291                case '2': facenum=2; learn=true; break;
292                case '3': facenum=3; learn=true; break;
293                case '4': facenum=4; learn=true; break;
294                case '5': facenum=5; learn=true; break;
295                case '6': facenum=6; learn=true; break;
296                case '7': facenum=7; learn=true; break;
297                case '8': facenum=8; learn=true; break;
298                case '9': facenum=9; learn=true; break;
299                case '0': facenum=0; learn=true; break;
300                case 'c': facebank.Clear(); break;
301                }
302
303                ///////////////////////////////////
304                // read from yarp
305
306                Bottle *b=ctrlport.read(false);
307                if (b!=NULL)
308                {
309                        if (b->get(0).asString()=="train")
310                        {
311                                facenum=b->get(1).asInt();
312                                learn=true;
313                                idle=false;
314                        }
315                        if (b->get(0).asString()=="idle")
316                        {
317                                facenum=b->get(1).asInt();
318                                idle=true;
319                        }
320                        else if (b->get(0).asString()=="clear")
321                        {
322                                facebank.Clear();
323                        }
324                        else if (b->get(0).asString()=="detect")
325                        {
326                                learn=false;
327                                idle=false;
328                        }
329                        else if (b->get(0).asString()=="load")
330                        {
331                                facebank.Load(b->get(1).asString().c_str());
332                        }
333                        else if (b->get(0).asString()=="save")
334                        {
335                                facebank.Save(b->get(1).asString().c_str());
336                        }
337                }
338
339                ///////////////////////////////////
340
341                if (!idle)
342                {
343                        for(int i = 0; i < (faces ? faces->total : 0); i++ )
344                        {
345                                CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
346                                CvMat small_img_roi;
347
348                                unsigned int ID=999;
349                                float confidence=0;
350                                // get the face area as a sub image
351                                IplImage *face = SubImage(small_img, *r);
352                                // pass it into the face bank
353                                if (learn)
354                                {
355                                        confidence=facebank.Suggest(face,facenum);
356                                        ID=facenum;
357                                }
358                                else
359                                {       
360                                        confidence=facebank.Identify(face,ID);
361                                }
362
363                                cvReleaseImage(&face);
364                                CvScalar color = colors[ID%8];
365
366                                // if it's recognised the face (should really check the confidence)
367                                if (ID!=999)
368                                {
369                                        char s[32];
370                                        sprintf(s,"%d %0.2f",ID,confidence);
371                                        cvPutText(small_img, s, cvPoint(r->x,r->y+25), &font, color);
372                                        int x=(facebank.GetFaceWidth()+1)*ID;
373                                        int y=imgsize.height-facebank.GetFaceHeight();
374                                        cvLine(small_img, cvPoint(r->x+r->width/2,r->y+r->height/2),
375                                                cvPoint(x+facebank.GetFaceWidth()/2,y), color);                 
376
377                                        if (!learn)
378                                        {
379                                                scenestate.AddPresent(ID, SceneState::User(confidence));
380                                        }
381                                }
382
383                                cvRectangle(small_img, cvPoint(r->x,r->y), cvPoint(r->x+r->width,r->y+r->height), color);
384                        }
385                }
386                else
387                {
388                        // idling, so free up some cpu
389                #ifdef WIN32
390                        Sleep(2000);
391                #else
392                        usleep(200000);
393                #endif
394                }
395        }
396
397        scenestate.Update();
398
399        char info[256];
400        if (learn)
401        {
402                snprintf(info,256,"learning user %d",facenum);
403        }
404        else
405        {
406                snprintf(info,256,"detecting faces");
407        }
408        cvPutText(small_img, info, cvPoint(20,30), &infofont, CV_RGB(0,0,0));
409
410        snprintf(info,256,"keys:");
411        cvPutText(small_img, info, cvPoint(20,50), &helpfont, CV_RGB(0,0,0));
412        snprintf(info,256,"number key 0-9 : learn face");
413        cvPutText(small_img, info, cvPoint(20,60), &helpfont, CV_RGB(0,0,0));
414        snprintf(info,256,"'d' : face detect mode");
415        cvPutText(small_img, info, cvPoint(20,70), &helpfont, CV_RGB(0,0,0));
416        snprintf(info,256,"'c' : clear all faces");
417        cvPutText(small_img, info, cvPoint(20,80), &helpfont, CV_RGB(0,0,0));
418
419#ifdef SHOW_FACES
420        for(map<unsigned int,Face*>::iterator ii=facebank.GetFaceMap().begin();
421                ii!=facebank.GetFaceMap().end(); ++ii)
422        {
423                int x=(facebank.GetFaceWidth()+1)*ii->first;
424                int y=imgsize.height-facebank.GetFaceHeight();
425                BlitImage(ii->second->m_Image,small_img,cvPoint(x,y));
426        }
427#endif
428
429        cvShowImage( "result", small_img );
430
431#ifdef SAVE_FRAMES
432        char name[256];
433        sprintf(name,"out-%0.4d.jpg",framenum);
434        cvSaveImage(name,small_img);
435#endif
436
437        cvReleaseImage( &small_img );
438}
Note: See TracBrowser for help on using the repository browser.