00001 /*!@file Transport/Stimulus2D.C generate stimulus from file */ 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: David Berg <dberg@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Transport/Stimulus2D.C $ 00035 00036 #include "Transport/Stimulus2D.H" 00037 #include "Transport/TransportOpts.H" // for MOC_INPUT 00038 #include "Component/ModelOptionDef.H" 00039 #include "Image/DrawOps.H" 00040 #include "Image/Normalize.H" // for FLOAT_NORM_PRESERVE 00041 #include "Raster/GenericFrame.H" 00042 #include "Util/StringConversions.H" 00043 #include "Util/StringUtil.H" 00044 #include "Util/SimTime.H" 00045 #include <fstream> 00046 00047 const ModelOptionDef OPT_Stimulus2DRadius = 00048 { MODOPT_ARG(int), "Stimulus2DRadius", &MOC_INPUT, OPTEXP_CORE, 00049 "The radius of the point to be drawn when reading from a stimulus " 00050 "2D file (.stim)", 00051 "stim2d-radius", '\0', "<integer>", "1" }; 00052 00053 //###################################################################### 00054 /*! 00055 Class to read a text file of 2d time varying input 00056 00057 File must have the following format: 00058 Sampling rate 00059 Image Size 00060 X Y VALUE ....repeat for multiple locations 00061 X Y VALUE .... 00062 . 00063 . 00064 00065 The first line is the Sampling period (eg .001s). The 00066 second line is the image size (e.g. 640x480) Remaining lines are time 00067 steps. The number of columns in each line will be a multiple of 00068 three. Each triplit will represent the horizontal (integer), vertical 00069 (integer) and intensity (float) of a stimulus. So two triplets, or six 00070 columns, would represent 2 stimuli. 00071 */ 00072 // ###################################################################### 00073 Stimulus2D::Stimulus2D(OptionManager& mgr, 00074 const std::string& descrName, 00075 const std::string& tagName) : 00076 FrameIstream(mgr, descrName, tagName), 00077 itsRadius(&OPT_Stimulus2DRadius, this), 00078 itsStim(), itsSR(SimTime::ZERO()), itsT(SimTime::ZERO()), itsDims(0,0) 00079 { }; 00080 00081 // ###################################################################### 00082 void Stimulus2D::setConfigInfo(const std::string& fileName) 00083 { 00084 //load our file 00085 std::ifstream *itsFile; 00086 itsFile = new std::ifstream(fileName.c_str()); 00087 00088 //error if no file 00089 if (itsFile->is_open() == false) 00090 LFATAL("Cannot open '%s' for reading",fileName.c_str()); 00091 00092 //get the number of samples 00093 std::string line; 00094 int linenum = 0; 00095 while (!itsFile->eof()) 00096 { 00097 getline(*itsFile, line); 00098 ++linenum; 00099 } 00100 itsFile->clear(); 00101 itsFile->seekg(0,std::ios_base::beg); 00102 linenum -= 3; 00103 00104 //get sampling rate line 1 00105 if (getline(*itsFile, line) < 0)//kill if empty 00106 LFATAL("Bad Format '%s'",fileName.c_str()); 00107 itsSR = SimTime(SimTime::SECS(fromStr<double>(line))); 00108 LINFO("Period:%3.8f",itsSR.secs()); 00109 00110 //get screen size line 2 00111 if (getline(*itsFile, line) < 0)//kill if empty 00112 LFATAL("Bad Format '%s'",fileName.c_str()); 00113 std::vector<std::string> tmptok;//tokenizer 00114 split(line, "x", std::back_inserter(tmptok)); 00115 if (tmptok.size() < 2)//kill if screen size wrong format 00116 LFATAL("Bad Format '%s', Screen size", fileName.c_str()); 00117 00118 //set image output dims 00119 itsDims = Dims(fromStr<int>(tmptok[0]), 00120 fromStr<int>(tmptok[1])); 00121 LINFO("Image Size: %dx%d",itsDims.w(),itsDims.h()); 00122 00123 std::streampos strpos = itsFile->tellg(); 00124 //read our first line for the number of stims 00125 getline(*itsFile, line); 00126 // let's tokenize it: 00127 std::vector<std::string> tok; 00128 split(line," ", std::back_inserter(tok)); 00129 //crash if wrong format 00130 if ((tok.size() % 3) != 0) 00131 LFATAL("Error parsing '%s', line %d only %d columns", 00132 fileName.c_str(), 3, (int)tok.size()); 00133 00134 //store number of stims and reset file position pointer 00135 const int numstims = tok.size(); 00136 itsStim = Image<float>(numstims,linenum,ZEROS); 00137 itsFile->seekg(strpos); 00138 00139 //loop until end counting lines 00140 linenum = 0; 00141 while (!itsFile->eof()) 00142 { 00143 // get a line 00144 getline(*itsFile, line); 00145 00146 // let's tokenize it: 00147 std::vector<std::string> strtok; 00148 split(line, " ", std::back_inserter(strtok)); 00149 //crash if wrong format 00150 if ((tok.size() % 3) != 0) 00151 LFATAL("Error parsing '%s', line %d only %d columns", 00152 fileName.c_str(), 3, (int)strtok.size()); 00153 00154 //valid line, so lets grab our data 00155 for (size_t jj = 0; jj < strtok.size(); jj++) 00156 itsStim.setVal(jj,linenum,fromStr<float>(strtok[jj])); 00157 00158 linenum++; 00159 } 00160 itsFile->close(); 00161 } 00162 00163 // ###################################################################### 00164 bool Stimulus2D::setFrameNumber(int n) 00165 { 00166 return skipTo(SimTime::SECS(n * itsSR.secs())); 00167 } 00168 00169 // ###################################################################### 00170 GenericFrameSpec Stimulus2D::peekFrameSpec() 00171 { 00172 if (itsStim.initialized()) 00173 { 00174 GenericFrameSpec fs; 00175 fs.nativeType = GenericFrame::GRAY_F32; 00176 fs.videoFormat = VIDFMT_AUTO; 00177 fs.videoByteSwap = false; 00178 fs.dims = getDims(); 00179 fs.floatFlags = FLOAT_NORM_PRESERVE; 00180 fs.frameRate = getSR().hertz(); 00181 return fs; 00182 } 00183 else 00184 { 00185 LFATAL("Don't be greedy, you can't peek the next frame until" 00186 " you've loaded a file."); 00187 return GenericFrameSpec(); 00188 } 00189 } 00190 00191 // ###################################################################### 00192 SimTime Stimulus2D::getNaturalFrameTime() const 00193 { 00194 return getSR(); 00195 } 00196 00197 // ###################################################################### 00198 GenericFrame Stimulus2D::readFrame() 00199 { 00200 return GenericFrame( next(itsRadius.getVal()), FLOAT_NORM_PRESERVE); 00201 } 00202 00203 // ###################################################################### 00204 const SimTime Stimulus2D::getTime() const 00205 { 00206 return itsT; 00207 } 00208 00209 // ###################################################################### 00210 const SimTime Stimulus2D::getTotalTime() const 00211 { 00212 double time = ((double)itsStim.getDims().h()-1) * itsSR.secs(); 00213 SimTime t(SimTime::SECS(time)); 00214 return t; 00215 } 00216 00217 // ###################################################################### 00218 const SimTime Stimulus2D::getSR() const 00219 { 00220 return itsSR; 00221 } 00222 00223 // ###################################################################### 00224 const Dims Stimulus2D::getDims() const 00225 { 00226 return itsDims; 00227 } 00228 00229 // ###################################################################### 00230 Image<float> Stimulus2D::next(const int rad) 00231 { 00232 if (itsStim.initialized()) 00233 { 00234 Image<float> retImage(itsDims,ZEROS); 00235 int pos = int(itsT.secs() / itsSR.secs()); 00236 for (int jj = 0; jj < itsStim.getDims().w();jj+=3){ 00237 int x,y; 00238 float in = itsStim.getVal(jj,pos); 00239 x = (int)itsStim.getVal(jj+1,pos); 00240 y = (int)itsStim.getVal(jj+2,pos); 00241 drawDisk(retImage,Point2D<int>(x,y),rad,in); 00242 } 00243 itsT+=itsSR; 00244 return retImage; 00245 } 00246 else 00247 { 00248 LFATAL("Must call setInputFile before requesting any data!"); 00249 return Image<float>();//will never execute. 00250 } 00251 } 00252 00253 // ###################################################################### 00254 bool Stimulus2D::skipTo(const SimTime t) 00255 { 00256 if (t > getTotalTime()) 00257 return false; 00258 else 00259 itsT = t; 00260 return true; 00261 } 00262 00263 // ###################################################################### 00264 /* So things look consistent in everyone's emacs... */ 00265 /* Local Variables: */ 00266 /* indent-tabs-mode: nil */ 00267 /* End: */