00001 /** 00002 \file Robots/LoBot/io/LoEMD.H 00003 \brief A generic class implementing a Reichardt Elementary Motion 00004 Detector. 00005 00006 This file defines a class that implements an Elementary Motion 00007 Detector using two inputs, viz., a left and a right (though it could 00008 just as well be up and down instead or any other pair of opposing 00009 directions). The EMD expects to be given a direction vector and 00010 returns a scaled version of this vector to indicate the current motion 00011 from its inputs. 00012 */ 00013 00014 // //////////////////////////////////////////////////////////////////// // 00015 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00016 // by the University of Southern California (USC) and the iLab at USC. // 00017 // See http://iLab.usc.edu for information about this project. // 00018 // //////////////////////////////////////////////////////////////////// // 00019 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00020 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00021 // in Visual Environments, and Applications'' by Christof Koch and // 00022 // Laurent Itti, California Institute of Technology, 2001 (patent // 00023 // pending; application number 09/912,225 filed July 23, 2001; see // 00024 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00025 // //////////////////////////////////////////////////////////////////// // 00026 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00027 // // 00028 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00029 // redistribute it and/or modify it under the terms of the GNU General // 00030 // Public License as published by the Free Software Foundation; either // 00031 // version 2 of the License, or (at your option) any later version. // 00032 // // 00033 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00034 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00035 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00036 // PURPOSE. See the GNU General Public License for more details. // 00037 // // 00038 // You should have received a copy of the GNU General Public License // 00039 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00040 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00041 // Boston, MA 02111-1307 USA. // 00042 // //////////////////////////////////////////////////////////////////// // 00043 // 00044 // Primary maintainer for this file: mviswana usc edu 00045 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/io/LoEMD.H $ 00046 // $Id: LoEMD.H 13037 2010-03-23 01:00:53Z mviswana $ 00047 // 00048 00049 #ifndef LOBOT_ELEMENTARY_MOTION_DETECTOR_DOT_H 00050 #define LOBOT_ELEMENTARY_MOTION_DETECTOR_DOT_H 00051 00052 //------------------------------ HEADERS -------------------------------- 00053 00054 // lobot headers 00055 #include "Robots/LoBot/misc/LoVector.H" 00056 #include "Robots/LoBot/util/LoMath.H" 00057 00058 //----------------------------- NAMESPACE ------------------------------- 00059 00060 namespace lobot { 00061 00062 //------------------------- CLASS DEFINITION ---------------------------- 00063 00064 /** 00065 \class lobot::EMD 00066 \brief A generic Elementary Motion Detector. 00067 00068 This class implements the notion of an Elementary Motion Detector. It 00069 takes two inputs (left and right, though they could be a pair of any 00070 opposing directions) and performs the Reichardt EMD computation to 00071 assess the "amount" of motion in left or right directions (negative 00072 amounts mean leftward motion whereas positive amounts indicate 00073 rightwards motion). This scalar quantity is vectorized by scaling a 00074 direction vector provided to the EMD on its creation. 00075 00076 Like all templates, this one too implies an interface for its type 00077 parameters. Specifically, the EMD's input type is required to 00078 implement a value() function that returns floating point number 00079 indicating the current level of whatever activity it measures. 00080 */ 00081 template<typename input_type> 00082 class EMD { 00083 // Prevent copy and assignment 00084 EMD(const EMD&) ; 00085 EMD& operator=(const EMD&) ; 00086 00087 /// An Elementary Motion Detector is built from a pair of adjacent 00088 /// inputs. 00089 const input_type& m_left ; 00090 const input_type& m_right ; 00091 00092 /// For the EMD to work, we need to keep track of both the input 00093 /// values from the previous time step. 00094 float m_left_prev, m_right_prev ; 00095 00096 /// The EMD is setup to point along a certain direction. 00097 Vector m_direction ; 00098 00099 public: 00100 /// Clients must specify the left and right (up/down, whatever) inputs 00101 /// and also supply a direction vector for the EMD. The direction 00102 /// vector is specified as an angle in degrees. 00103 EMD(const input_type& left, const input_type& right, float angle) ; 00104 00105 /// This method uses the latest values from the EMD's left and right 00106 /// inputs and computes the vector representing the total motion. 00107 Vector update() ; 00108 00109 /// Destructor 00110 virtual ~EMD() ; 00111 } ; 00112 00113 // Initialization 00114 template<typename input_type> 00115 EMD<input_type>:: 00116 EMD(const input_type& left, const input_type& right, float angle) 00117 : m_left(left), m_right(right), 00118 m_left_prev(0), m_right_prev(0), 00119 m_direction(cos(angle), sin(angle)) 00120 {} 00121 00122 // EMD update 00123 template<typename input_type> 00124 Vector EMD<input_type>::update() 00125 { 00126 const float L = m_left.value() ; 00127 const float R = m_right.value() ; 00128 const float M = m_left_prev * R - L * m_right_prev ; 00129 00130 m_left_prev = L ; 00131 m_right_prev = R ; 00132 00133 //return M * m_direction ; // FIXME: should this be abs(M) * m_direction? 00134 return abs(M) * m_direction ; // FIXME: should not be abs(M) * m_direction? 00135 } 00136 00137 // Clean-up 00138 template<typename input_type> 00139 EMD<input_type>::~EMD() 00140 {} 00141 00142 //---------------------- POINTER SPECIALIZATION ------------------------- 00143 00144 // Full specialization for void pointers 00145 template<> 00146 class EMD<void*> { 00147 // Prevent copy and assignment 00148 EMD(const EMD&) ; 00149 EMD& operator=(const EMD&) ; 00150 00151 // The left and right inputs of the EMD 00152 const void* m_left ; 00153 const void* m_right ; 00154 00155 // The previous values of the two inputs 00156 float m_left_prev, m_right_prev ; 00157 00158 // The EMD's direction vector 00159 Vector m_direction ; 00160 00161 protected: 00162 // Constructor 00163 EMD(const void* left, const void* right, float angle) ; 00164 00165 // The EMD computation method 00166 Vector update() ; 00167 00168 // Derived classes must supply this methods for retrieving the current 00169 // input value from the specified input. 00170 virtual float value(const void* input) = 0 ; 00171 00172 public: 00173 // Destructor 00174 virtual ~EMD() ; 00175 } ; 00176 00177 // Initialization 00178 EMD<void*>:: 00179 EMD(const void* left, const void* right, float angle) 00180 : m_left(left), m_right(right), 00181 m_left_prev(0), m_right_prev(0), 00182 m_direction(cos(angle), sin(angle)) 00183 {} 00184 00185 // EMD update 00186 Vector EMD<void*>::update() 00187 { 00188 const float L = value(m_left) ; 00189 const float R = value(m_right) ; 00190 const float M = m_left_prev * R - L * m_right_prev ; 00191 00192 m_left_prev = L ; 00193 m_right_prev = R ; 00194 00195 //return M * m_direction ; // FIXME: should this be abs(M) * m_direction? 00196 return abs(M) * m_direction ; // FIXME: should not be abs(M) * m_direction? 00197 } 00198 00199 // Clean-up 00200 EMD<void*>::~EMD() 00201 {} 00202 00203 // Partial specialization for non-void pointers 00204 template<typename input_type> 00205 class EMD<input_type*> : private EMD<void*> { 00206 // Handy type to have around in a derived class 00207 typedef EMD<void*> base ; 00208 00209 // Prevent copy and assignment 00210 EMD(const EMD&) ; 00211 EMD& operator=(const EMD&) ; 00212 00213 public: 00214 // Constructor 00215 EMD(const input_type* left, const input_type* right, float angle) ; 00216 00217 // Destructor 00218 ~EMD() ; 00219 00220 // EMD update 00221 Vector update() {return base::update() ;} 00222 00223 protected: 00224 // Override required of derived class 00225 float value(const void* input) ; 00226 } ; 00227 00228 // Initialization 00229 template<typename input_type> 00230 EMD<input_type*>:: 00231 EMD(const input_type* left, const input_type* right, float angle) 00232 : base(reinterpret_cast<const void*>(left), 00233 reinterpret_cast<const void*>(right), 00234 angle) 00235 {} 00236 00237 // EMD update 00238 template<typename input_type> 00239 float EMD<input_type*>::value(const void* input) 00240 { 00241 return (reinterpret_cast<const input_type*>(input))->value() ; 00242 } 00243 00244 // Destructor 00245 template<typename input_type> 00246 EMD<input_type*>::~EMD() 00247 {} 00248 00249 //----------------------------------------------------------------------- 00250 00251 } // end of namespace encapsulating this file's definitions 00252 00253 #endif 00254 00255 /* So things look consistent in everyone's emacs... */ 00256 /* Local Variables: */ 00257 /* indent-tabs-mode: nil */ 00258 /* End: */