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 #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
00050
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),
00083
00084
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
00102
00103
00104
00105 LINFO("options: %s", options.c_str());
00106 if (options.size() == 0) return;
00107
00108
00109
00110
00111 std::string rops = options;
00112 std::string::size_type fcpos = rops.find_first_of(',');
00113
00114
00115
00116
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
00134
00135
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
00148 fcpos = rops.find_first_of(',');
00149
00150
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
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
00171 setConfigAsymmetry(params, 2);
00172 else
00173 if(!op.compare("AsymmetrySlow"))
00174
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
00245 }
00246 else if(mode == 1 || mode == 3)
00247 {
00248 itsSingleDotDx = 1.0;
00249 itsSingleDotDy = 0.0;
00250 LINFO("Asymmetry Motion Slow");
00251
00252
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
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
00290 fcmpos = rops.find_first_of(',');
00291
00292
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
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
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
00387
00388
00389 return temp;
00390 }
00391
00392
00393 Image<float> DotStimuli::getSingleDotStimuli(uint step)
00394 {
00395
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,
00418 height * double(rand())/(RAND_MAX + 1.0));
00419 }
00420
00421
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
00432
00433 return temp;
00434 }
00435
00436
00437 Image<float> DotStimuli::getPlanarDotStimuli(uint step)
00438 {
00439
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
00455
00456 uint sideLength = SIDE_LENGTH;
00457 float orgDotSize = 1.0;
00458
00459
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
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
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
00501
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
00516
00517 uint dotNum = DOT_NUM;
00518
00519 float orgDotSize = 1.0;
00520
00521
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
00535 for(uint i = 0; i < dotNum; i++)
00536 {
00537
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
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
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
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
00590
00591 float dotOrgDSize = DOT_ORG_DSIZE;
00592
00593
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
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
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
00621
00622
00623 itsFoeDotSizes[i] = orgDotSize;
00624 }
00625 }
00626
00627
00628 for(uint i = 0; i < DOT_NUM; i++)
00629 {
00630
00631
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
00640 itsFoeDotSizes[i] = orgDotSize;
00641 }
00642 }
00643
00644
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
00656 else
00657 {
00658 if(step == 0)
00659 {
00660 itsFoeDotSizes[i] = dotOrgDSize * dist;
00661 }
00662 else
00663 {
00664
00665 if(itsFoeDotSizes[i] < ABS_MAX_DSIZE)
00666 {
00667 itsFoeDotSizes[i] = (1.0 + DOT_DSIZE) *
00668 dotOrgDSize * dist;
00669 }
00670
00671 }
00672 }
00673 }
00674 else if(itsFoeHaveTempSGrad && !itsFoeHaveSpatSGrad)
00675 {
00676
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
00687 }
00688
00689
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
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
00707 for(uint i = 0; i < DOT_NUM; i++)
00708 {
00709
00710
00711 drawDisk(temp,Point2D<int>(itsFoeDots[i].i,
00712 itsFoeDots[i].j),itsFoeDotSizes[i],
00713 byte(255));
00714
00715 }
00716
00717
00718
00719
00720 return temp;
00721 }
00722
00723
00724 Image<float> DotStimuli::getRotationDotStimuli(uint step)
00725 {
00726 Image<byte> temp(itsDims, ZEROS);
00727
00728
00729
00730 LINFO("Rotation Motion: FIXXX: NOT YET IMPLEMENTED");
00731
00732 return temp;
00733 }
00734
00735
00736
00737
00738
00739
00740
00741 #endif // TRANSPORT_RANDOMINPUT_C_DEFINED