00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "Component/ModelManager.H"
00040 #include "Image/ColorOps.H"
00041 #include "Image/CutPaste.H"
00042 #include "Image/Image.H"
00043 #include "Image/MathOps.H"
00044 #include "Psycho/PsychoDisplay.H"
00045 #include "Psycho/EyeTrackerConfigurator.H"
00046 #include "Psycho/EyeTracker.H"
00047 #include "Psycho/PsychoOpts.H"
00048 #include "Component/EventLog.H"
00049 #include "Component/ComponentOpts.H"
00050 #include "Raster/Raster.H"
00051 #include "Util/MathFunctions.H"
00052 #include "Util/StringUtil.H"
00053 #include "Util/stats.H"
00054 #include "Util/Timer.H"
00055 #include "Image/ShapeOps.H"
00056 #include "Image/DrawOps.H"
00057 #include <ctype.h>
00058 #include <vector>
00059 #include <string>
00060 #include <fstream>
00061 #include <deque>
00062
00063 using namespace std;
00064
00065
00066 #define NMASK 10
00067
00068 struct gPatch
00069 {
00070 int patchNo;
00071 Point2D<int> pos;
00072 };
00073
00074
00075
00076 static int submain(const int argc, char** argv)
00077 {
00078 MYLOGVERB = LOG_INFO;
00079
00080
00081 ModelManager manager("Psycho Search");
00082
00083
00084 nub::soft_ref<PsychoDisplay> d(new PsychoDisplay(manager));
00085 manager.addSubComponent(d);
00086
00087 nub::soft_ref<EyeTrackerConfigurator>
00088 etc(new EyeTrackerConfigurator(manager));
00089 manager.addSubComponent(etc);
00090
00091 nub::soft_ref<EventLog> el(new EventLog(manager));
00092 manager.addSubComponent(el);
00093
00094 manager.setOptionValString(&OPT_EventLogFileName, "psychodata.psy");
00095 manager.setOptionValString(&OPT_EyeTrackerType, "ISCAN");
00096
00097
00098 if (manager.parseCommandLine(argc, argv, "<imagelist.txt> <subjectname>", 2, 2) == false)
00099 return(1);
00100
00101
00102 nub::soft_ref<EyeTracker> et = etc->getET();
00103 d->setEyeTracker(et);
00104 d->setEventLog(el);
00105 et->setEventLog(el);
00106
00107 et->requestQuickEyeS();
00108
00109
00110 manager.start();
00111 string subjName =std::string(manager.getExtraArg(1).c_str());
00112
00113
00114 FILE *f = fopen(manager.getExtraArg(0).c_str(), "r");
00115 if (f == NULL) LFATAL("Cannot read stimulus file");
00116 char line[1024];
00117 std::vector<std::string> ilist, tlist, rlist, slist;
00118 int correct = 0, accuracy = 100, total = 0;
00119
00120 while(fgets(line, 1024, f))
00121 {
00122 std::vector<std::string> tokens;
00123
00124
00125
00126
00127 LINFO("line reads %s",line);
00128 split(line," ", std::back_inserter(tokens));
00129
00130
00131 tlist.push_back(std::string(tokens[0]));
00132 ilist.push_back(std::string(tokens[1]));
00133 rlist.push_back(std::string(tokens[2]));
00134 slist.push_back(std::string(tokens[3]));
00135 LINFO("\nNew pair \nline1 reads: %s, \nline2 reads:%s, \nline 3 reads %s,\nline 4 reads %s,",tokens[0].c_str(), tokens[1].c_str(),tokens[2].c_str(), tokens[3].c_str());
00136
00137 }
00138 fclose(f);
00139
00140
00141 int nimg = ilist.size(); int imindex[nimg];
00142 for (int i = 0; i < nimg; i ++) imindex[i] = i;
00143 randShuffle(imindex, nimg);
00144
00145
00146 d->clearScreen();
00147 d->displayISCANcalib();
00148 d->waitForKey();
00149
00150
00151 d->displayText("<SPACE> to calibrate; other key to skip");
00152 int c = d->waitForKey();
00153 if (c == ' ') et->calibrateOnline(d);
00154
00155
00156 d->clearScreen();
00157
00158 d->displayText("<SPACE> to start experiment");
00159 d->waitForKey();
00160
00161
00162 int sampleCnt=0,numSamples=50;
00163 std::deque<Point2D<int> > currentEyeSamples(numSamples);
00164 Point2D<int>meanFixation;
00165 stats<float> Stats;
00166
00167
00168
00169 for (int im = 0; im < nimg; im++) {
00170 int imnum = imindex[im];
00171
00172
00173 d->clearScreen();
00174 LINFO("Loading '%s' / '%s'...", ilist[imnum].c_str(),tlist[imnum].c_str());
00175
00176
00177
00178 if(!Raster::fileExists(tlist[imnum]))
00179 {
00180
00181 manager.stop();
00182 LFATAL("i couldnt find image file %s", tlist[imnum].c_str());
00183 }
00184
00185 Image< PixRGB<byte> > targetImg = Raster::ReadRGB(tlist[imnum]);
00186 Image< PixRGB<byte> > rndimg(d->getDims(), NO_INIT);
00187 rndimg.clear(d->getGrey());
00188 int rndx = 0,rndy = 0;
00189
00190 SDL_Surface *surf1 = d->makeBlittableSurface(targetImg, true);
00191 char buf[256];
00192
00193 if(!Raster::fileExists(ilist[imnum]))
00194 {
00195 manager.stop();
00196 LFATAL("i couldnt find image file %s", ilist[imnum].c_str());
00197 }
00198 Image<PixRGB<byte> > ArrayImg = Raster::ReadRGB(ilist[imnum]);
00199 SDL_Surface *surf2 = d->makeBlittableSurface(ArrayImg, true);
00200
00201
00202
00203
00204 if(!Raster::fileExists(rlist[imnum]))
00205 {
00206
00207 manager.stop();
00208 LFATAL(" i couldnt find image file %s", tlist[imnum].c_str());
00209 }
00210
00211 Image< PixRGB<byte> > reportImg = Raster::ReadRGB(rlist[imnum]);
00212
00213
00214
00215 usleep(200000);
00216
00217
00218 d->displayFixationBlink();
00219
00220 d->waitNextRequestedVsync(false, true);
00221
00222
00223 sprintf(buf, "===== Showing imagelet: %s at (%d, %d) =====",
00224 tlist[imnum].c_str(), rndx, rndy);
00225
00226 d->pushEvent(buf);
00227 d->displaySurface(surf1, 0, true);
00228 usleep(2000000);
00229
00230 d->clearScreen();
00231 SDL_FreeSurface(surf1);
00232
00233
00234
00235 et->track(true);
00236
00237 std::vector<std::string> stimNameTokens;
00238 split(ilist[imnum],"/",std::back_inserter(stimNameTokens));
00239
00240 et->setCurrentStimFile(std::string(subjName + "_" + stimNameTokens[stimNameTokens.size()-1]));
00241 currentEyeSamples.resize(0);
00242 sampleCnt =0;
00243
00244
00245 d->pushEvent(std::string("===== Showing search image: ") + ilist[imnum] +
00246 std::string(" ====="));
00247
00248
00249 d->displaySurface(surf2, 0, true);
00250
00251 Image<PixRGB<byte> > dispImage(1920,1080,NO_INIT);
00252
00253 d->checkForKey();
00254 Timer timer(100);
00255 timer.reset();
00256 double startTime=timer.getSecs();
00257 bool timeOut=false;
00258 while(d->checkForKey() < 0 && !timeOut)
00259 {
00260 dispImage = ArrayImg;
00261
00262 Point2D<int> tempEye = et->getCalibEyePos();
00263 if(tempEye.i >0 && tempEye.i <1960 && tempEye.j>0 &&tempEye.j<1080)
00264 currentEyeSamples.push_back(tempEye);
00265
00266
00267
00268 drawCircle(dispImage, tempEye,5,PixRGB<byte>(255,255,255));
00269 surf2 = d->makeBlittableSurface(dispImage,true);
00270 d->displaySurface(surf2,-2);
00271 LINFO("getting live eyepos %d,%d",currentEyeSamples.back().i,
00272 currentEyeSamples.back().j);
00273
00274 if(currentEyeSamples.size() ==(size_t)numSamples)
00275 {
00276 currentEyeSamples.pop_front();
00277 sampleCnt=numSamples;
00278 }
00279 if(sampleCnt < numSamples);
00280 sampleCnt++;
00281
00282 SDL_FreeSurface(surf2);
00283 if(timer.getSecs() >= startTime + 10)
00284 timeOut=true;
00285 }
00286
00287
00288
00289 et->track(false);
00290 LINFO("getting out of track mode");
00291 LINFO("currenteye samples available %d",(int)currentEyeSamples.size());
00292
00293
00294 std::vector<float> xVals(sampleCnt),yVals(sampleCnt);
00295 float xMean,yMean;
00296
00297 Point2D<int>temp;
00298 for(int i =0;i <(int)currentEyeSamples.size();i++)
00299 {
00300 LINFO("accessing front cnt=%d %d",i,currentEyeSamples[i].i);
00301 temp = currentEyeSamples[i];
00302 LINFO("\n counting %d,%d",temp.i,temp.j);
00303 xVals[i]=temp.i;
00304 yVals[i]=temp.j;
00305 }
00306
00307 if(sampleCnt > 0)
00308 {
00309 xMean = Stats.mean(xVals);
00310 yMean = Stats.mean(yVals);
00311 }
00312 else
00313 {
00314 xMean = 0;
00315 yMean=0;
00316 }
00317
00318 LINFO("mean target %f,%f",xMean,yMean);
00319
00320 char tmp[40];
00321
00322
00323 ifstream specFile(slist[imnum].c_str(), ifstream::in);
00324
00325 bool found =false;
00326 string testLine;
00327 std::vector<std::string> specTokens,xTokens,yTokens,gTokens;
00328 std::vector<gPatch> gPatches(32);
00329 int targetNum=0,patchCnt=0;
00330
00331 LINFO("opening specfile");
00332 if(specFile.is_open())
00333 {
00334 while(!specFile.eof() && !found)
00335 {
00336 getline(specFile, testLine);
00337 LINFO("got line %s",testLine.c_str());
00338 string::size_type loc = testLine.find("target", 0);
00339 string::size_type loc2 = testLine.find("Gabor",0);
00340 string::size_type loc3 = testLine.find("Xpos",0);
00341 string::size_type loc4 = testLine.find("Ypos",0);
00342
00343 if(loc != string::npos)
00344 {
00345 split(testLine," ", std::back_inserter(specTokens));
00346 targetNum = atoi(specTokens[1].c_str());
00347 specTokens.resize(0);
00348 found = true;
00349 }
00350
00351 if(loc2 != string::npos)
00352 {
00353
00354 split(testLine," ", std::back_inserter(gTokens));
00355 gPatches[patchCnt].patchNo = atoi(gTokens[1].c_str());
00356 LINFO("gPatches[%d].patchNo = %d",patchCnt,gPatches[patchCnt].patchNo);
00357 gTokens.resize(0);
00358
00359 }
00360
00361 if(loc3 != string::npos)
00362 {
00363 split(testLine,"\t", std::back_inserter(xTokens));
00364 gPatches[patchCnt].pos.i = atoi(xTokens[1].c_str())+120;
00365 LINFO("gPatches[%d].pos.i = %d",patchCnt,gPatches[patchCnt].pos.i);
00366 xTokens.resize(0);
00367 }
00368 if(loc4 != string::npos)
00369 {
00370 split(testLine,"\t", std::back_inserter(yTokens));
00371 gPatches[patchCnt].pos.j = atoi(yTokens[1].c_str())+120;
00372 LINFO("gPatches[%d].pos.j = %d",patchCnt,gPatches[patchCnt].pos.j);
00373 yTokens.resize(0);
00374 if(patchCnt < 31)
00375 patchCnt++;
00376 }
00377
00378 }
00379
00380 LINFO("specfile parsed finding target x y");
00381
00382 if(!found)
00383 {
00384 manager.stop();
00385 LFATAL("couldnt find the target number from spec file");
00386 }
00387
00388
00389
00390
00391 std::vector<float> euclidDists(32);
00392 float minDist=500000;
00393 int minIdx=-1;
00394
00395
00396 for(int i=0;i<32;i++)
00397 {
00398 LINFO("finding distance between fix %f,%f and gabor%d,%d",xMean,yMean,gPatches[i].pos.i,gPatches[i].pos.j);
00399 euclidDists[i] = gPatches[i].pos.distance(Point2D<int>((int)xMean,(int)yMean));
00400 if(euclidDists[i] < minDist)
00401 {
00402 minDist = euclidDists[i];
00403 minIdx = i;
00404 }
00405 LINFO("euclidDist %d %f",i,euclidDists[i]);
00406
00407 }
00408 if(minIdx == -1)
00409 { minIdx =0;
00410 LINFO("cannot find a match in euclid distance");
00411 }
00412 LINFO("found min IDx to be %d", minIdx);
00413
00414 int txPos = gPatches[minIdx].pos.i, tyPos = gPatches[minIdx].pos.j;
00415 SDL_Surface *surf4;
00416
00417
00418 for(int i=0;i<20;i++)
00419 {
00420
00421
00422
00423 drawCircle(ArrayImg, Point2D<int> (txPos,tyPos),5,PixRGB<byte>(255,255,255));
00424 surf4 = d->makeBlittableSurface(ArrayImg, true);
00425 d->displaySurface(surf4,-2);
00426 drawCircle(ArrayImg, Point2D<int> (txPos,tyPos),5,PixRGB<byte>(255,0,0));
00427
00428 surf4 = d->makeBlittableSurface(ArrayImg, true);
00429 d->displaySurface(surf4,-2);
00430 }
00431
00432
00433 SDL_FreeSurface(surf4);
00434
00435
00436 LINFO("after showing selection");
00437
00438 total++;
00439 if (minIdx == targetNum)
00440 {
00441 correct ++;
00442 accuracy = correct * 100 / total;
00443 sprintf(tmp, "Correct! Accuracy is %d%%", accuracy);
00444 d->displayText(tmp);
00445 d->pushEvent(std::string("===== Correct ====="));
00446 usleep(500000);
00447 }
00448 else
00449 {
00450 accuracy = correct * 100 / total;
00451 sprintf(tmp, "Wrong! Accuracy is %d%%", accuracy);
00452 d->displayText(tmp);
00453 d->pushEvent(std::string("===== Wrong ====="));
00454 usleep(500000);
00455 }
00456 specFile.close();
00457 }
00458
00459 else
00460 {
00461 d->displayText("no target file found!");
00462 LFATAL("couldnt open the file -%s-",slist[imnum].c_str());
00463 }
00464
00465 LINFO("out of spec file zone");
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483 if (im==50)
00484 {
00485 d->displayText("You may take a break press space to continue when ready");
00486 d->waitForKey();
00487
00488 d->clearScreen();
00489 d->displayISCANcalib();
00490 d->waitForKey();
00491
00492 d ->displayText("<SPACE> to calibrate; other key to skip");
00493 int c = d->waitForKey();
00494 if (c == ' ') et->calibrateOnline(d);
00495 }
00496 }
00497
00498
00499
00500 d->clearScreen();
00501 d->displayText("Experiment complete. Thank you!");
00502 d->waitForKey();
00503
00504
00505 manager.stop();
00506
00507
00508 return 0;
00509 }
00510
00511
00512
00513
00514
00515 extern "C" int main(const int argc, char** argv)
00516 {
00517
00518
00519
00520
00521 try
00522 {
00523 return submain(argc, argv);
00524 }
00525 catch (...)
00526 {
00527 REPORT_CURRENT_EXCEPTION;
00528 }
00529
00530 return 1;
00531 }
00532
00533
00534
00535
00536