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 <ravGT); 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 <ravGT) 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: */