00001 /*!@file SceneUnderstanding/LGN.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: Lior Elazary <elazary@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/plugins/SceneUnderstanding/LGN.C $ 00035 // $Id: LGN.C 14397 2011-01-14 20:33:47Z lior $ 00036 // 00037 00038 #ifndef LGN_C_DEFINED 00039 #define LGN_C_DEFINED 00040 00041 #include "plugins/SceneUnderstanding/LGN.H" 00042 00043 #include "Image/DrawOps.H" 00044 //#include "Image/OpenCVUtil.H" 00045 #include "Image/MathOps.H" 00046 #include "Image/Layout.H" 00047 #include "Simulation/SimEventQueue.H" 00048 #include "Simulation/SimEvents.H" 00049 #include "Media/MediaSimEvents.H" 00050 #include "Channels/InputFrame.H" 00051 #include "Image/Kernels.H" 00052 #include "Image/FilterOps.H" 00053 #include "Image/Convolutions.H" 00054 #include "GUI/DebugWin.H" 00055 #include <math.h> 00056 #include <fcntl.h> 00057 #include <limits> 00058 #include <string> 00059 00060 const ModelOptionCateg MOC_LGN = { 00061 MOC_SORTPRI_3, "LGN-Related Options" }; 00062 00063 // Used by: SimulationViewerEyeMvt 00064 const ModelOptionDef OPT_LGNShowDebug = 00065 { MODOPT_ARG(bool), "LGNShowDebug", &MOC_LGN, OPTEXP_CORE, 00066 "Show debug img", 00067 "lgn-debug", '\0', "<true|false>", "false" }; 00068 00069 00070 //Define the inst function name 00071 SIMMODULEINSTFUNC(LGN); 00072 00073 // ###################################################################### 00074 LGN::LGN(OptionManager& mgr, const std::string& descrName, 00075 const std::string& tagName) : 00076 SimModule(mgr, descrName, tagName), 00077 SIMCALLBACK_INIT(SimEventInputFrame), 00078 SIMCALLBACK_INIT(SimEventSaveOutput), 00079 itsShowDebug(&OPT_LGNShowDebug, this), 00080 itsInitialized(false) 00081 00082 { 00083 } 00084 00085 // ###################################################################### 00086 LGN::~LGN() 00087 { 00088 00089 } 00090 00091 // ###################################################################### 00092 void LGN::init(Dims numCells) 00093 { 00094 Image<float> img(numCells, ZEROS); 00095 for(int i=0; i<3; i++) 00096 { 00097 itsCellsInput.push_back(img); 00098 itsCellsMu.push_back(img); 00099 img.clear(1.0); 00100 itsCellsSig.push_back(img); 00101 } 00102 00103 00104 //NOTE: Should the LGN cells be initalizied randomly from the 00105 //using the learned sigma? 00106 // 00107 00108 itsInitialized = true; 00109 00110 } 00111 00112 // ###################################################################### 00113 void LGN::onSimEventInputFrame(SimEventQueue& q, 00114 rutz::shared_ptr<SimEventInputFrame>& e) 00115 { 00116 // here is the inputs image: 00117 GenericFrame frame = e->frame(); 00118 00119 const Image<PixRGB<byte> > inimg = rescale(frame.asRgb(), 640, 480); 00120 itsCurrentImg = inimg; 00121 00122 if (!itsInitialized) 00123 init(itsCurrentImg.getDims()); 00124 00125 00126 rutz::shared_ptr<GenericFrame::MetaData> metaData; 00127 if (frame.hasMetaData(std::string("ObjectsData"))) 00128 metaData = frame.getMetaData(std::string("ObjectsData")); 00129 00130 //set the LGN input 00131 Image<float> lum,rg,by; 00132 //getDKL(inimg, lum, rg, by); 00133 getLAB(inimg, lum, rg, by); 00134 00135 //Normalize all values to the same level 00136 inplaceNormalize(lum, 0.0F, 255.0F); 00137 inplaceNormalize(rg, 0.0F, 255.0F); 00138 inplaceNormalize(by, 0.0F, 255.0F); 00139 00140 Image<float> kernel = gaussian<float>(0.0F, 1.4, lum.getWidth(),1.0F); 00141 Image<float> kernel2 = gaussian<float>(0.0F, 1.5, lum.getWidth(),1.0F); 00142 Image<float> kernel3 = gaussian<float>(0.0F, 1.5, lum.getWidth(),1.0F); 00143 //// do the convolution: 00144 itsCellsInput[LUM] = sepFilter(lum, kernel, kernel, CONV_BOUNDARY_CLEAN); 00145 itsCellsInput[RG] = sepFilter(rg, kernel2, kernel2, CONV_BOUNDARY_CLEAN); 00146 itsCellsInput[BY] = sepFilter(by, kernel3, kernel3, CONV_BOUNDARY_CLEAN); 00147 00148 itsCellsMu[LUM] = itsCellsInput[LUM]; 00149 itsCellsMu[RG] = itsCellsInput[RG]; 00150 itsCellsMu[BY] = itsCellsInput[BY]; 00151 //evolve(); 00152 00153 //Output the cells 00154 q.post(rutz::make_shared(new SimEventLGNOutput(this, itsCellsMu, metaData))); 00155 00156 } 00157 00158 // ###################################################################### 00159 void LGN::onSimEventSaveOutput(SimEventQueue& q, rutz::shared_ptr<SimEventSaveOutput>& e) 00160 { 00161 if (itsShowDebug.getVal()) 00162 { 00163 // get the OFS to save to, assuming sinfo is of type 00164 // SimModuleSaveInfo (will throw a fatal exception otherwise): 00165 nub::ref<FrameOstream> ofs = 00166 dynamic_cast<const SimModuleSaveInfo&>(e->sinfo()).ofs; 00167 Layout<PixRGB<byte> > disp = getDebugImage(); 00168 ofs->writeRgbLayout(disp, "LGN", FrameInfo("LGN", SRC_POS)); 00169 } 00170 } 00171 00172 00173 void LGN::setBias(const ImageSet<float>& prior) 00174 { 00175 00176 } 00177 00178 // ###################################################################### 00179 void LGN::evolve() 00180 { 00181 float R = 2; //5; //Sensor noise variance 00182 float Q=0.1; //Prcess noise variance 00183 00184 //getchar(); 00185 for(int i=0; i<3; i++) 00186 { 00187 00188 //Update the gagnlion cells 00189 Image<float>::const_iterator inPtr = itsCellsInput[i].begin(); 00190 Image<float>::const_iterator inStop = itsCellsInput[i].end(); 00191 00192 Image<float>::iterator muPtr = itsCellsMu[i].beginw(); 00193 Image<float>::iterator sigPtr = itsCellsSig[i].beginw(); 00194 00195 //Kalman filtering for each LGN cell 00196 while(inPtr != inStop) 00197 { 00198 //Predict 00199 float mu_hat = *muPtr; // + *gangPriorPtr; 00200 float sig_hat = *sigPtr + Q; 00201 00202 //update 00203 float K = (sig_hat)/(sig_hat + R); 00204 //*muPtr = mu_hat + K * (*inPtr - mu_hat); 00205 *muPtr =*inPtr; 00206 *sigPtr = (1-K)*sig_hat; 00207 00208 //Calculate surprise KL(P(M|D),P(M)) 00209 //P(M|D) = N(*muPtr, * sigPtr); 00210 //P(M) = N(mu_hat, sig_hat); 00211 00212 float surprise = (((*muPtr-mu_hat)*(*muPtr-mu_hat)) + (*sigPtr * *sigPtr) + (sig_hat*sig_hat)); 00213 surprise = surprise / (2*sig_hat*sig_hat); 00214 surprise += log(sig_hat / *sigPtr); 00215 00216 //if (surprise > 0.1) 00217 // *outPtr = *inPtr; 00218 //else 00219 //*outPtr = surprise; 00220 00221 ++inPtr; 00222 ++muPtr; 00223 ++sigPtr; 00224 } 00225 } 00226 00227 } 00228 00229 Layout<PixRGB<byte> > LGN::getDebugImage() 00230 { 00231 //Display the results 00232 Image<float> lumPerc = itsCellsMu[0]; 00233 Image<float> rgPerc = itsCellsMu[1]; 00234 Image<float> byPerc = itsCellsMu[2]; 00235 00236 //Display result 00237 inplaceNormalize(lumPerc, 0.0F, 255.0F); 00238 inplaceNormalize(rgPerc, 0.0F, 255.0F); 00239 inplaceNormalize(byPerc, 0.0F, 255.0F); 00240 //inplaceNormalize(gangPercSig, 0.0F, 255.0F); 00241 //inplaceNormalize(gangOut, 0.0F, 255.0F); 00242 00243 Layout<PixRGB<byte> > disp; 00244 disp = hcat(itsCurrentImg, toRGB(Image<byte>(lumPerc))); 00245 disp = hcat(disp, toRGB(Image<byte>(rgPerc))); 00246 disp = hcat(disp, toRGB(Image<byte>(byPerc))); 00247 00248 return disp; 00249 00250 } 00251 00252 00253 // ###################################################################### 00254 /* So things look consistent in everyone's emacs... */ 00255 /* Local Variables: */ 00256 /* indent-tabs-mode: nil */ 00257 /* End: */ 00258 00259 #endif 00260