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
00042 #include "Neuro/GistEstimatorGen.H"
00043 #include "Component/ModelManager.H"
00044 #include "Channels/ChannelMaps.H"
00045 #include "Channels/BlueYellowChannel.H"
00046 #include "Channels/ColorChannel.H"
00047 #include "Channels/GaborChannel.H"
00048 #include "Channels/IntensityChannel.H"
00049 #include "Channels/OrientationChannel.H"
00050 #include "Channels/RedGreenChannel.H"
00051 #include "Channels/Hue1Channel.H"
00052 #include "Channels/Hue2Channel.H"
00053 #include "Channels/HueChannel.H"
00054 #include "Channels/H2SVChannel.H"
00055 #include "Channels/CIELabChannel.H"
00056 #include "Channels/JunctionChannel.H"
00057 #include "Channels/EndPointChannel.H"
00058 #include "Channels/TJunctionChannel.H"
00059 #include "Channels/LJunctionChannel.H"
00060 #include "Channels/XJunctionChannel.H"
00061 #include "GUI/XWinManaged.H"
00062 #include "Image/CutPaste.H"
00063 #include "Image/DrawOps.H"
00064 #include "Image/FilterOps.H"
00065 #include "Image/MathOps.H"
00066 #include "Image/ShapeOps.H"
00067 #include "Neuro/gistParams.H"
00068 #include "Raster/Raster.H"
00069 #include "Simulation/SimEventQueue.H"
00070 #include "Neuro/NeuroSimEvents.H"
00071 #include "Simulation/SimEvents.H"
00072 #include "Channels/ChannelOpts.H"
00073 #include "Channels/SingleChannel.H"
00074 #include "Util/Timer.H"
00075 #include "Util/StringUtil.H"
00076 #include "Neuro/NeuroOpts.H"
00077
00078 #define PYR_LEVEL 5 // if without center surround then use 5 levels pyramid
00079
00080
00081
00082
00083 Image<float> getSubSumGen(Image<float> img)
00084 {
00085 Image<float> res(1, 21, ZEROS);
00086
00087 int w = img.getWidth(); int h = img.getHeight();
00088 std::vector<float> tempRes(21);
00089 for (int i = 0; i < 21; i++) tempRes[i] = 0.0;
00090 std::vector<int> counts(16);
00091 for (int i = 0 ; i < 16; i++) counts[i] = 0;
00092
00093 Image<float>::const_iterator itr = img.begin();
00094 for (int y = 0; y < h; ++y)
00095 {
00096 int suby = (4*y)/h;
00097 for (int x = 0; x < w; ++x)
00098 {
00099 int subx = (4*x)/w;
00100 int subpos = 4*suby + subx;
00101 tempRes[subpos+5] += *itr;
00102
00103 ++(counts[subpos]);
00104 ++itr;
00105 }
00106
00107 }
00108
00109 int order[] = { 5,6,9,10, 7,8,11,12, 13,14,17,18, 15,16,19,20 };
00110 for (int i = 0 ; i < 16; ++i)
00111 if (counts[i] > 0)
00112 res[i+5] = tempRes[order[i]] / (counts[order[i] - 5]+ 0.0);
00113
00114 float tre1 = tempRes[5] + tempRes[6] + tempRes[9] + tempRes[10];
00115 int ct1 = counts[0] + counts[1] + counts[4] + counts[5];
00116
00117 float tre2 = tempRes[7] + tempRes[8] + tempRes[11] + tempRes[12];
00118 int ct2 = counts[2] + counts[3] + counts[6] + counts[7];
00119
00120 float tre3 = tempRes[13] + tempRes[14] + tempRes[17] + tempRes[18];
00121 int ct3 = counts[8] + counts[9] + counts[12] + counts[13];
00122
00123 float tre4 = tempRes[15] + tempRes[16] + tempRes[19] + tempRes[20];
00124 int ct4 = counts[10] + counts[11] + counts[14] + counts[15];
00125
00126 res[1] = tre1/ct1;
00127 res[2] = tre2/ct2;
00128 res[3] = tre3/ct3;
00129 res[4] = tre4/ct4;
00130
00131 res[0] = (tre1 + tre2 + tre3 + tre4)/(ct1 + ct2 + ct3 + ct4);
00132
00133 LDEBUG("lev1 : %14.4f", res[0]);
00134 LDEBUG("lev2 : %14.4f, %14.4f", res[1], res[2]);
00135 LDEBUG(" : %14.4f, %14.4f", res[3], res[4]);
00136 LDEBUG("lev3 : %14.4f, %14.4f, %14.4f, %14.4f",
00137 res[ 5], res[ 6], res[ 9], res[10]);
00138 LDEBUG(" : %14.4f, %14.4f, %14.4f, %14.4f",
00139 res[ 7], res[ 8], res[11], res[12]);
00140 LDEBUG(" : %14.4f, %14.4f, %14.4f, %14.4f",
00141 res[13], res[14], res[17], res[18]);
00142 LDEBUG(" : %14.4f, %14.4f, %14.4f, %14.4f",
00143 res[15], res[16], res[19], res[20]);
00144
00145 return res;
00146 }
00147
00148
00149
00150 GistEstimatorGen::GistEstimatorGen(OptionManager& mgr,
00151 const std::string& descrName,
00152 const std::string& tagName) :
00153 GistEstimatorAdapter(mgr, descrName, tagName),
00154 SIMCALLBACK_INIT(SimEventVisualCortexOutput),
00155 itsLevelSpec(&OPT_LevelSpec, this),
00156 itsUseCS(&OPT_GistCenterSurroundFlag,this)
00157 {
00158 itsGistSize = 0;
00159 }
00160
00161
00162 GistEstimatorGen::~GistEstimatorGen()
00163 { }
00164
00165
00166 void GistEstimatorGen::
00167 onSimEventVisualCortexOutput(SimEventQueue& q, rutz::shared_ptr<SimEventVisualCortexOutput>& e)
00168 {
00169
00170 rutz::shared_ptr<SimReqVCXmaps> vcxm(new SimReqVCXmaps(this));
00171 q.request(vcxm);
00172 rutz::shared_ptr<ChannelMaps> chm = vcxm->channelmaps();
00173
00174
00175 getFeatureVector(chm);
00176
00177
00178 rutz::shared_ptr<SimEventGistOutput>
00179 ew(new SimEventGistOutput(this, itsGistVector));
00180 q.post(ew);
00181 }
00182
00183
00184 Image<double> GistEstimatorGen::getGist()
00185 {
00186 return itsGistVector;
00187 }
00188
00189
00190 void GistEstimatorGen::start1()
00191 {
00192 getManager().setOptionValString(&OPT_SingleChannelComputeFullPyramidForGist,"true");
00193 GistEstimatorAdapter::start1();
00194 }
00195
00196
00197 void GistEstimatorGen::getFeatureVector(rutz::shared_ptr<ChannelMaps> chanMaps)
00198 {
00199
00200 int sz = 0, sz_cs=0, sz_nocs = 0;
00201 if(itsUseCS.getVal() == 1 || itsUseCS.getVal() == 2)
00202 sz_cs += chanMaps->numSubmaps();
00203
00204
00205 if(itsUseCS.getVal() == 0 || itsUseCS.getVal() == 2)
00206 for(uint i=0; i < chanMaps->numSubchans(); i++)
00207 {
00208 rutz::shared_ptr<ChannelMaps> currChan = chanMaps->subChanMaps(i);
00209 if(currChan->numSubchans() == 0)
00210 sz_nocs++;
00211 else
00212 sz_nocs += currChan->numSubchans();
00213 }
00214 sz_nocs *= PYR_LEVEL;
00215
00216 sz = sz_cs + sz_nocs;
00217 LINFO("there are in total %4d gist feature chans", sz);
00218 itsGistVector.resize(1,NUM_GIST_FEAT * sz, NO_INIT);
00219
00220 int count = 0;
00221
00222
00223 if(itsUseCS.getVal() == 1 || itsUseCS.getVal() == 2)
00224 for(int i = 0; i<sz_cs; i++)
00225 {
00226 inplacePaste(itsGistVector,getSubSumGen(chanMaps->getRawCSmap(i)),
00227 Point2D<int>(0, count*NUM_GIST_FEAT));
00228 count++;
00229 }
00230
00231
00232 if(itsUseCS.getVal() == 0 || itsUseCS.getVal() == 2)
00233 for(uint i=0; i<chanMaps->numSubchans(); i++)
00234 {
00235 rutz::shared_ptr<ChannelMaps> currChan = chanMaps->subChanMaps(i);
00236 if(currChan->numSubchans() == 0)
00237 {
00238 ASSERT(currChan->hasPyramid());
00239 for(uint j=0; j<PYR_LEVEL; j++)
00240 {
00241 inplacePaste(itsGistVector,getSubSumGen
00242 (currChan->getPyramid().getImage(j)),
00243 Point2D<int>(0,count*NUM_GIST_FEAT));
00244 count++;
00245 }
00246 }
00247 else
00248 {
00249 for(uint i=0; i<currChan->numSubchans(); i++)
00250 {
00251 rutz::shared_ptr<ChannelMaps> currSubChan = currChan->subChanMaps(i);
00252 ASSERT(currSubChan->hasPyramid());
00253 for(uint j=0; j<PYR_LEVEL; j++)
00254 {
00255 inplacePaste(itsGistVector,getSubSumGen
00256 (currSubChan->getPyramid().getImage(j)),
00257 Point2D<int>(0,count*NUM_GIST_FEAT));
00258 count++;
00259 }
00260 }
00261 }
00262 }
00263 ASSERT(count == sz);
00264 itsGistSize = sz;
00265 }
00266
00267
00268
00269 Image<float> GistEstimatorGen::getGistImage(int sqSize,
00270 float minO, float maxO,
00271 float minC, float maxC,
00272 float minI, float maxI)
00273 {
00274
00275 int s = sqSize;
00276 Image<float> img(NUM_GIST_COL * s, NUM_GIST_FEAT * s, ZEROS);
00277 float range;
00278
00279
00280 if(maxO == minO)
00281 {
00282 minO = itsGistVector.getVal(0);
00283 maxO = itsGistVector.getVal(0);
00284 for(int i = 0; i < 16; i++)
00285 for(int j = 0; j < NUM_GIST_FEAT; j++)
00286 {
00287 float val = itsGistVector.getVal(i*NUM_GIST_FEAT+j);
00288 if(val < minO)
00289 minO = val;
00290 else if(val > maxO)
00291 maxO = val;
00292 }
00293 LDEBUG("Orientation Channel Min: %f, max: %f", minO, maxO);
00294 }
00295 range = maxO - minO;
00296
00297
00298 for(int a = 0; a < 4; a++)
00299 for(int b = 0; b < 4; b++)
00300 for(int j = 0; j < NUM_GIST_FEAT; j++)
00301 {
00302 int i = b*4 + a;
00303 int ii = a*4 + b;
00304 float val = itsGistVector.getVal(ii*NUM_GIST_FEAT+j);
00305
00306
00307 drawPatch(img, Point2D<int>(i*s+s/2,j*s+s/2),s/2,(val-minO)/range);
00308
00309 }
00310
00311
00312 if(maxC == minC)
00313 {
00314 minC = itsGistVector.getVal(16*NUM_GIST_FEAT);
00315 maxC = itsGistVector.getVal(16*NUM_GIST_FEAT);
00316 for(int i = 16; i < 28; i++)
00317 for(int j = 0; j < NUM_GIST_FEAT; j++)
00318 {
00319 float val = itsGistVector.getVal(i*NUM_GIST_FEAT+j);
00320 if(val < minC)
00321 minC = val;
00322 else if(val > maxC)
00323 maxC = val;
00324 }
00325 LDEBUG("Color Channel Min: %f, max: %f", minC, maxC);
00326 }
00327 range = maxC - minC;
00328
00329
00330 for(int i = 16; i < 28; i++)
00331 for(int j = 0; j < NUM_GIST_FEAT; j++)
00332 {
00333 float val = itsGistVector.getVal(i*NUM_GIST_FEAT+j);
00334
00335
00336 drawPatch(img, Point2D<int>(i*s+s/2,j*s+s/2),s/2,(val-minC)/range);
00337
00338 }
00339
00340
00341 if(maxI == minI)
00342 {
00343 minI = itsGistVector.getVal(28*NUM_GIST_FEAT);
00344 maxI = itsGistVector.getVal(28*NUM_GIST_FEAT);
00345 for(int i = 28; i < 34; i++)
00346 for(int j = 0; j < NUM_GIST_FEAT; j++)
00347 {
00348 float val = itsGistVector.getVal(i*NUM_GIST_FEAT+j);
00349 if(val < minI)
00350 minI = val;
00351 else if(val > maxI)
00352 maxI = val;
00353 }
00354 LDEBUG("Intensity Channel Min: %f, max: %f", minI, maxI);
00355 }
00356 range = maxI - minI;
00357
00358
00359 for(int i = 28; i < NUM_GIST_COL; i++)
00360 for(int j = 0; j < NUM_GIST_FEAT; j++)
00361 {
00362 float val = itsGistVector.getVal(i*NUM_GIST_FEAT+j);
00363
00364
00365 drawPatch(img, Point2D<int>(i*s+s/2,j*s+s/2),s/2,(val-minI)/range);
00366
00367 }
00368
00369
00370
00371 float max = 1.0f;
00372 drawLine(img, Point2D<int>(0, 1*s), Point2D<int>(NUM_GIST_COL*s, 1*s), max, 1);
00373 drawLine(img, Point2D<int>(0, 5*s), Point2D<int>(NUM_GIST_COL*s, 5*s), max, 1);
00374 drawLine(img, Point2D<int>(0, 9*s), Point2D<int>(NUM_GIST_COL*s, 9*s), max/2, 1);
00375 drawLine(img, Point2D<int>(0, 13*s), Point2D<int>(NUM_GIST_COL*s, 13*s), max/2, 1);
00376 drawLine(img, Point2D<int>(0, 17*s), Point2D<int>(NUM_GIST_COL*s, 17*s), max/2, 1);
00377
00378
00379 drawLine(img, Point2D<int>( 4*s, 0), Point2D<int>( 4*s, NUM_GIST_FEAT*s), max, 1);
00380 drawLine(img, Point2D<int>( 8*s, 0), Point2D<int>( 8*s, NUM_GIST_FEAT*s), max, 1);
00381 drawLine(img, Point2D<int>(12*s, 0), Point2D<int>(12*s, NUM_GIST_FEAT*s), max, 1);
00382 drawLine(img, Point2D<int>(16*s, 0), Point2D<int>(16*s, NUM_GIST_FEAT*s), max, 1);
00383 drawLine(img, Point2D<int>(22*s, 0), Point2D<int>(22*s, NUM_GIST_FEAT*s), max, 1);
00384 drawLine(img, Point2D<int>(28*s, 0), Point2D<int>(28*s, NUM_GIST_FEAT*s), max, 1);
00385
00386 return img;
00387 }
00388
00389
00390
00391 Image<float> GistEstimatorGen::diffGist(Image<float> in)
00392 {
00393 LFATAL("fix");
00394 float total = 0.0;
00395 float a,b,c,d;
00396
00397 for(int i = 0; i < NUM_GIST_COL; i++)
00398 {
00399 for(int j = 0; j < NUM_GIST_FEAT; j++)
00400 {
00401 a = itsGistVector.getVal(i*NUM_GIST_FEAT +j) /
00402 itsGistVector.getVal(i*NUM_GIST_FEAT);
00403 b = in.getVal(i*NUM_GIST_FEAT +j) / in.getVal(i*NUM_GIST_FEAT);
00404 c = itsGistVector.getVal(i*NUM_GIST_FEAT) +
00405 in.getVal(i*NUM_GIST_FEAT);
00406 d = (a - b) * c/2;
00407 LINFO("%6.3f - %6.3f = %f",a,b,fabs(d));
00408
00409 if((j-5)%4 == 3) LINFO("-:-:-");
00410 total += sqrt((d*d));
00411 }
00412 LINFO(" ");
00413 }
00414 LINFO("Diff = %f -> %f\n",total,total/NUM_GIST_COL/NUM_GIST_FEAT);
00415 Raster::waitForKey();
00416
00417 return Image<float>();
00418 }
00419
00420
00421
00422
00423 int GistEstimatorGen::getGistSize()
00424 {
00425 return itsGistSize;
00426 }
00427
00428
00429
00430
00431
00432
00433
00434