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

Revision 30, 11.1 KB checked in by dave, 11 years ago (diff)

turned multiple face detect back on

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#include <yarp/os/all.h>
32
33#include "FaceBank.h"
34#include "ImageUtils.h"
35
36using namespace std;
37using namespace yarp::os;
38
39#ifdef _EiC
40#define WIN32
41#endif
42
43static CvMemStorage* storage = 0;
44static CvHaarClassifierCascade* cascade = 0;
45static CvHaarClassifierCascade* nested_cascade = 0;
46int use_nested_cascade = 0;
47
48void detect_and_draw( IplImage* image );
49
50const char* cascade_name =
51    "/usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt.xml";
52/*    "haarcascade_profileface.xml";*/
53const char* nested_cascade_name =
54    "/usr/local/share/opencv/haarcascades/haarcascade_eye_tree_eyeglasses.xml";
55//    "../../data/haarcascades/haarcascade_eye.xml";
56double scale = 1;
57
58//////////////////////////////////////////////////////////
59// These are the tweakable bits - see comments in FaceBank.h
60FaceBank facebank(30, 40, 0.15);
61
62// show all faces currently detected
63#define SHOW_FACES
64//#define SAVE_FRAMES
65
66// globals
67bool learn=true;
68int facenum=0;
69int framenum=0;
70
71Network YarpNetwork;
72Port YarpPort;
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        /////////////////////////////////
116        // yarp init
117        cerr<<"connecting to yarp..."<<endl;
118        YarpPort.open("/faceident");
119       
120        /////////////////////////////////
121
122    cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
123
124    if( !cascade )
125    {
126        fprintf( stderr, "ERROR: Could not load classifier cascade\n" );
127        fprintf( stderr,
128        "Usage: facedetect [--cascade=\"<cascade_path>\"]\n"
129        "   [--nested-cascade[=\"nested_cascade_path\"]]\n"
130        "   [--scale[=<image scale>\n"
131        "   [filename|camera_index]\n" );
132        return -1;
133    }
134    storage = cvCreateMemStorage(0);
135   
136    if( !input_name || (isdigit(input_name[0]) && input_name[1] == '\0') )
137        capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] - '0' );
138    else if( input_name )
139    {
140        image = cvLoadImage( input_name, 1 );
141        if( !image )
142            capture = cvCaptureFromAVI( input_name );
143    }
144    else
145        image = cvLoadImage( "lena.jpg", 1 );
146
147    cvNamedWindow( "result", 1 );
148       
149    if( capture )
150    {
151        for(;;)
152        {
153            if( !cvGrabFrame( capture ))
154                break;
155            frame = cvRetrieveFrame( capture );
156            if( !frame )
157                break;
158            if( !frame_copy )
159                frame_copy = cvCreateImage( cvSize(frame->width,frame->height),
160                                            IPL_DEPTH_8U, frame->nChannels );
161            if( frame->origin == IPL_ORIGIN_TL )
162                                //cvResize(frame, frame_copy, CV_INTER_LINEAR );
163                cvCopy( frame, frame_copy, 0 );
164            else
165                cvFlip( frame, frame_copy, 0 );
166           
167            detect_and_draw( frame_copy );
168        }
169
170_cleanup_:
171        cvReleaseImage( &frame_copy );
172        cvReleaseCapture( &capture );
173    }
174    else
175    {
176        if( image )
177        {
178            detect_and_draw( image );
179            cvReleaseImage( &image );
180        }
181        else if( input_name )
182        {
183            // assume it is a text file containing the
184            //   list of the image filenames to be processed - one per line
185            FILE* f = fopen( input_name, "rt" );
186            if( f )
187            {
188                char buf[1000+1];
189                while( fgets( buf, 1000, f ) )
190                {
191                    int len = (int)strlen(buf), c;
192                    while( len > 0 && isspace(buf[len-1]) )
193                        len--;
194                    buf[len] = '\0';
195                    printf( "file %s\n", buf );
196                    image = cvLoadImage( buf, 1 );
197                    if( image )
198                    {
199                        detect_and_draw( image );                       
200                        cvReleaseImage( &image );
201                    }
202                }
203                fclose(f);
204            }
205        }
206    }
207   
208    cvDestroyWindow("result");
209    return 0;
210}
211
212void detect_and_draw( IplImage* img )
213{
214    static CvScalar colors[] =
215    {
216        {{0,0,255}},
217        {{0,128,255}},
218        {{0,255,255}},
219        {{0,255,0}},
220        {{255,128,0}},
221        {{255,255,0}},
222        {{255,0,0}},
223        {{255,0,255}}
224    };
225
226    IplImage *gray, *small_img;
227    int j;
228        CvSize imgsize = cvGetSize(img);
229
230    gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );
231    small_img = cvCreateImage( cvSize( cvRound (img->width/scale),
232                         cvRound (img->height/scale)), 8, 1 );
233
234    cvCvtColor( img, gray, CV_BGR2GRAY );
235    cvResize( gray, small_img, CV_INTER_LINEAR );
236    cvEqualizeHist( small_img, small_img );
237    cvClearMemStorage( storage );
238
239        CvFont font;
240    cvInitFont( &font, CV_FONT_HERSHEY_PLAIN, 2, 2, 0, 1, CV_AA );
241
242        CvFont infofont;
243    cvInitFont( &infofont, CV_FONT_HERSHEY_PLAIN, 1, 1, 0, 1, CV_AA );
244
245        CvFont helpfont;
246    cvInitFont( &helpfont, CV_FONT_HERSHEY_PLAIN, 0.5, 0.5, 0, 1, CV_AA );
247       
248    if( cascade )
249    {
250        double t = (double)cvGetTickCount();
251        CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
252                                            1.1, 2, 0
253                                            //|CV_HAAR_FIND_BIGGEST_OBJECT
254                                            //|CV_HAAR_DO_ROUGH_SEARCH
255                                            //|CV_HAAR_DO_CANNY_PRUNING
256                                            //|CV_HAAR_SCALE_IMAGE
257                                            ,
258                                            cvSize(30, 30) );
259        t = (double)cvGetTickCount() - t;
260        //printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
261               
262                /*framenum++;
263                if (framenum==100)
264                {
265                        cerr<<"next face"<<endl;
266                        facenum++;
267                }
268               
269                if (framenum==220)
270                {
271                        cerr<<"stopped learning"<<endl;
272                        cerr<<facebank.GetFaceMap().size()<<" faces recorded"<<endl;
273                        learn=false; 
274                }*/
275               
276               
277                int key=cvWaitKey(10);
278               
279                switch (key)
280                {
281                        case 'd': learn=false; break;
282                        case '1': facenum=1; learn=true; break;
283                        case '2': facenum=2; learn=true; break;
284                        case '3': facenum=3; learn=true; break;
285                        case '4': facenum=4; learn=true; break;
286                        case '5': facenum=5; learn=true; break;
287                        case '6': facenum=6; learn=true; break;
288                        case '7': facenum=7; learn=true; break;
289                        case '8': facenum=8; learn=true; break;
290                        case '9': facenum=9; learn=true; break;
291                        case '0': facenum=0; learn=true; break;
292                        case 'c': facebank.Clear(); break;
293                }
294               
295                               
296        for(int i = 0; i < (faces ? faces->total : 0); i++ )
297        {
298            CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
299            CvMat small_img_roi;
300                       
301                        unsigned int ID=999;
302                        float confidence=0;
303                        // get the face area as a sub image
304                        IplImage *face = SubImage(img, *r);
305                        // pass it into the face bank
306                        if (learn)
307                        {
308                                confidence=facebank.Suggest(face,facenum);
309                                ID=facenum;
310                        }
311                        else
312                        {       
313                                confidence=facebank.Identify(face,ID);
314                        }
315                       
316                        cvReleaseImage(&face);
317                        CvScalar color = colors[ID%8];
318
319                        // if it's recognised the face (should really check the confidence)
320                        if (ID!=999)
321                        {
322                                char s[32];
323                                sprintf(s,"%d %0.2f",ID,confidence);
324                                cvPutText(img, s, cvPoint(r->x,r->y+25), &font, color);
325                                int x=(facebank.GetFaceWidth()+1)*ID;
326                                int y=imgsize.height-facebank.GetFaceHeight();
327                                cvLine(img, cvPoint(r->x+r->width/2,r->y+r->height/2),
328                                        cvPoint(x+facebank.GetFaceWidth()/2,y), color);
329                                /////////////////////
330                                // YARP send
331                               
332                                if (!learn)
333                                {
334                                        Bottle b; 
335                                        b.clear();
336                                        b.add((int)ID);
337                                        b.add(confidence);
338                                        YarpPort.write(b);
339                                }
340
341                                ////////////////////
342
343                        }
344
345                        cvRectangle(img, cvPoint(r->x,r->y), cvPoint(r->x+r->width,r->y+r->height), color);
346        }
347    }
348
349        char info[256];
350        if (learn)
351        {
352                snprintf(info,256,"learning user %d",facenum);
353        }
354        else
355        {
356                snprintf(info,256,"detecting faces");
357        }
358        cvPutText(img, info, cvPoint(20,30), &infofont, CV_RGB(0,0,0));
359
360        snprintf(info,256,"keys:");
361        cvPutText(img, info, cvPoint(20,50), &helpfont, CV_RGB(0,0,0));
362        snprintf(info,256,"number key 0-9 : learn face");
363        cvPutText(img, info, cvPoint(20,60), &helpfont, CV_RGB(0,0,0));
364        snprintf(info,256,"'d' : face detect mode");
365        cvPutText(img, info, cvPoint(20,70), &helpfont, CV_RGB(0,0,0));
366        snprintf(info,256,"'c' : clear all faces");
367        cvPutText(img, info, cvPoint(20,80), &helpfont, CV_RGB(0,0,0));
368
369        #ifdef SHOW_FACES
370        for(map<unsigned int,Face*>::iterator ii=facebank.GetFaceMap().begin();
371                ii!=facebank.GetFaceMap().end(); ++ii)
372        {
373                int x=(facebank.GetFaceWidth()+1)*ii->first;
374                int y=imgsize.height-facebank.GetFaceHeight();
375                BlitImage(ii->second->m_Image,img,cvPoint(x,y));
376        }
377        #endif
378       
379    cvShowImage( "result", img );
380
381        #ifdef SAVE_FRAMES
382        char name[256];
383        sprintf(name,"out-%0.4d.jpg",framenum);
384        cvSaveImage(name,img);
385        #endif
386   
387        cvReleaseImage( &gray );
388    cvReleaseImage( &small_img );
389}
Note: See TracBrowser for help on using the repository browser.