nerd-camTCP2.C

Go to the documentation of this file.
00001 /*!@file Nerdcam/nerd-camTCP2.C A parallel vision slave to use w/ pvisionTCP2master */
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/Nerdcam/nerd-camTCP2.C $
00035 // $Id: nerd-camTCP2.C 12074 2009-11-24 07:51:51Z itti $
00036 //
00037 
00038 /*! See the pvisionTCP2go script in bin/ for how to launch the slaves, and
00039   see pvisionTCP2-master.C for the master program.
00040 */
00041 
00042 #include "Beowulf/Beowulf.H"
00043 #include "Component/ModelManager.H"
00044 #include "Image/ColorOps.H"
00045 #include "Image/Image.H"
00046 #include "Image/ImageSet.H"
00047 #include "Image/MathOps.H"
00048 #include "Image/Pixels.H"
00049 #include "Image/PyramidOps.H"
00050 #include "Image/ShapeOps.H"
00051 #include "Image/Transforms.H"
00052 #include "Image/fancynorm.H"
00053 #include "Parallel/pvisionTCP-defs.H"
00054 #include "Util/Assert.H"
00055 #include "Util/Timer.H"
00056 #include "Util/Types.H"
00057 
00058 #include <cstdlib>
00059 #include <signal.h>
00060 #include <time.h>
00061 #include <unistd.h>
00062 #include <cstdio>
00063 
00064 static bool goforever = true;  //!< Will turn false on interrupt signal
00065 
00066 //! Signal handler (e.g., for control-C)
00067 void terminate(int s) { LERROR("*** INTERRUPT ***"); goforever = false; }
00068 
00069 //! Compute a conspicuity map from an image received in a message
00070 void computeCMAP(TCPmessage& msg, const PyramidType ptyp,
00071                  const float ori, const float coeff,
00072                  const int slave, nub::soft_ref<Beowulf>& b);
00073 
00074 //! Compute a conspicuity map from two images received in a message
00075 void computeCMAP2(TCPmessage& msg, const PyramidType ptyp,
00076                  const float ori, const float coeff,
00077                  const int slave, nub::soft_ref<Beowulf>& b);
00078 
00079 //! Compute a conspicuity map from an image
00080 void computeCMAP(const Image<float>& fima, const PyramidType ptyp,
00081                  const float ori, const float coeff,
00082                  const int slave, nub::soft_ref<Beowulf>& b, const int32 id);
00083 
00084 // ######################################################################
00085 // ##### Global options:
00086 // ######################################################################
00087 #define sml        2
00088 #define delta_min  3
00089 #define delta_max  4
00090 #define level_min  0
00091 #define level_max  2
00092 #define maxdepth   (level_max + delta_max + 1)
00093 #define normtyp    (VCXNORM_MAXNORM)
00094 
00095 // number of output saliency maps kept in buffer (to accomodate for
00096 // speed variations):
00097 #define NBOUT 10
00098 
00099 // relative feature weights:
00100 #define IWEIGHT 1.0
00101 #define CWEIGHT 1.0
00102 #define OWEIGHT 1.0
00103 #define FWEIGHT 1.5
00104 
00105 // ######################################################################
00106 int main(const int argc, const char **argv)
00107 {
00108   MYLOGVERB = LOG_INFO;
00109 
00110   // instantiate a model manager:
00111   ModelManager manager("NerdCam TCP - Slave");
00112 
00113   // Instantiate our various ModelComponents:
00114   nub::soft_ref<Beowulf>
00115     beo(new Beowulf(manager, "Beowulf Slave", "BeowulfSlave", false));
00116   manager.addSubComponent(beo);
00117 
00118   // Parse command-line:
00119   if (manager.parseCommandLine(argc, argv, "", 0, 0) == false) return(1);
00120 
00121   // setup signal handling:
00122   signal(SIGHUP, terminate); signal(SIGINT, terminate);
00123   signal(SIGQUIT, terminate); signal(SIGTERM, terminate);
00124   initRandomNumbers();
00125 
00126   // various processing inits:
00127   Image<float> outmap[NBOUT]; // array of output saliency maps
00128   int32 outframe[NBOUT];      // array of output frame numbers
00129   int nbcmap[NBOUT];          // how many consp maps in each outmap
00130   for (int i = 0; i < NBOUT; i ++) { outframe[i] = -1; nbcmap[i] = 0; }
00131   Image<float> previma;       // previous image; for flicker processing
00132   Timer tim;                  // to measure processing speed
00133   TCPmessage rmsg;                 // message being received and to process
00134   TCPmessage smsg;                 // message being sent
00135 
00136   // let's get all our ModelComponent instances started:
00137   manager.start();
00138 
00139   // wait for data and process it:
00140   while(goforever)
00141     {
00142       int32 rframe, raction, rnode = -1;  // receive from any node
00143       if (beo->receive(rnode, rmsg, rframe, raction, 3))  // wait up to 3ms
00144         {
00145           LINFO("Frame %d, action %d from node %d", rframe, raction, rnode);
00146           tim.reset();
00147 
00148           // select processing branch based on frame number:
00149           switch(raction)
00150             {
00151             case BEO_INIT:       // ##############################
00152               {
00153                 // ooops, someone wants to re-initialize us!
00154                 // forget about all our current frames:
00155                 for (int i = 0; i < NBOUT; i ++)
00156                   { outframe[i] = -1; nbcmap[i] = 0; }
00157                 // reinitialization of beowulf is handled automatically.
00158               }
00159               break;
00160             case BEO_RETINA:     // ##############################
00161               {
00162                 // get the color image:
00163                 Image< PixRGB<byte> > ima = rmsg.getElementColByteIma();
00164 
00165                 // compute luminance and send it off:
00166                 Image<byte> lum = luminance(ima);
00167                 smsg.reset(rframe, BEO_LUMINANCE);
00168                 smsg.addImage(lum);
00169                 beo->send(0, smsg);  // send off to luminance slave
00170 
00171                 // compute RG and BY and send them off:
00172                 Image<byte> r, g, b, y; getRGBY(ima, r, g, b, y, (byte)25);
00173                 smsg.reset(rframe, BEO_REDGREEN);
00174                 smsg.addImage(r); smsg.addImage(g);
00175                 beo->send(1, smsg);  // send off to RG slave
00176                 smsg.reset(rframe, BEO_BLUEYELLOW);
00177                 smsg.addImage(b); smsg.addImage(y);
00178                 beo->send(2, smsg);  // send off to BY slave
00179               }
00180               break;
00181             case BEO_LUMINANCE:  // ##############################
00182               {
00183                 // first, send off luminance to orientation slaves:
00184                 rmsg.setAction(BEO_ORI0);
00185                 beo->send(3, rmsg);  // send off to ori0 slave
00186                 rmsg.setAction(BEO_ORI45);
00187                 beo->send(4, rmsg);  // send off to ori45 slave
00188                 rmsg.setAction(BEO_ORI90);
00189                 beo->send(5, rmsg);  // send off to ori90 slave
00190                 rmsg.setAction(BEO_ORI135);
00191                 beo->send(6, rmsg);  // send off to ori135 slave
00192 
00193                 // and also send to flicker slave:
00194                 rmsg.setAction(BEO_FLICKER);
00195                 beo->send(8, rmsg);  // send off to flick slave
00196 
00197                 // now compute intensity conspicuity map and send to collector:
00198                 computeCMAP(rmsg, Gaussian5, 0.0, IWEIGHT, 7, beo);
00199               }
00200               break;
00201             case BEO_FLICKER:
00202               {
00203                 // get the luminance image out of the message:
00204                 Image<byte> ima = rmsg.getElementByteIma();
00205                 Image<float> fima = ima;  // convert to float
00206 
00207                 // compute flicker consp map and send to collector:
00208                 if (previma.initialized() == false) previma = fima;
00209                 previma -= fima;
00210                 computeCMAP(previma, Gaussian5, 0.0, FWEIGHT, 7,
00211                             beo, rframe);
00212                 previma = fima;
00213               }
00214               break;
00215             case BEO_REDGREEN:   // ##############################
00216               computeCMAP2(rmsg, Gaussian5, 0.0, CWEIGHT, 7, beo);
00217               break;
00218             case BEO_BLUEYELLOW: // ##############################
00219               computeCMAP2(rmsg, Gaussian5, 0.0, CWEIGHT, 7, beo);
00220               break;
00221             case BEO_ORI0:       // ##############################
00222               computeCMAP(rmsg, Oriented5, 0.0, OWEIGHT, 7, beo);
00223               break;
00224             case BEO_ORI45:      // ##############################
00225               computeCMAP(rmsg, Oriented5, 45.0, OWEIGHT, 7, beo);
00226               break;
00227             case BEO_ORI90:      // ##############################
00228               computeCMAP(rmsg, Oriented5, 90.0, OWEIGHT, 7, beo);
00229               break;
00230             case BEO_ORI135:     // ##############################
00231               computeCMAP(rmsg, Oriented5, 135.0, OWEIGHT, 7, beo);
00232               break;
00233             case BEO_CMAP:       // ##############################
00234               {
00235                 // get the map:
00236                 Image<float> ima = rmsg.getElementFloatIma();
00237 
00238                 // do we already have some accumulated data on this
00239                 // frame, or is this a new frame?
00240                 int32 oldestidx = 0;
00241                 int32 oldestframe = std::numeric_limits<int32>::max();
00242                 int32 curridx = -1;
00243                 for (int32 i = 0; i < NBOUT; i ++)
00244                   {
00245                     if (outframe[i] < oldestframe)
00246                       { oldestframe = outframe[i]; oldestidx = i; }
00247                     if (outframe[i] == rframe) // ok, already in progress
00248                       { curridx = i; break; }
00249                   }
00250 
00251                 // if we are not already processing this frame, set it up,
00252                 // possibly dropping oldest frame in buffer if buffer full:
00253                 if (curridx == -1)
00254                   {
00255                     // ok, use oldest frame, then...
00256                     curridx = oldestidx;
00257                     // was it in progress?
00258                     if (nbcmap[curridx])
00259                       {
00260                         LINFO("Dropping frame %d!", outframe[curridx]);
00261                         char junk[1024], junk2[256]; junk[0] = '\0';
00262                         for (int i = 0; i < NBOUT; i ++)
00263                           {
00264                             sprintf(junk2, "%d/%d ", outframe[i], nbcmap[i]);
00265                             strcat(junk, junk2);
00266                           }
00267                         LINFO("BUFFER = [ %s]", junk);
00268                       }
00269                     // now we process frame nb rframe at slot curridx:
00270                     outframe[curridx] = rframe; nbcmap[curridx] = 0;
00271                     outmap[curridx].resize(ima.getWidth(),
00272                                            ima.getHeight(), true);
00273                   }
00274 
00275                 // add received cmap to output map:
00276                 outmap[curridx] += ima; nbcmap[curridx] ++;
00277 
00278                 // have we received all the cmaps?
00279                 if (nbcmap[curridx] == NBCMAP2)
00280                   {
00281                     outmap[curridx] =
00282                       maxNormalize(outmap[curridx], 0.0f, 9.0f, normtyp);
00283                     inplaceClamp(outmap[curridx], 0.0f, 255.0f);
00284 
00285                     // send result to master:
00286                     smsg.reset(outframe[curridx], BEO_WINNER);
00287                     Image<byte> smap = outmap[curridx]; // convert to byte
00288 
00289                     smsg.addImage(smap);
00290                     beo->send(-1, smsg);
00291                     nbcmap[curridx] = 0;  // ready for next frame
00292                     //LINFO("sending off %d", outframe[curridx]);
00293                   }
00294               }
00295               break;
00296             default: // ##############################
00297               LERROR("Bogus action %d -- IGNORING.", raction);
00298               break;
00299             }
00300           if (rframe % 101 == 0)
00301             LINFO("Action %d, frame %d processed in %llxms",
00302                   raction, rframe, tim.get());
00303         }
00304     }
00305 
00306   // we got broken:
00307   manager.stop();
00308   return 0;
00309 }
00310 
00311 // ######################################################################
00312 void computeCMAP(TCPmessage& msg, const PyramidType ptyp,
00313                  const float ori, const float coeff,
00314                  const int slave, nub::soft_ref<Beowulf>& b)
00315 {
00316   Image<byte> ima = msg.getElementByteIma();
00317   Image<float> fima = ima; // convert to float
00318 
00319   computeCMAP(fima, ptyp, ori, coeff, slave, b, msg.getID());
00320 }
00321 
00322 // ######################################################################
00323 void computeCMAP2(TCPmessage& msg, const PyramidType ptyp,
00324                  const float ori, const float coeff,
00325                  const int slave, nub::soft_ref<Beowulf>& b)
00326 {
00327   Image<byte> ima1 = msg.getElementByteIma();
00328   Image<byte> ima2 = msg.getElementByteIma();
00329   Image<float> fima = ima1 - ima2;
00330 
00331   computeCMAP(fima, ptyp, ori, coeff, slave, b, msg.getID());
00332 }
00333 
00334 // ######################################################################
00335 void computeCMAP(const Image<float>& fima, const PyramidType ptyp,
00336                  const float ori, const float coeff,
00337                  const int slave, nub::soft_ref<Beowulf>& b, const int32 id)
00338 {
00339   // compute pyramid:
00340   ImageSet<float> pyr = buildPyrGeneric(fima, 0, maxdepth,
00341                                         ptyp, ori);
00342 
00343   // alloc conspicuity map and clear it:
00344   Image<float> cmap(pyr[sml].getDims(), ZEROS);
00345 
00346   // intensities is the max-normalized weighted sum of IntensCS:
00347   for (int delta = delta_min; delta <= delta_max; delta ++)
00348     for (int lev = level_min; lev <= level_max; lev ++)
00349       {
00350         Image<float> tmp = centerSurround(pyr, lev, lev + delta, true);
00351         tmp = downSize(tmp, cmap.getWidth(), cmap.getHeight());
00352         inplaceAddBGnoise(tmp, 255.0);
00353         tmp = maxNormalize(tmp, MAXNORMMIN, MAXNORMMAX, normtyp);
00354         cmap += tmp;
00355       }
00356   if (normtyp == VCXNORM_MAXNORM)
00357     cmap = maxNormalize(cmap, MAXNORMMIN, MAXNORMMAX, normtyp);
00358   else
00359     cmap = maxNormalize(cmap, 0.0f, 0.0f, normtyp);
00360 
00361   // multiply by conspicuity coefficient:
00362   cmap *= coeff;
00363 
00364   //float mi, ma; getMinMax(cmap, mi, ma); LINFO("[%f .. %f]", mi, ma);
00365 
00366   // send off resulting conspicuity map:
00367   TCPmessage smsg(id, BEO_CMAP);
00368   smsg.addImage(cmap);
00369   b->send(slave, smsg);
00370 }
00371 
00372 // ######################################################################
00373 /* So things look consistent in everyone's emacs... */
00374 /* Local Variables: */
00375 /* indent-tabs-mode: nil */
00376 /* End: */
Generated on Sun May 8 08:41:02 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3