StimMaker.C

Go to the documentation of this file.
00001 /*!@file Psycho/StimMaker.C make different kind of visual test stimuli
00002 */
00003 
00004 // //////////////////////////////////////////////////////////////////// //
00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00006 // 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: T. Nathan Mundhenk <mundhenk@usc.edu>
00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Psycho/StimMaker.C $
00036 // $Id: StimMaker.C 9412 2008-03-10 23:10:15Z farhan $
00037 //
00038 
00039 #ifndef STIM_MAKER_C_DEFINED
00040 #define STIM_MAKER_C_DEFINED
00041 
00042 #include "Psycho/StimMaker.H"
00043 
00044 StimMaker::StimMaker(const unsigned short ImageSizeX,
00045                      const unsigned short ImageSizeY,
00046                      const unsigned short frameCount,
00047                      const char bgColor)
00048 {
00049   itsFrameCount = frameCount;
00050   itsSizeX      = ImageSizeX;
00051   itsSizeY      = ImageSizeY;
00052   itsSlowRate   = SM_SLOW_RATE;
00053   itsFastRate   = SM_FAST_RATE;
00054   itsStopRate   = SM_STOP_RATE;
00055   itsRandomSeed = 0;
00056 
00057   itsBlack.set(0.0F,0.0F,0.0F);
00058   itsColorVec.resize(SM_COLORS,itsBlack);
00059 
00060   itsRed.set(255.0F,0.0F,0.0F);
00061   itsOrange.set(255.0F,128.0F,0.0F);
00062   itsYellow.set(255.0F,255.0F,0.0F);
00063   itsGreen.set(0.0F,255.0F,0.0F);
00064   itsBlue.set(0.0F,0.0F,255.0F);
00065   itsPurple.set(255.0F,0.0F,255.0F);
00066   itsWhite.set(255.0F,255.0F,255.0F);
00067 
00068   itsColorVec[0] = itsRed;
00069   itsColorVec[1] = itsOrange;
00070   itsColorVec[2] = itsYellow;
00071   itsColorVec[3] = itsGreen;
00072   itsColorVec[4] = itsBlue;
00073   itsColorVec[5] = itsPurple;
00074   itsColorVec[6] = itsWhite;
00075 
00076   itsGTtargetColor.set(255.0F,255.0F,255.0F);
00077   itsGTtargetColorPatch1.set(0.0F,128.0F,128.0F);
00078   itsGTtargetColorPatch2.set(0.0F,0.0F,255.0F);
00079   itsGTtargetColorPatch1off.set(128.0F,128.0F,0.0F);
00080   itsGTtargetColorPatch2off.set(255.0F,0.0F,0.0F);
00081   itsGTdistColor.set(128.0F,128.0F,128.0F);
00082 
00083   SM_init(bgColor);
00084 }
00085 
00086 /*****************************************************************************/
00087 
00088 StimMaker::~StimMaker()
00089 {}
00090 
00091 /*****************************************************************************/
00092 
00093 // reset the frames and back ground truth to the background color
00094 void StimMaker::SM_init(const char bgColor)
00095 {
00096   Image<PixRGB<float> > baseImage;
00097   baseImage.resize(itsSizeX,itsSizeY);
00098   itsFrames.resize(itsFrameCount, baseImage);
00099   std::vector<Image<PixRGB<float> > >::iterator framesIter = itsFrames.begin();
00100   while(framesIter != itsFrames.end())
00101   {
00102     Image<PixRGB<float> >::iterator imgIter = framesIter->beginw();
00103     while(imgIter != framesIter->endw())
00104     {
00105       *imgIter = itsColorVec[itsBGcolor+1];
00106       ++imgIter;
00107     }
00108     ++framesIter;
00109   }
00110 
00111   itsGroundTruth.resize(itsFrameCount, baseImage);
00112   framesIter = itsGroundTruth.begin();
00113   while(framesIter != itsGroundTruth.end())
00114   {
00115     Image<PixRGB<float> >::iterator imgIter = framesIter->beginw();
00116     while(imgIter != framesIter->endw())
00117     {
00118       *imgIter = itsBlack;
00119       ++imgIter;
00120     }
00121     ++framesIter;
00122   }
00123   SM_setStandardBackGround(bgColor);
00124 
00125 }
00126 
00127 /*****************************************************************************/
00128 
00129 // reset the frames and back ground truth to the background color
00130 void StimMaker::SM_setStandardBackGround(const unsigned char bgColor)
00131 {
00132   itsBGcolor         = bgColor;
00133   itsCustomBG        = itsColorVec[itsBGcolor];
00134   itsUseCustomColors = false;
00135 }
00136 
00137 /*****************************************************************************/
00138 
00139 void StimMaker::SM_overRideRates(const unsigned char slowRate,
00140                                  const unsigned char fastRate,
00141                                  const unsigned char stopRate)
00142 {
00143   itsSlowRate = slowRate;
00144   itsFastRate = fastRate;
00145   itsStopRate = stopRate;
00146 }
00147 
00148 /*****************************************************************************/
00149 
00150 void StimMaker::SM_setCustomColors(const PixRGB<float> BGcolor,
00151                                    const PixRGB<float> TargetColor,
00152                                    const PixRGB<float> DistColor)
00153 {
00154   itsCustomBG        = BGcolor;
00155   itsCustomTarg      = TargetColor;
00156   itsCustomDist      = DistColor;
00157   itsUseCustomColors = true;
00158 }
00159 
00160 /*****************************************************************************/
00161 inline ushort StimMaker::SM_speedUpCheck(ushort currBlinkRate,
00162                                          const ushort frame,
00163                                          const ushort changeFrame,
00164                                          const unsigned char stimRate,
00165                                          const unsigned char useSmoothRateChange) const
00166 {
00167   if(frame > changeFrame)
00168   {
00169     // we are slow, go fast
00170     if(stimRate == SM_SLOW_STIM)
00171     {
00172       if(currBlinkRate > itsFastRate)
00173       {
00174         if(useSmoothRateChange == SM_USE_SMOOTH_RATE_CHANGE)
00175           currBlinkRate -= SM_SMOOTH_ACCEL;
00176         else
00177           currBlinkRate = itsFastRate;
00178       }
00179       else
00180         if(currBlinkRate < itsFastRate)
00181           currBlinkRate = itsFastRate;
00182     }
00183     // we are steady, start into slow
00184     else if(stimRate == SM_NSPD_STIM)
00185     {
00186       if(currBlinkRate != itsSlowRate)
00187         currBlinkRate = itsSlowRate;
00188     }
00189   }
00190   return currBlinkRate;
00191 }
00192 
00193 /*****************************************************************************/
00194 inline ushort StimMaker::SM_speedDownCheck(ushort currBlinkRate,
00195                                            const ushort frame,
00196                                            const ushort changeFrame,
00197                                            const unsigned char stimRate,
00198                                            const unsigned char useSmoothRateChange) const
00199 {
00200   if(frame > changeFrame)
00201   {
00202     // we are fast, go slow
00203     if(stimRate == SM_FAST_STIM)
00204     {
00205       if(currBlinkRate < itsSlowRate)
00206       {
00207         if(useSmoothRateChange == SM_USE_SMOOTH_RATE_CHANGE)
00208           currBlinkRate += SM_SMOOTH_ACCEL;
00209         else
00210           currBlinkRate = itsSlowRate;
00211       }
00212       else
00213         if(currBlinkRate > itsSlowRate)
00214           currBlinkRate = itsSlowRate;
00215     }
00216     // we are slow, then stop
00217     else if(stimRate == SM_SLOW_STIM)
00218     {
00219       if(currBlinkRate != itsStopRate)
00220         currBlinkRate = itsStopRate;
00221     }
00222   }
00223   return currBlinkRate;
00224 
00225 }
00226 
00227 
00228 
00229 /*****************************************************************************/
00230 
00231 inline void StimMaker::SM_drawGroundTruth(const ushort frame,
00232                                           const unsigned char stimSizeX,
00233                                           const unsigned char stimSizeY,
00234                                           const ushort PosX,
00235                                           const ushort PosY,
00236                                           const bool targetOn)
00237 {
00238   const Point2D<int> P1(PosX,PosY);
00239   if(targetOn)
00240   {
00241     drawDisk(itsGroundTruth[frame],P1,stimSizeX,itsGTtargetColorPatch1);
00242     drawDisk(itsGroundTruth[frame],P1,stimSizeX/2,itsGTtargetColorPatch2);
00243 
00244   }
00245   else
00246   {
00247     drawDisk(itsGroundTruth[frame],P1,stimSizeX,itsGTtargetColorPatch1off);
00248     drawDisk(itsGroundTruth[frame],P1,stimSizeX/2,itsGTtargetColorPatch2off);
00249   }
00250 }
00251 
00252 /*****************************************************************************/
00253 
00254 inline void StimMaker::SM_drawSingleTarget(const ushort frame,
00255                                            const unsigned char stimShape,
00256                                            const unsigned char stimColor,
00257                                            const unsigned char stimSizeX,
00258                                            const unsigned char stimSizeY,
00259                                            const ushort PosX,
00260                                            const ushort PosY,
00261                                            const float stimOri,
00262                                            const float shapePositionJitter,
00263                                            const float shapeOrientationJitter,
00264                                            const bool target)
00265 {
00266   // Compute random shape if any
00267 
00268   unsigned char shape;
00269 
00270   if(stimShape == SM_STIM_RAND)
00271   {
00272     shape = 1 + (unsigned char)(SM_SHAPES*rand()/(RAND_MAX+1.0));
00273   }
00274   else
00275   {
00276     shape = stimShape;
00277   }
00278 
00279   // Compute random color if needed
00280   if(stimColor == SM_COLOR_RAND)
00281   {
00282     unsigned char color = 1 + (unsigned char)(SM_COLORS*rand()/(RAND_MAX+1.0));
00283     if(target)
00284       itsCustomTarg = itsColorVec[color];
00285     else
00286       itsCustomDist = itsColorVec[color];
00287   }
00288   else
00289   {
00290     if(stimColor != SM_COLOR_CUSTOM)
00291     {
00292       if(target)
00293         itsCustomTarg = itsColorVec[stimColor-1];
00294       else
00295         itsCustomDist = itsColorVec[stimColor-1];
00296     }
00297   }  // compute jitter if any
00298   float posJitterX,posJitterY,oriJitter;
00299 
00300   if(shapePositionJitter != 0.0F)
00301   {
00302     // some shapes are defined by a radius which is actaully
00303     // the diameter, as such we have to devide their size by 1/2
00304     float divider;
00305     if((stimShape == SM_STIM_DISK) ||
00306        (stimShape == SM_STIM_CROSS) ||
00307        (stimShape == SM_STIM_PATCH) ||
00308        (stimShape == SM_STIM_CIRC))
00309       divider = 4.0F;
00310     else
00311       divider = 2.0F;
00312     // jitter by as much as +/- .5 the size of the stim
00313     posJitterX = ((float)stimSizeX)*(shapePositionJitter*rand())
00314       /(RAND_MAX+1.0F) - stimSizeX/divider;
00315     posJitterY = ((float)stimSizeY)*(shapePositionJitter*rand())
00316       /(RAND_MAX+1.0F) - stimSizeY/divider;
00317   }
00318   else
00319   {
00320     posJitterX = 0.0F;
00321     posJitterY = 0.0F;
00322   }
00323 
00324   if(shapeOrientationJitter != 0.0F)
00325   {
00326     // jitter by as much as +/- Pi degrees
00327     oriJitter  = shapeOrientationJitter *
00328       (((2.0F*M_PI*rand())/(RAND_MAX+1.0F)) - M_PI);
00329   }
00330   else
00331   {
00332     oriJitter = 0.0F;
00333   }
00334 
00335   const float newPosX = posJitterX + PosX;
00336   const float newPosY = posJitterY + PosY;
00337 
00338   const float newOri  = stimOri + oriJitter;
00339 
00340   // Draw Disk
00341   if(shape == SM_STIM_DISK)
00342   {
00343     if(stimSizeX != stimSizeY)
00344       LINFO("WARNING: Disk size X and Y should be the same! Using X size.");
00345     if(stimOri != 0.0F)
00346       LINFO("WARNING: Disk cannot have orientation! Ignoring.");
00347     const Point2D<int> center((int)round(newPosX),(int)round(newPosY));
00348     if(target)
00349     {
00350       drawDisk(itsFrames[frame],center,stimSizeX/2,itsCustomTarg);
00351       drawDisk(itsGroundTruth[frame],center,stimSizeX/2,itsGTtargetColor);
00352     }
00353     else
00354     {
00355       drawDisk(itsFrames[frame],center,stimSizeX/2,itsCustomDist);
00356       drawDisk(itsGroundTruth[frame],center,stimSizeX/2,itsGTdistColor);
00357     }
00358   }
00359   // Draw Rect
00360   else if(shape == SM_STIM_RECT)
00361   {
00362     const int coordX1 = (int)floor(newPosX + (float)stimSizeX/2.0F);
00363     const int coordX2 = (int)floor(newPosX - (float)stimSizeX/2.0F);
00364     const int coordY1 = (int)floor(newPosY + (float)stimSizeY/2.0F);
00365     const int coordY2 = (int)floor(newPosY - (float)stimSizeY/2.0F);
00366     Rectangle rect = Rectangle::tlbrI(coordY2,coordX2,coordY1,coordX1);
00367 
00368     if(target)
00369     {
00370       drawRectOR(itsFrames[frame],rect,itsCustomTarg,2,newOri);
00371       drawRectOR(itsGroundTruth[frame],rect,itsGTtargetColor,2,newOri);
00372     }
00373     else
00374     {
00375       drawRectOR(itsFrames[frame],rect,itsCustomDist,2,newOri);
00376       drawRectOR(itsGroundTruth[frame],rect,itsGTdistColor,2,newOri);
00377     }
00378   }
00379   // Draw Line
00380   else if(shape == SM_STIM_LINE)
00381   {
00382     if(stimSizeX != stimSizeY)
00383       LINFO("WARNING: Line size X and Y should be the same! Using X size.");
00384     const float newX = stimSizeX/2 * sin(newOri);
00385     const float newY = stimSizeX/2 * cos(newOri);
00386 
00387     const int coordX1 = (int)floor(newPosX + newX);
00388     const int coordX2 = (int)floor(newPosX - newX);
00389     const int coordY1 = (int)floor(newPosY + newY);
00390     const int coordY2 = (int)floor(newPosY - newY);
00391     const Point2D<int> P1(coordX1,coordY1);
00392     const Point2D<int> P2(coordX2,coordY2);
00393 
00394     if(target)
00395     {
00396       drawLine(itsFrames[frame],P1,P2,itsCustomTarg,2);
00397       drawLine(itsGroundTruth[frame],P1,P2,itsGTtargetColor,2);
00398     }
00399     else
00400     {
00401       drawLine(itsFrames[frame],P1,P2,itsCustomDist,2);
00402       drawLine(itsGroundTruth[frame],P1,P2,itsGTdistColor,2);
00403     }
00404   }
00405   // Draw Cross
00406   else if(shape == SM_STIM_CROSS)
00407   {
00408     if(stimSizeX != stimSizeY)
00409       LINFO("WARNING: Cross size X and Y should be the same! Using X size.");
00410     const Point2D<int> P1((int)floor(newPosX),(int)floor(newPosY));
00411     if(target)
00412     {
00413       drawCrossOR(itsFrames[frame],P1,itsCustomTarg,stimSizeX/2,2,newOri);
00414       drawCrossOR(itsGroundTruth[frame],P1,itsGTtargetColor,stimSizeX/2,2,newOri);
00415     }
00416     else
00417     {
00418       drawCrossOR(itsFrames[frame],P1,itsCustomDist,stimSizeX/2,2,newOri);
00419       drawCrossOR(itsGroundTruth[frame],P1,itsGTdistColor,stimSizeX/2,2,newOri);
00420     }
00421   }
00422   // Draw Patch
00423   else if(shape == SM_STIM_PATCH)
00424   {
00425     if(stimOri != 0.0F)
00426       LINFO("WARNING: Patch cannot have orientation! Net yet supported. Ignoring.");
00427     if(stimSizeX != stimSizeY)
00428       LINFO("WARNING: Patch size X and Y should be the same! Using X size.");
00429     const Point2D<int> P1((int)floor(newPosX),(int)floor(newPosY));
00430     if(target)
00431     {
00432       drawPatch(itsFrames[frame],P1,stimSizeX/2,itsCustomTarg);
00433       drawPatch(itsGroundTruth[frame],P1,stimSizeX/2,itsGTtargetColor);
00434     }
00435     else
00436     {
00437       drawPatch(itsFrames[frame],P1,stimSizeX/2,itsCustomDist);
00438       drawPatch(itsGroundTruth[frame],P1,stimSizeX/2,itsGTdistColor);
00439     }
00440   }
00441   // Draw Arrow
00442   else if(shape == SM_STIM_ARROW)
00443   {
00444     if(stimSizeX != stimSizeY)
00445       LINFO("WARNING: Arrow size X and Y should be the same! Using X size.");
00446     const float newX = stimSizeX/2 * sin(newOri);
00447     const float newY = stimSizeX/2 * cos(newOri);
00448 
00449     const int coordX1 = (int)floor(newPosX + newX);
00450     const int coordX2 = (int)floor(newPosX - newX);
00451     const int coordY1 = (int)floor(newPosY + newY);
00452     const int coordY2 = (int)floor(newPosY - newY);
00453     const Point2D<int> P1(coordX1,coordY1);
00454     const Point2D<int> P2(coordX2,coordY2);
00455 
00456     if(target)
00457     {
00458       drawArrow(itsFrames[frame],P1,P2,itsCustomTarg,2);
00459       drawArrow(itsGroundTruth[frame],P1,P2,itsGTtargetColor,2);
00460     }
00461     else
00462     {
00463       drawArrow(itsFrames[frame],P1,P2,itsCustomDist,2);
00464       drawArrow(itsGroundTruth[frame],P1,P2,itsGTdistColor,2);
00465     }
00466   }
00467   // Draw Circle
00468   else if(shape == SM_STIM_CIRC)
00469   {
00470     if(stimSizeX != stimSizeY)
00471       LINFO("WARNING: Circle size X and Y should be the same! Using X size.");
00472     if(stimOri != 0.0F)
00473       LINFO("WARNING: Circle cannot have orientation! Ignoring.");
00474 
00475     const Point2D<int> center((int)round(newPosX),(int)round(newPosY));
00476     if(target)
00477     {
00478       drawCircle(itsFrames[frame],center,stimSizeX/2,itsCustomTarg);
00479       drawCircle(itsGroundTruth[frame],center,stimSizeX/2,itsGTtargetColor);
00480     }
00481     else
00482     {
00483       drawCircle(itsFrames[frame],center,stimSizeX/2,itsCustomDist);
00484       drawCircle(itsGroundTruth[frame],center,stimSizeX/2,itsGTdistColor);
00485     }
00486   }
00487   else
00488   {
00489     LFATAL("StimMaker tried to draw an unlisted shape %d. See list in StimMaker.H",shape);
00490   }
00491 }
00492 
00493 /*****************************************************************************/
00494 
00495 void StimMaker::SM_makeUniformStim(const StimMakerParam &stim)
00496 {
00497   itsRandomSeed = stim.SMP_randomSeed;
00498   // set the random seed so we can mix it up a little
00499   srand(itsRandomSeed);
00500   LINFO("Setting up stim params");
00501   // go through each frame
00502   uint frame = 0;
00503   // figure out where to place distractors
00504   const float divX     = ceil((float)itsSizeX/(float)stim.SMP_distPerRow);
00505   const float divY     = ceil((float)itsSizeY/(float)stim.SMP_distPerCol);
00506   const float startx   = round(divX/2);
00507   const float starty   = round(divY/2);
00508   const uint movieHalf = (uint)round((float)itsFrameCount/2.0F);
00509   const uint fastBlink = itsFastRate;
00510   const uint slowBlink = itsSlowRate;
00511 
00512   uint targBlinkRate;
00513   uint distBlinkRate;
00514 
00515   // slighly randomize the change time
00516   const uint changeFrame = (uint)floor((movieHalf/2)+(movieHalf*rand()/(RAND_MAX+1.0)));
00517 
00518   // define the speed at which the target blinks
00519   if(stim.SMP_targetRate == SM_FAST_STIM)
00520     targBlinkRate = fastBlink;
00521   else if(stim.SMP_targetRate == SM_SLOW_STIM)
00522     targBlinkRate = slowBlink;
00523   else
00524     targBlinkRate = 0;
00525 
00526   // define the speed at which the distractors blink
00527   if(stim.SMP_distRate == SM_FAST_STIM)
00528     distBlinkRate = fastBlink;
00529   else if(stim.SMP_distRate == SM_SLOW_STIM)
00530     distBlinkRate = slowBlink;
00531   else
00532     distBlinkRate = 0;
00533 
00534   //const float Randy = (1.0*rand()/(RAND_MAX+1.0));
00535 
00536   //float targAccelBase;
00537   //float distAccelBase;
00538 
00539   // Compute change rates as random over distractors or target
00540   /*
00541   if(targState > SM_STATE_STEADY)
00542   {
00543     targAccelBase = ((float)targBlinkRate/2.0F)*Randy;
00544   }
00545 
00546   if(distState > SM_STATE_STEADY)
00547   {
00548     distAccelBase = ((float)distBlinkRate/2.0F)*Randy;
00549   }
00550   */
00551 
00552   // allocate target
00553   uint currTargBlinkRate   = targBlinkRate;
00554   int currTargBlinkOffset  = 0;
00555   //uint currTargBlinkCount  = 0;
00556   uint currTargShape       = stim.SMP_targetShape;
00557   uint currTargColor       = stim.SMP_targetColor;
00558   uint currTargSizeX       = stim.SMP_targetSizeX;
00559   uint currTargSizeY       = stim.SMP_targetSizeY;
00560   bool currTargOn          = stim.SMP_targetOn;
00561 
00562   LINFO("Computing target values");
00563   // Start the target randomly?
00564   if(stim.SMP_useRandomStart == SM_USE_RANDOM_START)
00565   {
00566     const float distRand = (1.0*rand()/(RAND_MAX+1.0));
00567     currTargBlinkOffset = (uint)round((float)distBlinkRate*distRand);
00568     const float onRand = (1.0*rand()/(RAND_MAX+1.0));
00569     if(onRand > .5)
00570       currTargOn = true;
00571     else
00572       currTargOn = false;
00573   }
00574   // assign the target a random shape?
00575   if(stim.SMP_targetShape == SM_STIM_RAND)
00576   {
00577     const float distRand = 1.0F + (((float)(SM_SHAPES))*rand()/
00578                                       (RAND_MAX+1.0F));
00579     currTargShape = (uint)distRand;
00580   }
00581   // assign the target a random color?
00582   if(stim.SMP_targetColor == SM_COLOR_RAND)
00583   {
00584     const float distRand = 1.0F + (((float)(SM_COLORS-1.0F))*rand()/
00585                                       (RAND_MAX+1.0F));
00586     currTargColor = (uint)distRand;
00587   }
00588   // do we need to give a random size to the target?
00589   if(stim.SMP_targetSizeX == 0)
00590   {
00591     const float maxSizeX  = divX;
00592     const float distRandX = 1.0F + (((float)(maxSizeX-1.0F))*rand()/
00593                                        (RAND_MAX+1.0F));
00594     currTargSizeX = (uint)distRandX;
00595     const float maxSizeY  = divY;
00596     const float distRandY = 1.0F + (((float)(maxSizeY-1.0F))*rand()/
00597                                        (RAND_MAX+1.0F));
00598     currTargSizeY = (uint)distRandY;
00599   }
00600 
00601   LINFO("Setting up distractor vectors");
00602   // allocate vectors for distractors
00603   std::vector<ushort> distInit(stim.SMP_distPerCol,0);
00604   std::vector<int> distInitS(stim.SMP_distPerCol,0);
00605   std::vector<float> distInitF(stim.SMP_distPerCol,0);
00606 
00607   std::vector<std::vector<ushort> >
00608     currDistBlinkRate(stim.SMP_distPerRow,distInit);
00609   std::vector<std::vector<ushort> >
00610     currDistShape(stim.SMP_distPerRow,distInit);
00611   std::vector<std::vector<ushort> >
00612     currDistColor(stim.SMP_distPerRow,distInit);
00613   std::vector<std::vector<ushort> >
00614     currDistSizeX(stim.SMP_distPerRow,distInit);
00615   std::vector<std::vector<ushort> >
00616     currDistSizeY(stim.SMP_distPerRow,distInit);
00617   std::vector<std::vector<ushort> >
00618     currPosX(stim.SMP_distPerRow,distInit);
00619   std::vector<std::vector<ushort> >
00620     currPosY(stim.SMP_distPerRow,distInit);
00621 
00622   std::vector<std::vector<int> >
00623     currDistBlinkOffset(stim.SMP_distPerRow,distInitS);
00624 
00625   std::vector<std::vector<float> >
00626     currDistOrientation(stim.SMP_distPerRow,distInitF);
00627 
00628   std::vector<bool> distOnInit(stim.SMP_distPerCol,stim.SMP_distOn);
00629   std::vector<std::vector<bool> > currDistOn(stim.SMP_distPerRow,distOnInit);
00630 
00631   // (1) define the starting blink rate for each distractor
00632   // (2) define when its offset
00633   // (3) define its start state
00634   // (4) define shape
00635   // (5) define color
00636 
00637   LINFO("Setting up distractors");
00638   for(uint i = 0; i < stim.SMP_distPerRow; i++)
00639   {
00640     for(uint j = 0; j < stim.SMP_distPerCol; j++)
00641     {
00642       // determine start offset if random
00643       if(stim.SMP_useRandomStart == SM_USE_RANDOM_START)
00644       {
00645         const float distRand = (1.0F*rand()/(RAND_MAX+1.0));
00646         currDistBlinkOffset[i][j] = (uint)round((float)distBlinkRate*distRand);
00647         const float onRand = (1.0F*rand()/(RAND_MAX+1.0));
00648         if(onRand > 0.5F)
00649           currDistOn[i][j] = true;
00650         else
00651           currDistOn[i][j] = false;
00652       }
00653       else
00654       {
00655         currDistBlinkOffset[i][j] = 0;
00656       }
00657 
00658       // determine distractor shape if random
00659       if(stim.SMP_distShape == SM_STIM_RAND)
00660       {
00661         const float distRand = 1.0F + (((float)(SM_SHAPES))*rand()/
00662                                           (RAND_MAX+1.0F));
00663         currDistShape[i][j]  = (ushort)distRand;
00664       }
00665       else
00666       {
00667         currDistShape[i][j]  = stim.SMP_distShape;
00668       }
00669 
00670       // determine distractor color if random
00671       if(stim.SMP_distColor == SM_COLOR_RAND)
00672       {
00673         const float distRand = 1.0F + (((float)(SM_COLORS - 1.0F))*rand()/
00674                                        (RAND_MAX+1.0F));
00675 
00676         //std::cerr << ">>>>>NEW COLOR IS " << distRand << "\n";
00677         currDistColor[i][j]  = (ushort)distRand;
00678       }
00679       else
00680       {
00681         currDistColor[i][j] = stim.SMP_distColor;
00682       }
00683 
00684       // determine distractor size if random
00685       if(stim.SMP_distSizeX == 0)
00686       {
00687         const float maxSizeX  = divX;
00688         const float distRandX = 1.0F + (((float)(maxSizeX-1.0))*rand()/
00689                                           (RAND_MAX+1.0F));
00690         currDistSizeX[i][j]   = (ushort)distRandX;
00691         const float maxSizeY  = divY;
00692         const float distRandY = 1.0F + (((float)(maxSizeY-1.0))*rand()/
00693                                           (RAND_MAX+1.0F));
00694         currDistSizeY[i][j]   = (ushort)distRandY;
00695       }
00696       else
00697       {
00698         currDistSizeX[i][j]   = stim.SMP_distSizeX;
00699         currDistSizeY[i][j]   = stim.SMP_distSizeY;
00700       }
00701 
00702       currDistBlinkRate[i][j] = distBlinkRate;
00703 
00704       // determine if we need to jitter the position of the target
00705       if(stim.SMP_useHexagon == SM_USE_HEXAGON)
00706       {
00707         float newDiv = 0.0F;
00708         if(j%2 == 0)
00709           newDiv = divX/4;
00710         else
00711           newDiv = -1.0F*divX/4;
00712         // image pixel offset in X for target
00713         currPosX[i][j] = (uint)floor(newDiv + startx + i*divX);
00714         // image pixel offset in Y for target
00715         currPosY[i][j] = (uint)floor(starty + j*divY);
00716       }
00717       else
00718       {
00719         // image pixel offset in X for target
00720         currPosX[i][j] = (uint)floor(startx + i*divX);
00721         // image pixel offset in Y for target
00722         currPosY[i][j] = (uint)floor(starty + j*divY);
00723       }
00724       float posJitterX,posJitterY;
00725       if(stim.SMP_shapePositionJitterStatic != 0.0F)
00726       {
00727         float divider;
00728         if((j == stim.SMP_targetPosJ) && (i == stim.SMP_targetPosI))
00729         {
00730           if((currTargShape == SM_STIM_DISK)  ||
00731              (currTargShape == SM_STIM_CROSS) ||
00732              (currTargShape == SM_STIM_PATCH) ||
00733              (currTargShape == SM_STIM_CIRC))
00734             divider = 4.0F;
00735           else
00736             divider = 2.0F;
00737 
00738           posJitterX = ((float)stim.SMP_targetSizeX)
00739             *(stim.SMP_shapePositionJitterStatic*rand())
00740             /(RAND_MAX+1.0F) - stim.SMP_distSizeX/divider;
00741           posJitterY = ((float)stim.SMP_targetSizeY)
00742             *(stim.SMP_shapePositionJitterStatic*rand())
00743             /(RAND_MAX+1.0F) - stim.SMP_distSizeY/divider;
00744 
00745         }
00746         else
00747         {
00748           if((currDistShape[i][j] == SM_STIM_DISK)  ||
00749              (currDistShape[i][j] == SM_STIM_CROSS) ||
00750              (currDistShape[i][j] == SM_STIM_PATCH) ||
00751              (currDistShape[i][j] == SM_STIM_CIRC))
00752             divider = 4.0F;
00753           else
00754             divider = 2.0F;
00755 
00756 
00757           posJitterX = ((float)stim.SMP_targetSizeX)
00758             *(stim.SMP_shapePositionJitterStatic*rand())
00759             /(RAND_MAX+1.0F) - stim.SMP_distSizeX/divider;
00760           posJitterY = ((float)stim.SMP_targetSizeY)
00761             *(stim.SMP_shapePositionJitterStatic*rand())
00762             /(RAND_MAX+1.0F) - stim.SMP_distSizeY/divider;
00763         }
00764       }
00765       else
00766       {
00767         posJitterX = 0.0F;
00768         posJitterY = 0.0F;
00769       }
00770       currPosX[i][j] = (ushort)(round(posJitterX + currPosX[i][j]));
00771       currPosY[i][j] = (ushort)(round(posJitterY + currPosY[i][j]));
00772 
00773       // static jitter orientation if needed
00774       float oriJitter = 0.0F;
00775       if((j == stim.SMP_targetPosJ) && (i == stim.SMP_targetPosI))
00776       {
00777         if(stim.SMP_shapeOrientationJitterStatic != 0.0F)
00778         {
00779           oriJitter  = stim.SMP_shapeOrientationJitterStatic *
00780             (((2.0F*M_PI*rand())/(RAND_MAX+1.0F)) - M_PI);
00781         }
00782         currDistOrientation[i][j] = oriJitter + stim.SMP_targetOri;
00783       }
00784       else
00785       {
00786         if(stim.SMP_shapeOrientationJitterStatic != 0.0F)
00787         {
00788           oriJitter  = stim.SMP_shapeOrientationJitterStatic *
00789             (((2.0F*M_PI*rand())/(RAND_MAX+1.0F)) - M_PI);
00790         }
00791         currDistOrientation[i][j] = oriJitter + stim.SMP_distOri;
00792       }
00793     }
00794   }
00795 
00796   LINFO("Drawing stim images");
00797   std::vector<Image<PixRGB<float> > >::iterator framesIter = itsFrames.begin();
00798   while(framesIter != itsFrames.end())
00799   {
00800     // go over each stim
00801     // be sure not to write over the target
00802 
00803     for(uint i = 0; i < stim.SMP_distPerRow; i++)
00804     {
00805       for(uint j = 0; j < stim.SMP_distPerCol; j++)
00806 
00807       {
00808                //std::cerr << ".";
00809         // insert the target
00810         if((j == stim.SMP_targetPosJ) && (i == stim.SMP_targetPosI))
00811         {
00812           // is the target on or have no blink rate?
00813           if((currTargOn) || (currTargBlinkRate == 0))
00814           {
00815             SM_drawGroundTruth((ushort)frame,
00816                                (unsigned char)currTargSizeX,
00817                                (unsigned char)currTargSizeY,
00818                                (ushort)currPosX[i][j], (ushort)currPosY[i][j],
00819                                true);
00820             //std::cerr << "+";
00821             // draw the target on this image
00822 
00823             SM_drawSingleTarget((ushort)frame,
00824                                 (unsigned char)currTargShape,
00825                                 (unsigned char)currTargColor,
00826                                 (unsigned char)currTargSizeX,
00827                                 (unsigned char)currTargSizeY,
00828                                 (ushort)currPosX[i][j], (ushort)currPosY[i][j],
00829                                 currDistOrientation[i][j],
00830                                 stim.SMP_shapePositionJitter,
00831                                 stim.SMP_shapeOrientationJitter, true);
00832           }
00833           else
00834           {
00835             SM_drawGroundTruth((ushort)frame,
00836                                (unsigned char)currTargSizeX,
00837                                (unsigned char)currTargSizeY,
00838                                (ushort)currPosX[i][j], (ushort)currPosY[i][j],
00839                                false);
00840           }
00841 
00842           //std::cerr << "x";
00843 
00844           bool checkSpeed = false;
00845           if(currTargBlinkRate == 0)
00846             checkSpeed = true;
00847           else if(((frame+currTargBlinkOffset)
00848                    %currTargBlinkRate) == 0)
00849             checkSpeed = true;
00850 
00851           if(checkSpeed)
00852           {
00853             if(currTargBlinkRate != 0)
00854             {
00855               if(currTargOn)
00856                 currTargOn = false;
00857               else
00858                 currTargOn = true;
00859             }
00860             else
00861               currTargOn = true;
00862             // determin if we need to speed up the distractors
00863             // speed up or start (if possible)
00864             if(stim.SMP_targetState == SM_STATE_START)
00865             {
00866               const uint newRate = SM_speedUpCheck(
00867                                        currTargBlinkRate,
00868                                        frame,changeFrame,
00869                                        stim.SMP_targetRate,
00870                                        stim.SMP_useSmoothRateChange);
00871               if(newRate != currTargBlinkRate)
00872               {
00873                 currTargBlinkOffset = -1*frame;
00874                 currTargBlinkRate   = newRate;
00875               }
00876             }
00877             // determin if we need to slow down the distractors
00878             // slow down or stop (if possible)
00879             if(stim.SMP_targetState == SM_STATE_STOP)
00880             {
00881               const uint newRate = SM_speedDownCheck(
00882                                        currTargBlinkRate,
00883                                        frame,changeFrame,
00884                                        stim.SMP_targetRate,
00885                                        stim.SMP_useSmoothRateChange);
00886               if(newRate != currTargBlinkRate)
00887               {
00888                 currTargBlinkOffset = -1*frame;
00889                 currTargBlinkRate   = newRate;
00890               }
00891             }
00892           }
00893         }
00894         else
00895         {
00896           // is this target "on" in this frame
00897           // if the speed is set to zero, we are always "on"
00898           if((currDistOn[i][j]) || (currDistBlinkRate[i][j] == 0))
00899           {
00900             //std::cerr << "-";
00901             // draw the target on this image
00902             SM_drawSingleTarget((ushort)frame,
00903                                 (unsigned char)currDistShape[i][j],
00904                                 (unsigned char)currDistColor[i][j],
00905                                 (unsigned char)currDistSizeX[i][j],
00906                                 (unsigned char)currDistSizeY[i][j],
00907                                 (ushort)currPosX[i][j], (ushort)currPosY[i][j],
00908                                 currDistOrientation[i][j],
00909                                 stim.SMP_shapePositionJitter,
00910                                 stim.SMP_shapeOrientationJitter, false);
00911           }
00912           //std::cerr << "|";
00913           // turn target on or off at interval
00914           // If the current frame plus the offset is modulo 0 with the
00915           // rate of blink then turn it on or off
00916           /*
00917 =======
00918           bool checkSpeed = false;
00919           if(currTargBlinkRate == 0)
00920             checkSpeed = true;
00921           else if(((frame+currTargBlinkOffset)
00922                    %currTargBlinkRate) == 0)
00923             checkSpeed = true;
00924 >>>>>>> .r6413
00925 
00926           if(checkSpeed)
00927           {
00928             if(currTargBlinkRate != 0)
00929             {
00930               if(currTargOn)
00931                 currTargOn = false;
00932               else
00933                 currTargOn = true;
00934             }
00935             else
00936               currTargOn = true;
00937             // determin if we need to speed up the distractors
00938             // speed up or start (if possible)
00939             if(stim.SMP_targetState == SM_STATE_START)
00940             {
00941               const uint newRate = SM_speedUpCheck(
00942                                        currTargBlinkRate,
00943                                        frame,changeFrame,
00944                                        stim.SMP_targetRate,
00945                                        stim.SMP_useSmoothRateChange);
00946               if(newRate != currTargBlinkRate)
00947               {
00948                 currTargBlinkOffset = -1*frame;
00949                 currTargBlinkRate   = newRate;
00950               }
00951             }
00952             // determin if we need to slow down the distractors
00953             // slow down or stop (if possible)
00954             if(stim.SMP_targetState == SM_STATE_STOP)
00955             {
00956               const uint newRate = SM_speedDownCheck(
00957                                        currTargBlinkRate,
00958                                        frame,changeFrame,
00959                                        stim.SMP_targetRate,
00960                                        stim.SMP_useSmoothRateChange);
00961               if(newRate != currTargBlinkRate)
00962               {
00963                 currTargBlinkOffset = -1*frame;
00964                 currTargBlinkRate   = newRate;
00965               }
00966             }
00967           }
00968 
00969         }
00970         else
00971         {
00972           // is this target "on" in this frame
00973           // if the speed is set to zero, we are always "on"
00974           if((currDistOn[i][j]) || (currDistBlinkRate[i][j] == 0))
00975           {
00976             std::cerr << "-";
00977             // draw the target on this image
00978             SM_drawSingleTarget((ushort)frame,
00979                                 (unsigned char)currDistShape[i][j],
00980                                 (unsigned char)currDistColor[i][j],
00981                                 (unsigned char)currDistSizeX[i][j],
00982                                 (unsigned char)currDistSizeY[i][j],
00983                                 (ushort)currPosX[i][j], (ushort)currPosY[i][j],
00984                                 stim.SMP_distOri,
00985                                 stim.SMP_shapePositionJitter,
00986                                 stim.SMP_shapeOrientationJitter, false);
00987           }
00988           std::cerr << "|";
00989           */
00990           // turn target on or off at interval
00991           // If the current frame plus the offset is modulo 0 with the
00992           // rate of blink then turn it on or off
00993 
00994 
00995           bool checkSpeed = false;
00996           if(currDistBlinkRate[i][j] == 0)
00997             checkSpeed = true;
00998           else if(((frame+currDistBlinkOffset[i][j])
00999                    %currDistBlinkRate[i][j]) == 0)checkSpeed = true;
01000 
01001           if(checkSpeed)
01002           {
01003 
01004             if(currDistBlinkRate[i][j] != 0)
01005             {
01006 
01007               if(currDistOn[i][j])
01008                 currDistOn[i][j] = false;
01009               else
01010                 currDistOn[i][j] = true;
01011             }
01012             else
01013               currDistOn[i][j] = true;
01014             // determin if we need to speed up the distractors
01015             // speed up or start (if possible)
01016 
01017             if(stim.SMP_distState == SM_STATE_START)
01018             {
01019 
01020                const uint newRate = SM_speedUpCheck(
01021                                         currDistBlinkRate[i][j],
01022                                         frame,changeFrame,
01023                                         stim.SMP_distRate,
01024                                         stim.SMP_useSmoothRateChange);
01025               if(newRate != currDistBlinkRate[i][j])
01026               {
01027                   currDistBlinkOffset[i][j] = -1*frame;
01028                   currDistBlinkRate[i][j]   = newRate;
01029               }
01030             }
01031 
01032             // determin if we need to slow down the distractors
01033             // slow down or stop (if possible)
01034             if(stim.SMP_distState == SM_STATE_STOP)
01035             {
01036 
01037               const uint newRate = SM_speedDownCheck(
01038                                         currDistBlinkRate[i][j],
01039                                         frame,changeFrame,
01040                                         stim.SMP_distRate,
01041                                         stim.SMP_useSmoothRateChange);
01042               if(newRate != currDistBlinkRate[i][j])
01043               {
01044                 currDistBlinkOffset[i][j] = -1*frame;
01045                 currDistBlinkRate[i][j]   = newRate;
01046               }
01047             }
01048           }
01049         }
01050       }
01051     }
01052 
01053     frame++; ++framesIter;
01054     //std::cerr << "\n";
01055   }
01056   LINFO("Drawing complete");
01057 }
01058 
01059 /*****************************************************************************/
01060 
01061 std::vector<Image<PixRGB<float> > > StimMaker::SM_getStim() const
01062 {
01063   return itsFrames;
01064 }
01065 
01066 /*****************************************************************************/
01067 
01068 std::vector<Image<PixRGB<float> > > StimMaker::SM_getGroundTruth() const
01069 {
01070   return itsGroundTruth;
01071 }
01072 
01073 #endif // STIM_MAKER_H_DEFINED
01074 
01075 
01076 
01077 
Generated on Sun May 8 08:41:13 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3