SaliencyMapStdOptim.C

Go to the documentation of this file.
00001 /*!@file Neuro/SaliencyMapStdOptim.C */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00005 // by the 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: Rob Peters <rjpeters at usc dot edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Neuro/SaliencyMapStdOptim.C $
00035 // $Id: SaliencyMapStdOptim.C 13377 2010-05-09 15:55:07Z itti $
00036 //
00037 
00038 #ifndef NEURO_SALIENCYMAPSTDOPTIM_C_DEFINED
00039 #define NEURO_SALIENCYMAPSTDOPTIM_C_DEFINED
00040 
00041 #include "Neuro/SaliencyMapStdOptim.H"
00042 
00043 #include "Image/MathOps.H"
00044 #include "Neuro/NeuroOpts.H"
00045 #include "Simulation/SimEventQueue.H"
00046 #include "Util/JobWithSemaphore.H"
00047 #include "Util/MainJobServer.H"
00048 #include "Util/MathFunctions.H"
00049 #include "rutz/shared_ptr.h"
00050 #include "rutz/trace.h"
00051 
00052 #include <vector>
00053 
00054 namespace
00055 {
00056   //! Helper function to compute inhibition of return
00057   double iorHelper(const double d, const double ampl, const double sdev)
00058   {
00059     double d_dev = d / sdev; d_dev = -0.5 * d_dev * d_dev;
00060     if (d_dev < -20.0) return 0.0;
00061     return ampl * exp(d_dev);
00062   }
00063 
00064   //! Helper function to compute inhibition of return
00065   double iorHelper(const Point2D<int>& p1, const Point2D<int>& p2,
00066                    const double pampl, const double mampl,
00067                    const double psdev, const double msdev)
00068   {
00069     double dx = double(p1.i - p2.i);
00070     double dy = double(p1.j - p2.j);
00071     double d = sqrt(squareOf(dx) + squareOf(dy));
00072     return iorHelper(d, pampl, psdev) - iorHelper(d, mampl, msdev);
00073   }
00074 }
00075 
00076 struct SaliencyMapStdOptim::UpdateJob : public JobWithSemaphore
00077 {
00078   UpdateJob(Image<float>::iterator vitr_,
00079             Image<float>::iterator vstop_,
00080             Image<float>::const_iterator iitr_,
00081             Image<float>::iterator ginhitr_,
00082             const float decay_, const float dt_c_,
00083             const float gleak_,
00084             const SimTime start_tm_, const SimTime end_tm_,
00085             const SimTime dt_)
00086     :
00087     vitr(vitr_),
00088     vstop(vstop_),
00089     iitr(iitr_),
00090     ginhitr(ginhitr_),
00091     decay(decay_),
00092     dt_c(dt_c_),
00093     gleak(gleak_),
00094     start_tm(start_tm_),
00095     end_tm(end_tm_),
00096     dt(dt_)
00097   {}
00098 
00099   virtual ~UpdateJob()
00100   {}
00101 
00102   virtual void run()
00103   {
00104     while (vitr != vstop)
00105       {
00106         for (SimTime tt = start_tm; tt < end_tm; tt += dt)
00107           {
00108             (*vitr) += dt_c * ( (*iitr) - ( gleak + (*ginhitr) ) * (*vitr) );
00109             if (*vitr < 0.0F) *vitr = 0.0F;
00110             (*ginhitr) *= decay; // progressively loose inhibitory influences
00111           }
00112 
00113         ++vitr;
00114         ++ginhitr;
00115         ++iitr;
00116       }
00117 
00118     this->markFinished();
00119   }
00120 
00121   virtual const char* jobType() const
00122   { return "SaliencyMapStdOptimUpdateJob"; }
00123 
00124   Image<float>::iterator vitr;
00125   Image<float>::iterator vstop;
00126   Image<float>::const_iterator iitr;
00127   Image<float>::iterator ginhitr;
00128   const float decay;
00129   const float dt_c;
00130   const float gleak;
00131   const SimTime start_tm;
00132   const SimTime end_tm;
00133   const SimTime dt;
00134 };
00135 
00136 // ######################################################################
00137 // ######################################################################
00138 // ########## SaliencyMapStdOptim implementation
00139 // ######################################################################
00140 // ######################################################################
00141 
00142 // ######################################################################
00143 SaliencyMapStdOptim::SaliencyMapStdOptim(OptionManager& mgr,
00144                                const std::string& descrName,
00145                                const std::string& tagName) :
00146   SaliencyMapAdapter(mgr, descrName, tagName),
00147   SIMCALLBACK_INIT(SimEventClockTick),
00148   itsTimeStep(SimTime::SECS(0.0001)),
00149   itsT(SimTime::ZERO()),
00150   itsC(5.0E-8F),
00151   itsGleak(1.0E-7F),
00152   itsV(),
00153   itsGinhDecay(&OPT_SMginhDecay, this)
00154 {
00155 GVX_TRACE(__PRETTY_FUNCTION__);
00156 }
00157 
00158 // ######################################################################
00159 SaliencyMapStdOptim::~SaliencyMapStdOptim()
00160 {
00161 GVX_TRACE(__PRETTY_FUNCTION__);
00162 }
00163 
00164 // ######################################################################
00165 void SaliencyMapStdOptim::reset()
00166 {
00167 GVX_TRACE(__PRETTY_FUNCTION__);
00168   itsV.freeMem();
00169 }
00170 
00171 // ######################################################################
00172 void SaliencyMapStdOptim::input(SimEventQueue& q, const Image<float>& current)
00173 {
00174 GVX_TRACE(__PRETTY_FUNCTION__);
00175   if (itsV.initialized() == false)
00176     {
00177       itsGinh.resize(current.getDims(), true);
00178       itsV.resize(current.getDims(), true);
00179     }
00180   itsI = current;
00181 }
00182 
00183 // ######################################################################
00184 void SaliencyMapStdOptim::depress(SimEventQueue& q, const Point2D<int>& winner,
00185                              const double& pampl, const double& mampl,
00186                              const double& psdev, const double& msdev)
00187 {
00188 GVX_TRACE(__PRETTY_FUNCTION__);
00189   Point2D<int> p;
00190   const int ww = itsV.getWidth();
00191   const int hh = itsV.getHeight();
00192   Image<float>::iterator src = itsGinh.beginw();
00193 
00194   // open inhibitory conductances:
00195   for (p.j = 0; p.j < hh; ++p.j)
00196     for (p.i = 0; p.i < ww; ++p.i)
00197       (*src++) += float(iorHelper(winner, p, pampl, mampl, psdev, msdev));
00198 
00199   LDEBUG("Peak IOR conductance: %fmS",
00200          float(iorHelper(winner, winner, pampl, mampl, psdev, msdev)) * 1000.0F);
00201 }
00202 
00203 // ######################################################################
00204 void SaliencyMapStdOptim::depress(SimEventQueue& q, const Point2D<int>& winner, const double& ampl,
00205                              const Image<byte>& objectMask)
00206 {
00207 GVX_TRACE(__PRETTY_FUNCTION__);
00208   Point2D<int> p;
00209   const int ww = itsV.getWidth();
00210   const int hh = itsV.getHeight();
00211   Image<float>::iterator src = itsGinh.beginw();
00212 
00213   // open inhibitory conductances:
00214   for (p.j = 0; p.j < hh; ++p.j)
00215     for (p.i = 0; p.i < ww; ++p.i)
00216       (*src++) += 0.1F / 255.F * ampl * float(objectMask.getVal(p));
00217 
00218   LDEBUG("Peak IOR conductance: %fmS",
00219          0.1F / 255.F * ampl * float(objectMask.getVal(winner)) * 1000.0F);
00220 }
00221 
00222 // ######################################################################
00223 void SaliencyMapStdOptim::
00224 onSimEventClockTick(SimEventQueue& q, rutz::shared_ptr<SimEventClockTick>& e)
00225 {
00226 GVX_TRACE(__PRETTY_FUNCTION__);
00227   const SimTime t = q.now();
00228 
00229   // we run our difference equations with a time step of itsTimeStep;
00230   // let's here figure out how many iterations we will need to go from
00231   // itsT to t. We will iterate for a number of equal steps, with each
00232   // step as close to itsTimeStep as possible to that we end up at
00233   // time t after iterating for an integer number of time steps:
00234   const SimTime dt = SimTime::computeDeltaT((t - itsT), itsTimeStep);
00235   const float dtsc = float(dt.secs()) / itsC;
00236 
00237   JobServer& srv = getMainJobServer();
00238 
00239   const unsigned int ntiles = srv.getParallelismHint();
00240 
00241   std::vector<rutz::shared_ptr<UpdateJob> > jobs;
00242 
00243   for (unsigned int i = 0; i < ntiles; ++i)
00244     {
00245       const int start = (i*itsV.getSize()) / ntiles;
00246       const int end = ((i+1)*itsV.getSize()) / ntiles;
00247 
00248       jobs.push_back
00249         (rutz::make_shared(new UpdateJob
00250                            (itsV.beginw() + start,
00251                             itsV.beginw() + end,
00252                             itsI.begin() + start,
00253                             itsGinh.beginw() + start,
00254                             itsGinhDecay.getVal(),
00255                             dtsc,
00256                             itsGleak,
00257                             itsT, t, dt)));
00258 
00259       srv.enqueueJob(jobs.back());
00260     }
00261 
00262   // barrier:
00263   for (size_t i = 0; i < jobs.size(); ++i) jobs[i]->wait();
00264 
00265   // post our map for everyone to enjoy:
00266   q.post(rutz::make_shared(new SimEventSaliencyMapOutput(this, itsV, itsLevelSpec.getVal().mapLevel())));
00267 
00268   // we are done, just keep track of new current time:
00269   itsT = t;
00270 }
00271 
00272 // ######################################################################
00273 void SaliencyMapStdOptim::saccadicSuppression(SimEventQueue& q, const bool on)
00274 {
00275 GVX_TRACE(__PRETTY_FUNCTION__);
00276   // we setup a weak inhibitory conductance for saccadic suppression
00277   // of the Saliency Map, as there is evidence that some intra-saccadic visual
00278   // input may still influence eye movements.
00279   const float inG =
00280     on
00281     ? 1.0e-6F  // on inhibitory conductance, in Siemens
00282     : 0.0F;    // turning off
00283 
00284   itsGinh.clear(inG);
00285 
00286   LINFO("------- SaliencyMapStdOptim saccadic suppression %s -------", on ? "on":"off");
00287 }
00288 
00289 // ######################################################################
00290 void SaliencyMapStdOptim::blinkSuppression(SimEventQueue& q, const bool on)
00291 {
00292 GVX_TRACE(__PRETTY_FUNCTION__);
00293   // we setup a weak inhibitory conductance for blink suppression of
00294   // the Saliency Map, as the visual input should also be turned off
00295   // in Brain
00296   const float inG =
00297     on
00298     ? 1.0e-6F  // on inhibitory conductance, in Siemens
00299     : 0.0F;    // turning off
00300 
00301   itsGinh.clear(inG);
00302 
00303   LINFO("------- SaliencyMapStdOptim blink suppression %s -------", on ? "on":"off");
00304 }
00305 
00306 // ######################################################################
00307 Image<float> SaliencyMapStdOptim::getV() const
00308 {
00309 GVX_TRACE(__PRETTY_FUNCTION__);
00310   return itsV;
00311 }
00312 
00313 // ######################################################################
00314 float SaliencyMapStdOptim::getV(const Point2D<int>& p) const
00315 {
00316 GVX_TRACE(__PRETTY_FUNCTION__);
00317   return itsV.getVal(p);
00318 }
00319 
00320 // ######################################################################
00321 /* So things look consistent in everyone's emacs... */
00322 /* Local Variables: */
00323 /* mode: c++ */
00324 /* indent-tabs-mode: nil */
00325 /* End: */
00326 
00327 #endif // NEURO_SALIENCYMAPSTDOPTIM_C_DEFINED
Generated on Sun May 8 08:05:25 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3