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 "Channels/DescriptorVec.H"
00039
00040 #include "Channels/ChannelOpts.H"
00041 #include "Component/ModelOptionDef.H"
00042 #include "Component/OptionManager.H"
00043 #include "Image/CutPaste.H"
00044 #include "SIFT/VisualObject.H"
00045 #include "SIFT/Keypoint.H"
00046 #include "Image/ColorOps.H"
00047 #include "Image/FilterOps.H"
00048 #include "Image/MathOps.H"
00049 #include "Image/ShapeOps.H"
00050 #include "Image/Transforms.H"
00051 #include "Image/fancynorm.H"
00052
00053 #include "GUI/DebugWin.H"
00054 #include "Image/DrawOps.H"
00055
00056 #include <cstdlib>
00057 #include <iostream>
00058
00059
00060 static const ModelOptionDef OPT_DescriptorVecFOV =
00061 { MODOPT_ARG(Dims), "DescriptorVecFOV", &MOC_CHANNEL, OPTEXP_CORE,
00062 "Use the given fovea size for constructing DescriptorVec.",
00063 "descriptor-vec-fov", '\0', "<w>x<h>", "75x75" };
00064
00065
00066 DescriptorVec::DescriptorVec(OptionManager& mgr,
00067 const std::string& descrName,
00068 const std::string& tagName,
00069 ComplexChannel *cc)
00070 : ModelComponent(mgr, descrName, tagName),
00071 itsComplexChannel(cc), itsFoveaSize(&OPT_DescriptorVecFOV, this),
00072 itsFeatureHistogram(100),
00073 itsFEngine(0),
00074 itsFV(0)
00075 {
00076 itsFoveaSize.setVal(Dims(80,80));
00077 }
00078
00079
00080 DescriptorVec::~DescriptorVec()
00081 {}
00082
00083
00084 void DescriptorVec::setInputImg(const Image<PixRGB<byte> >& img)
00085 {
00086 itsInputImg = img;
00087 }
00088
00089
00090 void DescriptorVec::setFovea(Point2D<int> loc)
00091 {
00092 int locX = loc.i;
00093 int locY = loc.j;
00094 int foveaW = itsFoveaSize.getVal().w();
00095 int foveaH = itsFoveaSize.getVal().h();
00096
00097 LINFO("Getting descriptor from loc %i,%i", loc.i, loc.j);
00098 LINFO("Fovea size: %ix%i", foveaW, foveaH);
00099 if (itsComplexChannel->hasInput()){
00100
00101 Image<PixRGB<byte> > img = itsInputImg;
00102 int imgW = img.getWidth();
00103 int imgH = img.getHeight();
00104
00105 LINFO("Image size: %ix%i", imgW, imgH);
00106
00107
00108 int tl_x = locX - ((foveaW-1)/2);
00109 int tl_y = locY - ((foveaH-1)/2);
00110
00111
00112 if (tl_x < 0) tl_x = 0; if (tl_y < 0) tl_y = 0;
00113 if (tl_x+foveaW > imgW) tl_x = imgW - foveaW;
00114 if (tl_y+foveaH > imgH) tl_y = imgH - foveaH;
00115
00116
00117 locX = tl_x + ((foveaW-1)/2);
00118 locY = tl_y + ((foveaH-1)/2);
00119
00120 itsFoveaLoc = Point2D<int>(locX, locY);
00121
00122
00123 if (itsFoveaSize.getVal().w() < img.getWidth())
00124 {
00125 img= crop(img, Point2D<int>(tl_x, tl_y), itsFoveaSize.getVal());
00126 }
00127
00128
00129
00130
00131
00132 itsFoveaImg = img;
00133
00134
00135
00136 } else {
00137 LINFO("No input image in VC");
00138 }
00139
00140
00141 }
00142
00143
00144 void DescriptorVec::setFoveaSize(Dims &d)
00145 {
00146 itsFoveaSize.setVal(d);
00147 }
00148
00149
00150 void DescriptorVec::setFoveaSize(int foveaRadius)
00151 {
00152 Dims fr(foveaRadius, foveaRadius);
00153 itsFoveaSize.setVal(fr);
00154 }
00155
00156
00157 Dims DescriptorVec::getFoveaSize()
00158 {
00159 return itsFoveaSize.getVal();
00160 }
00161
00162
00163 float DescriptorVec::getDominateOrientation(const Image<float> &img){
00164
00165 const int ORIENTARRAY = 36;
00166 Image<float> gradmag, gradori;
00167 gradientSobel(luminance(img), gradmag, gradori);
00168
00169
00170 Histogram OV(ORIENTARRAY);
00171 for (int y=0; y<img.getHeight(); y++){
00172 for(int x=0; x<img.getWidth(); x++){
00173 const float gradVal = gradmag.getVal(x, y);
00174 float angle = gradori.getVal(x, y) + M_PI;
00175
00176 angle = 0.5F * angle * ORIENTARRAY / M_PI;
00177 while (angle < 0.0F) angle += ORIENTARRAY;
00178 while (angle >= ORIENTARRAY) angle -= ORIENTARRAY;
00179
00180 OV.addValueInterp(angle, 1 * gradVal);
00181
00182 }
00183 }
00184
00185
00186 for (int i = 0; i < 3; i++) OV.smooth();
00187
00188
00189 float maxPeakVal; int maxLoc;
00190 OV.findMax(maxLoc, maxPeakVal);
00191
00192
00193 const float leftval = OV.getValue((maxLoc == 0) ? ORIENTARRAY-1 : maxLoc-1);
00194
00195
00196 const float rightval = OV.getValue((maxLoc == ORIENTARRAY-1) ? 0 : maxLoc+1);
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 const float a = 0.5f * (leftval + rightval) - maxPeakVal;
00208
00209 const float b = 0.5f * (rightval - leftval);
00210 float realangle = float(maxLoc) - 0.5F * b / a;
00211
00212 realangle *= 2.0F * M_PI / ORIENTARRAY;
00213 realangle -= M_PI;
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 return realangle;
00258
00259 }
00260
00261
00262
00263 Image<PixRGB<byte> > DescriptorVec::getFoveaImage() {
00264
00265
00266 if (itsFoveaImg.initialized()){
00267
00268
00269
00270
00271
00272 } else {
00273 LINFO("No input image in VC");
00274 }
00275
00276 return itsFoveaImg;
00277 }
00278
00279
00280
00281 Image<PixRGB<byte> > DescriptorVec::getHistogramImage() {
00282
00283
00284 return itsFoveaImg;
00285
00286 }
00287
00288
00289
00290 void DescriptorVec::buildSIFTDV()
00291 {
00292 rutz::shared_ptr<VisualObject>
00293 obj(new VisualObject("NewObject", "NewObject", itsFoveaImg));
00294
00295 std::vector< rutz::shared_ptr<Keypoint> > keypoints = obj->getKeypoints();
00296
00297
00298 for (unsigned int i=0; i<keypoints.size(); i++)
00299 {
00300
00301 std::vector<double> fv;
00302
00303 for(unsigned int j=0; j<keypoints[i]->getFVlength(); j++)
00304 fv.push_back((byte)keypoints[i]->getFVelement(j));
00305
00306 }
00307
00308 }
00309
00310 void DescriptorVec::buildFftDV()
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 void DescriptorVec::buildParticleCountDV()
00356 {
00357
00358
00359 ComplexChannel& cc = dynamic_cast<ComplexChannel&>(*itsComplexChannel->subChan(0));
00360
00361 const LevelSpec lspec = itsComplexChannel->getModelParamVal<LevelSpec>("LevelSpec");
00362 const int smlevel = lspec.mapLevel();
00363 int x=int(itsFoveaLoc.i / double(1 << smlevel) + 0.49);
00364 int y=int(itsFoveaLoc.j / double(1 << smlevel) + 0.49);
00365
00366 itsFV.clear();
00367 int FVi = 0;
00368 for (uint i = 0; i < cc.numChans(); i++)
00369 {
00370 nub::ref<ChannelBase> cb = cc.subChan(i);
00371 if (dynamic_cast<ComplexChannel*>(cb.get()) != 0)
00372 {
00373 LINFO("Complex channel %i %s", i, cb->descriptiveName().c_str());
00374 } else {
00375 SingleChannel& sc = dynamic_cast<SingleChannel&>(*cb);
00376 LINFO("Single channel %i", i);
00377 for (uint j=0; j< sc.numSubmaps(); j++)
00378 {
00379 Image<float> submap = sc.getSubmap(j);
00380
00381 itsFV.push_back(submap.getVal(x, y));
00382 LINFO("FV%i %s:%i", FVi++, sc.descriptiveName().c_str(), j);
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 void DescriptorVec::buildDV()
00410 {
00411 const LevelSpec lspec = itsComplexChannel->getModelParamVal<LevelSpec>("LevelSpec");
00412 const int smlevel = lspec.mapLevel();
00413
00414 int x=int(itsFoveaLoc.i / double(1 << smlevel) + 0.49);
00415 int y=int(itsFoveaLoc.j / double(1 << smlevel) + 0.49);
00416
00417 int foveaW = int(itsFoveaSize.getVal().w() / double(1 << smlevel) + 0.49);
00418 int foveaH = int(itsFoveaSize.getVal().h() / double(1 << smlevel) + 0.49);
00419
00420
00421 int tl_x = x - (foveaW/2);
00422 int tl_y = y - (foveaH/2);
00423
00424
00425
00426 itsFV.clear();
00427 uint numSubmaps = itsComplexChannel->numSubmaps();
00428 for (uint i = 0; i < numSubmaps; i++)
00429 {
00430 Image<float> submap = itsComplexChannel->getSubmap(i);
00431
00432
00433
00434
00435
00436
00437 if (foveaW < submap.getWidth())
00438 submap = crop(submap, Point2D<int>(tl_x, tl_y), Dims(foveaW, foveaH));
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 float maxVal; Point2D<int> maxLoc;
00451 findMax(submap, maxLoc, maxVal);
00452
00453
00454
00455 itsFV.push_back(maxVal);
00456
00457 }
00458 }
00459
00460
00461 void DescriptorVec::buildRawDV()
00462 {
00463
00464 bool salientLocationWithinSubmaps = true;
00465 Point2D<int> objSalientLoc(-1,-1);
00466
00467 const LevelSpec lspec = itsComplexChannel->getModelParamVal<LevelSpec>("LevelSpec");
00468 const int smlevel = lspec.mapLevel();
00469
00470 int x=int(itsFoveaLoc.i / double(1 << smlevel) + 0.49);
00471 int y=int(itsFoveaLoc.j / double(1 << smlevel) + 0.49);
00472
00473 int foveaW = int(itsFoveaSize.getVal().w() / double(1 << smlevel) + 0.49);
00474 int foveaH = int(itsFoveaSize.getVal().h() / double(1 << smlevel) + 0.49);
00475
00476 int tl_x = x - (foveaW/2);
00477 int tl_y = y - (foveaH/2);
00478
00479 Dims mapDims = itsComplexChannel->getSubmap(0).getDims();
00480
00481
00482
00483 if (tl_x < 0) tl_x = 0; if (tl_y < 0) tl_y = 0;
00484 if (tl_x+foveaW > mapDims.w()) tl_x = mapDims.w() - foveaW;
00485 if (tl_y+foveaH > mapDims.h()) tl_y = mapDims.h() - foveaH;
00486
00487 if (!salientLocationWithinSubmaps)
00488 {
00489
00490 Image<float> SMap = itsComplexChannel->getOutput();
00491
00492 Image<float> tmp = SMap;
00493
00494
00495 float maxVal; Point2D<int> maxLoc;
00496 findMax(tmp, maxLoc, maxVal);
00497
00498
00499
00500 objSalientLoc.i=x;
00501 objSalientLoc.j=y;
00502 itsAttentionLoc = objSalientLoc;
00503 }
00504
00505
00506 itsFV.clear();
00507 uint numSubmaps = itsComplexChannel->numSubmaps();
00508 for (uint i = 0; i < numSubmaps; i++)
00509 {
00510
00511 Image<float> submap = itsComplexChannel->getRawCSmap(i);
00512
00513
00514 if (submap.getWidth() > mapDims.w())
00515 submap = downSize(submap, mapDims);
00516 else if (submap.getWidth() < mapDims.w())
00517 submap = rescale(submap, mapDims);
00518
00519
00520 if (salientLocationWithinSubmaps)
00521 {
00522 Image<float> tmp = submap;
00523
00524
00525 if (foveaW < tmp.getWidth())
00526 tmp = crop(tmp, Point2D<int>(tl_x, tl_y), Dims(foveaW, foveaH));
00527
00528
00529
00530 float maxVal; Point2D<int> maxLoc; findMax(tmp, maxLoc, maxVal);
00531
00532
00533 objSalientLoc.i=tl_x+maxLoc.i;
00534 objSalientLoc.j=tl_y+maxLoc.j;
00535
00536 }
00537
00538 if (objSalientLoc.i < 0) objSalientLoc.i = 0;
00539 if (objSalientLoc.j < 0) objSalientLoc.j = 0;
00540
00541 if (objSalientLoc.i > submap.getWidth()-1) objSalientLoc.i = submap.getWidth()-1;
00542 if (objSalientLoc.j > submap.getHeight()-1) objSalientLoc.j = submap.getHeight()-1;
00543
00544
00545
00546
00547
00548 float featureVal = submap.getVal(objSalientLoc.i,objSalientLoc.j);
00549 itsFV.push_back(featureVal);
00550
00551
00552 }
00553 }
00554
00555
00556 void DescriptorVec::buildLocalDV()
00557 {
00558
00559 Point2D<int> objSalientLoc(-1,-1);
00560
00561
00562
00563 itsFV.clear();
00564 uint numSubmaps = itsComplexChannel->numSubmaps();
00565 for (uint i = 0; i < numSubmaps; i++)
00566 {
00567
00568 Image<float> submap = itsComplexChannel->getRawCSmap(i);
00569
00570
00571 float maxVal; Point2D<int> maxLoc; findMax(submap, maxLoc, maxVal);
00572
00573
00574 float featureVal = submap.getVal(maxLoc.i,maxLoc.j);
00575 itsFV.push_back(featureVal);
00576
00577
00578 }
00579 }
00580
00581 void DescriptorVec::buildSingleChannelFV(SingleChannel &sc)
00582 {
00583 const LevelSpec lspec = itsComplexChannel->getModelParamVal<LevelSpec>("LevelSpec");
00584 const int smlevel = lspec.mapLevel();
00585 int x=int(itsFoveaLoc.i / double(1 << smlevel) + 0.49);
00586 int y=int(itsFoveaLoc.j / double(1 << smlevel) + 0.49);
00587
00588
00589 for (uint j=0; j< sc.numSubmaps(); j++)
00590 {
00591 Image<float> submap = sc.getSubmap(j);
00592 itsFV.push_back(submap.getVal(x, y));
00593 }
00594
00595 }
00596
00597 uint DescriptorVec::getFVSize()
00598 {
00599 ASSERT(itsComplexChannel != NULL);
00600 return itsComplexChannel->numSubmaps();
00601 }
00602
00603
00604 const std::vector<double>& DescriptorVec::getFV() const
00605 {
00606 return itsFV;
00607 }
00608
00609
00610
00611
00612
00613