MPIopenvision2.C

Go to the documentation of this file.
00001 /*!@file INVT/MPIopenvision2.C  another MPI version of openvision.C */
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/INVT/MPIopenvision2.C $
00035 // $Id: MPIopenvision2.C 10845 2009-02-13 08:49:12Z itti $
00036 //
00037 
00038 #include "Channels/RGBConvolveChannel.H"
00039 #include "Component/ModelManager.H"
00040 #include "Image/MathOps.H"
00041 #include "Image/MatrixOps.H"
00042 #include "Image/Pixels.H"
00043 #include "Image/Transforms.H"
00044 #include "Media/FrameSeries.H"
00045 #include "Neuro/NeuroOpts.H"
00046 #include "Channels/RawVisualCortex.H"
00047 #include "Raster/Raster.H"
00048 #include "Util/sformat.H"
00049 
00050 #include <fstream>
00051 #ifdef HAVE_MPI_H
00052 #include <mpi.h>
00053 #endif
00054 
00055 #define ITMAX 200
00056 #define FTOL 0.000001f
00057 #define MASTER 0
00058 #define MSG_STOP 10
00059 #define MSG_PIC 1
00060 #define MSG_DATA 2
00061 #define MSG_RESULT 200
00062 #define PATH "/tmphpc-01/itti/openvision"
00063 #define INPUTFILE "/tmphpc-01/itti/openvision/start.txt"
00064 #define NB_PICS 14
00065 #define NB_FILTERS 3
00066 #define NCOEFFS 8
00067 #define MCOEFFS NCOEFFS * NCOEFFS * NB_FILTERS * 3
00068 #define NB_EVALS 10
00069 #define NB_WAVES 5
00070 #define NB_PROCS NB_PICS * NB_EVALS * 2 + 1
00071 
00072 int main(int argc, char **argv)
00073 {
00074 #ifndef HAVE_MPI_H
00075 
00076   LFATAL("<mpi.h> must be installed to use this program");
00077 
00078 #else
00079 
00080   // Set verbosity:
00081   int loglev = LOG_ERR;
00082   MYLOGVERB = loglev;
00083 
00084   // Number of coefficients:
00085   int n = NCOEFFS;
00086   int m = MCOEFFS;
00087 
00088   // Initialize the MPI system and get the number of processes:
00089   int myrank, size;
00090   MPI_Init(&argc, &argv);
00091   MPI_Comm_size(MPI_COMM_WORLD, &size);
00092 
00093   // Check for proper number of processes:
00094   if(size < NB_PROCS)
00095     {
00096       LERROR("*** Error: %i Processes needed. ***", NB_PROCS);
00097       MPI_Finalize();
00098       return 1;
00099     }
00100 
00101   // Get the rank of the process:
00102   MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
00103 
00104   if (myrank == MASTER)
00105     {
00106       // ################ MASTER PROCESS ################
00107 
00108       // **************** INITIALIZATION ****************
00109 
00110       MPI_Status status;
00111 
00112       // Load start coefficients:
00113       float p[m];
00114       std::ifstream inputfile (INPUTFILE);
00115       if (inputfile.is_open())
00116         {
00117           for (int j = 0; j < m; j++)
00118             inputfile >> p[j];
00119           inputfile.close();
00120         }
00121       else
00122         {
00123           LERROR("*** Cannot open input file !");
00124           return 1;
00125         }
00126 
00127       // Generate the starting point, directions and function value:
00128       float xi[m][m];
00129       for(int i = 0; i < m; i++)
00130         {
00131           for(int j = 0; j < m; j++)
00132             xi[j][i] = 0.0f;
00133           xi[i][i] = 1.0f;
00134         }
00135       float fp = 10.0f;
00136 
00137       // **************** OPTIMIZATION ****************
00138 
00139       for (int iter = 0; ; iter++)
00140         {
00141           LERROR("### ITERATION %i ###", iter);
00142 
00143           int stop = 0;
00144           float del = 0.0f;
00145           int ibig = 0;
00146           float fstart = fp;
00147           float start[m];
00148           for (int i = 0; i < m; i++)
00149             start[m] = p[m];
00150           float fpt = fp;
00151           int mubig = 0;
00152 
00153           // Loop over all directions:
00154           for (int i = 0; i < m; i++)
00155             {
00156               mubig = 0;
00157               for (int wave = 0; wave < NB_WAVES; wave++)
00158                 {
00159                   int muplus = NB_EVALS * wave;
00160                   // Send data to slaves:
00161                   for (int part = 0; part < 2; part++)
00162                     for (int mu = 1; mu <= NB_EVALS; mu++)
00163                       {
00164                         int mu2 = (1 - 2 * part) * (mu + muplus);
00165                         float ptry[m];
00166                         for (int j = 0; j < m; j++)
00167                           ptry[j] = p[j] + (mu2 * 0.02f * xi[j][i]);
00168                         for (int pic = 0; pic < NB_PICS; pic++)
00169                           {
00170                             int proc = (NB_EVALS * NB_PICS * part);
00171                             proc += (NB_PICS * (mu - 1)) + pic + 1;
00172                             MPI_Send(&stop, 1, MPI_INT, proc,
00173                                      MSG_STOP, MPI_COMM_WORLD);
00174                             MPI_Send(&pic, 1, MPI_INT, proc,
00175                                      MSG_PIC, MPI_COMM_WORLD);
00176                             MPI_Send(ptry, m, MPI_FLOAT, proc,
00177                                      MSG_DATA, MPI_COMM_WORLD);
00178 
00179                           }
00180                       }
00181                   LERROR("*** Data sent to slaves");
00182 
00183                   // Receive result from slaves and keep best decrease:
00184                   for (int part = 0; part < 2; part++)
00185                     for (int mu = 1; mu <= NB_EVALS; mu++)
00186                       {
00187                         float fptry = 0.0f;
00188                         for (int pic = 0; pic < NB_PICS; pic++)
00189                           {
00190                             float value;
00191                             int proc = (NB_EVALS * NB_PICS * part);
00192                             proc += (NB_PICS * (mu - 1)) + pic + 1;
00193                             MPI_Recv(&value, 1, MPI_FLOAT, proc,
00194                                      MSG_RESULT, MPI_COMM_WORLD,
00195                                      &status);
00196                             fptry += value;
00197                           }
00198                         fptry /= NB_PICS;
00199                         if (fptry < fpt)
00200                           {
00201                             fpt = fptry;
00202                             mubig = (1 - 2 * part) * (mu + muplus);
00203                           }
00204                       }
00205                 }
00206 
00207               LERROR("*** Result received");
00208               // Keep the greatest decrease:
00209               if (fp - fpt > del)
00210                 {
00211                   del = fp - fpt;
00212                   ibig = i;
00213                 }
00214               fp = fpt;
00215               for (int j = 0; j < m; j++)
00216                 p[j] += mubig * 0.02f * xi[j][i];
00217 
00218               LERROR("*** Direction %i : mu = %i", i, mubig);
00219               LERROR("*** New value : %f", fp);
00220 
00221 //               float maxcoeff1 = 0;
00222 //               float maxcoeff2 = 0;
00223 //               float maxcoeff3 = 0;
00224 //               for (int j = 0; j < m / 3; j++)
00225 //                 {
00226 //                   if (fabs(p[j]) > maxcoeff1)
00227 //                     maxcoeff1 = fabs(p[j]);
00228 //                   if (fabs(p[j + m / 3]) > maxcoeff2)
00229 //                     maxcoeff2 = fabs(p[j + m / 3]);
00230 //                   if (fabs(p[j + 2 * m / 3]) > maxcoeff3)
00231 //                     maxcoeff3 = fabs(p[j + 2 * m / 3]);
00232 //                 }
00233 //               for (int j = 0; j < m / 3; j++)
00234 //                 {
00235 //                   p[j] /= maxcoeff1;
00236 //                   p[j + m / 3] /= maxcoeff2;
00237 //                   p[j + 2 * m / 3] /= maxcoeff3;
00238 //                 }
00239              }
00240 
00241           LERROR("### Total decrease for iteration : %f", fstart - fp);
00242 
00243           // Save current coefficients:
00244           const std::string filename =
00245             sformat("%s/results/step%03i.txt", PATH, iter);
00246           std::ofstream resultfile (filename.c_str());
00247           if (resultfile.is_open())
00248             {
00249               for (int j = 0; j < m; j++)
00250                 resultfile << p[j] << "\n";
00251               resultfile.close();
00252             }
00253           LERROR("### Current result saved in %s", filename.c_str());
00254 
00255           // Exit the loop if ITMAX is reach or if the decrease is too low:
00256           if (2.0 * fabs(fstart - fp) <= FTOL * (fabs(fstart) + fabs(fp)))
00257             {
00258               stop = 1;
00259               for (int i = 1; i < NB_PROCS; i++)
00260                 MPI_Send(&stop, 1, MPI_INT, i,
00261                          MSG_STOP, MPI_COMM_WORLD);
00262               LERROR("### Low decrease ! ###");
00263               sleep(10);
00264               // MPI_Finalize();
00265               return 0;
00266             }
00267           if (iter == ITMAX)
00268             {
00269               stop = 1;
00270               for (int i = 1; i < NB_PROCS; i++)
00271                 MPI_Send(&stop, 1, MPI_INT, i,
00272                          MSG_STOP, MPI_COMM_WORLD);
00273               LERROR("### Maximum iterations exceeded ! ###");
00274               sleep(10);
00275               // MPI_Finalize();
00276               return 1;
00277             }
00278 
00279           // Update data:
00280           float xit[m];
00281           float norm = 0;
00282           for (int j = 0; j < m; j++)
00283             {
00284               xit[j] = p[j] - start[j];
00285               norm += xit[j] * xit[j];
00286             }
00287           norm = sqrt(norm);
00288           for (int j = 0; j < m; j++)
00289             {
00290               xi[j][ibig] = xit[j] / norm;
00291             }
00292         }
00293     }
00294   else
00295     {
00296       // ################ SLAVES PROCESS ################
00297 
00298       // **************** INITIALIZATION ****************
00299 
00300       MPI_Status status;
00301 
00302       // Generate the haar transform matrix:
00303       Image<float> hmat(n, n, ZEROS);
00304       for(int i = 0; i < n; i++)
00305         {
00306           hmat.setVal(i, 0, 1.0f);
00307         }
00308       for(int i = 0; i < n / 2; i++)
00309         {
00310           hmat.setVal(i, 1, 1.0f);
00311           hmat.setVal(i + n / 2, 1, -1.0f);
00312           if (i - 2 < 0)
00313             {
00314               hmat.setVal(i, 2, 1.0f);
00315               hmat.setVal(i + 2, 2, -1.0f);
00316             }
00317           else
00318             {
00319               hmat.setVal(i + 2, 3, 1.0f);
00320               hmat.setVal(i + 4, 3, -1.0f);
00321             }
00322           hmat.setVal(2 * i, i + n / 2, 1.0f);
00323           hmat.setVal(2 * i + 1, i + n / 2, -1.0f);
00324         }
00325 
00326       // Load the input images and masks:
00327       ImageSet< PixRGB<byte> > input(NB_PICS);
00328       ImageSet<byte> mask(NB_PICS);
00329       for (int i = 0; i < NB_PICS; i++)
00330         {
00331           input[i] =
00332             Raster::ReadRGB(sformat("%s/pictures/PIC_%03i.PPM", PATH, i));
00333           mask[i] =
00334             Raster::ReadGray(sformat("%s/pictures/PIC_%03i.PGM", PATH, i));
00335         }
00336 
00337       LERROR("### SLAVE %i INITIALIZED SUCCESFULLY ! ###", myrank);
00338 
00339       // **************** OPTIMIZATION ****************
00340 
00341       for (int iter = 0; ; ++iter)
00342         {
00343           // Receive the stop message:
00344           int stop;
00345           MPI_Recv(&stop, 1, MPI_INT, MASTER,
00346                    MSG_STOP, MPI_COMM_WORLD, &status);
00347           if (stop == 1)
00348             {
00349               // MPI_Finalize();
00350               return 0;
00351             }
00352 
00353           // Receive data from master:
00354           int pic;
00355           MPI_Recv(&pic, 1, MPI_INT, MASTER,
00356                    MSG_PIC, MPI_COMM_WORLD, &status);
00357           float data[m];
00358           MPI_Recv(data, m, MPI_FLOAT, MASTER,
00359                    MSG_DATA, MPI_COMM_WORLD, &status);
00360 
00361           // Convert data into filters:
00362           ImageSet<float> trans(NB_FILTERS * 3);
00363           for (int i = 0; i < NB_FILTERS * 3; i++)
00364             trans[i] = Image<float>(data + (n * n * i), n, n);
00365           ImageSet<float> filter(NB_FILTERS * 3);
00366           for (int i = 0; i < NB_FILTERS * 3; i++)
00367             filter[i] = matrixMult(transpose(hmat),
00368                                    matrixMult(trans[i], hmat));
00369 
00370           // Compute the dot product of the filters:
00371           Image<float> prod1(8, 8, ZEROS);
00372           Image<float> prod2(8, 8, ZEROS);
00373           Image<float> prod3(8, 8, ZEROS);
00374           for (int i = 0; i < NB_FILTERS; i++)
00375             {
00376               prod1 += filter[3 * i] * filter[3 * i + 1];
00377               prod2 += filter[3 * i] * filter[3 * i + 2];
00378               prod3 += filter[3 * i + 2] * filter[3 * i + 1];
00379             }
00380           float dotprod = sum(prod1) + sum(prod2) + sum(prod3);
00381 
00382           // Instantiate a ModelManager:
00383           ModelManager manager("Open Attention Model");
00384 
00385           // Instantiate our various ModelComponents:
00386           nub::soft_ref<RawVisualCortex> vcx(new RawVisualCortex(manager));
00387           manager.addSubComponent(vcx);
00388 
00389           for (int i = 0; i < NB_FILTERS; i++)
00390             {
00391               // Create a channel attached to each filter:
00392               nub::soft_ref<RGBConvolveChannel>
00393                 channel(new RGBConvolveChannel(manager));
00394               channel->setDescriptiveName(sformat("RGBConvolve%d", i));
00395               channel->setTagName(sformat("rgbconv%d", i));
00396 
00397               // Assign the 3 filters to the channel:
00398               channel->setFilters(filter[3 * i], filter[3 * i + 1],
00399                                   filter[3 * i + 2],
00400                                   CONV_BOUNDARY_ZERO);
00401 
00402               // Attach the channel to our visual cortex:
00403               vcx->addSubChan(channel);
00404             }
00405 
00406           // Let's get all our ModelComponent instances started:
00407           manager.exportOptions(MC_RECURSE);
00408           manager.setModelParamString("UsingFPE", "false");
00409           manager.setModelParamString("TestMode", "true");
00410 
00411           // reduce amount of log messages:
00412           MYLOGVERB = loglev;
00413 
00414           manager.start();
00415 
00416           // Process the image through the visual cortex:
00417           vcx->input(InputFrame::fromRgb(&input[pic]));
00418 
00419           // Get the resulting saliency map:
00420           Image<float> sm = vcx->getOutput();
00421 
00422           // Normalize the saliency map:
00423           inplaceNormalize(sm, 0.0f, 255.0f);
00424           Image<byte> smb = sm;
00425 
00426           // Blur and resize the binary mask:
00427           Dims smbdim = smb.getDims();
00428           Image<byte> blur_mask = binaryReverse(chamfer34(mask[pic],
00429                                                           (byte) 255),
00430                                                 (byte) 255);
00431           inplaceLowThresh(blur_mask, (byte) 200);
00432           Image<byte> mask_in = scaleBlock(blur_mask, smbdim);
00433           Image<byte> mask_out = binaryReverse(mask_in, (byte) 255);
00434 
00435           // Weight the saliency map using the in and out masks:
00436           Image<float> smb_in = (mask_in * (1.0f / 255.0f)) * smb;
00437           Image<float> smb_out = (mask_out * (1.0f / 255.0f)) * smb;
00438 
00439           // Get the max_in and max_out values:
00440           float max_in, max_out, min;
00441           getMinMax(smb_in, min, max_in);
00442           getMinMax(smb_out, min, max_out);
00443 
00444           // Compute the error:
00445           float error = 1.0f - ((max_in - max_out) / 255.0f);
00446           float result = error * error + 0.001f * fabs(dotprod);
00447 
00448           // Stop all our ModelComponents
00449           manager.stop();
00450 
00451           // Send the result to the master :
00452           MPI_Send(&result, 1, MPI_FLOAT, MASTER,
00453                    MSG_RESULT, MPI_COMM_WORLD);
00454         }
00455     }
00456 
00457 #endif // HAVE_MPI_H
00458 
00459 }
00460 
00461 // ######################################################################
00462 /* So things look consistent in everyone's emacs... */
00463 /* Local Variables: */
00464 /* indent-tabs-mode: nil */
00465 /* End: */
00466 
Generated on Sun May 8 08:05:16 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3