00001 /*!@file Neuro/VisualBuffer.H Grab ausio samples from /dev/dsp */ 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/VisualBuffer.H $ 00035 // $Id: VisualBuffer.H 10779 2009-02-06 01:36:27Z itti $ 00036 // 00037 00038 #ifndef VISUALBUFFER_H_DEFINED 00039 #define VISUALBUFFER_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/fancynorm.H" 00046 #include "Neuro/WTAwinner.H" 00047 #include "Neuro/NeuroSimEvents.H" 00048 #include "Simulation/SimModule.H" 00049 #include "Util/SimTime.H" 00050 #include "Util/Types.H" 00051 00052 // ###################################################################### 00053 //! An integrative visual buffer, base class 00054 // ###################################################################### 00055 /*! A world-centered Visual Buffer to accumulate interesting locations 00056 (each time a covert attention shift occurs), with internal 00057 competitive dynamics within the buffer. Base class does nothing. */ 00058 class VisualBuffer : public SimModule 00059 { 00060 public: 00061 //! Constructor 00062 VisualBuffer(OptionManager& mgr, 00063 const std::string& descrName = "Visual Buffer", 00064 const std::string& tagName = "VisualBuffer"); 00065 00066 //! Destructor 00067 virtual ~VisualBuffer(); 00068 }; 00069 00070 // ###################################################################### 00071 //! An integrative visual buffer, stub implementation, does nothing 00072 // ###################################################################### 00073 class VisualBufferStub : public VisualBuffer 00074 { 00075 public: 00076 //! Constructor 00077 VisualBufferStub(OptionManager& mgr, 00078 const std::string& descrName = "Visual Buffer Stub", 00079 const std::string& tagName = "VisualBufferStub"); 00080 00081 //! Destructor 00082 virtual ~VisualBufferStub(); 00083 }; 00084 00085 // ###################################################################### 00086 //! VisualBuffer configurator 00087 // ###################################################################### 00088 /*! This will export the --vb-type=XX command-line option and will 00089 instantiate a VisualBuffer of the desired type as the option gets assigned a 00090 value. As this happens, new options may become available in the 00091 command-line. To see them, use --help AFTER you have chosen the type 00092 to use. The current VB may be retrieved using getVB(). */ 00093 class VisualBufferConfigurator : public ModelComponent 00094 { 00095 public: 00096 //! Constructor 00097 VisualBufferConfigurator(OptionManager& mgr, 00098 const std::string& descrName = "Visual Buffer Configurator", 00099 const std::string& tagName = "VisualBufferConfigurator"); 00100 00101 //! destructor 00102 virtual ~VisualBufferConfigurator(); 00103 00104 //! Get the chosen VB 00105 /*! You should call this during start() of the ModelComponent that 00106 needs the VB. NOTE: this will never return a null pointer (since 00107 it's a nub::ref rather than a nub::soft_ref), but it may return 00108 a "stub" object (e.g. VisualBufferStub). */ 00109 nub::ref<VisualBuffer> getVB() const; 00110 00111 protected: 00112 OModelParam<std::string> itsVBtype; //!< type of buffer 00113 00114 //! Intercept people changing our ModelParam 00115 /*! See ModelComponent.H; as parsing the command-line or reading a 00116 config file sets our name, we'll also here instantiate a 00117 buffer of the proper type (and export its options) */ 00118 virtual void paramChanged(ModelParamBase* const param, 00119 const bool valueChanged, 00120 ParamClient::ChangeStatus* status); 00121 00122 private: 00123 nub::ref<VisualBuffer> itsVB; // the buffer 00124 }; 00125 00126 // ###################################################################### 00127 //! An integrative visual buffer, std implementation 00128 // ###################################################################### 00129 /*! A world-centered Visual Buffer to accumulate interesting locations 00130 (each time a covert attention shift occurs), with internal 00131 competitive dynamics within the buffer. */ 00132 class VisualBufferStd : public VisualBuffer 00133 { 00134 public: 00135 //! Constructor 00136 VisualBufferStd(OptionManager& mgr, 00137 const std::string& descrName = "Visual Buffer", 00138 const std::string& tagName = "VisualBuffer"); 00139 00140 //! Destructor 00141 virtual ~VisualBufferStd(); 00142 00143 protected: 00144 //! Callback for every agm 00145 SIMCALLBACK_DECLARE(VisualBufferStd, SimEventAttentionGuidanceMapOutput); 00146 00147 //! Callback for every agm 00148 SIMCALLBACK_DECLARE(VisualBufferStd, SimEventRetinaImage); 00149 00150 //! New input 00151 /*! Beware that the inputs here are matched to what Brain naturally 00152 provides, which is 00153 @param win the coordinates of an atteention shift at retinal resolution 00154 @param sm the saliency map at the maplevel resolution 00155 @param objmask a mask with (if initialized) the shape of the attended 00156 object at retinal resolution. */ 00157 void input(const WTAwinner& win, const Image<float>& sm, const Image<byte>& objmask); 00158 00159 //! Get saliency mask 00160 /*! This is mostly for display purposes. The mask is the one that 00161 was created at the last input() and has the same size/scale as the 00162 saliency map and is in retinal coordinates */ 00163 Image<byte> getSaliencyMask() const; 00164 00165 //! Get current buffer 00166 Image<float> getBuffer() const; 00167 00168 //! evolve our internal dynamics 00169 void evolve(SimEventQueue& q); 00170 00171 //! inhibit a location, given in retinotopic/retinal-scale coords 00172 /*! A disk of radius FOAradius will be used for inhibition */ 00173 void inhibit(const Point2D<int>& loc); 00174 00175 //! inhibit a location, using a mask of same dims/scale as the buffer 00176 /*! @param mask should have same dims as the buffer, and values 00177 between 0.0 (no inhibition) and 1.0 (full inhibition). */ 00178 void inhibit(const Image<float>& mask); 00179 00180 //! Decide on most interesting target location given current eye position 00181 /*! All coordinates are in world-centered/sm-scale. The algorithm 00182 used here is inspired from the area activation model; we threshold 00183 out regions lower than a fraction of the maximum activation, then 00184 aim for the centroid of the region that is closest to current eye 00185 position. */ 00186 Point2D<int> findMostInterestingTarget(const Point2D<int>& p); 00187 00188 //! Decide on most interesting target location given current eye position 00189 /*! All coordinates are in world-centered/sm-scale. The algorithm 00190 used here will aim for the local max above a threshold that is 00191 closest to current eye position. */ 00192 Point2D<int> findMostInterestingTargetLocMax(const Point2D<int>& p); 00193 00194 //! transform coord from retinotopic/retinal-scale to world-centered/sm-scale 00195 Point2D<int> retinalToBuffer(const Point2D<int>& p) const; 00196 00197 //! transform coord from world-centered/sm-scale to retinotopic/retinal-scale 00198 Point2D<int> bufferToRetinal(const Point2D<int>& p) const; 00199 00200 //! are we object-based? 00201 bool isObjectBased() const; 00202 00203 OModelParam<int> itsFOAradius; //!< FOA radius 00204 OModelParam<bool> itsIgnoreBoring; //!< ignore boring attention shifts 00205 OModelParam<bool> itsObjectBased; //!< true if doing object-based 00206 OModelParam<Dims> itsBufferDims; //!< dims of our internal buffer 00207 OModelParam<LevelSpec> itsLevelSpec; //!< levelspec determines buffer scale 00208 OModelParam<Dims> itsInputDims; //!< input image dims 00209 OModelParam<SimTime> itsTimePeriod; //!< period at which to apply interaction 00210 OModelParam<float> itsDecayFactor; //!< temporal decay factor 00211 OModelParam<MaxNormType> itsNormType;//!< maxnorm type for our internals 00212 00213 //! get started (see ModelComponent.H) 00214 void start1(); 00215 00216 private: 00217 // apply one iteration of our internal dynamics 00218 void internalDynamics(); 00219 00220 Image<float> itsBuffer; 00221 Dims itsSMdims; 00222 Image<byte> itsSaliencyMask; 00223 SimTime itsTime; 00224 SimTime itsLastInteractTime; 00225 Point2D<int> itsRetinaOffset; 00226 }; 00227 00228 00229 // ###################################################################### 00230 //! Helper function to transform from buffer to retinal coordinates 00231 /*! You normally would not use this function directly, but rather 00232 VisualBufferStd::bufferToRetinal() or 00233 SimEventVisualBufferOutput::bufferToRetinal(). This function is 00234 here mostly so that both implementations of bufferToRetinal are 00235 always consistent. */ 00236 inline Point2D<int> visualBufferToRetinal(const Point2D<int>& p, const Point2D<int>& retinaOffset, 00237 const int smlev, const Dims& smdims, const Dims& bufdims) 00238 { 00239 // re-center out of the larger visual buffer: 00240 Point2D<int> pp = p - Point2D<int>((bufdims.w() - smdims.w()) / 2, (bufdims.h() - smdims.h()) / 2); 00241 00242 // scale back up to retinal scale (we do like in WTAwinner.H): 00243 pp.i <<= smlev; pp.j <<= smlev; 00244 00245 // then add our current eye position. Caution: make sure this is like rawToRetinal(): 00246 pp += retinaOffset; 00247 00248 return pp; 00249 } 00250 00251 // ###################################################################### 00252 //! Helper function to transform from buffer to retinal coordinates 00253 /*! You normally would not use this function directly. */ 00254 inline Point2D<int> retinalToVisualBuffer(const Point2D<int>& p, const Point2D<int>& retinaOffset, 00255 const int smlev, const Dims& smdims, const Dims& bufdims) 00256 { 00257 // first subtract our current eye position. Caution: Make sure this is the same as retinalToRaw(): 00258 Point2D<int> pp = p - retinaOffset; 00259 00260 // then downscale to maplevel (we do like in WTAwinner.H, but no random jitter): 00261 pp.i = int(pp.i / double(1 << smlev) + 0.49); 00262 pp.j = int(pp.j / double(1 << smlev) + 0.49); 00263 00264 // then re-center into the larger visual buffer: 00265 pp += Point2D<int>((bufdims.w() - smdims.w()) / 2, (bufdims.h() - smdims.h()) / 2); 00266 00267 return pp; 00268 } 00269 00270 #endif 00271 00272 // ###################################################################### 00273 /* So things look consistent in everyone's emacs... */ 00274 /* Local Variables: */ 00275 /* indent-tabs-mode: nil */ 00276 /* End: */