pvisionTCP-master.C

Go to the documentation of this file.
00001 /*!@file Parallel/pvisionTCP-master.C Grab video & process over beowulf w/ pvisionTCP */
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/pvisionTCP-master.C $
00035 // $Id: pvisionTCP-master.C 9412 2008-03-10 23:10:15Z farhan $
00036 //
00037 
00038 /* This parallel vision processing master is for use with pvisionTCP.
00039   See the pvisionTCPgo 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/DrawOps.H"
00048 #include "Image/Image.H"
00049 #include "Image/Pixels.H"
00050 #include "Image/ShapeOps.H"
00051 #include "Parallel/pvisionTCP-defs.H"
00052 #include "Transport/FrameIstream.H"
00053 #include "Util/Assert.H"
00054 
00055 #include <signal.h>
00056 
00057 
00058 //! Number of frames over which average framerate is computed
00059 #define NAVG 20
00060 //! Number of stats collected
00061 #define NSTAT 6
00062 
00063 //! prescale level by which we downsize images before sending them off
00064 #define PRESCALE 2
00065 
00066 static bool goforever = true;  //!< Will turn false on interrupt signal
00067 
00068 //! Signal handler (e.g., for control-C)
00069 void terminate(int s)
00070 { LERROR("*** INTERRUPT ***"); goforever = false; exit(1); }
00071 
00072 // ######################################################################
00073 int main(const int argc, const char **argv)
00074 {
00075   MYLOGVERB = LOG_INFO;
00076 
00077   // instantiate a model manager:
00078   ModelManager manager("Parallel Vision TCP Version 2");
00079 
00080   // Instantiate our various ModelComponents:
00081   nub::soft_ref<FrameGrabberConfigurator>
00082     gbc(new FrameGrabberConfigurator(manager));
00083   manager.addSubComponent(gbc);
00084 
00085   nub::soft_ref<Beowulf>
00086     beo(new Beowulf(manager, "Beowulf Master", "BeowulfMaster", true));
00087   manager.addSubComponent(beo);
00088 
00089   // Parse command-line:
00090   if (manager.parseCommandLine(argc, argv, "<nframes> <framepause>", 2, 2)
00091       == false) return(1);
00092 
00093   // do post-command-line configs:
00094   nub::soft_ref<FrameIstream> gb = gbc->getFrameGrabber();
00095   if (gb.isInvalid())
00096     LFATAL("You need to select a frame grabber type via the "
00097            "--fg-type=XX command-line option for this program "
00098            "to be useful");
00099   int w = gb->getWidth(), h = gb->getHeight();
00100 
00101   int nframes = manager.getExtraArgAs<int>(0);
00102   if (nframes < 1 || nframes > 2048) LFATAL("Invalid number of frames");
00103   uint64 framepause = manager.getExtraArgAs<uint64>(1);
00104   if (framepause < 1 || framepause > 2048) LFATAL("Invalid framepause");
00105 
00106   // catch signals and redirect them to terminate for clean exit:
00107   signal(SIGHUP, terminate); signal(SIGINT, terminate);
00108   signal(SIGQUIT, terminate); signal(SIGTERM, terminate);
00109   signal(SIGALRM, terminate);
00110 
00111   // get prepared to grab, communicate, display, etc:
00112   XWindow xw(gb->peekDims(), -1, -1, "USC Saliency Cam");
00113   int32 frame = 0;                // count the frames
00114   PixRGB<byte> pix(255, 255, 0);  // yellow color for fixations
00115   Point2D<int> win(w/2, h/2); // coordinates of attended location
00116   int foa_size = std::min(w, h) / 12; // radius of focus of attention
00117   TCPmessage rmsg;      // buffer to receive messages from nodes
00118   TCPmessage smsg;      // buffer to send messages to nodes
00119   Timer tim;            // for computation of framerate
00120   int t[NSTAT][NAVG], ff; // to compute average framerate and other stats
00121   int latency = 0, nlat = 0;  // to compute average processing latency
00122   int dropped = 0;    // number of frames dropped lately
00123 
00124   // setup array of frames:
00125   Image< PixRGB<byte> > ima[nframes];
00126 
00127   // let's get all our ModelComponent instances started:
00128   manager.start();
00129 
00130   // get the frame grabber to start streaming:
00131   gb->startStream();
00132 
00133   // ########## MAIN LOOP: grab, process, display:
00134   while(goforever)
00135     {
00136       // initialize the timer:
00137       tim.reset(); ff = frame % NAVG;
00138 
00139       // grab an image:
00140       int32 index = frame % nframes;
00141       ima[index] = gb->readRGB();
00142       t[0][ff] = tim.get();  // grab time
00143 
00144       // display current processed frame, i.e., grabbed frame-nframes+1 ago:
00145       if (frame >= nframes)
00146         xw.drawImage(ima[(frame - nframes + 1) % nframes]);
00147       t[1][ff] = tim.get() - t[0][ff];  // display time
00148       if (t[1][ff] > 20)
00149         LINFO("*** Display took %dms for frame %d", t[1][ff], frame);
00150 
00151       // send every image to processing, unless we are recovering from drops:
00152       if (dropped == 0)
00153         {
00154           // prescale image:
00155           Image< PixRGB<byte> > tmpi = ima[index];
00156           tmpi = rescale(tmpi,
00157                          tmpi.getWidth() >> PRESCALE,
00158                          tmpi.getHeight() >> PRESCALE);
00159 
00160           // select processing branch based on frame number:
00161           int32 offset; if (frame & 1) offset = POFFSET; else offset = 0;
00162 
00163           // we do the job of BEO_RETINA on the master to reduce latency:
00164           // compute luminance and send it off:
00165           Image<byte> lum = luminance(tmpi);
00166           smsg.reset(frame, BEO_LUMINANCE);
00167           smsg.addImage(lum);
00168           beo->send(offset + 0, smsg);  // send off to luminance slave
00169 
00170           // compute RG and BY and send them off:
00171           Image<byte> r, g, b, y; getRGBY(tmpi, r, g, b, y, (byte)25);
00172           smsg.reset(frame, BEO_REDGREEN);
00173           smsg.addImage(r); smsg.addImage(g);
00174           beo->send(offset + 1, smsg);  // send off to RG slave
00175           smsg.reset(frame, BEO_BLUEYELLOW);
00176           smsg.addImage(b); smsg.addImage(y);
00177           beo->send(offset + 2, smsg);  // send off to BY slave
00178 
00179           //LINFO("sent frame %d", frame);
00180         }
00181       t[2][ff] = tim.get() - t[1][ff] - t[0][ff];  // send out time
00182 
00183       // receive current coordinates of focus of attention:
00184       int32 rframe, raction, rnode = -1, recnb = 0;  // receive from any node
00185       while(beo->receive(rnode, rmsg, rframe, raction, 5)) // wait up to 5ms
00186         {
00187           // accumulate data for average latency computation:
00188           latency += frame - rframe; nlat ++;
00189           //LINFO("received %d/%d from %d while at %d",
00190           //    rframe, raction, rnode, frame);
00191           switch(raction)
00192             {
00193             case BEO_WINNER: // ##############################
00194               {
00195                 const Fixation fix = rmsg.getElementFixation();
00196                 win.i = fix.i; win.j = fix.j; rframe = fix.frame;
00197 
00198                 // are we going to keep or drop this result?
00199                 if (rframe > frame - nframes)
00200                   {
00201 
00202                     // rescale winner coordinates according to PRESCALE:
00203                     win.i <<= PRESCALE;
00204                     win.i += int(((1 << (PRESCALE - 1)) *
00205                                   float(rand()) ) / RAND_MAX);
00206                     win.j <<= PRESCALE;
00207                     win.j += int(((1 << (PRESCALE - 1)) *
00208                                   float(rand()) ) / RAND_MAX);
00209 
00210                     // plot focus of attention onto image, at winning coords:
00211                     int32 fidx = rframe % nframes;
00212                     drawPatch(ima[fidx], win, 3, pix);
00213                     drawCircle(ima[fidx], win, foa_size, pix, 3);
00214 
00215                     if (dropped) dropped --;
00216                   }
00217                 else
00218                   {
00219                     dropped += 3;
00220                     LINFO("    dropping frame %d (%d) [now %d]; dropped = %d",
00221                           rframe, rframe % nframes, frame, dropped);
00222                   }
00223               }
00224               break;
00225             default: // ##############################
00226               LERROR("Bogus action %d -- IGNORING.", raction);
00227               break;
00228             }
00229           // limit number of receives, so we don't hold CPU too long:
00230           recnb ++; if (recnb > 4) break;
00231         }
00232       t[3][ff] = tim.get() - t[2][ff] - t[1][ff] - t[0][ff]; // receive time
00233 
00234       // compute and show framerate and stats over the last NAVG frames:
00235       if (ff == 1 && frame > 1)
00236         {
00237           int avg[NSTAT];
00238           for (int j = 0; j < NSTAT; j ++)
00239             {
00240               avg[j] = 0;
00241               for (int i = 0; i < NAVG; i ++) avg[j] += t[j][i];
00242               avg[j] /= NAVG;
00243             }
00244           if (nlat == 0) { latency = -1; nlat = 1; }
00245           LINFO("%.1ffps/%llxms [G=%d D=%d S=%d R=%d A=%d T=%d F=%d]",
00246                 1000.0 / ((float)(avg[5])), framepause,
00247                 avg[0], avg[1], avg[2], avg[3], avg[4], avg[5],
00248                 latency / nlat);
00249           latency = 0; nlat = 0;
00250           // try to resorb the number of dropped frames:
00251           if (dropped) dropped --;
00252         }
00253       t[4][ff] = tim.get();  // after total before pause
00254 
00255       // if necessary, sleep for a while until fixed amount of time elapsed:
00256       while(tim.get() < framepause)
00257         {
00258           struct timespec ts, ts2;
00259           ts.tv_sec = 0; ts.tv_nsec = 1000000;  // sleep 1 ms
00260           nanosleep(&ts, &ts2);
00261         }
00262 
00263       t[5][ff] = tim.get();  // total time
00264 
00265       // ready for next frame:
00266       frame++;
00267     }
00268 
00269   // got interrupted; let's cleanup and exit:
00270   // stop all our ModelComponents
00271   manager.stop();
00272   exit(0);
00273 }
00274 
00275 // ######################################################################
00276 /* So things look consistent in everyone's emacs... */
00277 /* Local Variables: */
00278 /* indent-tabs-mode: nil */
00279 /* End: */
Generated on Sun May 8 08:05:30 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3