LoCompositor.H

Go to the documentation of this file.
00001 /**
00002    \file  Robots/LoBot/io/LoCompositor.H
00003    \brief Quick-and-dirty image stitcher.
00004 
00005    This file defines a class to read images from several sources and then
00006    stitch them together into a single image.
00007 */
00008 
00009 // //////////////////////////////////////////////////////////////////// //
00010 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00011 // by the University of Southern California (USC) and the iLab at USC.  //
00012 // See http://iLab.usc.edu for information about this project.          //
00013 // //////////////////////////////////////////////////////////////////// //
00014 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00015 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00016 // in Visual Environments, and Applications'' by Christof Koch and      //
00017 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00018 // pending; application number 09/912,225 filed July 23, 2001; see      //
00019 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00020 // //////////////////////////////////////////////////////////////////// //
00021 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00022 //                                                                      //
00023 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00024 // redistribute it and/or modify it under the terms of the GNU General  //
00025 // Public License as published by the Free Software Foundation; either  //
00026 // version 2 of the License, or (at your option) any later version.     //
00027 //                                                                      //
00028 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00029 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00030 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00031 // PURPOSE.  See the GNU General Public License for more details.       //
00032 //                                                                      //
00033 // You should have received a copy of the GNU General Public License    //
00034 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00035 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00036 // Boston, MA 02111-1307 USA.                                           //
00037 // //////////////////////////////////////////////////////////////////// //
00038 //
00039 // Primary maintainer for this file: Manu Viswanathan <mviswana at usc dot edu>
00040 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/io/LoCompositor.H $
00041 // $Id: LoCompositor.H 11230 2009-05-27 11:11:23Z mviswana $
00042 //
00043 
00044 #ifndef LOBOT_COMPOSITOR_DOT_H
00045 #define LOBOT_COMPOSITOR_DOT_H
00046 
00047 //------------------------------ HEADERS --------------------------------
00048 
00049 // lobot headers
00050 #include "Robots/LoBot/io/LoVideoStream.H"
00051 #include "Robots/LoBot/io/LoImageSource.H"
00052 
00053 #include "Robots/LoBot/misc/LoExcept.H"
00054 #include "Robots/LoBot/misc/LoTypes.H"
00055 
00056 // INVT image support
00057 #include "Image/CutPaste.H"
00058 #include "Image/ColorOps.H"
00059 #include "Image/Image.H"
00060 #include "Image/Point2D.H"
00061 #include "Image/Dims.H"
00062 
00063 // Standard C++ headers
00064 #include <list>
00065 #include <utility>
00066 
00067 //----------------------------- NAMESPACE -------------------------------
00068 
00069 namespace lobot {
00070 
00071 //------------------------- CLASS DEFINITION ----------------------------
00072 
00073 /**
00074    \class lobot::Compositor
00075    \brief Quick-and-dirty "panaromic" image stitcher.
00076 
00077    From Wikipedia:
00078 
00079       "Digital compositing is the process of digitally assembling
00080       multiple images to make a final image, typically for print, motion
00081       pictures or screen display. It is the evolution into the digital
00082       realm of optical film compositing."
00083 
00084    This class does not actually do any image compositing. No fancy alpha
00085    blending or any other such stuff. But technically, it does assemble
00086    multiple images into a final image and in that sense can be considered
00087    a kind of compositor (albeit a laughably crude one).
00088 
00089    Given a number of different video streams, lobot::Compositor reads the
00090    current frame from each and then simply stitches the images together
00091    to create a kind of panaromic image. Of course, it doesn't actually
00092    try to find correspondences between image boundaries and properly
00093    stitch the images to create the final result. Rather, it simply
00094    creates a big image and copies each of the source images into this
00095    final image.
00096 
00097    The motivation for this class is as follows: Robolocust is equipped
00098    with three FireWire cameras pointed straight ahead and to the left and
00099    right. We want to take the images from these cameras and create a
00100    single frame from them. Thus this simple-minded "compositor."
00101 */
00102 template<typename pixel_type>
00103 class Compositor : public ImageSource<pixel_type> {
00104    // Handy type to have around in a derived class
00105    typedef ImageSource<pixel_type> base ;
00106 
00107    // Prevent copy and assignment
00108    Compositor(const Compositor&) ;
00109    Compositor& operator=(const Compositor&) ;
00110 
00111    /// The compositor needs a number of video sources from which it can
00112    /// draw images to stitch into its final product.
00113    //@{
00114    typedef std::list<VideoStream*> Streams ;
00115    Streams m_streams ;
00116    //@}
00117 
00118    /// We update the dimensions of the output image as new sources are
00119    /// added so that we don't have to compute these dimensions every time
00120    /// the compositor's client requests it to output the compositing
00121    /// result.
00122    int m_output_width, m_output_height ;
00123 
00124 public:
00125    Compositor() ;
00126    ~Compositor() ;
00127 
00128    /// This method adds a video stream to the compositor's list of input
00129    /// sources.
00130    void push_back(VideoStream*) ;
00131 
00132    /// STL compatibility
00133    typedef Streams::const_reference const_reference ;
00134 
00135    /// This is the compositor's output routine. When invoked, it reads
00136    /// frames from all its current sources and stitches them together to
00137    /// create the final output image.
00138    void update() ;
00139 
00140    /// This method returns the output image's size
00141    Dims getImageSize() const {return Dims(m_output_width, m_output_height) ;}
00142 } ;
00143 
00144 //-------------------- INITIALIZATION AND CLEAN-UP ----------------------
00145 
00146 template<typename pixel_type>
00147 Compositor<pixel_type>::Compositor()
00148    : m_output_width(0), m_output_height(0)
00149 {}
00150 
00151 template<typename pixel_type>
00152 Compositor<pixel_type>::~Compositor()
00153 {}
00154 
00155 //----------------------- ADDING IMAGE SOURCES --------------------------
00156 
00157 // Every time a source is added, we need to update the dimensions of the
00158 // output image. If we don't do this here, in the output routine, we will
00159 // have to walk through the sources list twice: the first pass to
00160 // determine the output image's size and second to do the actual
00161 // compositing.
00162 template<typename pixel_type>
00163 void Compositor<pixel_type>::push_back(VideoStream* V)
00164 {
00165    if (! V)
00166       return ;
00167    m_streams.push_back(V) ;
00168 
00169    Dims frame_size = V->frameSize() ;
00170    m_output_width += frame_size.w() ;
00171    m_output_height = std::max(m_output_height, frame_size.h()) ;
00172 }
00173 
00174 //------------------------ IMAGE "COMPOSITING" --------------------------
00175 
00176 // The following function object reads the next frame from the specified
00177 // input video source and copies it into the target image. On each
00178 // invocation, it copies the source image into the correct location of
00179 // the target image by maintaining a "cursor" to keep track of the
00180 // insertion point. This cursor only moves along the x-direction, i.e.,
00181 // source images are copied to the target flush up against the top.
00182 namespace {
00183 
00184 template<typename T>
00185 class paste_into {
00186    mutable Image<T>& target ;
00187    mutable Point2D<int> cursor ;
00188 public:
00189    paste_into(Image<T>&) ;
00190    void operator()(const VideoStream* V) const {
00191       inplacePaste(target, V->readFrame(), cursor) ;
00192       cursor.i += V->frameSize().w() ;
00193    }
00194 } ;
00195 
00196 // When the above function object is instantiated, we will use the
00197 // supplied image as the target and initialize the cursor to start
00198 // inserting at the top left corner (0,0) of the target image.
00199 template<typename T>
00200 paste_into<T>::paste_into(Image<T>& I)
00201    : target(I), cursor(0,0)
00202 {}
00203 
00204 } // end of local namespace encapsulating above function object
00205 
00206 // This is the compositor's output routine. It assembles the output image
00207 // from the frames of each of its input video sources.
00208 template<typename T>
00209 void Compositor<T>::update()
00210 {
00211    if (m_streams.empty())
00212       throw vstream_error(NO_COMPOSITOR_SOURCES) ;
00213 
00214    Image<T> I(m_output_width, m_output_height, NO_INIT) ;
00215    std::for_each(m_streams.begin(), m_streams.end(), paste_into<T>(I)) ;
00216 
00217    base::m_image = I ;
00218    base::m_image_gray = GrayImage(luminance(I)) ;
00219 }
00220 
00221 //-----------------------------------------------------------------------
00222 
00223 } // end of namespace encapsulating this file's definitions
00224 
00225 #endif
00226 
00227 /* So things look consistent in everyone's emacs... */
00228 /* Local Variables: */
00229 /* indent-tabs-mode: nil */
00230 /* End: */
Generated on Sun May 8 08:41:30 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3