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 #include <stdio.h>
00039 #include <stdlib.h>
00040
00041 #include "Robots/Beobot2/Navigation/FOE_Navigation/MiddleTemporal.H"
00042
00043 #include <cstdio>
00044 #include "Image/ColorOps.H"
00045 #include "Image/CutPaste.H"
00046 #include "Image/DrawOps.H"
00047 #include "Image/FilterOps.H"
00048 #include "Image/MathOps.H"
00049 #include "Image/Pixels.H"
00050 #include "Image/ShapeOps.H"
00051 #include "Image/SimpleFont.H"
00052
00053 #include "Util/Timer.H"
00054
00055
00056
00057
00058
00059 MiddleTemporal::MiddleTemporal()
00060 {
00061 itsWin.reset();
00062 }
00063
00064
00065 MiddleTemporal::~MiddleTemporal()
00066 { }
00067
00068
00069 std::vector<Image<float> > MiddleTemporal::getMTfeatures()
00070 {
00071 return itsMTfeatures;
00072 }
00073
00074
00075 std::vector<Image<float> > MiddleTemporal::getMToptimalShift()
00076 {
00077 return itsMToptimalShift;
00078 }
00079
00080
00081 void MiddleTemporal::computeMTfeatures
00082 (std::vector<std::vector<ImageSet<float> > > rawSpatioTemporalEnergy)
00083 {
00084 if(rawSpatioTemporalEnergy[0][0].size() == 0) return;
00085 itsRawSpatioTemporalEnergy = rawSpatioTemporalEnergy;
00086 reset();
00087
00088
00089
00090 for (uint i = 0; i < itsNumDirs; i++)
00091 {
00092
00093 computeMaxSpeed(i);
00094
00095
00096 }
00097
00098
00099
00100
00101
00102 computeSteMaxVals();
00103
00104
00105
00106
00107
00108
00109
00110
00111 normalizeOnMaxVal();
00112
00113
00114
00115
00116
00117
00118
00119 computeDirSteMaxVals();
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 computeOpponencies();
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 weighMTfeaturesForDominance();
00144
00145
00146 findMaxMotionVals();
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 }
00158
00159
00160 void MiddleTemporal::reset()
00161 {
00162 itsNumDirs = itsRawSpatioTemporalEnergy.size();
00163 itsNumSpeeds = itsRawSpatioTemporalEnergy[0].size();
00164 itsNumPyrLevels = itsRawSpatioTemporalEnergy[0][0].size();
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 itsSpatioTemporalEnergy.resize(itsNumDirs);
00177 itsSpatioTemporalEnergyOptimalShift.resize(itsNumDirs);
00178 for(uint i = 0; i < itsNumDirs; i++)
00179 itsSpatioTemporalEnergyOptimalShift[i].reset(itsNumPyrLevels);
00180
00181 itsMTfeatures.resize(itsNumDirs);
00182 itsMToptimalShift.resize(itsNumDirs);
00183 }
00184
00185
00186
00187 void MiddleTemporal::computeMaxSpeed(uint index)
00188 {
00189 int depth = itsRawSpatioTemporalEnergy[index][0].size();
00190 if(depth == 0) return;
00191 ImageSet<float> result(depth);
00192
00193
00194 for (int scale = 0; scale < depth; scale++)
00195 result[scale] = computeMaxSpeed(index, scale);
00196
00197 itsSpatioTemporalEnergy[index] = result;
00198 }
00199
00200
00201 Image<float> MiddleTemporal::computeMaxSpeed(uint index, int scale)
00202 {
00203
00204
00205
00206 uint width = itsRawSpatioTemporalEnergy[index][0][scale].getWidth();
00207 uint height = itsRawSpatioTemporalEnergy[index][0][scale].getHeight();
00208 Image<float> result(width, height, ZEROS);
00209
00210 itsSpatioTemporalEnergyOptimalShift[index][scale] =
00211 Image<float>(width, height, ZEROS);
00212
00213 Image<float>::iterator resultT = result.beginw();
00214
00215 Image<float>::iterator
00216 shiftT = itsSpatioTemporalEnergyOptimalShift[index][scale].beginw();
00217
00218 Image<float>::iterator resT[itsNumSpeeds];
00219 for (unsigned int i = 0; i < itsNumSpeeds; i++)
00220 resT[i] = itsRawSpatioTemporalEnergy[index][i][scale].beginw();
00221
00222 for(uint i = 0; i < width; i++)
00223 {
00224 for(uint j = 0; j < height; j++)
00225 {
00226 float max = 0.0; float optShift = 0.0;
00227 for(uint r = 0; r < itsNumSpeeds; r++)
00228 {
00229 float val = *resT[r]++;
00230 if(max < val)
00231 {
00232 max = val;
00233 optShift = pow(2.0,r);
00234 }
00235 }
00236 *resultT++ = max;
00237 *shiftT++ = optShift;
00238 }
00239 }
00240
00241 return result;
00242 }
00243
00244
00245 void MiddleTemporal::computeSteMaxVals()
00246 {
00247 itsSteMaxVals.reset(itsNumPyrLevels);
00248
00249
00250
00251
00252 uint width = itsSpatioTemporalEnergy[0][0].getWidth();
00253 uint height = itsSpatioTemporalEnergy[0][0].getHeight();
00254
00255
00256 for(uint l = 0; l < itsNumPyrLevels; l++)
00257 {
00258 uint pxSize = uint(pow(2.0, l));
00259 uint lwidth = width/pxSize;
00260 uint lheight = height/pxSize;
00261
00262
00263
00264 uint steps = 1;
00265 if(pxSize < MAX_NEIGHBORHOOD)
00266 steps = MAX_NEIGHBORHOOD/pxSize;
00267
00268
00269 itsSteMaxVals[l] = Image<float>(lwidth/steps, lheight/steps, NO_INIT);
00270
00271
00272
00273
00274
00275
00276
00277 for(uint i = 0; i < lwidth; i+= steps)
00278 {
00279 for(uint j = 0; j < lheight; j+= steps)
00280 {
00281
00282 float max = 0.0;
00283 for(uint d = 0; d < itsNumDirs; d++)
00284 {
00285
00286 for(uint di = 0; di < steps; di++)
00287 {
00288 for(uint dj = 0; dj < steps; dj++)
00289 {
00290 float val =
00291 itsSpatioTemporalEnergy[d][l].getVal(i+di,j+dj);
00292 if(val > max) max = val;
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 }
00308 }
00309
00310 }
00311 itsSteMaxVals[l].setVal(i/steps, j/steps, max);
00312 }
00313 }
00314 }
00315 }
00316
00317
00318 void MiddleTemporal::computeDirSteMaxVals()
00319 {
00320
00321 itsDirSteMaxVals.resize(itsNumDirs);
00322 for(uint i = 0; i < itsNumDirs; i++)
00323 itsDirSteMaxVals[i].reset(itsNumPyrLevels);
00324
00325 uint width = itsSpatioTemporalEnergy[0][0].getWidth();
00326 uint height = itsSpatioTemporalEnergy[0][0].getHeight();
00327
00328
00329 for(uint l = 0; l < itsNumPyrLevels; l++)
00330 {
00331 uint pxSize = uint(pow(2.0, l));
00332 uint lwidth = width/pxSize;
00333 uint lheight = height/pxSize;
00334
00335
00336
00337 uint steps = 1;
00338 if(pxSize < MAX_NEIGHBORHOOD)
00339 steps = MAX_NEIGHBORHOOD/pxSize;
00340
00341
00342
00343 for(uint dir = 0; dir < itsNumDirs; dir++)
00344 itsDirSteMaxVals[dir][l] =
00345 Image<float>(lwidth/steps, lheight/steps, NO_INIT);
00346
00347
00348
00349
00350 for(uint i = 0; i < lwidth; i+= steps)
00351 {
00352 for(uint j = 0; j < lheight; j+= steps)
00353 {
00354
00355
00356 for(uint d = 0; d < itsNumDirs; d++)
00357 {
00358 float dirMax = 0.0;
00359 for(uint di = 0; di < steps; di++)
00360 {
00361 for(uint dj = 0; dj < steps; dj++)
00362 {
00363 float val =
00364 itsSpatioTemporalEnergy[d][l].getVal(i+di,j+dj);
00365
00366 if(val > dirMax) dirMax = val;
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 }
00381 }
00382 itsDirSteMaxVals[d][l].setVal(i/steps, j/steps, dirMax);
00383 }
00384
00385 }
00386 }
00387 }
00388 }
00389
00390
00391
00392 void MiddleTemporal::normalizeOnMaxVal()
00393 {
00394 uint width = itsSpatioTemporalEnergy[0][0].getWidth();
00395 uint height = itsSpatioTemporalEnergy[0][0].getHeight();
00396
00397
00398 for(uint l = 0; l < itsNumPyrLevels; l++)
00399 {
00400 uint pxSize = uint(pow(2.0, l));
00401 uint lwidth = width/pxSize;
00402 uint lheight = height/pxSize;
00403
00404 uint steps = 1;
00405 if(pxSize < MAX_NEIGHBORHOOD) steps = MAX_NEIGHBORHOOD/pxSize;
00406 for(uint i = 0; i < lwidth; i+= steps)
00407 {
00408 for(uint j = 0; j < lheight; j+= steps)
00409 {
00410 uint mi = i/steps;
00411 uint mj = j/steps;
00412
00413 uint lm = 0; if(mi > 2) lm = mi - 3;
00414 uint rm = lwidth/steps-1; if(mi < lwidth/steps-4) rm = mi + 3;
00415 uint tm = 0; if(mj > 2) tm = mj - 3;
00416 uint bm = lheight/steps-1; if(mj < lheight/steps-4)bm = mj + 3;
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430 float max = 0.0;
00431 for(uint bi = lm; bi <= rm; bi++)
00432 {
00433 for(uint bj = tm; bj <= bm; bj++)
00434 {
00435 float val = itsSteMaxVals[l].getVal(bi, bj);
00436 if(max < val) max = val;
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 }
00451 }
00452
00453
00454 for(uint d = 0; d < itsNumDirs; d++)
00455 {
00456 for(uint di = 0; di < steps; di++)
00457 {
00458 for(uint dj = 0; dj < steps; dj++)
00459 {
00460 float val = itsSpatioTemporalEnergy[d][l].getVal(i+di,j+dj);
00461
00462 if(max == 0.0)
00463 itsSpatioTemporalEnergy[d][l].setVal(i+di,j+dj, 0.0);
00464 else
00465 itsSpatioTemporalEnergy[d][l].setVal(i+di,j+dj, val/max);
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 }
00485 }
00486 }
00487 }
00488 }
00489 }
00490 }
00491
00492
00493 void MiddleTemporal::computeOpponencies()
00494 {
00495
00496 std::vector <ImageSet<float> > osInhibitMap(itsNumDirs);
00497 std::vector <ImageSet<float> > nInhibitMap(itsNumDirs);
00498 for (uint i = 0; i < itsNumDirs; i++)
00499 {
00500 osInhibitMap[i].reset(itsSpatioTemporalEnergy[i].size());
00501
00502 for(uint j = 0; j < itsSpatioTemporalEnergy[i].size(); j++)
00503 {
00504 osInhibitMap[i][j] = getOnSpotInhibitSpatioTemporalEnergy(i,j);
00505
00506 }
00507 }
00508
00509
00510 for (uint i = 0; i < itsNumDirs; i++)
00511 {
00512 for(uint j = 0; j < itsSpatioTemporalEnergy[i].size(); j++)
00513 {
00514 itsSpatioTemporalEnergy[i][j] -= osInhibitMap[i][j];
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 float mn,mx; getMinMax(itsSpatioTemporalEnergy[i][j],mn,mx);
00526 inplaceClamp(itsSpatioTemporalEnergy[i][j], 0.0f, mx);
00527 }
00528 }
00529
00530
00531
00532
00533 }
00534
00535
00536 void MiddleTemporal::weighMTfeaturesForDominance()
00537 {
00538
00539 }
00540
00541
00542 Image<float> MiddleTemporal::getOnSpotInhibitSpatioTemporalEnergy
00543 (uint dir, uint scale)
00544 {
00545 uint oppDir = (dir + itsNumDirs/2)%itsNumDirs;
00546
00547 uint width = itsSpatioTemporalEnergy[dir][scale].getWidth();
00548 uint height = itsSpatioTemporalEnergy[dir][scale].getHeight();
00549 uint pxSize = uint(pow(2.0, scale));
00550 uint steps = 1;
00551 if(pxSize < MAX_NEIGHBORHOOD) steps = MAX_NEIGHBORHOOD/pxSize;
00552 uint nwidth = width/steps;
00553 uint nheight = height/steps;
00554
00555
00556 Image<float> result(width,height,NO_INIT);
00557 Image<float>::iterator resultT = result.beginw();
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 for(uint j = 0; j < height; j++)
00568 {
00569 for(uint i = 0; i < width; i++)
00570 {
00571 float sum = 0.0;
00572 float opp = 0.0;
00573 for (uint k = 0; k < itsNumDirs; k++)
00574 {
00575
00576
00577
00578
00579
00580
00581 uint mi = i/steps;
00582 uint mj = j/steps;
00583
00584 uint lm = 0; if(mi > 0) lm = mi - 1;
00585 uint rm = nwidth-1; if(mi < nwidth-2) rm = mi + 1;
00586 uint tm = 0; if(mj > 0) tm = mj - 1;
00587 uint bm = nheight-1; if(mj < nheight-2)bm = mj + 1;
00588
00589
00590
00591
00592
00593
00594
00595
00596 float nmax = 0.0;
00597 for(uint bi = lm; bi <= rm; bi++)
00598 {
00599 for(uint bj = tm; bj <= bm; bj++)
00600 {
00601 float nval = itsDirSteMaxVals[k][scale].getVal(bi, bj);
00602 if(nmax < nval) nmax = nval;
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612 }
00613 }
00614
00615 float tval = nmax;
00616
00617
00618
00619 if(k != dir) sum += tval;
00620
00621
00622
00623 if(k == oppDir) opp = tval;
00624
00625
00626 }
00627 sum /= (itsNumDirs-2.0);
00628
00629
00630
00631
00632
00633 *resultT++ = opp;
00634 }
00635 }
00636
00637 return result;
00638 }
00639
00640
00641 Image<float> MiddleTemporal::getNeighborInhibitSpatioTemporalEnergy
00642 (uint dir, uint scale)
00643 {
00644 uint width = itsSpatioTemporalEnergy[dir][scale].getWidth();
00645 uint height = itsSpatioTemporalEnergy[dir][scale].getHeight();
00646 Image<float> result(width,height,ZEROS);
00647
00648 float cosAng = cos((2.0*M_PI * dir)/itsNumDirs);
00649 float sinAng = sin((2.0*M_PI * dir)/itsNumDirs);
00650
00651 Image<float>::iterator stT[itsNumDirs];
00652 for (unsigned int i=0; i < itsNumDirs; i++)
00653 stT[i] = itsSpatioTemporalEnergy[i][scale].beginw();
00654
00655
00656
00657
00658
00659
00660 std::vector<float> fweights(4);
00661 fweights[0] = .15;
00662 fweights[1] = .07;
00663 fweights[2] = .02;
00664 fweights[3] = .01;
00665
00666 std::vector<float> bweights(3);
00667 bweights[0] = .10;
00668 bweights[1] = .05;
00669 bweights[2] = .02;
00670
00671 for(uint j = 0; j < height; j++)
00672 {
00673 for(uint i = 0; i < width; i++)
00674 {
00675 float val = *stT[dir]++;
00676
00677 for(uint k = 0; k < fweights.size(); k++)
00678 {
00679 int ii = (i + (k+1.0)*cosAng);
00680 int jj = (j + (k+1.0)*sinAng);
00681
00682 if(ii > 0 && ii < int(width) &&
00683 jj > 0 && jj < int(height) )
00684 {
00685 float rval = result.getVal(ii,jj);
00686 result.setVal(ii,jj, rval + (fweights[k] * val));
00687 }
00688 }
00689 }
00690
00691
00692 }
00693 return result;
00694 }
00695
00696
00697 void MiddleTemporal::findMaxMotionVals()
00698 {
00699
00700
00701
00702
00703
00704 uint width = itsSpatioTemporalEnergy[0][0].getWidth();
00705 uint height = itsSpatioTemporalEnergy[0][0].getHeight();
00706
00707 uint mWidth = width/MAX_NEIGHBORHOOD;
00708 uint mHeight = height/MAX_NEIGHBORHOOD;
00709
00710
00711
00712 for(uint d = 0; d < itsNumDirs; d++)
00713 {
00714 Image<float> tMTfeatures (mWidth, mHeight, NO_INIT);
00715 Image<float>::iterator tmtT = tMTfeatures.beginw();
00716
00717 Image<float> tMToptimalShift (mWidth, mHeight, NO_INIT);
00718 Image<float>::iterator tmtosT = tMToptimalShift.beginw();
00719
00720 for(uint j = 0; j < mHeight; j++)
00721 {
00722 for(uint i = 0; i < mWidth; i++)
00723 {
00724
00725 float max = 0.0; float optShift = 0.0;
00726 for(uint l = 0; l < itsNumPyrLevels; l++)
00727 {
00728 uint pxSize = uint(pow(2.0, l));
00729 uint lwidth = width/pxSize;
00730 uint lheight = height/pxSize;
00731
00732 uint steps = 1;
00733 if(pxSize < MAX_NEIGHBORHOOD)
00734 steps = MAX_NEIGHBORHOOD/pxSize;
00735
00736
00737 uint ti = i * steps;
00738 uint tj = j * steps;
00739
00740
00741 uint lstep = ti; if(ti >= steps) lstep = ti - steps;
00742 uint rstep = ti; if(ti+steps < lwidth) rstep = ti + steps;
00743 uint tstep = tj; if(tj >= steps) tstep = tj - steps;
00744 uint bstep = tj; if(tj+steps < lheight) bstep = tj + steps;
00745
00746
00747 if(pxSize > MAX_NEIGHBORHOOD)
00748 {
00749
00750 uint div = pxSize/MAX_NEIGHBORHOOD;
00751
00752
00753 float val =
00754 itsSpatioTemporalEnergy[d][l].getVal(i/div,j/div);
00755 float shift =
00756 itsSpatioTemporalEnergyOptimalShift[d][l].getVal(i/div,j/div);
00757 if(max < val)
00758 {
00759 max = val;
00760 optShift = shift;
00761 }
00762 }
00763 else
00764 {
00765 for(uint di = lstep; di < rstep; di++)
00766 {
00767 for(uint dj = tstep; dj < bstep; dj++)
00768 {
00769
00770
00771 float val =
00772 itsSpatioTemporalEnergy[d][l].getVal(di, dj);
00773 float shift =
00774 itsSpatioTemporalEnergyOptimalShift[d][l].getVal(di, dj) * pxSize;
00775 if(max < val)
00776 {
00777 max = val;
00778 optShift = shift;
00779 }
00780 }
00781 }
00782 }
00783 }
00784
00785
00786
00787 *tmtT++ = max;
00788 *tmtosT++ = optShift;
00789 }
00790 }
00791 itsMTfeatures[d] = tMTfeatures;
00792 itsMToptimalShift[d] = tMToptimalShift;
00793 }
00794 }
00795
00796
00797 void MiddleTemporal::printItsSpatioTemporalEnergy
00798 (uint si, uint ei, uint sj, uint ej, bool stop, float div)
00799 {
00800 if(itsSpatioTemporalEnergy[0].size() == 0) return;
00801
00802
00803 for(uint k = 0; k < itsNumPyrLevels; k++)
00804 {
00805 uint step = uint(pow(2.0,k));
00806 for(uint i = 0; i < itsNumDirs; i++)
00807 {
00808 LINFO("itsSpatioTemporalEnergy features: dir: %d lev: %d", i, k);
00809
00810 for(uint y = sj/step; y < ej/step; y++)
00811 {
00812 for(uint x = si/step; x < ei/step; x++)
00813 printf("%8.3f ", itsSpatioTemporalEnergy[i][k].getVal(x,y)/div);
00814 printf("\n");
00815 }
00816 LINFO("\n");
00817
00818
00819
00820 if(stop) Raster::waitForKey();
00821 }
00822 }
00823 }
00824
00825
00826 void MiddleTemporal::displayItsSpatioTemporalEnergy()
00827 {
00828 if(itsSpatioTemporalEnergy[0].size() == 0) return;
00829 uint w = itsSpatioTemporalEnergy[0][0].getWidth();
00830 uint h = itsSpatioTemporalEnergy[0][0].getHeight();
00831 Image<float> disp(w*4, h*2,NO_INIT);
00832
00833 if(itsWin.is_invalid())
00834 itsWin.reset(new XWinManaged(Dims(w*4,h*2), w+10, 0, "FOE Detector"));
00835 else itsWin->setDims(Dims(w*4,h*2));
00836
00837 for(uint i = 0; i < itsNumPyrLevels; i++)
00838
00839 {
00840 LINFO("level: %d", i);
00841
00842 uint scale = uint(pow(2.0, i));
00843 inplacePaste(disp, zoomXY(itsSpatioTemporalEnergy[0][i], scale),
00844 Point2D<int>(0, 0));
00845 inplacePaste(disp, zoomXY(itsSpatioTemporalEnergy[1][i], scale),
00846 Point2D<int>(w, 0));
00847 inplacePaste(disp, zoomXY(itsSpatioTemporalEnergy[2][i], scale),
00848 Point2D<int>(2*w, 0));
00849 inplacePaste(disp, zoomXY(itsSpatioTemporalEnergy[3][i], scale),
00850 Point2D<int>(3*w, 0));
00851
00852 if(itsNumDirs > 4)
00853 {
00854 inplacePaste(disp, zoomXY(itsSpatioTemporalEnergy[4][i], scale),
00855 Point2D<int>(0, h));
00856 inplacePaste(disp, zoomXY(itsSpatioTemporalEnergy[5][i], scale),
00857 Point2D<int>(w, h));
00858 inplacePaste(disp, zoomXY(itsSpatioTemporalEnergy[6][i], scale),
00859 Point2D<int>(2*w, h));
00860 inplacePaste(disp, zoomXY(itsSpatioTemporalEnergy[7][i], scale),
00861 Point2D<int>(3*w, h));
00862 }
00863
00864 if(itsNumDirs > 8)
00865 {
00866 inplacePaste(disp, zoomXY(itsSpatioTemporalEnergy[8][i], scale),
00867 Point2D<int>(0, h));
00868 inplacePaste(disp, zoomXY(itsSpatioTemporalEnergy[9][i], scale),
00869 Point2D<int>(w/2, h));
00870 inplacePaste(disp, zoomXY(itsSpatioTemporalEnergy[10][i], scale),
00871 Point2D<int>(w, h));
00872 inplacePaste(disp, zoomXY(itsSpatioTemporalEnergy[11][i], scale),
00873 Point2D<int>(3*w/2, h));
00874 }
00875 itsWin->drawImage(disp,0,0);
00876 Raster::waitForKey();
00877 }
00878 }
00879
00880
00881 void MiddleTemporal::printItsMTfeatures
00882 (uint si, uint ei, uint sj, uint ej, bool stop)
00883 {
00884 if(itsSpatioTemporalEnergy[0].size() == 0) return;
00885
00886
00887 LINFO("MT features ");
00888 for(uint i = 0; i < itsNumDirs; i++)
00889 {
00890 for(uint y = sj; y < ej; y++)
00891 {
00892 for(uint x = si; x < ei; x++)
00893 printf("%7.3f ", itsMTfeatures[i].getVal(x,y));
00894 printf("\n");
00895 }
00896 LINFO("MT features: %d", i);
00897 if(stop)Raster::waitForKey();
00898 }
00899 }
00900
00901
00902 void MiddleTemporal::printItsMToptimalShift
00903 (uint si, uint ei, uint sj, uint ej, bool stop)
00904 {
00905 if(itsSpatioTemporalEnergy[0].size() == 0) return;
00906
00907
00908 LINFO("MT features Optimal Shift");
00909 for(uint i = 0; i < itsNumDirs; i++)
00910 {
00911 for(uint y = sj; y < ej; y++)
00912 {
00913 for(uint x = si; x < ei; x++)
00914 printf("%7.3f ", itsMToptimalShift[i].getVal(x,y));
00915 printf("\n");
00916 }
00917 LINFO("MT features: %d", i);
00918 if(stop)Raster::waitForKey();
00919 }
00920 }
00921
00922
00923 void MiddleTemporal::displayItsMToptimalShift()
00924 {
00925 if(itsSpatioTemporalEnergy[0].size() == 0) return;
00926 uint w = itsSpatioTemporalEnergy[0][0].getWidth();
00927 uint h = itsSpatioTemporalEnergy[0][0].getHeight();
00928
00929 uint wDisp = w*2; uint hDisp = h/2;
00930 if(itsNumDirs == 8) { wDisp = w*2; hDisp = h; }
00931 else if(itsNumDirs == 8) { wDisp = w*2; hDisp = 3*h/2; }
00932
00933 Image<float> disp(wDisp,hDisp,NO_INIT);
00934 if(itsWin.is_invalid())
00935 itsWin.reset(new XWinManaged(Dims(wDisp,hDisp), w+10, 0, "FOE Detector"));
00936 else itsWin->setDims(Dims(wDisp, hDisp));
00937
00938 LINFO("display MT optimal shift");
00939
00940 inplacePaste(disp, zoomXY(itsMToptimalShift[0], MAX_NEIGHBORHOOD/2),
00941 Point2D<int>(0, 0));
00942 inplacePaste(disp, zoomXY(itsMToptimalShift[1], MAX_NEIGHBORHOOD/2),
00943 Point2D<int>(w/2, 0));
00944 inplacePaste(disp, zoomXY(itsMToptimalShift[2], MAX_NEIGHBORHOOD/2),
00945 Point2D<int>(w, 0));
00946 inplacePaste(disp, zoomXY(itsMToptimalShift[3], MAX_NEIGHBORHOOD/2),
00947 Point2D<int>(3*w/2, 0));
00948
00949 if(itsNumDirs > 4)
00950 {
00951 inplacePaste(disp, zoomXY(itsMToptimalShift[4], MAX_NEIGHBORHOOD/2),
00952 Point2D<int>(0, h/2));
00953 inplacePaste(disp, zoomXY(itsMToptimalShift[5], MAX_NEIGHBORHOOD/2),
00954 Point2D<int>(w/2, h/2));
00955 inplacePaste(disp, zoomXY(itsMToptimalShift[6], MAX_NEIGHBORHOOD/2),
00956 Point2D<int>(w, h/2));
00957 inplacePaste(disp, zoomXY(itsMToptimalShift[7], MAX_NEIGHBORHOOD/2),
00958 Point2D<int>(3*w/2,h/2));
00959 }
00960
00961 if(itsNumDirs > 8)
00962 {
00963 inplacePaste(disp, zoomXY(itsMToptimalShift[8], MAX_NEIGHBORHOOD/2),
00964 Point2D<int>(0, h));
00965 inplacePaste(disp, zoomXY(itsMToptimalShift[9], MAX_NEIGHBORHOOD/2),
00966 Point2D<int>(w/2, h));
00967 inplacePaste(disp, zoomXY(itsMToptimalShift[10], MAX_NEIGHBORHOOD/2),
00968 Point2D<int>(w, h));
00969 inplacePaste(disp, zoomXY(itsMToptimalShift[11], MAX_NEIGHBORHOOD/2),
00970 Point2D<int>(3*w/2, h));
00971 }
00972
00973 float mn,mx; getMinMax(disp,mn,mx);
00974 drawLine(disp, Point2D<int>(0 , h/2), Point2D<int>(w*2 , h/2), mx, 1);
00975 drawLine(disp, Point2D<int>(0 , h ), Point2D<int>(w*2 , h ), mx, 1);
00976 drawLine(disp, Point2D<int>(w/2 , 0 ), Point2D<int>(w/2 , h ), mx, 1);
00977 drawLine(disp, Point2D<int>(w , 0 ), Point2D<int>(w , h ), mx, 1);
00978 drawLine(disp, Point2D<int>(3*w/2, 0 ), Point2D<int>(3*w/2, h ), mx, 1);
00979 itsWin->drawImage(disp,0,0);
00980 Raster::waitForKey();
00981 }
00982
00983
00984 void MiddleTemporal::displayItsMTfeatures()
00985 {
00986 if(itsSpatioTemporalEnergy[0].size() == 0) return;
00987 uint w = itsSpatioTemporalEnergy[0][0].getWidth();
00988 uint h = itsSpatioTemporalEnergy[0][0].getHeight();
00989
00990 uint wDisp = w*2; uint hDisp = h/2;
00991 if(itsNumDirs == 8) { wDisp = w*2; hDisp = h; }
00992 else if(itsNumDirs == 8) { wDisp = w*2; hDisp = 3*h/2; }
00993
00994 Image<float> disp(wDisp,hDisp,NO_INIT);
00995 if(itsWin.is_invalid())
00996 itsWin.reset(new XWinManaged(Dims(wDisp,hDisp), w+10, 0, "FOE Detector"));
00997 else itsWin->setDims(Dims(wDisp, hDisp));
00998
00999 LINFO("display MT features");
01000
01001 inplacePaste(disp, zoomXY(itsMTfeatures[0], MAX_NEIGHBORHOOD/2),
01002 Point2D<int>(0, 0));
01003 inplacePaste(disp, zoomXY(itsMTfeatures[1], MAX_NEIGHBORHOOD/2),
01004 Point2D<int>(w/2, 0));
01005 inplacePaste(disp, zoomXY(itsMTfeatures[2], MAX_NEIGHBORHOOD/2),
01006 Point2D<int>(w, 0));
01007 inplacePaste(disp, zoomXY(itsMTfeatures[3], MAX_NEIGHBORHOOD/2),
01008 Point2D<int>(3*w/2, 0));
01009
01010 if(itsNumDirs > 4)
01011 {
01012 inplacePaste(disp, zoomXY(itsMTfeatures[4], MAX_NEIGHBORHOOD/2),
01013 Point2D<int>(0, h/2));
01014 inplacePaste(disp, zoomXY(itsMTfeatures[5], MAX_NEIGHBORHOOD/2),
01015 Point2D<int>(w/2, h/2));
01016 inplacePaste(disp, zoomXY(itsMTfeatures[6], MAX_NEIGHBORHOOD/2),
01017 Point2D<int>(w, h/2));
01018 inplacePaste(disp, zoomXY(itsMTfeatures[7], MAX_NEIGHBORHOOD/2),
01019 Point2D<int>(3*w/2,h/2));
01020 }
01021
01022 if(itsNumDirs > 8)
01023 {
01024 inplacePaste(disp, zoomXY(itsMTfeatures[8], MAX_NEIGHBORHOOD/2),
01025 Point2D<int>(0, h));
01026 inplacePaste(disp, zoomXY(itsMTfeatures[9], MAX_NEIGHBORHOOD/2),
01027 Point2D<int>(w/2, h));
01028 inplacePaste(disp, zoomXY(itsMTfeatures[10], MAX_NEIGHBORHOOD/2),
01029 Point2D<int>(w, h));
01030 inplacePaste(disp, zoomXY(itsMTfeatures[11], MAX_NEIGHBORHOOD/2),
01031 Point2D<int>(3*w/2, h));
01032 }
01033
01034 float mn,mx; getMinMax(disp,mn,mx);
01035 drawLine(disp, Point2D<int>(0 , h/2), Point2D<int>(w*2 , h/2), mx, 1);
01036 drawLine(disp, Point2D<int>(0 , h ), Point2D<int>(w*2 , h ), mx, 1);
01037 drawLine(disp, Point2D<int>(w/2 , 0 ), Point2D<int>(w/2 , h ), mx, 1);
01038 drawLine(disp, Point2D<int>(w , 0 ), Point2D<int>(w , h ), mx, 1);
01039 drawLine(disp, Point2D<int>(3*w/2, 0 ), Point2D<int>(3*w/2, h ), mx, 1);
01040 itsWin->drawImage(disp,0,0);
01041 Raster::waitForKey();
01042 }
01043
01044
01045 Layout<byte> MiddleTemporal::getMTfeaturesDisplay(Image<byte> image)
01046 {
01047 if(itsRawSpatioTemporalEnergy.size() == 0 ||
01048 itsRawSpatioTemporalEnergy[0][0].size() == 0)
01049 return Layout<byte>(image);
01050
01051 uint width = image.getWidth();
01052 uint height = image.getHeight();
01053
01054 uint scale = 1;
01055 Image<float> lum = image;
01056 Image<float> motion(width* scale, height * scale, ZEROS);
01057
01058 uint mtWidth = itsMTfeatures[0].getWidth();
01059 uint mtHeight = itsMTfeatures[0].getHeight();
01060
01061 Image<float>::iterator mtT[itsNumDirs];
01062 for (unsigned int i=0; i < itsNumDirs; i++)
01063 mtT[i] = itsMTfeatures[i].beginw();
01064
01065 Image<float>::iterator mtosT[itsNumDirs];
01066 for (unsigned int i=0; i < itsNumDirs; i++)
01067 mtosT[i] = itsMToptimalShift[i].beginw();
01068
01069 float boom = 0;
01070
01071 for(uint dir = 0; dir < itsNumDirs; dir++)
01072 {
01073 float angle = (dir*2.0*M_PI)/itsNumDirs;
01074 if(dir%2 == 1)
01075 {
01076
01077 angle = (dir*2.0*M_PI)/itsNumDirs + M_PI/2.0;
01078
01079 }
01080
01081 for(uint j = 0; j < mtHeight; j++)
01082 {
01083 for(uint i = 0; i < mtWidth; i++)
01084 {
01085 float val = *mtT[dir]++;
01086 float shift = *mtosT[dir]++;
01087 if(val > .20)
01088 {
01089 boom++;
01090
01091 drawLine(motion,
01092 Point2D<int>(i*MAX_NEIGHBORHOOD*scale,
01093 j*MAX_NEIGHBORHOOD*scale),
01094
01095 angle, shift*4*scale, val);
01096
01097
01098
01099
01100 }
01101 }
01102 }
01103 }
01104
01105 Image<float> res = motion;
01106 inplaceNormalize(res, 0.0F, 255.0F);
01107 inplaceNormalize(lum, 0.0F, 64.0F);
01108 inplaceNormalize(motion, 0.0F, 255.0F);
01109
01110
01111
01112
01113 Image<byte> vimg = res;
01114
01115
01116
01117 Image<byte> himg = res;
01118
01119
01120
01121
01122
01123
01124 Layout<byte> disp(res+lum);
01125
01126 return disp;
01127 }
01128
01129
01130
01131
01132
01133