source: level2/competencies/FaceClassifier/src/App.cpp @ 1706

Revision 234, 7.3 KB checked in by dave, 10 years ago (diff)

updated docs with yarp interface

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#include <assert.h>
18#include "App.h"
19#include "PCAClassifier.h"
20#include "FileTools.h"
21
22//#define SAVE_FRAMES
23
24using namespace std;
25
26//int w=50;
27//int h=80;
28
29int w=20;
30int h=30;
31
32App::App(const string &filename) :
33m_Capture(NULL),
34m_Classifier(NULL),
35m_FaceBank(NULL),
36m_FaceNum(1),
37m_Learn(true),
38m_Idle(false),
39frame(NULL),
40frame_copy(NULL),
41m_FrameNum(0)
42{
43        m_CtrlPort.open("/faceclassifier-ctrl");
44       
45        if (filename=="")
46        {
47                m_Capture = cvCaptureFromCAM(0);
48        }
49        else
50        {
51                m_Capture = cvCaptureFromAVI(filename.c_str());
52        }
53       
54        assert(m_Capture);
55       
56        PCA pca(w*h);
57        //FILE *f=fopen("../no-redist/eigenspaces/spacek-50x80.pca", "rb");
58        FILE *f=fopen("../../../libs/magicsquares/data/eigenspaces/spacek-20x30.pca", "rb");
59        pca.Load(f);
60        fclose(f);
61        pca.Compress(10,500);
62       
63        m_Classifier = new PCAClassifier(pca);
64        m_FaceBank = new FaceBank(w,h,0.4,0.1,m_Classifier);
65        cvInitFont( &m_Font, CV_FONT_HERSHEY_PLAIN, 0.5, 0.5, 0, 1, CV_AA );
66        cvInitFont( &m_LargeFont, CV_FONT_HERSHEY_PLAIN, 25, 25, 0, 10, CV_AA );
67   
68        cvNamedWindow( "face classifier", 1 );
69       
70        //Benchmark("yale");
71}
72
73App::~App()
74{
75}
76
77static CvScalar colors[] =
78    {
79        {{0,0,255}},
80        {{0,128,255}},
81        {{0,255,255}},
82        {{0,255,0}},
83        {{255,128,0}},
84        {{255,255,0}},
85        {{255,0,0}},
86        {{255,0,255}},
87    };
88
89void App::Run()
90{
91        frame = cvQueryFrame( m_Capture );
92    if( !frame )
93        {
94                cerr<<"no frame captured"<<endl;
95                return;
96        }
97       
98        if( !frame_copy )
99        frame_copy = cvCreateImage( cvSize(frame->width,frame->height),
100                                    IPL_DEPTH_8U, frame->nChannels );
101    if( frame->origin == IPL_ORIGIN_TL )
102        cvCopy( frame, frame_copy, 0 );
103    else
104        cvFlip( frame, frame_copy, 0 );
105       
106        Image camera(frame_copy);
107        Update(camera);
108       
109        m_FrameNum++;
110#ifdef SAVE_FRAMES
111        char name[256];
112        sprintf(name,"out-%0.4d.jpg",m_FrameNum);
113        cerr<<"saving "<<name<<endl;
114        cvSaveImage(name,camera.m_Image);
115#endif
116
117        cvShowImage("face classifier", camera.m_Image);
118}
119
120void App::Update(Image &camera)
121{       
122        ///////////////////////////////////
123        // dispatch from input
124
125        int key=cvWaitKey(10);
126               
127        switch (key)
128        {
129                case 'd': m_Learn=false; break;
130                case '1': m_FaceNum=1; m_Learn=true; break;
131                case '2': m_FaceNum=2; m_Learn=true; break;
132                case '3': m_FaceNum=3; m_Learn=true; break;
133                case '4': m_FaceNum=4; m_Learn=true; break;
134                case '5': m_FaceNum=5; m_Learn=true; break;
135                case '6': m_FaceNum=6; m_Learn=true; break;
136                case '7': m_FaceNum=7; m_Learn=true; break;
137                case '8': m_FaceNum=8; m_Learn=true; break;
138                case '9': m_FaceNum=9; m_Learn=true; break;
139                case '0': m_FaceNum=0; m_Learn=true; break;
140                case 'c': m_FaceBank->Clear(); break;
141        }
142               
143
144        ///////////////////////////////////
145        // read from yarp
146
147        Bottle *b=m_CtrlPort.read(false);
148        if (b!=NULL)
149        {
150                if (b->get(0).asString()=="train")
151                {
152                        m_FaceNum=b->get(1).asInt();
153                        m_Learn=true;
154                        m_Idle=false;
155                }
156                if (b->get(0).asString()=="idle")
157                {
158                        m_FaceNum=b->get(1).asInt();
159                        m_Idle=true;
160                }
161                else if (b->get(0).asString()=="clear")
162                {
163                        m_FaceBank->Clear();
164                }
165                else if (b->get(0).asString()=="detect")
166                {
167                        m_Learn=false;
168                        m_Idle=false;
169                }
170                else if (b->get(0).asString()=="load")
171                {
172                        m_FaceBank->Load(b->get(1).asString().c_str());
173                }
174                else if (b->get(0).asString()=="save")
175                {
176                        m_FaceBank->Save(b->get(1).asString().c_str());
177                }
178                else if (b->get(0).asString()=="errorthresh")
179                {
180                        m_FaceBank->SetErrorThresh(b->get(1).asDouble());
181                }
182        }
183
184        if (m_Idle)
185        {
186                        // idling, so free up some cpu
187                #ifdef WIN32
188                        Sleep(2000);
189                #else
190                        usleep(200000);
191                #endif
192        }
193        else
194        {
195                vector<Rect> rects = m_FaceFinder.Find(camera,m_Learn);
196                for(vector<Rect>::iterator i = rects.begin(); i!=rects.end(); i++ )
197                {
198                        unsigned int ID=999;
199                        int imagenum=-1;
200                        float confidence=0;
201                        // get the face area as a sub image
202                        Image face = camera.SubImage(*i);
203
204                        //face.SubMean();
205                        //camera.Blit(face.Scale(w,h).RGB2GRAY(),100,100);
206
207                        // pass it into the face bank
208                        if (m_Learn)
209                        {
210                                confidence=m_FaceBank->Suggest(face,m_FaceNum);
211                                ID=m_FaceNum;
212                        }
213                        else
214                        {       
215                                confidence=m_FaceBank->Identify(face,ID,imagenum);
216                        }                               
217
218                        // if it's recognised the face (should really check the confidence)
219                        if (ID!=999)
220                        {
221                                char s[32];
222                                map<int,string>::iterator d = m_DebugNames.find(ID);
223                                if (d!=m_DebugNames.end())
224                                {
225                                        sprintf(s,"%s",d->second.c_str());
226                                }
227                                else
228                                {
229                                        sprintf(s,"%d",ID);
230                                }
231
232                                cvPutText(camera.m_Image, s, cvPoint(i->x,i->y+i->h-5), &m_LargeFont, colors[ID]);
233
234                                if (!m_Learn)
235                                {
236                                        m_SceneState.AddPresent(ID, SceneState::User(confidence));
237                                }
238                        }
239
240                        cvRectangle(camera.m_Image, cvPoint(i->x,i->y), cvPoint(i->x+i->w,i->y+i->h), colors[0]);
241                }
242
243                char info[256];
244                if (m_Learn)
245                {
246                        snprintf(info,256,"Learning user :%d",m_FaceNum);
247
248                        PCAClassifier *c = static_cast<PCAClassifier*>(m_FaceBank->GetClassifier());
249                        if (c->GroupExists(m_FaceNum))
250                        {
251                                Vector<float> p = c->GetGroupMean(m_FaceNum);
252                                Vector<float> r = c->GetPCA().Synth(p);
253                                camera.Blit(Image(w,h,1,r),0,100);
254                        }
255                }
256                else
257                {
258                        snprintf(info,256,"Detecting users");
259                }
260
261                cvPutText(camera.m_Image, info, cvPoint(10,10), &m_Font, colors[0]);
262
263                m_SceneState.Update();
264        }
265       
266}
267
268void App::Benchmark(const string &test)
269{
270        cerr<<"Running benchmark test"<<endl;
271        string path(string("../data/benchmark/")+test);
272        vector<string> people=Glob(path+string("/training/*"));
273        int ID=0;
274        m_Learn=true;
275       
276        for(vector<string>::iterator pi=people.begin(); pi!=people.end(); ++pi)
277        {
278                m_DebugNames[ID]=pi->substr(pi->find_last_of("/")+1,pi->length());
279                vector<string> images=Glob(*pi+"/*.jpg");
280                for(vector<string>::iterator ii=images.begin(); ii!=images.end(); ++ii)
281                {
282                        cerr<<ID<<" "<<*ii<<endl;
283                        m_FaceNum=ID;
284                        Image image(*ii);
285                        Update(image);
286                        //string fn=*ii+"-out.png";
287                        //cvSaveImage(fn.c_str(),image.m_Image);
288                }
289                ID++;
290        }
291       
292        m_Learn=false;
293       
294        /*vector<string> images=Glob(path+string("/control/*.jpg"));
295        for(vector<string>::iterator ti=images.begin(); ti!=images.end(); ++ti)
296        {       
297                cerr<<*ti<<endl;
298                Image test(*ti);       
299                Update(test);
300                string fn=*ti+"-out.png";
301                cvSaveImage(fn.c_str(),test.m_Image);
302        }*/
303
304        int imgw=1024;
305        int imgh=768;
306        Image out(imgw,imgh,8,3);
307        int across=13;
308        int down=13;
309        int w=imgw/across;
310        int h=imgh/down;
311
312        int i=0;
313        vector<string> images=Glob(path+string("/test/*.jpg"));
314        for(vector<string>::iterator ti=images.begin(); ti!=images.end(); ++ti)
315        {       
316                cerr<<*ti<<endl;
317                Image test(*ti);       
318                Update(test);
319                int x=i%across;
320                int y=i/across;
321                out.Blit(test.Scale(w,h),x*w,y*h);
322                cerr<<x*w<<" "<<y*h<<endl;
323                i++;
324        }
325       
326        char fn[256];
327        snprintf(fn,256,"%s/out.jpg",path.c_str());
328        cvSaveImage(fn,out.m_Image);
329}
Note: See TracBrowser for help on using the repository browser.