00001 /*!@file */ 00002 // //////////////////////////////////////////////////////////////////// // 00003 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00004 // University of Southern California (USC) and the iLab at USC. // 00005 // See http://iLab.usc.edu for information about this project. // 00006 // //////////////////////////////////////////////////////////////////// // 00007 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00008 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00009 // in Visual Environments, and Applications'' by Christof Koch and // 00010 // Laurent Itti, California Institute of Technology, 2001 (patent // 00011 // pending; application number 09/912,225 filed July 23, 2001; see // 00012 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00013 // //////////////////////////////////////////////////////////////////// // 00014 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00015 // // 00016 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00017 // redistribute it and/or modify it under the terms of the GNU General // 00018 // Public License as published by the Free Software Foundation; either // 00019 // version 2 of the License, or (at your option) any later version. // 00020 // // 00021 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00022 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00023 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00024 // PURPOSE. See the GNU General Public License for more details. // 00025 // // 00026 // You should have received a copy of the GNU General Public License // 00027 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00028 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00029 // Boston, MA 02111-1307 USA. // 00030 // //////////////////////////////////////////////////////////////////// // 00031 // 00032 // Primary maintainer for this file: Christian Siagian <siagian@usc.edu> 00033 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/Beobot2/Localization/Beobot2GistSalMaster.C $ 00034 // $Id: Beobot2GistSalMaster.C 13085 2010-03-30 03:21:24Z siagian $ 00035 // 00036 00037 #include "Robots/Beobot2/Localization/Beobot2GistSalMaster.H" 00038 00039 #include "Image/MathOps.H" // for findMax 00040 #include "Image/CutPaste.H" // for inplacePaste() 00041 #include "Image/DrawOps.H" 00042 #include "Image/FilterOps.H" 00043 #include "Image/PyramidOps.H" 00044 #include "Image/ShapeOps.H" 00045 #include "Image/Transforms.H" 00046 00047 00048 #ifndef BEOBOT2GISTSALMASTERI_C 00049 #define BEOBOT2GISTSALMASTERI_C 00050 00051 #define ERR_INTERVAL 5000 00052 00053 //! get all the necessary information from the visual cortex 00054 void getBbmtResults 00055 ( nub::soft_ref<BeobotBrainMT> bbmt, 00056 Image<PixRGB<byte> > &currIma, Image<double> &cgist, 00057 Image<float> &currSalMap, ImageSet<float> &cmap, 00058 std::vector<Point2D<int> > &salpt, std::vector<std::vector<double> > &feat, 00059 std::vector<Rectangle> &objRect, 00060 BeobotEvents::GistSalMessagePtr msg); 00061 00062 //! display results 00063 void dispResults 00064 ( Image< PixRGB<byte> > disp, rutz::shared_ptr<XWinManaged> win, 00065 Image< PixRGB<byte> > ima, Image< PixRGB<byte> > prevIma, 00066 std::vector<Point2D<int> > clmpt, std::vector<Point2D<int> > nlmpt, 00067 Image<float> currSalMap, 00068 std::vector<Point2D<int> > salpt, std::vector<Rectangle> objRect); 00069 00070 // ###################################################################### 00071 Beobot2GistSalMasterI::Beobot2GistSalMasterI(OptionManager& mgr, 00072 const std::string& descrName, const std::string& tagName) : 00073 RobotBrainComponent(mgr, descrName, tagName), 00074 itsIfs(new InputFrameSeries(mgr)), 00075 itsBbmt(new BeobotBrainMT(mgr)), 00076 itsCurrMessageID(-1), 00077 itsInputFrameRate(0), 00078 itsInputTimer(1000000) 00079 { 00080 addSubComponent(itsIfs); 00081 addSubComponent(itsBbmt); 00082 00083 itsCmap.reset(NUM_CHANNELS); 00084 } 00085 00086 // ###################################################################### 00087 void Beobot2GistSalMasterI::start1() 00088 { 00089 00090 int w = itsIfs->getWidth(), 00091 h = itsIfs->getHeight(); 00092 std::string dims = convertToString(Dims(w, h)); 00093 LINFO("image size: [%4dx%4d]", w, h); 00094 00095 // image buffer and window for display: 00096 //itsDisp = Image<PixRGB<byte> >(w * 5, h, ZEROS); 00097 // //itsDisp = Image<PixRGB<byte> >(w, h, ZEROS); 00098 //itsMwin.reset 00099 // (new XWinManaged(itsDisp.getDims(), 0, 0, "Master window")); 00100 00101 itsNextFrameFlag = true; 00102 itsInputTimer.reset(); 00103 itsTimes.clear(); 00104 } 00105 00106 // ###################################################################### 00107 Beobot2GistSalMasterI::~Beobot2GistSalMasterI() 00108 { } 00109 00110 // ###################################################################### 00111 void Beobot2GistSalMasterI::registerTopics() 00112 { 00113 this->registerPublisher("GistSalMessageTopic"); 00114 this->registerPublisher("AbortMessageTopic"); 00115 00116 this->registerSubscription("NextFrameMessageTopic"); 00117 } 00118 00119 // ###################################################################### 00120 void Beobot2GistSalMasterI::evolve() 00121 { 00122 // check if we can go to next frame 00123 if((itsInputFrameRate == 0 && itsNextFrameFlag) || 00124 (itsInputFrameRate != 0 && 00125 itsInputTimer.get() > (itsInputFrameRate - ERR_INTERVAL))) 00126 { 00127 if(itsCurrMessageID != -1) 00128 { 00129 float loopTime = itsInputTimer.get()/1000.0F; 00130 itsTimes.push_back(loopTime); 00131 LINFO("[%5d] Time: %f", itsCurrMessageID, loopTime); 00132 } 00133 itsInputTimer.reset(); 00134 itsNextFrameFlag = false; 00135 itsCurrMessageID++; 00136 00137 // get the next frame and start processing 00138 std::vector<float> procTime; 00139 Image<PixRGB<byte> > ima; //int32 fNum = itsCurrMessageID;//fstart; 00140 Image<PixRGB<byte> > prevIma; 00141 itsIfs->updateNext(); ima = itsIfs->readRGB(); 00142 if(ima.initialized()) 00143 { 00144 itsBbmt->input(ima); 00145 00146 // wait until the saliency and gist computation is ready 00147 Timer bbmtTimer(1000000); 00148 // this takes 40 ms or so 00149 while(!itsBbmt->outputReady()) usleep(100); 00150 float bbmtTime = bbmtTimer.get()/1000.0F; 00151 LINFO("BBMT Time: %f", bbmtTime); 00152 00153 // prepare the Sal Regions and Gist features message 00154 BeobotEvents::GistSalMessagePtr msg = 00155 new BeobotEvents::GistSalMessage; 00156 00157 // get all the necesary information from V1: 00158 Image<PixRGB<byte> > currIma; Image<float> currSalMap; 00159 Image<double> cgist; 00160 std::vector<Point2D<int> > salpt; 00161 std::vector<std::vector<double> >feat; 00162 std::vector<Rectangle> objRect; 00163 getBbmtResults(itsBbmt, currIma, cgist, currSalMap, 00164 itsCmap, salpt, feat, objRect, msg); 00165 00166 // display the results 00167 // //itsMwin->drawImage(currIma,0,0); 00168 //itsMwin->setTitle(sformat("fNum: %d",fNum).c_str()); 00169 //dispResults(itsDisp, itsMwin, currIma, prevIma, 00170 // itsClmpt, itsNlmpt, 00171 // currSalMap, salpt, objRect); 00172 00173 msg->RequestID = itsCurrMessageID; 00174 00175 // publish the message 00176 LINFO("Publishing Message with ID: %d", itsCurrMessageID); 00177 publish("GistSalMessageTopic", msg); 00178 } 00179 00180 // we are done 00181 else 00182 { 00183 // display the loop statistics 00184 double meanTime, minTime, maxTime, stdevTime; 00185 Image<double> t1(1, itsTimes.size(),NO_INIT); 00186 for(uint i = 0; i < itsTimes.size(); i++) 00187 t1.setVal(0, i, double(itsTimes[i])); 00188 00189 meanTime = mean(t1); 00190 getMinMax(t1, minTime, maxTime); 00191 stdevTime = stdev(t1); 00192 00193 LINFO("Time: %f (%f - %f) std: %f", 00194 meanTime, minTime, maxTime, stdevTime); 00195 00196 // send an abort message 00197 BeobotEvents::AbortMessagePtr msg = 00198 new BeobotEvents::AbortMessage; 00199 00200 LINFO("Publishing AbortMessage"); 00201 publish("AbortMessageTopic", msg); 00202 00203 sleep(5); 00204 exit(0); 00205 } 00206 } 00207 } 00208 00209 // ###################################################################### 00210 void Beobot2GistSalMasterI::updateMessage 00211 (const RobotSimEvents::EventMessagePtr& eMsg, const Ice::Current&) 00212 { 00213 //Get a retina message 00214 if(eMsg->ice_isA("::BeobotEvents::NextFrameMessage")) 00215 { 00216 LINFO("NextFrameMessage - go to the next frame"); 00217 if(itsInputFrameRate == 0) 00218 { 00219 //Raster::waitForKey(); 00220 itsNextFrameFlag = true; 00221 } 00222 } 00223 } 00224 00225 // ###################################################################### 00226 bool checkInput(int opMode, bool resetNextLandmark, uint64 inputFrameRate, 00227 uint64 inputTime) 00228 { 00229 // if train mode: need to have a ventral reset signal 00230 if(opMode == TRAIN_MODE && resetNextLandmark) return true; 00231 00232 // if test mode and using infinite time: need reset signal 00233 if(opMode == TEST_MODE && inputFrameRate == 0 && 00234 resetNextLandmark) return true; 00235 00236 // else test mode and need to get in after time is up 00237 if(opMode == TEST_MODE && inputFrameRate != 0 && 00238 (inputFrameRate - ERR_INTERVAL) < inputTime) return true; 00239 00240 return false; 00241 } 00242 00243 // ###################################################################### 00244 void getBbmtResults 00245 ( nub::soft_ref<BeobotBrainMT> bbmt, 00246 Image<PixRGB<byte> > &currIma, Image<double> &cgist, 00247 Image<float> &currSalMap, ImageSet<float> &cmap, 00248 std::vector<Point2D<int> > &salpt, std::vector<std::vector<double> > &feat, 00249 std::vector<Rectangle> &objRect, 00250 BeobotEvents::GistSalMessagePtr msg) 00251 { 00252 // current image, gist vector, and saliency map 00253 currIma = bbmt->getCurrImage(); 00254 cgist = bbmt->getGist(); 00255 currSalMap = bbmt->getSalMap(); 00256 00257 // current conspicuity maps 00258 for(uint i = 0; i < NUM_CHANNELS; i++) cmap[i] = bbmt->getCurrCMap(i); 00259 00260 salpt.clear(); objRect.clear(); 00261 uint numpt = bbmt->getNumSalPoint(); 00262 for(uint i = 0; i < numpt; i++) 00263 { 00264 salpt.push_back(bbmt->getSalPoint(i)); 00265 objRect.push_back(bbmt->getObjRect(i)); 00266 00267 // store the salient point location 00268 BeobotEvents::SalientRegion salReg; 00269 salReg.salpt.i = salpt[i].i; 00270 salReg.salpt.j = salpt[i].j; 00271 salReg.objRect.tl.i = objRect[i].topLeft().i; 00272 salReg.objRect.tl.j = objRect[i].topLeft().j; 00273 salReg.objRect.br.i = objRect[i].bottomRight().i; 00274 salReg.objRect.br.j = objRect[i].bottomRight().j; 00275 LDEBUG("[%4d] sp[%4d,%4d] rect[%4d,%4d,%4d,%4d]", 00276 i, salpt[i].i, salpt[i].j, 00277 objRect[i].topLeft().i,objRect[i].topLeft().j, 00278 objRect[i].bottomRight().i,objRect[i].bottomRight().j); 00279 00280 std::vector<double> features; bbmt->getSalientFeatures(i, features); 00281 feat.push_back(features); 00282 00283 // store the salient feature vector 00284 for(uint j = 0; j < features.size(); j++) 00285 { 00286 salReg.salFeatures.push_back(feat[i][j]); 00287 LDEBUG("[%4d]:%7f", j, feat[i][j]); 00288 } 00289 msg->salientRegions.push_back(salReg); 00290 } 00291 00292 // store the input image 00293 msg->currIma = Image2Ice(currIma); 00294 00295 // store the conspicuity maps 00296 for(uint i = 0; i < NUM_CHANNELS; i++) 00297 msg->conspicuityMaps.push_back(Image2Ice(cmap[i])); 00298 00299 // store the gist in the message 00300 for(uint i = 0; i < cgist.size(); i++) 00301 msg->gistFeatures.push_back(cgist[i]); 00302 } 00303 00304 // ###################################################################### 00305 void dispResults 00306 ( Image< PixRGB<byte> > disp, rutz::shared_ptr<XWinManaged> win, 00307 Image< PixRGB<byte> > ima, Image< PixRGB<byte> > prevIma, 00308 std::vector<Point2D<int> > clmpt, std::vector<Point2D<int> > nlmpt, 00309 Image<float> currSalMap, 00310 std::vector<Point2D<int> > salpt, std::vector<Rectangle> objRect) 00311 { 00312 int w = ima.getWidth(); 00313 int h = ima.getHeight(); 00314 const int foa_size = std::min(w, h) / 12; 00315 00316 // display input image: 00317 inplacePaste(disp, ima, Point2D<int>(0, 0)); 00318 00319 // display the saliency map 00320 Image<float> dispsm = quickInterpolate(currSalMap * SMFAC, 1 << sml); 00321 inplaceNormalize(dispsm, 0.0f, 255.0f); 00322 Image<PixRGB<byte> > sacImg = Image<PixRGB<byte> >(toRGB(dispsm)); 00323 for(uint i = 0; i < objRect.size(); i++) 00324 drawRect(sacImg,objRect[i],PixRGB<byte>(255,0,0)); 00325 inplacePaste(disp, sacImg, Point2D<int>(w, 0)); 00326 00327 // draw coordinates of fixation for both input and sal image 00328 for(uint i = 0; i < salpt.size(); i++) 00329 { 00330 Point2D<int> salpt2(salpt[i].i + w, salpt[i].j); 00331 drawDisk(disp, salpt[i], foa_size/6+2, PixRGB<byte>(20, 50, 255)); 00332 drawDisk(disp, salpt[i], foa_size/6, PixRGB<byte>(255, 255, 20)); 00333 drawDisk(disp, salpt2, foa_size/6+2, PixRGB<byte>(20, 50, 255)); 00334 drawDisk(disp, salpt2, foa_size/6, PixRGB<byte>(255, 255, 20)); 00335 } 00336 00337 // draw the SE bounding box 00338 Image< PixRGB<byte> > roiImg = ima; 00339 for(uint i = 0; i < objRect.size(); i++) 00340 { 00341 drawRect(roiImg, objRect[i], PixRGB<byte>(255,255,0)); 00342 drawDisk(roiImg, salpt[i], 3, PixRGB<byte>(255,0,0)); 00343 std::string ntext(sformat("%d", i)); 00344 writeText(roiImg, salpt[i], ntext.c_str()); 00345 } 00346 inplacePaste(disp, roiImg, Point2D<int>(w*2, 0)); 00347 00348 // if there is a previous image 00349 if(prevIma.initialized()) 00350 { 00351 // display the current landmark tracked 00352 Image< PixRGB<byte> > clmDisp = prevIma; 00353 for(uint i = 0; i < clmpt.size(); i++) 00354 { 00355 if(clmpt[i].isValid()) 00356 { 00357 drawDisk(clmDisp, clmpt[i], 3, PixRGB<byte>(0,255,0)); 00358 std::string ntext(sformat("%d", i)); 00359 writeText(clmDisp, clmpt[i], ntext.c_str()); 00360 } 00361 } 00362 inplacePaste(disp, clmDisp, Point2D<int>(w*3, 0)); 00363 00364 // display the next landmark tracked 00365 Image< PixRGB<byte> > nlmDisp = prevIma; 00366 for(uint i = 0; i < nlmpt.size(); i++) 00367 { 00368 if(nlmpt[i].isValid()) 00369 { 00370 drawDisk(nlmDisp, nlmpt[i], 3, PixRGB<byte>(0,255,255)); 00371 std::string ntext(sformat("%d", i)); 00372 writeText(nlmDisp, nlmpt[i], ntext.c_str()); 00373 } 00374 } 00375 inplacePaste(disp, nlmDisp, Point2D<int>(w*4, 0)); 00376 } 00377 00378 // display the image 00379 //win->drawImage(disp,0,0); 00380 } 00381 00382 #endif 00383 00384 // ###################################################################### 00385 /* So things look consistent in everyone's emacs... */ 00386 /* Local Variables: */ 00387 /* indent-tabs-mode: nil */ 00388 /* End: */