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 14139 2010-10-16 02:11:21Z dparks $ 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 virtual void setFrameDims(Dims d); 00235 virtual Dims getFrameDims(); 00236 00237 //! Set the frame source; same as doing --in=source on the command line 00238 void setFrameSource(const std::string& source); 00239 00240 //! Get the current frame number 00241 int frame() const; 00242 00243 //! Get a reference to our frame source 00244 nub::ref<FrameIstream> getFrameSource() const; 00245 00246 //! Get a copy of the framerange 00247 FrameRange getFrameRange() const ; 00248 00249 //! Force the frame number to a new value 00250 bool setFrameNumber(int n); 00251 00252 private: 00253 //! post-commandline-parsing initialization 00254 /*! Sets the initial frame number. */ 00255 virtual void start1(); 00256 00257 //! post-commandline-parsing initialization (see ModelComponent.H) 00258 /*! Will peek the first frame (without fully loading it) and set 00259 "FOAradius", "FoveaRadius", "InputFrameDims" 00260 "SCinitialEyePosition" and "SCinitialHeadPosition" model 00261 parameters from input image dims if someone wants them and they 00262 have not been set */ 00263 virtual void start2(); 00264 00265 //! text log file name 00266 OModelParam<std::string> itsLogFile; 00267 00268 //! if in test mode, then shouldWait() is always false 00269 OModelParam<bool> itsTestMode; 00270 00271 //! range of frames and inter-frame delay in SECONDS 00272 OModelParam<FrameRange> itsFrameRange; 00273 00274 //! Wether to set the frame back to the start if we reached the end 00275 OModelParam<bool> itsFrameWrap; 00276 00277 //! Rectangle to which frames should be cropped 00278 OModelParam<Rectangle> itsCropRect; 00279 00280 //! dims to which frames should be resized on read/write, or 0x0 for none 00281 OModelParam<Dims> itsDims; 00282 00283 //! if true, aspect ratio of original image will be preserved when resizing 00284 OModelParam<bool> itsPreserveAspect; 00285 00286 //! If true, all frame numbers are 000000, forces no numbering 00287 OModelParam<bool> itsZeroNumberFrames; 00288 00289 //! catch --in command-line options 00290 OModelParam<std::string> itsFrameSource; 00291 00292 //! catch --io command-line options 00293 OModelParam<std::string> itsInOut; 00294 00295 //! catch --in-echo command-line options 00296 OModelParam<std::string> itsInputEcho; 00297 00298 //! whether to wait for user's keypress between frames 00299 OModelParam<bool> itsWaitForUser; 00300 00301 //! whether to keep going even after input is exhausted 00302 OModelParam<bool> itsKeepGoing; 00303 00304 struct Impl; 00305 friend struct Impl; 00306 Impl* const rep; 00307 }; 00308 00309 // ###################################################################### 00310 //! A FrameSeries with additional facilities for writing output frames 00311 /*! OutputFrameSeries implements a number of helper functions to 00312 facilitate writing frames in a standardized manner, with possible 00313 on-the-fly rescaling and visualization. 00314 00315 SEE ADDITIONAL DOCUMENTATION in InputFrameSeries. 00316 */ 00317 class OutputFrameSeries : public FrameOstream 00318 { 00319 public: 00320 //! Constructor 00321 OutputFrameSeries(OptionManager& mgr, 00322 const std::string& descrName = "Frame Series", 00323 const std::string& tagName = "FrameSeries"); 00324 00325 //! Destructor 00326 virtual ~OutputFrameSeries(); 00327 00328 //! resets this FrameSeries to its state after construction 00329 virtual void reset1(); 00330 00331 //! Override the base version so that we can trap --out options 00332 virtual void paramChanged(ModelParamBase* const param, 00333 const bool valueChanged, 00334 ParamClient::ChangeStatus* status); 00335 00336 //! Update internal state and return corresponding FrameState 00337 /*! @param stime current time in seconds 00338 @param sdelay time step in seconds 00339 @param new_event whether a new application-defined event has occurred 00340 */ 00341 FrameState update(const SimTime& stime, bool new_event); 00342 00343 //! Update by moving to the next frame and not worrying about time counts 00344 FrameState updateNext(); 00345 00346 //! Have we displayed frames and need to wait for a user keypress? 00347 /*! This is reset to false on each call to update(), and becomes 00348 true if (1) any frames were written AND (2) itsWaitForUser is 00349 true (which the use can control with --wait/--nowait). You can 00350 check it in order to decide whether you should pause and wait 00351 for the user after each series of displays at a given time 00352 step). */ 00353 bool shouldWait() const; 00354 00355 //! Write a frame to all frame destinations 00356 virtual void writeFrame(const GenericFrame& frame, 00357 const std::string& shortname, 00358 const FrameInfo& auxinfo = FrameOstream::defaultInfo); 00359 00360 //! Check if we have no output destinations (e.g., user gave --out=none) 00361 /*! Clients can test isVoid() before they generate potentially 00362 expensive output images. This is just a performance optimization 00363 -- even if isVoid() is true, it's still safe to call writeRGB(), 00364 writeGray(), etc., but those calls will do nothing, and so any 00365 time spent computing the image will have been wasted. */ 00366 virtual bool isVoid() const; 00367 00368 //! Check if we have become void after starting out non-void 00369 /*! This is useful to test in main loops to know whether some 00370 substream has gotten closed (e.g. the user pressing the close 00371 button on an open window). */ 00372 bool becameVoid() const; 00373 00374 //! Call closeStream(shortname) on all of our substreams 00375 virtual void closeStream(const std::string& shortname); 00376 00377 //! Add a frame destination; same as doing --out=source on the command line 00378 void addFrameDest(const std::string& source); 00379 00380 //! Get the current frame number 00381 int frame() const; 00382 00383 //! Get the number of frame destinations that we have 00384 size_t getNumFrameDests() const; 00385 00386 //! Get a reference to the n-th frame destination 00387 nub::ref<FrameOstream> getFrameDest(size_t n) const; 00388 00389 //! Try to return a frame destination matching type T, if any 00390 template <class T> 00391 nub::soft_ref<T> findFrameDestType() const 00392 { 00393 const size_t n = this->getNumFrameDests(); 00394 for (size_t i = 0; i < n; ++i) 00395 { 00396 const nub::soft_ref<T> casted = 00397 dyn_cast_weak<T>(this->getFrameDest(i)); 00398 00399 if (casted.is_valid()) 00400 return casted; 00401 } 00402 return nub::soft_ref<T>(); 00403 } 00404 00405 private: 00406 //! post-commandline-parsing initialization (see ModelComponent.H) 00407 virtual void start2(); 00408 00409 //! text log file name 00410 OModelParam<std::string> itsLogFile; 00411 00412 //! if in test mode, then shouldWait() is always false 00413 OModelParam<bool> itsTestMode; 00414 00415 //! range of frames and inter-frame delay in SECONDS 00416 OModelParam<FrameRange> itsFrameRange; 00417 00418 //! dims to which frames should be resized on read/write, or 0x0 for none 00419 OModelParam<Dims> itsDims; 00420 00421 //! if true, aspect ratio of original image will be preserved when resizing 00422 OModelParam<bool> itsPreserveAspect; 00423 00424 //! number of levels to zoom in (positive value) or out (negative value) 00425 OModelParam<int> itsZoom; 00426 00427 //! If true, all frame numbers are 000000, forces no numbering 00428 OModelParam<bool> itsZeroNumberFrames; 00429 00430 //! catch --out command-line options 00431 OModelParam<std::string> itsFrameSink; 00432 00433 //! catch --io command-line options 00434 OModelParam<std::string> itsInOut; 00435 00436 //! whether to wait for user's keypress between frames 00437 OModelParam<bool> itsWaitForUser; 00438 00439 //! how many times to replicate each output frame 00440 OModelParam<uint> itsOutputReplicate; 00441 00442 //! number of frames written since last update 00443 int itsNumWritten; 00444 00445 struct Impl; 00446 Impl* const rep; 00447 }; 00448 00449 #endif 00450 00451 // ###################################################################### 00452 /* So things look consistent in everyone's emacs... */ 00453 /* Local Variables: */ 00454 /* indent-tabs-mode: nil */ 00455 /* End: */