00001 /*!@file ModelNeuron/Weights.H Class A class to compute interactions 00002 between neurons. */ 00003 00004 // //////////////////////////////////////////////////////////////////// // 00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00006 // University of Southern California (USC) and the iLab at USC. // 00007 // See http://iLab.usc.edu for information about this project. // 00008 // //////////////////////////////////////////////////////////////////// // 00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00011 // in Visual Environments, and Applications'' by Christof Koch and // 00012 // Laurent Itti, California Institute of Technology, 2001 (patent // 00013 // pending; application number 09/912,225 filed July 23, 2001; see // 00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00015 // //////////////////////////////////////////////////////////////////// // 00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00017 // // 00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00019 // redistribute it and/or modify it under the terms of the GNU General // 00020 // Public License as published by the Free Software Foundation; either // 00021 // version 2 of the License, or (at your option) any later version. // 00022 // // 00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00026 // PURPOSE. See the GNU General Public License for more details. // 00027 // // 00028 // You should have received a copy of the GNU General Public License // 00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00031 // Boston, MA 02111-1307 USA. // 00032 // //////////////////////////////////////////////////////////////////// // 00033 // 00034 // Primary maintainer for this file: David Berg <dberg@usc.edu> 00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/ModelNeuron/Weights.H $ 00036 00037 #ifndef MODELNEURON_WEIGHTS_H_DEFINED 00038 #define MODELNEURON_WEIGHTS_H_DEFINED 00039 00040 #include "Image/Image.H" 00041 #include "Image/LowPassLpt.H" 00042 #include "Image/Convolutions.H" 00043 00044 #include <vector> 00045 00046 // ###################################################################### 00047 // Policies for different weighting schemes to be used as a template 00048 // argument by Layer. A valid policy should have at least: 00049 // 00050 // a default constructor. 00051 // Image<double> compute(const Image<double>& in); 00052 // const bool initialized() const; 00053 // 00054 // All equations for the below classes are inspired by Neural Field 00055 // dynamics: Amari & Arbib, 77; Coombs, 05; Erlhagen & Bicho, 2006 00056 // ###################################################################### 00057 00058 // ###################################################################### 00059 // A weight class that defines minimum interface and can be used virtually 00060 // ###################################################################### 00061 struct Weights 00062 { 00063 public: 00064 Weights() : itsInit(false) { }; 00065 virtual ~Weights() { }; 00066 virtual Image<double> compute(const Image<double>& in) = 0; 00067 virtual Weights* clone() const = 0; 00068 virtual const bool initialized() const { return itsInit; }; 00069 protected: 00070 bool itsInit; 00071 }; 00072 00073 // ###################################################################### 00074 //! A class to derive from to create new Weightss. New 00075 //! Weights derived types can derive from this class to inherit 00076 //! the clone() function if desired. 00077 /* 00078 Programmer Note: This class uses the 'quriously recursive template 00079 pattern' to simplify creation of new classes for the programmer. As 00080 such, to create a new simulation module, classes should adhear the 00081 following convention: 00082 00083 class mymodule : public WeightsDerived<mymodule> 00084 { 00085 mymodule(//params//) : Weights<mymodule>(//params//) { }; 00086 //...rest of functions 00087 }; 00088 */ 00089 // ###################################################################### 00090 template <class Derived> 00091 class WeightsDerived : public Weights 00092 { 00093 public: 00094 Weights* clone() const 00095 { return new Derived(dynamic_cast<const Derived&>(*this)); }; 00096 protected: 00097 WeightsDerived() : Weights() { }; 00098 virtual ~WeightsDerived() { }; 00099 }; 00100 00101 00102 // ###################################################################### 00103 // A simple weights configuration that just multiplies the input by a 00104 // constant. 00105 // ###################################################################### 00106 class WeightsEmpty : public WeightsDerived<WeightsEmpty> 00107 { 00108 public: 00109 //default constructor 00110 WeightsEmpty() : WeightsDerived<WeightsEmpty>() { itsInit = true; }; 00111 00112 //destructor 00113 ~WeightsEmpty() { }; 00114 00115 //compute the spread of activity 00116 Image<double> compute(const Image<double>& in) {return Image<double>(in.getDims(), ZEROS); }; 00117 }; 00118 00119 // ###################################################################### 00120 // A weights configuration where the every neural connects to every 00121 // other neuron. 00122 // ###################################################################### 00123 class WeightsAll : public WeightsDerived<WeightsAll> 00124 { 00125 public: 00126 //default constructor 00127 WeightsAll(); 00128 00129 //constructor 00130 WeightsAll(const double& weight); 00131 00132 //destructor 00133 ~WeightsAll() { }; 00134 00135 //compute the spread of activity 00136 Image<double> compute(const Image<double>& in); 00137 00138 private: 00139 double itsW; 00140 }; 00141 00142 // ###################################################################### 00143 // A simple weights configuration that just multiplies the input by a 00144 // constant. 00145 // ###################################################################### 00146 class WeightsUniform : public WeightsDerived<WeightsUniform> 00147 { 00148 public: 00149 //default constructor 00150 WeightsUniform(); 00151 00152 //constructor 00153 WeightsUniform(const double& weight); 00154 00155 //destructor 00156 ~WeightsUniform() { }; 00157 00158 //compute the spread of activity 00159 Image<double> compute(const Image<double>& in); 00160 00161 private: 00162 double itsW; 00163 }; 00164 00165 // ###################################################################### 00166 // A weight configuration that uses a 1D binomial kernel 00167 // 00168 // Iterative seperable convolution is applied to achieve the desired 00169 // standard deviation. The output is then scaled so that the response 00170 // to an impulse is unity at the center. Self activation is optionally 00171 // subtracted. This object state is set to initialzed after 00172 // its first call. 00173 // 00174 // Several convolution strategies are supported. If the BorderType == 00175 // 0, then clean convolution will be performed. The filter is 00176 // truncated and normalized at the image edge. 00177 00178 // Other border types listed below, were designed for radially 00179 // transformed (RT) images that represent visual space in 00180 // hemifields. Only 3 and 5-tap binomial filtering is 00181 // implemented. Three boundary conditions are supported for these 00182 // images: 00183 // 00184 // 1) SEPARATE_HEMI 00185 // No hemifield interactions. Clean (normalized energy) border 00186 // conditions apply at each hemifild in both directions. 00187 // 2) CROSS_HEMI 00188 // Convolutions will cross hemifields in both the R (ring) and W 00189 // (wedge) dirctions. 00190 // 3) CROSS_ANGLE 00191 // Convolutions will only cross hemifields in the W (wedge) 00192 // direction. Clean (normalized energy) border condition will be 00193 // applied in the R (ring) dircection. 00194 // ###################################################################### 00195 class WeightsBinomial : public WeightsDerived<WeightsBinomial> 00196 { 00197 public: 00198 //default constructor 00199 WeightsBinomial(); 00200 00201 //constructor 00202 WeightsBinomial(const double& std, const double& weight, 00203 const bool doSubCenter, 00204 const BorderPolicy bp, 00205 const uint taps = 3); 00206 //destructor 00207 ~WeightsBinomial() { }; 00208 00209 //compute the spread of activity 00210 Image<double> compute(const Image<double>& in); 00211 00212 private: 00213 uint itsTaps; 00214 uint itsIter; 00215 bool subCenter; 00216 double itsCenter; 00217 double itsWeight; 00218 BorderPolicy itsBp; 00219 bool itsSetup; 00220 }; 00221 00222 // ###################################################################### 00223 // a simple center surround pattern using a gaussian minus a constant 00224 // ###################################################################### 00225 class WeightsCS : public WeightsDerived<WeightsCS> 00226 { 00227 public: 00228 //default constructor 00229 WeightsCS(); 00230 00231 //constructor 00232 WeightsCS(const double& estd, const double& eweight, 00233 const double& inhibit, const bool doSubCenter, 00234 const BorderPolicy bp, const uint taps = 3); 00235 00236 //destructor 00237 ~WeightsCS() { }; 00238 00239 //compute the spread of activity 00240 Image<double> compute(const Image<double>& in); 00241 00242 private: 00243 WeightsBinomial itsW; 00244 double itsInh; 00245 }; 00246 00247 // ###################################################################### 00248 // A weight configuration that uses 1D binomial kernels to approximate 00249 // a difference of gaussians 00250 // 00251 // Iterative seperable convolution is applied to achieve the desired 00252 // standard deviation. The output is then scaled so that the response 00253 // to an impulse is the desired weight. 00254 // ###################################################################### 00255 class WeightsDoG : public WeightsDerived<WeightsDoG> 00256 { 00257 public: 00258 //default constructor 00259 WeightsDoG(); 00260 00261 //constructor 00262 WeightsDoG(const double& estd, const double& istd, 00263 const double& eweight, const double& iweight, 00264 const bool subCenter, const BorderPolicy bp, 00265 const uint taps = 3); 00266 //destructor 00267 ~WeightsDoG() { }; 00268 00269 //compute the spread of activity 00270 Image<double> compute(const Image<double>& in); 00271 00272 private: 00273 WeightsBinomial itsE, itsI; 00274 }; 00275 00276 // ###################################################################### 00277 // A weight configuration that uses 1D seperable kernels 00278 // 00279 // If more than one filter set (x and y filters) is added then filters 00280 // are applied in the order they were added and other processing (such 00281 // as subtracting self activation). 00282 // ###################################################################### 00283 class Weights1D : public WeightsDerived<Weights1D> 00284 { 00285 public: 00286 //default constructor 00287 Weights1D(); 00288 00289 //constructor 00290 Weights1D(const bool doSubCenter, 00291 const ConvolutionBoundaryStrategy strat = CONV_BOUNDARY_CLEAN); 00292 00293 //destructor 00294 ~Weights1D() { }; 00295 00296 //add a kernel to the bank, to be used in both x and y direction 00297 void addWeight(const Image<double>& wxy); 00298 00299 //add the kernels to be used in the x and y direction 00300 void addWeight(const Image<double>& wx, const Image<double>& wy); 00301 00302 //!clear our weights 00303 void clear(); 00304 00305 //compute weighted output 00306 Image<double> compute(const Image<double>& in); 00307 00308 private: 00309 bool subCenter; 00310 double itsCenter; 00311 ConvolutionBoundaryStrategy itsStrat; 00312 std::vector<Image<double> > itsX; 00313 std::vector<Image<double> > itsY; 00314 bool itsSetup; 00315 }; 00316 00317 // ###################################################################### 00318 // A weight configuration that uses a 2D kernel 00319 // 00320 // If more than one filter is added the filter are applied in the order 00321 // they were added. 00322 //###################################################################### 00323 class Weights2D : public WeightsDerived<Weights2D> 00324 { 00325 public: 00326 //constructor 00327 Weights2D(const ConvolutionBoundaryStrategy strat = CONV_BOUNDARY_CLEAN); 00328 00329 //destructor 00330 ~Weights2D() { }; 00331 00332 //add a kernel to the bank 00333 void addWeight(const Image<double>& w); 00334 00335 //!clear our weights 00336 void clear(); 00337 00338 //compute weighted output 00339 Image<double> compute(const Image<double>& in); 00340 00341 private: 00342 ConvolutionBoundaryStrategy itsStrat; 00343 std::vector<Image<double> > itsW; 00344 }; 00345 00346 // ###################################################################### 00347 // A weight configuration that uses a Mask 00348 // 00349 // In this weight scheme the connection pattern is fully 00350 // specified. That means that you must add a seperate Image<double> 00351 // for each pixels which describes which other pixels contribute to 00352 // its response. The objects state is set to initialzed when the 00353 // object is constructed, but calls to compute will return images of 00354 // zeros unless one weight mask has been added for every pixel in the 00355 // input. 00356 // ###################################################################### 00357 class WeightsMask : public WeightsDerived<WeightsMask> 00358 { 00359 public: 00360 //constructor 00361 WeightsMask(); 00362 00363 //destructor 00364 ~WeightsMask() { }; 00365 00366 //add a kernel to the bank 00367 void addWeight(const Image<double>& w); 00368 00369 //!clear our weights 00370 void clear(); 00371 00372 //compute weighted output 00373 Image<double> compute(const Image<double>& in); 00374 00375 private: 00376 std::vector<Image<double> > itsW; 00377 }; 00378 00379 // ###################################################################### 00380 //helper functions 00381 // ###################################################################### 00382 00383 // for weights that use binomial 00384 Image<double> filterBinomial(const Image<double>& in, const uint iterations, 00385 const uint taps, const BorderPolicy bp); 00386 00387 //print the impulse response of a weight 00388 template<class W> 00389 void printImpulse(const uint w, const uint h, W& weights); 00390 00391 //print the image 00392 void printImage(const Image<double>& in); 00393 00394 00395 #endif 00396 00397 // ###################################################################### 00398 /* So things look consistent in everyone's emacs... */ 00399 /* Local Variables: */ 00400 /* indent-tabs-mode: nil */ 00401 /* End: */