
00001 /*!@file Media/FrameSeries.H a series of frames */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003 // 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: Rob Peters <rjpeters at usc dot edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Media/FrameSeries.H $ 00035 // $Id: FrameSeries.H 8896 2007-10-24 22:18:42Z rjpeters $ 00036 // 00037 00038 #ifndef FRAMESERIES_H_DEFINED 00039 #define FRAMESERIES_H_DEFINED 00040 00041 #include "Component/ModelParam.H" 00042 #include "Image/Dims.H" 00043 #include "Image/Rectangle.H" 00044 #include "Media/FrameRange.H" 00045 #include "Media/FrameState.H" 00046 #include "Transport/FrameIstream.H" 00047 #include "Transport/FrameOstream.H" 00048 #include "Util/Types.H" 00049 00050 class SimTime; 00051 template <class T> class Image; 00052 template <class T> class PixRGB; 00053 00054 // ###################################################################### 00055 //! A FrameSeries with additional facilities for reading input frames 00056 /*! General notes for InputFrameSeries and OutputFrameSeries: these 00057 classes keep track of a range of frames ([first..last]) and an 00058 interframe delay in seconds (see FrameRange.H). The key behavior 00059 is the update() function, which takes the current simulation time 00060 in seconds and the simulation step in s, and returns a status code 00061 indicating whether the frame series (a) was unchanged, (b) will 00062 require that the next frame be loaded just before the simulation 00063 time is advanced by the current simulation step, or (c) is 00064 finished. 00065 00066 InputFrameSeries implements a number of helper functions to 00067 facilitate reading frames in a standardized manner, with possible 00068 on-the-fly rescaling and visualization. 00069 00070 NOTE: if we're in test mode (because --test-mode was given on the 00071 command line), we will turn off all displays even though they may 00072 be on here (actually what happens is that ImageDisplayStream 00073 refuses to do anything if in --test-mode). 00074 00075 NOTE: when start() is called, we will set the "FOAradius", 00076 "FoveaRadius", "InputFrameDims", "SCinitialEyePosition" and 00077 "SCinitialHeadPosition" model parameters from input image dims, if 00078 someone wants them and they have not been set. 00079 00080 00081 NOTES on controlling InputFrameSeries and OutputFrameSeries from 00082 the command-line: 00083 00084 Examples: 00085 \verbatim 00086 --in=raster:foo.ppm 00087 --in=raster:#.png [to get foo000000.ppm, foo000001.ppm, etc.] 00088 --in=mpeg:/path/to/file.mpg 00089 --in=random:512x512 00090 --in=colorbars 00091 00092 --out=display 00093 --out=qt 00094 --out=mpeg 00095 --out=png:/path/to/basestem 00096 --out=pnm:/path/to/basestem 00097 --out=none 00098 --out=hash 00099 00100 --io=raster:path/to/framestem 00101 --io=mpeg:file.mpg 00102 \endverbatim 00103 00104 Any time you use an InputFrameSeries or OutputFrameSeries, you can 00105 automatically use input/output in any of the formats that we 00106 support. That means: 00107 00108 - your InputFrameSeries can take input from a series of raster 00109 files (the previous default behavior), or from any movie file 00110 that is readable by avcodec, or from an in-memory random number 00111 generator. Other input formats are possible, please write your 00112 own subclass of FrameIstream and add command-line support for it 00113 to InputFrameSeries. 00114 00115 - your OutputFrameSeries can generate output going to series of 00116 raster files (the previous default behavior), or to mpeg files, 00117 or to onscreen windows, or to nowhere at all. Again, other 00118 output formats are possible, please write your own subclass of 00119 FrameOstream and add command-line support for it to 00120 OutputFrameSeries. 00121 00122 The simplest behavior (which matches the historical behavior of 00123 the ezvision executable in which input and output both deal with 00124 raster file series using the same filename stem) can be gotten 00125 like this: 00126 00127 ./bin/ezvision --bunch --of --options --io=raster:myinputfilestem 00128 00129 To get to the more advanced features, you can use --in and --out 00130 instead of --io (note that --io=foo is just an alias for --in=foo 00131 --out=foo). For any of the options, you want to pass something of 00132 the form "type:spec", where 'type' is one of <raster|mpeg|random> 00133 for input options, or <raster|mpeg|display|none> for output 00134 options. The 'spec' part is type-dependent; for raster or mpeg the 00135 spec gives the filename or filename stem; for random, the spec is 00136 the desired image size as WWWxHHH (e.g. 512x512); for display and 00137 none, the spec is not required. 00138 00139 As a shorthand convenience, you can eliminate either the type or 00140 spec if it can be inferred from the other part. E.g., if your spec 00141 ends in a raster file extension (.ppm, .pnm, .png, .pgm) or mpeg 00142 file extension (.mpg, .mpeg, .m4v), you can skip the 'type' and just 00143 do --in=file.ppm or --out=file.mpg, which will be interpreted as 00144 --in=raster:file.ppm or --out=mpeg:file.mpg. Likewise, for the types 00145 that don't require any extra spec info, you can just do 00146 --out=display or --out=none, which are shorthand for --out=display: 00147 and --out=none:. 00148 00149 Note that you can only have one input source, so if you have 00150 multiple --in or --io options on your command-line, the last such 00151 option will override all previous ones. 00152 00153 On the other hand, you can reasonably have multiple output 00154 destinations, so if there are multiple --out or --io options on 00155 the command-line, the output will be sent to all destinations in 00156 parallel. So, if you want to save your results to files but also 00157 watch them onscreen as the computation progresses, you could do 00158 --out=mpeg --out=display. As a special case, if you do --out=none, 00159 it will cancel any previous --out options (though later --out 00160 options will still take effect). 00161 00162 Finally, you can use the --in-echo option to specify one or more 00163 destinations to which copies of the input should be sent. The 00164 --in-echo option accepts the same types of values as does --out, 00165 so e.g. if you want to see your input stream in an onscreen 00166 window, you can do --in=mpeg:myfile.mpg --in-echo=display. 00167 00168 A couple other miscellaneous things: 00169 00170 - the [no]display-input frames and [no]display-output-frames options 00171 have been superseded by the new, more flexible behavior -- if you 00172 want to mimic --nodisplay-input-frames or 00173 --nodisplay-output-frames, just do nothing since the default is 00174 for the frames to not be displayed onscreen. If you do want 00175 display, you can use --in-copy=display and/or --out=display. 00176 00177 - there is a new command-line flag, --[no]wait, that controls the 00178 result of InputFrameSeries::shouldWait() and 00179 OutputFrameSeries::shouldWait(), which is used to determine 00180 whether we do a Raster::waitForKey() in the main loop after 00181 processing a new input or output frame; the default is --nowait, 00182 so if you want the pause, then you should do an explicit --wait 00183 on the command-line 00184 */ 00185 class InputFrameSeries : public FrameIstream 00186 { 00187 public: 00188 //! Constructor 00189 InputFrameSeries(OptionManager& mgr, 00190 const std::string& descrName = "Frame Series", 00191 const std::string& tagName = "FrameSeries"); 00192 00193 //! Destructor 00194 virtual ~InputFrameSeries(); 00195 00196 //! resets this FrameSeries to its state after construction 00197 virtual void reset1(); 00198 00199 //! Override the base version so that we can trap --in and --in-echo options 00200 virtual void paramChanged(ModelParamBase* const param, 00201 const bool valueChanged, 00202 ParamClient::ChangeStatus* status); 00203 00204 //! Update internal state and return corresponding FrameState 00205 /*! @param stime current time in seconds 00206 @param sdelay time step in seconds */ 00207 FrameState update(const SimTime& stime); 00208 00209 //! Update by moving to the next frame and not worrying about time counts 00210 FrameState updateNext(); 00211 00212 //! Have we displayed frames and need to wait for a user keypress? 00213 /*! This is reset to false on each call to update(), and becomes 00214 true if (1) any frames were written AND (2) itsWaitForUser is 00215 true (which the use can control with --wait/--nowait). You can 00216 check it in order to decide whether you should pause and wait 00217 for the user after each series of displays at a given time 00218 step). */ 00219 bool shouldWait() const; 00220 00221 //! Get specifications of the image frames 00222 /*! It is okay to call this before the model is started(). If input 00223 resizing is being done, the returned dimensions will be the 00224 resized dims. All in all, this will return the size of whatever 00225 you will get when calling readFrame(), readRGB(), etc. */ 00226 virtual GenericFrameSpec peekFrameSpec(); 00227 00228 //! Optional call to efficiently prepare for frame streaming 00229 virtual void startStream(); 00230 00231 //! Read a GenericFrame 00232 virtual GenericFrame readFrame(); 00233 00234 //! Set the frame source; same as doing --in=source on the command line 00235 void setFrameSource(const std::string& source); 00236 00237 //! Get the current frame number 00238 int frame() const; 00239 00240 //! Get a reference to our frame source 00241 nub::ref<FrameIstream> getFrameSource() const; 00242 00243 private: 00244 //! post-commandline-parsing initialization 00245 /*! Sets the initial frame number. */ 00246 virtual void start1(); 00247 00248 //! post-commandline-parsing initialization (see ModelComponent.H) 00249 /*! Will peek the first frame (without fully loading it) and set 00250 "FOAradius", "FoveaRadius", "InputFrameDims" 00251 "SCinitialEyePosition" and "SCinitialHeadPosition" model 00252 parameters from input image dims if someone wants them and they 00253 have not been set */ 00254 virtual void start2(); 00255 00256 //! text log file name 00257 OModelParam<std::string> itsLogFile; 00258 00259 //! if in test mode, then shouldWait() is always false 00260 OModelParam<bool> itsTestMode; 00261 00262 //! range of frames and inter-frame delay in SECONDS 00263 OModelParam<FrameRange> itsFrameRange; 00264 00265 //! Rectangle to which frames should be cropped 00266 OModelParam<Rectangle> itsCropRect; 00267 00268 //! dims to which frames should be resized on read/write, or 0x0 for none 00269 OModelParam<Dims> itsDims; 00270 00271 //! if true, aspect ratio of original image will be preserved when resizing 00272 OModelParam<bool> itsPreserveAspect; 00273 00274 //! If true, all frame numbers are 000000, forces no numbering 00275 OModelParam<bool> itsZeroNumberFrames; 00276 00277 //! catch --in command-line options 00278 OModelParam<std::string> itsFrameSource; 00279 00280 //! catch --io command-line options 00281 OModelParam<std::string> itsInOut; 00282 00283 //! catch --in-echo command-line options 00284 OModelParam<std::string> itsInputEcho; 00285 00286 //! whether to wait for user's keypress between frames 00287 OModelParam<bool> itsWaitForUser; 00288 00289 //! whether to keep going even after input is exhausted 00290 OModelParam<bool> itsKeepGoing; 00291 00292 struct Impl; 00293 friend struct Impl; 00294 Impl* const rep; 00295 }; 00296 00297 // ###################################################################### 00298 //! A FrameSeries with additional facilities for writing output frames 00299 /*! OutputFrameSeries implements a number of helper functions to 00300 facilitate writing frames in a standardized manner, with possible 00301 on-the-fly rescaling and visualization. 00302 00303 SEE ADDITIONAL DOCUMENTATION in InputFrameSeries. 00304 */ 00305 class OutputFrameSeries : public FrameOstream 00306 { 00307 public: 00308 //! Constructor 00309 OutputFrameSeries(OptionManager& mgr, 00310 const std::string& descrName = "Frame Series", 00311 const std::string& tagName = "FrameSeries"); 00312 00313 //! Destructor 00314 virtual ~OutputFrameSeries(); 00315 00316 //! resets this FrameSeries to its state after construction 00317 virtual void reset1(); 00318 00319 //! Override the base version so that we can trap --out options 00320 virtual void paramChanged(ModelParamBase* const param, 00321 const bool valueChanged, 00322 ParamClient::ChangeStatus* status); 00323 00324 //! Update internal state and return corresponding FrameState 00325 /*! @param stime current time in seconds 00326 @param sdelay time step in seconds 00327 @param new_event whether a new application-defined event has occurred 00328 */ 00329 FrameState update(const SimTime& stime, bool new_event); 00330 00331 //! Update by moving to the next frame and not worrying about time counts 00332 FrameState updateNext(); 00333 00334 //! Have we displayed frames and need to wait for a user keypress? 00335 /*! This is reset to false on each call to update(), and becomes 00336 true if (1) any frames were written AND (2) itsWaitForUser is 00337 true (which the use can control with --wait/--nowait). You can 00338 check it in order to decide whether you should pause and wait 00339 for the user after each series of displays at a given time 00340 step). */ 00341 bool shouldWait() const; 00342 00343 //! Write a frame to all frame destinations 00344 virtual void writeFrame(const GenericFrame& frame, 00345 const std::string& shortname, 00346 const FrameInfo& auxinfo = FrameOstream::defaultInfo); 00347 00348 //! Check if we have no output destinations (e.g., user gave --out=none) 00349 /*! Clients can test isVoid() before they generate potentially 00350 expensive output images. This is just a performance optimization 00351 -- even if isVoid() is true, it's still safe to call writeRGB(), 00352 writeGray(), etc., but those calls will do nothing, and so any 00353 time spent computing the image will have been wasted. */ 00354 virtual bool isVoid() const; 00355 00356 //! Check if we have become void after starting out non-void 00357 /*! This is useful to test in main loops to know whether some 00358 substream has gotten closed (e.g. the user pressing the close 00359 button on an open window). */ 00360 bool becameVoid() const; 00361 00362 //! Call closeStream(shortname) on all of our substreams 00363 virtual void closeStream(const std::string& shortname); 00364 00365 //! Add a frame destination; same as doing --out=source on the command line 00366 void addFrameDest(const std::string& source); 00367 00368 //! Get the current frame number 00369 int frame() const; 00370 00371 //! Get the number of frame destinations that we have 00372 size_t getNumFrameDests() const; 00373 00374 //! Get a reference to the n-th frame destination 00375 nub::ref<FrameOstream> getFrameDest(size_t n) const; 00376 00377 //! Try to return a frame destination matching type T, if any 00378 template <class T> 00379 nub::soft_ref<T> findFrameDestType() const 00380 { 00381 const size_t n = this->getNumFrameDests(); 00382 for (size_t i = 0; i < n; ++i) 00383 { 00384 const nub::soft_ref<T> casted = 00385 dyn_cast_weak<T>(this->getFrameDest(i)); 00386 00387 if (casted.is_valid()) 00388 return casted; 00389 } 00390 return nub::soft_ref<T>(); 00391 } 00392 00393 private: 00394 //! post-commandline-parsing initialization (see ModelComponent.H) 00395 virtual void start2(); 00396 00397 //! text log file name 00398 OModelParam<std::string> itsLogFile; 00399 00400 //! if in test mode, then shouldWait() is always false 00401 OModelParam<bool> itsTestMode; 00402 00403 //! range of frames and inter-frame delay in SECONDS 00404 OModelParam<FrameRange> itsFrameRange; 00405 00406 //! dims to which frames should be resized on read/write, or 0x0 for none 00407 OModelParam<Dims> itsDims; 00408 00409 //! if true, aspect ratio of original image will be preserved when resizing 00410 OModelParam<bool> itsPreserveAspect; 00411 00412 //! number of levels to zoom in (positive value) or out (negative value) 00413 OModelParam<int> itsZoom; 00414 00415 //! If true, all frame numbers are 000000, forces no numbering 00416 OModelParam<bool> itsZeroNumberFrames; 00417 00418 //! catch --out command-line options 00419 OModelParam<std::string> itsFrameSink; 00420 00421 //! catch --io command-line options 00422 OModelParam<std::string> itsInOut; 00423 00424 //! whether to wait for user's keypress between frames 00425 OModelParam<bool> itsWaitForUser; 00426 00427 //! how many times to replicate each output frame 00428 OModelParam<uint> itsOutputReplicate; 00429 00430 //! number of frames written since last update 00431 int itsNumWritten; 00432 00433 struct Impl; 00434 Impl* const rep; 00435 }; 00436 00437 #endif 00438 00439 // ###################################################################### 00440 /* So things look consistent in everyone's emacs... */ 00441 /* Local Variables: */ 00442 /* indent-tabs-mode: nil */ 00443 /* End: */
1.4.4