00001 /*!@file VFAT/fzvision2.C simplified version of vision.C with feature analysis 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/VFAT/fzvision2.C $ 00036 // $Id: fzvision2.C 14376 2011-01-11 02:44:34Z pez $ 00037 // 00038 // ############################################################ 00039 // ############################################################ 00040 // ##### --- VFAT --- 00041 // ##### Vision Feature Analysis Tool: 00042 // ##### T. Nathan Mundhenk nathan@mundhenk.com 00043 // ##### Laurent Itti itti@pollux.usc.edu 00044 // ##### 00045 // ############################################################ 00046 // ############################################################ 00047 00048 //#include "saliency.H" 00049 #include "Component/ModelManager.H" 00050 #include "Media/FrameSeries.H" 00051 #include "GUI/XWindow.H" 00052 #include "Media/MediaSimEvents.H" 00053 #include "Neuro/StdBrain.H" 00054 #include "Neuro/NeuroSimEvents.H" 00055 #include "VFAT/featureClusterVision.H" 00056 #include "VFAT/segmentImageTrackMC2.H" 00057 #include "Simulation/SimEventQueueConfigurator.H" 00058 00059 // define standard deviation multiplier for simple tracker 00060 #define H1_STD 2.0F 00061 #define H2_STD 2.0F 00062 #define S_STD 2.0F 00063 #define V_STD 2.0F 00064 00065 // DV Size 00066 00067 #define IMAGE_SIZE_X 640 00068 #define IMAGE_SIZE_Y 480 00069 00070 #define GAMMA1 0 00071 #define GAMMA2 1 00072 #define GAMMA3 2 00073 00074 //#define SPATX 8 00075 //#define SPATY 9 00076 00077 #define MOTION 3 00078 //#define MOTION 0 00079 00080 #define HUE1 6 00081 //#define HUE1 3 00082 #define HUE2 7 00083 //#define HUE2 4 00084 #define SAT 4 00085 //#define SAT 1 00086 #define VALUE 5 00087 //#define VALUE 2 00088 00089 // Small NTSC Size 00090 00091 //#define IMAGE_SIZE_X 320 00092 //#define IMAGE_SIZE_Y 240 00093 00094 // maximum value currently is 6 00095 #define TRACKER_NUMBER 3 00096 #define USE_LOGS true 00097 #define SAVE_TRACK_DRAW true 00098 00099 00100 00101 00102 //! Basic entry and test binary to featureClusterVision 00103 00104 int main(const int argc, const char **argv) 00105 { 00106 MYLOGVERB = LOG_INFO; // suppress debug messages 00107 00108 bool use_logs = USE_LOGS; 00109 bool save_track_draw = SAVE_TRACK_DRAW; 00110 00111 // Instantiate a ModelManager: 00112 ModelManager manager("Attention Model"); 00113 00114 // Instantiate our various ModelComponents: 00115 nub::soft_ref<SimEventQueueConfigurator> 00116 seqc(new SimEventQueueConfigurator(manager)); 00117 manager.addSubComponent(seqc); 00118 00119 nub::soft_ref<InputFrameSeries> ifs(new InputFrameSeries(manager)); 00120 manager.addSubComponent(ifs); 00121 00122 nub::soft_ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager)); 00123 manager.addSubComponent(ofs); 00124 00125 nub::soft_ref<StdBrain> brain(new StdBrain(manager)); 00126 manager.addSubComponent(brain); 00127 00128 // feature analysis part of model 00129 const std::string name = "featureCluster"; 00130 const std::string tag = "fCV"; 00131 Image< PixRGB<byte> > input; 00132 Image< PixRGB<float> > finput; 00133 std::vector<covHolder<double> > covHolder; 00134 00135 // Parse command-line: 00136 if (manager.parseCommandLine(argc, argv, "<image>", 1, 1) == false) 00137 return(1); 00138 00139 nub::soft_ref<featureClusterVision<float> > 00140 fCV(new featureClusterVision<float>(manager,name,tag,brain,ifs, 00141 manager.getExtraArg(0))); 00142 manager.addSubComponent(fCV); 00143 nub::soft_ref<SimEventQueue> seq = seqc->getQ(); 00144 00145 // let's get all our ModelComponent instances started: 00146 manager.start(); 00147 // main loop: 00148 //************************************************************ 00149 // set up output x windows 00150 00151 Image<PixRGB<float> > fima1; Image<PixRGB<byte> > bima1; 00152 XWindow win2(Dims(IMAGE_SIZE_X, IMAGE_SIZE_Y), 0, 0, "CLASSES TEMPORAL"); 00153 Image<PixRGB<float> > fima2; Image<PixRGB<byte> > bima2; 00154 XWindow win3(Dims(IMAGE_SIZE_X, IMAGE_SIZE_Y), 0, 0, "TARGETS TEMPORAL"); 00155 Image<PixRGB<float> > fima3; Image<PixRGB<byte> > bima3; 00156 Image<float> fima4; Image<byte> bima4; 00157 00158 00159 XWindow wini(Dims(IMAGE_SIZE_X, IMAGE_SIZE_Y), 00160 0, 0, "Test-input window"); 00161 XWindow wino(Dims(IMAGE_SIZE_X/SIT_GLOBAL_DEC, 00162 (IMAGE_SIZE_Y/SIT_GLOBAL_DEC)*TRACKER_NUMBER), 00163 0, 0, "Test-output window"); 00164 XWindow winAux(Dims(500, 450), 00165 0, 0, "Channel levels"); 00166 unsigned short wi = IMAGE_SIZE_X; 00167 unsigned short hi = IMAGE_SIZE_Y; 00168 //! Holds H2SV representation of image for simple tracker 00169 Image<PixH2SV2<float> > H2SVimage; 00170 //! output display image 00171 Image< PixRGB<byte> > display; 00172 00173 //************************************************************ 00174 // Initalize translation values and other const values from 00175 // covHolder to segHolder 00176 00177 // how many standard deviations out to adapt, higher means less bias 00178 std::vector<float> adapt(4,0.0F); 00179 adapt[0] = 3.5F; adapt[1] = 3.5F; adapt[2] = 3.5F; adapt[3] = 3.5F; 00180 // set mkodifer over standard deviation. 00181 // A larger number means less bias 00182 std::vector<float> STDmod(4,0.0F); 00183 STDmod[0] = H1_STD; STDmod[1] = H2_STD; 00184 STDmod[2] = S_STD; STDmod[3] = V_STD; 00185 // input feature names to be helpful 00186 std::vector<std::string> fname(4,""); 00187 fname[0] = "Hue1"; fname[1] = "Hue2"; 00188 fname[2] = "Sat"; fname[3] = "Val"; 00189 // Hard upperBound modifier 00190 std::vector<float> lowerBoundMod(4,0.0F); 00191 lowerBoundMod[0] = 0.45F; lowerBoundMod[1] = 0.45F; 00192 lowerBoundMod[2] = 0.45F; lowerBoundMod[3] = 0.55F; 00193 // Hard lower bound modifer 00194 std::vector<float> upperBoundMod(4,0.0F); 00195 upperBoundMod[0] = 0.45F; upperBoundMod[1] = 0.45F; 00196 upperBoundMod[2] = 0.45F; upperBoundMod[3] = 0.55F; 00197 // maps the channels in covHolder to the channels in segHolder 00198 // since segHolder may have fewer channels this is needed 00199 std::vector<unsigned short> channelMap(4,0); 00200 channelMap[0] = HUE1; channelMap[1] = HUE2; 00201 channelMap[2] = SAT; channelMap[3] = VALUE; 00202 // This holds color infomation for output on screen 00203 unsigned char oc[6][6] = { 00204 {128,0,0 ,255,0,0} , 00205 {0,128,0 ,0,255,0} , 00206 {0,0,128 ,0,0,255} , 00207 {128,128,0 ,255,255,0} , 00208 {0,128,128 ,0,255,255} , 00209 {128,0,128 ,255,0,255} 00210 }; 00211 00212 //************************************************************ 00213 // Set up trackers and tracker signature holders 00214 segmentImageTrackMC<float,unsigned int,4> _segmenter(wi*hi); 00215 segHolder<float,unsigned int,4> _segHolder; 00216 00217 std::vector<segmentImageTrackMC<float,unsigned int,4> > 00218 segmenters(TRACKER_NUMBER,_segmenter); 00219 std::vector<segHolder<float,unsigned int,4> > 00220 segHolder(TRACKER_NUMBER,_segHolder); 00221 00222 // Set up each tracker 00223 // here we set up inital values for each tracker and 00224 // each channel 00225 00226 for(int i = 0; i < TRACKER_NUMBER; i++) 00227 { 00228 segmenters[i].SITuseLog(true); 00229 segmenters[i].SITsetFrame(&wi,&hi); 00230 segmenters[i].SITsetCircleColor(0,255,0); 00231 segmenters[i].SITsetUseSmoothing(true,10); 00232 segmenters[i].SITsetBoxColor(oc[i][0], oc[i][1], oc[i][2], 00233 oc[i][3], oc[i][4], oc[i][5]); 00234 segHolder[i].imageSizeX = wi; 00235 segHolder[i].imageSizeY = hi; 00236 segHolder[i].baseID = i; 00237 00238 for(int j = 0; j < 4; j++) 00239 { 00240 segHolder[i].channelAdapt[j] = adapt[j]; 00241 segHolder[i].STDmod[j] = STDmod[j]; 00242 segHolder[i].upperBoundMod[j] = upperBoundMod[j]; 00243 segHolder[i].lowerBoundMod[j] = lowerBoundMod[j]; 00244 segHolder[i].channelMap[j] = channelMap[j]; 00245 segHolder[i].featureName[j] = fname[j]; 00246 } 00247 } 00248 00249 //************************************************************ 00250 //std::vector<bool> noTargetYet(TRACKER_NUMBER,true); 00251 //std::vector<unsigned int> contTrackTime(TRACKER_NUMBER,0); 00252 00253 //************************************************************ 00254 // Set up log files 00255 if(use_logs) 00256 { 00257 std::ofstream outfileStart1("tracker.fzvision.log",std::ios::out); 00258 outfileStart1 << "\n*************************************************\n\n"; 00259 outfileStart1.close(); 00260 std::ofstream outfileStart2("blobs.fzvision.log",std::ios::out); 00261 outfileStart2 << "\n*************************************************\n\n"; 00262 outfileStart2.close(); 00263 } 00264 00265 //************************************************************ 00266 while(1) { 00267 // write outputs or quit? 00268 bool shouldsave = false; 00269 bool shouldquit = false; 00270 bool gotcovert = false; 00271 if (seq->check<SimEventWTAwinner>(0)) gotcovert = true; 00272 const FrameState os = ofs->update(seq->now(), gotcovert); 00273 00274 if (os == FRAME_NEXT || os == FRAME_FINAL) 00275 shouldsave = true; 00276 00277 if (os == FRAME_FINAL) 00278 shouldquit = true; 00279 00280 if (shouldsave) 00281 { 00282 SimModuleSaveInfo sinfo(ofs, *seq); 00283 brain->save(sinfo); 00284 int foo = ifs->frame(); 00285 std::string Myname; 00286 std::string a = manager.getExtraArg(0); 00287 std::string b = "."; 00288 char c[100]; 00289 if(foo == 1) 00290 ; //init = false; 00291 if(foo < 10) 00292 sprintf(c,"00000%d",foo); 00293 else if(foo < 100) 00294 sprintf(c,"0000%d",foo); 00295 else if(foo < 1000) 00296 sprintf(c,"000%d",foo); 00297 else if(foo < 10000) 00298 sprintf(c,"00%d",foo); 00299 else if(foo < 100000) 00300 sprintf(c,"0%d",foo); 00301 else 00302 sprintf(c,"%d",foo); 00303 Myname = a + b + c; 00304 std::cout << "******************************************************\n"; 00305 std::cout << "******************************************************\n"; 00306 // NOTE: added '0' at the end here because there was no value 00307 // matching the final '%d' 00308 std::cout << "RUNNING FRAME " << foo << "\n"; 00309 std::cout << "NAME " << Myname << "\n"; 00310 // Upload a frame to the classifier 00311 fCV->fCVuploadImage(input,Myname); 00312 // classify and cluster this image 00313 fCV->fCVclusterImage(); 00314 std::cout << "******************************************************\n"; 00315 std::cout << "******************************************************\n"; 00316 // get back image data 00317 fCV->fCVgetClusterImages(&fima1,&fima2,&fima3,&fima4); 00318 bima1 = fima1; bima2 = fima2; bima3 = fima3; bima4 = fima4*255.0F; 00319 bima4 = rescale(bima4,bima1.getWidth(),bima1.getHeight()); 00320 //Raster::WriteRGB(bima1,sformat("classes.out.%s.ppm",c)); 00321 //Raster::WriteRGB(bima2,sformat("temporal.out.%s.ppm",c)); 00322 Raster::WriteRGB(bima3,sformat("target.out.%s.ppm",c)); 00323 //Raster::WriteGray(bima4,sformat("salmap.out.%s.pgm",c)); 00324 //win1.drawImage(bima1); 00325 win2.drawImage(bima2); 00326 win3.drawImage(bima3); 00327 // optional SIGNATURE DATA FROM THIS CLASS (see covHolder.H) 00328 covHolder = fCV->fCVgetCovHolders(); 00329 // optional Size of the covHolder Vector 00330 00331 // See covHolder.H to see how data is stored 00332 // See covEstimate.C matchPmeanAccum to see how these 00333 // numbers are computed. 00334 std::ofstream outfile("tracker.fzvision.log",std::ios::app); 00335 if(use_logs) 00336 { 00337 outfile << ">>> FRAME " << foo; 00338 } 00339 // Update each tracker as to the current frame number 00340 for(int i = 0; i < TRACKER_NUMBER; i++) 00341 { 00342 segmenters[i].SITsetFrameNumber(foo); 00343 } 00344 00345 //************************************************************ 00346 /* For each potental target from the complex tracker, check 00347 to see if it is good to track. If so, assign it to a simple 00348 tracker, but check that the tracker is free and/or not 00349 already tracking this exact same thing. 00350 */ 00351 00352 // for each interesting object in the complex tracker 00353 for(int x = 0; x < (signed)fCV->fCVgetCovHolderSize(); x++) 00354 { 00355 // for each of the simple trackers 00356 for(int i = 0; i < TRACKER_NUMBER; i++) 00357 { 00358 // if the simple tracker is not tracking anything yet 00359 if(segHolder[i].noTargetYet == true) 00360 { 00361 // if an object in the complex tracker is moving 00362 if(covHolder[x].mean[MOTION] > 2.5F) 00363 { 00364 if(use_logs) 00365 outfile << "\t- (" << x 00366 << ") MASS OK " << covHolder[x].mean[MOTION]; 00367 bool unique = true; 00368 // For all the other simple trackers 00369 for(int j = 0; j < TRACKER_NUMBER; j++) 00370 { 00371 // if the other tracker is tracking a target 00372 if(segHolder[j].noTargetYet == false) 00373 { 00374 //if(segHolder[j].LOT == false) 00375 //{ 00376 00377 // check to see that the target we want to track 00378 // is not already being tracked 00379 unique = segmenters[j]. 00380 SITintersection(&covHolder[x],30,30); 00381 if(use_logs) 00382 outfile << "\n\t- CHECKED " << i 00383 << " WITH " << j << " : "; 00384 //} 00385 } 00386 } 00387 // if the target is new and not being tracked 00388 if(unique == true) 00389 { 00390 if(use_logs) 00391 outfile << "\t- Samples " << covHolder[x].samples << " ... "; 00392 // make sure it is large enough to track 00393 if(covHolder[x].samples > 25) 00394 { 00395 if(use_logs) 00396 { 00397 outfile << "OK "; 00398 outfile << " Variance " << covHolder[x].STD[HUE1] * H1_STD 00399 << " " << covHolder[x].STD[HUE2] * H2_STD 00400 << " ... "; 00401 outfile << "OK\n"; 00402 00403 outfile << "<<<NEW TRACKING>>> " << x << "\t" 00404 << "FRAME " << foo << "\t" 00405 << "TRACKER " << i << "\t" 00406 << "LIFE SPAN " << covHolder[x].lifeSpan << "\t" 00407 << "(" << covHolder[x].posX 00408 << "," << covHolder[x].posY << ")\t" 00409 << "Max (" << covHolder[x].maxX 00410 << "," << covHolder[x].maxY << ")\t" 00411 << "Min (" << covHolder[x].minX 00412 << "," << covHolder[x].minY << ")\n"; 00413 } 00414 // assign target to a simple tracker 00415 segHolder[i].noTargetYet = false; 00416 // What colors should the target have? 00417 segmenters[i].SITsetTrackSignature(&covHolder[x], 00418 &segHolder[i]); 00419 } 00420 } 00421 } 00422 } 00423 } 00424 } 00425 if(use_logs) 00426 { 00427 outfile << "\n"; 00428 outfile.close(); 00429 } 00430 display = input; 00431 Image<PixRGB<byte> > Aux; 00432 Aux.resize(100,450,true); 00433 Image<byte> tempPaste; 00434 tempPaste.resize(IMAGE_SIZE_X/SIT_GLOBAL_DEC, 00435 (IMAGE_SIZE_Y/SIT_GLOBAL_DEC)*TRACKER_NUMBER,true); 00436 00437 //************************************************************ 00438 /* For all simple trackers which are tracking a target, 00439 check to make sure that it is tracking what it should 00440 be tracking. 00441 */ 00442 00443 // for each simple tracker 00444 for(int i = 0; i < TRACKER_NUMBER; i++) 00445 { 00446 Image<byte> temp; 00447 temp.resize(IMAGE_SIZE_X/SIT_GLOBAL_DEC, 00448 IMAGE_SIZE_Y/SIT_GLOBAL_DEC,true); 00449 // if the simple tracker is tracking 00450 if(segHolder[i].noTargetYet == false) 00451 { 00452 H2SVimage = input; 00453 // track the current image 00454 segmenters[i].SITtrackImage(H2SVimage,&display); 00455 // Retrieve and Draw all our output images 00456 temp = segmenters[i].SITreturnCandidateImage(); 00457 // Get back the current signature of the target being tracked 00458 segmenters[i].SITgetTrackSignature(&segHolder[i]); 00459 00460 if(use_logs) 00461 { 00462 char whynotcomeupwithacoolname[100]; 00463 sprintf(whynotcomeupwithacoolname,"blobs.%d.fzvision.log",i); 00464 00465 std::ofstream outfile2(whynotcomeupwithacoolname,std::ios::app); 00466 outfile2 << "FRAME " << foo 00467 << "\t" 00468 << "TOTAL TRACK TIME " << segHolder[i].totalLifeSpan 00469 << "\t" 00470 << "TRACK TIME " << segHolder[i].lifeSpan 00471 << "\t" 00472 << "BLOBS " << segHolder[i].blobNumber 00473 << "\t" 00474 << "LOT status " << segHolder[i].LOTtypeName 00475 << "\t" 00476 << "LOT count " << segHolder[i].LOTcount 00477 << "\t" 00478 << "MASS " << segHolder[i].mass 00479 << "\n"; 00480 for(unsigned int ii = 0; ii < segHolder[i].blobNumber; ii++) 00481 { 00482 outfile2 << "\tBLOB NUMBER " << ii << "\t" 00483 << segmenters[i].SITgetBlobReasonForKill(ii) 00484 << " ... \t" 00485 << segmenters[i].SITgetBlobMass(ii) << "\t" 00486 << segmenters[i].SITgetBlobPosX(ii) << "\t" 00487 << segmenters[i].SITgetBlobPosY(ii) << "\n"; 00488 } 00489 outfile2 << "\n"; 00490 outfile2.close(); 00491 } 00492 if(use_logs) 00493 { 00494 std::ofstream outfile("tracker.fzvision.log",std::ios::app); 00495 outfile << "OVERLAP - \n"; 00496 } 00497 // for all the other simple trackers 00498 for(int j = 0; j < TRACKER_NUMBER; j++) 00499 { 00500 if(i != j) 00501 { 00502 // if the other simple tracker is tracking 00503 if(segHolder[j].noTargetYet == false) 00504 { 00505 // if the other simple tracker is not in Loss Of Track 00506 if(segHolder[j].LOT == false) 00507 { 00508 float overlap, thisarea, otherarea; 00509 // check if our targets are overlaping 00510 segmenters[j].SITpercentOverlap(&segHolder[i],&overlap, 00511 &thisarea,&otherarea); 00512 if(use_logs) 00513 { 00514 std::ofstream outfile("tracker.fzvision.log",std::ios::app); 00515 outfile << i << " - " << j 00516 << " : i / j = " << overlap 00517 << "\n"; 00518 outfile.close(); 00519 } 00520 // if there is alot of overlap, we are most 00521 // likely tracking the exact same thing 00522 if(overlap > 0.75F) 00523 { 00524 // kill the younger of the overlappers 00525 // if same age, kill the smaller 00526 if(segHolder[j].lifeSpan == segHolder[i].lifeSpan) 00527 { 00528 if(thisarea > otherarea) 00529 segHolder[i].noTargetYet = true; 00530 else 00531 segHolder[j].noTargetYet = true; 00532 } 00533 else if(segHolder[j].lifeSpan > segHolder[i].lifeSpan) 00534 segHolder[i].noTargetYet = true; 00535 else 00536 segHolder[j].noTargetYet = true; 00537 if(use_logs) 00538 { 00539 std::ofstream outfile("tracker.fzvision.log",std::ios::app); 00540 outfile << i << " OVERLAPS WITH " << j << "\n"; 00541 outfile.close(); 00542 } 00543 } 00544 } 00545 } 00546 } 00547 } 00548 // for this tracker, if to many Loss of Tracks have 00549 // been encountered in a row, the tracker gives up and 00550 // resets. 00551 if(segHolder[i].LOTandReset == true) 00552 { 00553 segHolder[i].noTargetYet = true; 00554 std::cout << "LOSS OF TRACK RESET" << "\n"; 00555 if(use_logs) 00556 { 00557 std::ofstream outfile("tracker.fzvision.log",std::ios::app); 00558 outfile << ">>>LOSS OF TRACK " << i 00559 << " RESET AT FRAME " << foo << "\n"; 00560 outfile.close(); 00561 } 00562 } 00563 } 00564 pasteImage(tempPaste,temp, 00565 (byte)128,Point2D<int>(0,(IMAGE_SIZE_Y/SIT_GLOBAL_DEC)*i)); 00566 } 00567 00568 wino.drawImage(tempPaste); 00569 winAux.drawImage(Aux); 00570 wini.drawImage(display); 00571 if(save_track_draw) 00572 { 00573 Raster::WriteGray(tempPaste, 00574 sformat("tracker.candidates.out.%s.pgm",c)); 00575 Raster::WriteRGB(Aux,sformat("tracker.levels.out.%s.ppm",c)); 00576 Raster::WriteRGB(display,sformat("tracker.out.%s.ppm",c)); 00577 } 00578 } 00579 00580 if (shouldquit) break; // done 00581 00582 // why do we handle the output before the input? That's because 00583 // both the input and output frame series will switch to the next 00584 // frame at the exact same time, if input and output framerates 00585 // are equal. When the input series switches to a new frame, it 00586 // will reset any drawings that were obtained on the previous 00587 // frame. So we need to make sure we have saved those results 00588 // before we read the new frame in. 00589 00590 // if we displayed a bunch of images, let's pause: 00591 if (ifs->shouldWait() || ofs->shouldWait()) 00592 Raster::waitForKey(); 00593 00594 // read new image in? 00595 const FrameState is = ifs->update(seq->now()); 00596 if (is == FRAME_COMPLETE) break; // done 00597 if (is == FRAME_NEXT || is == FRAME_FINAL) // new frame 00598 { 00599 input = ifs->readRGB(); 00600 00601 // empty image signifies end-of-stream 00602 if (input.initialized()) 00603 { 00604 rutz::shared_ptr<SimEventInputFrame> 00605 e(new SimEventInputFrame(brain.get(), GenericFrame(input), 0)); 00606 seq->post(e); // post the image to the brain 00607 00608 // show memory usage if in debug mode: 00609 if (MYLOGVERB >= LOG_DEBUG) 00610 SHOWMEMORY("MEMORY USAGE: frame %d t=%.1fms", ifs->frame(), 00611 seq->now().msecs()); 00612 } 00613 } 00614 00615 // evolve brain: 00616 const SimStatus status = seq->evolve(); 00617 00618 if (SIM_BREAK == status) // Brain decided it's time to quit 00619 break; 00620 } 00621 00622 00623 //fCV->checkMixing(); 00624 //fCV->checkICA(); 00625 //std::string fileName = "features.txt"; 00626 fCV->fCVfeaturesToFile(manager.getExtraArg(0),false); 00627 fCV->fCVICAfeaturesToFile(manager.getExtraArg(0)); 00628 // stop all our ModelComponents 00629 00630 manager.stop(); 00631 00632 // all done! 00633 return 0; 00634 } 00635 00636 // ###################################################################### 00637 /* So things look consistent in everyone's emacs... */ 00638 /* Local Variables: */ 00639 /* indent-tabs-mode: nil */ 00640 /* End: */