00001 /*!@file CINNIC/CINNIC2.C CINNIC2 classes */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: T Nathan Mundhenk <mundhenk@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/CINNIC/CINNIC2.C $ 00035 // $Id: CINNIC2.C 6191 2006-02-01 23:56:12Z rjpeters $ 00036 // 00037 00038 #include "CINNIC/CINNIC2.H" 00039 00040 #include "Image/ColorOps.H" 00041 #include "Image/FilterOps.H" 00042 #include "Image/MathOps.H" 00043 #include "Image/ShapeOps.H" 00044 00045 #include <cmath> 00046 00047 using std::vector; 00048 using std::string; 00049 00050 // ############################################################ 00051 // ############################################################ 00052 // ##### ---CINNIC2--- 00053 // ##### Contour Integration: 00054 // ##### T. Nathan Mundhenk nathan@mundhenk.com 00055 // ############################################################ 00056 // ############################################################ 00057 00058 //***************************************************************** 00059 CINNIC2_DEC 00060 CINNIC2_CLASS::CINNIC2() 00061 { 00062 CINuseFrameSeries = false; 00063 } 00064 00065 //***************************************************************** 00066 CINNIC2_DEC 00067 CINNIC2_CLASS::~CINNIC2() 00068 {} 00069 00070 //***************************************************************** 00071 CINNIC2_DEC 00072 void CINNIC2_CLASS::CINtoggleFrameSeries(bool toggle) 00073 { 00074 CINuseFrameSeries = toggle; 00075 } 00076 00077 //***************************************************************** 00078 CINNIC2_DEC 00079 void CINNIC2_CLASS::CINconfigLoad(readConfig &config) 00080 { 00081 00082 // Some of these do nothing, I am weeding them out as I can 00083 CINedgeAtten = (INT)config.getItemValueF("edgeAtten"); 00084 CINGnum = (INT)config.getItemValueF("Gnum"); 00085 CINlogto = config.getItemValueS("logOutDir"); 00086 CINsaveto = config.getItemValueS("imageOutDir"); 00087 CINlPass = (INT)config.getItemValueF("lPass"); 00088 CINgroupSize = (INT)config.getItemValueF("groupSize"); 00089 CINGroupTop = config.getItemValueF("GroupTop"); 00090 CINstoreArraySize = (INT)config.getItemValueF("storeArraySize"); 00091 CINscaleBias[0] = config.getItemValueF("scaleBias1"); 00092 CINscaleBias[1] = config.getItemValueF("scaleBias2"); 00093 CINscaleBias[2] = config.getItemValueF("scaleBias3"); 00094 CINscaleSize[0] = (INT)config.getItemValueF("scaleSize1"); 00095 CINscaleSize[1] = (INT)config.getItemValueF("scaleSize2"); 00096 CINscaleSize[2] = (INT)config.getItemValueF("scaleSize3"); 00097 CINbaseSize = (INT)config.getItemValueF("baseSize"); 00098 CINuseMaps = config.getItemValueB("useMaps"); 00099 } 00100 00101 //***************************************************************** 00102 //***************************************************************** 00103 // START HERE 00104 //***************************************************************** 00105 //***************************************************************** 00106 CINNIC2_DEC 00107 void CINNIC2_CLASS::CINrunSimpleImage( 00108 const ContourNeuronCreate<FLOAT> &NeuronTemplate, 00109 const char fileName[100], unsigned int frame, 00110 Image<byte> &input, 00111 readConfig &config) 00112 { 00113 CINframe = frame; 00114 LINFO("FRAME %d",CINframe); 00115 Timer tim; 00116 tim.reset(); 00117 int t1 = 0; 00118 int t2 = 0; 00119 int t3 = 0; 00120 int t0 = tim.get(); // to measure display time 00121 if(frame == 1) 00122 { 00123 LINFO("Read Config"); 00124 CINconfigLoad(config); 00125 t1 = tim.get(); 00126 t2 = t1 - t0; t3 = t2; 00127 LINFO("TIME: %d ms Slice: %d ms",t2,t3); 00128 00129 LINFO("Init CINNIC"); 00130 CINinitCINNIC(CINVFinput,config,input.getWidth(),input.getHeight()); 00131 t1 = tim.get(); 00132 t3 = t2; t2 = t1 - t0; t3 = t2 - t3; 00133 LINFO("TIME: %d ms Slice: %d ms",t2,t3); 00134 } 00135 00136 LINFO("Get Orient Filtered Image"); 00137 if(CINuseMaps == false) 00138 CINgetOrientFiltered(input); 00139 else 00140 CINgetOrientFilteredMap(input); 00141 t1 = tim.get(); 00142 t3 = t2; t2 = t1 - t0; t3 = t2 - t3; 00143 LINFO("TIME: %d ms Slice: %d ms",t2,t3); 00144 00145 LINFO("Get Scaled Images"); 00146 CINgetScaled(); 00147 t1 = tim.get(); 00148 t3 = t2; t2 = t1 - t0; t3 = t2 - t3; 00149 LINFO("TIME: %d ms Slice: %d ms",t2,t3); 00150 00151 if(frame == 1) 00152 { 00153 LINFO("Compute Groups"); 00154 CINcomputeGroups(CINVFinput); 00155 t1 = tim.get(); 00156 t3 = t2; t2 = t1 - t0; t3 = t2 - t3; 00157 LINFO("TIME: %d ms Slice: %d ms",t2,t3); 00158 } 00159 00160 LINFO("Run Image"); 00161 if(CINuseFrameSeries == false) 00162 CINrunImage(NeuronTemplate,CINVFinput,config,CINgroupTopVec); 00163 else 00164 CINrunImageFrames(NeuronTemplate,CINVFinput,config,CINgroupTopVec); 00165 t1 = tim.get(); 00166 t3 = t2; t2 = t1 - t0; t3 = t2 - t3; 00167 LINFO("TIME: %d ms Slice: %d ms",t2,t3); 00168 //CINgetResults(config); 00169 } 00170 00171 //***************************************************************** 00172 CINNIC2_DEC 00173 void CINNIC2_CLASS::CINgetOrientFiltered(Image<byte> &input) 00174 { 00175 CINorignalImageSizeX = input.getWidth(); 00176 CINorignalImageSizeY = input.getHeight(); 00177 Image<float> inputCopy = input; 00178 00179 while((inputCopy.getWidth() > CINbaseSize) || 00180 (inputCopy.getHeight() > CINbaseSize)) 00181 { 00182 inputCopy = decXY(inputCopy); 00183 } 00184 00185 LINFO("(1) Image resized via decimation to %d x %d", 00186 inputCopy.getWidth(),inputCopy.getHeight()); 00187 00188 Image<FLOAT> i2 = inputCopy; 00189 00190 if(CINlPass == 0) 00191 { 00192 i2 = lowPass9(i2); 00193 Raster::VisuFloat(i2, FLOAT_NORM_0_255, sformat("lowPass.out.pgm")); 00194 inputCopy -= i2; 00195 } 00196 else if(CINlPass == 1) 00197 { 00198 i2 = lowPass5(i2); 00199 Raster::VisuFloat(i2, FLOAT_NORM_0_255, sformat("lowPass.out.pgm")); 00200 inputCopy -= i2; 00201 } 00202 else if(CINlPass == 2) 00203 { 00204 i2 = lowPass3(i2); 00205 Raster::VisuFloat(i2, FLOAT_NORM_0_255, sformat("lowPass.out.pgm")); 00206 inputCopy -= i2; 00207 } 00208 00209 for(INT i = 0; i < CINorientations; i++) 00210 { 00211 const FLOAT mpi = M_PI / CINGnum; 00212 CINFinput[i] = orientedFilter(inputCopy,mpi,NeuralAngles[i]); 00213 inplaceAttenuateBorders(CINFinput[i], CINedgeAtten); 00214 } 00215 } 00216 //***************************************************************** 00217 CINNIC2_DEC 00218 void CINNIC2_CLASS::CINgetOrientFilteredMap(Image<byte> &input) 00219 { 00220 CINorignalImageSizeX = input.getWidth(); 00221 CINorignalImageSizeY = input.getHeight(); 00222 Image<FLOAT> inputCopy = input; 00223 00224 while((inputCopy.getWidth() > CINbaseSize) || 00225 (inputCopy.getHeight() > CINbaseSize)) 00226 { 00227 inputCopy = decXY(inputCopy); 00228 } 00229 00230 LINFO("(2) Image resized via decimation to %d x %d", 00231 inputCopy.getWidth(),inputCopy.getHeight()); 00232 00233 if(CINframe == 1) 00234 { 00235 readMatrix rm("lowPassKernel.mat"); 00236 rm.echoMatrix(); 00237 CINcMap.CMsmallNumber = 1.1F; 00238 CINcMap.CMinitVecSize = 1; 00239 CINcMap.CMkernel = rm.returnMatrixAsImage(); 00240 CINcMap.CMorigImage = inputCopy; 00241 computeConvolutionMaps(CINcMap); 00242 } 00243 00244 CINcMap.CMcopyImage(inputCopy); 00245 //Raster::Visu(CINcMap.CMstaticImage, true, false, 00246 // sformat("staticImage.pgm")); 00247 Image<FLOAT> i2 = convolveWithMaps(CINcMap); 00248 //Raster::VisuGray(i2, sformat("lowPassImage.%06d.pgm",CINframe)); 00249 inputCopy -= i2; 00250 00251 for(INT i = 0; i < CINorientations; i++) 00252 { 00253 const FLOAT mpi = M_PI / CINGnum; 00254 CINFinput[i] = orientedFilter(inputCopy,mpi,NeuralAngles[i]); 00255 inplaceAttenuateBorders(CINFinput[i], CINedgeAtten); 00256 } 00257 } 00258 00259 //***************************************************************** 00260 CINNIC2_DEC 00261 void CINNIC2_CLASS::CINgetScaled() 00262 { 00263 for(INT i = 0; i < CINorientations; i++) 00264 { 00265 // resize images INTo different scales 00266 00267 INT WHold, HHold; 00268 for(INT s = 0; s < CINscales; s++) 00269 { 00270 if(CINFinput[i].getWidth() > CINFinput[i].getHeight()) 00271 { 00272 const FLOAT ratio = 00273 ((float)CINscaleSize[s]/(float)CINFinput[i].getWidth()); 00274 WHold = CINscaleSize[s]; 00275 HHold = (int)(CINFinput[i].getHeight() * ratio); 00276 } 00277 else 00278 { 00279 const FLOAT ratio = 00280 ((float)CINscaleSize[s]/(float)CINFinput[i].getHeight()); 00281 HHold = CINscaleSize[s]; 00282 WHold = (int)(CINFinput[i].getWidth() * ratio); 00283 } 00284 //CINVFinput[s][i] = CINFinput[i]; 00285 //LINFO("Image Scale %d %d", WHold, HHold); 00286 CINVFinput[s][i] = rescale(CINFinput[i], WHold,HHold); 00287 //uncomment this line to see all scale maps 00288 //Raster::VisuFloat(CINVFinput[s][i], FLOAT_NORM_0_255, 00289 // sformat("image.%f.%d.%06d.pgm",NeuralAngles[i],s,CINframe)); 00290 } 00291 } 00292 } 00293 00294 //***************************************************************** 00295 CINNIC2_DEC 00296 void CINNIC2_CLASS::CINinitCINNIC(const std::vector< std::vector<Image<FLOAT> > > &input, 00297 readConfig &config, 00298 const INT sizeX, 00299 const INT sizeY) 00300 { 00301 Image<FLOAT> blankImage; 00302 Image<FLOAT> foo(sizeX,sizeY,ZEROS); 00303 00304 //! resize and create contourRun2 for scales 00305 contourRun2<CINkernelSize,CINscales, 00306 CINorientations,CINiterations, 00307 FLOAT,INT> cont; 00308 00309 CINcontourRun.resize(CINscales,cont); 00310 00311 // Resize and filter image INTo oriented images 00312 CINFinput.resize(AnglesUsed,blankImage); 00313 CINVFinput.resize(CINscales,CINFinput); 00314 00315 CINresults.resize(CINiterations,blankImage); 00316 CINIresults.resize(CINscales,CINresults); 00317 00318 CINgroup.resize(CINscales,foo); 00319 CINgroupCount.resize(CINscales); 00320 CINgroupTopVec.resize(CINscales); 00321 //CINcontourRun.resize(CINscales); 00322 00323 CINcombinedSalMap = Image<byte>(sizeX,sizeY,ZEROS); 00324 }; 00325 00326 //***************************************************************** 00327 CINNIC2_DEC 00328 void CINNIC2_CLASS::CINcomputeGroups( 00329 const std::vector< std::vector<Image<FLOAT> > > &input) 00330 { 00331 INT GS = CINgroupSize; 00332 INT size = CINstoreArraySize; 00333 00334 // size and label groups 00335 00336 for(unsigned short s = 0; s < CINscales; s++) 00337 { 00338 size = size/4; 00339 if(s > 0) 00340 { 00341 GS = GS/2; 00342 } 00343 CINgroupCount[s] = 0; 00344 CINgroupTopVec[s] = CINGroupTop; 00345 CINGroupTop = CINGroupTop/4; 00346 00347 CINgroup[s] = Image<FLOAT>(input[s][0].getDims(),ZEROS); 00348 INT Hmod,Wmod; 00349 INT Wtemp = input[s][0].getWidth()/GS; 00350 if((Wmod = (input[s][0].getWidth()%GS)) != 0){Wtemp++;} 00351 INT Htemp = input[s][0].getHeight()/GS; 00352 if((Hmod = (input[s][0].getHeight()%GS)) != 0){Htemp++;} 00353 00354 for(INT x = 0; x < Wtemp; x++) 00355 { 00356 for(INT y = 0; y < Htemp; y++) 00357 { 00358 for(INT i = 0; i < GS; i++) 00359 { 00360 for(INT j = 0; j < GS; j++) 00361 { 00362 const INT intx = i+(GS*x); 00363 const INT inty = j+(GS*y); 00364 if( (intx < CINgroup[s].getWidth()) 00365 && (inty < CINgroup[s].getHeight())) 00366 { 00367 CINgroup[s].setVal(intx,inty, 00368 static_cast<FLOAT>(CINgroupCount[s])); 00369 } 00370 } 00371 } 00372 CINgroupCount[s]++; 00373 } 00374 } 00375 } 00376 }; 00377 00378 //***************************************************************** 00379 CINNIC2_DEC 00380 void CINNIC2_CLASS::CINrunImage( 00381 const ContourNeuronCreate<FLOAT> &NeuronTemplate, 00382 const std::vector< std::vector<Image<FLOAT> > > &input, 00383 readConfig &config, 00384 const std::vector<FLOAT> >V) 00385 { 00386 for(unsigned short t = 0; t < CINiterations; t++) 00387 { 00388 LINFO(">>>> ITERATION %d <<<<",t); 00389 CINresults[t].resize(CINVFinput[0][0].getWidth(), 00390 CINVFinput[0][0].getHeight(),true); 00391 for(unsigned short s = 0; s < CINscales; s++) 00392 { 00393 LINFO("SCALE %d",s); 00394 LINFO("%d x %d",CINVFinput[s][0].getWidth() 00395 ,CINVFinput[s][0].getHeight()); 00396 //LINFO("2 %d %d",CINgroup[s].getWidth(),CINgroup[s].getHeight()); 00397 //LINFO("3 %d",GTV[s]); 00398 CINcontourRun[s].CONTtoggleFrameSeries(CINuseFrameSeries); 00399 CINcontourRun[s].CONTcontourRunMain(CINVFinput[s],NeuronTemplate, 00400 config,CINgroup[s], 00401 CINgroupCount[s],t,GTV[s]); 00402 CINIresults[s][t] = CINcontourRun[s].CONTgetSMI(t); 00403 CINresults[t] += rescale(CINIresults[s][t] * CINscaleBias[s], 00404 CINresults[t].getWidth(), 00405 CINresults[t].getHeight()); 00406 } 00407 CINresults[t] /= CINscales; 00408 Image<float> resultsRescaled = rescale(CINresults[t], 00409 CINorignalImageSizeX, 00410 CINorignalImageSizeY); 00411 /* 00412 if(t < 10) 00413 Raster::Visu(resultsRescaled, 00414 sformat("results.00%d.out.pgm",t)); 00415 else if(t < 100) 00416 Raster::Visu(resultsRescaled, 00417 sformat("results.0%d.out.pgm",t)); 00418 else 00419 Raster::Visu(resultsRescaled, 00420 sformat("results.%d.out.pgm",t)); 00421 */ 00422 00423 Raster::VisuFloat(resultsRescaled, FLOAT_NORM_0_255, 00424 sformat("results.%06d.out.pgm",t)); 00425 } 00426 }; 00427 00428 00429 //***************************************************************** 00430 CINNIC2_DEC 00431 void CINNIC2_CLASS::CINrunImageFrames( 00432 const ContourNeuronCreate<FLOAT> &NeuronTemplate, 00433 const std::vector< std::vector<Image<FLOAT> > > &input, 00434 readConfig &config, 00435 const std::vector<FLOAT> >V) 00436 { 00437 INT iter = 0; 00438 if(CINframe == 1) 00439 { 00440 for(unsigned short t = 0; t < CINiterations; t++) 00441 { 00442 CINresults[t].resize(CINVFinput[0][0].getWidth(), 00443 CINVFinput[0][0].getHeight(),true); 00444 } 00445 } 00446 00447 for(unsigned short s = 0; s < CINscales; s++) 00448 { 00449 LINFO("SCALE %d",s); 00450 LINFO("%d x %d",CINVFinput[s][0].getWidth() 00451 ,CINVFinput[s][0].getHeight()); 00452 //LINFO("2 %d %d",CINgroup[s].getWidth(),CINgroup[s].getHeight()); 00453 //LINFO("3 %d",GTV[s]); 00454 CINcontourRun[s].CONTtoggleFrameSeries(true); 00455 CINcontourRun[s].CONTcontourRunFrames(CINVFinput[s],NeuronTemplate, 00456 config,CINgroup[s], 00457 CINgroupCount[s],CINframe,GTV[s]); 00458 LINFO("A"); 00459 iter = CINcontourRun[s].CONTgetCurrentIter(); 00460 LINFO("iter (next) %d",iter); 00461 CINIresults[s][iter] = CINcontourRun[s].CONTgetSMI(iter); 00462 LINFO("C"); 00463 CINresults[iter] += rescale(CINIresults[s][iter] * CINscaleBias[s], 00464 CINresults[iter].getWidth(), 00465 CINresults[iter].getHeight()); 00466 } 00467 LINFO("D"); 00468 CINresults[iter] /= CINscales; 00469 LINFO("E"); 00470 Image<float> resultsRescaled = rescale(CINresults[iter], 00471 CINorignalImageSizeX, 00472 CINorignalImageSizeY); 00473 /* 00474 if(t < 10) 00475 Raster::Visu(resultsRescaled, 00476 sformat("results.00%d.out.pgm",t)); 00477 else if(t < 100) 00478 Raster::Visu(resultsRescaled, 00479 sformat("results.0%d.out.pgm",t)); 00480 else 00481 Raster::Visu(resultsRescaled, 00482 sformat("results.%d.out.pgm",t)); 00483 */ 00484 LINFO("F"); 00485 Raster::VisuFloat(resultsRescaled, FLOAT_NORM_0_255, 00486 sformat("results.%06d.out.pgm",CINframe)); 00487 00488 }; 00489 00490 #undef CINNIC2_DEC 00491 #undef CINNIC2_CLASS 00492 00493 // explicit instantiations: 00494 template class CINNIC2<(unsigned short)12, (unsigned short)3, 00495 (unsigned short)4, (unsigned short)3, float, int>; 00496 00497 // ###################################################################### 00498 /* So things look consistent in everyone's emacs... */ 00499 /* Local Variables: */ 00500 /* indent-tabs-mode: nil */ 00501 /* End: */