psycho-dsearch.C

Go to the documentation of this file.
00001 /*!@file AppPsycho/psycho-dsearch.C Psychophysics display for a search for two
00002   targets that are presented to the observer prior to the search */
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-dsearch.C $
00036 // $Id: psycho-dsearch.C 9412 2008-03-10 23:10:15Z farhan $
00037 //
00038 
00039 #include "Component/ModelManager.H"
00040 #include "Image/ColorOps.H" // for makeRGB()
00041 #include "Image/CutPaste.H" // for inplacePaste()
00042 #include "Image/Image.H"
00043 #include "Image/MathOps.H"  // for inplaceSpeckleNoise()
00044 #include "Psycho/PsychoDisplay.H"
00045 #include "Psycho/EyeTrackerConfigurator.H"
00046 #include "Psycho/EyeTracker.H"
00047 #include "Psycho/PsychoOpts.H"
00048 #include "GUI/GUIOpts.H"
00049 #include "Component/EventLog.H"
00050 #include "Component/ComponentOpts.H"
00051 #include "GUI/SDLdisplay.H"
00052 #include "Raster/Raster.H"
00053 #include "Util/MathFunctions.H"
00054 #include "Util/Types.H"
00055 
00056 #include <ctype.h>
00057 #include <vector>
00058 
00059 //! number of frames in the mask
00060 #define NMASK 10
00061 
00062 // ######################################################################
00063 extern "C" int main(const int argc, char** argv)
00064 {
00065   MYLOGVERB = LOG_INFO;  // suppress debug messages
00066 
00067   // Instantiate a ModelManager:
00068   ModelManager manager("Psycho Double Search");
00069 
00070   // Instantiate our various ModelComponents:
00071   nub::soft_ref<PsychoDisplay> d(new PsychoDisplay(manager));
00072   manager.addSubComponent(d);
00073 
00074   nub::soft_ref<EyeTrackerConfigurator>
00075     etc(new EyeTrackerConfigurator(manager));
00076   manager.addSubComponent(etc);
00077 
00078   nub::soft_ref<EventLog> el(new EventLog(manager));
00079   manager.addSubComponent(el);
00080 
00081   manager.setOptionValString(&OPT_EventLogFileName, "psychodata.psy");
00082   manager.setOptionValString(&OPT_EyeTrackerType, "ISCAN");
00083   manager.setOptionValString(&OPT_SDLdisplayDims, "1280x1024");
00084   d->setModelParamVal("PsychoDisplayBackgroundColor", PixRGB<byte>(0));
00085   d->setModelParamVal("PsychoDisplayTextColor", PixRGB<byte>(255));
00086   d->setModelParamVal("PsychoDisplayBlack", PixRGB<byte>(255));
00087   d->setModelParamVal("PsychoDisplayWhite", PixRGB<byte>(128));
00088   d->setModelParamVal("PsychoDisplayFixSiz", 5);
00089   d->setModelParamVal("PsychoDisplayFixThick", 5);
00090 
00091   // Parse command-line:
00092   if (manager.parseCommandLine(argc, argv, "<imagelist.txt>", 1, 1) == false)
00093     return(1);
00094 
00095   // hook our various babies up and do post-command-line configs:
00096   nub::soft_ref<EyeTracker> et = etc->getET();
00097   d->setEyeTracker(et);
00098   d->setEventLog(el);
00099   et->setEventLog(el);
00100 
00101   // let's get all our ModelComponent instances started:
00102   manager.start();
00103 
00104   // let's prepare the mask images:
00105   SDL_Surface *mask[NMASK]; int mindex[NMASK]; Dims ddims = d->getDims();
00106 
00107   for (int i = 0; i < NMASK; i ++) {
00108     Image<byte> n(ddims, ZEROS);
00109     inplaceSpeckleNoise(n, 1.0F, i+1, 255, true);
00110     mask[i] = d->makeBlittableSurface(makeRGB(n, n, n), false);
00111 
00112     // keep an array of indices that we will later randomize:
00113     mindex[i] = i;
00114   }
00115 
00116   // let's pre-load all the image names so that we can randomize them later:
00117   FILE *f = fopen(manager.getExtraArg(0).c_str(), "r");
00118   if (f == NULL) LFATAL("Cannot read stimulus file");
00119   char line[1024];
00120   std::vector<std::string> ilist, t1list, t2list;
00121   while(fgets(line, 1024, f))
00122     {
00123       // each line has three filenames: first the two imagelets that
00124       // contain only each of the targets, second the image that
00125       // contains the targets in their environment:
00126       char *line2 = line; while(*line2 != '\0' && !isspace(*line2)) line2 ++;
00127       *line2++ = '\0';
00128       char *line3 = line2; while(*line3 != '\0' && !isspace(*line3)) line3 ++;
00129       *line3++ = '\0'; line3[strlen(line3) - 1] = '\0';
00130       // now line is at the first imagelet, line2 at the second, line3
00131       // at the search array image
00132       t1list.push_back(std::string(line));
00133       t2list.push_back(std::string(line2));
00134       ilist.push_back(std::string(line3));
00135     }
00136   fclose(f);
00137 
00138   // randomize stimulus presentation order:
00139   int nimg = ilist.size(); int imindex[nimg];
00140   for (int i = 0; i < nimg; i ++) imindex[i] = i;
00141   randShuffle(imindex, nimg);
00142 
00143   // let's display an ISCAN calibration grid:
00144   d->clearScreen();
00145   d->displayISCANcalib();
00146   d->waitForKey();
00147 
00148   // let's do an eye tracker calibration:
00149   d->displayText("<SPACE> to calibrate; other key to skip");
00150   int c = d->waitForKey();
00151   if (c == ' ') d->displayEyeTrackerCalibration(3, 3);
00152 
00153   // we are ready to start:
00154   d->clearScreen();
00155   d->displayText("<SPACE> to start experiment");
00156   d->waitForKey();
00157   d->waitNextRequestedVsync(false, true);
00158 
00159   // main loop:
00160   for (int im = 0; im < nimg; im ++) {
00161     int imnum = imindex[im];
00162 
00163     // load up the images and show a fixation cross on a blank screen:
00164     d->clearScreen();
00165     LINFO("Loading '%s' / '%s'/ '%s'...",
00166           ilist[imnum].c_str(), t1list[imnum].c_str(), t2list[imnum].c_str());
00167 
00168     // get the imagelets and place them around fixation:
00169     Image< PixRGB<byte> > img1 = Raster::ReadRGB(t1list[imnum]);
00170     Image< PixRGB<byte> > img2 = Raster::ReadRGB(t2list[imnum]);
00171     Image< PixRGB<byte> > img(d->getDims(), NO_INIT);
00172     img.clear(d->getGrey());
00173     inplacePaste(img, img1, Point2D<int>(img.getWidth() / 2 - img1.getWidth() * 2,
00174                             (img.getHeight() - img1.getHeight()) / 2));
00175     inplacePaste(img, img2, Point2D<int>(img.getWidth() / 2 + img2.getWidth(),
00176                             (img.getHeight() - img2.getHeight()) / 2));
00177     SDL_Surface *surf1 = d->makeBlittableSurface(img, false);
00178     char buf[256];
00179     sprintf(buf, "===== Showing imagelets: %s %s =====",
00180             t1list[imnum].c_str(), t1list[imnum].c_str());
00181 
00182     // load up the full-scene image:
00183     img = Raster::ReadRGB(ilist[imnum]);
00184     SDL_Surface *surf2 = d->makeBlittableSurface(img, false);
00185 
00186     // randomize presentation order of mask frames:
00187     randShuffle(mindex, NMASK);
00188 
00189     // give a chance to other processes if single-CPU:
00190     usleep(200000);
00191 
00192     // ready to go whenever the user is ready:
00193     d->displayText("Press <SPACE> when you are ready");
00194     d->waitForKey();
00195     d->pushEvent(buf);
00196 
00197     // show the imagelet2:
00198     d->displaySurface(surf1, 0, true);
00199 
00200     // wait for a bit:
00201     sleep(5);
00202 
00203     // show the masks:
00204     d->pushEvent("===== Showing mask =====");
00205     for (int j = 0; j < NMASK; j ++)
00206       d->displaySurface(mask[mindex[j]], j+1, true);
00207 
00208     // show a fixation at center:
00209     d->clearScreen();
00210     d->displayFixation();
00211     for (int i = 0; i < 40; i ++) d->waitNextRequestedVsync();
00212 
00213     // start the eye tracker:
00214     et->track(true);
00215 
00216     // blink the fixation:
00217     d->displayFixationBlink();
00218 
00219     // show the image:
00220     d->pushEvent(std::string("===== Showing search image: ") + ilist[imnum] +
00221                  std::string(" ====="));
00222     d->displaySurface(surf2, 0, true);
00223 
00224     // wait for key twice; it will record reaction time in the logs:
00225     d->waitForKey();  // first target found
00226     d->waitForKey();  // second target found
00227 
00228     // free the imagelet and image:
00229     SDL_FreeSurface(surf1); SDL_FreeSurface(surf2);
00230 
00231     // stop the eye tracker:
00232     usleep(150000);
00233     et->track(false);
00234 
00235     // let's do a quickie eye tracker calibration once in a while:
00236     if ((im + 1) % 5 == 0) {
00237       d->displayText("press <SPACE> when you are ready for recalibration");
00238       d->waitForKey();
00239       d->displayEyeTrackerCalibration(3, 3);
00240       d->clearScreen();
00241       d->displayText("Press <SPACE> to continue with the movies");
00242       d->waitForKey();
00243     }
00244   }
00245 
00246   d->clearScreen();
00247   d->displayText("Experiment complete. Thank you!");
00248   d->waitForKey();
00249 
00250   // stop all our ModelComponents
00251   manager.stop();
00252 
00253   // free mask images:
00254   for (int i = 0; i < NMASK; i++) SDL_FreeSurface(mask[i]);
00255 
00256   // all done!
00257   return 0;
00258 }
00259 
00260 // ######################################################################
00261 /* So things look consistent in everyone's emacs... */
00262 /* Local Variables: */
00263 /* indent-tabs-mode: nil */
00264 /* End: */
Generated on Sun May 8 08:40:08 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3