psycho-reading-eval.C

00001 /*!@file AppPsycho/psycho-reading.C Psychophysics display of
00002    paragraphs, individtual sentences, and transitions between
00003    sentences with questions. */
00004 
00005 // //////////////////////////////////////////////////////////////////// //
00006 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00007 // University of Southern California (USC) and the iLab at USC.         //
00008 // See http://iLab.usc.edu for information about this project.          //
00009 // //////////////////////////////////////////////////////////////////// //
00010 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00011 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00012 // in Visual Environments, and Applications'' by Christof Koch and      //
00013 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00014 // pending; application number 09/912,225 filed July 23, 2001; see      //
00015 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00016 // //////////////////////////////////////////////////////////////////// //
00017 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00018 //                                                                      //
00019 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00020 // redistribute it and/or modify it under the terms of the GNU General  //
00021 // Public License as published by the Free Software Foundation; either  //
00022 // version 2 of the License, or (at your option) any later version.     //
00023 //                                                                      //
00024 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00025 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00026 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00027 // PURPOSE.  See the GNU General Public License for more details.       //
00028 //                                                                      //
00029 // You should have received a copy of the GNU General Public License    //
00030 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00031 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00032 // Boston, MA 02111-1307 USA.                                           //
00033 // //////////////////////////////////////////////////////////////////// //
00034 //
00035 // Primary maintainer for this file: David J. Berg <dberg@usc.edu>
00036 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/AppPsycho/psycho-reading-eval.C $
00037 
00038 #include "Component/ModelManager.H"
00039 #include "Image/Image.H"
00040 #include "Image/ShapeOps.H"
00041 #include "Image/DrawOps.H"
00042 #include "Image/Transforms.H"
00043 #include "Image/SimpleFont.H"
00044 #include "Raster/Raster.H"
00045 #include "Psycho/PsychoDisplay.H"
00046 #include "Psycho/EyeTrackerConfigurator.H"
00047 #include "Psycho/EyeTracker.H"
00048 #include "Psycho/PsychoOpts.H"
00049 #include "Component/EventLog.H"
00050 #include "Component/ComponentOpts.H"
00051 #include "Util/StringUtil.H"
00052 #include "Util/sformat.H"
00053 
00054 #include <iostream>
00055 #include <fstream>
00056 
00057 #define TEXTSCREEN 1920
00058 #define TEXTYPOS 25
00059 // ######################################################################
00060 // Load our image files
00061 // ######################################################################
00062 std::vector<Image<PixRGB<byte> > > readParagraphs(const std::string& filename, 
00063                                                   std::vector<std::string>& names)
00064 {
00065   names.clear();
00066   
00067   std::vector<std::string> parts;
00068   split(filename, ".", back_inserter(parts));
00069   const std::string base = parts[0];
00070   const std::string ext  = parts[1];
00071   
00072   std::vector<Image<PixRGB<byte> > > vec;
00073   int c = 0;
00074   bool add = false;
00075   std::string fn = filename;
00076   while (Raster::fileExists(fn))
00077     {
00078       //good file, so add it
00079       LINFO("adding file : %s:", fn.c_str());
00080       vec.push_back(Raster::ReadRGB(fn));
00081       names.push_back(fn);
00082       
00083       //next filename
00084       const int cp = (add) ? 1 : 0;
00085       fn = base + "_" + toStr<int>(c) + toStr<int>(c + cp) + "." + ext;
00086       if (add)
00087         ++c;
00088       add = !add;
00089     }
00090   return vec;
00091 }
00092 
00093 // ######################################################################
00094 // count the number of summaries for a document
00095 // ######################################################################
00096 const uint countSummaries(const std::string& base)
00097 {
00098   int ii = 1;
00099   std::string fn = base + "_" + toStr<int>(ii) + ".png";
00100 
00101   while (Raster::fileExists(fn))
00102     fn = base + "_" + toStr<int>(++ii) + ".png";
00103   
00104   return ii - 1;
00105 }
00106 
00107 
00108 // ######################################################################
00109 extern "C" int main(const int argc, char** argv)
00110 {
00111   MYLOGVERB = LOG_INFO;  // suppress debug messages
00112 
00113   // Instantiate a ModelManager:
00114   ModelManager manager("Psycho Reading");
00115 
00116   // Instantiate our various ModelComponents:
00117   nub::soft_ref<PsychoDisplay> d(new PsychoDisplay(manager));
00118   manager.addSubComponent(d);
00119 
00120   nub::soft_ref<EyeTrackerConfigurator>
00121     etc(new EyeTrackerConfigurator(manager));
00122   manager.addSubComponent(etc);
00123 
00124   nub::soft_ref<EventLog> el(new EventLog(manager));
00125   manager.addSubComponent(el);
00126 
00127   manager.setOptionValString(&OPT_EventLogFileName, "psychodata.psy");
00128   manager.setOptionValString(&OPT_EyeTrackerType, "EL");
00129 
00130   // Parse command-line:
00131   if (manager.parseCommandLine(argc, argv,
00132                                "<questions file> <doc base1> <doc base2> ", 
00133                                2, -1)==false)
00134     return(1);
00135 
00136   // hook our various babies up and do post-command-line configs:
00137   nub::soft_ref<EyeTracker> et = etc->getET();
00138   d->setEyeTracker(et);
00139   d->setEventLog(el);
00140   et->setEventLog(el);
00141   
00142   // let's get all our ModelComponent instances started:
00143   manager.start();
00144 
00145   // setup array of document indices:
00146   uint nbimgs = manager.numExtraArgs()-1; int index[nbimgs];
00147   for (uint ii = 0; ii < nbimgs; ++ii) index[ii] = ii+1;
00148   randShuffle(index, nbimgs);
00149 
00150   SimpleFont fnt = SimpleFont::FIXED(20);
00151 
00152   /*read in the questions */
00153   std::vector<std::string > questions;
00154   std::ifstream file;
00155   file.open(manager.getExtraArg(0).c_str());
00156   if (file.is_open()) 
00157     {
00158       while (!file.eof()) 
00159         {
00160           std::string temp;
00161           getline(file, temp);
00162           LINFO("%s", temp.c_str());
00163           questions.push_back(temp);
00164         } 
00165       questions.pop_back();
00166       file.close();
00167     }
00168   else LFATAL("Cannot open questions file. ");
00169   
00170 try
00171   {
00172     // main loop:
00173     for (uint i = 0; i < nbimgs; ++i)
00174       {
00175         // let's do an eye tracker calibration:
00176         LINFO("Have the subject read summary: %s", manager.getExtraArg(index[i]).c_str());
00177         d->displayText("Please read a summary <press enter when finished>, then we'll do a quick calibration.");
00178         d->waitForKey();
00179 
00180         LINFO("Performing calibration");
00181         et->calibrate(d);
00182         
00183         //clear the screen of any junk
00184         d->clearScreen();
00185         
00186         //randomize summaries for this document
00187         uint nbsums = countSummaries(manager.getExtraArg(index[i]));
00188         LINFO("%d Summaries found for Document '%s'", nbsums, 
00189               manager.getExtraArg(index[i]).c_str());
00190         int sindex[nbsums];
00191         for (uint ii = 0; ii < nbsums; ++ii) sindex[ii] = ii + 1;
00192         randShuffle(sindex, nbsums);
00193         
00194         for (uint j = 0; j < nbsums; ++j)
00195           {
00196             //write a loading message to the screen
00197             d->clearScreen();
00198             d->displayText("Loading - please wait.....");
00199             
00200             const std::string file = manager.getExtraArg(index[i]) + "_" + 
00201               toStr<int>(sindex[j]) + ".png";
00202             LINFO("Loading summary set '%s'...", file.c_str());
00203             std::vector<std::string> fnames;
00204             std::vector<Image<PixRGB<byte> > > imageset = 
00205               readParagraphs(file, fnames);
00206             
00207             //setup our anchors for displaying text
00208             //int w = imageset[0].getWidth();//width and height of SDL surface
00209             const int w = TEXTSCREEN;
00210             std::vector<Point2D<int> > anchors;
00211             std::vector<std::string >::const_iterator 
00212               iter(questions.begin()), end(questions.end());
00213             while (iter != end)
00214               {  
00215                 int hposq = w/2 - 
00216                   int(double(fnt.w() * (uint)iter->size()) / 2.0);
00217                 anchors.push_back(Point2D<int>(hposq, TEXTYPOS));
00218                 ++iter;
00219               }
00220             
00221             d->clearScreen();
00222             
00223             //loop over the images
00224             for (uint k = 0; k < imageset.size(); ++k)
00225               {
00226                 //display the first image
00227                 Image<PixRGB<byte> > cimg = imageset[k];
00228                 
00229                 //if our first image display with fixation blink etc              
00230                 if (k == 0)
00231                   {
00232                     //create surface
00233                     SDL_Surface *surf = d->makeBlittableSurface(cimg, true);
00234                     
00235                     LINFO("ready '%s'...", fnames[k].c_str());
00236                     
00237                     //do a quick drift correct
00238                     et->recalibrate(d,0);
00239                     
00240                     //fixation 
00241                     //d->displaFixation();
00242                     
00243                     // ready to go whenever the user is ready:
00244                     //d->waitForKey();
00245                     d->waitNextRequestedVsync(false, true);
00246                     d->pushEvent(sformat("===== Showing text: %s =====", 
00247                                          fnames[k].c_str()));
00248                     
00249                     // start the eye tracker:
00250                     et->track(true);
00251                     
00252                     // blink the fixation:
00253                     d->displayFixationBlink();
00254                     
00255                     // show the image:
00256                     d->displaySurface(surf, -2);
00257                     
00258                     // wait for key:
00259                     d->waitForKey();
00260                     
00261                     // free the image:
00262                     SDL_FreeSurface(surf);
00263                     
00264                     // stop the eye tracker:
00265                     usleep(50000);
00266                     et->track(false);
00267                     LINFO("recorded eye tracker session");
00268                   }
00269                 
00270                 //ask the user a questions and record a new eye tracker session:
00271                 std::vector<Image<PixRGB<byte> > > cimgq(questions.size(), cimg);
00272                 for (uint m = 0; m < questions.size(); ++m)
00273                   {
00274                     //create images with questions 
00275                     const float factor = (float)d->getHeight() / (float)d->getWidth();
00276                     const int tempv = TEXTSCREEN * factor;
00277                     Image<PixRGB<byte> > temp(TEXTSCREEN, tempv, ZEROS);
00278                     
00279                     writeText(temp, anchors[m], questions[m].c_str(), 
00280                               PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),fnt);
00281                     
00282                     //combine question text with our current image
00283                     temp = rescaleBilinear(temp, cimgq[m].getDims());
00284                     cimgq[m] = composite(temp, cimgq[m], PixRGB<byte>(0,0,0));
00285                     
00286                     //create surface
00287                     SDL_Surface *surf = d->makeBlittableSurface(cimgq[m], true);
00288                     
00289                     LINFO("ready Q%d '%s'...", m, fnames[k].c_str());
00290                     
00291                     d->waitNextRequestedVsync(false, true);
00292                     d->pushEvent(sformat("===== Showing Q%d \"%s\": %s =====", 
00293                                          m, questions[k].c_str(), fnames[k].c_str()));
00294                     
00295                     // show the image:
00296                     d->displaySurface(surf, -2);
00297                     d->waitForKey();
00298                     SDL_FreeSurface(surf);
00299                   }
00300               }
00301           }
00302       }
00303     
00304     d->clearScreen();
00305     d->displayText("Experiment complete. Thank you! Press any key.");
00306     d->waitForKey();
00307     
00308   }
00309  catch (...)
00310    {
00311      REPORT_CURRENT_EXCEPTION;
00312    };
00313  
00314 // stop all our ModelComponents
00315  manager.stop();
00316 
00317   // all done!
00318   return 0;
00319 }
00320 
00321 // ######################################################################
00322 /* So things look consistent in everyone's emacs... */
00323 /* Local Variables: */
00324 /* indent-tabs-mode: nil */
00325 /* End: */
Generated on Sun May 8 08:04:12 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3