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 #include "Beobot/BeobotBrainMT.H"
00041 #include "Neuro/gistParams.H"
00042 #include "Neuro/GistEstimatorStd.H"
00043
00044 #include "Image/MathOps.H"
00045 #include "Image/DrawOps.H"
00046 #include "Image/ShapeOps.H"
00047 #include "Image/Transforms.H"
00048 #include "Image/fancynorm.H"
00049 #include "Image/FilterOps.H"
00050 #include "Image/PyrBuilder.H"
00051 #include "Image/ColorOps.H"
00052 #include "Util/Timer.H"
00053 #include "Image/CutPaste.H"
00054 #include "Image/MorphOps.H"
00055
00056
00057 void *BeobotBrainMT_threadCompute(void *c)
00058 {
00059 BeobotBrainMT *d = (BeobotBrainMT *)c;
00060 d->threadCompute();
00061 return NULL;
00062 }
00063
00064
00065 BeobotBrainMT::BeobotBrainMT(OptionManager& mgr,
00066 const std::string& descrName,
00067 const std::string& tagName)
00068 :
00069 ModelComponent(mgr, descrName, tagName)
00070 {
00071 numWorkers = 0U;
00072
00073
00074 itsNumChannels = NUM_CHANNELS;
00075
00076
00077 itsChanWeight.resize(itsNumChannels);
00078 itsChanWeight[REDGREEN ] = CWEIGHT;
00079 itsChanWeight[BLUEYELLOW] = CWEIGHT;
00080 itsChanWeight[INTENSITY ] = IWEIGHT;
00081 itsChanWeight[ORI0 ] = OWEIGHT;
00082 itsChanWeight[ORI45 ] = OWEIGHT;
00083 itsChanWeight[ORI90 ] = OWEIGHT;
00084 itsChanWeight[ORI135 ] = OWEIGHT;
00085
00086
00087 itsCMaps.resize(itsNumChannels);
00088
00089
00090 uint cscount =
00091 (level_max - level_min + 1) * (delta_max - delta_min + 1);
00092 itsCSMaps.resize(itsNumChannels);
00093 itsRawCSMaps.resize(itsNumChannels);
00094 for(uint i = 0; i < itsNumChannels; i++)
00095 {
00096 itsCSMaps[i].resize(cscount);
00097 itsRawCSMaps[i].resize(cscount);
00098 }
00099
00100
00101 itsImgPyrs.resize(itsNumChannels);
00102
00103
00104 const int ss = 8;
00105 structEl = Image<byte>(ss+ss,ss+ss,ZEROS);
00106 drawDisk(structEl, Point2D<int>(ss,ss),ss,(byte)1);
00107
00108
00109 itsGistFeatSize = NUM_GIST_FEAT_SIZE;
00110 itsGistVector = Image<double>(1, itsGistFeatSize, NO_INIT);
00111 LINFO("initialized");
00112
00113
00114
00115
00116
00117 itsTimer.reset(new Timer(1000000));
00118 itsProcessTime = -1.0F;
00119 }
00120
00121
00122 void BeobotBrainMT::start1()
00123 {
00124
00125
00126 pthread_mutex_init(&jobLock, NULL);
00127 pthread_mutex_init(&mapLock, NULL);
00128 pthread_cond_init(&jobCond, NULL);
00129
00130 LINFO("Starting with %d threads...", numBBMTthreads);
00131
00132
00133 worker = new pthread_t[numBBMTthreads];
00134 for (uint i = 0; i < numBBMTthreads; i ++)
00135 {
00136 pthread_create(&worker[i], NULL, BeobotBrainMT_threadCompute,
00137 (void *)this);
00138
00139
00140
00141 usleep(100000);
00142 }
00143 }
00144
00145
00146 void BeobotBrainMT::stop2()
00147 {
00148
00149 pthread_cond_destroy(&jobCond);
00150
00151
00152
00153
00154 delete [] worker;
00155 }
00156
00157
00158 BeobotBrainMT::~BeobotBrainMT()
00159 { }
00160
00161
00162 bool BeobotBrainMT::outputReady()
00163 {
00164 bool ret = false;
00165
00166 pthread_mutex_lock(&jobLock);
00167 if (jobsTodo == 0U) ret = true;
00168
00169
00170
00171 pthread_mutex_lock(&mapLock);
00172 if(!itsCurrImg.initialized()) ret = false;
00173 pthread_mutex_unlock(&mapLock);
00174
00175 pthread_mutex_unlock(&jobLock);
00176
00177 return ret;
00178 }
00179
00180
00181 void BeobotBrainMT::input(Image< PixRGB<byte> > img)
00182 {
00183 itsTimer->reset();
00184 computeCIOpyr(img);
00185 }
00186
00187
00188 void BeobotBrainMT::computeCIOpyr(Image< PixRGB<byte> > img)
00189 {
00190 pthread_mutex_lock(&mapLock);
00191
00192
00193
00194 itsCurrImg = img;
00195 itsCurrImgWidth = img.getWidth();
00196 itsCurrImgHeight = img.getHeight();
00197
00198
00199
00200 itsSalmap.freeMem();
00201 gotLum = false; gotRGBY = false;
00202 pthread_mutex_unlock(&mapLock);
00203
00204
00205 pthread_mutex_lock(&jobLock);
00206 jobQueue.clear();
00207
00208
00209 jobQueue.push_back(jobData(REDGREEN, Gaussian5, CWEIGHT, 0.0F));
00210 jobQueue.push_back(jobData(BLUEYELLOW, Gaussian5, CWEIGHT, 0.0F));
00211
00212
00213 jobQueue.push_back(jobData(INTENSITY, Gaussian5, IWEIGHT, 0.0F));
00214
00215
00216 jobQueue.push_back(jobData(ORI0, Oriented5, OWEIGHT, 0.0F));
00217 jobQueue.push_back(jobData(ORI45, Oriented5, OWEIGHT, 45.0F));
00218 jobQueue.push_back(jobData(ORI90, Oriented5, OWEIGHT, 90.0F));
00219 jobQueue.push_back(jobData(ORI135, Oriented5, OWEIGHT, 135.0F));
00220
00221 jobsTodo = jobQueue.size();
00222 pthread_mutex_unlock(&jobLock);
00223
00224
00225 pthread_cond_broadcast(&jobCond);
00226
00227 }
00228
00229
00230 Image<float> BeobotBrainMT::getSalMap()
00231 {
00232 Image<float> ret;
00233
00234 pthread_mutex_lock(&mapLock);
00235 ret = itsSalmap;
00236 pthread_mutex_unlock(&mapLock);
00237
00238 return ret;
00239 }
00240
00241
00242 Image<double> BeobotBrainMT::getGist()
00243 {
00244 Image<double> ret;
00245 pthread_mutex_lock(&gistLock);
00246 ret = itsGistVector;
00247 pthread_mutex_unlock(&gistLock);
00248
00249 return ret;
00250 }
00251
00252
00253
00254 void BeobotBrainMT::threadCompute()
00255 {
00256 pthread_mutex_lock(&mapLock);
00257 uint myNum = numWorkers ++;
00258 pthread_mutex_unlock(&mapLock);
00259 LINFO(" ... worker %u ready.", myNum);
00260
00261 while(true)
00262 {
00263
00264 pthread_mutex_lock(&jobLock);
00265 jobData current(0, Gaussian5, 0.0F, 0.0F); bool nojobs = true;
00266 if (jobQueue.empty() == false)
00267 {
00268 current = jobQueue.front();
00269 jobQueue.pop_front();
00270 nojobs = false;
00271 }
00272 else
00273 pthread_cond_wait(&jobCond, &jobLock);
00274 pthread_mutex_unlock(&jobLock);
00275
00276
00277 if (nojobs) continue;
00278
00279
00280
00281
00282
00283 Image<float> curImage;
00284
00285
00286
00287 pthread_mutex_lock(&mapLock);
00288 switch(current.jobType)
00289 {
00290
00291
00292
00293
00294 case REDGREEN:
00295 if (gotRGBY == false)
00296 {
00297 getRGBY(itsCurrImg, rgimg, byimg, 25.5f);
00298 gotRGBY = true;
00299 }
00300 curImage = rgimg;
00301 break;
00302
00303
00304 case BLUEYELLOW:
00305 if (gotRGBY == false)
00306 {
00307 getRGBY(itsCurrImg, rgimg, byimg, 25.5f);
00308 gotRGBY = true;
00309 }
00310 curImage = byimg;
00311 break;
00312
00313
00314 case ORI0:
00315 case ORI45:
00316 case ORI90:
00317 case ORI135:
00318 case INTENSITY:
00319 if (gotLum == false)
00320 {
00321 itsCurrLumImg =
00322 Image<float>(luminance(Image<PixRGB<float> >(itsCurrImg)));
00323 gotLum = true;
00324 }
00325 curImage = itsCurrLumImg;
00326 break;
00327
00328
00329 default:
00330 LERROR("invalid job type");
00331 curImage = itsCurrLumImg;
00332 }
00333 pthread_mutex_unlock(&mapLock);
00334
00335 ImageSet<float> pyr;
00336
00337
00338 int cW = itsCurrImgWidth /(int)(pow(2,sml));
00339 int cH = itsCurrImgHeight/(int)(pow(2,sml));
00340 Image<float> cmap(cW,cH, ZEROS);
00341
00342
00343
00344
00345 int count = 0; uint cscount = 0;
00346 int s_index = 0; int offset = 0;
00347 switch(current.jobType)
00348 {
00349
00350 case INTENSITY: s_index += 6;
00351 case BLUEYELLOW: s_index += 6;
00352 case REDGREEN: s_index += 16;
00353
00354
00355 pyr = buildPyrGaussian(curImage, 0, maxdepth, 5);
00356 itsImgPyrs[current.jobType] = pyr;
00357
00358
00359
00360 for (int lev = level_min; lev <= level_max; lev ++)
00361 for (int delta = delta_min; delta <= delta_max; delta ++)
00362 {
00363 Image<float> tmp = centerSurround(pyr, lev, lev + delta, true);
00364
00365
00366 LDEBUG("%d_%d_%d",current.jobType,lev,lev+delta);
00367 pthread_mutex_lock(&gistLock);
00368 inplacePaste(itsGistVector, getSubSum(tmp),
00369 Point2D<int>(0, (s_index + count)*NUM_GIST_FEAT));
00370 pthread_mutex_unlock(&gistLock);
00371 count++;
00372
00373
00374
00375
00376
00377 tmp = rescale(tmp, cmap.getWidth(), cmap.getHeight());
00378
00379 float minv, maxv; getMinMax(tmp, minv, maxv);
00380 itsRawCSMaps[current.jobType][cscount] = tmp;
00381 tmp = maxNormalize(tmp, MAXNORMMIN, MAXNORMMAX, normtyp);
00382 cmap += tmp;
00383 itsCSMaps[current.jobType][cscount] = tmp; cscount++;
00384 }
00385
00386 break;
00387
00388
00389
00390
00391 case ORI135: offset += 1;
00392 case ORI90: offset += 1;
00393 case ORI45: offset += 1;
00394 case ORI0:
00395
00396
00397 pyr = buildPyrOriented(curImage, 0, maxdepth, 9,
00398 offset*45.0f, 10.0f);
00399 itsImgPyrs[current.jobType] = pyr;
00400
00401
00402 for(int i = 0; i < NUM_GIST_LEV; i++)
00403 {
00404 LDEBUG("or_%f_%d",offset*45.0f,i);
00405 pthread_mutex_lock(&gistLock);
00406 inplacePaste
00407 (itsGistVector, getSubSum(pyr[i]),
00408 Point2D<int>(0, (i * NUM_GIST_LEV + offset) * NUM_GIST_FEAT));
00409 pthread_mutex_unlock(&gistLock);
00410 }
00411
00412
00413 for (int lev = level_min; lev <= level_max; lev ++)
00414 for (int delta = delta_min; delta <= delta_max; delta ++)
00415 {
00416 Image<float> tmp = centerSurround(pyr, lev, lev + delta, true);
00417
00418 tmp = rescale(tmp, cmap.getWidth(), cmap.getHeight());
00419 itsRawCSMaps[current.jobType][cscount] = tmp;
00420 tmp = maxNormalize(tmp, MAXNORMMIN, MAXNORMMAX, normtyp);
00421 cmap += tmp;
00422
00423 itsCSMaps[current.jobType][cscount] = tmp; cscount++;
00424 }
00425
00426
00427 break;
00428
00429 default:
00430 LERROR("invalid job type");
00431 }
00432
00433
00434 itsCMaps[current.jobType] = cmap;
00435
00436
00437 inplaceAddBGnoise(cmap, 25.0F);
00438
00439 if (normtyp == VCXNORM_MAXNORM)
00440 cmap = maxNormalize(cmap, MAXNORMMIN, MAXNORMMAX, normtyp);
00441 else
00442 cmap = maxNormalize(cmap, 0.0f, 0.0f, normtyp);
00443
00444
00445 if (current.weight != 1.0F) cmap *= current.weight;
00446
00447
00448 pthread_mutex_lock(&mapLock);
00449 if (itsSalmap.initialized()) itsSalmap += cmap;
00450 else itsSalmap = cmap;
00451 pthread_mutex_unlock(&mapLock);
00452
00453 pthread_mutex_lock(&jobLock);
00454 jobsTodo--;
00455
00456
00457
00458 if(jobsTodo == 0)
00459 {
00460
00461 findObjects();
00462
00463
00464 computeSalientFeatures();
00465
00466 itsProcessTime = itsTimer->get()/1000.0F;
00467 }
00468 pthread_mutex_unlock(&jobLock);
00469 }
00470 }
00471
00472
00473 void BeobotBrainMT::findObjects()
00474 {
00475
00476 itsWinner.clear();
00477 itsObjRect.clear();
00478 itsWinningChan.clear();
00479 itsWinningSubmapNum.clear();
00480 itsWinningMap.clear();
00481 itsObjectMask.clear();
00482
00483 int scale = (int)(pow(2,sml));
00484 Image<float> currSalMap = itsSalmap;
00485 Image<byte> accMask(currSalMap.getDims(),ZEROS);
00486 int area = 0;
00487
00488
00489 float maxval; Point2D<int> currwin; findMax(currSalMap, currwin, maxval);
00490 float cmval = maxval;
00491 int maxArea = currSalMap.getSize();
00492 LDEBUG("max val: %f", maxval);
00493
00494
00495
00496
00497 uint i = 0;
00498 while((.05 *maxval < cmval) && (i < 5) && (float(area)/maxArea < .5))
00499 {
00500
00501 Point2D<int> cwins = currwin*scale;
00502 itsWinner.push_back(cwins);
00503 setWinningMap(cwins);
00504 Image<float> cobjmask = getObjectMask();
00505 itsObjectMask.push_back(cobjmask);
00506 Rectangle crect = getSEBoundingBox();
00507 itsObjRect.push_back(crect);
00508
00509
00510 Image<float> temp(cobjmask);
00511 temp = convGauss<float>(temp,4,4,2);
00512 inplaceNormalize(temp, 0.0F,3.0F);
00513 inplaceClamp(temp, 0.0F, 1.0F);
00514 Image<float> supMask(temp);
00515
00516
00517 inplaceNormalize(supMask, 0.0F, 1.0F);
00518 supMask = (supMask * -1.0F) + 1.0F;
00519 currSalMap *= supMask;
00520
00521
00522 findMax(currSalMap, currwin, cmval);
00523
00524
00525 accMask += cobjmask;
00526 area = int(sum(cobjmask)/255.0);
00527
00528
00529
00530
00531
00532
00533
00534
00535 LDEBUG("accMask: %d cmval: %f", area, cmval);
00536
00537
00538
00539
00540
00541
00542
00543 float maxovl = 0.0;
00544 for(uint j = 0; j < itsObjRect.size()-1; j++)
00545 {
00546 Rectangle covl = crect.getOverlap(itsObjRect[j]);
00547 float pcnt = 0.0;
00548 if(covl.isValid())
00549 {
00550 pcnt = (float(covl.area())/crect.area() +
00551 float(covl.area())/itsObjRect[j].area())/2.0;
00552 if(maxovl < pcnt) maxovl = pcnt;
00553
00554 }
00555
00556 }
00557
00558
00559 if(maxovl > .66)
00560 {
00561
00562 itsWinner.pop_back();
00563 itsObjRect.pop_back();
00564 itsWinningChan.pop_back();
00565 itsWinningSubmapNum.pop_back();
00566 itsWinningMap.pop_back();
00567 itsObjectMask.pop_back();
00568 LDEBUG("object overlap with previous ones > .66");
00569 }
00570 else
00571 {
00572 LDEBUG("sal pt %u done",i); i++;
00573 }
00574
00575 }
00576 }
00577
00578
00579 bool BeobotBrainMT::setWinningMap(Point2D<int> winner)
00580 {
00581 Point2D<int> scwin = downScaleCoords(winner, itsCMaps[0].getDims());
00582
00583
00584 uint wchan; float mx = -1.0F;
00585 for (uint i = 0; i < itsNumChannels; ++i)
00586 {
00587 Image<float> output = itsCMaps[i] * itsChanWeight[i];
00588 float curr_val = output.getVal(scwin);
00589 if (curr_val >= mx){mx = curr_val; wchan = i;}
00590 }
00591
00592
00593
00594 uint wschan; mx = -1.0F;
00595 for (uint j = 0; j < itsCSMaps[wchan].size(); j++)
00596 {
00597 Image<float> csmap = itsCSMaps[wchan][j];
00598 float curr_val = csmap.getVal(scwin);
00599 if (curr_val >= mx) { mx = curr_val; wschan = j; }
00600
00601
00602
00603
00604
00605 }
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 itsWinningChan.push_back(wchan);
00621 itsWinningSubmapNum.push_back(wschan);
00622 itsWinningMap.push_back(itsCSMaps[wchan][wschan]);
00623
00624 LDEBUG("[%d,%d] winner: chan(%d), sub-chan(%d)",
00625 winner.i, winner.j, wchan, wschan);
00626 return true;
00627 }
00628
00629
00630 Point2D<int> BeobotBrainMT::downScaleCoords(Point2D<int> winner, Dims targetDims)
00631 {
00632
00633 int i = (winner.i * targetDims.w()) / itsCurrImgWidth;
00634 int j = (winner.j * targetDims.h()) / itsCurrImgHeight;
00635 return Point2D<int>(i,j);
00636 }
00637
00638
00639 Image<byte> BeobotBrainMT::getObjectMask()
00640 {
00641 int index = itsWinningMap.size() - 1;
00642 Image<float> winMapNormalized = itsWinningMap[index];
00643 inplaceNormalize(winMapNormalized, 0.0F, 1.0F);
00644
00645 Point2D<int> wp = downScaleCoords(itsWinner[index],
00646 itsWinningMap[index].getDims());
00647
00648
00649
00650 std::vector<Point2D<int> > surr(4);
00651 surr[0] = Point2D<int>(0,0); surr[1] = Point2D<int>(-1,0);
00652 surr[2] = Point2D<int>(0,1); surr[3] = Point2D<int>(-1,1);
00653
00654 bool haveValue = false;
00655 for (uint i = 0; i < surr.size(); ++i)
00656 {
00657 Point2D<int> wp2 = wp + surr[i];
00658 wp2.clampToDims(itsWinningMap[index].getDims());
00659 if (itsWinningMap[index].getVal(wp2) > 0.0F)
00660 {
00661 wp = wp2; haveValue = true; break;
00662 }
00663 }
00664
00665 Image<byte> objMask;
00666 if (haveValue) objMask = segmentObjectClean(winMapNormalized, wp, 4);
00667 return objMask;
00668 }
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689 Rectangle BeobotBrainMT::getSEBoundingBox()
00690 {
00691 int scale = (int)(pow(2,sml));
00692
00693
00694 int index = itsObjectMask.size() - 1;
00695 Rectangle r = findBoundingRect(itsObjectMask[index], byte(255));
00696 int tr = r.top(); if(tr > 0) tr--;
00697 int lr = r.left(); if(lr > 0) lr--;
00698 int br = r.bottomO(); if(br < itsCurrImgHeight/scale) br++;
00699 int rr = r.rightO(); if(rr < itsCurrImgWidth/scale) rr++;
00700 Rectangle rsc =
00701 Rectangle::tlbrO(tr*scale, lr*scale, br*scale, rr*scale);
00702
00703
00704 int w = itsCMaps[0].getWidth()*scale;
00705 int h = itsCMaps[0].getHeight()*scale;
00706 Rectangle rscc = correctBB(rsc, itsWinner[index], w, h);
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811 return rscc;
00812 }
00813
00814
00815 Rectangle BeobotBrainMT::correctBB(Rectangle r, Point2D<int> p, int w, int h)
00816 {
00817 float wlow = .35; float whigh = .5;
00818 float hlow = .35; float hhigh = .5;
00819
00820
00821 int pslack = 5;
00822
00823 int tr = r.top(); int lr = r.left();
00824 int br = r.bottomI(); int rr = r.rightI();
00825 int wr = r.width(); int hr = r.height();
00826 LDEBUG("SE bb [%3d,%3d,%3d,%d](%dx%d): p:[%d,%d]",
00827 tr, lr, br, rr, wr, hr, p.i, p.j);
00828
00829
00830
00831 if(((lr + pslack) > p.i) || ((rr - pslack) < p.i) ||
00832 ((tr + pslack) > p.j) || ((br - pslack) < p.j) )
00833 {
00834 LDEBUG("point is out of or near border of box");
00835
00836
00837
00838 if((lr + pslack) > p.i)
00839 { lr = p.i - pslack; if(lr < 0 ) lr = 0; LDEBUG("left "); }
00840 if((rr - pslack) < p.i)
00841 { rr = p.i + pslack; if(rr > w-1) rr = w-1;LDEBUG("right "); }
00842 if((tr + pslack) > p.j)
00843 { tr = p.j - pslack; if(tr < 0 ) tr = 0; LDEBUG("top "); }
00844 if((br - pslack) < p.j)
00845 { br = p.j + pslack; if(br > h-1) br = h-1;LDEBUG("bottom"); }
00846
00847 wr = rr - lr;
00848 hr = br - tr;
00849
00850 LDEBUG("CNT SE bb [%3d,%3d,%3d,%d](%dx%d) p: [%d,%d]",
00851 tr, lr, br, rr, wr, hr, p.i, p.j);
00852 }
00853
00854
00855
00856
00857 if(wr < wlow * w)
00858 {
00859 int wdiff = int(wlow * w) - wr;
00860 float pnt = float(wdiff)/(wr + 0.0f);
00861 LDEBUG("enlarge width (%d -> %d) by: %d (%f)",
00862 wr, int(wlow * w), wdiff, pnt);
00863
00864 int ls = 0, rs = 0;
00865 if((p.i - lr)/(wr+0.0) > .7)
00866 {
00867 ls = int(.7 * wr); rs = int(.3 * wr); LDEBUG("left skew");
00868 }
00869 else if((rr - p.i)/(wr+0.0) > .7)
00870 {
00871 ls = int(.3 * wr); rs = int(.7 * wr); LDEBUG("right skew");
00872 }
00873 else
00874 {
00875 ls = p.i - lr; rs = rr - p.i; LDEBUG("horz centered");
00876 }
00877 int ladd = int(ls * pnt);
00878 int radd = int(rs * pnt);
00879 LDEBUG("add: l: %d, r: %d", ladd, radd);
00880
00881 if(lr < ladd)
00882 {
00883 rr += radd + ladd - lr; lr = 0;
00884 LDEBUG("hit left border: lr: %d, rr:%d", lr, rr);
00885 }
00886 else if(w - 1 < (rr + radd))
00887 {
00888 ladd += rr + radd - w + 1;
00889 lr = lr - ladd;
00890 rr = w - 1;
00891 LDEBUG("hit right border: lr: %d, rr:%d", lr, rr);
00892 }
00893 else
00894 {
00895 lr = lr - ladd; rr = rr + radd;
00896 LDEBUG("centered: lr: %d, rr:%d", lr, rr);
00897 }
00898 }
00899
00900
00901 else if(wr > whigh * w)
00902 {
00903 int wdiff = wr - int(whigh * w);
00904 float pnt = float(wdiff)/(wr + 0.0f);
00905 LDEBUG("decrease width (%d -> %d) by: %d (%f)",
00906 wr, int(whigh * w), wdiff, pnt);
00907 int mid = (lr + rr)/2;
00908 LDEBUG("mid horz: %d", mid);
00909
00910
00911 if(mid > p.i)
00912 {
00913
00914 int ldiff = p.i - lr;
00915 LDEBUG("Point more left %d, right %d", ldiff, rr - p.i);
00916 if(ldiff >= pslack)
00917 {
00918 int cut = int (ldiff * pnt);
00919 lr = lr + cut;
00920 wdiff-= cut;
00921 LDEBUG("cut left slack %d, lr %d, wdiff now: %d",
00922 cut, lr, wdiff);
00923 }
00924 else LDEBUG("left is not cut");
00925
00926 rr-= wdiff; LDEBUG("rr: %d", rr);
00927 }
00928
00929 else
00930 {
00931
00932 int rdiff = rr - p.i;
00933 LDEBUG("Point more right %d left: %d", rdiff, p.i - lr);
00934 if(rdiff >= pslack)
00935 {
00936 int cut = int (rdiff * pnt);
00937 rr = rr - cut;
00938 wdiff-= cut;
00939 LDEBUG("cut right slack %d, rr %d, wdiff now: %d",
00940 cut, rr, wdiff);
00941 }
00942 else LDEBUG("right is not cut");
00943
00944 lr+= wdiff; LDEBUG("lr: %d", lr);
00945 }
00946 }
00947
00948
00949 if(hr < hlow * h)
00950 {
00951 int hdiff = int(hlow * h) - hr;
00952 float pnt = float(hdiff)/(hr + 0.0f);
00953 LDEBUG("increase the height (%d -> %d) by: %d (%f)",
00954 hr, int(hlow * h), hdiff, pnt);
00955
00956 int ts = 0, bs = 0;
00957 if((p.j - tr)/(hr+0.0) > .7)
00958 {
00959 ts = int(.7 * hr); bs = int(.3 * hr); LDEBUG("top skew");}
00960 else if((br - p.j)/(hr+0.0) > .7)
00961 {
00962 ts = int(.3 * hr); bs = int(.7 * hr); LDEBUG("bottom skew");
00963 }
00964 else
00965 {
00966 ts = p.j - tr; bs = br - p.j; LDEBUG("vert centered");
00967 }
00968
00969 int tadd = int(ts * pnt);
00970 int badd = int(bs * pnt);
00971 LDEBUG("adding: t: %d, b: %d", tadd, badd);
00972
00973 if(tr < tadd)
00974 {
00975 br += badd + tadd - tr; tr = 0;
00976 LDEBUG("hit top border: tr: %d, br:%d", tr, br);
00977 }
00978 else if(h - 1 < (br + badd))
00979 {
00980 tadd += br + badd - h + 1;
00981 tr = tr - tadd;
00982 br = h - 1;
00983 LDEBUG("hit bottom border: tr: %d, br:%d", tr, br);
00984 }
00985 else
00986 {
00987 tr = tr - tadd; br = br + badd;
00988 LDEBUG("centered vertically: lr: %d, rr:%d", tr, br);
00989 }
00990 }
00991
00992 else if(hr > hhigh * h)
00993 {
00994 int hdiff = hr - int(hhigh * h);
00995 float pnt = float(hdiff)/(hr + 0.0f);
00996 LDEBUG("enlarge the heigth (%d -> %d) by: %d (%f)",
00997 hr, int(hhigh * h), hdiff, pnt);
00998 int mid = (tr + br)/2;
00999 LDEBUG("mid vert: %d", mid);
01000
01001
01002 if(mid > p.j)
01003 {
01004
01005 int tdiff = p.j - tr;
01006 LDEBUG("Point more top %d, bottom %d", tdiff, br - p.j);
01007 if(tdiff >= pslack)
01008 {
01009 int cut = int (tdiff * pnt);
01010 tr = tr + cut;
01011 hdiff-= cut;
01012 LDEBUG("cut top slack %d, tr %d, hdiff now: %d",
01013 cut, tr, hdiff);
01014 }
01015 else LDEBUG("top not cut");
01016
01017 br-= hdiff; LDEBUG("br: %d", br);
01018 }
01019
01020 else
01021 {
01022
01023 int bdiff = br - p.j;
01024 LDEBUG("Point more bottom %d top: %d", bdiff, p.j - tr);
01025 if(bdiff >= pslack)
01026 {
01027 int cut = int (bdiff * pnt);
01028 br = br - cut;
01029 hdiff-= cut;
01030 LDEBUG("cut bottom slack %d, br %d, wdiff now: %d",
01031 cut, br, hdiff);
01032 }
01033 else LDEBUG("bottom not cut");
01034
01035 tr+= hdiff; LDEBUG("tr: %d", tr);
01036 }
01037 }
01038
01039
01040
01041 if(((lr + pslack) > p.i) || ((rr - pslack) < p.i) ||
01042 ((tr + pslack) > p.j) || ((br - pslack) < p.j) )
01043 {
01044 LDEBUG("point is out of or near border of box");
01045 if((lr + pslack) > p.i)
01046 { lr = p.i - pslack; if(lr < 0 ) lr = 0; LDEBUG("left "); }
01047 if((rr - pslack) < p.i)
01048 { rr = p.i + pslack; if(rr > w-1) rr = w-1; LDEBUG("right "); }
01049 if((tr + pslack) > p.j)
01050 { tr = p.j - pslack; if(tr < 0 ) tr = 0; LDEBUG("top "); }
01051 if((br - pslack) < p.j)
01052 { br = p.j + pslack; if(br > h-1) br = h-1; LDEBUG("bottom"); }
01053 }
01054
01055 Rectangle newR = Rectangle::tlbrI(tr, lr, br, rr);
01056 LDEBUG("SE bb [%3d,%3d,%3d,%d](%dx%d): p:[%d,%d]",
01057 tr, lr, br, rr, newR.width(), newR.height(), p.i, p.j);
01058 return newR;
01059 }
01060
01061
01062 void BeobotBrainMT::computeSalientFeatures()
01063 {
01064 itsSalientFeatures.resize(itsWinner.size());
01065 for(uint i = 0; i < itsWinner.size(); i++)
01066 {
01067
01068
01069
01070
01071
01072
01073 itsSalientFeatures[i].clear();
01074 Point2D<int> locn = itsWinner[i];
01075 for(uint c = 0; c < itsNumChannels; c++)
01076 {
01077 for(int di = -2; di < 3; di++)
01078 for(int dj = -2; dj < 3; dj++)
01079 {
01080 uint fidx = 0;
01081 for (int lev = level_min; lev <= level_max; lev ++)
01082 for (int delta = delta_min; delta <= delta_max; delta ++)
01083 {
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109 int csi = locn.i/4, csj = locn.j/4;
01110 float rval = 0.0;
01111 if(itsCSMaps[c][fidx].coordsOk(csi + di, csj + dj))
01112 rval = fabs(itsCSMaps[c][fidx].getVal(csi, csj));
01113 float minv, maxv;
01114 getMinMax(itsCSMaps[c][fidx], minv, maxv);
01115 float val;
01116 if((maxv - minv) < 1.0) val = 0.0F;
01117 else val = (rval - minv)/(maxv - minv);
01118
01119
01120
01121 itsSalientFeatures[i].push_back(double(val));
01122 fidx++;
01123 }
01124 }
01125 }
01126 }
01127 }
01128
01129
01130
01131
01132
01133