00001 /*!@file Transport/RandomInput.C A FrameIstream subclass for 00002 generating random images */ 00003 00004 // //////////////////////////////////////////////////////////////////// // 00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00006 // by the 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: Rob Peters <rjpeters at usc dot edu> 00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Transport/RandomInput.C $ 00036 // $Id: RandomInput.C 8602 2007-07-20 23:10:44Z rjpeters $ 00037 // 00038 00039 #ifndef TRANSPORT_DOTSTIMULI_C_DEFINED 00040 #define TRANSPORT_DOTSTIMULI_C_DEFINED 00041 00042 #define DOT_NUM 500 // 200 1000 --> Shuo: 640x480: 2000 dots 00043 00044 #define FOE_X 2*WIDTH/4 // W/4 00045 #define FOE_Y 3*HEIGHT/4 // 2H/4 +4 00046 00047 #define DOT_VEL 2.0/80.0 // Shuo: .035 00048 00049 // Shuo: in PsychToolbox: size refers to diameter, in our code radius 00050 // Shuo: Abs max: 21, ave DS is 9.767 across all dots in each frames 00051 #define DOT_ORG_DSIZE .02 // .04 00052 #define DOT_DSIZE .07 // .035 00053 #define MIN_DOT_SIZE 1 00054 #define MAX_DOT_SIZE 5 00055 #define ABS_MAX_DSIZE 50 00056 #define NFRAME 60 00057 00058 #define HAVE_MOTION 1 00059 #define HAVE_TEMP_SGRAD 1 00060 #define HAVE_SPAT_SGRAD 1 00061 00062 #define NUM_PYR_LEVEL 3 // 3 for 640x480 00063 #define NUM_DIRS 8 00064 #define NUM_SPEEDS 3 00065 00066 #define SIDE_LENGTH 20 00067 00068 #include "Transport/DotStimuli.H" 00069 00070 #include "Image/Image.H" 00071 #include "Image/ColorOps.H" 00072 #include "Image/MathOps.H" 00073 #include "Raster/Raster.H" 00074 #include "Image/Pixels.H" 00075 #include "Raster/GenericFrame.H" 00076 #include "Image/DrawOps.H" 00077 00078 // ###################################################################### 00079 DotStimuli::DotStimuli(OptionManager& mgr) 00080 : 00081 FrameIstream(mgr, "Random Input", "RandomInput"), 00082 itsDims(320,240), // if you change this default value, also update 00083 // the documentation of OPT_InputFrameSource in 00084 // Media/MediaOpts.C 00085 00086 itsGenerator(0), 00087 itsIsFoe(false), 00088 itsFoe(Point2D<int>(-1,-1)) 00089 { 00090 itsStep = 0; 00091 itsAsymmetryMode = 0; 00092 } 00093 00094 // ###################################################################### 00095 DotStimuli::~DotStimuli() 00096 {} 00097 00098 // ###################################################################### 00099 void DotStimuli::setConfigInfo(const std::string& options) 00100 { 00101 // NOTE: if you modify any behavior here, then please update the 00102 // corresponding documentation for the global "--in" option inside 00103 // the OPT_InputFrameSource definition in Media/MediaOpts.C 00104 00105 LINFO("options: %s", options.c_str()); 00106 if (options.size() == 0) return; 00107 00108 // parse the options 00109 00110 // compounds are separated by commas ',' 00111 std::string rops = options; 00112 std::string::size_type fcpos = rops.find_first_of(','); 00113 00114 // check for resizing first option 00115 // (has to be in first position) 00116 // --in=dots:WxH, 00117 std::string op1 = rops.substr(0, fcpos); 00118 LDEBUG("op1: %s", op1.c_str()); 00119 00120 std::string::size_type fxpos = rops.find_first_of('x'); 00121 if(fcpos != std::string::npos && 00122 fxpos != std::string::npos && 00123 fxpos < fcpos) 00124 { 00125 Dims d; convertFromString(op1, d); 00126 this->setDims(d); 00127 00128 std::string temp = rops.substr(fcpos+1); rops = temp; 00129 00130 LDEBUG("new stimuli dimension: %dx%d", d.w(), d.h()); 00131 } 00132 00133 // subsequent commands 00134 // NOTE: the shared config parameters will be set to 00135 // what the last command specifies 00136 while(rops.size() != 0) 00137 { 00138 fcpos = rops.find_first_of(','); 00139 std::string op = rops.substr(0, fcpos); 00140 if(fcpos != std::string::npos) 00141 { 00142 std::string temp = rops.substr(fcpos+1); rops = temp; 00143 } 00144 else rops = std::string(""); 00145 LDEBUG("op:%s rest:%s", op.c_str(), rops.c_str()); 00146 00147 // for the next iteration 00148 fcpos = rops.find_first_of(','); 00149 00150 // paramaters for this option is between "[ ]" 00151 std::string::size_type fbpos = op.find_first_of('['); 00152 std::string::size_type bbpos = op.find_first_of(']'); 00153 std::string params; 00154 if(fbpos != std::string::npos) 00155 { 00156 params = op.substr(fbpos+1,bbpos - fbpos - 1); 00157 LDEBUG("params: %s", params.c_str()); 00158 00159 std::string temp = op.substr(0,fbpos); op = temp; 00160 } 00161 00162 // go through all the different motion 00163 if(!op.compare("Random")) setConfigRandom(params); 00164 else 00165 if(!op.compare("Single")) setConfigSingle(params); 00166 else 00167 if(!op.compare("Planar")) setConfigPlanar(params); 00168 else 00169 if(!op.compare("AsymmetryFast")) 00170 //setConfigAsymmetry(params, 0); 00171 setConfigAsymmetry(params, 2); 00172 else 00173 if(!op.compare("AsymmetrySlow")) 00174 //setConfigAsymmetry(params, 1); 00175 setConfigAsymmetry(params, 3); 00176 else 00177 if(!op.compare("Foe")) setConfigFoe(params); 00178 else 00179 if(!op.compare("Rotation")) setConfigRotation(params); 00180 else LFATAL("unknown DotStimuli option: %s", op.c_str()); 00181 } 00182 } 00183 00184 // ###################################################################### 00185 void DotStimuli::setDims(const Dims& s) 00186 { 00187 itsDims = s; 00188 } 00189 00190 // ###################################################################### 00191 void DotStimuli::setConfigRandom(const std::string& params) 00192 { 00193 itsIsRandom = true; 00194 LINFO("Random Motion"); 00195 00196 if(params.size() == 0) return; 00197 } 00198 00199 // ###################################################################### 00200 void DotStimuli::setConfigSingle(const std::string& params) 00201 { 00202 itsIsSingleDot = true; 00203 00204 itsSingleDotDx = 2.0; 00205 itsSingleDotDy = 0.0; 00206 00207 float orgDotSize = 2.0; 00208 itsSingleDotSize = orgDotSize; 00209 00210 LINFO("Single Dot Motion"); 00211 00212 if(params.size() == 0) return; 00213 } 00214 00215 // ###################################################################### 00216 void DotStimuli::setConfigPlanar(const std::string& params) 00217 { 00218 itsIsPlanar = true; 00219 itsPlanarDx = 2.0; 00220 itsPlanarDy = 0.0; 00221 LINFO("Planar Motion"); 00222 00223 if(params.size() == 0) return; 00224 } 00225 00226 // ###################################################################### 00227 void DotStimuli::setConfigAsymmetry(const std::string& params, uint mode) 00228 { 00229 itsIsPlanar = true; 00230 itsIsSingleDot = true; 00231 itsPlanarDx = 2.0; 00232 itsPlanarDy = 0.0; 00233 00234 float orgDotSize = 1.0; 00235 itsSingleDotSize = orgDotSize; 00236 00237 itsAsymmetryMode = mode; 00238 if(mode == 0 || mode == 2) 00239 { 00240 itsSingleDotDx = 4.0; 00241 itsSingleDotDy = 0.0; 00242 LINFO("Asymmetry Motion Fast"); 00243 00244 //if(mode == 2) itsIsSingleDot = false; 00245 } 00246 else if(mode == 1 || mode == 3) 00247 { 00248 itsSingleDotDx = 1.0; 00249 itsSingleDotDy = 0.0; 00250 LINFO("Asymmetry Motion Slow"); 00251 00252 //if(mode == 3) itsIsSingleDot = false; 00253 } 00254 00255 00256 if(params.size() == 0) return; 00257 } 00258 00259 // ###################################################################### 00260 void DotStimuli::setConfigFoe(const std::string& params) 00261 { 00262 itsIsFoe = true; 00263 00264 itsFoe = Point2D<int>(160,120); 00265 LINFO("Focus of Expansion"); 00266 00267 if(params.size() == 0) 00268 { 00269 itsFoeHaveMotion = HAVE_MOTION; 00270 itsFoeHaveTempSGrad = HAVE_TEMP_SGRAD; 00271 itsFoeHaveSpatSGrad = HAVE_SPAT_SGRAD; 00272 return; 00273 } 00274 00275 // parse the parameters 00276 std::string rops = params; 00277 std::string::size_type fcmpos = rops.find_first_of('/'); 00278 while(rops.size() != 0) 00279 { 00280 std::string op = rops.substr(0, fcmpos); 00281 if(fcmpos != std::string::npos) 00282 { 00283 std::string temp = rops.substr(fcmpos+1); rops = temp; 00284 } 00285 else rops = std::string(""); 00286 00287 LINFO("op:%s rest:%s", op.c_str(), rops.c_str()); 00288 00289 // for the next iteration 00290 fcmpos = rops.find_first_of(','); 00291 00292 // paramaters for this option is after colon : 00293 std::string::size_type fclpos = op.find_first_of(':'); 00294 std::string params; 00295 if(fclpos != std::string::npos) 00296 { 00297 params = op.substr(fclpos+1); 00298 LINFO("params: %s", params.c_str()); 00299 00300 std::string temp = op.substr(0,fclpos); op = temp; 00301 } 00302 00303 // go through all the different motion 00304 if(!op.compare("Shuo")) 00305 { 00306 LINFO("Shuo Stimuli"); 00307 } 00308 else if(!op.compare("flags")) 00309 { 00310 int flag = atoi(params.c_str()); 00311 itsFoeHaveMotion = (flag & 4); 00312 itsFoeHaveTempSGrad = (flag & 2); 00313 itsFoeHaveSpatSGrad = (flag & 1); 00314 00315 LINFO("flag is: %d: (%d %d %d)", flag, 00316 itsFoeHaveMotion, 00317 itsFoeHaveTempSGrad, 00318 itsFoeHaveSpatSGrad); 00319 } 00320 00321 else LFATAL("unknown Foe param: %s", op.c_str()); 00322 } 00323 } 00324 00325 // ###################################################################### 00326 void DotStimuli::setConfigRotation(const std::string& params) 00327 { 00328 itsIsRotation = true; 00329 LINFO("Rotation Motion"); 00330 00331 if(params.size() == 0) return; 00332 } 00333 00334 // ###################################################################### 00335 GenericFrameSpec DotStimuli::peekFrameSpec() 00336 { 00337 GenericFrameSpec result; 00338 00339 result.nativeType = GenericFrame::RGB_U8; 00340 result.videoFormat = VIDFMT_AUTO; 00341 result.videoByteSwap = false; 00342 result.dims = itsDims; 00343 result.floatFlags = 0; 00344 00345 return result; 00346 } 00347 00348 // ###################################################################### 00349 GenericFrame DotStimuli::readFrame() 00350 { 00351 Image<float> result(itsDims, ZEROS); 00352 00353 // add dots 00354 if(itsIsRandom) 00355 { 00356 result += getRandomDotStimuli(itsStep); 00357 } 00358 if(itsIsSingleDot) 00359 { 00360 result += getSingleDotStimuli(itsStep); 00361 } 00362 if(itsIsPlanar) 00363 { 00364 result += getPlanarDotStimuli(itsStep); 00365 } 00366 if(itsIsFoe) 00367 { 00368 result += getFoeStimuli(itsStep); 00369 } 00370 if(itsIsRotation) 00371 { 00372 result += getRotationDotStimuli(itsStep); 00373 } 00374 00375 itsStep++; 00376 00377 inplaceNormalize(result, 0.0F, 255.0F); 00378 Image<PixRGB<byte> > temp = makeRGB(result,result,result); 00379 return GenericFrame(temp); 00380 } 00381 00382 // ###################################################################### 00383 Image<float> DotStimuli::getRandomDotStimuli(uint step) 00384 { 00385 Image<byte> temp(itsDims, ZEROS); 00386 //uint width = itsDims.w(); 00387 //uint height = itsDims.h(); 00388 00389 return temp; 00390 } 00391 00392 // ###################################################################### 00393 Image<float> DotStimuli::getSingleDotStimuli(uint step) 00394 { 00395 //LINFO("SINGLE DOT\n\n\n"); 00396 00397 Image<float> temp(itsDims, ZEROS); 00398 uint width = itsDims.w(); 00399 uint height = itsDims.h(); 00400 00401 uint sideLength = SIDE_LENGTH; 00402 float nHorz = width/sideLength; 00403 float nVert = height/sideLength; 00404 00405 if(step == 0) 00406 { 00407 if(itsAsymmetryMode > 1) 00408 { 00409 uint i = uint((nHorz*rand())/(RAND_MAX + 1.0)); 00410 uint j = uint((nVert*rand())/(RAND_MAX + 1.0)); 00411 itsSingleDotLocation = Point2D<float> 00412 (sideLength/2 + i * sideLength, 00413 sideLength/2 + j * sideLength ); 00414 } 00415 else 00416 itsSingleDotLocation = Point2D<float> 00417 (width * .1,// * double(rand())/(RAND_MAX + 1.0), 00418 height * double(rand())/(RAND_MAX + 1.0)); 00419 } 00420 00421 // planar motion 00422 if(itsSingleDotDx != 0.0 || itsSingleDotDy != 0.0) 00423 itsSingleDotLocation = 00424 Point2D<float>(fmod(itsSingleDotLocation.i + itsSingleDotDx, width), 00425 fmod(itsSingleDotLocation.j + itsSingleDotDy, height)); 00426 00427 drawDisk(temp, 00428 Point2D<int>(itsSingleDotLocation.i, 00429 itsSingleDotLocation.j), 00430 itsSingleDotSize, 1.0F); 00431 //LINFO("(%f %f)", itsSingleDotLocation.i, itsSingleDotLocation.j); 00432 00433 return temp; 00434 } 00435 00436 // ###################################################################### 00437 Image<float> DotStimuli::getPlanarDotStimuli(uint step) 00438 { 00439 //LINFO("PLANAR DOT\n\n\n"); 00440 00441 if(itsAsymmetryMode > 1) 00442 return getGridPlanarDotStimuli(step); 00443 else 00444 return getRandomPlanarDotStimuli(step); 00445 } 00446 00447 // ###################################################################### 00448 Image<float> DotStimuli::getGridPlanarDotStimuli(uint step) 00449 { 00450 Image<float> temp(itsDims, ZEROS); 00451 uint width = itsDims.w(); 00452 uint height = itsDims.h(); 00453 00454 //if(step > NFRAME) return Image<byte>(); 00455 00456 uint sideLength = SIDE_LENGTH; 00457 float orgDotSize = 1.0; 00458 00459 // create random dot initially 00460 if(step == 0) 00461 { 00462 uint nHorz = width/sideLength; 00463 uint nVert = height/sideLength; 00464 itsPlanarDots.clear(); itsPlanarDotSizes.clear(); 00465 00466 for(uint i = 0; i < nHorz; i++) 00467 { 00468 for(uint j = 0; j < nVert; j++) 00469 { 00470 Point2D<float> currPt 00471 (sideLength/2 + i*sideLength, 00472 sideLength/2 + j*sideLength ); 00473 if(currPt.i != itsSingleDotLocation.i - itsSingleDotDx || 00474 currPt.j != itsSingleDotLocation.j - itsSingleDotDy ) 00475 { 00476 itsPlanarDots.push_back(currPt); 00477 itsPlanarDotSizes.push_back(orgDotSize); 00478 } 00479 } 00480 } 00481 } 00482 uint nDots = itsPlanarDots.size(); 00483 00484 // planar motion 00485 if(itsPlanarDx != 0.0 || itsPlanarDy != 0.0) 00486 for(uint i = 0; i < nDots; i++) 00487 { 00488 itsPlanarDots[i] = 00489 Point2D<float>(fmod(itsPlanarDots[i].i + itsPlanarDx, width), 00490 fmod(itsPlanarDots[i].j + itsPlanarDy, height)); 00491 } 00492 00493 // finally draw the dots 00494 for(uint i = 0; i < nDots; i++) 00495 { 00496 LDEBUG("[%d] loc: %10.3f %10.3f: size: %7.3f", 00497 i, itsPlanarDots[i].i, itsPlanarDots[i].j, itsPlanarDotSizes[i]); 00498 drawDisk(temp,Point2D<int>(itsPlanarDots[i].i, itsPlanarDots[i].j), 00499 itsPlanarDotSizes[i], 1.0F); 00500 //temp.setVal(itsPlanarDots[i].i, itsPlanarDots[i].j, byte(128)); 00501 //LINFO("pt: %8.3f %8.3f", itsPlanarDots[i].i, itsPlanarDots[i].j); 00502 } 00503 00504 return temp; 00505 } 00506 00507 00508 // ###################################################################### 00509 Image<float> DotStimuli::getRandomPlanarDotStimuli(uint step) 00510 { 00511 Image<float> temp(itsDims, ZEROS); 00512 uint width = itsDims.w(); 00513 uint height = itsDims.h(); 00514 00515 //if(step > NFRAME) return Image<byte>(); 00516 00517 uint dotNum = DOT_NUM; 00518 00519 float orgDotSize = 1.0; 00520 00521 // create random dot initially 00522 if(step == 0) 00523 { 00524 itsPlanarDots.resize(dotNum); itsPlanarDotSizes.resize(dotNum); 00525 for(uint i = 0; i < dotNum; i++) 00526 { 00527 itsPlanarDots[i] = Point2D<float> 00528 (width * double(rand())/(RAND_MAX + 1.0), 00529 height * double(rand())/(RAND_MAX + 1.0)); 00530 itsPlanarDotSizes[i] = orgDotSize; 00531 } 00532 } 00533 00534 // check for out-of-bounds dot needed to be shown 00535 for(uint i = 0; i < dotNum; i++) 00536 { 00537 // NOTE: can also kill dots randomly before going out of the image 00538 if(!temp.getBounds().contains(Point2D<int>(itsPlanarDots[i].i, 00539 itsPlanarDots[i].j))) 00540 { 00541 float srx = 0.0; float sry = 0.0; 00542 float rx = width; float ry = height; 00543 if(itsPlanarDx < 0.0) { srx = 7.0*width/8.0; rx = width/8; } 00544 else if(itsPlanarDx > 0.0){ srx = 0.0; rx = width/8; } 00545 00546 if(itsPlanarDy < 0.0) { sry = 7.0*height/8.0; ry = height/8; } 00547 else if(itsPlanarDy > 0.0){ sry = 0.0; ry = height/8; } 00548 00549 float sx = rx * double(rand())/(RAND_MAX + 1.0) + srx; 00550 float sy = ry * double(rand())/(RAND_MAX + 1.0) + sry; 00551 00552 itsPlanarDots[i] = Point2D<float>(sx,sy); 00553 itsPlanarDotSizes[i] = orgDotSize; 00554 LDEBUG("new dots[%3d]: %7.3f %7.3f", i, sx, sy); 00555 } 00556 else 00557 { 00558 Point2D<int> pt(itsPlanarDots[i].i, itsPlanarDots[i].j); 00559 LDEBUG("[%3d] it's ok: (%7.3f %7.3f) -> %3d %3d", 00560 i, itsPlanarDots[i].i, itsPlanarDots[i].j, pt.i, pt.j); 00561 } 00562 } 00563 00564 // planar motion 00565 if(itsPlanarDx != 0.0 || itsPlanarDy != 0.0) 00566 for(uint i = 0; i < dotNum; i++) 00567 { 00568 itsPlanarDots[i] = Point2D<float>(itsPlanarDots[i].i + itsPlanarDx, 00569 itsPlanarDots[i].j + itsPlanarDy); 00570 } 00571 00572 // finally draw the dots 00573 for(uint i = 0; i < dotNum; i++) 00574 { 00575 LDEBUG("[%d] loc: %10.3f %10.3f: size: %7.3f", 00576 i, itsPlanarDots[i].i, itsPlanarDots[i].j, itsPlanarDotSizes[i]); 00577 drawDisk(temp,Point2D<int>(itsPlanarDots[i].i, itsPlanarDots[i].j), 00578 itsPlanarDotSizes[i], 1.0F); 00579 //temp.setVal(itsPlanarDots[i].i, itsPlanarDots[i].j, byte(128)); 00580 } 00581 00582 return temp; 00583 } 00584 00585 // ###################################################################### 00586 Image<float> DotStimuli::getFoeStimuli(uint step) 00587 { 00588 float dx = 0.0; float dy = 0.0; 00589 //float dx = pshift.i; float dy = pshift.j; 00590 00591 float dotOrgDSize = DOT_ORG_DSIZE; 00592 00593 // planar (Yaw-Pitch) motion correction 00594 uint dir = 0.0; float speed = 0.0; 00595 00596 LINFO("[%3d] haveMotion: %d haveTempSGrad: %d haveSpatSGrad: %d " 00597 "dx dy: %7.3f %7.3f dotOrgDSize: %f comp: %d %f", 00598 itsStep, 00599 itsFoeHaveMotion, itsFoeHaveTempSGrad, itsFoeHaveSpatSGrad, 00600 dx, dy, dotOrgDSize, dir, speed); 00601 00602 //if(step > NFRAME) return Image<byte>(); 00603 00604 Image<byte> temp(itsDims, ZEROS); 00605 uint width = itsDims.w(); 00606 uint height = itsDims.h(); 00607 00608 float orgDotSize = 1.0; 00609 00610 // create random dot initially 00611 if(step == 0) 00612 { 00613 itsFoeDots.resize(DOT_NUM); itsFoeDotSizes.resize(DOT_NUM); 00614 for(uint i = 0; i < DOT_NUM; i++) 00615 { 00616 itsFoeDots[i] = Point2D<float> 00617 (width * double(rand())/(RAND_MAX + 1.0), 00618 height * double(rand())/(RAND_MAX + 1.0)); 00619 00620 // just do it in order to get identical average size 00621 //float range = MAX_DOT_SIZE - MIN_DOT_SIZE; 00622 //dotSizes[i] = i*range/(DOT_NUM-1.0)+ double(MIN_DOT_SIZE); 00623 itsFoeDotSizes[i] = orgDotSize; 00624 } 00625 } 00626 00627 // check for out-of-bounds dot needed to be shown 00628 for(uint i = 0; i < DOT_NUM; i++) 00629 { 00630 // NOTE: can also kill dots randomly before going out of the image 00631 // NOTE: how about adding new dots in the FOE quadrants 00632 if(!temp.getBounds(). 00633 contains(Point2D<int>(itsFoeDots[i].i, itsFoeDots[i].j))) 00634 { 00635 itsFoeDots[i] = Point2D<float> 00636 (width * double(rand())/(RAND_MAX + 1.0), 00637 height * double(rand())/(RAND_MAX + 1.0) ); 00638 00639 // keep the sizes or 1.0? 00640 itsFoeDotSizes[i] = orgDotSize; 00641 } 00642 } 00643 00644 // modify sizes according to rules 00645 for(uint i = 0; i < DOT_NUM; i++) 00646 { 00647 if(itsFoeHaveTempSGrad && itsFoeHaveSpatSGrad) 00648 { 00649 float dist = sqrt(pow((itsFoeDots[i].i - itsFoe.i), 2.0) + 00650 pow((itsFoeDots[i].j - itsFoe.j), 2.0) ); 00651 if(itsFoeHaveMotion) 00652 { 00653 itsFoeDotSizes[i] = dotOrgDSize * dist; 00654 } 00655 // growing, FOE coherent, but not moving 00656 else 00657 { 00658 if(step == 0) 00659 { 00660 itsFoeDotSizes[i] = dotOrgDSize * dist; 00661 } 00662 else 00663 { 00664 // increase until ABS_MAX_DSIZE, then stop 00665 if(itsFoeDotSizes[i] < ABS_MAX_DSIZE) 00666 { 00667 itsFoeDotSizes[i] = (1.0 + DOT_DSIZE) * 00668 dotOrgDSize * dist; 00669 } 00670 // else dot size stays the same 00671 } 00672 } 00673 } 00674 else if(itsFoeHaveTempSGrad && !itsFoeHaveSpatSGrad) 00675 { 00676 // all dot have same size just increase 00677 float ds = MAX_DOT_SIZE - MIN_DOT_SIZE; 00678 itsFoeDotSizes[i] = step*ds/(NFRAME - 1.0)+ double(MIN_DOT_SIZE); 00679 } 00680 else if(!itsFoeHaveTempSGrad && itsFoeHaveSpatSGrad) 00681 { 00682 float dist = sqrt(pow((itsFoeDots[i].i - itsFoe.i), 2.0) + 00683 pow((itsFoeDots[i].j - itsFoe.j), 2.0) ); 00684 itsFoeDotSizes[i] = dotOrgDSize * dist; 00685 } 00686 // else just keep size 00687 } 00688 00689 // move the dots if needed 00690 if(itsFoeHaveMotion) 00691 for(uint i = 0; i < DOT_NUM; i++) 00692 { 00693 itsFoeDots[i] = Point2D<float> 00694 (itsFoeDots[i].i + DOT_VEL * (itsFoeDots[i].i - itsFoe.i), 00695 itsFoeDots[i].j + DOT_VEL * (itsFoeDots[i].j - itsFoe.j)); 00696 } 00697 00698 // add lateral motion 00699 if(dx != 0.0 || dy != 0.0) 00700 for(uint i = 0; i < DOT_NUM; i++) 00701 { 00702 itsFoeDots[i] = Point2D<float>(itsFoeDots[i].i + dx, 00703 itsFoeDots[i].j + dy); 00704 } 00705 00706 // finally draw the dots 00707 for(uint i = 0; i < DOT_NUM; i++) 00708 { 00709 //LINFO("loc: %10.3f %10.3f: size: %7.3f", 00710 // dots[i].i, dots[i].j, dotSizes[i]); 00711 drawDisk(temp,Point2D<int>(itsFoeDots[i].i, 00712 itsFoeDots[i].j),itsFoeDotSizes[i], 00713 byte(255)); 00714 //temp.setVal(itsFoeDots[i].i, itsFoeDots[i].j, byte(128)); 00715 } 00716 00717 // draw the FOE 00718 //drawDisk(temp,itsFoe,2,byte(128)); 00719 00720 return temp; 00721 } 00722 00723 // ###################################################################### 00724 Image<float> DotStimuli::getRotationDotStimuli(uint step) 00725 { 00726 Image<byte> temp(itsDims, ZEROS); 00727 //uint width = itsDims.w(); 00728 //uint height = itsDims.h(); 00729 00730 LINFO("Rotation Motion: FIXXX: NOT YET IMPLEMENTED"); 00731 00732 return temp; 00733 } 00734 00735 // ###################################################################### 00736 /* So things look consistent in everyone's emacs... */ 00737 /* Local Variables: */ 00738 /* indent-tabs-mode: nil */ 00739 /* End: */ 00740 00741 #endif // TRANSPORT_RANDOMINPUT_C_DEFINED