00001 /*!@file Demo/test-SaliencyMT.C tests the multi-threaded salincy code */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Zack Gossman <gossman@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Demo/test-SaliencyMT.C $ 00035 // $Id: test-SaliencyMT.C 12074 2009-11-24 07:51:51Z itti $ 00036 // 00037 00038 #ifndef TESTSALIENCYMT_H_DEFINED 00039 #define TESTSALIENCYMT_H_DEFINED 00040 00041 #include "Component/ModelManager.H" 00042 #include "Demo/SaliencyMT.H" 00043 #include "Devices/DeviceOpts.H" 00044 #include "Devices/FrameGrabberConfigurator.H" 00045 #include "GUI/XWindow.H" 00046 #include "Image/CutPaste.H" // for inplacePaste() 00047 #include "Image/Image.H" 00048 #include "Image/Pixels.H" 00049 #include "Neuro/NeuroOpts.H" 00050 #include "Neuro/SaccadeController.H" 00051 #include "Neuro/SaccadeControllerConfigurator.H" 00052 #include "Raster/Raster.H" 00053 #include "Simulation/SimEventQueue.H" 00054 #include "Simulation/SimEventQueueConfigurator.H" 00055 #include "Transport/FrameIstream.H" 00056 #include "Util/Timer.H" 00057 00058 #include <arpa/inet.h> 00059 #include <fcntl.h> 00060 #include <netdb.h> 00061 #include <signal.h> 00062 #include <cstdio> 00063 #include <unistd.h> 00064 00065 //! Number of frames over which average framerate is computed 00066 #define NAVG 20 00067 00068 //! Factor to display the sm values as greyscale: 00069 #define SMFAC 0.05F 00070 00071 // UDP communications: 00072 #define UDPHOST "192.168.0.8" 00073 #define UDPPORT 5003 00074 00075 static bool goforever = true; //!< Will turn false on interrupt signal 00076 00077 //! Signal handler (e.g., for control-C) 00078 void terminate(int s) 00079 { LERROR("*** INTERRUPT ***"); goforever = false; exit(1); } 00080 00081 // ###################################################################### 00082 int main(const int argc, const char **argv) 00083 { 00084 MYLOGVERB = LOG_INFO; 00085 00086 // instantiate a model manager (for camera input): 00087 ModelManager manager("SaliencyMT Tester"); 00088 00089 // Instantiate our various ModelComponents: 00090 nub::soft_ref<SimEventQueueConfigurator> 00091 seqc(new SimEventQueueConfigurator(manager)); 00092 manager.addSubComponent(seqc); 00093 00094 nub::ref<FrameGrabberConfigurator> 00095 gbc(new FrameGrabberConfigurator(manager)); 00096 manager.addSubComponent(gbc); 00097 00098 nub::ref<SaliencyMT> smt(new SaliencyMT(manager)); 00099 manager.addSubComponent(smt); 00100 00101 nub::ref<SaccadeControllerEyeConfigurator> 00102 scc(new SaccadeControllerEyeConfigurator(manager)); 00103 manager.addSubComponent(scc); 00104 00105 // Set the appropriate defaults for our machine that is connected to 00106 // Stefan's robot head: 00107 manager.exportOptions(MC_RECURSE); 00108 manager.setOptionValString(&OPT_FrameGrabberType, "V4L"); 00109 manager.setOptionValString(&OPT_FrameGrabberChannel, "1"); 00110 manager.setOptionValString(&OPT_FrameGrabberHue, "0"); 00111 manager.setOptionValString(&OPT_FrameGrabberContrast, "16384"); 00112 manager.setOptionValString(&OPT_FrameGrabberDims, "320x240"); 00113 manager.setOptionValString(&OPT_SaccadeControllerEyeType, "Threshfric"); 00114 manager.setOptionValString(&OPT_SCeyeMaxIdleSecs, "1000.0"); 00115 manager.setOptionValString(&OPT_SCeyeThreshMinOvert, "4.0"); 00116 manager.setOptionValString(&OPT_SCeyeThreshMaxCovert, "3.0"); 00117 manager.setOptionValString(&OPT_SCeyeThreshMinNum, "2"); 00118 // manager.setOptionValString(&OPT_SCeyeSpringK, "1000000.0"); 00119 00120 // Parse command-line: 00121 if (manager.parseCommandLine(argc, argv, "", 0, 0) == false) return(1); 00122 00123 // do post-command-line configs: 00124 nub::soft_ref<SimEventQueue> seq = seqc->getQ(); 00125 00126 nub::soft_ref<FrameIstream> gb = gbc->getFrameGrabber(); 00127 if (gb.isInvalid()) 00128 LFATAL("You need to select a frame grabber type via the " 00129 "--fg-type=XX command-line option for this program " 00130 "to be useful"); 00131 const int w = gb->getWidth(), h = gb->getHeight(); 00132 00133 nub::ref<SaccadeController> sc = scc->getSC(); 00134 00135 const int foa_size = std::min(w, h) / 12; 00136 manager.setModelParamVal("InputFrameDims", Dims(w, h), 00137 MC_RECURSE | MC_IGNORE_MISSING); 00138 manager.setModelParamVal("SCeyeStartAtIP", true, 00139 MC_RECURSE | MC_IGNORE_MISSING); 00140 manager.setModelParamVal("SCeyeInitialPosition", Point2D<int>(w/2,h/2), 00141 MC_RECURSE | MC_IGNORE_MISSING); 00142 manager.setModelParamVal("FOAradius", foa_size, 00143 MC_RECURSE | MC_IGNORE_MISSING); 00144 manager.setModelParamVal("FoveaRadius", foa_size, 00145 MC_RECURSE | MC_IGNORE_MISSING); 00146 00147 // catch signals and redirect them to terminate for clean exit: 00148 signal(SIGHUP, terminate); signal(SIGINT, terminate); 00149 signal(SIGQUIT, terminate); signal(SIGTERM, terminate); 00150 signal(SIGALRM, terminate); 00151 00152 // setup socket: 00153 int sock = socket(AF_INET, SOCK_DGRAM, 0); 00154 if (sock == -1) PLFATAL("Cannot create server socket"); 00155 00156 // figure out destination address: 00157 struct hostent *he = gethostbyname(UDPHOST); 00158 if (he == NULL) LFATAL("Cannot gethostbyname on %s", UDPHOST); 00159 00160 struct sockaddr_in destaddr; 00161 destaddr.sin_family = AF_INET; 00162 destaddr.sin_addr.s_addr = 00163 inet_addr(inet_ntoa(*((in_addr *)(he->h_addr_list[0])))); 00164 destaddr.sin_port = htons(UDPPORT); 00165 00166 // get prepared to grab, communicate, display, etc: 00167 uint frame = 0U; // count the frames 00168 uint lastframesent = 0U; // last frame sent for processing 00169 00170 uint64 avgtime = 0; int avgn = 0; // for average framerate 00171 float fps = 0.0F; // to display framerate 00172 Timer tim; // for computation of framerate 00173 Timer masterclock; // master clock for simulations 00174 00175 int sml = 3; // pyramid level of saliency map 00176 Image<float> sm(w >> sml, h >> sml, ZEROS); // saliency map 00177 Point2D<int> fixation(-1, -1); // coordinates of eye fixation 00178 00179 // image buffer for display: 00180 Image<PixRGB<byte> > disp(w * 2, h + 20, ZEROS); 00181 disp += PixRGB<byte>(128); 00182 XWindow xwin(disp.getDims(), -1, -1, "USC Robot Demo"); 00183 00184 /// int ovlyoff = (w * 2) * ((dh - disp.getHeight()) / 2); 00185 ///int ovluvoff = ovlyoff / 4; 00186 00187 char info[1000]; // general text buffer for various info messages 00188 00189 Point2D<int> lastpointsent(w/2, h/2); 00190 00191 // ###################################################################### 00192 try { 00193 // let's do it! 00194 manager.start(); 00195 00196 // get the frame grabber to start streaming: 00197 gb->startStream(); 00198 00199 // initialize the timers: 00200 tim.reset(); masterclock.reset(); 00201 00202 while(goforever) 00203 { 00204 // grab image: 00205 Image< PixRGB<byte> > ima = gb->readRGB(); 00206 00207 // display image: 00208 inplacePaste(disp, ima, Point2D<int>(0, 0)); 00209 Image<float> dispsm = sm * SMFAC; 00210 inplacePaste(disp, Image<PixRGB<byte> > 00211 (toRGB(quickInterpolate(dispsm, 1 << sml))), 00212 Point2D<int>(w, 0)); 00213 00214 sc->evolve(*seq); 00215 Point2D<int> eye = sc->getDecision(*seq); 00216 if (eye.i >= 0) fixation = eye; 00217 Point2D<int> fix2(fixation); fix2.i += w; 00218 if (fixation.i >= 0) 00219 { 00220 drawDisk(disp, fixation, foa_size/6+2, PixRGB<byte>(20, 50, 255)); 00221 drawDisk(disp, fixation, foa_size/6, PixRGB<byte>(255, 255, 20)); 00222 drawDisk(disp, fix2, foa_size/6+2, PixRGB<byte>(20, 50, 255)); 00223 drawDisk(disp, fix2, foa_size/6, PixRGB<byte>(255, 255, 20)); 00224 } 00225 00226 xwin.drawImage(disp); 00227 00228 // are we ready to process a new frame? if so, send our new one: 00229 if (smt->outputReady()) 00230 { 00231 // let's get the previous results, if any: 00232 Image<float> out = smt->getOutput(); 00233 if (out.initialized()) sm = out; 00234 00235 // find most salient location and feed saccade controller: 00236 float maxval; Point2D<int> currwin; findMax(sm, currwin, maxval); 00237 WTAwinner newwin = 00238 WTAwinner::buildFromSMcoords(currwin, sml, true, 00239 masterclock.getSimTime(), 00240 maxval, false); 00241 if (newwin.isValid()) sc->setPercept(newwin, *seq); 00242 00243 // feed our current image as next one to process: 00244 smt->newInput(decXY(ima)); 00245 lastframesent = frame; 00246 //LINFO("Processing frame %u", frame); 00247 00248 // send UDP packet: 00249 lastpointsent.i = newwin.p.i * 2; lastpointsent.j = newwin.p.j * 2; 00250 00251 const size_t buflen = 4; 00252 int buf[buflen]; 00253 buf[0] = htonl(1234); buf[1] = htonl(lastpointsent.i); 00254 buf[2] = htonl(lastpointsent.j); buf[3] = htonl(5678); 00255 00256 // send message: 00257 size_t ret = sendto(sock, buf, buflen * sizeof(int), 0, 00258 (sockaddr*)(&destaddr), sizeof(destaddr)); 00259 if (ret != buflen * sizeof(int)) 00260 LERROR("Only %"ZU"/%"ZU" bytes sent to %s:%d", ret, buflen*sizeof(int), 00261 inet_ntoa(destaddr.sin_addr), 00262 ntohs(destaddr.sin_port)); 00263 } 00264 00265 // compute and show framerate and stats over the last NAVG frames: 00266 avgtime += tim.getReset(); avgn ++; 00267 if (avgn == NAVG) 00268 { 00269 fps = 1000.0F / float(avgtime) * float(avgn); 00270 avgtime = 0; avgn = 0; 00271 } 00272 00273 // create an info string: 00274 sprintf(info, "USC - %06u / %06u - [%03d %03d] to %s:%d - %.1ffps ", 00275 frame, lastframesent, lastpointsent.i, lastpointsent.j, 00276 inet_ntoa(destaddr.sin_addr), ntohs(destaddr.sin_port), fps); 00277 00278 writeText(disp, Point2D<int>(0, h), info, 00279 PixRGB<byte>(255), PixRGB<byte>(127)); 00280 00281 // ready for next frame: 00282 ++ frame; 00283 while(seq->now() < masterclock.getSimTime()) seq->evolve(); 00284 } 00285 00286 // get ready to terminate: 00287 manager.stop(); 00288 close(sock); 00289 00290 } catch ( ... ) { }; 00291 00292 return 0; 00293 } 00294 00295 #endif 00296 // ###################################################################### 00297 /* So things look consistent in everyone's emacs... */ 00298 /* Local Variables: */ 00299 /* indent-tabs-mode: nil */ 00300 /* End: */