00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "Channels/ChannelOpts.H"
00042 #include "Component/GlobalOpts.H"
00043 #include "Component/ModelManager.H"
00044 #include "GUI/XWinManaged.H"
00045 #include "Gist/FFN.H"
00046 #include "Image/FFTWWrapper.H"
00047 #include "Gist/ModelFace.H"
00048 #include "Image/CutPaste.H"
00049 #include "Image/DrawOps.H"
00050 #include "Image/Image.H"
00051 #include "Image/ImageSet.H"
00052 #include "Image/Kernels.H"
00053 #include "Image/MathOps.H"
00054 #include "Image/Pixels.H"
00055 #include "Image/PyramidOps.H"
00056 #include "Image/ShapeOps.H"
00057 #include "Image/Transforms.H"
00058 #include "Media/FrameSeries.H"
00059 #include "Media/MediaSimEvents.H"
00060 #include "Neuro/NeuroOpts.H"
00061 #include "Neuro/NeuroSimEvents.H"
00062 #include "Neuro/ShapeEstimator.H"
00063 #include "Neuro/VisualCortex.H"
00064 #include "Neuro/StdBrain.H"
00065 #include "Raster/Raster.H"
00066 #include "Simulation/SimEventQueueConfigurator.H"
00067
00068
00069 #include "Channels/BlueYellowChannel.H"
00070 #include "Channels/ColorChannel.H"
00071 #include "Channels/GaborChannel.H"
00072 #include "Channels/IntensityChannel.H"
00073 #include "Channels/OrientationChannel.H"
00074 #include "Channels/RedGreenChannel.H"
00075
00076
00077 CloseButtonListener wList;
00078 XWinManaged *imgWin;
00079 XWinManaged *fftWin;
00080 XWinManaged *salWin;
00081 XWinManaged *workWin;
00082
00083 ImageSet<float> pyrImg;
00084
00085
00086 FFTWWrapper *fftw;
00087 rutz::shared_ptr<FeedForwardNetwork> ffn_pl;
00088 int primeLev = 0;
00089 double *input = NULL;
00090 Image<double> gft;
00091 double *iptr = NULL;
00092 double **outFftw = NULL;
00093 double ****gaborMask = NULL;
00094 Image<float> gaborMaskImg[NUM_G_LEV][NUM_G_DIR];
00095 void setupPrimeLevEstimator();
00096 void setupFFTW(Image<float> img);
00097 int* getPrimeLev(Image<float> img);
00098 void setupGaborMask(Image<float> img);
00099 Image<float> normalize(Image<float> img);
00100 Image<float> getFftImage(double **outFft, int w, int h);
00101 void fftCompute(Image<float> img, double **outFft);
00102 void getFeatureVector
00103 (double **outFft, Image<double> &res, int w, int h);
00104 void getFeatureVector2
00105 (nub::soft_ref<StdBrain> brain, Image<double> &vec, int w, int h);
00106 void freeFftwData(Image<float> img);
00107
00108
00109 rutz::shared_ptr<FeedForwardNetwork> ffn_e;
00110 rutz::shared_ptr<FeedForwardNetwork> ffn_n;
00111 rutz::shared_ptr<FeedForwardNetwork> ffn_m;
00112
00113
00114
00115
00116 Image<float> currImg;
00117 ImageSet<float> currGaPyr[NUM_DIR];
00118
00119 void setupPartDetectors();
00120 Rectangle getWindow (Image<float> img, Point2D<int> p, int s);
00121 void getFacePartProb (Point2D<int> p, float ang, double *pPart);
00122 void correctGabors (Image<float> **Img, float ang);
00123 void getFacePartFeatures(Rectangle r, FacePart part, Image<double> &features);
00124
00125
00126 void getEyeFeature (Rectangle r, Image<double> &features);
00127 void getEyeFeature (Image<float> **img, Image<double> &features);
00128 void getNoseFeature (Rectangle r, Image<double> &features);
00129 void getNoseFeature (Image<float> **img, Image<double> &features);
00130 void getMouthFeature (Rectangle r, Image<double> &features);
00131 void getMouthFeature (Image<float> **img, Image<double> &features);
00132
00133
00134 void detectFace (Image<float> img, nub::soft_ref<StdBrain> brain,
00135 Point2D<int> winner);
00136 Point2D<int> getIntSalPt (Image<float> img, Point2D<int> p);
00137 Point2D<int> getIntSalPt (Image<float> img, Image<float>& vis, Point2D<int> p);
00138 float getSalG (Point2D<int> p, int lev);
00139 void getLocalSalPt (Point2D<int> pWinner, int max,
00140 Point2D<int> **pt, double **ang, int *np);
00141 void crop (Image<float>& img, Point2D<int> p);
00142 void getContextPt (Point2D<int> *attPt, float *dir, double **pProb,
00143 int n, int max,
00144 Point2D<int> **pt, double **ang, int *np);
00145 double getAng (Point2D<int> p);
00146 float getPotVal (Point2D<int> *attPt, float *dir,
00147 double *pProb[NUM_FACE_PART], int n,
00148 Point2D<int> pt, float a, double
00149 tProb[NUM_FACE_PART]);
00150 float getGeomRelProb (FacePart o,FacePart c, Point2D<int> oPt, float oD,
00151 Point2D<int> cPt, float cA);
00152 bool locateFace (Point2D<int> *attPt, float *dir,
00153 double *pProb[NUM_FACE_PART], int n);
00154 void drawFace (Image<float>& img);
00155 void printRegion (Image<float> img,int sX,int eX,int dX,
00156 int sY,int eY, int dY);
00157 void displayPartImage (Image<float> img, Rectangle pr);
00158
00159
00160 Point2D<int> eyeP, eye2P, noseP, mouthP;
00161 float eyeD, eye2D, noseD, mouthD;
00162
00163
00164
00165 int main(const int argc, const char **argv)
00166 {
00167 MYLOGVERB = LOG_INFO;
00168
00169
00170 ModelManager manager("Face Detection Model");
00171
00172 nub::soft_ref<SimEventQueueConfigurator>
00173 seqc(new SimEventQueueConfigurator(manager));
00174 manager.addSubComponent(seqc);
00175
00176 nub::soft_ref<InputFrameSeries> ifs(new InputFrameSeries(manager));
00177 manager.addSubComponent(ifs);
00178
00179 nub::soft_ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager));
00180 manager.addSubComponent(ofs);
00181
00182
00183 nub::soft_ref<StdBrain> brain(new StdBrain(manager));
00184 manager.addSubComponent(brain);
00185
00186 manager.setOptionValString(&OPT_MaxNormType, "FancyOne");
00187 manager.setOptionValString(&OPT_UseRandom, "false");
00188
00189
00190 manager.setOptionValString(&OPT_ShapeEstimatorMode, "FeatureMap");
00191 manager.setOptionValString(&OPT_ShapeEstimatorSmoothMethod, "Chamfer");
00192
00193 manager.setOptionValString(&OPT_RawVisualCortexChans,"OIC");
00194
00195 manager.setOptionValString(&OPT_IORtype, "Disc");
00196
00197
00198 if (manager.parseCommandLine(argc, argv, "<image>", 1, 1) == false)
00199 return(1);
00200
00201 LFATAL("FIXME");
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 while(!(wList.pressedAnyCloseButton()))sleep(1);
00463
00464 manager.stop();
00465
00466
00467 printf("All done\n");
00468 return 0;
00469 }
00470
00471
00472
00473 void setupPartDetectors()
00474 {
00475
00476 ffn_e.reset(new FeedForwardNetwork());
00477 ffn_n.reset(new FeedForwardNetwork());
00478 ffn_m.reset(new FeedForwardNetwork());
00479
00480
00481 std::string h1EName(sformat("%s%s%s",WEIGHT_DATA_FOLDER,FILE_TAGNAME,"hidden1EYE.dat"));
00482 std::string h2EName(sformat("%s%s%s",WEIGHT_DATA_FOLDER,FILE_TAGNAME,"hidden2EYE.dat"));
00483 std::string oEName(sformat("%s%s%s",WEIGHT_DATA_FOLDER,FILE_TAGNAME,"outEYE.dat"));
00484
00485 std::string h1NName(sformat("%s%s%s",WEIGHT_DATA_FOLDER,FILE_TAGNAME,"hidden1NOSE.dat"));
00486 std::string h2NName(sformat("%s%s%s",WEIGHT_DATA_FOLDER,FILE_TAGNAME,"hidden2NOSE.dat"));
00487 std::string oNName(sformat("%s%s%s",WEIGHT_DATA_FOLDER,FILE_TAGNAME,"outNOSE.dat"));
00488
00489 std::string h1MName(sformat("%s%s%s",WEIGHT_DATA_FOLDER,FILE_TAGNAME,"hidden1MOUTH.dat"));
00490 std::string h2MName(sformat("%s%s%s",WEIGHT_DATA_FOLDER,FILE_TAGNAME,"hidden2MOUTH.dat"));
00491 std::string oMName(sformat("%s%s%s",WEIGHT_DATA_FOLDER,FILE_TAGNAME,"outMOUTH.dat"));
00492
00493
00494
00495 ffn_e->init3L(h1EName, h2EName, oEName,
00496 RE_INPUT, RE_HIDDEN_1, RE_HIDDEN_2, 1, 0.0, 0.0);
00497 ffn_n->init3L(h1NName, h2NName, oNName,
00498 N_INPUT, N_HIDDEN_1, N_HIDDEN_2, 1, 0.0, 0.0);
00499 ffn_m->init3L(h1MName, h2MName, oMName,
00500 M_INPUT, M_HIDDEN_1, M_HIDDEN_2, 1, 0.0, 0.0);
00501 }
00502
00503
00504
00505 void setupPrimeLevEstimator()
00506 {
00507
00508 ffn_pl.reset(new FeedForwardNetwork());
00509
00510
00511 std::string h1PLName(sformat("%s%s",WEIGHT_DATA_FOLDER,"hidden1PL.dat"));
00512 std::string h2PLName(sformat("%s%s",WEIGHT_DATA_FOLDER,"hidden2PL.dat"));
00513 std::string oPLName(sformat("%s%s",WEIGHT_DATA_FOLDER,"outPL.dat"));
00514
00515
00516
00517 ffn_pl->init3L(h1PLName, h2PLName, oPLName,
00518 NUM_G_LEV*NUM_G_DIR, PL_HIDDEN_1, PL_HIDDEN_2, NUM_H_LEV,
00519 0.0, 0.0);
00520 }
00521
00522
00523
00524 void detectFace(Image<float> img, nub::soft_ref<StdBrain> brain, Point2D<int> winner)
00525 {
00526 LFATAL("FIXME");
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 }
00691
00692
00693 Point2D<int> getIntSalPt(Image<float> img, Point2D<int> p)
00694 {
00695
00696 Image<float> vis(img.getWidth(), img.getHeight(), ZEROS);
00697
00698 Point2D<int> a = getIntSalPt(img,vis,p);
00699
00700
00701
00702
00703 return a;
00704 }
00705
00706
00707 Point2D<int> getIntSalPt(Image<float> img, Image<float>& vis, Point2D<int> p)
00708 {
00709 float a = img.getVal(p); float b;
00710 if(vis.getVal(p) == 255.0) return p;
00711 else vis.setVal(p,255.0);
00712 Point2D<int> n; Point2D<int> mn; float mc = 0.0;
00713 int lev = primeLev;
00714
00715
00716
00717 int w = img.getWidth(); int h = img.getHeight();
00718 if(p.i > 0)
00719 {
00720 n = p + Point2D<int>(-1,0); b = img.getVal(n);
00721 if(fabs(a - b)/a < .5 && b > 0.001) n = getIntSalPt(img, vis, n);
00722 mn = n; mc = getSalG(n,lev);
00723 }
00724 if(p.i < w-1)
00725 {
00726 n = p + Point2D<int>(1,0); b = img.getVal(n);
00727 if(fabs(a - b)/a < .5 && b > 0.001) n = getIntSalPt(img, vis, n);
00728 if(mc < getSalG(n,lev))
00729 { mn = n; mc = getSalG(n,lev); }
00730 }
00731
00732 if(p.j > 0)
00733 {
00734 n = p + Point2D<int>(0,-1); b = img.getVal(n);
00735 if(fabs(a - b)/a < .5 && b > 0.001) n = getIntSalPt(img, vis, n);
00736 if(mc < getSalG(n,lev))
00737 { mn = n; mc = getSalG(n,lev); }
00738 }
00739 if(p.j < h-1)
00740 {
00741 n = p + Point2D<int>(0,1); b = img.getVal(n);
00742 if(fabs(a - b)/a < .5 && b > 0.001) n = getIntSalPt(img, vis, n);
00743 if(mc < getSalG(n,lev))
00744 { mn = n; mc = getSalG(n,lev); }
00745 }
00746
00747 return mn;
00748 }
00749
00750
00751 float getSalG(Point2D<int> p, int lev)
00752 {
00753 float max = 0.0;
00754 for(int i = 0; i< NUM_DIR; i++)
00755 {
00756 if(currGaPyr[i][lev].getVal(p) > max)
00757 max = currGaPyr[i][lev].getVal(p);
00758 }
00759 return max;
00760 }
00761
00762
00763 XWinManaged *tXW; int txwC = 0;
00764 void getLocalSalPt(Point2D<int> pWinner, int max,
00765 Point2D<int> **pt, double **ang, int *np)
00766 {
00767
00768 *np = 0;
00769 Image<float> temp = pyrImg[primeLev];
00770
00771
00772
00773
00774
00775
00776
00777
00778 Rectangle r = getWindow(pyrImg[primeLev], pWinner, 40);
00779 r = Rectangle::tlbrO(r.top(),r.left(),
00780 (r.bottomO()/4)*4,(r.rightO()/4)*4);
00781 printf("r(%d,%d,%d,%d) = PI[%d,%d],pW(%d,%d) \n",
00782 r.top(),r.left(),r.bottomI(),r.rightI(),
00783 pyrImg[primeLev].getWidth(),pyrImg[primeLev].getHeight(),pWinner.i,pWinner.j);
00784
00785 Image<float> sumS;
00786 Image<float> sMap; sMap.resize(r.width(),r.height(),true);
00787
00788 Image<float> gI[NUM_DIR];
00789 for(int i = 0; i< NUM_DIR; i++) gI[i].resize(r.width(),r.height(),true);
00790
00791
00792 for(int c = 0; c < 3; c++)
00793 for(int s = c+1; s< 3; s++)
00794 {
00795 for(int i = 0; i < NUM_DIR; i++)
00796 {
00797
00798
00799 gI[i] = crop(zoomXY(currGaPyr[i][primeLev+c],int(pow(2.0,c)),-1),r) -
00800 crop(zoomXY(currGaPyr[i][primeLev+s],int(pow(2.0,s)),-1),r) ;
00801 }
00802
00803 sumS = gI[0]+gI[1]+gI[2]+gI[3];
00804 inplaceNormalize(sumS, 0.0f, 255.0f);
00805 sumS = squared(squared(sumS));
00806 sMap+= sumS;
00807
00808
00809
00810
00811
00812
00813 }
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827 sMap = squared(sMap);
00828 inplaceNormalize(sMap, 0.0f, 255.0f);
00829 float t;
00830 for(int i = 0; i < max; i++)
00831 {
00832 findMax(sMap, (*pt)[i],t);
00833
00834
00835 if(t < 20.0) break;
00836 crop(sMap,(*pt)[i]);
00837
00838
00839 for(int j = 0; j < i; j++)
00840 if((*pt)[j].distance((*pt)[i]) < 6.0)
00841 {
00842 j = i+1;
00843 i--;(*np)--;
00844 }
00845
00846 (*ang)[i] = getAng((*pt)[i]+Point2D<int>(r.left(),r.top()));
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857 (*np)++;
00858 }
00859
00860 for(int i = 0; i< *np; i++) (*pt)[i] = (*pt)[i] + Point2D<int>(r.left(),r.top());
00861
00862
00863 }
00864
00865
00866
00867 void crop(Image<float>& img, Point2D<int> p)
00868 {
00869
00870 float a = img.getVal(p);
00871 float b;
00872 img.setVal(p,0.0);
00873 int w = img.getWidth(); int h = img.getHeight();
00874
00875
00876
00877 if(p.i > 0)
00878 {
00879 b = img.getVal(p + Point2D<int>(-1,0));
00880 if(fabs(a - b)/a < .5 && b > 0.001) crop(img, p+Point2D<int>(-1,0));
00881 }
00882 if(p.i < w-1)
00883 {
00884 b = img.getVal(p + Point2D<int>(1,0));
00885 if(fabs(a - b)/a < .5 && b > 0.001) crop(img, p+Point2D<int>(1,0));
00886 }
00887 if(p.j > 0)
00888 {
00889 b = img.getVal(p + Point2D<int>(0,-1));
00890 if(fabs(a - b)/a < .5 && b > 0.001) crop(img, p+Point2D<int>(0,-1));
00891 }
00892 if(p.j < h-1)
00893 {
00894 b = img.getVal(p + Point2D<int>(0,1));
00895 if(fabs(a - b)/a < .5 && b > 0.001) crop(img, p+Point2D<int>(0,1));
00896 }
00897 }
00898
00899
00900 double getAng(Point2D<int> p)
00901 {
00902
00903 int iMax = 0; float max = 0.0;
00904 for(int i = 0; i< NUM_DIR; i++)
00905 {
00906 if(currGaPyr[i][primeLev].getVal(p) > max)
00907 {max = currGaPyr[i][primeLev].getVal(p); iMax = i;}
00908 }
00909 return iMax*M_PI/NUM_DIR;
00910 }
00911
00912
00913 void getContextPt(Point2D<int> *attPt, float *dir, double **pProb, int n, int max,
00914 Point2D<int> **pt, double **ang, int *np)
00915 {
00916
00917 int i = n-1;
00918
00919
00920
00921
00922
00923 float dx, dy; int dxR, dyR; Point2D<int> temp;
00924 Rectangle r = pyrImg[primeLev].getBounds();
00925
00926
00927
00928
00929 if(pProb[i][EYE] > .08)
00930 {
00931 float c = cos(dir[i]); float s = sin(dir[i]);
00932
00933
00934 dx = 24.0; dy = 0.0;
00935 dxR = int(round( dx*c + -dy*s));
00936 dyR = int(round( dx*s + dy*c));
00937 temp = attPt[i] + Point2D<int>(dxR,dyR);
00938 if(r.contains(temp) & (*np < max))
00939 {
00940 (*pt)[*np] = temp;
00941 (*ang)[*np] = dir[i];
00942 (*np)++;
00943 }
00944 dx = -24.0; dy = 0.0;
00945 dxR = int(round( dx*c + -dy*s));
00946 dyR = int(round( dx*s + dy*c));
00947 temp = attPt[i] + Point2D<int>(dxR,dyR);
00948 if(r.contains(temp) & (*np < max))
00949 {
00950 (*pt)[*np] = temp;
00951 (*ang)[*np] = dir[i];
00952 (*np)++;
00953 }
00954
00955
00956 dx = 12.0; dy = 8.0;
00957 dxR = int(round( dx*c + -dy*s));
00958 dyR = int(round( dx*s + dy*c));
00959 temp = attPt[i] + Point2D<int>(dxR,dyR);
00960 if(r.contains(temp) & (*np < max))
00961 {
00962 (*pt)[*np] = temp;
00963 (*ang)[*np] = fmod(dir[i]+M_PI/2.0, M_PI);
00964 (*np)++;
00965 }
00966 dx = -12.0; dy = 8.0;
00967 dxR = int(round( dx*c + -dy*s));
00968 dyR = int(round( dx*s + dy*c));
00969 temp = attPt[i] + Point2D<int>(dxR,dyR);
00970 if(r.contains(temp) & (*np < max))
00971 {
00972 (*pt)[*np] = temp;
00973 (*ang)[*np] = fmod(dir[i]+M_PI/2.0, M_PI);
00974 (*np)++;
00975 }
00976
00977
00978 dx = 12.0; dy = 28.0;
00979 dxR = int(round( dx*c + -dy*s));
00980 dyR = int(round( dx*s + dy*c));
00981 temp = attPt[i] + Point2D<int>(dxR,dyR);
00982 if(r.contains(temp) & (*np < max))
00983 {
00984 (*pt)[*np] = temp;
00985 (*ang)[*np] = dir[i];
00986 (*np)++;
00987 }
00988 dx = -12.0; dy = 28.0;
00989 dxR = int(round( dx*c + -dy*s));
00990 dyR = int(round( dx*s + dy*c));
00991 temp = attPt[i] + Point2D<int>(dxR,dyR);
00992 if(r.contains(temp) & (*np < max))
00993 {
00994 (*pt)[*np] = temp;
00995 (*ang)[*np] = dir[i];
00996 (*np)++;
00997 }
00998 }
00999
01000 if(pProb[i][NOSE] > .08)
01001 {
01002 float c = cos(fmod(dir[i]+M_PI/2.0, M_PI));
01003 float s = sin(fmod(dir[i]+M_PI/2.0, M_PI));
01004
01005
01006 dx = 12.0; dy = -8.0;
01007 dxR = int(round( dx*c + -dy*s));
01008 dyR = int(round( dx*s + dy*c));
01009 temp = attPt[i] + Point2D<int>(dxR,dyR);
01010 if(r.contains(temp) & (*np < max))
01011 {
01012 (*pt)[*np] = temp;
01013 (*ang)[*np] = fmod(dir[i]+M_PI/2.0, M_PI);
01014 (*np)++;
01015 }
01016 dx = -12.0; dy = -8.0;
01017 dxR = int(round( dx*c + -dy*s));
01018 dyR = int(round( dx*s + dy*c));
01019 temp = attPt[i] + Point2D<int>(dxR,dyR);
01020 if(r.contains(temp) & (*np < max))
01021 {
01022 (*pt)[*np] = temp;
01023 (*ang)[*np] = fmod(dir[i]+M_PI/2.0, M_PI);
01024 (*np)++;
01025 }
01026
01027
01028 dx = 0.0; dy = 20.0;
01029 dxR = int(round( dx*c + -dy*s));
01030 dyR = int(round( dx*s + dy*c));
01031 temp = attPt[i] + Point2D<int>(dxR,dyR);
01032 if(r.contains(temp) & (*np < max))
01033 {
01034 (*pt)[*np] = temp;
01035 (*ang)[*np] = fmod(dir[i]+M_PI/2.0, M_PI);
01036 (*np)++;
01037 }
01038 }
01039
01040 if(pProb[i][MOUTH] > .08)
01041 {
01042 float c = cos(dir[i]); float s = sin(dir[i]);
01043
01044
01045 dx = 12.0; dy = -28.0;
01046 dxR = int(round( dx*c + -dy*s));
01047 dyR = int(round( dx*s + dy*c));
01048 temp = attPt[i] + Point2D<int>(dxR,dyR);
01049 if(r.contains(temp) & (*np < max))
01050 {
01051 (*pt)[*np] = temp;
01052 (*ang)[*np] = dir[i];
01053 (*np)++;
01054 }
01055 dx = -12.0; dy = -28.0;
01056 dxR = int(round( dx*c + -dy*s));
01057 dyR = int(round( dx*s + dy*c));
01058 temp = attPt[i] + Point2D<int>(dxR,dyR);
01059 if(r.contains(temp) & (*np < max))
01060 {
01061 (*pt)[*np] = temp;
01062 (*ang)[*np] = dir[i];
01063 (*np)++;
01064 }
01065
01066
01067 dx = 0.0; dy = -20.0;
01068 dxR = int(round( dx*c + -dy*s));
01069 dyR = int(round( dx*s + dy*c));
01070 temp = attPt[i] + Point2D<int>(dxR,dyR);
01071 if(r.contains(temp) & (*np < max))
01072 {
01073 (*pt)[*np] = temp;
01074 (*ang)[*np] = fmod(dir[i]+M_PI/2.0, M_PI);
01075 (*np)++;
01076 }
01077 }
01078 }
01079
01080
01081 float getPotVal(Point2D<int> *attPt, float *dir, double *pProb[NUM_FACE_PART],
01082 int n, Point2D<int> pt, float a, double tProb[NUM_FACE_PART])
01083 {
01084
01085
01086
01087
01088
01089
01090 for(int i = 0; i < n; i++)
01091 if(pt.distance(attPt[i]) <= 3.0) return 0.0;
01092
01093
01094 float mVal = 0.0;
01095 for(int i = 0; i < n; i++)
01096 {
01097
01098 for(int o = 0; o < NUM_FACE_PART; o++)
01099 for(int c = 0; c < NUM_FACE_PART; c++)
01100 {
01101 float val = getGeomRelProb((FacePart)o,(FacePart)c,attPt[i],dir[i],pt,a);
01102
01103
01104 val *= pProb[i][o] * tProb[c];
01105
01106 if (val > mVal) mVal = val;
01107 }
01108
01109 }
01110
01111 return mVal;
01112 }
01113
01114
01115 float getGeomRelProb(FacePart o,FacePart c, Point2D<int> oPt, float oD,
01116 Point2D<int> cPt, float cA)
01117 {
01118
01119 int dx = cPt.i - oPt.i; int dy = cPt.j - oPt.j;
01120 float dist = cPt.distance(oPt);
01121 float dir = atan2(dy,dx) + oD;
01122 if(dir > M_PI) dir -= 2.0*M_PI;
01123
01124
01125
01126 float pOri[NUM_DIR] = {0.35, 0.25, 0.005, 0.25};
01127
01128
01129
01130
01131 switch(o)
01132 {
01133 case EYE: case L_EYE: case R_EYE:
01134 switch(c)
01135 {
01136 case EYE: case L_EYE: case R_EYE:
01137 {
01138
01139 int dOri = int(round(4.0 * fabs(oD - cA)/M_PI));
01140
01141
01142 float mean = 24.0; float stdev = 6.0;
01143 float dProb = 1.0/(stdev*sqrt(2*M_PI))*
01144 pow(M_E,-1*pow(dist-mean, 2.0)/(2.0*stdev*stdev));
01145
01146
01147 float aProb;
01148 if(fabs(dir) <= M_PI/2.0)
01149 aProb = (-fabs(dir)/(M_PI/2) + 1.0)/2.0;
01150 else
01151 aProb = ((fabs(dir) - M_PI)/(M_PI/2) + 1.0)/2.0;
01152
01153 return pOri[dOri] * dProb * aProb;
01154 }
01155 case NOSE:
01156 {
01157
01158 int dOri = int(round(4.0 * fabs(fmod(oD + M_PI/2.0, M_PI) - cA)/M_PI));
01159
01160
01161 float mean = 15.0; float stdev = 7.0;
01162 float dProb = 1.0/(stdev*sqrt(2*M_PI))*
01163 pow(M_E,-1*pow(dist-mean, 2.0)/(2.0*stdev*stdev));
01164
01165
01166 float nDir = fmod(fabs(dir),M_PI/2);
01167 float aProb = (-fabs(nDir-M_PI/4)/(M_PI/4) + 1.0)/4.0;
01168
01169 return pOri[dOri] * dProb * aProb;
01170 }
01171 case MOUTH:
01172 {
01173
01174 int dOri = int(round(4.0 * fabs(oD - cA)/M_PI));
01175
01176
01177 float mean = 30.0; float stdev = 8.0;
01178 float dProb = 1.0/(stdev*sqrt(2*M_PI))*
01179 pow(M_E,-1*pow(dist-mean,2.0)/(2.0*stdev*stdev));
01180
01181
01182 float nDir = fmod(fabs(dir),M_PI/2);
01183 float aProb = (-fabs(nDir-M_PI/4)/(M_PI/4) + 1.0)/4.0;
01184
01185 return pOri[dOri] * dProb * aProb;
01186 }
01187 }
01188
01189 case NOSE:
01190 switch(c)
01191 {
01192 case EYE: case L_EYE: case R_EYE:
01193 {
01194
01195 int dOri = int(round(4.0 * fabs(fmod(oD + M_PI/2.0, M_PI) - cA)/M_PI));
01196
01197
01198 float mean = 15.0; float stdev = 6.0;
01199 float dProb = 1.0/(stdev*sqrt(2*M_PI))*
01200 pow(M_E,-1*pow(dist-mean,2.0)/(2.0*stdev*stdev));
01201
01202
01203 float nDir = fmod(fabs(dir),M_PI/2);
01204 float aProb = (-fabs(nDir-M_PI/4)/(M_PI/4) + 1.0)/4.0;
01205
01206 return pOri[dOri] * dProb * aProb;
01207 }
01208 case NOSE:
01209 {
01210 return 0.0;
01211 }
01212 case MOUTH:
01213 {
01214
01215 int dOri = int(round(4.0 * fabs(fmod(oD + M_PI/2.0, M_PI) - cA)/M_PI));
01216
01217
01218 float mean = 20.0; float stdev = 5.0;
01219 float dProb = 1.0/(stdev*sqrt(2*M_PI))*
01220 pow(M_E,-1*pow(dist-mean, 2.0)/(2.0*stdev*stdev));
01221
01222
01223 float nDir = fabs(dir);
01224 float aProb = (-fabs(nDir-M_PI/2)/(M_PI/2) + 1.0)/2.0;
01225
01226 return pOri[dOri] * dProb * aProb;
01227 }
01228 }
01229
01230 case MOUTH:
01231 switch(c)
01232 {
01233 case EYE: case L_EYE: case R_EYE:
01234 {
01235
01236 int dOri = int(round(4.0 * fabs(oD - cA)/M_PI));
01237
01238
01239 float mean = 30.0; float stdev = 6.0;
01240 float dProb = 1.0/(stdev*sqrt(2*M_PI))*
01241 pow(M_E,-1*pow(dist-mean, 2.0)/(2.0*stdev*stdev));
01242
01243
01244 float nDir = fmod(fabs(dir),M_PI/2);
01245 float aProb = (-fabs(nDir-M_PI/4)/(M_PI/4) + 1.0)/4.0;
01246
01247 return pOri[dOri] * dProb * aProb;
01248 }
01249 case NOSE:
01250 {
01251
01252 int dOri = int(round(4.0 * fabs(fmod(oD + M_PI/2.0, M_PI) - cA)/M_PI));
01253
01254
01255 float mean = 20.0; float stdev = 5.0;
01256 float dProb = 1.0/(stdev*sqrt(2*M_PI))*
01257 pow(M_E,-1*pow(dist-mean, 2.0)/(2.0*stdev*stdev));
01258
01259
01260 float nDir = fabs(dir);
01261 float aProb = (-fabs(nDir-M_PI/2)/(M_PI/2) + 1.0)/2.0;
01262
01263 return pOri[dOri] * dProb * aProb;
01264 }
01265 case MOUTH:
01266 {
01267 return 0.0;
01268 }
01269 }
01270 }
01271 return 0.0;
01272 }
01273
01274
01275 bool locateFace(Point2D<int> *attPt, float *dir, double *pProb[NUM_FACE_PART],
01276 int n)
01277 {
01278 if(n < 4) return false;
01279
01280
01281
01282
01283
01284
01285 int nE = 0, nM = 0, nN = 0;
01286 Point2D<int> pE[n], pM[n], pN[n];
01287 float dE[n], dM[n], dN[n];
01288
01289 for(int i = 2; i < n; i++)
01290 {
01291 if(pProb[i][EYE] > .10)
01292 { pE[nE] = attPt[i]; dE[nE] = dir[i]; nE++; }
01293
01294 if(pProb[i][MOUTH] > .10)
01295 { pM[nM] = attPt[i]; dM[nM] = dir[i]; nM++; }
01296
01297 if(pProb[i][NOSE] > .0005 && fabs(dir[i] - M_PI/2)<.01 )
01298 { pN[nN] = attPt[i]; dN[nN] = dir[i]; nN++; }
01299 }
01300
01301 printf("-+-+-+-(%d,%d,%d)\n",nE,nM,nN);
01302
01303 for(int i = 0; i < nE-1; i++)
01304 for(int i2 = i+1; i2 < nE; i2++)
01305 for(int j = 0; j < nM; j++)
01306 for(int k = 0; k < nN; k++)
01307 {
01308
01309 float ee2 = getGeomRelProb(EYE, EYE , pE[i], dE[i], pE[i2], dE[i2]);
01310
01311
01312 float em = getGeomRelProb(EYE, MOUTH, pE[i], dE[i], pM[j], dM[j]);
01313
01314
01315 float en = getGeomRelProb(EYE, NOSE , pE[i], dE[i], pN[k], dN[k]);
01316
01317
01318 float nm = getGeomRelProb(NOSE, MOUTH, pN[k], dN[k], pM[j], dM[j]);
01319
01320 printf("[%d,%d,%d,%d] ee2: %f, en: %f em: %f nm: %f\n",
01321 i,i2,k,j,ee2,en,em,nm);
01322
01323
01324
01325
01326 if(ee2 > .001 && em > .001 && en >.002)
01327 {
01328 eyeP = pE[i]; eyeD = 0.0;
01329 eye2P = pE[i2]; eye2D = 0.0;
01330 mouthP = pM[j]; mouthD = 0.0;
01331 noseP = pN[k]; noseD = dN[k];
01332 return true;
01333 }
01334 }
01335 return false;
01336 }
01337
01338
01339 void drawFace (Image<float>& img)
01340 {
01341 inplaceNormalize(img, 0.0f, 128.0f);
01342
01343
01344 drawCircle(img, eyeP , 2, 255.0f, 1);
01345 Point2D<int> ePt(int(5*cos(eyeD)),int(5*sin(eyeD)));
01346 drawLine(img, eyeP - ePt, eyeP + ePt, 255.0f, 1);
01347 drawCircle(img, eye2P, 2, 255.0f, 1);
01348 Point2D<int> e2Pt(int(5*cos(eye2D)),int(5*sin(eye2D)));
01349 drawLine(img, eye2P - e2Pt, eye2P + e2Pt, 255.0f, 1);
01350
01351
01352 Point2D<int> nPt(int(10*cos(noseD)),int(10*sin(noseD)));
01353 drawLine(img, noseP - nPt, noseP + nPt, 255.0f, 1);
01354
01355
01356 drawCircle(img, mouthP , 5, 255.0f, 1);
01357 Point2D<int> mPt(int(8*cos(mouthD)),int(8*sin(mouthD)));
01358 drawLine(img, mouthP - mPt, mouthP + mPt, 255.0f, 1);
01359
01360
01361
01362 }
01363
01364
01365
01366 Image<float> normalize(Image<float> img)
01367 {
01368 Image<float> tImg = img;
01369 float tMean = float(mean(img));
01370 float tStdev = float(stdev(img));
01371 tImg -= tMean;
01372 tImg /= tStdev;
01373
01374 return tImg;
01375 }
01376
01377
01378
01379 void setupFFTW(Image<float> img)
01380 {
01381 int w = img.getWidth(), h = img.getHeight();
01382
01383 fftw = new FFTWWrapper(w,h);
01384 input = new double[w*h];
01385 fftw->init(input);
01386
01387
01388 outFftw = new double*[h];
01389 for(int i = 0; i < h; i++) outFftw[i] = new double[w/2+1];
01390
01391
01392 setupGaborMask(img);
01393 }
01394
01395
01396 void setupGaborMask(Image<float> img)
01397 {
01398
01399 int w = img.getWidth(), h = img.getHeight();
01400 int dim = (w<h)?w:h;
01401 float stdev = float(floor((dim - 3.0)/2.0/sqrt(10.0)));
01402 float period = float(stdev * 2.0);
01403
01404
01405 gaborMask = new double***[NUM_G_LEV];
01406 for(int i = 0; i < NUM_G_LEV; i++)
01407 gaborMask[i] = new double**[NUM_G_DIR];
01408
01409
01410
01411
01412
01413
01414 float scale = 1.0;
01415 for(int i = 0; i < NUM_G_LEV; i++)
01416 {
01417 for(int j = 0; j < NUM_G_DIR; j++)
01418 {
01419
01420 Image<float> gaborF = gaborFilter<float>(stdev/scale,period/scale,0,
01421 (j*180.0)/NUM_G_DIR);
01422 Image<float> temp (img.getDims(), ZEROS);
01423 inplacePaste(temp, gaborF, Point2D<int>(0,0));
01424
01425
01426 gaborMask[i][j] = new double*[h];
01427 for(int k = 0; k < h; k++)
01428 gaborMask[i][j][k] = new double[w/2+1];
01429
01430
01431 fftCompute(temp, gaborMask[i][j]);
01432 gaborMaskImg[i][j] = getFftImage(gaborMask[i][j], w, h);
01433
01434
01435
01436
01437
01438
01439 }
01440 scale *= 2;
01441 }
01442 }
01443
01444
01445
01446 void fftCompute(Image<float> img, double **outFft)
01447 {
01448 int w = img.getWidth(), h = img.getHeight();
01449
01450 iptr = input;
01451 for(int j = 0; j < h; j++)
01452 for(int i = 0; i < w; i++)
01453 *iptr++ = (double)img.getVal(i,j);
01454
01455 fftw->compute(outFft);
01456 }
01457
01458
01459 void getFeatureVector(double **outFft, Image<double> &res, int w, int h)
01460 {
01461 double sum = 0.0; int c = 0;
01462
01463
01464 for(int i = 0; i < NUM_G_LEV; i++)
01465 for(int j = 0; j < NUM_G_DIR; j++)
01466 {
01467
01468 sum = 0.0;
01469 for(int k = 0; k < h; k++)
01470 for(int l = 0; l < w/2+1; l++)
01471 sum += log(1.0 + gaborMask[i][j][k][l]) * log(1.0 + outFft[k][l]);
01472 res[c] = sum/(h*w/2+1);
01473 c++;
01474 }
01475 }
01476
01477
01478 void getFeatureVector2
01479 (nub::soft_ref<StdBrain> brain, Image<double> &vec, int w, int h)
01480 {
01481 LFATAL("fixme");
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529 }
01530
01531
01532 int* getPrimeLev(Image<float> img)
01533 {
01534
01535 int w = img.getWidth(), h = img.getHeight();
01536
01537
01538 fftCompute(img, outFftw);
01539
01540
01541 getFeatureVector(outFftw, gft, w, h);
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553 Image<double> vout = ffn_pl->run3L(gft);
01554 float mVal; int m; double tLev[NUM_H_LEV];
01555 int* probLev = new int[NUM_H_LEV];
01556
01557 for(int i = 0; i < NUM_H_LEV; i++)
01558 tLev[i] = vout[i];
01559
01560 for(int i = 0; i < NUM_H_LEV; i++)
01561 {
01562 mVal = tLev[0]; m = 0;
01563 for(int j = 1; j < NUM_H_LEV; j++)
01564 {
01565 if (mVal <= tLev[j])
01566 {
01567 mVal = tLev[j]; m = j;
01568 }
01569 }
01570 probLev[i] = m;
01571 tLev[m] = 0.0;
01572 }
01573
01574
01575 Image<float> ftImg = getFftImage(outFftw, w, h);
01576 float min,max; getMinMax(ftImg, min,max);
01577 printf("ftIMg: Min: %f, Max: %f\n",min,max);
01578 inplaceNormalize(ftImg, 0.0f, 255.0f);
01579 fftWin->drawImage(zoomXY(ftImg,1,-1),0,0);
01580 return probLev;
01581 }
01582
01583
01584 Image<float> getFftImage(double **outFft, int w, int h)
01585 {
01586
01587
01588
01589 float ln2 = log(2.0);
01590
01591
01592 float gc = 0.75;
01593
01594
01595 Image<float> ftImg; ftImg.resize(w,h);
01596 for(int i = 0; i < w/2; i++)
01597 for(int j = 0; j < h/2; j++)
01598 ftImg.setVal(i+w/2, h/2-j,
01599 pow(log(1.0 + outFft[j][i+1])/ln2, gc));
01600
01601 for(int i = 0; i < w/2; i++)
01602 for(int j = h/2; j < h; j++)
01603 ftImg.setVal(i+w/2, 3*h/2-1-j,
01604 pow(log(1.0 + outFft[j][i+1])/ln2, gc));
01605
01606 for(int i = 0; i < w/2; i++)
01607 for(int j = 0; j < h; j++)
01608 ftImg.setVal(i, j, ftImg.getVal(w-1-i, h-1-j));
01609 return ftImg;
01610 }
01611
01612
01613
01614 void freeFftwData(Image<float> img)
01615 {
01616 int h = img.getHeight();
01617
01618 free(input);
01619
01620 for(int i = 0; i < h; i++) free(outFftw[i]);
01621 free(outFftw);
01622
01623 for(int i = 0; i < NUM_G_LEV; i++)
01624 for(int j = 0; j < NUM_G_DIR; j++)
01625 for(int k = 0; k < h; k++)
01626 free(gaborMask[i][j][k]);
01627 for(int i = 0; i < NUM_G_LEV; i++)
01628 for(int j = 0; j < NUM_G_DIR; j++)
01629 free(gaborMask[i][j]);
01630 for(int i = 0; i < NUM_G_LEV; i++) free(gaborMask[i]);
01631 free(gaborMask);
01632 }
01633
01634
01635 XWinManaged *xwi[2][4]; int xwiC = 0;
01636 void getFacePartProb(Point2D<int> p, float ang, double *pPart)
01637 {
01638 ang = 0.0;
01639
01640
01641 Image<float> **gImg = new Image<float>*[2];
01642 for(int i = 0; i < 2; i++) gImg[i] = new Image<float>[NUM_DIR];
01643
01644
01645
01646
01647 int w = 2+MODEL_NOSE_DIAGONAL, h = 2+MODEL_NOSE_DIAGONAL;
01648
01649
01650 Rectangle r = getWindow(pyrImg[primeLev], p, w);
01651 Rectangle r2 =
01652 Rectangle::tlbrI(r.top()/2 , r.left()/2 ,
01653 r.top()/2+r.height()/2-1, r.left()/2+r.width()/2-1);
01654
01655
01656 if(r.width() < w || r.height() < h || r2.width() < w/2 || r2.height() < h/2)
01657 {
01658 int ph = r.left() - p.i + w/2;
01659 int pv = r.top() - p.j + h/2;
01660 int ph2 = r2.left() - p.i/2 + w/4;
01661 int pv2 = r2.top() - p.j/2 + h/4;
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672 for(int i = 0; i < NUM_DIR; i++)
01673 {
01674 gImg[0][i].resize(w, h, true);
01675 for(int j = ph; j < ph + r.width(); j++)
01676 for(int k = pv; k < pv + r.height(); k++)
01677 gImg[0][i].setVal(j,k,
01678 currGaPyr[i][primeLev].getVal(r.left()+j-ph, r.top()+k-pv));
01679
01680 gImg[1][i].resize(w/2, h/2, true);
01681 for(int j = ph2; j < ph2 + r2.width(); j++)
01682 for(int k = pv2; k < pv2 + r2.height(); k++)
01683 gImg[1][i].setVal(j,k,
01684 currGaPyr[i][primeLev+1].getVal(r2.left()+j-ph2, r2.top()+k-pv2));
01685 }
01686 }
01687
01688 else
01689 for(int i = 0; i < NUM_DIR; i++)
01690 {
01691 gImg[0][i] = crop(currGaPyr[i][primeLev ], r );
01692 gImg[1][i] = crop(currGaPyr[i][primeLev+1], r2);
01693 }
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752 int a = int(4*ang/M_PI);
01753 float cAng = ((4-a)%4)*M_PI/4.0;
01754
01755 correctGabors(gImg,cAng);
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766 Image<double> eFeat(1, RE_INPUT + 1, NO_INIT);
01767 Rectangle er =
01768 Rectangle::tlbrI (h/2 - MODEL_EYE_HEIGHT/2, w/2 - MODEL_EYE_WIDTH/2,
01769 h/2 + MODEL_EYE_HEIGHT/2 - 1, w/2 + MODEL_EYE_WIDTH/2 - 1);
01770 Rectangle er2 =
01771 Rectangle::tlbrI(er.top()/2 , er.left()/2 ,
01772 er.top()/2+er.height()/2-1, er.left()/2+er.width()/2-1);
01773
01774
01775 Image<float> **eImg = new Image<float>*[2];
01776 for(int i = 0; i < 2; i++) eImg[i] = new Image<float>[NUM_DIR];
01777 for(int j = 0; j < NUM_DIR; j++)
01778 {
01779 eImg[0][j] = crop(gImg[0][j], er );
01780 eImg[1][j] = crop(gImg[1][j], er2);
01781 }
01782 getEyeFeature(eImg, eFeat);
01783 Image<double> evout = ffn_e->run3L(eFeat);
01784 pPart[EYE] = evout[0];
01785
01786
01787 Image<double> mFeat(1, M_INPUT + 1, NO_INIT);
01788 Rectangle mr =
01789 Rectangle::tlbrI(h/2 - MODEL_MOUTH_HEIGHT/2, w/2 - MODEL_MOUTH_WIDTH/2,
01790 h/2 + MODEL_MOUTH_HEIGHT/2 - 1, w/2 + MODEL_MOUTH_WIDTH/2 - 1);
01791 Rectangle mr2 =
01792 Rectangle::tlbrI(mr.top()/2 , mr.left()/2 ,
01793 mr.top()/2+mr.height()/2-1, mr.left()/2+mr.width()/2-1);
01794
01795
01796 Image<float> **mImg = new Image<float>*[2];
01797 for(int i = 0; i < 2; i++) mImg[i] = new Image<float>[NUM_DIR];
01798 for(int j = 0; j < NUM_DIR; j++)
01799 {
01800 mImg[0][j] = crop(gImg[0][j], mr );
01801 mImg[1][j] = crop(gImg[1][j], mr2);
01802 }
01803 getMouthFeature(mImg, mFeat);
01804 Image<double> mvout =ffn_m->run3L(mFeat);
01805 pPart[MOUTH] = mvout[0];
01806
01807
01808
01809
01810 correctGabors(gImg,M_PI/2.0);
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822 Image<double> nFeat(1, N_INPUT + 1, NO_INIT);
01823 Rectangle nr =
01824 Rectangle::tlbrI(h/2 - MODEL_NOSE_HEIGHT/2, w/2 - MODEL_NOSE_WIDTH/2,
01825 h/2 + MODEL_NOSE_HEIGHT/2 - 1, w/2 + MODEL_NOSE_WIDTH/2 - 1);
01826 Rectangle nr2 =
01827 Rectangle::tlbrI(nr.top()/2 , nr.left()/2 ,
01828 nr.top()/2+nr.height()/2-1, nr.left()/2+nr.width()/2-1);
01829
01830
01831
01832
01833
01834
01835
01836
01837 Image<float> **nImg = new Image<float>*[2];
01838 for(int i = 0; i < 2; i++) nImg[i] = new Image<float>[NUM_DIR];
01839 for(int j = 0; j < NUM_DIR; j++)
01840 {
01841 nImg[0][j] = crop(gImg[0][j], nr );
01842 nImg[1][j] = crop(gImg[1][j], nr2);
01843 }
01844
01845
01846
01847
01848 getNoseFeature(nImg, nFeat);
01849 Image<double> nvout = ffn_n->run3L(nFeat);
01850 pPart[NOSE] = nvout[0];
01851
01852
01853
01854 correctGabors(gImg,M_PI/2.0);
01855 correctGabors(gImg,M_PI/2.0);
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865 for(int j = 0; j < NUM_DIR; j++)
01866 {
01867 nImg[0][j] = crop(gImg[0][j], nr );
01868 nImg[1][j] = crop(gImg[1][j], nr2);
01869 }
01870 getNoseFeature(nImg, nFeat);
01871 Image<double> n2vout = ffn_n->run3L(nFeat);
01872 if(pPart[NOSE] < n2vout[0])
01873 pPart[NOSE] = n2vout[0];
01874
01875
01876
01877 }
01878
01879
01880
01881 Rectangle getWindow(Image<float> img, Point2D<int> p, int s)
01882 {
01883 int w = img.getWidth(), h = img.getHeight();
01884
01885 int t = (p.j - s/2 < 0 )? 0 : p.j - s/2;
01886 int l = (p.i - s/2 < 0 )? 0 : p.i - s/2;
01887 int b = (p.j + s/2 - 1 > h - 1)? h - 1 : p.j + s/2 - 1;
01888 int r = (p.i + s/2 - 1 > w - 1)? w - 1 : p.i + s/2 - 1;
01889
01890 return Rectangle::tlbrI(t,l,b,r);
01891 }
01892
01893
01894 XWinManaged *xwCG[2][4];
01895 void correctGabors(Image<float> **gImg, float ang)
01896 {
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908 for(int j = 0; j < NUM_DIR; j++)
01909 {
01910 gImg[0][j] = rotate(gImg[0][j], MODEL_NOSE_DIAGONAL/2+1,
01911 MODEL_NOSE_DIAGONAL/2+1 , ang);
01912 gImg[1][j] = rotate(gImg[1][j], (MODEL_NOSE_DIAGONAL/2+1)/2,
01913 (MODEL_NOSE_DIAGONAL/2+1)/2, ang);
01914 }
01915
01916
01917
01918
01919
01920
01921 Image<float> tG[2][4];
01922 for (int i = 0; i< 2; i++)
01923 for (int j = 0; j< 4; j++)
01924 tG[i][j] = gImg[i][j];
01925
01926 int i = int(round(ang*4/M_PI));
01927 for(int j = 0; j < NUM_DIR; j++)
01928 {
01929 gImg[0][j] = tG[0][(i+j)%4];
01930 gImg[1][j] = tG[1][(i+j)%4];
01931 }
01932
01933
01934
01935
01936
01937
01938 }
01939
01940
01941
01942 void getFacePartFeatures(Rectangle r, FacePart part, Image<double> &features)
01943 {
01944 switch(part)
01945 {
01946 case EYE: getEyeFeature (r, features); break;
01947 case NOSE: getNoseFeature (r, features); break;
01948 case MOUTH: getMouthFeature(r, features); break;
01949 default:
01950 LFATAL("Unknown face part");
01951 }
01952 }
01953
01954
01955 void getEyeFeature(Rectangle r, Image<double> &features)
01956 {
01957
01958 Image<float> **img = new Image<float>*[2];
01959 for(int i = 0; i < 2; i++) img[i] = new Image<float>[NUM_DIR];
01960
01961 Rectangle r2 =
01962 Rectangle::tlbrI(r.top()/2 , r.left()/2 ,
01963 r.top()/2+r.height()/2-1, r.left()/2+r.width()/2-1 );
01964
01965
01966 for(int j = 0; j < NUM_DIR; j++)
01967 img[0][j] = crop(currGaPyr[j][primeLev ], r );
01968 for(int j = 0; j < NUM_DIR; j++)
01969 img[1][j] = crop(currGaPyr[j][primeLev+1], r2);
01970 getEyeFeature(img, features);
01971 }
01972
01973
01974 void getEyeFeature(Image<float> **img, Image<double> &features)
01975 {
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989 int totalF1 = 24;
01990 int xF1[24] = { 4, 5, 6, 7, 4, 5, 6, 7, 0, 3, 8,11,
01991 0, 3, 8,11, 0, 3, 8,11, 0, 3, 8,11 };
01992 int yF1[24] = { 0, 0, 0, 0, 5, 5, 5, 5, 1, 1, 1, 1,
01993 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 };
01994
01995
01996
01997
01998
01999
02000
02001 int totalF2 = 8;
02002 int xF2[8] = { 2, 3, 0, 2, 3, 5, 2, 3 };
02003 int yF2[8] = { 0, 0, 1, 1, 1, 1, 2, 2 };
02004
02005 int k = 0;
02006
02007 for(int n = 0; n < NUM_DIR; n++)
02008 {
02009 for(int i = 0; i< totalF1; i++)
02010 {
02011 features[k] = double(img[0][n].getVal(xF1[i], yF1[i]));
02012 k++;
02013 }
02014
02015 for(int i = 0; i< totalF2; i++)
02016 {
02017 features[k] = double(img[1][n].getVal(xF2[i], yF2[i]));
02018 k++;
02019 }
02020 }
02021 }
02022
02023
02024 void getNoseFeature(Rectangle r, Image<double> &features)
02025 {
02026
02027 Image<float> **img = new Image<float>*[2];
02028 for(int i = 0; i < 2; i++) img[i] = new Image<float>[NUM_DIR];
02029
02030 Rectangle r2 =
02031 Rectangle::tlbrI(r.top()/2 , r.left()/2 ,
02032 r.top()/2+r.height()/2-1, r.left()/2+r.width()/2-1 );
02033
02034
02035 for(int j = 0; j < NUM_DIR; j++)
02036 img[0][j] = crop(currGaPyr[j][primeLev ], r );
02037 for(int j = 0; j < NUM_DIR; j++)
02038 img[1][j] = crop(currGaPyr[j][primeLev+1], r2);
02039 getNoseFeature(img, features);
02040 }
02041
02042
02043 void getNoseFeature(Image<float> **img, Image<double> &features)
02044 {
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073 int totalF1 = 44;
02074 int xF1[44] = { 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7, 6, 7,
02075 3, 4, 5, 6, 7, 8, 9,10, 3,10, 3,10, 3,10, 3,10, 3, 4, 5, 6,
02076 7, 8, 9,10 };
02077 int yF1[44] = { 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,10,10,11,11,
02078 12,12,12,12,12,12,12,12,13,13,14,14,15,15,16,16,17,17,17,17,
02079 17,17,17,17 };
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094 int totalF2 = 17;
02095 int xF2[17] = { 3, 3, 3, 3, 3, 1, 2, 3, 4, 5, 1, 5, 1, 2, 3, 4, 5 };
02096 int yF2[17] = { 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 7, 7, 8, 8, 8, 8, 8 };
02097
02098 int k = 0;
02099
02100
02101 for(int n = 0; n < NUM_DIR; n++)
02102 {
02103 for(int i = 0; i< totalF1; i++)
02104 {
02105 features[k] = double(img[0][n].getVal(xF1[i], yF1[i]));
02106 k++;
02107 }
02108
02109 for(int i = 0; i< totalF2; i++)
02110 {
02111 features[k] = double(img[1][n].getVal(xF2[i], yF2[i]));
02112 k++;
02113 }
02114 }
02115 }
02116
02117
02118 void getMouthFeature(Rectangle r, Image<double> &features)
02119 {
02120
02121 Image<float> **img = new Image<float>*[2];
02122 for(int i = 0; i < 2; i++) img[i] = new Image<float>[NUM_DIR];
02123
02124 Rectangle r2 =
02125 Rectangle::tlbrI(r.top()/2 , r.left()/2 ,
02126 r.top()/2+r.height()/2-1, r.left()/2+r.width()/2-1 );
02127
02128
02129 for(int j = 0; j < NUM_DIR; j++)
02130 img[0][j] = crop(currGaPyr[j][primeLev ], r );
02131 for(int j = 0; j < NUM_DIR; j++)
02132 img[1][j] = crop(currGaPyr[j][primeLev+1], r2);
02133 getMouthFeature(img, features);
02134 }
02135
02136
02137 void getMouthFeature(Image<float> **img, Image<double> &features)
02138 {
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156 int totalF1 = 32;
02157 int xF1[32] = { 2, 7, 8, 9,10,11,12,17, 2, 9,10,17, 2, 9,10,17,
02158 2, 9,10,17, 2, 9,10,17, 2, 7, 8, 9,10,11,12,17 };
02159 int yF1[32] = { 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
02160 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7 };
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170 int totalF2 = 16;
02171 int xF2[16] = { 1, 3, 4, 5, 6, 8, 1, 4, 5, 8, 1, 3, 4, 5, 6, 8 };
02172 int yF2[16] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3 };
02173
02174 int k = 0;
02175
02176
02177 for(int n = 0; n < NUM_DIR; n++)
02178 {
02179 for(int i = 0; i< totalF1; i++)
02180 {
02181 features[k] = double(img[0][n].getVal(xF1[i], yF1[i]));
02182 k++;
02183 }
02184
02185 for(int i = 0; i< totalF2; i++)
02186 {
02187 features[k] = double(img[1][n].getVal(xF2[i], yF2[i]));
02188 k++;
02189 }
02190 }
02191 }
02192
02193
02194 XWinManaged *partWin;
02195 int start = 0;
02196 void displayPartImage(Image<float> img, Rectangle pr)
02197 {
02198
02199 if(start == 0)
02200 {
02201 partWin = new XWinManaged(img.getDims(),1000,700,"Image"); wList.add(*partWin);
02202 start = 1;
02203 }
02204
02205 drawRect(img, pr, 255.0f, 1);
02206 partWin->drawImage(img,0,0);
02207 Raster::waitForKey();
02208 }
02209
02210
02211
02212 void printRegion(Image<float> img,int sX,int eX,int dX, int sY,int eY, int dY)
02213 {
02214 for(int j = sY; j<=eY; j+=dY)
02215 {
02216 for(int i = sX; i<=eX; i+=dX)
02217 printf("%8.3f ", img.getVal(i,j));
02218 printf(" \n");
02219 }
02220 printf("\n");
02221 }
02222
02223
02224
02225
02226
02227