mexSaliency.C

Go to the documentation of this file.
00001 /*!@file Matlab/mexSaliency.C This is the MEX file version of the Saliency program<br>
00002   This file compiles into a MEX file that can be called from within
00003   Matlab for extracting the saliency information from an image. The
00004   call from Matlab is:<BR> <TT>[num_sal, coords, times, salmap,
00005   modfunc, areas, labels] = Saliency(image, targets, max_time, foa_size,
00006   weights, normtype, smoothFactor, levels);</TT><P>
00007 
00008   The return values are:
00009 
00010   @param num_sal the number of salient spots found
00011   @param coords (2, num_sal) array that contains the x and y coordinates
00012   of the salient spots in (1,:) and (2,:), respectively
00013   @param times (1, num_sal) array that contains the evolution times
00014   @param salmap the saliency map (normalized between 0 and 1)
00015   @param modfunc (num_sal, height, width) array that contains the modulation
00016   functions for the salient spots, maxnormalized to 1.0
00017   @param areas (1, num_sal) array that contains the number of pixels for
00018   salient spot that have contributed to the modulation function
00019   @param labels {num_sal} cell array containing the label strings from the
00020   size info analysis
00021 
00022   The only <I>required</I> argument is:
00023   @param image the input image
00024 
00025   <I>Optional</I> paramters that have pre-assigned default values are:
00026   @param targets map of the same size as the input image, in which
00027   targets for the focus of attention are 255 and the rest is
00028   zero. Pass a scalar 0 (the default) if you have no targets to look for.
00029   @param max_time the maximum amount of (simulated) time that the saliency map
00030   should evolve in seconds <I>(default: 0.7)</I>
00031   @param foa_size the size of the focus of attention in pixels.
00032   The default is 1/12 of min(height, width) of the input image.
00033   Pass -1 if you want to use the default.
00034   @param weights Vector of length 3 containing the weights for the
00035   following channels (in this order): <TT>[wIntens, wOrient, wColor]</TT>
00036   <I>(default: [1.0 1.0 1.0])</I>
00037   @param normtype normalization type; see fancynorm.H
00038   <I>(default: 2 = VCXNORM_NORM)</I>
00039   @param smoothMethod method used for smoothing the shapeEstimator masks;
00040   see ShapeEstimatorModes.H; (default: 1 = Gaussian Smoothing)
00041   @param levels Vector of length 6 containing the following parameters:
00042   <TT>[sm_level, level_min, level_max, delta_min, delta_max, nborients]</TT>
00043   <I>(default: [4 2 4 3 4 4])</I>
00044 */
00045 
00046 // //////////////////////////////////////////////////////////////////// //
00047 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00048 // University of Southern California (USC) and the iLab at USC.         //
00049 // See http://iLab.usc.edu for information about this project.          //
00050 // //////////////////////////////////////////////////////////////////// //
00051 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00052 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00053 // in Visual Environments, and Applications'' by Christof Koch and      //
00054 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00055 // pending; application number 09/912,225 filed July 23, 2001; see      //
00056 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00057 // //////////////////////////////////////////////////////////////////// //
00058 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00059 //                                                                      //
00060 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00061 // redistribute it and/or modify it under the terms of the GNU General  //
00062 // Public License as published by the Free Software Foundation; either  //
00063 // version 2 of the License, or (at your option) any later version.     //
00064 //                                                                      //
00065 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00066 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00067 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00068 // PURPOSE.  See the GNU General Public License for more details.       //
00069 //                                                                      //
00070 // You should have received a copy of the GNU General Public License    //
00071 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00072 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00073 // Boston, MA 02111-1307 USA.                                           //
00074 // //////////////////////////////////////////////////////////////////// //
00075 //
00076 // Primary maintainer for this file: Dirk Walther <walther@caltech.edu>
00077 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Matlab/mexSaliency.C $
00078 // $Id: mexSaliency.C 14376 2011-01-11 02:44:34Z pez $
00079 //
00080 
00081 #define FPEXCEPTIONSDISABLED
00082 
00083 #include "Channels/ChannelOpts.H"
00084 #include "Component/GlobalOpts.H"
00085 #include "Component/ModelManager.H"
00086 #include "Component/ModelOptionDef.H"
00087 #include "Image/fancynorm.H"
00088 #include "Image/LevelSpec.H"
00089 #include "Image/MathOps.H"
00090 #include "Image/Pixels.H"
00091 #include "Image/ShapeOps.H"
00092 #include "Matlab/mexConverts.H"
00093 #include "Media/MediaSimEvents.H"
00094 #include "Neuro/NeuroOpts.H"
00095 #include "Neuro/NeuroSimEvents.H"
00096 #include "Neuro/ShapeEstimator.H"
00097 #include "Neuro/StdBrain.H"
00098 #include "Neuro/VisualCortex.H"
00099 #include "Simulation/SimEventQueueConfigurator.H"
00100 
00101 #include <cmath>
00102 #include <mex.h>
00103 #include <sstream>
00104 #include <string>
00105 #include <vector>
00106 
00107 // ##########################################################################
00108 // ############  The main function
00109 // ##########################################################################
00110 void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
00111 {
00112 
00113 #ifdef DEBUG
00114   LOG_FLAGS |= LOG_FULLTRACE;
00115 #else
00116   LOG_FLAGS &= (~LOG_FULLTRACE);
00117 #endif
00118 
00119   // #### check whether # of params is 1..8 and number of returned values <= 7
00120   if (nrhs < 1)  mexErrMsgTxt("At least one parameter required: image");
00121   if (nrhs > 8) mexErrMsgTxt("Too many parameters (max. 8).");
00122   if (nlhs > 7)  mexErrMsgTxt("Too many return values (max. 7).");
00123 
00124   // counter for parameters
00125   int p = 1;
00126 
00127   // #### first input: the image
00128   Image< PixRGB<byte> > img = mexArray2RGBImage<byte>(prhs[p-1]);
00129   p++;
00130 
00131   // #### targets
00132   Image<byte> targets;
00133   if ((nrhs >= p) && (mxGetNumberOfElements(prhs[p-1]) > 1))
00134     targets = mexArray2Image<byte>(prhs[p-1]);
00135   p++;
00136 
00137   // #### maximum evolution time
00138   double max_time = 0.7;
00139   if (nrhs >= p) max_time = (double)mxGetScalar(prhs[p-1]);
00140   p++;
00141 
00142   // #### foa_size
00143   //int foa_size = -1;
00144   //if (nrhs >= p) foa_size = (int)mxGetScalar(prhs[p-1]);
00145   p++;
00146 
00147   // #### weight for all the channels
00148   /*double wIntens = 1.0, wOrient = 1.0, wColor = 1.0;
00149   if (nrhs >= p)
00150     {
00151       std::vector<double> weights = mexArr2Vector<double>(prhs[p-1], 3);
00152       wIntens = weights[0]; wOrient  = weights[1];
00153       wColor  = weights[2];
00154     }*/
00155   p++;
00156 
00157   // #### norm_type
00158   int norm_type = VCXNORM_FANCY;
00159   if (nrhs >= p) norm_type = (int)mxGetScalar(prhs[p-1]);
00160   p++;
00161 
00162 
00163   // #### smoothing method for shapeEstimator
00164   int smoothMethod = 1;
00165   if (nrhs >= p) smoothMethod = (int)mxGetScalar(prhs[p-1]);
00166   p++;
00167 
00168   // #### which levels?
00169   int sml=4, level_min=2, level_max=4, delta_min=3, delta_max=4, nborients=4;
00170   if (nrhs >= p)
00171     {
00172          std::vector<int> lev = mexArr2Vector<int>(prhs[p-1], 6);
00173          sml = lev[0]; level_min = lev[1]; level_max = lev[2];
00174          delta_min = lev[3]; delta_max = lev[4]; nborients = lev[5];
00175     }
00176   p++;
00177 
00178 
00179   // #### make sure, all parameters are within range
00180   if (max_time < 0.0) mexErrMsgTxt("max_time must be positive.");
00181   if ((norm_type < VCXNORM_NONE))
00182     mexErrMsgTxt("norm_type can only have the following values:\n"
00183                  "0  -  no normalization\n"
00184                  "1  -  maximum normalization\n"
00185                  "2  -  fancy normalization (default)\n"
00186                  "3  -  fancy normalization - fast implementation\n"
00187                  "4  -  fancy normalization with one iteration");
00188   if ((smoothMethod < 0) || (smoothMethod >= NBSHAPEESTIMATORSMOOTHMETHODS))
00189     mexErrMsgTxt("smoothing methods can have the following values:\n"
00190                  "0 - no smoothing\n"
00191                  "1 - Gaussian smoothing (default)\n"
00192                  "2 - Chamfer smoothing");
00193   if (nborients <= 0) mexErrMsgTxt("nborients must be positive");
00194   if (level_min > level_max) mexErrMsgTxt("must have level_min <= level_max");
00195   if (delta_min > delta_max) mexErrMsgTxt("must have delta_min <= delta_max");
00196   if (sml < level_max) mexErrMsgTxt("must have sml >= level_max");
00197 
00198 
00199 #ifdef DEBUG
00200   // This is for debugging only
00201   std::cout << "#### mexSaliency\n";
00202   std::cout << "max_time = " << max_time << "\n";
00203   std::cout << "norm_type = " << norm_type <<"\n";
00204   std::cout << "foa_size = " << foa_size <<"\n";
00205   std::cout << "wIntens = " << wIntens <<"\n";
00206   std::cout << "wOrient = " << wOrient <<"\n";
00207   std::cout << "wColor = " << wColor <<"\n";
00208   std::cout << "nborient = " << nborients <<"\n";
00209   std::cout << "level_min = " << level_min <<"\n";
00210   std::cout << "level_max = " << level_max <<"\n";
00211   std::cout << "delta_min = " << delta_min <<"\n";
00212   std::cout << "delta_max = " << delta_max <<"\n";
00213   std::cout << "sml = " << sml <<"\n";
00214   // end debugging
00215 #endif
00216 
00217 
00218   // get a standard brain:
00219   ModelManager manager("Mex Attention Model");
00220   manager.allowOptions(OPTEXP_CORE);
00221 
00222   manager.setOptionValString(&OPT_UsingFPE,"false");
00223 
00224 #ifdef DEBUG
00225   manager.setOptionValString(&OPT_DebugMode,"true");
00226 #else
00227   manager.setOptionValString(&OPT_DebugMode,"false");
00228 #endif
00229 
00230   nub::soft_ref<SimEventQueueConfigurator> seqc(new SimEventQueueConfigurator(manager));
00231   manager.addSubComponent(seqc);
00232 
00233   nub::soft_ref<StdBrain> brain(new StdBrain(manager));
00234   manager.addSubComponent(brain);
00235   manager.exportOptions(MC_RECURSE);
00236 
00237 
00238   // set a few custom defaults for our possible options:
00239   manager.setOptionValString(&OPT_NumOrientations,
00240                              convertToString(nborients));
00241   manager.setOptionValString(&OPT_LevelSpec,
00242                              convertToString(LevelSpec(level_min,level_max,
00243                                                        delta_min,delta_max,sml)));
00244   manager.setOptionValString(&OPT_MaxNormType,
00245                              convertToString(MaxNormType(norm_type)));
00246   manager.setOptionValString(&OPT_UseRandom, "true");
00247   manager.setOptionValString(&OPT_IORtype,"ShapeEst");
00248   manager.setOptionValString(&OPT_ShapeEstimatorMode, "FeatureMap");
00249   manager.setOptionValString(&OPT_ShapeEstimatorSmoothMethod,
00250                              convertToString(ShapeEstimatorSmoothMethod
00251                                              (smoothMethod)));
00252   manager.setOptionValString(&OPT_RawVisualCortexChans,"OIC");
00253 
00254   nub::soft_ref<SimEventQueue> seq = seqc->getQ();
00255 
00256   // get started:
00257   manager.start();
00258 
00259   LFATAL("fixme");
00260 
00261   nub::soft_ref<VisualCortex> vc;/////// = brain->getVC();
00262 
00263   /*
00264   vc->setSubchanTotalWeight("color", wColor);
00265   vc->setSubchanTotalWeight("intensity", wIntens);
00266   vc->setSubchanTotalWeight("orientation", wOrient);
00267   */
00268 
00269   // let everyone (and in particular our TargetChecker) know about our target mask:
00270   seq->post(rutz::make_shared(new SimEventTargetMask(brain.get(), targets)));
00271 
00272   // post the image to the brain:
00273   seq->post(rutz::make_shared(new SimEventInputFrame(brain.get(), GenericFrame(img), 0)));
00274 
00275   Image<float> salmap;//////////////// = vc->getOutput();
00276   inplaceNormalize(salmap, 0.0f, 1.0f);
00277   salmap = rescale(salmap,img.getDims());
00278 
00279   std::vector<Point2D<int> > coords;
00280   std::vector<double> times;
00281   std::vector<int> areas;
00282   ImageSet<float> s_vect;
00283   std::vector<std::string> labelstrings;
00284 
00285   int num_sal = 0;
00286 
00287   const bool forever = (targets.initialized() && (max_time == 0.0));
00288 
00289   // time-loop, evolve
00290   while (((seq->now().secs() < max_time)||forever))
00291     {
00292       (void) seq->evolve();
00293 
00294       // we have a winner
00295       if (SeC<SimEventWTAwinner> e = seq->check<SimEventWTAwinner>(0))
00296         {
00297           const Point2D<int> winner = e->winner().p;
00298 
00299           num_sal++;
00300 
00301           coords.push_back(winner);
00302           times.push_back(seq->now().secs());
00303 
00304           //only do the shape estimator stuff if necessary
00305           if (nlhs > 5)
00306             {
00307               Image<float> semask; std::string selabel; int searea;
00308               if (SeC<SimEventShapeEstimatorOutput>
00309                   ese = seq->check<SimEventShapeEstimatorOutput>(0))
00310                 {
00311                   semask = ese->smoothMask();
00312                   selabel = ese->winningLabel();
00313                   searea = ese->objectArea();
00314                 }
00315 
00316               if (!semask.initialized()) semask.resize(img.getDims(),ZEROS);
00317               s_vect.push_back(semask);
00318 
00319               areas.push_back(searea);
00320 
00321               std::ostringstream os;
00322               os << (seq->now().msecs()) << " ms - " << selabel;
00323               labelstrings.push_back(os.str());
00324             }
00325         } // end if (brain->gotCovertShift())
00326     } // end while
00327 
00328 #ifdef DEBUG
00329   // This is for debugging only
00330   std::cout << "#### mexSaliency\n";
00331   std::cout << "x\ty\tt\n";
00332   for (int i = 0; i < num_sal; i++)
00333     std::cout << coords[i].i << "\t" << coords[i].j << "\t" << times[i] << "\n";
00334   // end debugging
00335 #endif
00336 
00337   // get stopped:
00338   manager.stop();
00339 
00340   // ######## create the return variables
00341   p = 1;
00342 
00343   // #### number of salient spots
00344   if (nlhs >= p) plhs[p-1] = mxCreateScalarDouble(num_sal);
00345   p++;
00346 
00347   // #### x and y coordinates of salient spot
00348   if (nlhs >= p) plhs[p-1] = Point2DVec2mexArr(coords);
00349   p++;
00350 
00351   // #### evolution times
00352   if (nlhs >= p) plhs[p-1] = Vector2mexArr(times);
00353   p++;
00354 
00355   // #### the saliency map
00356   if (nlhs >= p) plhs[p-1] = Image2mexArray(salmap);
00357   p++;
00358 
00359   // #### shape info
00360   mxArray* Labels = mxCreateCellArray(1, &num_sal);
00361   if (nlhs >= p)
00362     {
00363       for (int i = 0; i < num_sal; i++)
00364         {
00365           mxSetCell(Labels, i, mxCreateString(labelstrings[i].c_str()));
00366 #ifdef DEBUG
00367           std::cout << labelstrings[i].c_str() << "\n";
00368 #endif
00369         }
00370       plhs[p-1] = ImgVec2mexArr(s_vect);
00371     }
00372   p++;
00373 
00374   // #### area measures of shape info
00375   if (nlhs >= p) plhs[p-1] = Vector2mexArr(areas);
00376   p++;
00377 
00378   // #### label strings
00379   if (nlhs >= p) plhs[p-1] = Labels;
00380   p++;
00381 
00382  // #### done
00383   return;
00384 }
00385 
00386 // ######################################################################
00387 /* So things look consistent in everyone's emacs... */
00388 /* Local Variables: */
00389 /* indent-tabs-mode: nil */
00390 /* End: */
Generated on Sun May 8 08:40:59 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3