pvisionTCP2-master.C

Go to the documentation of this file.
00001 /*!@file Parallel/pvisionTCP2-master.C Grab & process over beowulf w/ pvisionTCP2 */
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: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Parallel/pvisionTCP2-master.C $
00035 // $Id: pvisionTCP2-master.C 9412 2008-03-10 23:10:15Z farhan $
00036 //
00037 
00038 /*! This parallel vision processing master is for use with pvisionTCP2.
00039   See the pvisionTCP2go script in bin/ for how to launch the slaves.
00040 */
00041 
00042 #include "Beowulf/Beowulf.H"
00043 #include "Component/ModelManager.H"
00044 #include "Devices/FrameGrabberConfigurator.H"
00045 #include "GUI/XWindow.H"
00046 #include "Image/ColorOps.H"
00047 #include "Image/CutPaste.H"   // for inplacePaste()
00048 #include "Image/DrawOps.H"
00049 #include "Image/FilterOps.H"
00050 #include "Image/Image.H"
00051 #include "Image/Image.H"
00052 #include "Image/ImageSet.H"
00053 #include "Image/MathOps.H"
00054 #include "Image/Pixels.H"
00055 #include "Image/ShapeOps.H"   // for decX() etc.
00056 #include "Parallel/pvisionTCP-defs.H"
00057 #include "Transport/FrameIstream.H"
00058 #include "Util/Assert.H"
00059 #include "Util/Timer.H"
00060 
00061 #include <signal.h>
00062 #include <unistd.h>
00063 
00064 
00065 //! Number of frames over which average framerate is computed
00066 #define NAVG 20
00067 //! Number of stats collected
00068 #define NSTAT 4
00069 
00070 //! prescale level by which we downsize images before sending them off
00071 #define PRESCALE 2
00072 
00073 //! shift attention at most once every SHIFTINT frames
00074 #define SHIFTINT 5
00075 
00076 //! injection ratio between new and older sm:
00077 #define SMINJECT 0.6f
00078 
00079 //! threshold salience (between 0 and 255) to warrant a shift of attention
00080 #define SMTHRESH 200
00081 
00082 static bool goforever = true;  //!< Will turn false on interrupt signal
00083 
00084 //! Signal handler (e.g., for control-C)
00085 void terminate(int s)
00086 { LERROR("*** INTERRUPT ***"); goforever = false; exit(1); }
00087 
00088 // ######################################################################
00089 int main(const int argc, const char **argv)
00090 {
00091   MYLOGVERB = LOG_INFO;
00092 
00093   // instantiate a model manager:
00094   ModelManager manager("Parallel Vision TCP Version 2");
00095 
00096   // Instantiate our various ModelComponents:
00097   nub::soft_ref<FrameGrabberConfigurator>
00098     gbc(new FrameGrabberConfigurator(manager));
00099   manager.addSubComponent(gbc);
00100 
00101   nub::soft_ref<Beowulf>
00102     beo(new Beowulf(manager, "Beowulf Master", "BeowulfMaster", true));
00103   manager.addSubComponent(beo);
00104 
00105   // Parse command-line:
00106   if (manager.parseCommandLine(argc, argv, "", 0, 0) == false) return(1);
00107 
00108   // do post-command-line configs:
00109   nub::soft_ref<FrameIstream> gb = gbc->getFrameGrabber();
00110   if (gb.isInvalid())
00111     LFATAL("You need to select a frame grabber type via the "
00112            "--fg-type=XX command-line option for this program "
00113            "to be useful");
00114   int w = gb->getWidth(), h = gb->getHeight();
00115 
00116   // catch signals and redirect them to terminate for clean exit:
00117   signal(SIGHUP, terminate); signal(SIGINT, terminate);
00118   signal(SIGQUIT, terminate); signal(SIGTERM, terminate);
00119   signal(SIGALRM, terminate);
00120 
00121   // get prepared to grab, communicate, display, etc:
00122   XWindow xw(Dims(w * 2, h), -1, -1, "USC Saliency Cam");
00123   Image<PixRGB<byte> > disp(w * 2, h, ZEROS);
00124   int32 frame = 0;                // count the frames
00125   PixRGB<byte> pix(255, 255, 0);  // yellow color for fixations
00126   Point2D<int> win(w/2, h/2), winsm; // coordinates of attended location
00127   int foa_size = std::min(w, h) / 12; // radius of focus of attention
00128   TCPmessage rmsg;      // buffer to receive messages from nodes
00129   TCPmessage smsg;      // buffer to send messages to nodes
00130   Timer tim;            // for computation of framerate
00131   int t[NSTAT][NAVG], ff; // to compute average framerate and other stats
00132   int latency = 0, nlat = 0;  // to compute average processing latency
00133   int lastshift = 0;    // frame of last shift
00134   int sml = 4; Image<byte> sm;
00135 
00136   // let's get all our ModelComponent instances started:
00137   manager.start();
00138 
00139   // get the frame grabber to start streaming:
00140   gb->startStream();
00141 
00142   // ########## MAIN LOOP: grab, process, display:
00143   while(goforever)
00144     {
00145       // initialize the timer:
00146       tim.reset(); ff = frame % NAVG;
00147 
00148       // grab an image:
00149       Image< PixRGB<byte> > ima = gb->readRGB();
00150       t[0][ff] = tim.getReset();  // grab time
00151 
00152       // send every other image to processing:
00153       if (frame & 1)
00154         {
00155           // prescale image:
00156           Image<PixRGB<byte> > ima2 =
00157             decY(lowPass9y(decX(lowPass9x(ima),1<<PRESCALE)),1<<PRESCALE);
00158 
00159           // we do the job of BEO_RETINA on the master to reduce latency:
00160           // compute luminance and send it off:
00161           Image<byte> lum = luminance(ima2);
00162           smsg.reset(frame, BEO_LUMINANCE);
00163           smsg.addImage(lum);
00164           beo->send(0, smsg);  // send off to luminance slave
00165 
00166           // compute RG and BY and send them off:
00167           Image<byte> r, g, b, y; getRGBY(ima2, r, g, b, y, (byte)25);
00168           smsg.reset(frame, BEO_REDGREEN);
00169           smsg.addImage(r); smsg.addImage(g);
00170           beo->send(1, smsg);  // send off to RG slave
00171           smsg.reset(frame, BEO_BLUEYELLOW);
00172           smsg.addImage(b); smsg.addImage(y);
00173           beo->send(2, smsg);  // send off to BY slave
00174 
00175           t[1][ff] = tim.getReset();  // send out time
00176 
00177           //LINFO("sent frame %d", frame);
00178         }
00179       else
00180         {
00181           // sleep a bit so that we give more CPU to other threads/processes:
00182           struct timespec ts, ts2;
00183           ts.tv_sec = 0; ts.tv_nsec = 5000000;  // sleep 5 ms
00184           nanosleep(&ts, &ts2);
00185 
00186           // duplicate real send time from previous frame:
00187           int ff2 = ff - 1; if (ff2 < 0) ff2 += NAVG;
00188           t[1][ff] = t[1][ff2]; tim.reset();
00189         }
00190 
00191       // receive current coordinates of focus of attention:
00192       int32 rframe, raction, rnode = -1, recnb = 0;  // receive from any node
00193       while(beo->receive(rnode, rmsg, rframe, raction, 5)) // wait up to 5ms
00194         {
00195           // accumulate data for average latency computation:
00196           latency += frame - rframe; nlat ++;
00197           //LINFO("received %d/%d from %d while at %d",
00198           //    rframe, raction, rnode, frame);
00199           switch(raction)
00200             {
00201             case BEO_WINNER: // ##############################
00202               {
00203                 Image<byte> smap = rmsg.getElementByteIma();
00204 
00205                 // trigger IOR at currently-attended location:
00206                 if (sm.initialized() && rframe - lastshift <= SHIFTINT)
00207                   drawDisk(sm, winsm,
00208                            int(ceil(float(foa_size) / (1<<sml))),
00209                            byte(0));
00210 
00211                 // inject newly received saliency map:
00212                 if (sm.initialized())
00213                   sm = sm * (1.1f - SMINJECT) + smap * SMINJECT;
00214                 else
00215                   sm = smap;
00216 
00217                 if (rframe - lastshift >= SHIFTINT)
00218                   {
00219                     // find most salient location:
00220                     byte maxval; findMax(sm, winsm, maxval);
00221 
00222                     // rescale winner coordinates according to PRESCALE:
00223                     win.i = winsm.i << sml;
00224                     win.i += int(((1<<(sml-1)) * float(rand()))/RAND_MAX);
00225                     win.j = winsm.j << sml;
00226                     win.j += int(((1<<(sml-1)) * float(rand()))/RAND_MAX);
00227 
00228                     // just did a shift of attention:
00229                     lastshift = rframe;
00230                   }
00231               }
00232               break;
00233             default: // ##############################
00234               LERROR("Bogus action %d -- IGNORING.", raction);
00235               break;
00236             }
00237           // limit number of receives, so we don't hold CPU too long:
00238           recnb ++; if (recnb > 3) break;
00239         }
00240       t[2][ff] = tim.getReset(); // receive time
00241 
00242       // display image in window:
00243       inplacePaste(disp, ima, Point2D<int>(0, 0));
00244       drawPatch(disp, win, 3, pix);
00245       drawCircle(disp, win, foa_size, pix, 2);
00246       if (sm.initialized())
00247         inplacePaste(disp,
00248                      toRGB(quickInterpolate(sm, 1<<sml)), Point2D<int>(w, 0));
00249       xw.drawImage(disp);
00250 
00251       t[3][ff] = tim.getReset();  // display time
00252       if (t[3][ff] > 20)
00253         LINFO("*** Display took %dms for frame %d", t[3][ff], frame);
00254 
00255 
00256       // compute and show framerate and stats over the last NAVG frames:
00257       if (ff == 1 && frame > 1)
00258         {
00259           float avg[NSTAT], tot = 0.0f;
00260           for (int j = 0; j < NSTAT; j ++)
00261             {
00262               avg[j] = 0.0f;
00263               for (int i = 0; i < NAVG; i ++)
00264                 { avg[j] += t[j][i]; tot += t[j][i]; }
00265               avg[j] /= NAVG;
00266             }
00267           tot /= NAVG;
00268           if (nlat == 0) { latency = -1; nlat = 1; }
00269           LINFO("%.1ffps [G=%.1f S=%.1f R=%.1f D=%.1f T=%.1f F=%.1f]",
00270                 1000.0f / tot, avg[0], avg[1],
00271                 avg[2], avg[3], tot, float(latency) / nlat);
00272           latency = 0; nlat = 0;
00273         }
00274 
00275       // ready for next frame:
00276       frame++;
00277     }
00278 
00279   // got interrupted; let's cleanup and exit:
00280 
00281   // stop all our ModelComponents
00282   manager.stop();
00283   return 0;
00284 }
00285 
00286 // ######################################################################
00287 /* So things look consistent in everyone's emacs... */
00288 /* Local Variables: */
00289 /* indent-tabs-mode: nil */
00290 /* End: */
Generated on Sun May 8 08:41:08 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3