Changeset 84


Ignore:
Timestamp:
05/28/2009 03:52:09 PM (11 years ago)
Author:
dave
Message:

multiple image mode greatly improved

Location:
foam/trunk/simple-faceident
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • foam/trunk/simple-faceident/README

    r76 r84  
    1313face is given an ID based on it's closest match (within a given error  
    1414threshold) with the faces recorded during calibration. The boxes drawn around  
    15 the faces display the id and the confidence value of the match. When in this  
    16 mode the program sends the following YARP messages: 
     15the faces display the closest matched image, the id and confidence value of the  
     16match. When in this mode the program sends the following YARP messages: 
    1717 
    1818Output port     Bottle contents                 Meaning 
     
    3030/faceident-ctrl "idle"                          Switch to idle mode, mostly frees up cpu 
    3131/faceident-ctrl "multiimages" 1/0               Turn on or off multiple images per face, experimental 
     32/faceident-ctrl "errorthresh" value             Set the error threshold (default 0.2) 
     33/faceident-ctrl "newimagethresh" value          Set the threshold greater than which new images are  
     34                                                stored in training (default 0.1) 
    3235 
    33 Faces are saved in png format along with a text file to map them to id numbers. The sessionname  
    34 will be prepended onto the filenames for the text file and the image files, so you can save  
     36Faces are saved in png format along with a xml file to map them to id numbers. The sessionname  
     37will be prepended onto the filenames for the xml file and the image files, so you can save  
    3538multiple sessions. 
    3639 
     
    5255Todo: 
    5356* Try normalised cross correlation instead of image differencing 
    54 * Expose image size and error threshold via yarp 
    55 * Lighting is a problem 
    56    - Ignore the problem 
    57    - Try the edge image + blur trick 
    58    - LBP 
    59    - Store multiple faces per id, for different lighting conditions 
     57* Expose image size via yarp 
    6058 
    6159Questions to: 
     
    6361dave@fo.am 
    6462 
    65 Notes 
    66 ----- 
    67  
    68 Muliple face images 
    69 ------------------- 
    70  
    71 Could works as normal but with additional: 
    72  
    73 ----> "new lighting" or "new session" 
    74  
    75 recalibration results in additional id images for users (leaves existing ones alone) 
    76 search checks each image for each user 
    77 images added to saved set - possible to build up lots of images of users 
    78  
    79 would this work in some initial calibration with different lighting setups, or as it went along? 
    80  
    81 Edge image & blur 
    82 ----------------- 
    83  
    84 Remove low frequency lighting information from the face images 
    85 Blur the resulting edge images to make them more forgiving 
    86 - Would this just remove shape information? needs testing 
    87  
    88  
    89  
    90  
    91  
  • foam/trunk/simple-faceident/src/Face.h

    r76 r84  
    2626///////////////////////////////////////////////////////////////////////////////// 
    2727// A face representation 
     28// 
     29// Consists of a set of images representing an identity.  
    2830 
    2931class Face 
  • foam/trunk/simple-faceident/src/FaceBank.cpp

    r76 r84  
    3131///////////////////////////////////////////////////////////////////////////////// 
    3232         
    33 FaceBank::FaceBank(unsigned int FaceWidth, unsigned int FaceHeight, float ErrorThresh) :  
     33FaceBank::FaceBank(unsigned int FaceWidth, unsigned int FaceHeight, float ErrorThresh, float NewImageThresh) :  
    3434m_FaceWidth(FaceWidth), 
    3535m_FaceHeight(FaceHeight), 
    3636m_ErrorThresh(ErrorThresh), 
    37 m_MultiFaceImages(false) 
     37m_NewImageThresh(NewImageThresh) 
    3838{ 
    3939} 
     
    6767        {                
    6868                // Check it doesn't look like any we have already recorded 
    69                 unsigned int checkid=0; 
     69                /*unsigned int checkid=0; 
    7070                int imagenum=-1; 
    7171                if (Identify(faceresized,checkid,imagenum)>0) 
     
    7373                        cerr<<"We've already seen this face: "<<checkid<<":"<<imagenum<<endl;    
    7474                        return 0; 
    75                 } 
     75                }*/ 
    7676 
    7777                cerr<<"new face "<<ID<<endl; 
     
    8686        if (error<m_ErrorThresh)  
    8787        { 
    88                 //cerr<<"adding to face:"<<ID<<" image:"<<facenum<<endl; 
    89                 // Blend this face into the one we have already 
    90                 i->second->Learn(faceresized,0.2,facenum); 
    91                 cvReleaseImage(&faceresized); 
    92                 ID=i->first; 
     88                if (error>m_NewImageThresh) 
     89                { 
     90                        cerr<<"adding new image to face "<<error<<" "<<ID<<endl; 
     91                        i->second->AddImage(faceresized);                
     92                } 
     93                else 
     94                { 
     95                        //cerr<<"adding to face:"<<ID<<" image:"<<facenum<<endl; 
     96                        // Blend this face into the one we have already 
     97                         
     98                        // removed this, as its potentially throwing away information 
     99                        // multiple face images are better 
     100                        //i->second->Learn(faceresized,0,facenum); 
     101                        cvReleaseImage(&faceresized); 
     102                } 
     103                ID=i->first;     
    93104                return 1-error; 
    94         } 
    95          
    96         if (m_MultiFaceImages) 
    97         {        
    98                 // Does it look like any we have already recorded for any face? 
    99                 unsigned int checkid=0; 
    100                 int imagenum=-1; 
    101                 if (Identify(faceresized,checkid,imagenum)>0) 
    102                 { 
    103                         cerr<<"We've already seen this face: "<<checkid<<":"<<imagenum<<endl;    
    104                         return 0; 
    105                 }        
    106                  
    107                 cerr<<"too different - adding new image to face "<<error<<" "<<ID<<endl; 
    108                 i->second->AddImage(faceresized); 
    109105        } 
    110106         
     
    144140        } 
    145141         
     142        cvReleaseImage(&faceresized); 
     143         
    146144        // if the error is less than the threshold, return the id 
    147145        if (error<m_ErrorThresh) 
    148146        { 
    149                 // blend this face into the one we have already 
    150                 bestface->Learn(faceresized,0,imagenum); 
    151                 cvReleaseImage(&faceresized); 
    152147                ID=best; 
    153148                return 1-error; 
     
    155150         
    156151        cerr<<"unrecognised face"<<endl; 
    157          
    158152        return 0; 
    159153} 
  • foam/trunk/simple-faceident/src/FaceBank.h

    r76 r84  
    2727///////////////////////////////////////////////////////////////////////////////// 
    2828// A database of detected faces 
     29// 
     30// The facebank is mainly driven by calling Suggest() (which maps face images with  
     31// id numbers) or Identify() which looks in it's current set of faces (and in the  
     32// images contained in those faces) for the closest match.  
     33// 
     34// Thresholding explanations 
     35// 
     36// Suggest mode: 
     37// 
     38//    Error -> 
     39//    0          RelearnThresh       ErrorThresh                         1 
     40//    I----------------I------------------I------------------------------> 
     41//        Do nothing      Add New Image       Suggestion rejected 
     42// 
     43// In suggest mode, suggestions are also rejected if they are too similar 
     44// to faces already in the bank - this is an attempt to make calibration  
     45// possible while other people are in shot. 
     46// 
     47// Identify mode: 
     48// 
     49//    Error -> 
     50//    0                              ErrorThresh                         1 
     51//    I-----------------------------------I------------------------------> 
     52//                  Match                           No match 
     53// 
     54// 
    2955 
    3056class FaceBank 
     
    3258public: 
    3359        // FaceWidth and FaceHeight are the size for the internal stored image of the face for  
    34         // comparison, ErrorThresh is the error amount which will trigger a new face to be stored 
    35         FaceBank(unsigned int FaceWidth, unsigned int FaceHeight, float ErrorThresh); 
     60        // comparison, ErrorThresh is the threshold at which a face will be considered as recognised, 
     61        // NewImageThresh is a threshold greater than which a suggested face will be stored as  
     62        // a new image. 
     63        FaceBank(unsigned int FaceWidth, unsigned int FaceHeight, float ErrorThresh, float NewImageThresh); 
    3664        ~FaceBank(); 
    3765 
    3866        void Clear(); 
     67         
     68        void SetErrorThresh(float s) { m_ErrorThresh=s; } 
     69        void SetNewImageThresh(float s) { m_NewImageThresh=s; } 
    3970         
    4071        // Learn this face, the face may be a false positive, so we'll discard the  
     
    4475        // Gives the id, given a face, and returns the confidence 
    4576        float Identify(IplImage *face, unsigned int &ID, int &imagenum); 
    46          
    47         // Collect multiple images per user 
    48         void AllowMultiFaceImages(bool s) { m_MultiFaceImages=s; } 
    49          
     77                 
    5078        std::map<unsigned int, Face*> &GetFaceMap() { return m_FaceMap; } 
    5179         
     
    6189        unsigned int m_FaceHeight; 
    6290        float m_ErrorThresh; 
    63         bool m_MultiFaceImages; 
     91        float m_NewImageThresh; 
    6492         
    6593        std::map<unsigned int, Face*> m_FaceMap; 
  • foam/trunk/simple-faceident/src/ImageUtils.cpp

    r76 r84  
    6363                        { 
    6464                cvSet2D(dstimage,y+pos.y,x+pos.x,cvGet2D(srcimage,y,x)); 
     65                        } 
     66                } 
     67        } 
     68} 
     69 
     70///////////////////////////////////////////////////////////// 
     71// paste an image over the top of another, with transparency 
     72 
     73void BlitImageAlpha(const IplImage *srcimage, IplImage *dstimage, CvPoint pos, float alpha) 
     74{ 
     75        CvSize size = cvGetSize(srcimage); 
     76        CvSize dstsize = cvGetSize(dstimage); 
     77         
     78        for(int y=0; y<size.height; y++) 
     79        { 
     80        for(int x=0; x<size.width; x++) 
     81                { 
     82                        if (x+pos.x>0 && x+pos.x<dstsize.width && 
     83                                y+pos.y>0 && y+pos.y<dstsize.height) 
     84                        { 
     85                                CvScalar sv = cvGet2D(srcimage,y,x); 
     86                        CvScalar dv = cvGet2D(dstimage,y+pos.y,x+pos.x); 
     87                                 
     88                                CvScalar out; 
     89                                out.val[0]=sv.val[0]*alpha+dv.val[0]*(1-alpha);                          
     90                                out.val[1]=sv.val[1]*alpha+dv.val[1]*(1-alpha);                          
     91                                out.val[2]=sv.val[2]*alpha+dv.val[2]*(1-alpha);                          
     92 
     93                        cvSet2D(dstimage,y+pos.y,x+pos.x,out); 
    6594                        } 
    6695                } 
  • foam/trunk/simple-faceident/src/ImageUtils.h

    r76 r84  
    2525IplImage* SubImage(IplImage *image, CvRect roi); 
    2626void BlitImage(const IplImage *srcimage, IplImage *dstimage, CvPoint pos); 
     27void BlitImageAlpha(const IplImage *srcimage, IplImage *dstimage, CvPoint pos, float alpha); 
    2728void SubMean(IplImage *image); 
    2829float Diff(const IplImage *imagea, const IplImage *imageb); 
  • foam/trunk/simple-faceident/src/main.cpp

    r76 r84  
    6666////////////////////////////////////////////////////////// 
    6767// These are the tweakable bits - see comments in FaceBank.h 
    68 FaceBank facebank(30, 40, 0.15);  
     68FaceBank facebank(30, 40, 0.2, 0.1); //0.2 
    6969SceneState scenestate; 
    7070 
     
    104104        ///////////////////////// 
    105105 
     106        //facebank.Load("a"); 
     107 
    106108        for( i = 1; i < argc; i++ ) 
    107109        { 
     
    121123                                scale = 1; 
    122124                } 
     125                else if( strncmp( argv[i], "--load=", 7 ) == 0 ) 
     126                { 
     127                        cerr<<"loading "<<argv[i]+7<<endl; 
     128                        facebank.Load(argv[i]+7); 
     129                } 
    123130                else if( argv[i][0] == '-' ) 
    124131                { 
     
    135142                fprintf( stderr, "ERROR: Could not load classifier cascade\n" ); 
    136143                fprintf( stderr, 
    137                         "Usage: facedetect [--cascade=\"<cascade_path>\"]\n" 
     144                        "Usage: faceident [--cascade=\"<cascade_path>\"]\n" 
    138145                        "   [--nested-cascade[=\"nested_cascade_path\"]]\n" 
    139146                        "   [--scale[=<image scale>\n" 
     
    242249 
    243250        CvFont font; 
    244         cvInitFont( &font, CV_FONT_HERSHEY_PLAIN, 2, 2, 0, 1, CV_AA ); 
     251        cvInitFont( &font, CV_FONT_HERSHEY_PLAIN, 0.75, 0.75, 0, 1, CV_AA ); 
    245252 
    246253        CvFont infofont; 
     
    333340                                facebank.Save(b->get(1).asString().c_str()); 
    334341                        } 
    335                         else if (b->get(0).asString()=="multiimage") 
    336                         { 
    337                                 facebank.AllowMultiFaceImages(b->get(1).asInt()); 
     342                        else if (b->get(0).asString()=="errorthresh") 
     343                        { 
     344                                facebank.SetErrorThresh(b->get(1).asDouble()); 
     345                        } 
     346                        else if (b->get(0).asString()=="newimagethresh") 
     347                        { 
     348                                facebank.SetNewImageThresh(b->get(1).asDouble()); 
    338349                        } 
    339350                } 
    340351 
    341352                /////////////////////////////////// 
    342  
    343353                if (!idle) 
    344354                { 
     
    372382                                        char s[32]; 
    373383                                        sprintf(s,"%d %0.2f",ID,confidence); 
    374                                         cvPutText(small_img, s, cvPoint(r->x,r->y+25), &font, color); 
    375                                         int x=(facebank.GetFaceWidth()+1)*ID; 
     384                                        cvPutText(small_img, s, cvPoint(r->x,r->y+r->height-5), &font, color); 
     385                                        int x=(facebank.GetFaceWidth()+8)*ID; 
    376386                                        int y=imgsize.height-facebank.GetFaceHeight(); 
    377                                         y-=(facebank.GetFaceHeight()+2)*imagenum; 
     387                                        //y-=(facebank.GetFaceHeight()+2)*imagenum; 
     388                                        y-=5*imagenum; 
     389                                         
    378390                                        cvLine(small_img, cvPoint(r->x+r->width/2,r->y+r->height/2), 
    379                                                 cvPoint(x+facebank.GetFaceWidth()/2,y), color);                  
     391                                                cvPoint(x+facebank.GetFaceWidth()/2,y+facebank.GetFaceHeight()/2), color); 
     392 
     393                                        cvRectangle(small_img,cvPoint(x-1,y-1),cvPoint(x+facebank.GetFaceWidth(),y+facebank.GetFaceHeight()), color); 
     394 
     395                                        if (imagenum>=0) 
     396                                        { 
     397                                                BlitImageAlpha(facebank.GetFaceMap()[ID]->m_ImageVec[imagenum],small_img,cvPoint(r->x,r->y),0.75); 
     398                                        } 
    380399 
    381400                                        if (!learn) 
     
    425444                ii!=facebank.GetFaceMap().end(); ++ii) 
    426445        { 
    427                 int x=(facebank.GetFaceWidth()+1)*ii->first; 
     446                int x=(facebank.GetFaceWidth()+8)*ii->first; 
    428447                int y=imgsize.height-facebank.GetFaceHeight(); 
    429448                for(vector<IplImage *>::iterator im=ii->second->m_ImageVec.begin(); 
    430449                        im!=ii->second->m_ImageVec.end(); im++) 
    431450                { 
     451                        //BlitImage(*im,small_img,cvPoint(x,y)); 
    432452                        BlitImage(*im,small_img,cvPoint(x,y)); 
    433                         y-=facebank.GetFaceHeight()+2; 
     453                        //y-=facebank.GetFaceHeight()+2; 
     454                        y-=5; 
    434455                } 
    435456        } 
    436457#endif 
    437458 
     459 
    438460        cvShowImage( "result", small_img ); 
    439  
     461        framenum++; 
    440462#ifdef SAVE_FRAMES 
    441463        char name[256]; 
    442464        sprintf(name,"out-%0.4d.jpg",framenum); 
     465        cerr<<"saving "<<name<<endl; 
    443466        cvSaveImage(name,small_img); 
    444467#endif 
Note: See TracChangeset for help on using the changeset viewer.