FrameSeries.H

Go to the documentation of this file.
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: */
Generated on Sun May 8 08:41:01 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3