00001 /*!@file Neuro/WinnerTakeAll.H Header file for 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.H $ 00035 // $Id: WinnerTakeAll.H 10818 2009-02-11 06:05:24Z itti $ 00036 // 00037 00038 #ifndef WINNERTAKEALL_H_DEFINED 00039 #define WINNERTAKEALL_H_DEFINED 00040 00041 #include "Component/ModelComponent.H" 00042 #include "Component/ModelParam.H" 00043 #include "Image/Image.H" 00044 #include "Image/LevelSpec.H" 00045 #include "Image/Point2DT.H" 00046 #include "Media/MediaSimEvents.H" 00047 #include "Neuro/LeakyIntFire.H" 00048 #include "Neuro/LeakyIntFireAdp.H" 00049 #include "Neuro/NeuroSimEvents.H" 00050 #include "Neuro/WTAwinner.H" 00051 #include "Simulation/SimModule.H" 00052 #include "Simulation/SimEvents.H" 00053 #include "VFAT/segmentImageMC2.H" 00054 #include "Util/SimTime.H" 00055 00056 class FrameOstream; 00057 class ModelManager; 00058 00059 // ###################################################################### 00060 //! The winner-take-all base class 00061 // ###################################################################### 00062 /*! This is a 2D winner-take-all, a.k.a., spatial maximum detector. It 00063 is just a base class with virtual function definitions. Various 00064 winner-take-all variants are available below, which provide 00065 implementations for these virtual functions. The WTA receives input 00066 through the input() function, and its current state (membrane 00067 potential of neurons) can be retrieved using getV(). Various 00068 inplementations will typically derive from class Image and inherit 00069 all the standard methods of class Image. 00070 00071 See also WinnerTakeAllAdapter for an intermediate base class that 00072 provides the getV() output functions. Why are those functions not in 00073 this base class? The reason is that Brain only requires the input 00074 interface of WinnerTakeAll, and separating the output interface 00075 allows us to make a stub class that has just no-op input functions. 00076 */ 00077 class WinnerTakeAll : public SimModule 00078 { 00079 public: 00080 // ###################################################################### 00081 //! @name Constructor, destructor, and reset 00082 //@{ 00083 00084 //! Ininitialized constructor 00085 /*! The SM will be resized and initialized the first time input() is 00086 called */ 00087 WinnerTakeAll(OptionManager& mgr, 00088 const std::string& descrName, 00089 const std::string& tagName); 00090 00091 //! Destructor 00092 virtual ~WinnerTakeAll(); 00093 00094 //@} 00095 00096 private: 00097 // forbid assignment and copy-construction: 00098 WinnerTakeAll& operator=(const WinnerTakeAll& wta); 00099 WinnerTakeAll(const WinnerTakeAll& wta); 00100 }; 00101 00102 00103 // ###################################################################### 00104 //! A do-nothing stub implementation of WinnerTakeAll 00105 // ###################################################################### 00106 class WinnerTakeAllStub : public WinnerTakeAll 00107 { 00108 public: 00109 //! Constructor 00110 WinnerTakeAllStub(OptionManager& mgr, 00111 const std::string& descrName = "Winner-Take-All Stub", 00112 const std::string& tagName = "WinnerTakeAllStub"); 00113 00114 //! Destructor 00115 virtual ~WinnerTakeAllStub(); 00116 }; 00117 00118 // ###################################################################### 00119 //! A partial winner-take-all implementation with a few common member variables 00120 // ###################################################################### 00121 class WinnerTakeAllAdapter : public WinnerTakeAll 00122 { 00123 public: 00124 //! Constructor 00125 WinnerTakeAllAdapter(OptionManager& mgr, 00126 const std::string& descrName, 00127 const std::string& tagName); 00128 00129 //! Destructor 00130 virtual ~WinnerTakeAllAdapter(); 00131 00132 //! Reset our number of shifts 00133 virtual void reset1(); 00134 00135 protected: 00136 //! Callback for when a new data from the AGM is available 00137 SIMCALLBACK_DECLARE(WinnerTakeAllAdapter, SimEventAttentionGuidanceMapOutput); 00138 00139 //! Callback for when a new eye activity is going on 00140 SIMCALLBACK_DECLARE(WinnerTakeAllAdapter, SimEventSaccadeStatusEye); 00141 00142 //! Callback for every clock tick, to run our diff equations in integrate() 00143 SIMCALLBACK_DECLARE(WinnerTakeAllAdapter, SimEventInputFrame); 00144 00145 //! Callback for every time we should save our outputs 00146 SIMCALLBACK_DECLARE(WinnerTakeAllAdapter, SimEventSaveOutput); 00147 00148 //! Set new input currents for all neurons 00149 /*! This will initialize and resize the network if the network is 00150 currently uninitialized (e.g., just after construction or reset()). */ 00151 virtual void input(const Image<float>& in) = 0; 00152 00153 //! Update with new eye position 00154 virtual void eyeMovement(const Point2D<int>& curreye); 00155 00156 //! Return all our membrane potential voltages as an Image<float> 00157 virtual Image<float> getV() const = 0; 00158 00159 //! Turn saccadic suppression on/off 00160 virtual void saccadicSuppression(const bool on) = 0; 00161 00162 //! Turn blink suppression on/off 00163 virtual void blinkSuppression(const bool on) = 0; 00164 00165 //! evolve and check if we got a winner 00166 virtual void integrate(const SimTime& t, Point2D<int>& winner) = 0; 00167 00168 //! Text log file name 00169 OModelParam<std::string> itsLogFile; 00170 00171 //! Save our internals when saveResults() is called? 00172 OModelParam<bool> itsSaveResults; 00173 00174 //! use saccadic suppression? 00175 OModelParam<bool> itsUseSaccadicSuppression; 00176 00177 //! use blink suppression? 00178 OModelParam<bool> itsUseBlinkSuppression; 00179 00180 //! Specification of our image processing center-surround levels 00181 /*! The only thing that we care about here is the saliency map level */ 00182 OModelParam<LevelSpec> itsLevelSpec; 00183 00184 //! add jitter to winning location? 00185 OModelParam<bool> itsUseRandom; 00186 00187 //! Exit after a given number of attention shifts (if not zero) 00188 OModelParam<int> itsTooManyShifts; 00189 00190 //! Exit after a given number of attention shifts per frame (if not zero) 00191 OModelParam<int> itsTooManyShiftsPerFrame; 00192 00193 //! Inter-covert-shift delay that makes a shift of attention boring 00194 OModelParam<SimTime> itsBoringDelay; 00195 00196 /*! Minimum saliency map depolarization (in mV) to make a covert 00197 attention shift not boring */ 00198 OModelParam<float> itsBoringSMmv; 00199 00200 //! attention shift number (to decide whether we have done too many) 00201 int itsNumShifts; 00202 00203 //! copy of our last input 00204 Image<float> itsInputCopy; 00205 00206 //! last eye position 00207 Point2D<int> itsEyePos; 00208 00209 //! its most recent winner 00210 WTAwinner itsLastWinner; 00211 }; 00212 00213 // ###################################################################### 00214 //! The standard winner-take-all 00215 // ###################################################################### 00216 /*! This is a trivial winner-take-all implementation, based on a 2D 00217 layer of LeakyIntFire neurons and a unique global inhibitory 00218 neuron. All neurons in the layer charge up in parallel; whenever one 00219 reaches threshold, it activates the inhibitory interneuron (which is 00220 connected to all neurons in the layer), which in turn resets all 00221 neurons in the layer. WinnerTakeAllStd is an Image<LeakyIntFire> 00222 and inherits all the standard methods of class Image. To avoid 00223 confusion, we here add explicit input() and getV() methods (rather 00224 than providing conversion functions between LeakyIntFire and float, 00225 which could make the process more transparent but also possibly more 00226 confusing). */ 00227 class WinnerTakeAllStd : public WinnerTakeAllAdapter 00228 { 00229 public: 00230 //! Constructor 00231 WinnerTakeAllStd(OptionManager& mgr, 00232 const std::string& descrName = "Winner-Take-All Std", 00233 const std::string& tagName = "WinnerTakeAllStd"); 00234 00235 //! Destructor 00236 virtual ~WinnerTakeAllStd(); 00237 00238 //! Reset to initial state just after construction 00239 virtual void reset1(); 00240 00241 protected: 00242 //! Set new input currents for all neurons 00243 /*! This will initialize and resize the network if the network is 00244 currently uninitialized (e.g., just after construction or reset()). */ 00245 virtual void input(const Image<float>& in); 00246 00247 //! Return all our membrane potential voltages as an Image<float> 00248 virtual Image<float> getV() const; 00249 00250 //! Turn saccadic suppression on/off 00251 virtual void saccadicSuppression(const bool on); 00252 00253 //! Turn blink suppression on/off 00254 virtual void blinkSuppression(const bool on); 00255 00256 //! Integrate inputs until time t (in s) and update membrane potentials 00257 virtual void integrate(const SimTime& t, Point2D<int>& winner); 00258 00259 Image<LeakyIntFire> itsNeurons; 00260 LeakyIntFire itsGIN; // global inhibition neuron 00261 SimTime itsT; // keep track of time 00262 float itsGleak, itsGinh; // in Siemens 00263 float itsGinput; // in Siemens 00264 void inhibit(); // inhibit the whole layer 00265 }; 00266 00267 // ###################################################################### 00268 //! A fast winner-take-all 00269 // ###################################################################### 00270 /*! This just does an Image<T>::findMax() on the last input array 00271 received. It hence returns a winner at each time step. */ 00272 class WinnerTakeAllFast : public WinnerTakeAllAdapter 00273 { 00274 public: 00275 //! Ininitialized constructor 00276 /*! The WTA will be resized and initialized the first time input() is 00277 called */ 00278 WinnerTakeAllFast(OptionManager& mgr, 00279 const std::string& descrName = "Winner-Take-All Fast", 00280 const std::string& tagName = "WinnerTakeAllFast"); 00281 00282 //! Destructor 00283 virtual ~WinnerTakeAllFast(); 00284 00285 protected: 00286 //! Set new input currents for all neurons 00287 /*! This will initialize and resize the network if the network is 00288 currently uninitialized (e.g., just after construction or reset()). */ 00289 virtual void input(const Image<float>& in); 00290 00291 //! Return all our membrane potential voltages as an Image<float> 00292 virtual Image<float> getV() const; 00293 00294 //! Turn saccadic suppression on/off 00295 virtual void saccadicSuppression(const bool on); 00296 00297 //! Turn blink suppression on/off 00298 virtual void blinkSuppression(const bool on); 00299 00300 //! Integrate inputs until time t (in s) and update membrane potentials 00301 virtual void integrate(const SimTime& t, Point2D<int>& winner); 00302 }; 00303 00304 // ###################################################################### 00305 //! A greedy attention selection mechanism, not exactly winner-take-all 00306 // ###################################################################### 00307 /*! This will select, among a set of possible candidate targets that 00308 are above a threshold, the one that is closest to current eye 00309 position. It hence relies on being passed a valid current eye position 00310 in the queue. Note that the returned winner could be exactly at our 00311 current eye position if that is above threshold; we here do not 00312 attempt to force it to be some distance away from current fixation, 00313 and instead rely on IOR in the saliency map to enforce that if 00314 desired. */ 00315 class WinnerTakeAllGreedy : public WinnerTakeAllStd 00316 { 00317 public: 00318 //! Ininitialized constructor 00319 WinnerTakeAllGreedy(OptionManager& mgr, 00320 const std::string& descrName = "Winner-Take-All Greedy", 00321 const std::string& tagName = "WinnerTakeAllGreedy"); 00322 00323 //! Destructor 00324 virtual ~WinnerTakeAllGreedy(); 00325 00326 protected: 00327 //! Integrate inputs until time t (in s) and update membrane potentials 00328 /*! We operate like a WinnerTakeAllStd, except that when a winner is 00329 found, we look around for locations that are above threshold, and 00330 pick the closest one to our current eye position. */ 00331 virtual void integrate(const SimTime& t, Point2D<int>& winner); 00332 00333 OModelParam<float> itsThresholdFac; //!< Threshold factor, in [0.0 .. 1.0] 00334 }; 00335 00336 // ###################################################################### 00337 //! Winner take all adapted for temporal noticing 00338 // ###################################################################### 00339 /*! This is a trivial winner-take-all implementation, based on a 2D 00340 layer of LeakyIntFire neurons and a unique global inhibitory 00341 neuron. All neurons in the layer charge up in parallel; whenever one 00342 reaches threshold, it activates the inhibitory interneuron (which is 00343 connected to all neurons in the layer), which in turn resets all 00344 neurons in the layer. WinnerTakeAllStd is an Image<LeakyIntFire> 00345 and inherits all the standard methods of class Image. To avoid 00346 confusion, we here add explicit input() and getV() methods (rather 00347 than providing conversion functions between LeakyIntFire and float, 00348 which could make the process more transparent but also possibly more 00349 confusing). */ 00350 class WinnerTakeAllTempNote : public WinnerTakeAllStd 00351 { 00352 public: 00353 //! Ininitialized constructor 00354 /*! The WTA will be resized and initialized the first time input() is 00355 called */ 00356 WinnerTakeAllTempNote(OptionManager& mgr, 00357 const std::string& descrName = "Winner-Take-All Temporal Noticing", 00358 const std::string& tagName = "WinnerTakeAllTempNote"); 00359 00360 //! Destructor 00361 virtual ~WinnerTakeAllTempNote(); 00362 00363 //! Reset to initial state just after construction 00364 virtual void reset1(); 00365 00366 protected: 00367 //! Set new input currents for all neurons 00368 /*! This will initialize and resize the network if the network is 00369 currently uninitialized (e.g., just after construction or reset()). */ 00370 virtual void input(const Image<float>& in); 00371 00372 //! Return all our membrane potential voltages as an Image<float> 00373 /*! The curent values are possibly normalized to 0..255. The 00374 normalization will use itsSalmapFactor if it is non-null */ 00375 virtual Image<float> getV() const; 00376 00377 //! Turn saccadic suppression on/off 00378 virtual void saccadicSuppression(const bool on); 00379 00380 //! Turn blink suppression on/off 00381 virtual void blinkSuppression(const bool on); 00382 00383 Image<float> getVth(const bool normalize = false) const; 00384 00385 //! Integrate inputs until time t (in s) and update membrane potentials 00386 virtual void integrate(const SimTime& t, Point2D<int>& winner); 00387 00388 Image<LeakyIntFireAdp> itsNeurons; 00389 //! Use the color segmenter to find a good mask region around winner 00390 segmentImageMC2<float, unsigned int, 1> itsMaskSegment; 00391 std::vector<float> itsLowMaskBound; 00392 std::vector<float> itsHighMaskBound; 00393 Image<float> itsInitMask; 00394 LeakyIntFire itsGIN; // global inhibition neuron 00395 SimTime itsT; // keep track of time 00396 float itsGleak, itsGinh; // in Siemens 00397 float itsGinput; // in Siemens 00398 void inhibit(); // inhibit the whole layer 00399 00400 //! Save our various results 00401 virtual void save1(const ModelComponentSaveInfo& sinfo); 00402 }; 00403 00404 #endif 00405 00406 // ###################################################################### 00407 /* So things look consistent in everyone's emacs... */ 00408 /* Local Variables: */ 00409 /* indent-tabs-mode: nil */ 00410 /* End: */