psycho-compare.C

Go to the documentation of this file.
00001 /*!@file AppPsycho/psycho-compare.C Compare two still images */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00005 // University of Southern California (USC) and the iLab at USC.         //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/AppPsycho/psycho-compare.C $
00035 // $Id: psycho-compare.C 9412 2008-03-10 23:10:15Z farhan $
00036 //
00037 
00038 #include "Component/ModelManager.H"
00039 #include "Component/ComponentOpts.H"
00040 #include "Component/EventLog.H"
00041 #include "Image/Image.H"
00042 #include "Image/CutPaste.H"
00043 #include "Image/DrawOps.H"
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 "Raster/Raster.H"
00050 #include "Util/Types.H"
00051 #include "Util/StringUtil.H"
00052 #include "Util/MathFunctions.H"
00053 #include <fstream>
00054 
00055 //! Compare two images along a number of criteria
00056 /*! This shows two images and asks the user to emit a judgement along
00057   a number of criteria. The two images are randomly presented on the
00058   left/right of fixation. After 5 seconds, criteria questions are
00059   displayed at the bottom of the screen. Input file format is:
00060 
00061   <num criteria>
00062   <textual description of criterion 1>
00063   ...
00064   <textual description of criterion N>
00065   <image filename 1> <image filename 2>
00066   ...
00067   <image filename 1> <image filename 2>
00068 
00069 
00070   EXAMPLE:
00071 
00072   3
00073   Which image is more beautiful?
00074   Which image contains more animals?
00075   Which image is more geeky?
00076   image001.png image002.png
00077   image003.png image004.png
00078   image005.png image006.png
00079 
00080 */
00081 
00082 // ######################################################################
00083 static int submain(const int argc, char** argv)
00084 {
00085   MYLOGVERB = LOG_INFO;  // suppress debug messages
00086 
00087   // Instantiate a ModelManager:
00088   ModelManager manager("Psychophysics Comparison");
00089 
00090   // Instantiate our various ModelComponents:
00091   nub::soft_ref<EventLog> el(new EventLog(manager));
00092   manager.addSubComponent(el);
00093 
00094   nub::soft_ref<PsychoDisplay> d(new PsychoDisplay(manager));
00095   manager.addSubComponent(d);
00096 
00097   nub::soft_ref<EyeTrackerConfigurator>
00098     etc(new EyeTrackerConfigurator(manager));
00099   manager.addSubComponent(etc);
00100 
00101 
00102   // set a default display size:
00103   manager.exportOptions(MC_RECURSE);
00104   manager.setOptionValString(&OPT_SDLdisplayDims, "1920x1080");
00105   manager.setOptionValString(&OPT_EventLogFileName, "psychodata.psy");
00106  manager.setOptionValString(&OPT_EyeTrackerType, "ISCAN");
00107 
00108   // Parse command-line:
00109   if (manager.parseCommandLine(argc, argv, "<fileList>", 1, -1) == false)
00110     return(1);
00111 
00112   nub::soft_ref<EyeTracker> et = etc->getET();
00113   d->setEyeTracker(et);
00114   d->setEventLog(el);
00115   et->setEventLog(el);
00116 
00117   // let's get all our ModelComponent instances started:
00118   manager.start();
00119 
00120   // get the list of images
00121   std::ifstream file(manager.getExtraArg(0).c_str());
00122   if (file == 0) LFATAL("Couldn't open file: '%s'",
00123                         manager.getExtraArg(0).c_str());
00124 
00125   initRandomNumbers();
00126 
00127   std::string line;
00128   if (!getline(file, line)) LFATAL("Bogus file format: missing num criteria");
00129   int numcrit; convertFromString(line, numcrit);
00130   std::vector<std::string> message;
00131 
00132   for (int i = 0; i < numcrit; ++ i)
00133     {
00134       if (!getline(file, line))
00135         LFATAL("Bogus file format: missing text for criterion %d", i+1);
00136       message.push_back(line);
00137     }
00138 
00139   // load up all the image pairs:
00140   std::vector<std::string> lines;
00141   while(getline(file, line)) lines.push_back(line);
00142 
00143   // create a randomized index:
00144   uint *idx = new uint[lines.size()];
00145   for (uint i = 0; i < lines.size(); i ++) idx[i] = i;
00146   randShuffle(idx, lines.size());
00147   LINFO("Randomized %"ZU" pairs of images.", lines.size());
00148 
00149   const uint dw = d->getWidth(), dh = d->getHeight();
00150 
00151   // let's do an eye tracker calibration:
00152   // let's display an ISCAN calibration grid:
00153   d->clearScreen();
00154   d->displayISCANcalib();
00155   d->waitForKey();
00156 
00157   // let's do an eye tracker calibration:
00158   d->displayText("<SPACE> to calibrate; other key to skip");
00159   int c = d->waitForKey();
00160   if (c == ' ') d->displayEyeTrackerCalibration();
00161 
00162   d->clearScreen();
00163   d->displayText("<SPACE> To Cotinue Experiment");
00164   c = d->waitForKey();
00165 
00166   for (uint ii = 0; ii < lines.size(); ++ii)
00167     {
00168       std::vector<std::string> tokens;
00169       split(lines[idx[ii]], " \t", std::back_inserter(tokens));
00170       if (tokens.size() != 2)
00171         LFATAL("Need two filenames per line: %s", lines[idx[ii]].c_str());
00172 
00173       // pick a random display order:
00174       uint idx1 = 0, idx2 = 1;
00175       if (randomUpToNotIncluding(2) > 0) { idx1 = 1; idx2 = 0; }
00176 
00177       // load up the two images and show a fixation cross on a blank screen:
00178       d->clearScreen();
00179       LINFO("Loading '%s'...", tokens[idx1].c_str());
00180       Image< PixRGB<byte> > image1 = Raster::ReadRGB(tokens[idx1]);
00181       LINFO("Loading '%s'...", tokens[idx2].c_str());
00182       Image< PixRGB<byte> > image2 = Raster::ReadRGB(tokens[idx2]);
00183 
00184       // Create a composite side-by-side image:
00185       Image< PixRGB<byte> > image(d->getDims(), NO_INIT);
00186       image.clear(d->getGrey());
00187 
00188       const uint m = 20;  // margin around the images
00189       const uint mm = 20; // half spacing between the images
00190       inplaceEmbed(image, image1,
00191                    Rectangle(Point2D<int>(m, m), Dims(dw/2-mm-m*2, dh-m*2)),
00192                    d->getGrey(), true);
00193       inplaceEmbed(image, image2,
00194                    Rectangle(Point2D<int>(dw/2+mm+m, m), Dims(dw/2-mm-m*2, dh-m*2)),
00195                    d->getGrey(), true);
00196 
00197       SDL_Surface *surf = d->makeBlittableSurface(image, true);
00198 
00199       LINFO("%s / %s ready.", tokens[idx1].c_str(), tokens[idx2].c_str());
00200       d->displayFixation();
00201 
00202       // ready to go whenever the user is ready:
00203       d->waitForKey();
00204       d->pushEvent(std::string("===== Showing images: ") +
00205                    tokens[idx1] + " / " + tokens[idx2] + " =====");
00206 
00207       // start the eye tracker:
00208       et->track(true);
00209 
00210       // blink the fixation:
00211       d->displayFixationBlink();
00212 
00213       // show the image:
00214       d->displaySurface(surf, -2);
00215 
00216       // sleep a bit and stop the tracker:
00217       usleep(5000000);
00218       et->track(false);
00219 
00220       const int fh = 20; // font height in pixels
00221 
00222       // display the questions and wait for a key each time:
00223       for (int i = 0; i < numcrit; ++i)
00224         {
00225           d->pushEvent(std::string("===== Question: ") +
00226                        message[i] + " =====");
00227 
00228           drawFilledRect(image, Rectangle(Point2D<int>(0, d->getHeight() - fh-10),
00229                                           Dims(d->getWidth(), fh+10)),
00230                          d->getGrey());
00231 
00232           writeText(image,
00233                     Point2D<int>((d->getWidth() - 10 * message[i].size()) / 2,
00234                             d->getHeight() - fh - 5),
00235                     message[i].c_str(), PixRGB<byte>(0, 0, 64),
00236                     d->getGrey(), SimpleFont::FIXED(10));
00237 
00238           SDL_Surface *s = d->makeBlittableSurface(image, true);
00239           d->displaySurface(s, -2);
00240 
00241           // wait for key (will log which key was pressed):
00242           d->waitForKey();
00243 
00244           SDL_FreeSurface(s);
00245         }
00246 
00247       // get ready for next one or end:
00248       d->clearScreen();
00249       SDL_FreeSurface(surf);
00250     }
00251 
00252   d->clearScreen();
00253   d->displayText("Experiment complete. Thank you!");
00254   d->waitForKey();
00255 
00256   // stop all our ModelComponents
00257   manager.stop();
00258 
00259   delete [] idx;
00260 
00261   // all done!
00262   return 0;
00263 }
00264 
00265 // ######################################################################
00266 extern "C" int main(const int argc, char** argv)
00267 {
00268   // simple wrapper around submain() to catch exceptions (because we
00269   // want to allow PsychoDisplay to shut down cleanly; otherwise if we
00270   // abort while SDL is in fullscreen mode, the X server won't return
00271   // to its original resolution)
00272   try
00273     {
00274       return submain(argc, argv);
00275     }
00276   catch (...)
00277     {
00278       REPORT_CURRENT_EXCEPTION;
00279     }
00280 
00281   return 1;
00282 }
00283 
00284 // ######################################################################
00285 /* So things look consistent in everyone's emacs... */
00286 /* Local Variables: */
00287 /* indent-tabs-mode: nil */
00288 /* End: */
Generated on Sun May 8 08:04:11 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3