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 #ifndef GANGLION_C_DEFINED
00039 #define GANGLION_C_DEFINED
00040
00041 #include "plugins/SceneUnderstanding/Ganglion.H"
00042
00043 #include "Image/DrawOps.H"
00044 #include "Image/MathOps.H"
00045 #include "Image/Layout.H"
00046 #include "Simulation/SimEventQueue.H"
00047 #include "Simulation/SimEvents.H"
00048 #include "Media/MediaSimEvents.H"
00049 #include "Channels/InputFrame.H"
00050 #include "Image/Kernels.H"
00051 #include "Image/FilterOps.H"
00052 #include "Image/Convolutions.H"
00053 #include "GUI/DebugWin.H"
00054 #include <math.h>
00055 #include <fcntl.h>
00056 #include <limits>
00057 #include <string>
00058
00059 const ModelOptionCateg MOC_GANGLION = {
00060 MOC_SORTPRI_3, "Ganglion-Related Options" };
00061
00062
00063 const ModelOptionDef OPT_GanglionShowDebug =
00064 { MODOPT_ARG(bool), "GanglionShowDebug", &MOC_GANGLION, OPTEXP_CORE,
00065 "Show debug img",
00066 "ganglion-debug", '\0', "<true|false>", "false" };
00067
00068
00069
00070
00071 Ganglion::Ganglion(OptionManager& mgr, const std::string& descrName,
00072 const std::string& tagName) :
00073 SimModule(mgr, descrName, tagName),
00074 SIMCALLBACK_INIT(SimEventInputFrame),
00075 SIMCALLBACK_INIT(SimEventSaveOutput),
00076 itsShowDebug(&OPT_GanglionShowDebug, this)
00077
00078 {
00079 init(Dims(320,240));
00080 }
00081
00082
00083 Ganglion::~Ganglion()
00084 {
00085
00086 }
00087
00088
00089 void Ganglion::init(Dims numCells)
00090 {
00091 Image<float> img(numCells, ZEROS);
00092 itsGanglionCellsMu.push_back(img);
00093 itsGanglionCellsInput.push_back(img);
00094 itsGanglionCellsOutput.push_back(img);
00095 itsGanglionCellsOutput.push_back(img);
00096
00097 img.clear(1.0);
00098 itsGanglionCellsSig.push_back(img);
00099 itsGanglionCellsPrior.push_back(img);
00100
00101
00102
00103
00104 itsProbe.i = -1;
00105 itsProbe.j = -1;
00106
00107
00108
00109
00110 }
00111
00112
00113 void Ganglion::onSimEventInputFrame(SimEventQueue& q,
00114 rutz::shared_ptr<SimEventInputFrame>& e)
00115 {
00116
00117 const Image<PixRGB<byte> > inimg = e->frame().asRgb();
00118 itsCurrentImg = inimg;
00119
00120
00121 Image<float> rg, by;
00122 getRGBY(inimg, rg, by, 25.0F);
00123
00124
00125 Image<float> in = rg;
00126 inplaceNormalize(in, 0.0F, 255.0F);
00127
00128 Image<byte> input = luminance(inimg);
00129
00130
00131 itsGanglionCellsInput[LUM] = input;
00132
00133
00134
00135
00136 evolve();
00137
00138
00139 q.post(rutz::make_shared(new SimEventGanglionOutput(this, itsGanglionCellsOutput)));
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 }
00153
00154
00155 void Ganglion::onSimEventSaveOutput(SimEventQueue& q, rutz::shared_ptr<SimEventSaveOutput>& e)
00156 {
00157 if (itsShowDebug.getVal())
00158 {
00159
00160
00161 nub::ref<FrameOstream> ofs =
00162 dynamic_cast<const SimModuleSaveInfo&>(e->sinfo()).ofs;
00163 Layout<PixRGB<byte> > disp = getDebugImage();
00164 ofs->writeRgbLayout(disp, "Ganglion", FrameInfo("Ganglion", SRC_POS));
00165
00166
00167
00168
00169 }
00170 }
00171
00172
00173 void Ganglion::setBias(const ImageSet<float>& prior)
00174 {
00175
00176 Point2D<int> maxPos; float maxVal;
00177 findMax(prior[0], maxPos, maxVal);
00178 LINFO("maxVal %f", maxVal);
00179
00180
00181 float filter_period = 100;
00182 float elongation = 2.0;
00183 float angle = 90;
00184 int size = -1;
00185 const double major_stddev = filter_period / 30.0;
00186 const double minor_stddev = major_stddev * elongation;
00187
00188 Image<float> gabor = gaborFilter3(major_stddev, minor_stddev,
00189 filter_period, 90, 180 - angle + 90.0 , size);
00190
00191 gabor -= mean(gabor);
00192
00193
00194 gabor /= sum(squared(gabor));
00195
00196 gabor *= 20;
00197 gabor += 1.0;
00198
00199 const int w = itsGanglionCellsMu[0].getWidth(), h = itsGanglionCellsMu[0].getHeight();
00200 const int Nx = gabor.getWidth(), Ny = gabor.getHeight();
00201 Image<float> result = itsGanglionCellsMu[0];
00202
00203
00204 Image<float>::const_iterator sptr = itsGanglionCellsMu[0].begin();
00205 Image<float>::iterator dptr = result.beginw();
00206
00207 const int kkk = Nx * Ny - 1;
00208 const int Nx2 = (Nx - 1) / 2;
00209 const int Ny2 = (Ny - 1) / 2;
00210
00211 const float* filter = gabor.getArrayPtr();
00212
00213
00214 for (int j = 0; j < h; ++j)
00215 {
00216 const int j_offset = j-Ny2;
00217
00218 for (int i = 0; i < w; ++i)
00219 {
00220 if (prior[0].getVal(i,j) > 1)
00221 {
00222
00223 const int i_offset = i-Nx2;
00224 const int kj_bgn = std::max(- j_offset, 0);
00225 const int kj_end = std::min(h - j_offset, Ny);
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 for (int kj = kj_bgn; kj < kj_end; ++kj)
00248 {
00249 const int kjj = kj + j_offset;
00250 const int src_offset = w * kjj + i_offset;
00251 const int filt_offset = kkk - Nx*kj;
00252
00253 const int ki_bgn = std::max(-i_offset, 0);
00254 const int ki_end = std::min(w-i_offset, Nx);
00255
00256 for (int ki = ki_bgn; ki < ki_end; ++ki)
00257 {
00258 dptr[ki + src_offset] += sptr[ki + src_offset] * filter[filt_offset - ki];
00259
00260 }
00261 }
00262
00263 }
00264
00265 }
00266 }
00267 LINFO("Result");
00268 SHOWIMG(result);
00269 itsGanglionCellsMu[0] = result;
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 void Ganglion::setInput(const Image<PixRGB<byte> > &img)
00322 {
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 Image<byte> input = luminance(img);
00333 if (itsProbe.isValid())
00334 {
00335 printf("%i %i %i %i %i\n", input.getVal(itsProbe),
00336 input.getVal(itsProbe.i-1, itsProbe.j-1),
00337 input.getVal(itsProbe.i+1, itsProbe.j-1),
00338 input.getVal(itsProbe.i+1, itsProbe.j+1),
00339 input.getVal(itsProbe.i-1, itsProbe.j+1));
00340 }
00341
00342
00343 itsGanglionCellsInput[LUM] = input;
00344
00345
00346
00347
00348
00349 evolve();
00350 }
00351
00352
00353 void Ganglion::evolve()
00354 {
00355 float R = 3.5;
00356 float Q=0.5;
00357
00358
00359 for(int i=0; i<1; i++)
00360 {
00361
00362
00363 Image<float>::const_iterator inPtr = itsGanglionCellsInput[i].begin();
00364 Image<float>::const_iterator inStop = itsGanglionCellsInput[i].end();
00365
00366 Image<float>::iterator gangMuPtr = itsGanglionCellsMu[i].beginw();
00367 Image<float>::iterator gangPriorPtr = itsGanglionCellsPrior[i].beginw();
00368 Image<float>::iterator gangSigPtr = itsGanglionCellsSig[i].beginw();
00369 Image<float>::iterator outMuPtr = itsGanglionCellsOutput[0].beginw();
00370 Image<float>::iterator outSigPtr = itsGanglionCellsOutput[1].beginw();
00371
00372
00373 while(inPtr != inStop)
00374 {
00375
00376 float mu_hat = *gangMuPtr;
00377 float sig_hat = *gangSigPtr + Q;
00378
00379
00380 float K = (sig_hat)/(sig_hat + R);
00381 *gangMuPtr = mu_hat + K * (*inPtr - mu_hat);
00382 *gangSigPtr = (1-K)*sig_hat;
00383
00384
00385
00386
00387
00388 float surprise = (((*gangMuPtr-mu_hat)*(*gangMuPtr-mu_hat)) + (*gangSigPtr * *gangSigPtr) + (sig_hat*sig_hat));
00389 surprise = surprise / (2*sig_hat*sig_hat);
00390 surprise += log(sig_hat / *gangSigPtr);
00391
00392
00393
00394
00395
00396 *outMuPtr = *inPtr;
00397 *outSigPtr = *gangSigPtr;
00398
00399 ++inPtr;
00400 ++gangMuPtr;
00401 ++gangPriorPtr;
00402 ++gangSigPtr;
00403 ++outMuPtr;
00404 ++outSigPtr;
00405 }
00406 }
00407
00408 }
00409
00410 Layout<PixRGB<byte> > Ganglion::getDebugImage()
00411 {
00412 Layout<PixRGB<byte> > outDisp;
00413
00414 Image<float> gangIn = itsGanglionCellsInput[0];
00415 Image<float> gangPercMu = itsGanglionCellsMu[0];
00416
00417
00418
00419
00420
00421 inplaceNormalize(gangIn, 0.0F, 255.0F);
00422
00423
00424 if (itsProbe.isValid())
00425 drawCircle(gangIn, itsProbe, 6, 255.0F);
00426 inplaceNormalize(gangPercMu, 0.0F, 255.0F);
00427
00428
00429
00430 Layout<PixRGB<byte> > disp;
00431 disp = hcat(itsCurrentImg, toRGB(Image<byte>(gangPercMu)));
00432
00433
00434 outDisp = vcat(outDisp, disp);
00435
00436 return outDisp;
00437
00438 }
00439
00440
00441
00442
00443
00444
00445
00446 #endif
00447