GameOfLifeInput.C

Go to the documentation of this file.
00001 /*!@file Transport/GameOfLifeInput.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/Transport/GameOfLifeInput.C $
00035 // $Id: GameOfLifeInput.C 9412 2008-03-10 23:10:15Z farhan $
00036 //
00037 
00038 #ifndef TRANSPORT_GAMEOFLIFEINPUT_C_DEFINED
00039 #define TRANSPORT_GAMEOFLIFEINPUT_C_DEFINED
00040 
00041 #include "Transport/GameOfLifeInput.H"
00042 
00043 #include "Component/ModelOptionDef.H"
00044 #include "Image/CutPaste.H"
00045 #include "Image/ShapeOps.H"
00046 #include "Raster/GenericFrame.H"
00047 #include "Transport/TransportOpts.H"
00048 
00049 namespace
00050 {
00051   Image<byte> gameOfLifeUpdate(const Image<byte>& in,
00052                                int* nlive)
00053   {
00054     Image<byte> out(in.getDims(), ZEROS);
00055 
00056     Image<byte>::const_iterator sptr = in.begin();
00057     Image<byte>::iterator dptr = out.beginw();
00058 
00059     const int w = in.getWidth();
00060     const int h = in.getHeight();
00061 
00062     *nlive = 0;
00063 
00064     for (int y = 0; y < h; ++y)
00065       for (int x = 0; x < w; ++x)
00066         {
00067           int nn = 0; // number of live neighbors
00068 
00069           if (y > 1)
00070             {
00071               if (x > 1   && sptr[-1-w] > 0) ++nn;
00072               if (           sptr[ 0-w] > 0) ++nn;
00073               if (x < w-1 && sptr[ 1-w] > 0) ++nn;
00074             }
00075 
00076           if (x > 1   && sptr[-1] > 0) ++nn;
00077           if (x < w-1 && sptr[ 1] > 0) ++nn;
00078 
00079           if (y < h-1)
00080             {
00081               if (x > 1   && sptr[-1+w] > 0) ++nn;
00082               if (           sptr[ 0+w] > 0) ++nn;
00083               if (x < w-1 && sptr[ 1+w] > 0) ++nn;
00084             }
00085 
00086           if (*sptr > 0) // cell is currently live
00087             {
00088               *dptr =
00089                 (nn == 2 || nn == 3)
00090                 ? 255 // stay alive
00091                 : 0;  // die
00092             }
00093           else // cell is currently dead
00094             {
00095               *dptr =
00096                 (nn == 3)
00097                 ? 255 // come alive
00098                 : 0;  // stay dead
00099             }
00100 
00101           if (*dptr > 0)
00102             ++*nlive;
00103 
00104           ++sptr;
00105           ++dptr;
00106         }
00107 
00108     return out;
00109   }
00110 }
00111 
00112 // Used by: GameOfLifeInput
00113 const ModelOptionDef OPT_GameOfLifeFillFraction =
00114   { MODOPT_ARG(double), "GameOfLifeFillFraction", &MOC_INPUT, OPTEXP_CORE,
00115     "In the \"Game of Life\" (with --in=life), this is the fraction "
00116     "of cells to be filled as \"live\" when creating the initial "
00117     "random game board, and when re-seeding the board after it becomes "
00118     "stuck.",
00119     "life-fill-fraction", '\0', "float", "0.4" };
00120 
00121 // Used by: GameOfLifeInput
00122 const ModelOptionDef OPT_GameOfLifeCellSize =
00123   { MODOPT_ARG(uint), "GameOfLifeCellSize", &MOC_INPUT, OPTEXP_CORE,
00124     "In the \"Game of Life\" (with --in=life), this is the size, in "
00125     "pixels, of each cell.",
00126     "life-cell-size", '\0', "uint", "4" };
00127 
00128 // ######################################################################
00129 GameOfLifeInput::GameOfLifeInput(OptionManager& mgr)
00130   :
00131   FrameIstream(mgr, "Random Input", "GameOfLifeInput"),
00132   itsFillFraction(&OPT_GameOfLifeFillFraction, this),
00133   itsCellSize(&OPT_GameOfLifeCellSize, this),
00134   itsDims(320,240), // if you change this default value, also update
00135                     // the documentation of OPT_InputFrameSource in
00136                     // Media/MediaOpts.C
00137   itsGenerator(0),
00138   itsBoard(),
00139   itsStarted(false)
00140 {
00141   itsGenerator.seed(time(NULL));
00142 }
00143 
00144 // ######################################################################
00145 GameOfLifeInput::~GameOfLifeInput()
00146 {}
00147 
00148 // ######################################################################
00149 void GameOfLifeInput::setConfigInfo(const std::string& dimsstring)
00150 {
00151   // NOTE: if you modify any behavior here, then please update the
00152   // corresponding documentation for the global "--in" option inside
00153   // the OPT_InputFrameSource definition in Media/MediaOpts.C
00154 
00155   if (dimsstring.size() == 0)
00156     return;
00157 
00158   Dims d; convertFromString(dimsstring, d);
00159   this->setDims(d);
00160 }
00161 
00162 // ######################################################################
00163 GenericFrameSpec GameOfLifeInput::peekFrameSpec()
00164 {
00165   GenericFrameSpec result;
00166 
00167   result.nativeType = GenericFrame::RGB_U8;
00168   result.videoFormat = VIDFMT_AUTO;
00169   result.videoByteSwap = false;
00170   result.dims = itsDims;
00171   result.floatFlags = 0;
00172 
00173   return result;
00174 }
00175 
00176 // ######################################################################
00177 GenericFrame GameOfLifeInput::readFrame()
00178 {
00179   if (!itsStarted)
00180     {
00181 
00182 #if 0
00183 
00184 #define i 0
00185 #define Q 255
00186       const byte gosper_glider_gun[] =
00187         {
00188           //    0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5
00189           /*0*/ i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,Q,i,i,i,i,i,i,i,i,i,i,i,
00190           /*1*/ i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,Q,i,Q,i,i,i,i,i,i,i,i,i,i,i,
00191           /*2*/ i,i,i,i,i,i,i,i,i,i,i,i,Q,Q,i,i,i,i,i,i,Q,Q,i,i,i,i,i,i,i,i,i,i,i,i,Q,Q,
00192           /*3*/ i,i,i,i,i,i,i,i,i,i,i,Q,i,i,i,Q,i,i,i,i,Q,Q,i,i,i,i,i,i,i,i,i,i,i,i,Q,Q,
00193           /*4*/ Q,Q,i,i,i,i,i,i,i,i,Q,i,i,i,i,i,Q,i,i,i,Q,Q,i,i,i,i,i,i,i,i,i,i,i,i,i,i,
00194           /*5*/ Q,Q,i,i,i,i,i,i,i,i,Q,i,i,i,Q,i,Q,Q,i,i,i,i,Q,i,Q,i,i,i,i,i,i,i,i,i,i,i,
00195           /*6*/ i,i,i,i,i,i,i,i,i,i,Q,i,i,i,i,i,Q,i,i,i,i,i,i,i,Q,i,i,i,i,i,i,i,i,i,i,i,
00196           /*7*/ i,i,i,i,i,i,i,i,i,i,i,Q,i,i,i,Q,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,
00197           /*8*/ i,i,i,i,i,i,i,i,i,i,i,i,Q,Q,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i,i
00198         };
00199 
00200       const byte block_engine_1[] =
00201         {
00202           //    0,1,2,3,4,5,6,7,
00203           /*0*/ i,i,i,i,i,Q,i,Q,
00204           /*1*/ i,i,i,i,i,Q,i,i,
00205           /*2*/ i,i,i,Q,i,i,i,i,
00206           /*3*/ i,Q,i,Q,i,i,i,i,
00207           /*4*/ Q,Q,i,Q,i,i,i,i,
00208           /*5*/ i,Q,i,i,i,i,i,i,
00209         };
00210 
00211       const byte block_engine_2[] =
00212         {
00213           //    0,1,2,3,4,
00214           /*0*/ Q,i,Q,i,Q,
00215           /*1*/ Q,i,Q,Q,i,
00216           /*2*/ Q,Q,i,i,i,
00217           /*3*/ i,i,i,i,Q,
00218           /*4*/ Q,i,Q,Q,Q,
00219         };
00220 
00221       const byte block_engine_3[] =
00222         {
00223           //    0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8
00224           /*0*/ Q,Q,Q,Q,Q,Q,Q,Q,i,Q,Q,Q,Q,Q,i,i,i,Q,Q,Q,i,i,i,i,i,i,Q,Q,Q,Q,Q,Q,Q,i,Q,Q,Q,Q,Q
00225         };
00226 
00227 #undef i
00228 #undef Q
00229 
00230 #endif
00231 
00232       itsBoardHist.resize(0);
00233       itsBoard = Image<byte>(itsDims.w() / itsCellSize.getVal(),
00234                              itsDims.h() / itsCellSize.getVal(),
00235                              ZEROS);
00236 
00237 #if 0
00238       if (0)
00239         const Image<byte> pattern(&gosper_glider_gun[0], 36, 9);
00240       if (0)
00241         const Image<byte> pattern(&block_engine_1[0], 8, 6);
00242       if (0)
00243         const Image<byte> pattern(&block_engine_2[0], 5, 5);
00244       if (0)
00245         const Image<byte> pattern(&block_engine_3[0], 39, 1);
00246 
00247       inplacePaste(itsBoard, pattern, Point2D<int>(60,60));
00248 #endif
00249 
00250       const double t = itsFillFraction.getVal();
00251 
00252       for (Image<byte>::iterator
00253              p = itsBoard.beginw(), stop = itsBoard.endw();
00254            p != stop; ++p)
00255         *p =
00256           (itsGenerator.fdraw() < t)
00257           ? 255
00258           : 0;
00259 
00260       itsStarted = true;
00261     }
00262   else
00263     {
00264       int nlive = 0;
00265       itsBoard = gameOfLifeUpdate(itsBoard, &nlive);
00266       if (nlive == 0)
00267         // oops, everybody died, so let's restart on the next frame:
00268         itsStarted = false;
00269     }
00270 
00271   for (size_t i = 0; i  < itsBoardHist.size(); ++i)
00272     if (itsBoard == itsBoardHist[i])
00273       {
00274         // we've started cycling, so let's break the cycle and start
00275         // fresh on the next frame:
00276         LINFO("cycle detected with period %"ZU,
00277               itsBoardHist.size() - i);
00278         itsStarted = false;
00279         break;
00280       }
00281 
00282   itsBoardHist.push_back(itsBoard);
00283 
00284   while (itsBoardHist.size() >= 8)
00285     itsBoardHist.pop_front();
00286 
00287   const Image<byte> result =
00288     rescale(itsBoard, itsDims, RESCALE_SIMPLE_NOINTERP);
00289 
00290   return GenericFrame(result);
00291 }
00292 
00293 // ######################################################################
00294 void GameOfLifeInput::setDims(const Dims& s)
00295 {
00296   itsDims = s;
00297 }
00298 
00299 // ######################################################################
00300 /* So things look consistent in everyone's emacs... */
00301 /* Local Variables: */
00302 /* mode: c++ */
00303 /* indent-tabs-mode: nil */
00304 /* End: */
00305 
00306 #endif // TRANSPORT_GAMEOFLIFEINPUT_C_DEFINED
Generated on Sun May 8 08:06:57 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3