WinnerTakeAll.C

Go to the documentation of this file.
00001 /*!@file Neuro/WinnerTakeAll.C 2D winner-take-all network */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00005 // University of Southern California (USC) and the iLab at USC.         //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Neuro/WinnerTakeAll.C $
00035 // $Id: WinnerTakeAll.C 13065 2010-03-28 00:01:00Z itti $
00036 //
00037 
00038 #include "Neuro/WinnerTakeAll.H"
00039 
00040 #include "Channels/ChannelOpts.H" // for OPT_LevelSpec
00041 #include "Component/GlobalOpts.H"
00042 #include "Component/OptionManager.H"
00043 #include "Image/Image.H"
00044 #include "Image/MathOps.H"
00045 #include "Image/Transforms.H" // for chamfer34()
00046 #include "Neuro/NeuroOpts.H"
00047 #include "Neuro/WTAwinner.H"
00048 #include "Neuro/NeuroSimEvents.H"
00049 #include "Simulation/SimEventQueue.H"
00050 #include "Simulation/SimEvents.H"
00051 #include "Transport/FrameInfo.H"
00052 #include "Transport/FrameOstream.H"
00053 #include "Util/TextLog.H"
00054 #include "Util/log.H"
00055 #include "Util/sformat.H"
00056 #include "rutz/trace.h"
00057 
00058 // ######################################################################
00059 // ######################################################################
00060 // ########## WinnerTakeAll implementation
00061 // ######################################################################
00062 // ######################################################################
00063 
00064 WinnerTakeAll::WinnerTakeAll(OptionManager& mgr,
00065                              const std::string& descrName,
00066                              const std::string& tagName) :
00067   SimModule(mgr, descrName, tagName)
00068 {
00069 GVX_TRACE(__PRETTY_FUNCTION__);
00070 }
00071 
00072 // ######################################################################
00073 WinnerTakeAll::~WinnerTakeAll()
00074 {
00075 GVX_TRACE(__PRETTY_FUNCTION__);
00076 }
00077 
00078 // ######################################################################
00079 // ######################################################################
00080 // ########## WinnerTakeAllStub implementation
00081 // ######################################################################
00082 // ######################################################################
00083 
00084 WinnerTakeAllStub::WinnerTakeAllStub(OptionManager& mgr,
00085                                      const std::string& descrName,
00086                                      const std::string& tagName) :
00087   WinnerTakeAll(mgr, descrName, tagName)
00088 {
00089 GVX_TRACE(__PRETTY_FUNCTION__);
00090 }
00091 
00092 // ######################################################################
00093 WinnerTakeAllStub::~WinnerTakeAllStub()
00094 {
00095 GVX_TRACE(__PRETTY_FUNCTION__);
00096 }
00097 
00098 // ######################################################################
00099 // ######################################################################
00100 // ########## WinnerTakeAllAdapter implementation
00101 // ######################################################################
00102 // ######################################################################
00103 
00104 WinnerTakeAllAdapter::WinnerTakeAllAdapter(OptionManager& mgr,
00105                                            const std::string& descrName,
00106                                            const std::string& tagName) :
00107   WinnerTakeAll(mgr, descrName, tagName),
00108   SIMCALLBACK_INIT(SimEventAttentionGuidanceMapOutput),
00109   SIMCALLBACK_INIT(SimEventSaccadeStatusEye),
00110   SIMCALLBACK_INIT(SimEventInputFrame),
00111   SIMCALLBACK_INIT(SimEventSaveOutput),
00112   itsLogFile(&OPT_TextLogFile, this),
00113   itsSaveResults(&OPT_WTAsaveResults, this), // see Neuro/NeuroOpts.{H,C}
00114   itsUseSaccadicSuppression(&OPT_WTAuseSacSuppress, this),
00115   itsUseBlinkSuppression(&OPT_WTAuseBlinkSuppress, this),
00116   itsLevelSpec(&OPT_LevelSpec, this),
00117   itsUseRandom(&OPT_UseRandom, this), // see Component/ModelManager.{H,C}
00118   itsTooManyShifts(&OPT_BrainTooManyShifts, this), // Neuro/NeuroOpts.{H,C}
00119   itsTooManyShiftsPerFrame(&OPT_BrainTooManyShiftsPerFrame, this), // Neuro/NeuroOpts.{H,C}
00120   itsBoringDelay(&OPT_BrainBoringDelay, this),
00121   itsBoringSMmv(&OPT_BrainBoringSMmv, this),
00122   itsNumShifts(0),
00123   itsInputCopy(),
00124   itsEyePos(-1, -1),
00125   itsLastWinner(WTAwinner::NONE())
00126 {
00127 GVX_TRACE(__PRETTY_FUNCTION__);
00128 }
00129 
00130 // ######################################################################
00131 WinnerTakeAllAdapter::~WinnerTakeAllAdapter()
00132 {
00133 GVX_TRACE(__PRETTY_FUNCTION__);
00134 }
00135 
00136 // ######################################################################
00137 void WinnerTakeAllAdapter::reset1()
00138 {
00139 GVX_TRACE(__PRETTY_FUNCTION__);
00140   itsNumShifts = 0;
00141   itsInputCopy.freeMem();
00142   itsEyePos = Point2D<int>(-1, -1);
00143   WinnerTakeAll::reset1();
00144 }
00145 
00146 // ######################################################################
00147 void WinnerTakeAllAdapter::
00148 onSimEventInputFrame(SimEventQueue& q, rutz::shared_ptr<SimEventInputFrame>& e)
00149 {
00150   itsNumShifts = 0; // Reset at each new frame
00151 }
00152 
00153 // ######################################################################
00154 void WinnerTakeAllAdapter::
00155 onSimEventAttentionGuidanceMapOutput(SimEventQueue& q, rutz::shared_ptr<SimEventAttentionGuidanceMapOutput>& e)
00156 {
00157   // process the input:
00158   itsInputCopy = e->agm();
00159   this->input(itsInputCopy);
00160 
00161   // evolve our internals:
00162   Point2D<int> winner(-1,-1);
00163   this->integrate(q.now(), winner);
00164 
00165   // stop here if we have already too many shifts per frame:
00166   if (itsTooManyShiftsPerFrame.getVal() > 0 &&  itsNumShifts >= itsTooManyShiftsPerFrame.getVal()) return;
00167 
00168   // did we just get a winner?
00169   if (winner.isValid())
00170     {
00171       WTAwinner newwin = WTAwinner::buildFromSMcoords(winner, itsLevelSpec.getVal().mapLevel(),
00172                                                       itsUseRandom.getVal(), q.now(),
00173                                                       itsInputCopy.getVal(winner), false);
00174 
00175       // if the last covert attention shift was slow or the SM voltage
00176       // was low, mark the covert attention shift as boring:
00177       if ( (itsLastWinner.t > SimTime::ZERO() && newwin.t - itsLastWinner.t > itsBoringDelay.getVal() ) ||
00178            newwin.sv < itsBoringSMmv.getVal() * 0.001)
00179         newwin.boring = true;
00180 
00181       LINFO("##### WinnerTakeAll winner (%d,%d) at %fms %s#####",
00182             newwin.p.i, newwin.p.j, newwin.t.msecs(), newwin.boring ? "[boring] ":"");
00183 
00184       // log what happened:
00185       textLog(itsLogFile.getVal(), "CovertShift",
00186               sformat("(%d,%d) %.3fmV", newwin.p.i, newwin.p.j, newwin.sv * 1000.0F), newwin.t);
00187       itsLastWinner = newwin;
00188 
00189       // post an event so that anyone interested in the winner can grab it:
00190       q.post(rutz::make_shared(new SimEventWTAwinner(this, newwin, itsNumShifts)));
00191 
00192       // also notify that if we have a SimOutputFrameSeries that is
00193       // operating in event-driven mode (no framerate was specified on
00194       // the command-line), this covert shift is a good reason to save
00195       // outputs now:
00196       q.post(rutz::make_shared(new SimEventRequestSaveOutput(this)));
00197 
00198       // that's one more shift of attention:
00199       ++itsNumShifts;
00200 
00201       // too many shifts of attention?
00202       if (itsTooManyShifts.getVal() > 0 && itsNumShifts >= itsTooManyShifts.getVal())
00203         q.post(rutz::make_shared(new SimEventBreak(this, "Too many attention shifts")));
00204     }
00205 }
00206 
00207 // ######################################################################
00208 void WinnerTakeAllAdapter::
00209 onSimEventSaccadeStatusEye(SimEventQueue& q, rutz::shared_ptr<SimEventSaccadeStatusEye>& e)
00210 {
00211   this->eyeMovement(e->position());
00212 
00213   // should we also turn saccadic suppression on/off?
00214   TransientStatus evs = e->saccadeStatus();
00215   if (evs == TSTATUS_BEGIN) this->saccadicSuppression(true);
00216   else if (evs == TSTATUS_END) this->saccadicSuppression(false);
00217 
00218   // how about blink suppression?
00219   TransientStatus evb = e->blinkStatus();
00220   if (evb == TSTATUS_BEGIN) this->blinkSuppression(true);
00221   else if (evb == TSTATUS_END) this->blinkSuppression(false);
00222 }
00223 
00224 // ######################################################################
00225 void WinnerTakeAllAdapter::eyeMovement(const Point2D<int>& curreye)
00226 {
00227 GVX_TRACE(__PRETTY_FUNCTION__);
00228   itsEyePos = curreye;
00229 }
00230 
00231 // ######################################################################
00232 void WinnerTakeAllAdapter::
00233 onSimEventSaveOutput(SimEventQueue& q, rutz::shared_ptr<SimEventSaveOutput>& e)
00234 {
00235   if (itsSaveResults.getVal())
00236     {
00237       // get the OFS to save to, assuming sinfo is of type
00238       // SimModuleSaveInfo (will throw a fatal exception otherwise):
00239       nub::ref<FrameOstream> ofs =
00240         dynamic_cast<const SimModuleSaveInfo&>(e->sinfo()).ofs;
00241       ofs->writeFloat(this->getV(), FLOAT_NORM_PRESERVE, "WTA",
00242                       FrameInfo("winner-take-all map", SRC_POS));
00243     }
00244 }
00245 
00246 // ######################################################################
00247 // ######################################################################
00248 // ########## WinnerTakeAllStd implementation
00249 // ######################################################################
00250 // ######################################################################
00251 
00252 WinnerTakeAllStd::WinnerTakeAllStd(OptionManager& mgr,
00253                                    const std::string& descrName,
00254                                    const std::string& tagName) :
00255   WinnerTakeAllAdapter(mgr, descrName, tagName),
00256   itsNeurons(),
00257   itsGIN(), itsT(), itsGleak(1.0e-8F), itsGinh(1.0e-2F), itsGinput(5.0e-8F)
00258 {
00259 GVX_TRACE(__PRETTY_FUNCTION__);
00260   itsGIN.setGleak(itsGleak);
00261 }
00262 
00263 // ######################################################################
00264 WinnerTakeAllStd::~WinnerTakeAllStd()
00265 {
00266 GVX_TRACE(__PRETTY_FUNCTION__);
00267 }
00268 
00269 // ######################################################################
00270 void WinnerTakeAllStd::reset1()
00271 {
00272 GVX_TRACE(__PRETTY_FUNCTION__);
00273   itsNeurons.freeMem();
00274   itsGleak = 1.0e-8F;
00275   itsGinh = 1.0e-2F;
00276   itsGinput = 5.0e-8F;
00277   itsT = SimTime::ZERO();
00278 
00279   WinnerTakeAllAdapter::reset1();
00280 }
00281 
00282 // ######################################################################
00283 void WinnerTakeAllStd::input(const Image<float>& in)
00284 {
00285 GVX_TRACE(__PRETTY_FUNCTION__);
00286   if (itsNeurons.initialized() == false) {
00287     // first input, let's initialize our array
00288     itsNeurons.resize(in.getDims(), ZEROS);
00289 
00290     Image<LeakyIntFire>::iterator
00291       nptr = itsNeurons.beginw(), stop = itsNeurons.endw();
00292     while (nptr != stop)
00293       {
00294         nptr->setGleak(itsGleak);
00295         nptr->setG(0.0F, itsGinh);
00296         ++nptr;
00297       }
00298   }
00299 }
00300 
00301 // ######################################################################
00302 void WinnerTakeAllStd::integrate(const SimTime& t, Point2D<int>& winner)
00303 {
00304 GVX_TRACE(__PRETTY_FUNCTION__);
00305   winner.i = -1;
00306   const int w = itsNeurons.getWidth();
00307   const int h = itsNeurons.getHeight();
00308 
00309   // the array of neurons receive excitatory inputs from outside.
00310   // here we update the inputs and let the neurons evolve; here we
00311   // need to run this loop time step by time step, since this is a
00312   // feedback network, so we have code similar to that in
00313   // LeakyIntFire::evolve() to figure out how many time steps to run:
00314   const SimTime dt =
00315     SimTime::computeDeltaT((t - itsT), itsGIN.getTimeStep());
00316 
00317   for (SimTime tt = itsT; tt < t; tt += dt)
00318     {
00319       Image<LeakyIntFire>::iterator nptr = itsNeurons.beginw();
00320       Image<float>::const_iterator inptr = itsInputCopy.begin();
00321       for (int j = 0 ; j < h; j ++)
00322         for (int i = 0; i < w; i ++)
00323           {
00324             nptr->input(itsGinput * (*inptr++));
00325             if (nptr->integrate(tt)) { winner.i = i; winner.j = j; }
00326             nptr->setG(0.0F, 0.0F);  // only leak conductance
00327             ++nptr;
00328           }
00329 
00330       // if there is a winner, the winner triggers the global inhibition:
00331       if (winner.i > -1) itsGIN.setG(itsGleak * 10.0F, 0.0F);
00332 
00333       // when the global inhibition fires, it triggers inhibitory
00334       // conductances for one time step in the array of excited
00335       // neurons, shuts off excitatory conductances, and turns itself
00336       // off:
00337       if (itsGIN.integrate(tt)) inhibit();
00338     }
00339   itsT = t;
00340 }
00341 
00342 // ######################################################################
00343 Image<float> WinnerTakeAllStd::getV() const
00344 {
00345 GVX_TRACE(__PRETTY_FUNCTION__);
00346   Image<float> result(itsNeurons.getDims(), NO_INIT);
00347 
00348   Image<float>::iterator dptr = result.beginw(), stop = result.endw();
00349   Image<LeakyIntFire>::const_iterator nptr = itsNeurons.begin();
00350   while(dptr != stop) *dptr++ = (nptr++)->getV();
00351 
00352   return result;
00353 }
00354 
00355 // ######################################################################
00356 void WinnerTakeAllStd::inhibit()
00357 {
00358 GVX_TRACE(__PRETTY_FUNCTION__);
00359   Image<LeakyIntFire>::iterator
00360     nptr = itsNeurons.beginw(), stop = itsNeurons.endw();
00361   while(nptr != stop) (nptr++)->setG(0.0F, itsGinh);
00362   itsGIN.setG(0.0F, 0.0F);
00363   LDEBUG("WTA inhibition firing...");
00364 }
00365 
00366 // ######################################################################
00367 void WinnerTakeAllStd::saccadicSuppression(const bool on)
00368 {
00369 GVX_TRACE(__PRETTY_FUNCTION__);
00370   if (itsUseSaccadicSuppression.getVal() == false) return;
00371   if (on) inhibit();
00372   LINFO("------- WTA saccadic suppression %s -------", on ? "on":"off");
00373 }
00374 
00375 // ######################################################################
00376 void WinnerTakeAllStd::blinkSuppression(const bool on)
00377 {
00378 GVX_TRACE(__PRETTY_FUNCTION__);
00379   if (itsUseBlinkSuppression.getVal() == false) return;
00380   if (on) inhibit();
00381   LINFO("------- WTA blink suppression %s -------", on ? "on":"off");
00382 }
00383 
00384 // ######################################################################
00385 // ######################################################################
00386 // ########## WinnerTakeAllFast implementation
00387 // ######################################################################
00388 // ######################################################################
00389 
00390 WinnerTakeAllFast::WinnerTakeAllFast(OptionManager& mgr,
00391                                      const std::string& descrName,
00392                                      const std::string& tagName) :
00393   WinnerTakeAllAdapter(mgr, descrName, tagName)
00394 {
00395 GVX_TRACE(__PRETTY_FUNCTION__);
00396 }
00397 
00398 // ######################################################################
00399 WinnerTakeAllFast::~WinnerTakeAllFast()
00400 {
00401 GVX_TRACE(__PRETTY_FUNCTION__);
00402 }
00403 
00404 // ######################################################################
00405 void WinnerTakeAllFast::input(const Image<float>& in)
00406 {
00407 GVX_TRACE(__PRETTY_FUNCTION__);
00408 }
00409 
00410 // ######################################################################
00411 void WinnerTakeAllFast::integrate(const SimTime& t, Point2D<int>& winner)
00412 {
00413 GVX_TRACE(__PRETTY_FUNCTION__);
00414   float maxval;
00415   findMax(itsInputCopy, winner, maxval);
00416   if (maxval <= 1.0e-20F) { winner.i = -1; winner.j = -1; }
00417 
00418 }
00419 
00420 // ######################################################################
00421 Image<float> WinnerTakeAllFast::getV() const
00422 {
00423 GVX_TRACE(__PRETTY_FUNCTION__);
00424   return itsInputCopy;
00425 }
00426 
00427 // ######################################################################
00428 void WinnerTakeAllFast::saccadicSuppression(const bool on)
00429 {
00430 GVX_TRACE(__PRETTY_FUNCTION__);
00431   if (itsUseSaccadicSuppression.getVal() == false) return;
00432   if (on) itsInputCopy.clear();
00433   LINFO("------- WTA saccadic suppression %s -------", on ? "on":"off");
00434 }
00435 
00436 // ######################################################################
00437 void WinnerTakeAllFast::blinkSuppression(const bool on)
00438 {
00439 GVX_TRACE(__PRETTY_FUNCTION__);
00440   if (itsUseBlinkSuppression.getVal() == false) return;
00441   if (on) itsInputCopy.clear();
00442   LINFO("------- WTA blink suppression %s -------", on ? "on":"off");
00443 }
00444 
00445 // ######################################################################
00446 // ######################################################################
00447 // ########## WinnerTakeAllGreedy implementation
00448 // ######################################################################
00449 // ######################################################################
00450 
00451 WinnerTakeAllGreedy::WinnerTakeAllGreedy(OptionManager& mgr,
00452                                          const std::string& descrName,
00453                                          const std::string& tagName) :
00454   WinnerTakeAllStd(mgr, descrName, tagName),
00455   itsThresholdFac(&OPT_WinnerTakeAllGreedyThreshFac, this)
00456 {
00457 GVX_TRACE(__PRETTY_FUNCTION__);
00458 }
00459 
00460 // ######################################################################
00461 WinnerTakeAllGreedy::~WinnerTakeAllGreedy()
00462 {
00463 GVX_TRACE(__PRETTY_FUNCTION__);
00464 }
00465 
00466 // ######################################################################
00467 void WinnerTakeAllGreedy::integrate(const SimTime& t, Point2D<int>& winner)
00468 {
00469 GVX_TRACE(__PRETTY_FUNCTION__);
00470   if (itsEyePos.isValid() == false) CLFATAL("I need a valid eyepos");
00471 
00472   winner.i = -1;
00473   const int w = itsNeurons.getWidth();
00474   const int h = itsNeurons.getHeight();
00475 
00476   // the array of neurons receive excitatory inputs from outside.
00477   // here we update the inputs and let the neurons evolve; here we
00478   // need to run this loop time step by time step, since this is a
00479   // feedback network, so we have code similar to that in
00480   // LeakyIntFire::evolve() to figure out how many time steps to run:
00481   const SimTime dt =
00482     SimTime::computeDeltaT((t - itsT), itsGIN.getTimeStep());
00483 
00484   for (SimTime tt = itsT; tt < t; tt += dt)
00485     {
00486       Image<LeakyIntFire>::iterator nptr = itsNeurons.beginw();
00487       Image<float>::const_iterator inptr = itsInputCopy.begin();
00488       for (int j = 0 ; j < h; j ++)
00489         for (int i = 0; i < w; i ++)
00490           {
00491             nptr->input(itsGinput * (*inptr++));
00492             if (nptr->integrate(tt)) { winner.i = i; winner.j = j; }
00493             nptr->setG(0.0F, 0.0F);  // only leak conductance
00494             ++nptr;
00495           }
00496 
00497       // if there is a winner, the winner triggers the global
00498       // inhibition; but before that let's replace our true WTA winner
00499       // by whoever is above threshold and closest to current eye
00500       // position:
00501       if (winner.i > -1)
00502         {
00503           // get our current voltages:
00504           Image<float> v = getV();
00505 
00506           // do not consider values below threshold:
00507           float thresh = v.getVal(winner) * itsThresholdFac.getVal();
00508 
00509           // scale the current eye position down to salmap level coords:
00510           Point2D<int> eye = itsEyePos;
00511           const int smlevel = itsLevelSpec.getVal().mapLevel();
00512           eye.i = int(eye.i / double(1 << smlevel) + 0.49);
00513           eye.j = int(eye.j / double(1 << smlevel) + 0.49);
00514 
00515           // if eye out of image (or unknown), we will not do our
00516           // special greedy processing here and instead will just act
00517           // like a normal WTA:
00518           if (v.coordsOk(eye) && (eye.i != 0 || eye.j != 0))
00519             {
00520               // create distance map from a single pixel at our eye position:
00521               Image<float> dmap(v.getDims(), ZEROS);
00522               dmap.setVal(eye, 100.0f);
00523               dmap = chamfer34(dmap, 1000.0f);
00524 
00525               // let's scan the dmap and find the closest location
00526               // that is a local max and is above threshold:
00527               const int w = v.getWidth(), h = v.getHeight();
00528               float bestd = 1000.0f; Point2D<int> p;
00529 
00530               for (p.j = 0; p.j < h; p.j ++)
00531                 for (p.i = 0; p.i < w; p.i ++)
00532                   if (v.getVal(p) >= thresh &&  // we are above threshold
00533                       dmap.getVal(p) < bestd && // we are closer to eye
00534                       isLocalMax(v, p) == true)  // we are a local max
00535                     {
00536                       winner.i = p.i;
00537                       winner.j = p.j;
00538                       bestd = dmap.getVal(p);
00539                     }
00540             }
00541 
00542           // trigger global inhibition:
00543           itsGIN.setG(itsGleak * 10.0F, 0.0F);
00544         }
00545 
00546       // when the global inhibition fires, it triggers inhibitory
00547       // conductances for one time step in the array of excited
00548       // neurons, shuts off excitatory conductances, and turns itself
00549       // off:
00550       if (itsGIN.integrate(tt)) inhibit();
00551     }
00552   itsT = t;
00553 }
00554 
00555 // ######################################################################
00556 // ######################################################################
00557 // ########## WinnerTakeAll Temporal Noticing  implementation
00558 // ######################################################################
00559 // ######################################################################
00560 
00561 WinnerTakeAllTempNote::WinnerTakeAllTempNote(OptionManager& mgr,
00562                                    const std::string& descrName,
00563                                    const std::string& tagName) :
00564   WinnerTakeAllStd(mgr, descrName, tagName),
00565   itsNeurons(),
00566   itsGIN(), itsT(), itsGleak(1.0e-8F), itsGinh(1.0e-2F), itsGinput(5.0e-8F)
00567 {
00568 GVX_TRACE(__PRETTY_FUNCTION__);
00569   itsGIN.setGleak(itsGleak);
00570   itsHighMaskBound.resize(1,256.0F);
00571   itsLowMaskBound.resize(1,0.0002F);
00572 }
00573 
00574 // ######################################################################
00575 WinnerTakeAllTempNote::~WinnerTakeAllTempNote()
00576 {
00577 GVX_TRACE(__PRETTY_FUNCTION__);
00578 }
00579 
00580 // ######################################################################
00581 void WinnerTakeAllTempNote::reset1()
00582 {
00583 GVX_TRACE(__PRETTY_FUNCTION__);
00584   itsNeurons.freeMem();
00585   itsGleak = 1.0e-8F;
00586   itsGinh = 1.0e-2F;
00587   itsGinput = 5.0e-8F;
00588   itsT = SimTime::ZERO();
00589 
00590   WinnerTakeAllStd::reset1();
00591 }
00592 
00593 // ######################################################################
00594 void WinnerTakeAllTempNote::input(const Image<float>& in)
00595 {
00596 GVX_TRACE(__PRETTY_FUNCTION__);
00597   if (itsNeurons.initialized() == false) {
00598     // first input, let's initialize our array
00599     itsNeurons.resize(in.getDims(), ZEROS);
00600 
00601     Image<LeakyIntFireAdp>::iterator
00602       nptr = itsNeurons.beginw(), stop = itsNeurons.endw();
00603     while (nptr != stop)
00604     {
00605       nptr->setGleak(itsGleak);
00606       nptr->setG(0.0F, itsGinh);
00607       ++nptr;
00608     }
00609 
00610     int width  = in.getWidth();
00611     int height = in.getHeight();
00612 
00613     itsInitMask.resize(width,height);
00614 
00615     // set up mask segmenting
00616     itsMaskSegment.SIsetFrame(&width,&height);
00617     itsMaskSegment.SIsetValThresh(itsHighMaskBound,itsLowMaskBound);
00618     itsMaskSegment.SIsetAvg(1);
00619     itsMaskSegment.SItoggleCandidateBandPass(false);
00620   }
00621 }
00622 
00623 // ######################################################################
00624 void WinnerTakeAllTempNote::integrate(const SimTime& t, Point2D<int>& winner)
00625 {
00626 GVX_TRACE(__PRETTY_FUNCTION__);
00627   winner.i = -1;
00628   const int w = itsNeurons.getWidth();
00629   const int h = itsNeurons.getHeight();
00630 
00631   // the array of neurons receive excitatory inputs from outside.
00632   // here we update the inputs and let the neurons evolve; here we
00633   // need to run this loop time step by time step, since this is a
00634   // feedback network, so we have code similar to that in
00635   // LeakyIntFire::evolve() to figure out how many time steps to run:
00636   const SimTime dt =
00637     SimTime::computeDeltaT((t - itsT), itsGIN.getTimeStep());
00638 
00639   for (SimTime tt = itsT; tt < t; tt += dt)
00640   {
00641     Image<LeakyIntFireAdp>::iterator nptr = itsNeurons.beginw();
00642     Image<float>::const_iterator inptr    = itsInputCopy.begin();
00643     for (int j = 0 ; j < h; j ++)
00644     {
00645       for (int i = 0; i < w; i ++)
00646       {
00647         nptr->input(itsGinput * (*inptr++));
00648         if (nptr->integrate(tt)) { winner.i = i; winner.j = j; }
00649         nptr->setG(0.0F, 0.0F);  // only leak conductance
00650         ++nptr;
00651       }
00652     }
00653 
00654     // if there is a winner, the winner triggers the global inhibition:
00655     if (winner.i > -1)
00656     {
00657       itsGIN.setG(itsGleak * 10.0F, 0.0F);
00658     }
00659 
00660     if (winner.i > -1)
00661     {
00662       const float Vfire = itsNeurons.getVal(winner.i,winner.j).getVfire();
00663       const float V = itsNeurons.getVal(winner.i,winner.j).getV();
00664       LINFO("VFIRE IS %f",Vfire);
00665       LINFO("V is %f",V);
00666       std::vector<Image<float> > sal_input(1, itsInputCopy);
00667 
00668       // find out which neurons around the winner are salient based
00669       // on their salmap values
00670       itsMaskSegment.SIsegment(&sal_input,true);
00671       Image<long> maskCandidates = itsMaskSegment.SIreturnBlobs();
00672       const long winnerID = maskCandidates.getVal(winner.i, winner.j);
00673 
00674       itsInitMask = itsMaskSegment.SIreturnNormalizedCandidates();
00675 
00676       // for each salient pixel/neuron that is grouped with the winner
00677       // update its threshold fire value
00678       Image<long>::iterator  imask = maskCandidates.beginw();
00679       Image<float>::iterator isal  = itsInputCopy.beginw();
00680       Image<LeakyIntFireAdp>::iterator nptr = itsNeurons.beginw();
00681       for (int j = 0 ; j < h; j ++)
00682       {
00683         for (int i = 0; i < w; i ++)
00684         {
00685           if(*imask == winnerID)
00686           {
00687             LINFO("WINNER %d, %d - SLAVE %d, %d - ID %d",winner.i,winner.j,i,j
00688                   ,(int)winnerID);
00689             const float dist = sqrt(pow(winner.i - i,2) + pow(winner.j - j,2));
00690             nptr->setNewVth(*isal,Vfire,dist);
00691           }
00692           ++imask; ++isal; ++nptr;
00693         }
00694       }
00695     }
00696 
00697     // when the global inhibition fires, it triggers inhibitory
00698     // conductances for one time step in the array of excited
00699     // neurons, shuts off excitatory conductances, and turns itself
00700     // off:
00701     if (itsGIN.integrate(tt))
00702     {
00703       inhibit();
00704     }
00705   }
00706   itsT = t;
00707 }
00708 
00709 // ######################################################################
00710 Image<float> WinnerTakeAllTempNote::getV() const
00711 {
00712 GVX_TRACE(__PRETTY_FUNCTION__);
00713   Image<float> result(itsNeurons.getDims(), NO_INIT);
00714 
00715   Image<float>::iterator dptr = result.beginw(), stop = result.endw();
00716   Image<LeakyIntFireAdp>::const_iterator nptr = itsNeurons.begin();
00717   while(dptr != stop) *dptr++ = (nptr++)->getV();
00718 
00719   return result;
00720 }
00721 
00722 // ######################################################################
00723 Image<float> WinnerTakeAllTempNote::getVth(const bool normalize) const
00724 {
00725 GVX_TRACE(__PRETTY_FUNCTION__);
00726   Image<float> result(itsNeurons.getDims(),NO_INIT);
00727 
00728   Image<float>::iterator dptr = result.beginw(), stop = result.endw();
00729   Image<LeakyIntFireAdp>::const_iterator nptr = itsNeurons.begin();
00730   while(dptr != stop)
00731   {
00732     *dptr = (nptr)->getVth();
00733     ++dptr; ++nptr;
00734   }
00735 
00736   if (normalize)
00737     inplaceNormalize(result, 0.0F, 255.0F);
00738 
00739   result = result * 1000.0F;
00740 
00741   return result;
00742 }
00743 
00744 // ######################################################################
00745 void WinnerTakeAllTempNote::inhibit()
00746 {
00747 GVX_TRACE(__PRETTY_FUNCTION__);
00748   Image<LeakyIntFireAdp>::iterator
00749     nptr = itsNeurons.beginw(), stop = itsNeurons.endw();
00750   while(nptr != stop) (nptr++)->setG(0.0F, itsGinh);
00751   itsGIN.setG(0.0F, 0.0F);
00752   LDEBUG("WTA inhibition firing...");
00753 }
00754 
00755 // ######################################################################
00756 void WinnerTakeAllTempNote::saccadicSuppression(const bool on)
00757 {
00758 GVX_TRACE(__PRETTY_FUNCTION__);
00759   if (itsUseSaccadicSuppression.getVal() == false) return;
00760   if (on) inhibit();
00761   LINFO("------- WTA saccadic suppression %s -------", on ? "on":"off");
00762 }
00763 
00764 // ######################################################################
00765 void WinnerTakeAllTempNote::blinkSuppression(const bool on)
00766 {
00767 GVX_TRACE(__PRETTY_FUNCTION__);
00768   if (itsUseBlinkSuppression.getVal() == false) return;
00769   if (on) inhibit();
00770   LINFO("------- WTA blink suppression %s -------", on ? "on":"off");
00771 }
00772 
00773 // ######################################################################
00774 void WinnerTakeAllTempNote::save1(const ModelComponentSaveInfo& sinfo)
00775 {
00776 GVX_TRACE(__PRETTY_FUNCTION__);
00777 
00778 // get the OFS to save to, assuming sinfo is of type
00779 // SimModuleSaveInfo (will throw a fatal exception otherwise):
00780  nub::ref<FrameOstream> ofs =
00781    dynamic_cast<const SimModuleSaveInfo&>(sinfo).ofs;
00782 
00783   ofs->writeFloat(this->getV(), FLOAT_NORM_PRESERVE, "WTA",
00784                   FrameInfo("winner-take-all map", SRC_POS));
00785 
00786   ofs->writeFloat(getVth(false), FLOAT_NORM_0_255, "WTA-Vth",
00787                   FrameInfo("winner-take-all threshold", SRC_POS));
00788 
00789   ofs->writeFloat(itsInitMask,FLOAT_NORM_0_255, "WTA-MASK",
00790                   FrameInfo("winner-take-all mask", SRC_POS));
00791 
00792 }
00793 
00794 // ######################################################################
00795 /* So things look consistent in everyone's emacs... */
00796 /* Local Variables: */
00797 /* indent-tabs-mode: nil */
00798 /* End: */
Generated on Sun May 8 08:41:07 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3