beobot-GSnav.C

Go to the documentation of this file.
00001 /*!@file Beobot/beobot-GSnav.C Robot navigation using saliency and gist.
00002   Run beobot-GSnav-master at CPU_A to run Gist-Saliency model
00003   Run beobot-GSnav        at CPU_B to run SIFT                          */
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: Christian Siagian <siagian@usc.edu>
00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Beobot/beobot-GSnav.C $
00036 // $Id: beobot-GSnav.C 14376 2011-01-11 02:44:34Z pez $
00037 //
00038 //////////////////////////////////////////////////////////////////////////
00039 // beobot-Gist-Sal-Nav.C <input_train.txt>
00040 //
00041 //
00042 // This is an on-going project for biologically-plausible
00043 // mobile-robotics navigation.
00044 // It accepts any inputs: video  clip <input.mpg>, camera feed, frames.
00045 //
00046 // The system uses Gist to recognize places and saliency
00047 // to get better localization within the place
00048 // The program also is made to be streamline for fast processing using
00049 // parallel computation. That is the V1 features of different channels are
00050 // computed in parallel
00051 //
00052 // Currently it is able to recognize places through the use of gist features.
00053 // The place classifier is a neural networks,
00054 // passed in a form of <input_train.txt> -
00055 // the same file is used in the training phase by train-FFN.C.
00056 // Related files of interest: GistEstimator.C (and .H) and
00057 // GistEstimatorConfigurator.C (and .H) used by Brain.C to compute
00058 // the gist features.
00059 // test-Gist.C uses GistEstimator to extract gist features from an image.
00060 //
00061 // In parallel we use saliency to get a better spatial resolution
00062 // as well as better place accuracy. The saliency model is used to obtain
00063 // salient locations. We then use ShapeEstimator algorithm to segment out
00064 // the sub-region to get a landmark. Using the pre-attentive features and
00065 // SIFT we can identify the object, create a database, etc.
00066 //
00067 // for localization, path planning we perform landmark-hopping
00068 // to get to the final destination
00069 //
00070 //
00071 //
00072 
00073 /*
00074 maybe need to figure out how the shape of the object change on our movement
00075 
00076 use scale
00077 temporal ordering, frame number
00078 winning channel, channel weights
00079 
00080 can also play with biasing of where the next object could be
00081 or bias away from (anywhere but) the salpt to see if there is another object.
00082 
00083 benefit of temporal ordering:
00084 -> figure out the best time the next LM should kick in
00085 -> best way to turn at the end of a segment.
00086 
00087 for current landmark tracking remember fnum of the previous match
00088 so that you won't have to start over
00089 
00090 Maybe we should be doing biased sal (as oppose to straight sal)
00091 even in the training process
00092 
00093 important landmarks to track:
00094 
00095 guide you to the next landmark -> biased salient loc
00096 
00097 currently in db processing
00098 
00099 kept on getting salient hits -> plain salient loc
00100 
00101 =============
00102 
00103 scenarios:
00104 have an object
00105 we're done what next
00106 we're almost done
00107 we're following the point, any changes
00108 we're lost what do we do now.
00109 
00110 ==============
00111 */
00112 
00113 #include "Beowulf/Beowulf.H"
00114 #include "Component/ModelManager.H"
00115 #include "Raster/Raster.H"
00116 #include "Image/Image.H"
00117 #include "Image/Pixels.H"
00118 #include "GUI/XWinManaged.H"
00119 #include "Util/Timer.H"
00120 
00121 #include "Beobot/BeobotControl.H"
00122 
00123 #include "SIFT/VisualObject.H"
00124 #include "SIFT/VisualObjectDB.H"
00125 #include "SIFT/Histogram.H"
00126 
00127 #include "Image/MathOps.H"      // for inPlaceNormalize()
00128 #include "Image/CutPaste.H"     // for inplacePaste()
00129 #include "Image/DrawOps.H"      // for drawing
00130 #include "Image/ShapeOps.H"     // for decXY()
00131 #include "Image/MatrixOps.H"    // for matrixMult(), matrixInv(), etc
00132 
00133 #include "Beobot/beobot-GSnav-def.H"
00134 #include "Beobot/GSnavResult.H"
00135 #include "Beobot/Environment.H"
00136 #include "Beobot/GSlocalizer.H"
00137 
00138 #include <signal.h>
00139 
00140 #include <errno.h>
00141 
00142 static bool goforever = true;  //!< Will turn false on interrupt signal
00143 
00144 // ######################################################################
00145 // ######################################################################
00146 
00147 //! process the message passed by Visual Cortex
00148 void getSearchCommand
00149 ( TCPmessage &rmsg, int32 rframe, int32 raction, bool &resetVentralSearch,
00150   Image<PixRGB<byte> > &ima, Image<double> &cgist,
00151   std::vector<rutz::shared_ptr<VisualObject> > &inputVO,
00152   std::vector<Point2D<int> > &objOffset,
00153   std::string saveFilePath, std::string testRunFPrefix,
00154   float &dx, float &dy, uint &snumGT, float &ltravGT);
00155 
00156 //! display the salient objects passed by Visual Cortex program
00157 Image<PixRGB<byte> > getSalImage
00158 ( Image<PixRGB<byte> > ima,
00159   std::vector<rutz::shared_ptr<VisualObject> > inputVO,
00160   std::vector<Point2D<int> > objOffset,  std::vector<bool> found);
00161 
00162 //! process the returned search result
00163 Image<PixRGB<byte> > processLocalizerResults
00164 ( nub::ref<GSlocalizer> gslocalizer, std::string savePrefix);
00165 
00166 Image<PixRGB<byte> > getDisplayImage(nub::ref<GSlocalizer> gslocalizer);
00167 
00168 //! save gist vector to a file
00169 bool saveGist
00170 ( std::string saveFilePath, std::string testRunFPrefix,
00171   int currSegNum, int count, Image<double> cgist);
00172 
00173 //! report the results of the trial run
00174 void reportResults(std::string savePrefix, uint nsegment);
00175 
00176 //! report the results of all the trial runs
00177 //! it's a hack code
00178 void reportTrialResults();
00179 
00180 // ######################################################################
00181 //! Signal handler (e.g., for control-C)
00182 void terminate(int s) { LERROR("*** INTERRUPT ***"); goforever = false; }
00183 
00184 // ######################################################################
00185 int main(const int argc, const char **argv)
00186 {
00187   MYLOGVERB = LOG_INFO;
00188 
00189   // instantiate a model manager:
00190   ModelManager manager("beobot Navigation using Gist & Saliency - "
00191                        "Ventral");
00192 
00193   // Instantiate our various ModelComponents:
00194   nub::soft_ref<Beowulf>
00195     beo(new Beowulf(manager, "Beowulf Slave", "BeowulfSlave", false));
00196   manager.addSubComponent(beo);
00197 
00198   nub::ref<GSlocalizer> gslocalizer(new GSlocalizer(manager));
00199   manager.addSubComponent(gslocalizer);
00200 
00201   // Parse command-line:
00202   if (manager.parseCommandLine(argc, argv, "", 0, 0) == false)
00203     return(1);
00204 
00205   // setup signal handling:
00206   signal(SIGHUP,  terminate); signal(SIGINT,  terminate);
00207   signal(SIGQUIT, terminate); signal(SIGTERM, terminate);
00208 
00209   TCPmessage rmsg;            // message being received and to process
00210   TCPmessage smsg;            // message being sent
00211   int32 rframe, raction, rnode = -1;
00212 
00213   // let's get all our ModelComponent instances started:
00214   manager.start();
00215 
00216   // receive the image dimension first
00217   while(!beo->receive(rnode, rmsg, rframe, raction, 5));
00218   LINFO("Ventral size: %d", rmsg.getSize());
00219   const int fstart = int(rmsg.getElementInt32());
00220   const int w = int(rmsg.getElementInt32());
00221   const int h = int(rmsg.getElementInt32());
00222   const int opMode = int(rmsg.getElementInt32());
00223   const int nSegment = int(rmsg.getElementInt32());
00224   int currSegNum = int(rmsg.getElementInt32());
00225   std::string envFName = rmsg.getElementString();
00226   std::string testRunFPrefix = rmsg.getElementString();
00227   std::string saveFilePath = rmsg.getElementString();
00228   std::string resultPrefix = rmsg.getElementString();
00229   int ldpos = envFName.find_last_of('.');
00230   int lspos = envFName.find_last_of('/');
00231   std::string testRunEnvFName = envFName.substr(0, ldpos) +
00232     std::string("-") + testRunFPrefix + std::string(".env");
00233   std::string envPrefix =  envFName.substr(lspos+1, ldpos - lspos - 1);
00234 
00235   LINFO("fstart: %d", fstart);
00236   LINFO("envFName: %s", envFName.c_str());
00237   LINFO("Where we save data: %s", saveFilePath.c_str());
00238   LINFO("envPrefix: %s", envPrefix.c_str());
00239   LINFO("testRunEnvFName: %s", testRunEnvFName.c_str());
00240   LINFO("result prefix: %s", resultPrefix.c_str());
00241   LINFO("test run prefix: %s", testRunFPrefix.c_str());
00242   LINFO("Image dimension %d by %d", w,h);
00243   switch(opMode)
00244     {
00245     case TRAIN_MODE:
00246       LINFO("number of segments:  %d", nSegment);
00247       LINFO("current segment: %d", currSegNum);
00248       LINFO("TRAIN_MODE: build the landmark DB");
00249       break;
00250     case TEST_MODE:
00251       LINFO("TEST_MODE: let's roll");
00252       break;
00253     default: LERROR("Unknown operation mode");
00254     }
00255   rmsg.reset(rframe, raction);
00256 
00257   // create a gist folder
00258   std::string gistFolder =
00259     saveFilePath + std::string("gist/");
00260   if (mkdir(gistFolder.c_str(), 0777) == -1 && errno != EEXIST)
00261     {
00262       LFATAL("Cannot create gist folder: %s", gistFolder.c_str());
00263     }
00264 
00265   // create a gistTrain folder
00266   std::string gistTrainFolder =
00267     saveFilePath + std::string("gistTrain/");
00268   if (mkdir(gistTrainFolder.c_str(), 0777) == -1 && errno != EEXIST)
00269     {
00270       LFATAL("Cannot create gistTrain folder: %s", gistTrainFolder.c_str());
00271     }
00272 
00273   // HACK: this is for printing summary results
00274   //reportTrialResults();
00275   //reportResults(resultPrefix,9); Raster::waitForKey();
00276 
00277   rutz::shared_ptr<XWinManaged> inputWin;
00278   inputWin.reset(new XWinManaged(Dims(w, h), 2*w+ 20, 0, "Input Window" ));
00279   rutz::shared_ptr<XWinManaged> matchWin;
00280   matchWin.reset(new XWinManaged(Dims(2*w, 2*h), 0, 0, "Result Window" ));
00281   rutz::shared_ptr<XWinManaged> mainWin;
00282 
00283   // initialize an environment - even if the .env file does not exist
00284   // automatically create a blank environment, ready to be built
00285   rutz::shared_ptr<Environment> env(new Environment(envFName));
00286   env->setWindow(matchWin);
00287 
00288   // training: set the segment and current segment explicitly
00289   if(opMode == TRAIN_MODE)
00290     {
00291       // if the stored DB is already loaded,
00292       // don't reset it'll discard the stored DB
00293       if(env->getNumSegment() == 0) env->resetNumSegment(nSegment);
00294 
00295       env->setCurrentSegment(currSegNum);
00296       env->startBuild();
00297     }
00298   // else if(opMode == TRAIN_X_MODE)
00299   //   {
00300   //     env->startJunctionBuild();
00301   //   }
00302   else if(opMode == TEST_MODE)
00303     {
00304       // if environment object is blank then abort
00305       if(env->isBlank())
00306         LFATAL("empty environment .env file may not exist");
00307 
00308       // file prefix to save performance data
00309       gslocalizer->setSavePrefix(resultPrefix);
00310 
00311       // link the environment to the localizer
00312       gslocalizer->setEnvironment(env);
00313 
00314       // initialize the particles
00315       // in case we have a starting belief
00316       std::string sBelFName = resultPrefix +
00317         sformat("_bel_%07d.txt", fstart-1);
00318       LINFO("Starting belief file: %s", sBelFName.c_str());
00319       gslocalizer->initParticles(sBelFName);
00320 
00321       // set the beowulf access
00322       gslocalizer->setBeoWulf(beo);
00323 
00324       // set the window display as well
00325       gslocalizer->setWindow(matchWin);
00326 
00327       // this is the main window for display of test results
00328       mainWin.reset
00329         (new XWinManaged(Dims(5*w, 3*h), 0, 0, "Main Window" ));
00330     }
00331   else LFATAL("invalid opmode");
00332 
00333   // send a message of ready to go
00334   smsg.reset(rframe, INIT_DONE);
00335   beo->send(rnode, smsg);
00336 
00337   // MAIN LOOP
00338   LINFO("MAIN LOOP"); uint fNum = 0; std::vector<float> procTime;
00339   Timer tim(1000000); uint64 t[NAVG]; 
00340   uint snumGT; float ltravGT; // ground truth information
00341   while(goforever)
00342     {
00343       // if we get a new message from master
00344       // check the type of action to take with the data
00345       if(beo->receive(rnode, rmsg, rframe, raction, 2))
00346         {
00347           LINFO("[%d] message rec: %d", rframe, raction);
00348           fNum = rframe;
00349 
00350           // abort: break out of the loop and finish the operation
00351           if(raction == ABORT)
00352             {
00353               LINFO("done: BREAK"); goforever = false;
00354 
00355               // if test mode and need to save last image
00356               // skip if this is the first input frame
00357               if(gslocalizer->getInputImage().initialized())
00358                 {
00359                   // get whatever is available right now
00360                   // update the belief particles
00361                   gslocalizer->updateBelief();
00362 
00363                   // process localizer result
00364                   Image<PixRGB<byte> > dispIma =
00365                     processLocalizerResults(gslocalizer, resultPrefix);
00366 
00367                   uint lfnum = gslocalizer->getInputFnum();
00368                   mainWin->setTitle(sformat("Frame %d", lfnum).c_str());
00369                   mainWin->drawImage(dispIma,0,0);
00370                 }
00371             }
00372 
00373           //FIX: maybe for inquiry if search is done
00374           // search not yet done
00375           //  smsg.reset(rframe, SEARCH_LM_RES);
00376           //  smsg.addInt32(int32(SEARCH_NOT_DONE));
00377 
00378           // Ventral track task
00379           // FIX: check with the prev landmark first
00380 
00381           // object received: recognize
00382           // train: build landmark db
00383           // test : search landmark db & localize
00384           if(raction == SEARCH_LM)
00385             {
00386               tim.reset();
00387               Image<PixRGB<byte> > ima; Image<double> cgist;
00388               std::vector<rutz::shared_ptr<VisualObject> > inputVO;
00389               std::vector<Point2D<int> > objOffset; std::vector<bool> found;
00390               float dx, dy; bool resetVentralSearch = false;
00391               getSearchCommand(rmsg, fNum, raction, resetVentralSearch,
00392                                ima, cgist, inputVO, objOffset,
00393                                saveFilePath, testRunFPrefix,
00394                                dx, dy, snumGT, ltravGT);
00395               for(uint i = 0; i < inputVO.size(); i++) found.push_back(false);
00396               LDEBUG("[%d] getSearchCommand: %f", fNum, tim.get()/1000.0);
00397 
00398               inputWin->drawImage
00399                 (getSalImage(ima, inputVO, objOffset, found),0,0);
00400               inputWin->setTitle(sformat("fr: %d", fNum).c_str());
00401 
00402               // process based on the operation mode
00403               switch(opMode)
00404                 {
00405                 case TRAIN_MODE:
00406                   {
00407                     // create the visual object for the scene and salregs
00408                     std::string sName(sformat("scene%07d",fNum));
00409                     std::string sfName = sName + std::string(".png");
00410                     rutz::shared_ptr<VisualObject>
00411                       scene(new VisualObject(sName, sfName, ima));
00412 
00413                     for(uint i = 0; i < inputVO.size(); i++)
00414                       inputVO[i]->computeKeypoints();
00415 
00416                     // process input
00417                     env->build(inputVO, objOffset, fNum, scene);
00418 
00419                     // save the gist vector to the gist folder for training
00420                     saveGist(gistFolder, testRunFPrefix,
00421                              currSegNum, fNum, cgist);
00422 
00423                     smsg.reset(rframe, SEARCH_LM_RES);
00424                     smsg.addInt32(int32(fNum)); // always localized
00425                     smsg.addInt32(int32(fNum));
00426                     LINFO("DONE BUILD_LM: %d", fNum);
00427                     beo->send(rnode, smsg);
00428                     break;
00429                   }
00430                 case TEST_MODE:
00431                   {
00432                     uint64 tSave = 0; uint64 t0;
00433 
00434                     // skip if this is the first input frame
00435                     if(gslocalizer->getInputImage().initialized())
00436                       {
00437                         // get whatever is available right now
00438                         // update the belief particles
00439                         gslocalizer->updateBelief();
00440 
00441                         // process localizer result
00442                         t0 = tim.get();
00443                         Image<PixRGB<byte> > dispIma =
00444                           processLocalizerResults
00445                           (gslocalizer, resultPrefix);
00446                         tSave = tim.get() - t0;
00447 
00448                         // DISPLAY ONCE EVERY 10 FRAMES
00449                         LINFO("\n\nfNum: %d",fNum);
00450                         //if(fNum%10 == 0)
00451                         //  {
00452                             uint lfnum =  gslocalizer->getInputFnum();
00453                             mainWin->setTitle
00454                               (sformat("Frame %d", lfnum).c_str());
00455                             mainWin->drawImage(dispIma,0,0);
00456                         //  }
00457 
00458                         // clear search and add a new set of tasks
00459                         if(resetVentralSearch)
00460                           {
00461                             // soft/non-blocking call
00462                             // to stop all search threads
00463                             LINFO("[%d] resetting ventral search", fNum);
00464                             gslocalizer->stopSearch2();
00465                           }
00466                       }
00467 
00468                     // FIX: if still searching, may want to append search
00469                     //      but now simply to take gist and (dx,dy)
00470                     t0 = tim.get();
00471                     gslocalizer->input
00472                       (ima, inputVO, objOffset, fNum, cgist, dx, dy);
00473                     gslocalizer->setGroundTruth(snumGT, ltravGT);
00474                     uint64 tInput = tim.get() - t0;
00475 
00476                     LINFO("tS = %f, tI = %f", tSave/1000.0, tInput/1000.0);
00477                   }
00478                 break;
00479                 default:
00480                   LERROR("Unknown operation mode");
00481                 }
00482 
00483               // compute and show framerate over the last NAVG frames:
00484               t[fNum % NAVG] = tim.get();
00485               if (fNum % NAVG == 0 && fNum != 0)
00486                 {
00487                   uint64 avg = 0ULL; for(int i=0; i<NAVG; i++) avg+=t[i];
00488                 }
00489               uint64 ptime = tim.get(); float ptime2 = ptime/1000.0;
00490               LINFO("[%d] ventral proc time = %f", fNum, ptime2);
00491               procTime.push_back(ptime2);
00492             }
00493         }
00494     }
00495 
00496   // Received abort signal
00497   smsg.reset(rframe, raction);
00498   smsg.addInt32(int32(777));
00499   beo->send(rnode, smsg);
00500   LINFO("received ABORT signal");
00501 
00502   // ending operations
00503   switch(opMode)
00504     {
00505     case TRAIN_MODE:
00506 
00507       // finish up the training session
00508       env->finishBuild(envFName, testRunFPrefix, fNum);
00509       env->save(envFName, testRunEnvFName, envPrefix);
00510       break;
00511 
00512     case TEST_MODE:
00513       {
00514         // stop the gslocalizer - blocking code
00515         gslocalizer->stopSearch();
00516 
00517         // report some statistical data
00518         reportResults(resultPrefix, env->getNumSegment());
00519 
00520         float min = 0.0f, max = 0.0f;
00521         if(procTime.size() > 0){ min = procTime[0]; max = procTime[0]; }
00522         for(uint i = 1; i < procTime.size(); i++)
00523           {
00524             if (min > procTime[i]) min = procTime[i];
00525             if (max < procTime[i]) max = procTime[i];
00526           }
00527         LINFO("proc Time: %f - %f", min, max);
00528       }
00529       break;
00530 
00531     default: LERROR("Unknown operation mode");
00532     }
00533 
00534   // we got broken:
00535   manager.stop();
00536   Raster::waitForKey();
00537   return 0;
00538 }
00539 
00540 // ######################################################################
00541 Image<PixRGB<byte> >  getSalImage
00542 ( Image<PixRGB<byte> > ima,
00543   std::vector<rutz::shared_ptr<VisualObject> > inputVO,
00544   std::vector<Point2D<int> > objOffset,
00545   std::vector<bool> found)
00546 {
00547   int w = ima.getWidth();  int h = ima.getHeight();
00548   Image<PixRGB<byte> > dispIma(w,h,ZEROS);
00549   inplacePaste(dispIma,ima, Point2D<int>(0,0));
00550 
00551   // display the salient regions
00552   // and indicate if each is found or not
00553   LDEBUG("number of input objects: %"ZU, inputVO.size());
00554   for(uint i = 0; i < inputVO.size(); i++)
00555     {
00556       Rectangle r(objOffset[i], inputVO[i]->getImage().getDims());
00557       Point2D<int> salpt = objOffset[i] + inputVO[i]->getSalPoint();
00558       if(!found[i])
00559         {
00560           drawRect(dispIma,r,PixRGB<byte>(255,0,0));
00561           drawDisk(dispIma, salpt, 3, PixRGB<byte>(255,0,0));
00562         }
00563       else
00564         {
00565           drawRect(dispIma,r,PixRGB<byte>(0,255,0));
00566           drawDisk(dispIma, salpt, 3, PixRGB<byte>(0,255,0));
00567         }
00568       LDEBUG("found: %d", int(found[i]));
00569 
00570       std::string ntext(sformat("%d", i));
00571       writeText(dispIma, objOffset[i] + inputVO[i]->getSalPoint(),
00572                 ntext.c_str());
00573     }
00574 
00575   return dispIma;
00576 }
00577 
00578 
00579 // ######################################################################
00580 void getSearchCommand
00581 ( TCPmessage &rmsg, int32 rframe, int32 raction, bool &resetVentralSearch,
00582   Image<PixRGB<byte> > &ima, Image<double> &cgist,
00583   std::vector<rutz::shared_ptr<VisualObject> > &inputVO,
00584   std::vector<Point2D<int> > &objOffset,
00585   std::string saveFilePath, std::string testRunFPrefix,
00586   float &dx, float &dy, uint &snumGT, float &ltravGT)
00587 {
00588   resetVentralSearch = (int(rmsg.getElementInt32()) > 0);
00589 
00590   // get the image
00591   ima = rmsg.getElementColByteIma();
00592   LDEBUG("Image size: %d %d", ima.getWidth(), ima.getHeight());
00593 
00594   // get the gist
00595   uint gsize = uint(rmsg.getElementInt32());
00596   cgist.resize(1, gsize, NO_INIT);
00597   Image<double>::iterator aptr = cgist.beginw();
00598   for(uint i = 0; i < gsize; i++) *aptr++ = rmsg.getElementDouble();
00599 
00600   // get all the visual objects
00601   inputVO.clear(); objOffset.clear();
00602   uint nvo = uint(rmsg.getElementInt32());
00603   for(uint i = 0; i < nvo; i++)
00604     {
00605       int si, sj;
00606       si = int(rmsg.getElementInt32());
00607       sj = int(rmsg.getElementInt32());
00608       Point2D<int> salpt(si,sj);
00609 
00610       int tin, lin, bin, rin;
00611       tin = int(rmsg.getElementInt32());
00612       lin = int(rmsg.getElementInt32());
00613       bin = int(rmsg.getElementInt32());
00614       rin = int(rmsg.getElementInt32());
00615       Rectangle rect = Rectangle::tlbrO(tin, lin, bin, rin);
00616       int fsize = int(rmsg.getElementInt32());
00617       LDEBUG("[%d] salpt:(%s) r:[%s]", i,
00618              convertToString(salpt).c_str(),
00619              convertToString(rect).c_str());
00620       Point2D<int> offset(rect.left(), rect.top());
00621 
00622       objOffset.push_back(offset);
00623 
00624       // get the pre-attentive feature vector
00625       std::vector<float> features;
00626       for(int j = 0; j < fsize; j++)
00627         features.push_back(rmsg.getElementDouble());
00628 
00629       // create a visual object for the salient region
00630       Image<PixRGB<byte> > objImg =  crop(ima, rect);
00631       std::string
00632         iName(sformat("%s_SAL_%07d_%02d",
00633                       testRunFPrefix.c_str(), rframe, i));
00634       std::string ifName = iName + std::string(".png");
00635       ifName = saveFilePath + ifName;
00636       rutz::shared_ptr<VisualObject>
00637         vo(new VisualObject
00638            (iName, ifName, objImg, salpt - offset, features,
00639             std::vector< rutz::shared_ptr<Keypoint> >(), false, false));
00640       inputVO.push_back(vo);
00641 
00642       LDEBUG("rframe[%d] image[%d]: %s sal:[%d,%d] objOffset:[%d,%d]",
00643             rframe, i, iName.c_str(),
00644             (salpt - offset).i, (salpt - offset).j,
00645             objOffset[i].i, objOffset[i].j);
00646     }
00647 
00648   // get the odometry information
00649   dx = rmsg.getElementFloat();
00650   dy = rmsg.getElementFloat();
00651 
00652   // get the ground truth information
00653   snumGT  = uint(rmsg.getElementInt32());
00654   ltravGT = rmsg.getElementFloat();
00655 
00656   rmsg.reset(rframe, raction);
00657 }
00658 
00659 // ######################################################################
00660 Image<PixRGB<byte> > processLocalizerResults
00661 ( nub::ref<GSlocalizer> gslocalizer, std::string savePrefix)
00662 {
00663   Timer t1(1000000); t1.reset();
00664   // get the results
00665   uint index       = gslocalizer->getInputFnum();
00666   uint64 tGetRes = t1.get();  t1.reset();
00667 
00668   // check the ground truth
00669   rutz::shared_ptr<Environment> env = gslocalizer->getEnvironment();
00670   float xGT = -1.0F, yGT = -1.0F; float error = 0.0F;
00671   uint  snumRes = 0; float ltravRes = -1.0F;
00672   uint snumGT; float ltravGT; gslocalizer->getGroundTruth(snumGT, ltravGT);
00673   if(ltravGT != -1.0F)
00674     {
00675       env->getLocationFloat(snumGT, ltravGT, xGT, yGT);
00676       snumRes  = gslocalizer->getSegmentLocation();
00677       ltravRes = gslocalizer->getSegmentLengthTraveled();
00678       error = env->getTopologicalMap()->
00679         getDistance(snumGT, ltravGT, snumRes, ltravRes);
00680       LDEBUG("Ground Truth [%d %f] vs [%d %f]: error: %f",
00681             snumGT, ltravGT, snumRes, ltravRes, error);
00682     }
00683   uint64 tGetGT = t1.get();
00684 
00685   Image<PixRGB<byte> > dispIma;
00686   bool saveDisplay = true;
00687   if(saveDisplay)
00688     {
00689       dispIma = getDisplayImage(gslocalizer);
00690 
00691       // save it to be mpeg encoded
00692       std::string saveFName =  savePrefix + sformat("_RES_%07d.ppm", index);
00693       LINFO("saving: %s",saveFName.c_str());
00694       Raster::WriteRGB(dispIma,saveFName);
00695 
00696       // save the particle locations
00697       // in case we need to restart in the middle
00698       std::string belFName = savePrefix + sformat("_bel_%07d.txt", index);
00699       FILE *bfp; LDEBUG("belief file: %s", belFName.c_str());
00700       if((bfp = fopen(belFName.c_str(),"wt")) == NULL)LFATAL("not found");
00701       std::vector<GSparticle> belief = gslocalizer->getBeliefParticles();
00702       for(uint i = 0; i < belief.size(); i++)
00703         {
00704           std::string bel = sformat("%d %f ", belief[i].segnum,
00705                                     belief[i].lentrav);
00706           bel += std::string("\n");
00707           fputs(bel.c_str(), bfp);
00708         }
00709       fclose (bfp);
00710     }
00711 
00712   t1.reset();
00713 
00714   // save result in a file by appending to the file
00715   std::string resFName = savePrefix + sformat("_results.txt");
00716   FILE *rFile = fopen(resFName.c_str(), "at");
00717   if (rFile != NULL)
00718     {
00719       LDEBUG("saving result to %s", resFName.c_str());
00720       std::string line =
00721         sformat("%5d %3d %8.5f %3d %8.5f %10.6f %d ",
00722                 index, snumGT, ltravGT, snumRes, ltravRes, error, 0);
00723 
00724       LINFO("%s", line.c_str());
00725       line += std::string("\n");
00726 
00727       fputs(line.c_str(), rFile);
00728       fclose (rFile);
00729     }
00730   else LINFO("can't create file: %s", resFName.c_str());
00731   uint64 tSaveRes = t1.get();
00732 
00733   LDEBUG("tGR = %f, tGGT = %f, tSR = %f",
00734          tGetRes/1000.0, tGetGT/1000.0,tSaveRes/1000.0);
00735 
00736   return dispIma;
00737 }
00738 
00739 // ######################################################################
00740 Image<PixRGB<byte> > getDisplayImage(nub::ref<GSlocalizer> gslocalizer)
00741 {
00742   // if search is not done don't need to get those information
00743   Image<PixRGB<byte> > ima = gslocalizer->getInputImage();
00744   uint w = ima.getWidth(); uint h = ima.getHeight();
00745   Image<PixRGB<byte> > dispIma(5*w,3*h,ZEROS);
00746 
00747   uint ninput = gslocalizer->getNumInputObject();
00748   std::vector<bool> mfound(ninput);
00749   std::vector<uint> nObjSearch(ninput);
00750   std::vector<rutz::shared_ptr<VisualObject> > iObject(ninput);
00751   std::vector<Point2D<int> > iOffset(ninput);
00752   std::vector<rutz::shared_ptr<VisualObjectMatch> > cmatch(ninput);
00753   for(uint i = 0; i < ninput; i++)
00754     {
00755       mfound[i]     = gslocalizer->isMatchFound(i);
00756       nObjSearch[i] = gslocalizer->getNumObjectSearch(i);
00757       iObject[i]    = gslocalizer->getInputVO(i);
00758       iOffset[i]    = gslocalizer->getInputObjOffset(i);
00759       cmatch[i]     = gslocalizer->getVOmatch(i);
00760     }
00761 
00762   // display the results
00763   Image<PixRGB<byte> > salIma = getSalImage(ima, iObject, iOffset, mfound);
00764   inplacePaste(dispIma, zoomXY(salIma), Point2D<int>(0,0));
00765 
00766   // display the gist histogram
00767   Image<byte> gistHistImg =
00768     gslocalizer->getSegmentHistogram()->getHistogramImage(w*3, h, 0.0F, 1.0F);
00769   inplacePaste(dispIma, Image<PixRGB<byte> >(gistHistImg), Point2D<int>(0,2*h));
00770 
00771   // display the localization belief
00772   int scale;
00773   Image<PixRGB<byte> > beliefImg =
00774     gslocalizer->getBeliefImage(w*2, h*3, scale);
00775 
00776   // draw the ground truth
00777   rutz::shared_ptr<Environment> env = gslocalizer->getEnvironment();
00778   uint snumGT; float ltravGT; gslocalizer->getGroundTruth(snumGT, ltravGT);
00779   float xGT = -1.0F, yGT = -1.0F;
00780   env->getLocationFloat(snumGT, ltravGT, xGT, yGT);
00781   if(ltravGT != -1.0F)
00782     {
00783       Point2D<int> loc(int(xGT*scale + .5), int(yGT*scale + .5));
00784       LDEBUG("Ground Truth disp %f %f -> %d %d", xGT, yGT, loc.i, loc.j);
00785       drawDisk(beliefImg,loc, 4, PixRGB<byte>(255,0,0));
00786     }
00787 
00788   // show where the objects indicate its position to be
00789   uint numObjectFound = 0;
00790   for(uint i = 0; i < ninput; i++)
00791     {
00792       if(mfound[i])
00793         {
00794           numObjectFound++;
00795           uint  snum  = gslocalizer->getSegmentNumberMatch(i);
00796           float ltrav = gslocalizer->getLengthTraveledMatch(i);
00797           float x, y;
00798           env->getLocationFloat(snum, ltrav, x, y);
00799           Point2D<int> loc(int(x*scale + .5), int(y*scale + .5));
00800           LDEBUG("obj[%d] res: %f %f -> %d %d",i, x, y, loc.i, loc.j);
00801           drawDisk(beliefImg, loc, 3, PixRGB<byte>(255,255,0));
00802         }
00803     }
00804   inplacePaste(dispIma, beliefImg, Point2D<int>(3*w,0));
00805 
00806   // display a found object found
00807   uint fcount = 0;
00808   for(uint i = 0; i < ninput; i++)
00809     {
00810       if(mfound[i] && fcount == 0)
00811         {
00812           fcount++;
00813 
00814           //display the first object match found
00815           Image<PixRGB<byte> >matchIma =
00816             gslocalizer->getMatchImage(i, Dims(w,h));
00817           std::string ntext(sformat("object[%d]", i));
00818           writeText(matchIma, Point2D<int>(0,0), ntext.c_str());
00819           inplacePaste(dispIma, matchIma, Point2D<int>(2*w,0));
00820         }
00821     }
00822   if(fcount == 0) writeText(dispIma, Point2D<int>(2*w,0),"no objects found");
00823 
00824   return dispIma;
00825 }
00826 
00827 // ######################################################################
00828 bool saveGist(std::string saveFilePath, std::string testRunFPrefix,
00829               int currSegNum, int count, Image<double> cgist)
00830 {
00831   char gName[100];
00832   sprintf(gName,"%s_%03d_%06d.gist",
00833           (saveFilePath + testRunFPrefix).c_str(), currSegNum, count);
00834   LINFO("save gist file to: %s\n", gName);
00835 
00836   // write the data to the gist file
00837   FILE *gfp; if((gfp = fopen(gName,"wb")) != NULL)
00838     {
00839       Image<double>::iterator aptr = cgist.beginw(), stop = cgist.endw();
00840       while (aptr != stop)
00841         { double val = *aptr++; fwrite(&val, sizeof(double), 1, gfp); }
00842       fclose(gfp);
00843     }
00844   else { LINFO("can't save: %s",gName); return false; }
00845 
00846   return true;
00847 }
00848 
00849 // ######################################################################
00850 void reportResults(std::string savePrefix, uint nsegment)
00851 {
00852   GSnavResult r;
00853 
00854   // combine the *_GS_result.txt and *_result.txt files
00855   r.combine(savePrefix);
00856 
00857   // read the result file
00858   r.read(savePrefix, nsegment);
00859 
00860   // create a result summary file
00861   r.createSummaryResult();
00862 }
00863 
00864 // ######################################################################
00865 void reportTrialResults()
00866 {
00867   // ===================================================================
00868   // RESULT Printing TR07
00869   // ===================================================================
00870 //   uint nsegment =  9;
00871 //   std::string savePrefix("/lab/tmpib/u/siagian/PAMI07/FDFpark/envComb/RES/FDFpark"),
00872 //   float scale = 2.0;
00873 //   // get the input off all the test files
00874 //   // open the result file
00875 //   uint nTrials = 4;
00876 //   std::vector<std::string> inputFName(nTrials);
00877 //   inputFName[0] = savePrefix + sformat("_T_A/ACB");
00878 //   inputFName[1] = savePrefix + sformat("_T_B/ACB");
00879 //   inputFName[2] = savePrefix + sformat("_T_E/ACB");
00880 //   inputFName[3] = savePrefix + sformat("_T_F/ACB");
00881 //   LINFO("%s", inputFName[0].c_str());
00882 
00883 //   std::vector<GSnavResult> r(nTrials);
00884 //   for(uint i = 0; i < nTrials; i++) r[i].read(inputFName[i], nsegment);
00885 
00886 //   // trial segment result lines
00887 //   for(uint j = 0; j < nsegment; j++)
00888 //     {
00889 //       // get segment total across trials
00890 //       printf("%4d &", j+1);
00891 //       float err = 0.0; uint ct = 0;
00892 //       for(uint i = 0; i < nTrials; i++)
00893 //         {
00894 //           err += r[i].serror[j];
00895 //           ct  += r[i].scount[j];
00896 //           printf("%6d & %8.2f &",
00897 //                  r[i].scount[j], scale * r[i].serror[j]/r[i].scount[j]);
00898 //         }
00899 //       printf(" %6d  & %8.2f \n", ct, scale *err/ct);
00900 //     }
00901 
00902 //   // trial total result lines
00903 //   float terr = 0.0; uint tct = 0;
00904 //   for(uint i = 0; i < nTrials; i++)
00905 //     {
00906 //       float err = 0.0; uint ct = 0;
00907 //       for(uint j = 0; j < nsegment; j++)
00908 //         { err += r[i].serror[j]; ct += r[i].scount[j]; }
00909 //       printf("%6d & %8.2f & ",  ct, scale * err/ct);
00910 //       terr += err; tct += ct;
00911 //     }
00912 //   printf(" %6d  & %8.2f \n", tct, scale * terr/tct);
00913 
00914   // ===================================================================
00915   // RESULT Printing ICRA07 + IJRR08
00916   // ===================================================================
00917   uint nsegment =  9;
00918 
00919   // ===================================================================
00920   // ACB
00921   std::string savePrefix
00922     ("/lab/tmpib/u/siagian/PAMI07/ACB/envComb/RES/ACB");
00923   float scale = 2.00;
00924   uint nSalReg = 29710;
00925   // 29710 82502 90660
00926   LINFO("%s has %d sal reg", savePrefix.c_str(), nSalReg);
00927 
00928   // get the input off all the result files
00929   uint nTrials = 6;
00930   std::vector<std::string> inputFName(nTrials);
00931   inputFName[0] = savePrefix + sformat("_T_A_rand2/ACB");
00932   inputFName[1] = savePrefix + sformat("_T_A_seg2/ACB");
00933   inputFName[2] = savePrefix + sformat("_T_A_sal2/ACB");
00934   inputFName[3] = savePrefix + sformat("_T_A_loc2/ACB");
00935   inputFName[4] = savePrefix + sformat("_T_A_nee/ACB");
00936   inputFName[5] = savePrefix + sformat("_T_A2/ACB");
00937 
00938   // supplement data for AR08
00939 //   uint nTrials = 5;
00940 //   std::vector<std::string> inputFName(nTrials);
00941 //   inputFName[0] = savePrefix + sformat("_T_A_prioritize/ACB_10_20_33");
00942 //   inputFName[1] = savePrefix + sformat("_T_A_prioritize/ACB_05_10_20");
00943 //   inputFName[2] = savePrefix + sformat("_T_A_prioritize/ACB_03_06_10");
00944 //   inputFName[3] = savePrefix + sformat("_T_A_prioritize/ACB_01_03_05");
00945 //   inputFName[4] = savePrefix + sformat("_T_A_prioritize/ACB_01_02_03");
00946 
00947   // supplement data 2 for AR08
00948 //   uint nTrials = 3;
00949 //   std::vector<std::string> inputFName(nTrials);
00950 //   inputFName[0] = savePrefix + sformat("_T_A_track/AAAI/ACB_inf_comb");
00951 //   inputFName[1] = savePrefix + sformat("_T_A_track/AAAI/ACB_200_comb");
00952 //   inputFName[2] = savePrefix + sformat("_T_A_track/AAAI/ACB_100_comb");
00953 
00954 
00955   // ===================================================================
00956   // AnF
00957 //   std::string savePrefix
00958 //     ("/lab/tmpib/u/siagian/PAMI07/AnFpark/envComb/RES/AnFpark");
00959 //   float scale = 1.00;
00960 //   uint nSalReg = 82502;
00961 //   LINFO("%s has %d sal reg", savePrefix.c_str(), nSalReg);
00962 
00963   // get the input off all the result files
00964 //   uint nTrials = 6;
00965 //   std::vector<std::string> inputFName(nTrials);
00966 //   inputFName[0] = savePrefix + sformat("_D_rand2/AnFpark");
00967 //   inputFName[1] = savePrefix + sformat("_D_seg2/AnFpark");
00968 //   inputFName[2] = savePrefix + sformat("_D_sal2/AnFpark");
00969 //   inputFName[3] = savePrefix + sformat("_D_loc2/AnFpark");
00970 //   inputFName[4] = savePrefix + sformat("_D_nee/AnFpark");
00971 //   inputFName[5] = savePrefix + sformat("_D2/AnFpark");
00972 
00973   // supplement data for AR08
00974 //   uint nTrials = 5;
00975 //   std::vector<std::string> inputFName(nTrials);
00976 //   inputFName[0] = savePrefix + sformat("_D_prioritize/AnFpark_10_20_33");
00977 //   inputFName[1] = savePrefix + sformat("_D_prioritize/AnFpark_05_10_20");
00978 //   inputFName[2] = savePrefix + sformat("_D_prioritize/AnFpark_03_06_10");
00979 //   inputFName[3] = savePrefix + sformat("_D_prioritize/AnFpark_01_03_05");
00980 //   inputFName[4] = savePrefix + sformat("_D_prioritize/AnFpark_01_02_03");
00981 
00982   // supplement data 2 for AR08
00983 //   uint nTrials = 5;
00984 //   std::vector<std::string> inputFName(nTrials);
00985 //   inputFName[0] = savePrefix + sformat("_D_track/AAAI/AnFpark_inf_comb");
00986 //   inputFName[1] = savePrefix + sformat("_D_track/AAAI/AnFpark_1000_comb");
00987 //   inputFName[2] = savePrefix + sformat("_D_track/AAAI/AnFpark_500_comb");
00988 //   inputFName[3] = savePrefix + sformat("_D_track/AAAI/AnFpark_200_comb");
00989 //   inputFName[4] = savePrefix + sformat("_D_track/AAAI/AnFpark_100_comb");
00990 
00991   // ===================================================================
00992   // FDF
00993 //   std::string savePrefix
00994 //     ("/lab/tmpib/u/siagian/PAMI07/FDFpark/envComb/RES/FDFpark");
00995 //   float scale = 3.75;
00996 //   uint nSalReg =  90660;
00997 //   LINFO("%s has %d sal reg", savePrefix.c_str(), nSalReg);
00998 
00999   // get the input off all the result files
01000 //   uint nTrials = 6;
01001 //   std::vector<std::string> inputFName(nTrials);
01002 //   inputFName[0] = savePrefix + sformat("_T_C_rand2/AnFpark");
01003 //   inputFName[1] = savePrefix + sformat("_T_C_seg2/AnFpark");
01004 //   inputFName[2] = savePrefix + sformat("_T_C_sal2/AnFpark");
01005 //   inputFName[3] = savePrefix + sformat("_T_C_loc2/AnFpark");
01006 //   inputFName[4] = savePrefix + sformat("_T_C_nee/AnFpark");
01007 //   inputFName[5] = savePrefix + sformat("_T_A2/AnFpark");
01008 
01009   // supplement data for IJRR08
01010   // NOTE: take out the "_comb" in the GSnavResult::read
01011 //   uint nTrials = 5;
01012 //   std::vector<std::string> inputFName(nTrials);
01013 //   inputFName[0] = savePrefix + sformat("_T_C_prioritize/FDFpark_10_20_33");
01014 //   inputFName[1] = savePrefix + sformat("_T_C_prioritize/FDFpark_05_10_20");
01015 //   inputFName[2] = savePrefix + sformat("_T_C_prioritize/FDFpark_03_06_10");
01016 //   inputFName[3] = savePrefix + sformat("_T_C_prioritize/FDFpark_01_03_05");
01017 //   inputFName[4] = savePrefix + sformat("_T_C_prioritize/FDFpark_01_02_03");
01018 
01019   // supplement data 2 for IJRR08
01020 //   uint nTrials = 5;
01021 //   std::vector<std::string> inputFName(nTrials);
01022 //   inputFName[0] = savePrefix + sformat("_T_C_track/AAAI/FDFpark_inf_comb");
01023 //   inputFName[1] = savePrefix + sformat("_T_C_track/AAAI/FDFpark_1000_comb");
01024 //   inputFName[2] = savePrefix + sformat("_T_C_track/AAAI/FDFpark_500_comb");
01025 //   inputFName[3] = savePrefix + sformat("_T_C_track/AAAI/FDFpark_200_comb");
01026 //   inputFName[4] = savePrefix + sformat("_T_C_track/AAAI/FDFpark_100_comb");
01027 
01028   std::vector<GSnavResult> r(nTrials);
01029   for(uint i = 0; i < nTrials; i++)
01030     {
01031       r[i].read(inputFName[i], nsegment);
01032       //r[i].createSummaryResult();
01033     }
01034 
01035   // for each episode
01036   for(uint i = 0; i < nTrials; i++)
01037     {
01038       LINFO("%6d %10d: %10.3f + %6d %10d: %10.3f = %6d %10d %10.3f| "
01039             "%6d %10.6f",
01040             r[i].tfobj,  r[i].tfsearch,  r[i].tfsearch/float(r[i].tfobj),
01041             r[i].tnfobj, r[i].tnfsearch, r[i].tnfsearch/float(r[i].tnfobj),
01042             r[i].tobj,   r[i].tsearch,   r[i].tsearch/float(r[i].tobj),
01043             r[i].tcount, r[i].terror/r[i].tcount*scale);
01044     }
01045 
01046   // for each episode
01047   for(uint i = 0; i < nTrials; i++)
01048     {
01049       printf("& %10.2f\\%% & $%6.2f \\pm %6.2f$ "
01050              "& %10.2f\\%% & $%6.2f \\pm %6.2f$ "
01051              "& %10.2f\\%% & $%6.2f \\pm %6.2f$ & $%6.2f \\pm %6.2f$\\\\ \n",
01052              r[i].tfsearch/float(r[i].tfobj)/nSalReg*100.0,
01053              float(r[i].tfobj)/r[i].tcount, r[i].stdevNObjectFound,
01054              r[i].tnfsearch/float(r[i].tnfobj)/nSalReg*100.0,
01055              float(r[i].tnfobj)/r[i].tcount, r[i].stdevNObjectNotFound,
01056              r[i].tsearch/float(r[i].tobj)/nSalReg*100.0,
01057              float(r[i].tobj)/r[i].tcount, r[i].stdevNObject,
01058              r[i].terror/r[i].tcount*scale, r[i].stdevError*scale);
01059     }
01060 }
01061 
01062 // ######################################################################
01063 /* So things look consistent in everyone's emacs... */
01064 /* Local Variables: */
01065 /* indent-tabs-mode: nil */
01066 /* End: */
Generated on Sun May 8 08:40:12 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3