searcharray2d_lumin.C

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