searcharray2d.C

Go to the documentation of this file.
00001 /*!@file AppPsycho/searcharray2d.C create a randomized search array from
00002   image patches of a single target and the rest for distractors*/
00003 
00004 // ////////////////////////////////////////////////////////////////////
00005 // // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C)
00006 // 2000-2002 // by the University of Southern California (USC)
00007 // and the iLab at USC.  // See http://iLab.usc.edu for
00008 // information about this project.  //
00009 // ////////////////////////////////////////////////////////////////////
00010 // // Major portions of the iLab Neuromorphic Vision Toolkit
00011 // are protected // under the U.S. patent ``Computation of
00012 // Intrinsic Perceptual Saliency // in Visual Environments,
00013 // and Applications'' by Christof Koch and // Laurent Itti,
00014 // California Institute of Technology, 2001 (patent //
00015 // pending; application number 09/912,225 filed July 23, 2001;
00016 // see // http://pair.uspto.gov/cgi-bin/final/home.pl for
00017 // current status).  //
00018 // ////////////////////////////////////////////////////////////////////
00019 // // This file is part of the iLab Neuromorphic Vision C++
00020 // Toolkit.  // // The iLab Neuromorphic Vision C++ Toolkit is
00021 // free software; you can // redistribute it and/or modify it
00022 // under the terms of the GNU General // Public License as
00023 // published by the Free Software Foundation; either //
00024 // version 2 of the License, or (at your option) any later
00025 // version.  // // The iLab Neuromorphic Vision C++ Toolkit is
00026 // distributed in the hope // that it will be useful, but
00027 // WITHOUT ANY WARRANTY; without even the // implied warranty
00028 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE.
00029 // See the GNU General Public License for more details.  // //
00030 // You should have received a copy of the GNU General Public
00031 // License // along with the iLab Neuromorphic Vision C++
00032 // Toolkit; if not, write // to the Free Software Foundation,
00033 // Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307
00034 // USA.  //
00035 // ////////////////////////////////////////////////////////////////////
00036 // //
00037 //
00038 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00039 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/AppPsycho/searcharray2d.C $
00040 // $Id: searcharray2d.C 14376 2011-01-11 02:44:34Z pez $
00041 //
00042 
00043 #include "Image/Image.H"
00044 #include "Image/Pixels.H"
00045 #include "Component/ModelManager.H"
00046 #include "Raster/Raster.H"
00047 #include "Util/Assert.H"
00048 #include "Util/MathFunctions.H"
00049 #include "Util/StringConversions.H"
00050 #include "Util/log.H"
00051 
00052 #include <cstdio>
00053 #include <math.h>
00054 #include <unistd.h>
00055 #include <vector>
00056 
00057 void image_patch(const Image< PixRGB<byte> >& patch, const int ti,
00058                  const int tj, Image< PixRGB<byte> >& image,
00059                  const double alpha, const float FACTORx,
00060                  const float FACTORy,
00061                  Image<byte>& targets,
00062                  bool do_target, Image< PixRGB<byte> >& randomGrid,
00063                  const Image< PixRGB<byte> >& randomNum);
00064 
00065 
00066 /*! This program generates a randomized search array (and associated
00067   target mask) from several image patches (1 for target and the rest
00068   for distractors). */
00069 
00070 int main(const int argc, const char **argv)
00071 {
00072   MYLOGVERB = LOG_INFO;  // suppress debug messages
00073 
00074   // Instantiate a ModelManager:
00075   ModelManager manager("search array");
00076 
00077   // Parse command-line:
00078   if (manager.parseCommandLine(argc, argv,
00079                                "<target.ppm> <w> <alpha> <noise>"
00080                                "<numRows> <numCols> <output>"
00081                                "<reco> <noCheat> <checkResponse> <pathNumbers>"
00082                                "<distractor_1.ppm> ... <distractor_n.ppm>",
00083                                1, -1)==false)
00084     return(1);
00085 
00086   // let's get all our ModelComponent instances started:
00087   manager.start();
00088 
00089   // ------------------ READ INPUT --------------------------
00090   // get the arguments
00091   Image<PixRGB<byte> > target =
00092     Raster::ReadRGB(manager.getExtraArg (0));
00093   int w = manager.getExtraArgAs<int>(1);
00094   float alpha = manager.getExtraArgAs<float>(2);
00095   float noise = manager.getExtraArgAs<float>(3);
00096   int rows = manager.getExtraArgAs<int>(4);
00097   int cols = manager.getExtraArgAs<int>(5);
00098   const char* output = manager.getExtraArg (6).c_str();
00099   const char* reco = manager.getExtraArg (7).c_str();
00100   const char* noCheat = manager.getExtraArg (8).c_str();
00101   const char* checkResponse = manager.getExtraArg (9).c_str();
00102   std::string pathNumbers = manager.getExtraArg (10);
00103   uint numD = manager.numExtraArgs() - 11;
00104   Image<PixRGB<byte> >* distractor[numD];
00105   for (uint i = 0; i < numD; i++)
00106     {
00107       // read the distractor patches
00108       distractor[i] = new Image<PixRGB<byte> >
00109         (Raster::ReadRGB(manager.getExtraArg (11 + i)));
00110     }
00111   int pw = target.getWidth(), ph = target.getHeight();
00112 
00113   // ------------------ INITIALIZE PARAMS -------------------------
00114   for (uint i = 0; i < numD; i++)
00115     {
00116       //all targets equal size
00117       ASSERT(pw == distractor[i]->getWidth() &&
00118              ph == distractor[i]->getHeight());
00119     }
00120 
00121   initRandomNumbers();
00122 
00123   // initialize results:
00124   Image<PixRGB<byte> > image(w, w, ZEROS);
00125   Image<PixRGB<byte> > randomGrid(w, w, ZEROS);
00126   Image<byte> targets(w, w, ZEROS);
00127 
00128   float FACTORx = w / (cols * pw);
00129   float FACTORy = w / (rows * ph);
00130   int numBox = cols * rows;
00131   int numPerD = int((numBox - 1) / numD);
00132   LINFO (" image grid: %d x %d, number per distractor type = %d",
00133          cols, rows, numPerD);
00134 
00135   // read the 2 digit randomNumber patches: to avoid any head
00136   // movements while entering the digits, we restrict each digit to
00137   // 1..5, hence a max of 25 numbers
00138   /*int numR, numRows, numCols;
00139   if (numBox > 25)
00140     {
00141       numRows = 5;
00142       numCols = 5;
00143       numR = 25;
00144     }
00145   else
00146     {
00147       numRows = rows;
00148       numCols = cols;
00149       numR = numBox;
00150     }*/
00151   Image<PixRGB<byte> >* numbers[25];
00152   std::vector <std::string> names;
00153 
00154   // let's display some numbers to be displayed at each locn
00155   for (int i = 0; i < 5; i ++)
00156     for (int j = 0; j < 5; j++)
00157       {
00158         int k = i * 5 + j;
00159         names.push_back (pathNumbers + "/" + toStr (i+1) + toStr (j+1) +
00160                          ".ppm");
00161         numbers[k] = new Image<PixRGB<byte> >
00162           (Raster::ReadRGB(names[k]));
00163         //all targets equal size
00164         ASSERT(pw == numbers[k]->getWidth() &&
00165                ph == numbers[k]->getHeight());
00166       }
00167 
00168 
00169   // --------------- MAKE THE SEARCH ARRAY AND RANDOM GRID --------------
00170   // keep a list of all locns in the grid where items can appear
00171   int locn[numBox][2];
00172   int box[numBox]; // dummy for randomizing
00173 
00174   FILE* f = fopen (reco, "w");
00175   FILE* check = fopen (checkResponse, "w");
00176   for (int j = 0; j < cols; j++)
00177     for (int i = 0; i < rows; i++)
00178       {
00179         int k = i * cols + j;
00180         box[k] = k; // intialize with index
00181         // the above box is at locn. <i+1, j+1> in the grid
00182         locn[k][0] = i + 1;
00183         locn[k][1] = j + 1;
00184       }
00185    // list of indices that will be randomized for flashing numbers
00186   int random[25];
00187   for (int i = 0; i < 5; i ++)
00188     for (int j = 0; j < 5; j++){
00189       int k = i * 5 + j;
00190       random[k] = k; // intialize now: randomize later
00191     }
00192 
00193   // shuffle the grid to randomize the locn of the target and
00194   // distractors
00195   randShuffle (box, numBox);
00196 
00197   // also randomize the display of numbers in the grid
00198   randShuffle (random, 25);
00199 
00200   // allocate the target to the randomized box
00201   int idx = 0; // index for the box and random array
00202   int r = locn[box[idx]][0];
00203   int c = locn[box[idx]][1];
00204   // fprintf (f, "%d %d %s\n", r, c, manager.getExtraArg (0).c_str());
00205   LINFO("-- TARGET AT (%d, %d)", r, c);
00206   image_patch (target, c-1, r-1, image, alpha, FACTORx, FACTORy, targets, 1,
00207                randomGrid, *numbers[random[idx]]);
00208 
00209   // record the random number at the target locn to compare response
00210   int start = names[random[idx]].rfind ("/");
00211   int end = names[random[idx]].rfind (".ppm");
00212   fprintf (check, "%s", names[random[idx]].
00213            substr (start+1, end-start-1).c_str());
00214   fclose (check);
00215   // record the  random number displayed at this locn in the reco file
00216   fprintf (f, "%d %d %s %s\n", r, c,
00217                  manager.getExtraArg(0).c_str(),
00218                  names[random[idx]].substr (start+1, end-start-1).c_str());
00219   idx++;
00220 
00221   // allocate the items to the randomized boxes
00222   for (uint disType = 0; disType < numD; disType ++)
00223     for (int count = 0; count < numPerD; count ++)
00224       {
00225         r = locn[box[idx]][0];
00226         c = locn[box[idx]][1];
00227         // record the random number displayed at this locn
00228         int start = names[random[idx]].rfind ("/");
00229         int end = names[random[idx]].rfind (".ppm");
00230         fprintf (f, "%d %d %s %s\n", r, c,
00231                  manager.getExtraArg(11 + disType).c_str(),
00232                  names[random[idx]].substr (start+1, end-start-1).c_str());
00233         LINFO("-- distractor %d AT (%d, %d)", disType + 1, r, c);
00234         image_patch (*distractor[disType], c-1, r-1, image, alpha,
00235                      FACTORx, FACTORy,
00236                      targets, 0, randomGrid, *numbers[random[idx]]);
00237         idx++;
00238       }
00239 
00240   // ------------------- ADD NOISE -----------------------------------
00241   /* add noise */
00242   Image< PixRGB<byte> >::iterator iptr = image.beginw(),
00243     stop = image.endw();
00244   while(iptr != stop)
00245     {
00246       if (randomDouble() <= noise)
00247         {
00248           if (randomDouble() >= 0.5) iptr->setRed(255);
00249           else iptr->setRed(0);
00250           if (randomDouble() >= 0.5) iptr->setGreen(255);
00251           else iptr->setGreen(0);
00252           if (randomDouble() >= 0.5) iptr->setBlue(255);
00253           else iptr->setBlue(0);
00254         }
00255       iptr ++;
00256     }
00257 
00258   // ----------------------- WRITE OUTPUT -------------------------------
00259   fclose (f);
00260   Raster::WriteRGB(image,  output, RASFMT_PNM);
00261   Raster::WriteRGB(randomGrid,  noCheat, RASFMT_PNM);
00262   Raster::WriteGray(targets,  output, RASFMT_PNM);
00263 
00264   // erase the memory used
00265   for (uint i = 0; i < numD; i++)
00266     {
00267       delete (distractor[i]);
00268     }
00269   for (int i = 0; i < 25; i++)
00270     {
00271       delete (numbers[i]);
00272     }
00273   manager.stop();
00274   return 0;
00275 }
00276 
00277 // ######################################################################
00278 void image_patch(const Image< PixRGB<byte> >& patch, const int ti,
00279                  const int tj, Image< PixRGB<byte> >& image,
00280                  const double alpha,  const float FACTORx,
00281                  const float FACTORy, Image<byte>& targets,
00282                  bool do_target, Image< PixRGB<byte> >& randomGrid,
00283                  const Image< PixRGB<byte> >& randomNum)
00284 {
00285   int pw = patch.getWidth(), ph = patch.getHeight();
00286   int w = image.getWidth();
00287 
00288   //int jitx = int(randomDouble() * (FACTOR - 1.0) * pw);
00289   //int jity = int(randomDouble() * (FACTOR - 1.0) * ph);
00290   int jitx = int(randomDouble() * (FACTORx - 2.0) * pw);
00291   int jity = int(randomDouble() * (FACTORy - 2.0) * ph);
00292 
00293   float jita = float(alpha * 3.14159 / 180.0 * (randomDouble() - 0.5) * 2.0);
00294   int offset = int(w - floor(w / (pw * FACTORx)) * (pw * FACTORx)) / 2;
00295 
00296   PixRGB<byte> zero(0, 0, 0);
00297   int px = 0, py = 0;
00298 
00299   for (double y = int(tj *ph * FACTORy); y < int(tj * ph * FACTORy + ph); y ++)
00300     {
00301       for (double x = int(ti * pw * FACTORx); x < int(ti * pw * FACTORx + pw);
00302            x ++)
00303         {
00304           int x2 = int(x + jitx + offset);
00305           int y2 = int(y + jity + offset);
00306 
00307           /* Shifting back and forth the center of rotation.*/
00308           double px2 = px - pw / 2.0F;
00309           double py2 = py - ph / 2.0F;
00310 
00311           float px3 = float(cos(jita) * px2 + sin(jita) * py2 + pw / 2.0F);
00312           float py3 = float(-sin(jita) * px2 + cos(jita) * py2 + pw / 2.0F);
00313 
00314           if (px3 < 0 || px3 >= pw || py3 < 0 || py3 >= ph )
00315             {
00316               image.setVal(x2, y2, zero);
00317               randomGrid.setVal(x2, y2, zero);
00318             }
00319           else
00320             {
00321               image.setVal(x2, y2, patch.getValInterp(px3, py3));
00322               randomGrid.setVal(x2, y2, randomNum.getVal((int)px3, (int)py3));
00323               if (do_target)
00324                 {
00325                   if (patch.getVal(int(px3), int(py3)) == zero)
00326                     targets.setVal(x2, y2, 0);
00327                   else
00328                     targets.setVal(x2, y2, 255);
00329                 }
00330             }
00331           px ++;
00332         }
00333       py ++;
00334       px = 0;
00335     }
00336 }
00337 
00338 // ######################################################################
00339 /* So things look consistent in everyone's emacs... */
00340 /* Local Variables: */
00341 /* indent-tabs-mode: nil */
00342 /* End: */
Generated on Sun May 8 08:40:11 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3