00001 /*!@file AppPsycho/gaborSearch.C */ 00002 // //////////////////////////////////////////////////////////////////// // 00003 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00004 // University of Southern California (USC) and the iLab at USC. // 00005 // See http://iLab.usc.edu for information about this project. // 00006 // //////////////////////////////////////////////////////////////////// // 00007 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00008 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00009 // in Visual Environments, and Applications'' by Christof Koch and // 00010 // Laurent Itti, California Institute of Technology, 2001 (patent // 00011 // pending; application number 09/912,225 filed July 23, 2001; see // 00012 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00013 // //////////////////////////////////////////////////////////////////// // 00014 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00015 // // 00016 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00017 // redistribute it and/or modify it under the terms of the GNU General // 00018 // Public License as published by the Free Software Foundation; either // 00019 // version 2 of the License, or (at your option) any later version. // 00020 // // 00021 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00022 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00023 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00024 // PURPOSE. See the GNU General Public License for more details. // 00025 // // 00026 // You should have received a copy of the GNU General Public License // 00027 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00028 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00029 // Boston, MA 02111-1307 USA. // 00030 // //////////////////////////////////////////////////////////////////// // 00031 // 00032 // Primary maintainer for this file: Farhan Baluch <fbaluch@usc.edu> 00033 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/AppPsycho/gaborSearch.C $ 00034 // $Id: gaborSearch.C 11629 2009-08-28 01:20:43Z elno $ 00035 // 00036 00037 //generate random search arrays of colored gabor patches using the gaborfilterRGB function 00038 00039 #include "Component/ModelManager.H" 00040 #include "GUI/XWinManaged.H" 00041 #include "Image/CutPaste.H" 00042 #include "Image/DrawOps.H" 00043 #include "Image/FourierEngine.H" 00044 #include "Image/Image.H" 00045 #include "Image/Kernels.H" // for gaborFilter() 00046 #include "Image/MathOps.H" 00047 #include "Image/ShapeOps.H" 00048 #include "Image/Transforms.H" 00049 #include "Raster/PngWriter.H" 00050 #include "Raster/Raster.H" 00051 #include "Util/FileUtil.H" 00052 #include "Util/log.H" 00053 #include <stdio.h> 00054 #include <algorithm> 00055 #include <time.h> 00056 00057 typedef std::complex<float> complexf; 00058 00059 //! Return a noise added version of inputImg 00060 Image<PixRGB<byte> > addNoise(const Image<PixRGB<byte> >& inputImg, int beta, float blendFactor, double *meanGray) 00061 { 00062 00063 //beta = 2 for random noise 00064 //beta = -2 pink(1/f) noise 00065 //beta = -4 brown noise 00066 00067 bool owned; 00068 FILE* x = stdOutputFileOpen("testnoise",&owned); 00069 FILE* y = stdOutputFileOpen("testnoise_v",&owned); 00070 Image< PixRGB<byte> > theInputImg = inputImg; 00071 int inputW = theInputImg.getWidth(), inputH = theInputImg.getHeight(), squareDim; 00072 LINFO("input image inputW = %d h = %d",inputW,inputH); 00073 complexf il(0.0, 1.0); 00074 00075 if(inputW > inputH) 00076 squareDim = inputW; 00077 else 00078 squareDim = inputH; 00079 00080 std::vector<float> u(squareDim*squareDim), v(squareDim*squareDim), spectrum(squareDim*squareDim),phi(squareDim*squareDim), resultVec(squareDim*squareDim); 00081 std::vector<complexf> sfRoot(squareDim*squareDim), cosPart(squareDim*squareDim), sinPart(squareDim*squareDim), cmplxResult(squareDim*squareDim); 00082 00083 Dims slightlyBigger ((squareDim*2)-1, squareDim); 00084 00085 FourierInvEngine<double> ieng(slightlyBigger); 00086 00087 int crnt = 0, v_cnt = 0; 00088 //create u and v vectors (matrix abstractions) where v = transpose of u 00089 00090 for(int i=0; i < squareDim/2; i++) 00091 { 00092 u[i] = i+1; 00093 crnt = crnt + 1; 00094 } 00095 00096 00097 for(int j = - squareDim/2; j < 0; j++) 00098 u[crnt++] = j; 00099 00100 for(int i=1; i<squareDim; i++) 00101 for(int j=0; j<squareDim; j++) 00102 { 00103 u[crnt++] = u[j]; 00104 v[v_cnt] = u[i-1]; 00105 v_cnt = v_cnt + 1; 00106 } 00107 00108 00109 for(int j=0; j<squareDim ;j++) 00110 { 00111 v[v_cnt] = u[squareDim-1]; 00112 v_cnt = v_cnt + 1; 00113 } 00114 00115 Image<std::complex<float> > tempCmplxImg(squareDim,squareDim,NO_INIT); 00116 Image <complexf>::iterator cmplxItr =tempCmplxImg.beginw(); 00117 00118 00119 00120 complexf tempcf; 00121 for(int i=0; i< (squareDim*squareDim); i++) 00122 { 00123 spectrum[i] = pow((u[i]*u[i]) + (v[i]*v[i]),(beta/2)); 00124 srand(time(NULL) + 10*i); 00125 phi[i] = ((double)rand()/((double)(RAND_MAX)+(double)(1)) ); 00126 sfRoot[i] = complexf(pow(spectrum[i],0.5),0.0); 00127 cosPart[i] = complexf(cos(2*M_PI*phi[i]), 0.0); 00128 sinPart[i] = complexf(sin(2*M_PI*phi[i]), 0.0); 00129 tempcf = (cosPart[i] + il*sinPart[i]); 00130 cmplxResult[i] = sfRoot[i]*tempcf ; 00131 *cmplxItr++ = cmplxResult[i]; 00132 00133 } 00134 00135 00136 crnt =0; 00137 for(int i=0; i<squareDim; i++) 00138 { fprintf(x,"\n"); 00139 for(int j=0; j<squareDim; j++) 00140 { 00141 fprintf(x,"\tu[%d]=%f",crnt,u[crnt]); 00142 crnt = crnt +1; 00143 } 00144 } 00145 00146 00147 Image<double> res = ieng.ifft(tempCmplxImg); 00148 Image <double>::iterator apItr = res.beginw(); 00149 00150 double imgMax,imgMin; 00151 getMinMax(res,imgMin,imgMax); 00152 00153 apItr = res.beginw(); 00154 00155 for(int i=0; i<slightlyBigger.w()*slightlyBigger.h(); i++) 00156 { 00157 *apItr = ((*apItr - imgMin)/(imgMax - imgMin))*255; 00158 apItr++; 00159 } 00160 00161 apItr = res.beginw(); 00162 crnt = 0; 00163 for(int i=0; i<squareDim; i++) 00164 { fprintf(y,"\n"); 00165 for(int j=0; j<squareDim; j++) 00166 { 00167 fprintf(y,"\tv[%d]=%f",crnt,v[crnt]); 00168 crnt = crnt +1; 00169 } 00170 } 00171 00172 *meanGray = mean(res); 00173 Image<PixRGB<byte> > resPixRGB = res; 00174 00175 resPixRGB = rescale(resPixRGB,Dims (inputW,inputH)); 00176 00177 LINFO("input image w = %d h = %d",resPixRGB.getWidth(),resPixRGB.getHeight()); 00178 Image<PixRGB<byte> > resByte = theInputImg + resPixRGB*blendFactor; 00179 00180 fclose(x); 00181 fclose(y); 00182 return resByte; 00183 00184 } 00185 00186 00187 int main(int argc, char** argv) 00188 { 00189 00190 clock_t t1= clock(); 00191 //instantiate a model manager 00192 ModelManager manager("AppPsycho: gabor search stimuli"); 00193 00194 //dimensions of window 00195 Dims dims(1920,1080); 00196 00197 float stddev = 150.0; 00198 float freq = 5.0; 00199 float theta1 = 10; 00200 float hueShift= 5.0; 00201 float f,t,h; 00202 int gaborSize = 240; 00203 int n_gabors_w = dims.w()/gaborSize; 00204 int n_gabors_h = dims.h()/gaborSize; 00205 int totalGabors = n_gabors_w * n_gabors_h; 00206 char filename[255],fname[255]; 00207 00208 Image<PixRGB<byte> > dispImg(1280,720,NO_INIT); 00209 00210 if (manager.parseCommandLine(argc, argv,"<name>", 1, 1) == false) 00211 return(1); 00212 00213 manager.start(); 00214 00215 // get command line parameters 00216 sscanf(argv[1],"%s",fname); 00217 00218 sprintf(filename, "/lab/elno/research/exp1/spec/%sSPEC.dat",fname); 00219 FILE* specFile = fopen(filename, "w+"); 00220 if(specFile==0) 00221 LFATAL("couldnt open file:%s", filename); 00222 00223 fprintf(specFile,"stddev = %g; freq = %g; theta = %g; hueShift = %g",stddev,freq,theta1,hueShift); 00224 00225 //make a 2d vector of images// 00226 00227 std::vector< Image<PixRGB<byte> > > ivector(totalGabors + 1); 00228 std::vector< Image<PixRGB<byte> > > constructArray(totalGabors + 1); 00229 std::vector<Point2D<int> > gaborItems(totalGabors + 1); //vector to hold xy coordinates of the gabor Patches 00230 std::vector<Point2D<int> > randPos(totalGabors + 1); //vector to hold xy coordinates of the gabor Patches 00231 std::vector<int> used (totalGabors + 1); 00232 Dims standarddims(gaborSize,gaborSize); 00233 00234 srand(time(NULL)); 00235 //lets create some random positions 00236 int cnt =1; 00237 int yOffset =50; //yOffset required to compensate for the gaborSize/2 freespace 00238 for(int j = 1; j <= n_gabors_h; j++) 00239 for (int i = 1; i <= n_gabors_w; i++) 00240 { 00241 if(i>1 && i<n_gabors_w-1 && j>1 && j<n_gabors_h-1) 00242 randPos[cnt] = Point2D<int>((i*gaborSize-gaborSize) + 00243 (rand()*10)%(75),(j*gaborSize-gaborSize) + (rand()*10)%(75) + yOffset); 00244 else 00245 randPos[cnt] = Point2D<int>(i*gaborSize-gaborSize,j*gaborSize-gaborSize + yOffset); 00246 cnt++; 00247 } 00248 00249 00250 //create gabor patches and assign pseudorandom xy positions. 00251 00252 std::vector<int>::iterator result; 00253 srand(time(NULL)); 00254 int randIndex = rand() % totalGabors + 1; 00255 used.push_back(randIndex); 00256 result = used.end(); 00257 00258 00259 cnt=1; 00260 for(int j = 1; j <= n_gabors_h; j++) 00261 for (int i = 1; i <= n_gabors_w; i++) 00262 { 00263 00264 //frequencies can vary between 0.0075 and 0.0225 (0.0065-0.0075, and 0.0225-0.0250 reserved for post-training testing) 00265 f = ((rand()*(float(225-75)/RAND_MAX)) + 75)/10000; 00266 //orientation can vary between 15-75 deg (0-15 deg and 75-90 reserved for post-training testing) 00267 t = (rand()*(float(155-25)/RAND_MAX)) + 25; 00268 //hue shifts can vary between 0-360 00269 h = (rand()*(((float)360/RAND_MAX))); 00270 00271 ivector[cnt] = gaborFilterRGB(stddev, f,t,h); 00272 ivector[cnt] = rescale(ivector[cnt],standarddims); 00273 00274 while(result!=used.end()) 00275 { 00276 srand(time(NULL)); 00277 randIndex = rand() % totalGabors + 1; 00278 result = find(used.begin(),used.end(),randIndex); 00279 } 00280 00281 used.push_back(randIndex); 00282 gaborItems[cnt] = randPos[randIndex]; 00283 fprintf(specFile,"\n\nGabor %d",cnt); 00284 fprintf(specFile,"\nXpos\t%d\nYpos\t%d\nstddev\t%.0f\nHueShift\t%.0f\nfrequency\t%f\nOrientation\t%.0f", 00285 gaborItems[cnt].i,gaborItems[cnt].j,stddev,h,f*1000,t); 00286 cnt++; 00287 } 00288 00289 00290 //lets paste the gabors into one big image 00291 cnt=1; 00292 for(int j = 1; j <= n_gabors_h; j++) 00293 for (int i = 1; i <= n_gabors_w; i++) 00294 { 00295 constructArray[cnt] = Image<PixRGB<byte> >(1920,1080,NO_INIT); 00296 inplacePaste(constructArray[cnt],ivector[cnt],gaborItems[cnt]); 00297 cnt++; 00298 } 00299 00300 //lets put them together 00301 for (int i=1; i < cnt; i++) 00302 dispImg = dispImg + constructArray[i]*1; 00303 00304 //lets add some noise to the image and save it 00305 Image <PixRGB<byte> > myResult; 00306 double meanGray=0.0; 00307 myResult = addNoise(dispImg,-2,0.75, &meanGray); 00308 fprintf(specFile,"\nGray %f",meanGray); 00309 sprintf(filename, "/lab/elno/research/exp1/stim/%sARRAY.png",fname); 00310 Raster::WriteRGB(myResult,filename); 00311 00312 //create save the target image 00313 00314 Image<double> target(1920,1080,ZEROS); 00315 Image<PixRGB<byte> > targetBkg(1920,1080,ZEROS); 00316 00317 srand(time(NULL)); 00318 randIndex = rand() % totalGabors + 1; 00319 fprintf(specFile,"\n\ntarget %d",randIndex); 00320 00321 inplacePaste(targetBkg, ivector[randIndex],Point2D<int>((1920/2)-(gaborSize/2),(1080/2)-(gaborSize/2))); 00322 Image<double>::iterator aptr= target.beginw(); 00323 00324 while(aptr!=target.endw()) 00325 *aptr++ = meanGray; 00326 00327 Image<PixRGB<byte> > targetRGB = target; 00328 targetRGB = targetRGB + targetBkg; 00329 00330 char targetFileName[255]; 00331 sprintf(targetFileName, "/lab/elno/research/exp1/stim/%sTARGET.png",fname); 00332 Raster::WriteRGB(targetRGB,targetFileName); 00333 00334 //create the screen for reporting position of target gabor 00335 00336 Image<PixRGB<byte> > reportDot(1920,1080,ZEROS); 00337 reportDot = target; 00338 00339 for(int i=1;i<=totalGabors;i++) 00340 { 00341 // drawDisk(reportDot, gaborItems[i]+(gaborSize/2), 10,PixRGB<byte>(255,255,255)); 00342 writeText(reportDot, gaborItems[i]+(gaborSize/2)-10, sformat("%d",i).c_str(), 00343 PixRGB<byte>(0,0,0),PixRGB<byte>(0),SimpleFont::FIXED(12) ,true); 00344 } 00345 00346 char reportDotFile[255]; 00347 sprintf(reportDotFile, "/lab/elno/research/exp1/stim/%sREPORT.png",fname); 00348 Raster::WriteRGB(reportDot, reportDotFile); 00349 00350 clock_t t2= clock(); 00351 LINFO("generated search array in %fs", double(t2-t1)/CLOCKS_PER_SEC); 00352 00353 fclose(specFile); 00354 //finish all 00355 manager.stop(); 00356 00357 00358 return 0; 00359 00360 } 00361 00362 // ###################################################################### 00363 /* So things look consistent in everyone's emacs... */ 00364 /* Local Variables: */ 00365 /* indent-tabs-mode: nil */ 00366 /* End: */