SaliencyMap.C

Go to the documentation of this file.
00001 /*!@file Neuro/SaliencyMap.C Implementation for saliency map class */
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/SaliencyMap.C $
00035 // $Id: SaliencyMap.C 13377 2010-05-09 15:55:07Z itti $
00036 //
00037 
00038 #include "Neuro/SaliencyMap.H"
00039 
00040 #include "Channels/ChannelOpts.H" // for OPT_LevelSpec
00041 #include "Component/OptionManager.H"
00042 #include "Image/Image.H"
00043 #include "Image/MathOps.H"   // for inplaceAddWeighted()
00044 #include "Image/FilterOps.H"   // for inplaceAddWeighted()
00045 #include "Neuro/NeuroOpts.H"
00046 #include "Neuro/SpatialMetrics.H"
00047 #include "Neuro/NeuroSimEvents.H"
00048 #include "Simulation/SimulationOpts.H"
00049 #include "Simulation/SimEventQueue.H"
00050 #include "Transport/FrameInfo.H"
00051 #include "Transport/FrameOstream.H"
00052 #include "Util/Assert.H"
00053 #include "Util/MathFunctions.H"
00054 #include "Util/Types.H"
00055 #include "Util/log.H"
00056 #include "rutz/trace.h"
00057 
00058 #include <cmath>
00059 
00060 namespace
00061 {
00062   //! Helper function to compute inhibition of return
00063   double iorHelper(const double d, const double ampl, const double sdev)
00064   {
00065     double d_dev = d / sdev; d_dev = -0.5 * d_dev * d_dev;
00066     if (d_dev < -20.0) return 0.0;
00067     return ampl * exp(d_dev);
00068   }
00069 
00070   //! Helper function to compute inhibition of return
00071   double iorHelper(const Point2D<int>& p1, const Point2D<int>& p2,
00072                    const double pampl, const double mampl,
00073                    const double psdev, const double msdev)
00074   {
00075     double dx = double(p1.i - p2.i);
00076     double dy = double(p1.j - p2.j);
00077     double d = sqrt(squareOf(dx) + squareOf(dy));
00078     return iorHelper(d, pampl, psdev) - iorHelper(d, mampl, msdev);
00079   }
00080 }
00081 
00082 // ######################################################################
00083 // ######################################################################
00084 // ########## SaliencyMap implementation
00085 // ######################################################################
00086 // ######################################################################
00087 
00088 SaliencyMap::SaliencyMap(OptionManager& mgr,
00089                          const std::string& descrName,
00090                          const std::string& tagName) :
00091   SimModule(mgr, descrName, tagName)
00092 {
00093 GVX_TRACE(__PRETTY_FUNCTION__);
00094 }
00095 
00096 // ######################################################################
00097 SaliencyMap::~SaliencyMap()
00098 {
00099 GVX_TRACE(__PRETTY_FUNCTION__);
00100 }
00101 
00102 // ######################################################################
00103 // ######################################################################
00104 // ########## SaliencyMapStub implementation
00105 // ######################################################################
00106 // ######################################################################
00107 
00108 SaliencyMapStub::SaliencyMapStub(OptionManager& mgr,
00109                                  const std::string& descrName,
00110                                  const std::string& tagName) :
00111   SaliencyMap(mgr, descrName, tagName)
00112 {
00113 GVX_TRACE(__PRETTY_FUNCTION__);
00114 }
00115 
00116 // ######################################################################
00117 SaliencyMapStub::~SaliencyMapStub()
00118 {
00119 GVX_TRACE(__PRETTY_FUNCTION__);
00120 }
00121 
00122 // ######################################################################
00123 // ######################################################################
00124 // ########## SaliencyMapAdapter implementation
00125 // ######################################################################
00126 // ######################################################################
00127 
00128 SaliencyMapAdapter::SaliencyMapAdapter(OptionManager& mgr,
00129                                        const std::string& descrName,
00130                                        const std::string& tagName) :
00131   SaliencyMap(mgr, descrName, tagName),
00132   SIMCALLBACK_INIT(SimEventWTAwinner),
00133   SIMCALLBACK_INIT(SimEventVisualCortexOutput),
00134   SIMCALLBACK_INIT(SimEventSaccadeStatusEye),
00135   SIMCALLBACK_INIT(SimEventSaveOutput),
00136   itsMetrics(new SpatialMetrics(mgr)),
00137   itsIORtype(&OPT_IORtype, this),  // see Neuro/NeuroOpts.{H,C}
00138   itsLevelSpec(&OPT_LevelSpec, this), //Channels/ChannelOpts.{H,C}
00139   itsSaveResults(&OPT_SMsaveResults, this), // see Neuro/NeuroOpts.{H,C}
00140   itsSaveCumResults(&OPT_SMsaveCumResults, this), // idem
00141   itsUseSaccadicSuppression(&OPT_SMuseSacSuppress, this),
00142   itsUseBlinkSuppression(&OPT_SMuseBlinkSuppress, this),
00143   itsMaxWinMv(&OPT_SMmaxWinV, this)
00144 {
00145 GVX_TRACE(__PRETTY_FUNCTION__);
00146   this->addSubComponent(itsMetrics);
00147 }
00148 
00149 // ######################################################################
00150 SaliencyMapAdapter::~SaliencyMapAdapter()
00151 {
00152 GVX_TRACE(__PRETTY_FUNCTION__);
00153 }
00154 
00155 // ######################################################################
00156 void SaliencyMapAdapter::
00157 onSimEventWTAwinner(SimEventQueue& q, rutz::shared_ptr<SimEventWTAwinner>& e)
00158 {
00159   const WTAwinner winner = e->winner();
00160   const float winV = this->getV(winner.smpos);
00161 
00162   // show SM voltage at winning location:
00163   LINFO("SM voltage at winner: %fmV above rest", 1000.0 * winV);
00164 
00165   // if current winning voltage is too high, calm things down with
00166   // some mild broad inhibition:
00167   if (1000.0 * winV > itsMaxWinMv.getVal())
00168     {
00169       LINFO("Triggering global inhibition to avoid map explosion.");
00170       this->depress(q, winner.smpos,
00171                     0.00005 * (winV - itsMaxWinMv.getVal() / 1000.0),
00172                     0.0,
00173                     1000.0 * double(itsMetrics->getFOAradius()),
00174                     100.0);
00175     }
00176 
00177   // now do our inhibition-of-return, if any
00178   if (itsIORtype.getVal() != IORnone)
00179     {
00180       // any available ShapeEstimator IOR mask?  NOTE: The shape
00181       // estimator will not work without also specifying
00182       // --shape-estim-mode= at the command line otherwise the shape
00183       // estimator will not run and this will ALWAYS be not
00184       // initialized!
00185       Image<float> IORmask;
00186       if (SeC<SimEventShapeEstimatorOutput> ee =
00187           q.check<SimEventShapeEstimatorOutput>(this, SEQ_ANY))
00188         IORmask = ee->iorMask();
00189 
00190       if (itsIORtype.getVal() == IORdisc || IORmask.initialized() == false)
00191         {
00192           // compute the parameters of the local depression, and depress
00193           // amplitudes for M-hat:
00194           const double pAmpl = 0.1 * double(winV); // strongly inhib winner
00195           const double mAmpl = 1e-4 * pAmpl;      // mildly excite surround
00196           // standard deviations for M_hat: inhibit of the foa size
00197           const double pSdev = 0.3 * double(itsMetrics->getFOAradius()) /
00198             double(1 << itsLevelSpec.getVal().mapLevel());      //foa inhib
00199           const double mSdev = 4.0 * pSdev;  // wide mild excit outside foa
00200           this->depress(q, winner.smpos, pAmpl, mAmpl, pSdev, mSdev);
00201           LINFO("Inhibition of return fired.");
00202         }
00203       else if (itsIORtype.getVal() == IORshapeEst && IORmask.initialized())
00204         {
00205           this->depress(q, winner.smpos, winV, IORmask);
00206           LINFO("ShapeEstimator-based inhibition of return fired.");
00207         }
00208     }
00209 }
00210 
00211 // ######################################################################
00212 void SaliencyMapAdapter::
00213 onSimEventVisualCortexOutput(SimEventQueue& q, rutz::shared_ptr<SimEventVisualCortexOutput>& e)
00214 {
00215   // Use the new VisualCortex output as our inputs:
00216   this->input(q, e->vco());
00217 }
00218 
00219 // ######################################################################
00220 void SaliencyMapAdapter::
00221 onSimEventSaccadeStatusEye(SimEventQueue& q, rutz::shared_ptr<SimEventSaccadeStatusEye>& e)
00222 {
00223   // get any eye activity so we can check for saccades or blinks:
00224 
00225   // any eye saccade and we are using saccadic suppression?
00226   if (itsUseSaccadicSuppression.getVal())
00227     {
00228       if (e->saccadeStatus() == TSTATUS_BEGIN) this->saccadicSuppression(q, true);
00229       else if (e->saccadeStatus() == TSTATUS_END) this->saccadicSuppression(q, false);
00230     }
00231 
00232   // any eye blink and we are using blink suppression?
00233   if (itsUseBlinkSuppression.getVal())
00234     {
00235       if (e->blinkStatus() == TSTATUS_BEGIN) this->blinkSuppression(q, true);
00236       else if (e->blinkStatus() == TSTATUS_END) this->blinkSuppression(q, false);
00237     }
00238 }
00239 
00240 // ######################################################################
00241 void SaliencyMapAdapter::
00242 onSimEventSaveOutput(SimEventQueue& q, rutz::shared_ptr<SimEventSaveOutput>& e)
00243 {
00244   // get the OFS to save to, assuming sinfo is of type
00245   // SimModuleSaveInfo (will throw a fatal exception otherwise):
00246   nub::ref<FrameOstream> ofs = dynamic_cast<const SimModuleSaveInfo&>(e->sinfo()).ofs;
00247 
00248   // get current membrane potentials:
00249   const Image<float> rawsm = this->getV();
00250 
00251   if (itsSaveResults.getVal())
00252     // save un-normalized float images:
00253     ofs->writeFloat(rawsm, FLOAT_NORM_PRESERVE, "SM", FrameInfo("saliency map (bottom-up)", SRC_POS));
00254 
00255   if (itsSaveCumResults.getVal())
00256     {
00257       // FIXME: this is hacky, probably we should accumulate itsCumMap
00258       // in doEvolve() instead of here...
00259 
00260       if (itsCumMap.initialized())
00261         const_cast<SaliencyMapAdapter*>(this)->itsCumMap += rawsm;
00262       else
00263         const_cast<SaliencyMapAdapter*>(this)->itsCumMap = rawsm;
00264 
00265       ofs->writeFloat(itsCumMap, FLOAT_NORM_PRESERVE, "CUMSM",
00266                       FrameInfo("cumulative saliency map", SRC_POS));
00267     }
00268 }
00269 
00270 // ######################################################################
00271 // ######################################################################
00272 // ########## SaliencyMapStd implementation
00273 // ######################################################################
00274 // ######################################################################
00275 
00276 // ######################################################################
00277 SaliencyMapStd::SaliencyMapStd(OptionManager& mgr,
00278                                const std::string& descrName,
00279                                const std::string& tagName) :
00280   SaliencyMapAdapter(mgr, descrName, tagName),
00281   SIMCALLBACK_INIT(SimEventClockTick),
00282   itsGinhDecay(&OPT_SMginhDecay, this), itsNeurons()
00283 {
00284 GVX_TRACE(__PRETTY_FUNCTION__);
00285 }
00286 
00287 // ######################################################################
00288 SaliencyMapStd::~SaliencyMapStd()
00289 {
00290 GVX_TRACE(__PRETTY_FUNCTION__);
00291 }
00292 
00293 // ######################################################################
00294 void SaliencyMapStd::input(SimEventQueue& q, const Image<float>& in)
00295 {
00296   // if this is our first, initialize our neurons:
00297   if (itsNeurons.initialized() == false)
00298     {
00299       itsNeurons.resize(in.getDims(), true);
00300       Image<LeakyIntegrator>::iterator
00301         nptr = itsNeurons.beginw(), stop = itsNeurons.endw();
00302       const float decay = itsGinhDecay.getVal();
00303       while(nptr != stop) (nptr++)->setGinhDecay(decay);
00304     }
00305 
00306   // set every neuron's input:
00307   Image<LeakyIntegrator>::iterator nptr = itsNeurons.beginw();
00308   Image<float>::const_iterator cptr = in.begin(), stop = in.end();
00309   while (cptr != stop) (nptr++)->input(*cptr++);
00310 }
00311 
00312 // ######################################################################
00313 void SaliencyMapStd::depress(SimEventQueue& q, const Point2D<int>& winner,
00314                              const double& pampl, const double& mampl,
00315                              const double& psdev, const double& msdev)
00316 {
00317 GVX_TRACE(__PRETTY_FUNCTION__);
00318   Point2D<int> p;
00319   const int ww = itsNeurons.getWidth();
00320   const int hh = itsNeurons.getHeight();
00321   Image<LeakyIntegrator>::iterator src = itsNeurons.beginw();
00322 
00323   // open inhibitory conductances:
00324   for (p.j = 0; p.j < hh; p.j ++)
00325     for (p.i = 0; p.i < ww; p.i ++)
00326       (src++)->addGinh(float(iorHelper(winner, p, pampl, mampl, psdev, msdev)));
00327 
00328   LDEBUG("Peak IOR conductance: %fmS",
00329          iorHelper(winner, winner, pampl, mampl, psdev, msdev) * 1000.0);
00330 }
00331 
00332 // ######################################################################
00333 void SaliencyMapStd::depress(SimEventQueue& q, const Point2D<int>& winner, const double& ampl,
00334                              const Image<byte>& objectMask)
00335 {
00336 GVX_TRACE(__PRETTY_FUNCTION__);
00337   Point2D<int> p;
00338   const int ww = itsNeurons.getWidth();
00339   const int hh = itsNeurons.getHeight();
00340   Image<LeakyIntegrator>::iterator src = itsNeurons.beginw();
00341 
00342   // open inhibitory conductances:
00343   for (p.j = 0; p.j < hh; p.j ++)
00344     for (p.i = 0; p.i < ww; p.i ++)
00345         (src++)->addGinh(0.1F / 255.F * ampl * float(objectMask.getVal(p)));
00346 
00347   LDEBUG("Peak IOR conductance: %fmS",
00348          0.1F / 255.F * ampl * float(objectMask.getVal(winner)) * 1000.0F);
00349 }
00350 
00351 // ######################################################################
00352 void SaliencyMapStd::
00353 onSimEventClockTick(SimEventQueue& q, rutz::shared_ptr<SimEventClockTick>& e)
00354 {
00355   // evolve our neurons one time step:
00356   Image<LeakyIntegrator>::iterator itr = itsNeurons.beginw();
00357   Image<LeakyIntegrator>::iterator stop = itsNeurons.endw();
00358   while (itr != stop) (itr++)->integrate(q.now());
00359 
00360   // post our current saliency map if we have one:
00361   const Image<float> sm = this->getV();
00362   q.post(rutz::make_shared(new SimEventSaliencyMapOutput(this, sm, itsLevelSpec.getVal().mapLevel())));
00363 }
00364 
00365 // ######################################################################
00366 void SaliencyMapStd::saccadicSuppression(SimEventQueue& q, const bool on)
00367 {
00368   // we setup a weak inhibitory conductance for saccadic suppression
00369   // of the Saliency Map, as there is evidence that some
00370   // intra-saccadic visual input may still influence eye movements.
00371   const float inG = on ? 1.0e-6F : 0.0F;  // inhibitory conductance in Siemens
00372 
00373   // NOTE: this will erase any previous conductance pattern that may
00374   // have been present in the neurons, e.g., due to recent IORs. So it
00375   // is assumed here that IOR and saccadic suppression share the same
00376   // inhibitory mechanism.
00377   Image<LeakyIntegrator>::iterator src = itsNeurons.beginw();
00378   Image<LeakyIntegrator>::iterator stop = itsNeurons.endw();
00379   while(src != stop) (src++)->setGinh(inG);
00380 
00381   LINFO("------- SaliencyMapStd saccadic suppression %s -------", on ? "on" : "off");
00382 }
00383 
00384 // ######################################################################
00385 void SaliencyMapStd::blinkSuppression(SimEventQueue& q, const bool on)
00386 {
00387   // we setup a weak inhibitory conductance for blink suppression of
00388   // the Saliency Map, as the visual input should already have been
00389   // turned off by the Retina:
00390   const float inG = on ? 1.0e-6F : 0.0F;  // inhibitory conductance in Siemens
00391 
00392   // NOTE: this will erase any previous conductance pattern that may
00393   // have been present in the neurons, e.g., due to recent IORs. So it
00394   // is assumed here that IOR and saccadic suppression share the same
00395   // inhibitory mechanism.
00396   Image<LeakyIntegrator>::iterator src = itsNeurons.beginw();
00397   Image<LeakyIntegrator>::iterator stop = itsNeurons.endw();
00398   while(src != stop) (src++)->setGinh(inG);
00399 
00400   LINFO("------- SaliencyMapStd blink suppression %s -------", on ? "on" : "off");
00401 }
00402 
00403 // ######################################################################
00404 Image<float> SaliencyMapStd::getV() const
00405 {
00406 GVX_TRACE(__PRETTY_FUNCTION__);
00407   if (itsNeurons.initialized() == false) return Image<float>();
00408 
00409   Image<float> ret(itsNeurons.getDims(), NO_INIT);
00410   Image<float>::iterator dest = ret.beginw();
00411   Image<LeakyIntegrator>::const_iterator src = itsNeurons.begin();
00412   Image<LeakyIntegrator>::const_iterator stop = itsNeurons.end();
00413   while (src != stop) *dest++ = (src++)->getV();
00414 
00415   return ret;
00416 }
00417 
00418 // ######################################################################
00419 float SaliencyMapStd::getV(const Point2D<int>& p) const
00420 {
00421 GVX_TRACE(__PRETTY_FUNCTION__);
00422   return itsNeurons.getVal(p).getV();
00423 }
00424 
00425 // ######################################################################
00426 void SaliencyMapStd::reset1()
00427 {
00428 GVX_TRACE(__PRETTY_FUNCTION__);
00429   itsNeurons.freeMem();
00430 }
00431 
00432 
00433 // ######################################################################
00434 // ########## SaliencyMapTrivial implementation
00435 // ######################################################################
00436 // ######################################################################
00437 
00438 // ######################################################################
00439 SaliencyMapTrivial::SaliencyMapTrivial(OptionManager& mgr,
00440                                        const std::string& descrName,
00441                                        const std::string& tagName) :
00442   SaliencyMapAdapter(mgr, descrName, tagName),
00443   itsItoVcoeff(&OPT_SMItoVcoeff, this),
00444   itsNeurons()
00445 {
00446 GVX_TRACE(__PRETTY_FUNCTION__);
00447 }
00448 
00449 // ######################################################################
00450 SaliencyMapTrivial::~SaliencyMapTrivial()
00451 {
00452 GVX_TRACE(__PRETTY_FUNCTION__);
00453 }
00454 
00455 // ######################################################################
00456 void SaliencyMapTrivial::reset1()
00457 {
00458 GVX_TRACE(__PRETTY_FUNCTION__);
00459   itsNeurons.freeMem();
00460 }
00461 
00462 // ######################################################################
00463 void SaliencyMapTrivial::input(SimEventQueue& q, const Image<float>& current)
00464 {
00465 GVX_TRACE(__PRETTY_FUNCTION__);
00466  itsNeurons = current * itsItoVcoeff.getVal();
00467 
00468   // post our current saliency map if we have one:
00469   if (itsNeurons.initialized())
00470     q.post(rutz::make_shared(new SimEventSaliencyMapOutput(this, itsNeurons, itsLevelSpec.getVal().mapLevel())));
00471 }
00472 
00473 // ######################################################################
00474 void SaliencyMapTrivial::depress(SimEventQueue& q, const Point2D<int>& winner,
00475                                  const double& pampl, const double& mampl,
00476                                  const double& psdev, const double& msdev)
00477 {
00478 GVX_TRACE(__PRETTY_FUNCTION__);
00479   Point2D<int> p;
00480   const int ww = itsNeurons.getWidth();
00481   const int hh = itsNeurons.getHeight();
00482   Image<float>::iterator src = itsNeurons.beginw();
00483 
00484   // open inhibitory conductances:
00485   for (p.j = 0; p.j < hh; p.j ++)
00486     for (p.i = 0; p.i < ww; p.i ++)
00487       {
00488         *src -= float(iorHelper(winner, p, pampl, mampl, psdev, msdev));
00489         if (*src < 0.0F) *src = 0.0F;
00490         ++ src;
00491       }
00492 
00493   LDEBUG("Peak IOR conductance: %fmS",
00494          float(iorHelper(winner, winner, pampl, mampl, psdev, msdev)) * 1000.0F);
00495 
00496   // post our current saliency map if we have one:
00497   if (itsNeurons.initialized())
00498     q.post(rutz::make_shared(new SimEventSaliencyMapOutput(this, itsNeurons, itsLevelSpec.getVal().mapLevel())));
00499 }
00500 
00501 // ######################################################################
00502 void SaliencyMapTrivial::depress(SimEventQueue& q, const Point2D<int>& winner, const double& ampl,
00503                                  const Image<byte>& objectMask)
00504 {
00505 GVX_TRACE(__PRETTY_FUNCTION__);
00506   Image<float> inhib = objectMask * (ampl / 255.0F);
00507   itsNeurons -= inhib;        // subtract inhib for current saliency values
00508   inplaceRectify(itsNeurons); // remove possible negative values
00509 
00510   // post our current saliency map if we have one:
00511   if (itsNeurons.initialized())
00512     q.post(rutz::make_shared(new SimEventSaliencyMapOutput(this, itsNeurons, itsLevelSpec.getVal().mapLevel())));
00513 }
00514 
00515 // ######################################################################
00516 void SaliencyMapTrivial::saccadicSuppression(SimEventQueue& q, const bool on)
00517 {
00518 GVX_TRACE(__PRETTY_FUNCTION__);
00519   // we setup a weak inhibitory conductance for saccadic suppression
00520   // of the Saliency Map, as there is evidence that some intra-saccadic visual
00521   // input may still influence eye movements.
00522   if (on) itsNeurons -= 1.0e-6F;
00523   LINFO("------- SaliencyMapTrivial saccadic suppression %s -------", on ? "on":"off");
00524 
00525   // post our current saliency map if we have one:
00526   if (itsNeurons.initialized())
00527     q.post(rutz::make_shared(new SimEventSaliencyMapOutput(this, itsNeurons, itsLevelSpec.getVal().mapLevel())));
00528 }
00529 
00530 // ######################################################################
00531 void SaliencyMapTrivial::blinkSuppression(SimEventQueue& q, const bool on)
00532 {
00533 GVX_TRACE(__PRETTY_FUNCTION__);
00534   // we setup a weak inhibitory conductance for blink suppression of
00535   // the Saliency Map, as the visual input should also be turned off
00536   // in Brain
00537   if (on) itsNeurons -= 1.0e-6F;
00538   LINFO("------- SaliencyMapTrivial blink suppression %s -------", on ? "on":"off");
00539 
00540   // post our current saliency map if we have one:
00541   if (itsNeurons.initialized())
00542     q.post(rutz::make_shared(new SimEventSaliencyMapOutput(this, itsNeurons, itsLevelSpec.getVal().mapLevel())));
00543 }
00544 
00545 // ######################################################################
00546 Image<float> SaliencyMapTrivial::getV() const
00547 {
00548 GVX_TRACE(__PRETTY_FUNCTION__);
00549  return itsNeurons;
00550 }
00551 
00552 // ######################################################################
00553 float SaliencyMapTrivial::getV(const Point2D<int>& p) const
00554 {
00555 GVX_TRACE(__PRETTY_FUNCTION__);
00556   return itsNeurons.getVal(p);
00557 }
00558 
00559 // ######################################################################
00560 // ######################################################################
00561 // ########## SaliencyMapFast implementation
00562 // ######################################################################
00563 // ######################################################################
00564 
00565 // ######################################################################
00566 SaliencyMapFast::SaliencyMapFast(OptionManager& mgr,
00567                                  const std::string& descrName,
00568                                  const std::string& tagName) :
00569   SaliencyMapAdapter(mgr, descrName, tagName),
00570   itsTimeStep(&OPT_SimulationTimeStep, this), // see Neuro/NeuroOpts.{H,C}
00571   itsInputCoeff(&OPT_SMfastInputCoeff, this), // ModelOptionDefs.C
00572   itsItoVcoeff(&OPT_SMItoVcoeff, this), // idem
00573   itsNeurons(), itsInputCopy(), itsT()
00574 {
00575 GVX_TRACE(__PRETTY_FUNCTION__);
00576 }
00577 
00578 // ######################################################################
00579 SaliencyMapFast::~SaliencyMapFast()
00580 {
00581 GVX_TRACE(__PRETTY_FUNCTION__);
00582 }
00583 
00584 // ######################################################################
00585 void SaliencyMapFast::reset1()
00586 {
00587 GVX_TRACE(__PRETTY_FUNCTION__);
00588   itsNeurons.freeMem(); itsT = SimTime::ZERO();
00589 }
00590 
00591 // ######################################################################
00592 void SaliencyMapFast::input(SimEventQueue& q, const Image<float>& current)
00593 {
00594 GVX_TRACE(__PRETTY_FUNCTION__);
00595 
00596   // make sure we are up to date:
00597   integrate(q);
00598 
00599   // get the new inputs:
00600   itsInputCopy = current * itsItoVcoeff.getVal();
00601   itsNeurons = itsInputCopy;
00602 
00603   // post current map:
00604   // post our current saliency map if we have one:
00605   if (itsNeurons.initialized())
00606     q.post(rutz::make_shared(new SimEventSaliencyMapOutput(this, itsNeurons, itsLevelSpec.getVal().mapLevel())));
00607 }
00608 
00609 // ######################################################################
00610 void SaliencyMapFast::depress(SimEventQueue& q, const Point2D<int>& winner,
00611                               const double& pampl, const double& mampl,
00612                               const double& psdev, const double& msdev)
00613 {
00614 GVX_TRACE(__PRETTY_FUNCTION__);
00615 
00616   // make sure we are up to date:
00617   integrate(q);
00618 
00619   Point2D<int> p;
00620   const int ww = itsNeurons.getWidth();
00621   const int hh = itsNeurons.getHeight();
00622   Image<float>::iterator src = itsNeurons.beginw();
00623 
00624   // open inhibitory conductances:
00625   for (p.j = 0; p.j < hh; p.j ++)
00626     for (p.i = 0; p.i < ww; p.i ++)
00627       {
00628         *src -= float(iorHelper(winner, p, pampl*30, mampl, psdev, msdev));
00629         if (*src < 0.0F) *src = 0.0F;
00630         ++ src;
00631       }
00632 
00633   LDEBUG("Peak IOR conductance: %fmS",
00634          float(iorHelper(winner, winner, pampl*30, mampl, psdev, msdev)) * 1000.0F);
00635 
00636   // post our current saliency map if we have one:
00637   if (itsNeurons.initialized())
00638     q.post(rutz::make_shared(new SimEventSaliencyMapOutput(this, itsNeurons, itsLevelSpec.getVal().mapLevel())));
00639 }
00640 
00641 // ######################################################################
00642 void SaliencyMapFast::depress(SimEventQueue& q, const Point2D<int>& winner, const double& ampl,
00643                               const Image<byte>& objectMask)
00644 {
00645 GVX_TRACE(__PRETTY_FUNCTION__);
00646   // make sure we are up to date:
00647   integrate(q);
00648 
00649   Image<float> inhib = objectMask * (ampl / 255.0F);
00650   itsNeurons -= inhib;        // subtract inhib for current saliency values
00651   inplaceRectify(itsNeurons); // remove possible negative values
00652 
00653   // post our current saliency map if we have one:
00654   if (itsNeurons.initialized())
00655     q.post(rutz::make_shared(new SimEventSaliencyMapOutput(this, itsNeurons, itsLevelSpec.getVal().mapLevel())));
00656 }
00657 
00658 // ######################################################################
00659 void SaliencyMapFast::integrate(SimEventQueue& q)
00660 {
00661 GVX_TRACE(__PRETTY_FUNCTION__);
00662   double nsteps = (q.now() - itsT).secs() / itsTimeStep.getVal().secs();
00663   if (nsteps >= 1.0 && itsInputCoeff.getVal() < 1) // If we need to merge with old ones
00664     {
00665       float c1 = pow(itsInputCoeff.getVal(), nsteps), c2 = 1.0F - c1;
00666       itsNeurons *= c1;
00667       inplaceAddWeighted(itsNeurons, itsInputCopy, c2);
00668     }
00669   itsT = q.now();
00670 }
00671 
00672 // ######################################################################
00673 void SaliencyMapFast::saccadicSuppression(SimEventQueue& q, const bool on)
00674 {
00675 GVX_TRACE(__PRETTY_FUNCTION__);
00676   // make sure we are up to date:
00677   integrate(q);
00678 
00679   // we setup a weak inhibitory conductance for saccadic suppression
00680   // of the Saliency Map, as there is evidence that some intra-saccadic visual
00681   // input may still influence eye movements.
00682   if (on) itsNeurons -= 1.0e-6F;
00683   LINFO("------- SaliencyMapFast saccadic suppression %s -------", on ? "on":"off");
00684 
00685   // post our current saliency map if we have one:
00686   if (itsNeurons.initialized())
00687     q.post(rutz::make_shared(new SimEventSaliencyMapOutput(this, itsNeurons, itsLevelSpec.getVal().mapLevel())));
00688 }
00689 
00690 // ######################################################################
00691 void SaliencyMapFast::blinkSuppression(SimEventQueue& q, const bool on)
00692 {
00693 GVX_TRACE(__PRETTY_FUNCTION__);
00694   // make sure we are up to date:
00695   integrate(q);
00696 
00697   // we setup a weak inhibitory conductance for blink suppression of
00698   // the Saliency Map, as the visual input should also be turned off
00699   // in Brain
00700   if (on) itsNeurons -= 1.0e-6F;
00701   LINFO("------- SaliencyMapFast blink suppression %s -------", on ? "on":"off");
00702 
00703   // post our current saliency map if we have one:
00704   if (itsNeurons.initialized())
00705     q.post(rutz::make_shared(new SimEventSaliencyMapOutput(this, itsNeurons, itsLevelSpec.getVal().mapLevel())));
00706 }
00707 
00708 // ######################################################################
00709 Image<float> SaliencyMapFast::getV() const
00710 {
00711 GVX_TRACE(__PRETTY_FUNCTION__);
00712   return itsNeurons;
00713 }
00714 
00715 // ######################################################################
00716 float SaliencyMapFast::getV(const Point2D<int>& p) const
00717 {
00718 GVX_TRACE(__PRETTY_FUNCTION__);
00719   return itsNeurons.getVal(p);
00720 }
00721 
00722 // ######################################################################
00723 /* So things look consistent in everyone's emacs... */
00724 /* Local Variables: */
00725 /* indent-tabs-mode: nil */
00726 /* End: */
Generated on Sun May 8 08:05:25 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3