00001 /*!@file Beobot/beobot-Gist-Sal-Nav-master.C Robot navigation using a 00002 combination saliency and gist. 00003 Run beobot-Gist-Sal-Nav-master at A to do vision 00004 Run beobot-Gist-Sal-Nav at B to move */ 00005 00006 // //////////////////////////////////////////////////////////////////// // 00007 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00008 // University of Southern California (USC) and the iLab at USC. // 00009 // See http://iLab.usc.edu for information about this project. // 00010 // //////////////////////////////////////////////////////////////////// // 00011 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00012 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00013 // in Visual Environments, and Applications'' by Christof Koch and // 00014 // Laurent Itti, California Institute of Technology, 2001 (patent // 00015 // pending; application number 09/912,225 filed July 23, 2001; see // 00016 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00017 // //////////////////////////////////////////////////////////////////// // 00018 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00019 // // 00020 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00021 // redistribute it and/or modify it under the terms of the GNU General // 00022 // Public License as published by the Free Software Foundation; either // 00023 // version 2 of the License, or (at your option) any later version. // 00024 // // 00025 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00026 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00027 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00028 // PURPOSE. See the GNU General Public License for more details. // 00029 // // 00030 // You should have received a copy of the GNU General Public License // 00031 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00032 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00033 // Boston, MA 02111-1307 USA. // 00034 // //////////////////////////////////////////////////////////////////// // 00035 // 00036 // Primary maintainer for this file: Christian Siagian <siagian@usc.edu> 00037 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Beobot/beobot-Gist-Sal-Nav-master.C $ 00038 // $Id: beobot-Gist-Sal-Nav-master.C 10982 2009-03-05 05:11:22Z itti $ 00039 // 00040 //////////////////////////////////////////////////////// 00041 // beobot-Gist-Sal-Nav-Master.C <input_train.txt> 00042 // 00043 // a version of Gist/test-Gist-Sal-Nav.C to be run on the Beobot 00044 // 00045 00046 #include "Channels/ChannelOpts.H" 00047 #include "Component/GlobalOpts.H" 00048 #include "Component/ModelManager.H" 00049 #include "Component/ModelOptionDef.H" 00050 #include "Devices/FrameGrabberConfigurator.H" 00051 #include "GUI/XWinManaged.H" 00052 #include "Gist/FFN.H" 00053 #include "Gist/trainUtils.H" 00054 #include "Image/ColorOps.H" 00055 #include "Image/CutPaste.H" 00056 #include "Image/DrawOps.H" 00057 #include "Image/ImageCache.H" 00058 #include "Image/MathOps.H" 00059 #include "Image/MatrixOps.H" 00060 #include "Image/Pixels.H" 00061 #include "Image/Transforms.H" 00062 #include "Media/MPEGStream.H" 00063 #include "Media/MediaOpts.H" 00064 #include "Media/MediaSimEvents.H" 00065 #include "Neuro/GistEstimatorStd.H" 00066 #include "Neuro/NeuroOpts.H" 00067 #include "Neuro/NeuroSimEvents.H" 00068 #include "Neuro/ShapeEstimator.H" 00069 #include "Neuro/ShapeEstimatorModes.H" 00070 #include "Neuro/SpatialMetrics.H" 00071 #include "Neuro/StdBrain.H" 00072 #include "Neuro/gistParams.H" 00073 #include "Raster/Raster.H" 00074 #include "SIFT/Histogram.H" 00075 #include "Transport/FrameIstream.H" 00076 #include "Util/Timer.H" 00077 #include "Beobot/GridMap.H" 00078 //#include "Beobot/TopologicalMap.H" 00079 #include "Simulation/SimEventQueueConfigurator.H" 00080 00081 00082 #define W_ASPECT_RATIO 320 // ideal minimum width for display 00083 #define H_ASPECT_RATIO 240 // ideal minimum height for display 00084 00085 CloseButtonListener wList; 00086 XWinManaged *inputWin; 00087 XWinManaged *salWin; 00088 00089 XWinManaged *dispWin; 00090 int wDisp, hDisp, sDisp, scaleDisp; 00091 int wDispWin, hDispWin; 00092 00093 // gist display 00094 int pcaW = 16, pcaH = 5; 00095 int winBarW = 5, winBarH = 25; 00096 00097 // ###################################################################### 00098 void setupDispWin(int w, int h); 00099 00100 Image< PixRGB<byte> > getDispImg 00101 (Image< PixRGB<byte> > img, Image<float> gistImg, 00102 Image<float> gistPcaImg, Image<float> outHistImg); 00103 00104 // ###################################################################### 00105 // Main function 00106 int main(const int argc, const char **argv) 00107 { 00108 MYLOGVERB = LOG_INFO; // suppress debug messages 00109 00110 // Instantiate a ModelManager: 00111 ModelManager manager("Beobot: Navigation Model"); 00112 00113 // we cannot use saveResults() on our various ModelComponent objects 00114 // here, so let's not export the related command-line options. 00115 manager.allowOptions(OPTEXP_ALL & (~OPTEXP_SAVE)); 00116 00117 // Instantiate our various ModelComponents: 00118 nub::soft_ref<SimEventQueueConfigurator> 00119 seqc(new SimEventQueueConfigurator(manager)); 00120 manager.addSubComponent(seqc); 00121 00122 nub::soft_ref<FrameGrabberConfigurator> 00123 gbc(new FrameGrabberConfigurator(manager)); 00124 manager.addSubComponent(gbc); 00125 00126 nub::soft_ref<StdBrain> brain(new StdBrain(manager)); 00127 manager.addSubComponent(brain); 00128 00129 nub::ref<SpatialMetrics> metrics(new SpatialMetrics(manager)); 00130 manager.addSubComponent(metrics); 00131 00132 manager.exportOptions(MC_RECURSE); 00133 metrics->setFOAradius(30); // FIXME 00134 metrics->setFoveaRadius(30); // FIXME 00135 manager.setOptionValString(&OPT_MaxNormType, "FancyOne"); 00136 manager.setOptionValString(&OPT_UseRandom, "false"); 00137 // manager.setOptionValString("ShapeEstimatorMode","SaliencyMap"); 00138 // manager.setOptionValString(&OPT_ShapeEstimatorMode,"ConspicuityMap"); 00139 manager.setOptionValString(&OPT_ShapeEstimatorMode, "FeatureMap"); 00140 manager.setOptionValString(&OPT_ShapeEstimatorSmoothMethod, "Chamfer"); 00141 //manager.setOptionValString(&OPT_ShapeEstimatorSmoothMethod, "Gaussian"); 00142 manager.setOptionValString(&OPT_RawVisualCortexChans,"OIC"); 00143 //manager.setOptionValString(&OPT_IORtype, "ShapeEstFM"); 00144 manager.setOptionValString(&OPT_IORtype, "Disc"); 00145 00146 // setting up the GIST ESTIMATOR 00147 manager.setOptionValString(&OPT_GistEstimatorType,"Std"); 00148 00149 // Request a bunch of option aliases (shortcuts to lists of options): 00150 REQUEST_OPTIONALIAS_NEURO(manager); 00151 00152 // Parse command-line: 00153 if (manager.parseCommandLine(argc, argv, "<input_train.txt>", 00154 1, 1) == false) 00155 return(1); 00156 00157 // do post-command-line configs 00158 nub::soft_ref<FrameIstream> gb = gbc->getFrameGrabber(); 00159 if (gb.isInvalid()) 00160 LFATAL("You need to select a frame grabber type via the " 00161 "--fg-type=XX command-line option for this program " 00162 "to be useful -- ABORT"); 00163 int w = gb->getWidth(), h = gb->getHeight(); 00164 std::string dims = convertToString(Dims(w, h)); 00165 manager.setOptionValString(&OPT_InputFrameDims, dims); 00166 nub::soft_ref<SimEventQueue> seq = seqc->getQ(); 00167 00168 // frame delay in seconds 00169 double fdelay = 33.3667/1000.0; // real time 00170 00171 // let's get all our ModelComponent instances started: 00172 manager.start(); 00173 00174 // main loop: 00175 SimTime prevstime = SimTime::ZERO(); 00176 int fNum = 0; 00177 Image< PixRGB<byte> > inputImg; 00178 Image< PixRGB<byte> > dispImg; 00179 Image< PixRGB<byte> > tImg; 00180 00181 // instantiate a 3-layer feed-forward network 00182 // initialize with the provided parameters 00183 rutz::shared_ptr<FeedForwardNetwork> ffn_place(new FeedForwardNetwork()); 00184 FFNtrainInfo pcInfo(manager.getExtraArg(0).c_str()); 00185 ffn_place->init3L(pcInfo.h1Name, pcInfo.h2Name, pcInfo.oName, 00186 pcInfo.redFeatSize, pcInfo.h1size, pcInfo.h2size, 00187 pcInfo.nOutput, 0.0, 0.0); 00188 00189 // setup the PCA eigenvector 00190 Image<double> pcaVec = 00191 setupPcaIcaMatrix(pcInfo.trainFolder+pcInfo.evecFname, 00192 pcInfo.oriFeatSize, pcInfo.redFeatSize); 00193 00194 // get the frame grabber to start streaming: 00195 gb->startStream(); 00196 00197 // MAIN LOOP 00198 while(1) 00199 { 00200 // has the time come for a new frame? 00201 // LATER ON GIST WILL DECIDE IF WE WANT TO SLOW THINGS DOWN 00202 if (fNum == 0 || 00203 ((seq->now() - 0.5 * (prevstime - seq->now())).secs() - fNum * fdelay 00204 > fdelay)) 00205 { 00206 // NEED CONDITION TO END THE LOOP 00207 //if (??) break; 00208 00209 // grab a frame 00210 inputImg = gb->readRGB(); 00211 tImg = inputImg; 00212 00213 // setup display at the start of stream 00214 // NOTE: wDisp, hDisp, and sDisp are modified here 00215 if (fNum == 0) setupDispWin(w, h); 00216 //inputWin->drawImage(inputImg,0,0); 00217 00218 // pass input to brain: 00219 seq->post(rutz::make_shared(new SimEventInputFrame(brain.get(), GenericFrame(inputImg), 0))); 00220 LINFO("\nnew frame :%d",fNum); 00221 00222 // get the gist feature vector 00223 Image<double> cgist; 00224 if (SeC<SimEventGistOutput> ee = seq->check<SimEventGistOutput>(brain.get())) cgist = ee->gv(); 00225 else LFATAL("No gist output in the queue"); 00226 00227 // reduce feature dimension (if available) 00228 Image<double> in; 00229 if(pcInfo.isPCA) in = matrixMult(pcaVec, cgist); 00230 else in = cgist; 00231 00232 // recognize the place 00233 ffn_place->run3L(in); 00234 rutz::shared_ptr<Histogram> resHist(new Histogram(pcInfo.nOutput)); 00235 00236 for(uint i = 0; i < pcInfo.nOutput; i++) 00237 { 00238 LINFO("pl[%3d]: %.4f",i,ffn_place->getOutput().getVal(i)); 00239 resHist->addValue(i,ffn_place->getOutput().getVal(i)); 00240 } 00241 00242 // display or save the visuals 00243 LFATAL("FIXME SimEventGistOutput does not contain an image and should be updated"); 00244 /* 00245 dispImg = getDispImg 00246 (tImg, 00247 ge->getGistImage(sDisp), 00248 getPcaIcaFeatImage(in, pcaW, pcaH, sDisp*2), 00249 resHist->getHistogramImage(wDisp,sDisp*2 *pcaH, 0.0, 1.0)); 00250 */ 00251 00252 // have to press a key to continue to the next frame 00253 dispWin->drawImage(dispImg,0,0); 00254 Raster::waitForKey(); 00255 00256 // if we got an image, save it: 00257 // if (inputImg.initialized()) 00258 // { 00259 // std::string base = "../data/CameraCalib/beobotCF_"; 00260 // Raster::WriteRGB 00261 // (inputImg, PNM, sformat("%s%03d",base.c_str(),fNum)); 00262 // LINFO("saving %s%03d", base.c_str(), fNum); 00263 // } 00264 00265 // increment frame count 00266 fNum++; 00267 } 00268 00269 // evolve brain: 00270 prevstime = seq->now(); // time before current step 00271 const SimStatus status = seq->evolve(); 00272 00273 // process if salient location is selected 00274 if (SeC<SimEventWTAwinner> e = seq->check<SimEventWTAwinner>(0)) 00275 { 00276 const Point2D<int> winner = e->winner().p; 00277 00278 // use Shape estimator to focus on the attended region 00279 Image<float> fmask; std::string label; 00280 if (SeC<SimEventShapeEstimatorOutput> 00281 e = seq->check<SimEventShapeEstimatorOutput>(0)) 00282 { fmask = e->smoothMask(); label = e->winningLabel(); } 00283 00284 Image<float> roiImg; 00285 if (fmask.initialized()) 00286 roiImg = fmask * luminance(inputImg); 00287 else 00288 roiImg = luminance(inputImg); 00289 00290 drawCircle(roiImg, winner, 10, 0.0f, 1); 00291 LINFO("\nFrame: %d, winner: (%d,%d) in %s\n\n", 00292 fNum, winner.i, winner.j, label.c_str()); 00293 //salWin->drawImage(roiImg,0,0); 00294 //Raster::waitForKey(); 00295 //doSomeSalStuff(img, brain, winner); 00296 } 00297 00298 if (SIM_BREAK == status) // Brain decided it's time to quit 00299 break; 00300 } 00301 00302 // stop all our ModelComponents 00303 manager.stop(); 00304 00305 // all done! 00306 return 0; 00307 } 00308 00309 // ###################################################################### 00310 // setup display window for visualization purposes 00311 void setupDispWin(int w, int h) 00312 { 00313 // figure out the best display w, h, and scale 00314 00315 // check if both dimensions of the image 00316 // are much smaller than the desired resolution 00317 scaleDisp = 1; 00318 while (w*scaleDisp < W_ASPECT_RATIO*.75 && h*scaleDisp < H_ASPECT_RATIO*.75) 00319 scaleDisp++; 00320 00321 // check if the height is longer aspect-ratio-wise 00322 // this is because the whole display is setup wrt/ to it 00323 wDisp = w*scaleDisp; hDisp = h*scaleDisp; 00324 if(wDisp/(0.0 + W_ASPECT_RATIO) > hDisp/(0.0 + H_ASPECT_RATIO)) 00325 hDisp = (int)(wDisp / (0.0 + W_ASPECT_RATIO) * H_ASPECT_RATIO)+1; 00326 else 00327 wDisp = (int)(hDisp / (0.0 + H_ASPECT_RATIO) * W_ASPECT_RATIO)+1; 00328 00329 // add slack so that the gist feature entry is square 00330 sDisp = (hDisp/NUM_GIST_FEAT + 1); 00331 hDisp = sDisp * NUM_GIST_FEAT; 00332 00333 // add space for all the visuals 00334 wDispWin = wDisp + sDisp * NUM_GIST_COL; 00335 hDispWin = hDisp + sDisp * pcaH * 2; 00336 00337 dispWin = new XWinManaged(Dims(wDispWin, hDispWin), 0, 0, "dispImg"); 00338 wList.add(dispWin); 00339 00340 inputWin = new XWinManaged(Dims(w, h), w, 0, "input" ); 00341 wList.add(inputWin); 00342 00343 salWin = new XWinManaged(Dims(w, h), 2*w, 0, "Sal" ); 00344 wList.add(salWin); 00345 } 00346 00347 // ###################################################################### 00348 // get display image for visualization purposes 00349 Image< PixRGB<byte> > getDispImg (Image< PixRGB<byte> > img, 00350 Image<float> gistImg, 00351 Image<float> gistPcaImg, 00352 Image<float> outHistImg) 00353 { 00354 Image< PixRGB<byte> > dispImg(wDispWin, hDispWin, ZEROS); 00355 int w = img.getWidth(); int h = img.getHeight(); 00356 00357 // grid the displayed input image 00358 drawGrid(img, w/4,h/4,1,1,PixRGB<byte>(255,255,255)); 00359 inplacePaste(dispImg, img, Point2D<int>(0, 0)); 00360 00361 // display the gist features 00362 inplaceNormalize(gistImg, 0.0f, 255.0f); 00363 inplacePaste(dispImg, Image<PixRGB<byte> >(gistImg), Point2D<int>(wDisp, 0)); 00364 00365 // display the PCA gist features 00366 inplaceNormalize(gistPcaImg, 0.0f, 255.0f); 00367 inplacePaste(dispImg, Image<PixRGB<byte> >(gistPcaImg), Point2D<int>(wDisp, hDisp)); 00368 00369 // display the classifier output histogram 00370 inplaceNormalize(outHistImg, 0.0f, 255.0f); 00371 inplacePaste(dispImg, Image<PixRGB<byte> >(outHistImg), Point2D<int>(0, hDisp)); 00372 00373 // draw lines delineating the information 00374 drawLine(dispImg, Point2D<int>(0,hDisp), 00375 Point2D<int>(wDispWin,hDisp), 00376 PixRGB<byte>(255,255,255),1); 00377 drawLine(dispImg, Point2D<int>(wDisp-1,0), 00378 Point2D<int>(wDisp-1,hDispWin-1), 00379 PixRGB<byte>(255,255,255),1); 00380 return dispImg; 00381 } 00382 00383 // ###################################################################### 00384 /* So things look consistent in everyone's emacs... */ 00385 /* Local Variables: */ 00386 /* indent-tabs-mode: nil */ 00387 /* End: */