InputFrame.C

Go to the documentation of this file.
00001 /*!@file Channels/InputFrame.C */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
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/Channels/InputFrame.C $
00035 // $Id: InputFrame.C 14600 2011-03-14 21:52:47Z dberg $
00036 //
00037 
00038 #ifndef CHANNELS_INPUTFRAME_C_DEFINED
00039 #define CHANNELS_INPUTFRAME_C_DEFINED
00040 
00041 #include "Channels/InputFrame.H"
00042 
00043 #include "Image/ColorOps.H"
00044 #include "Util/Assert.H"
00045 #include "Util/JobWithSemaphore.H"
00046 #include "Util/MainJobServer.H"
00047 
00048 #include <pthread.h>
00049 #include <vector>
00050 
00051 // ######################################################################
00052 struct RgbByteToLuminanceJob : public JobWithSemaphore
00053 {
00054   RgbByteToLuminanceJob(const PixRGB<byte>* in_,
00055                         const PixRGB<byte>* end_,
00056                         float* lumout_)
00057     :
00058     in(in_), end(end_),
00059     lumout(lumout_)
00060   {}
00061 
00062   virtual ~RgbByteToLuminanceJob()
00063   {}
00064 
00065   virtual void run()
00066   {
00067     const PixRGB<byte>* in_ = in;
00068     const PixRGB<byte>* const end_ = end;
00069     float* lumout_ = lumout;
00070 
00071     const float one_third = 1.0f / 3.0f;
00072 
00073     while (in_ != end_)
00074       {
00075         *lumout_++ = one_third * (in_->p[0] + in_->p[1] + in_->p[2]);
00076         ++in_;
00077       }
00078 
00079     this->markFinished();
00080   }
00081 
00082   virtual const char* jobType() const { return "RgbByteToLuminanceJob"; }
00083 
00084   const PixRGB<byte>* const in;
00085   const PixRGB<byte>* const end;
00086   float* const lumout;
00087 };
00088 
00089 // ######################################################################
00090 struct RgbByteToFloatJob : public JobWithSemaphore
00091 {
00092   RgbByteToFloatJob(const PixRGB<byte>* in_,
00093                     const PixRGB<byte>* end_,
00094                     PixRGB<float>* rgbout_)
00095     :
00096     in(in_), end(end_),
00097     rgbout(rgbout_)
00098   {}
00099 
00100   virtual ~RgbByteToFloatJob()
00101   {}
00102 
00103   virtual void run()
00104   {
00105     const PixRGB<byte>* in_ = in;
00106     const PixRGB<byte>* const end_ = end;
00107     PixRGB<float>* rgbout_ = rgbout;
00108 
00109     while (in_ != end_)
00110       *rgbout_++ = PixRGB<float>(*in_++);
00111 
00112     this->markFinished();
00113   }
00114 
00115   virtual const char* jobType() const { return "RgbByteToFloatJob"; }
00116 
00117   const PixRGB<byte>* const in;
00118   const PixRGB<byte>* const end;
00119   PixRGB<float>* const rgbout;
00120 };
00121 
00122 // ######################################################################
00123 InputFrame::InputFrame()
00124 {}
00125 
00126 // ######################################################################
00127 InputFrame InputFrame::fromRgb(const Image<PixRGB<byte> >* in,
00128                                SimTime t,
00129                                const Image<byte>* clip,
00130                                const rutz::shared_ptr<PyramidCache<float> >& cache,
00131                                bool disableCache)
00132 {
00133   ASSERT(in != 0); ASSERT(in->initialized());
00134 
00135   InputFrame result;
00136 
00137   result.itsTime = t;
00138   result.itsDims = in->getDims();
00139   if (clip != 0)
00140     result.itsClipMask = *clip;
00141   else
00142     result.itsClipMask = Image<byte>();
00143   result.itsColorByte = *in;
00144 
00145   result.itsColorFloat = Image<PixRGB<float> >(); // will be generated on-demand in colorFloat()
00146   result.itsGrayFloat = Image<float>(in->getDims(), NO_INIT);
00147   result.itsPyrCache =
00148     disableCache
00149     ? rutz::shared_ptr<PyramidCache<float> >(/* null */)
00150     : cache.get() != 0
00151     ? cache
00152     : rutz::shared_ptr<PyramidCache<float> >(new PyramidCache<float>);
00153 
00154   result.itsPyrCacheRgb = rutz::shared_ptr<PyramidCache<PixRGB<float> > >(/* null */);
00155 
00156   const int sz = in->getSize();
00157 
00158   JobServer& srv = getMainJobServer();
00159 
00160   const unsigned int ntiles = srv.getParallelismHint();
00161 
00162   LDEBUG("ntiles = %u", ntiles);
00163 
00164   std::vector<rutz::shared_ptr<RgbByteToLuminanceJob > > jobs;
00165 
00166   for (unsigned int i = 0; i < ntiles; ++i)
00167     {
00168       const int start = (i*sz)/ntiles;
00169       const int end = ((i+1)*sz)/ntiles;
00170 
00171       jobs.push_back
00172         (rutz::make_shared(new RgbByteToLuminanceJob
00173                            (in->getArrayPtr() + start,
00174                             in->getArrayPtr() + end,
00175                             result.itsGrayFloat.getArrayPtr() + start)));
00176 
00177       srv.enqueueJob(jobs.back());
00178     }
00179 
00180   for (size_t i = 0; i < jobs.size(); ++i)
00181     jobs[i]->wait();
00182 
00183   return result;
00184 }
00185 
00186 // ######################################################################
00187 InputFrame InputFrame::fromRgbFloat(const Image<PixRGB<float> >* col,
00188                                     SimTime t,
00189                                     const Image<byte>* clip,
00190                                     const rutz::shared_ptr<PyramidCache<float> >& cache,
00191                                     bool disableCache)
00192 {
00193   ASSERT(col != 0); ASSERT(col->initialized());
00194 
00195   InputFrame result;
00196 
00197   result.itsTime = t;
00198   result.itsDims = col->getDims();
00199   if (clip != 0)
00200     result.itsClipMask = *clip;
00201   else
00202     result.itsClipMask = Image<byte>();
00203   result.itsColorByte = Image<PixRGB<byte> >();
00204   result.itsColorFloat = *col;
00205   result.itsGrayFloat = luminance(result.itsColorFloat);
00206   result.itsPyrCache =
00207     disableCache
00208     ? rutz::shared_ptr<PyramidCache<float> >(/* null */)
00209     : cache.get() != 0
00210     ? cache
00211     : rutz::shared_ptr<PyramidCache<float> >(new PyramidCache<float>);
00212   
00213   result.itsPyrCacheRgb = rutz::shared_ptr<PyramidCache<PixRGB<float> > >(/* null */);
00214     
00215   return result;
00216 }
00217 
00218 // ######################################################################
00219 InputFrame InputFrame::fromGrayFloat(const Image<float>* bw,
00220                                      SimTime t,
00221                                      const Image<byte>* clip,
00222                                      const rutz::shared_ptr<PyramidCache<float> >& cache,
00223                                      bool disableCache)
00224 {
00225   ASSERT(bw != 0); ASSERT(bw->initialized());
00226 
00227   InputFrame result;
00228 
00229   result.itsTime = t;
00230   result.itsDims = bw->getDims();
00231   if (clip != 0)
00232     result.itsClipMask = *clip;
00233   else
00234     result.itsClipMask = Image<byte>();
00235   result.itsColorByte = Image<PixRGB<byte> >();
00236   result.itsColorFloat = Image<PixRGB<float> >();
00237   result.itsGrayFloat = *bw;
00238   result.itsPyrCache =
00239     disableCache
00240     ? rutz::shared_ptr<PyramidCache<float> >(/* null */)
00241     : cache.get() != 0
00242     ? cache
00243     : rutz::shared_ptr<PyramidCache<float> >(new PyramidCache<float>);
00244 
00245   result.itsPyrCacheRgb = rutz::shared_ptr<PyramidCache<PixRGB<float> > >(/* null */);
00246 
00247   return result;
00248 }
00249 // ######################################################################
00250 InputFrame InputFrame::fromRgbAndGrayFloat(const Image<PixRGB<byte> >* rgbb,
00251                                            const Image<PixRGB<float> >* rgbf,
00252                                            const Image<float>* bw,
00253                                            SimTime t,
00254                                            const Image<byte>* clip,
00255                                            const rutz::shared_ptr<PyramidCache<float> >& cache,
00256                                            bool disableCache)
00257 {
00258   ASSERT(rgbb != 0); ASSERT(rgbb->initialized());
00259   ASSERT(rgbf != 0); ASSERT(rgbf->initialized());
00260   ASSERT(bw != 0); ASSERT(bw->initialized());
00261 
00262   if (rgbb->getDims() != rgbf->getDims())
00263     LFATAL("Color-byte and color-float inputs must have the same dimensions "
00264            "(got %dx%d color-byte and %dx%d color-float)",
00265            rgbb->getWidth(), rgbb->getHeight(),
00266            rgbf->getWidth(), rgbf->getHeight());
00267 
00268   if (rgbf->getDims() != bw->getDims())
00269     LFATAL("Color and grayscale inputs must have the same dimensions "
00270            "(got %dx%d color and %dx%d grayscale)",
00271            rgbf->getWidth(), rgbf->getHeight(),
00272            bw->getWidth(), bw->getHeight());
00273 
00274   InputFrame result;
00275 
00276   result.itsTime = t;
00277   result.itsDims = rgbb->getDims();
00278   if (clip != 0)
00279     result.itsClipMask = *clip;
00280   else
00281     result.itsClipMask = Image<byte>();
00282   result.itsColorByte = *rgbb;
00283   result.itsColorFloat = *rgbf;
00284   result.itsGrayFloat = *bw;
00285   result.itsPyrCache =
00286     disableCache
00287     ? rutz::shared_ptr<PyramidCache<float> >(/* null */)
00288     : cache.get() != 0
00289     ? cache
00290     : rutz::shared_ptr<PyramidCache<float> >(new PyramidCache<float>);
00291 
00292   result.itsPyrCacheRgb = rutz::shared_ptr<PyramidCache<PixRGB<float> > >(/* null */);
00293 
00294   return result;
00295 }
00296 // ######################################################################
00297 InputFrame InputFrame::fromRgbDepth(const Image<PixRGB<byte> >* in,
00298                                     const Image<uint16>* depth,
00299                                     SimTime t,
00300                                     const Image<byte>* clip,
00301                                     const rutz::shared_ptr<PyramidCache<float> >& cache,
00302                                     bool disableCache)
00303 {
00304   ASSERT(in != 0); ASSERT(in->initialized());
00305   ASSERT(depth != 0); ASSERT(depth->initialized());
00306 
00307   InputFrame result;
00308 
00309   result.itsTime = t;
00310   result.itsDims = in->getDims();
00311   if (clip != 0)
00312     result.itsClipMask = *clip;
00313   else
00314     result.itsClipMask = Image<byte>();
00315   result.itsColorByte = *in;
00316 
00317   result.itsDepthImage = *depth;
00318 
00319   result.itsColorFloat = Image<PixRGB<float> >(); // will be generated on-demand in colorFloat()
00320   result.itsGrayFloat = Image<float>(in->getDims(), NO_INIT);
00321   result.itsPyrCache =
00322     disableCache
00323     ? rutz::shared_ptr<PyramidCache<float> >(/* null */)
00324     : cache.get() != 0
00325     ? cache
00326     : rutz::shared_ptr<PyramidCache<float> >(new PyramidCache<float>);
00327 
00328   result.itsPyrCacheRgb = rutz::shared_ptr<PyramidCache<PixRGB<float> > >(/* null */);
00329 
00330   const int sz = in->getSize();
00331 
00332   JobServer& srv = getMainJobServer();
00333 
00334   const unsigned int ntiles = srv.getParallelismHint();
00335 
00336   LDEBUG("ntiles = %u", ntiles);
00337 
00338   std::vector<rutz::shared_ptr<RgbByteToLuminanceJob > > jobs;
00339 
00340   for (unsigned int i = 0; i < ntiles; ++i)
00341     {
00342       const int start = (i*sz)/ntiles;
00343       const int end = ((i+1)*sz)/ntiles;
00344 
00345       jobs.push_back
00346         (rutz::make_shared(new RgbByteToLuminanceJob
00347                            (in->getArrayPtr() + start,
00348                             in->getArrayPtr() + end,
00349                             result.itsGrayFloat.getArrayPtr() + start)));
00350 
00351       srv.enqueueJob(jobs.back());
00352     }
00353 
00354   for (size_t i = 0; i < jobs.size(); ++i)
00355     jobs[i]->wait();
00356 
00357   return result;
00358 }
00359 
00360 // ######################################################################
00361 const Image<PixRGB<float> >& InputFrame::colorFloat() const
00362 {
00363   if (!itsColorFloat.initialized() && itsColorByte.initialized())
00364     {
00365       itsColorFloat = Image<float>(itsColorByte.getDims(), NO_INIT);
00366 
00367       const int sz = itsColorByte.getSize();
00368 
00369       JobServer& srv = getMainJobServer();
00370 
00371       const unsigned int ntiles = srv.getParallelismHint();
00372 
00373       LDEBUG("ntiles = %u", ntiles);
00374 
00375       std::vector<rutz::shared_ptr<RgbByteToFloatJob > > jobs;
00376 
00377       for (unsigned int i = 0; i < ntiles; ++i)
00378         {
00379           const int start = (i*sz)/ntiles;
00380           const int end = ((i+1)*sz)/ntiles;
00381 
00382           jobs.push_back
00383             (rutz::make_shared(new RgbByteToFloatJob
00384                                (itsColorByte.getArrayPtr() + start,
00385                                 itsColorByte.getArrayPtr() + end,
00386                                 const_cast<PixRGB<float>*>
00387                                 (itsColorFloat.getArrayPtr() + start))));
00388 
00389           srv.enqueueJob(jobs.back());
00390         }
00391 
00392       for (size_t i = 0; i < jobs.size(); ++i)
00393         jobs[i]->wait();
00394     }
00395 
00396   return itsColorFloat;
00397 }
00398 
00399 const rutz::shared_ptr<PyramidCache<float> > InputFrame::emptyCache;
00400 
00401 // ######################################################################
00402 /* So things look consistent in everyone's emacs... */
00403 /* Local Variables: */
00404 /* indent-tabs-mode: nil */
00405 /* End: */
00406 
00407 #endif // CHANNELS_INPUTFRAME_C_DEFINED
Generated on Sun May 8 08:04:36 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3