psycho-spy3.C

00001 /*!@file AppPsycho/psycho-noCheat.C Psychophysics display of still images and
00002   check response to prevent cheating*/
00003 
00004 // //////////////////////////////////////////////////////////////////// //
00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00006 // University of Southern California (USC) and the iLab at USC.         //
00007 // See http://iLab.usc.edu for information about this project.          //
00008 // //////////////////////////////////////////////////////////////////// //
00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00011 // in Visual Environments, and Applications'' by Christof Koch and      //
00012 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00013 // pending; application number 09/912,225 filed July 23, 2001; see      //
00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00015 // //////////////////////////////////////////////////////////////////// //
00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00017 //                                                                      //
00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00019 // redistribute it and/or modify it under the terms of the GNU General  //
00020 // Public License as published by the Free Software Foundation; either  //
00021 // version 2 of the License, or (at your option) any later version.     //
00022 //                                                                      //
00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00026 // PURPOSE.  See the GNU General Public License for more details.       //
00027 //                                                                      //
00028 // You should have received a copy of the GNU General Public License    //
00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00031 // Boston, MA 02111-1307 USA.                                           //
00032 // //////////////////////////////////////////////////////////////////// //
00033 //
00034 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/AppPsycho/psycho-spy3.C $
00036 // $Id: psycho-spy3.C 10794 2009-02-08 06:21:09Z itti $
00037 //
00038 
00039 #include "Component/ModelManager.H"
00040 #include "Image/Image.H"
00041 #include "Psycho/PsychoDisplay.H"
00042 #include "GUI/GUIOpts.H"
00043 #include "Psycho/EyeTrackerConfigurator.H"
00044 #include "Psycho/EyeTracker.H"
00045 #include "Psycho/PsychoOpts.H"
00046 #include "Component/EventLog.H"
00047 #include "Component/ComponentOpts.H"
00048 #include "Raster/Raster.H"
00049 #include "Util/MathFunctions.H"
00050 #include "Util/Types.H"
00051 #include <fstream>
00052 
00053 // ######################################################################
00054 extern "C" int submain(const int argc, char** argv)
00055 {
00056   MYLOGVERB = LOG_INFO;  // suppress debug messages
00057 
00058   // Instantiate a ModelManager:
00059   ModelManager manager("Psycho no Cheating");
00060 
00061   // Instantiate our various ModelComponents:
00062   nub::soft_ref<PsychoDisplay> d(new PsychoDisplay(manager));
00063   manager.addSubComponent(d);
00064 
00065   nub::soft_ref<EyeTrackerConfigurator>
00066     etc(new EyeTrackerConfigurator(manager));
00067   manager.addSubComponent(etc);
00068 
00069   nub::soft_ref<EventLog> el(new EventLog(manager));
00070   manager.addSubComponent(el);
00071 
00072   // set some display params
00073   manager.setOptionValString(&OPT_SDLdisplayDims, "1920x1080");
00074   d->setModelParamVal("PsychoDisplayBackgroundColor", PixRGB<byte>(0));
00075   d->setModelParamVal("PsychoDisplayTextColor", PixRGB<byte>(255));
00076   d->setModelParamVal("PsychoDisplayBlack", PixRGB<byte>(255));
00077   d->setModelParamVal("PsychoDisplayWhite", PixRGB<byte>(128));
00078   d->setModelParamVal("PsychoDisplayFixSiz", 5);
00079   d->setModelParamVal("PsychoDisplayFixThick", 5);
00080   manager.setOptionValString(&OPT_EventLogFileName, "psychodata.psy");
00081   manager.setOptionValString(&OPT_EyeTrackerType, "ISCAN");
00082 
00083   // Parse command-line:
00084   if (manager.parseCommandLine(argc, argv, "<fileList>", 1, -1)==false)
00085     return(1);
00086 
00087   // hook our various babies up and do post-command-line configs:
00088   nub::soft_ref<EyeTracker> et = etc->getET();
00089   d->setEyeTracker(et);
00090   d->setEventLog(el);
00091   et->setEventLog(el);
00092 
00093   // let's get all our ModelComponent instances started:
00094   manager.start();
00095 
00096   // let's display an ISCAN calibration grid:
00097   d->clearScreen();
00098   d->displayISCANcalib();
00099   d->waitForKey();
00100 
00101   // get true random numbers:
00102   initRandomNumbers();
00103 
00104   // let's do an eye tracker calibration:
00105   d->displayText("<SPACE> to calibrate; other key to skip");
00106   int c = d->waitForKey();
00107   if (c == ' ') d->displayEyeTrackerCalibration(3, 3, 1);
00108 
00109   d->clearScreen();
00110 
00111   // setup array of stimuli:
00112   std::ifstream file(manager.getExtraArg(0).c_str());
00113   if (file == 0) LFATAL("Couldn't open object file: '%s'",
00114                         manager.getExtraArg(0).c_str());
00115 
00116 
00117   std::string line;
00118   getline(file, line);
00119   //parse the line to get the filepath
00120   //format: <abs filepath>
00121   std::string fpath = line.substr(0);
00122 
00123   getline(file, line);
00124   // parse the line to get the total number of images
00125   // format: <num>
00126   int numImgs = atoi(line.substr(0).c_str());
00127   std::string imgArr[numImgs][6];
00128 
00129   for(int a=0; a<numImgs; a++){
00130       getline(file, line);
00131 
00132       // parse the line to get the file names
00133       // format: <image> <target> <bg> <noCheat> <checkResponse> <reco>
00134       std::string::size_type end = line.find_first_of(" ");
00135       std::string::size_type start = 0;
00136       int i = 0; std::string imageName, targetName, bgName, noCheatName, checkName, recoName;
00137       while (end != std::string::npos) {
00138         std::string token = line.substr(start, end-start);
00139         switch(i)
00140           {
00141           case 0:
00142             imageName = token;
00143             break;
00144           case 1:
00145             targetName = token;
00146             break;
00147           case 2:
00148             bgName = token;
00149           case 3:
00150             noCheatName = token;
00151             break;
00152           case 4:
00153             checkName = token;
00154             break;
00155           }
00156         start = end + 1;
00157         end = line.find_first_of(" ", start);
00158         i ++;
00159       }
00160       // last token
00161       recoName = line.substr(start);
00162 
00163       // store file names in imgArr
00164       imgArr[a][0] = imageName;
00165       imgArr[a][1] = targetName;
00166       imgArr[a][2] = bgName;
00167       imgArr[a][3] = noCheatName;
00168       imgArr[a][4] = checkName;
00169       imgArr[a][5] = recoName;
00170     }
00171 
00172   //set up indices for randomizing images
00173   int index[numImgs];
00174   for (int i = 0; i < numImgs; i++) index[i] = i;
00175   LINFO("Randomizing images..."); randShuffle(index, numImgs);
00176 
00177   //begin experiment
00178   // int correct = 0, accuracy = 100, total = 0;
00179   int totalScore = 0;
00180 
00181   Timer timer, rt_timer;
00182 
00183   for(int a=0; a<numImgs; a++){
00184 
00185       std::string imageName, targetName, bgName, noCheatName, checkName, recoName;
00186       imageName = fpath +  imgArr[index[a]][0];
00187       targetName = fpath + imgArr[index[a]][1];
00188       bgName = fpath + imgArr[index[a]][2];
00189       noCheatName = fpath + imgArr[index[a]][3];
00190       checkName = fpath + imgArr[index[a]][4];
00191       recoName = fpath + imgArr[index[a]][5];
00192 
00193       // load up the frame and show a fixation cross on a blank screen:
00194       d->clearScreen();
00195       LINFO("Loading '%s'...", targetName.c_str());
00196       Image< PixRGB<byte> > target = Raster::ReadRGB(targetName);
00197       LINFO("Loading '%s'...", bgName.c_str());
00198       Image< PixRGB<byte> > background = Raster::ReadRGB(bgName);
00199       LINFO("Loading '%s'...", imageName.c_str());
00200       Image< PixRGB<byte> >image = Raster::ReadRGB(imageName);
00201       LINFO("Loading '%s'...", noCheatName.c_str());
00202       Image< PixRGB<byte> > noCheat = Raster::ReadRGB(noCheatName);
00203 
00204       SDL_Surface *surftarget = d->makeBlittableSurface(target, true);
00205       SDL_Surface *surfbackground = d->makeBlittableSurface(background, true);
00206       SDL_Surface *surfimage = d->makeBlittableSurface(image, true);
00207       SDL_Surface *surfnocheat = d->makeBlittableSurface(noCheat, true);
00208 
00209       LINFO("All images ready.");
00210 
00211       // ready to go whenever the user is ready:
00212       d->displayText("hit any key when ready");
00213       d->waitForKey();
00214       d->waitNextRequestedVsync(false, true);
00215 
00216       //fixation and target prime display
00217       // start the eye tracker:
00218       et->track(true);
00219       d->pushEvent(std::string("===== Showing target: ") + targetName +
00220                    " =====");
00221 
00222       // blink the fixation:
00223       d->displayFixationBlink();
00224 
00225       // show target image for 10*99ms:
00226       d->displaySurface(surftarget, -2, true);
00227       for (int j = 0; j < 30; j ++) d->waitNextRequestedVsync();
00228       SDL_FreeSurface(surftarget);
00229 
00230       // show bg image for 10*99ms:
00231       d->displaySurface(surfbackground, -2, true);
00232       for (int j = 0; j < 30; j ++) d->waitNextRequestedVsync();
00233       SDL_FreeSurface(surfbackground);
00234 
00235       // stop the eye tracker:
00236       usleep(50000);
00237       et->track(false);
00238 
00239       // load up the frame and show a fixation cross on a blank screen:
00240       d->clearScreen();
00241 
00242       //fixation and image display
00243       // start the eye tracker:
00244       et->track(true);
00245       d->pushEvent(std::string("===== Showing image: ") +imageName + " =====");
00246 
00247       // blink the fixation for a randomized amount of time:
00248       const int iter = 3 + randomUpToIncluding(5);
00249       d->displayFixationBlink(-1, -1, iter);
00250 
00251       // gobble up any keystrokes:
00252       while(d->checkForKey() != -1) ;
00253 
00254       // show the image until user responds, for up to 5s:
00255       d->displaySurface(surfimage, -2, true);
00256       double startTime = timer.getSecs();
00257       double reactTime = 0.0;
00258       rt_timer.reset();
00259 
00260       // wait for key; it will record reaction time in the logs:
00261       while(d->checkForKey() == -1 &&  (timer.getSecs() < startTime + 5.0))
00262         usleep(1000);
00263       reactTime =  rt_timer.getSecs();
00264       SDL_FreeSurface(surfimage);
00265 
00266       // stop the eye tracker:
00267       usleep(50000);
00268       et->track(false);
00269 
00270       // flash a random grid of numbers and check response to prevent
00271       // cheating
00272       d->pushEvent(std::string("===== Showing noCheat: ") + noCheatName
00273                    + " =====");
00274 
00275       // flash the image for 99ms:
00276       d->displaySurface(surfnocheat, -2, true);
00277       for (int j = 0; j < 3; j ++) d->waitNextRequestedVsync();
00278       SDL_FreeSurface(surfnocheat);
00279 
00280       // wait for response:
00281       d->displayText("Enter the number at the target location");
00282       c = d->waitForKey();
00283       int c2 = d->waitForKey();
00284       std::ifstream check (checkName.c_str());
00285       if (check == 0) LFATAL("Couldn't open check file: '%s'",
00286                              checkName.c_str());
00287       std::string response;
00288       //total ++;
00289       while (getline(check, response))
00290         {
00291           LINFO (" reading from %s", checkName.c_str());
00292           LINFO (" subject entered %d%d", c, c2);
00293           LINFO (" reading %c%c from %s", response[0], response[1],
00294                  checkName.c_str());
00295 
00296           // calculate score for reaction time
00297           int score = 0;
00298           if (reactTime <= 1.0) score = 10;
00299           else if (reactTime <= 2.0) score = 5;
00300           else if (reactTime <= 3.0) score = 4;
00301           else if (reactTime <= 4.0) score = 3;
00302           else if (reactTime <= 5.0) score = 2;
00303           else score = 1;
00304 
00305           // check the response
00306           char tmp[40];
00307           if (((int)response[0] == c) && ((int)response[1] == c2))
00308             {
00309               // correct ++;
00310               //accuracy = (correct * 100) / total;
00311               //sprintf(tmp, "Correct! Accuracy is %d%%", accuracy);
00312 
00313               totalScore += score;
00314               sprintf(tmp, "+%d...Total Score = %d", score, totalScore);
00315               d->displayText(tmp);
00316               d->pushEvent(std::string("===== Correct ====="));
00317             }
00318           else
00319             {
00320               //accuracy = (correct * 100) / total;
00321               // sprintf(tmp, "Wrong! Accuracy is %d%%", accuracy);
00322 
00323               sprintf(tmp, "+0...Total Score = %d", totalScore);
00324               d->displayText(tmp);
00325               d->pushEvent(std::string("===== Wrong ====="));
00326             }
00327 
00328           // maintain display
00329           for (int j = 0; j < 30; j ++) d->waitNextRequestedVsync();
00330         }
00331 
00332     et->recalibrate(d,20);
00333   }
00334 
00335   char tmp[40];
00336   sprintf(tmp, "===== Total Score = %d", totalScore);
00337   d->pushEvent(tmp);
00338 
00339   d->clearScreen();
00340   d->displayText("Experiment complete. Thank you!");
00341   d->waitForKey();
00342 
00343   // stop all our ModelComponents
00344   manager.stop();
00345 
00346   // all done!
00347   return 0;
00348 }
00349 
00350 extern "C" int main(const int argc, char** argv)
00351 {
00352   // simple wrapper around submain() to catch exceptions (because we
00353   // want to allow PsychoDisplay to shut down cleanly; otherwise if we
00354   // abort while SDL is in fullscreen mode, the X server won't return
00355   // to its original resolution)
00356   try
00357     {
00358       return submain(argc, argv);
00359     }
00360   catch (...)
00361     {
00362       REPORT_CURRENT_EXCEPTION;
00363     }
00364 
00365   return 1;
00366 }
00367 
00368 // ######################################################################
00369 /* So things look consistent in everyone's emacs... */
00370 /* Local Variables: */
00371 /* indent-tabs-mode: nil */
00372 /* End: */
Generated on Sun May 8 08:40:10 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3