fancynorm.C

Go to the documentation of this file.
00001 /*!@file Image/fancynorm.C Intrafeature competition with maxNormalize(). */
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/Image/fancynorm.C $
00035 // $Id: fancynorm.C 9993 2008-07-29 00:04:18Z lior $
00036 //
00037 
00038 #include "Image/fancynorm.H"
00039 
00040 #include "Util/Assert.H"
00041 #include "Image/Image.H"
00042 #include "Image/ImageSet.H"
00043 #include "Image/FilterOps.H"
00044 #include "Image/Kernels.H"
00045 #include "Image/MathOps.H"
00046 #include "Image/ShapeOps.H"
00047 #include "Image/Transforms.H"
00048 #include "Image/PyramidOps.H"
00049 #include "Util/StringConversions.H"
00050 #include "Util/log.H"
00051 #include "rutz/compat_cmath.h"
00052 #include "rutz/trace.h"
00053 
00054 #include <algorithm>
00055 #include <cmath>
00056 
00057 // uncomment this define to get some info on how maxNormalize works with your
00058 // images. Intended for debugging purposes.
00059 //#define SHOW_MAXNORM_INFO
00060 
00061 // ######################################################################
00062 template <class T>
00063 Image<T> maxNormalize(const Image<T>& src,
00064                       const T mi, const T ma, const MaxNormType normtyp,
00065                       int nbiter, const Image<float> *lrexcit)
00066 {
00067 GVX_TRACE(__PRETTY_FUNCTION__);
00068 #ifdef SHOW_MAXNORM_INFO
00069   T mm, mmm; getMinMax(src, mm, mmm);
00070   LDEBUG("mini = %f, maxi= %f", float(mm), float(mmm));
00071 #endif
00072 
00073   Image<T> result;
00074 
00075   // do normalization depending on desired type:
00076   switch(normtyp)
00077     {
00078     case VCXNORM_NONE:
00079       result = maxNormalizeNone(src, mi, ma);
00080       break;
00081     case VCXNORM_MAXNORM:
00082       result = maxNormalizeStd(src, mi, ma);
00083       break;
00084     case VCXNORM_FANCYFAST:
00085       result = maxNormalizeFancyFast(src, mi, ma, nbiter);
00086       break;
00087     case VCXNORM_FANCYONE:
00088       nbiter = 1;
00089     case VCXNORM_FANCY:
00090       result = maxNormalizeFancy(src, mi, ma, nbiter, 1.0, lrexcit);
00091       break;
00092     case VCXNORM_FANCYLANDMARK:
00093       result = maxNormalizeFancyLandmark(src, mi, ma, nbiter);
00094       break;
00095     case VCXNORM_LANDMARK:
00096       result = maxNormalizeLandmark(src, mi, ma);
00097       break;
00098     case VCXNORM_FANCYWEAK:
00099       result = maxNormalizeFancy(src, mi, ma, nbiter, 0.5);
00100       break;
00101     case VCXNORM_FANCYVWEAK:
00102       result = maxNormalizeFancy(src, mi, ma, nbiter, 0.1);
00103       break;
00104     case VCXNORM_IGNORE:
00105       result = src;
00106       break;
00107     case VCXNORM_SURPRISE:
00108       result = src;
00109       break;
00110     case VCXNORM_STDEV:
00111       result = maxNormalizeStdev(src);
00112       break;
00113     case VCXNORM_STDEV0:
00114       result = maxNormalizeStdev0(src);
00115       break;
00116     default:
00117       LFATAL("Unknown normalization type: %d", int(normtyp));
00118     }
00119 
00120 #ifdef SHOW_MAXNORM_INFO
00121   getMinMax(result, mm, mmm);
00122   LDEBUG("newmin = %f, newmax = %f", float(mm), float(mmm));
00123 #endif
00124 
00125   return result;
00126 }
00127 
00128 // ######################################################################
00129 template <class T>
00130 Image<T> maxNormalizeNone(const Image<T>& src, const T mi, const T ma)
00131 {
00132 GVX_TRACE(__PRETTY_FUNCTION__);
00133   Image<T> result = src;
00134 
00135   // first clamp negative values to zero
00136   inplaceRectify(result);
00137 
00138   // then, normalize between mi and ma if not zero
00139   if (mi != T() || ma != T()) inplaceNormalize(result, mi, ma);
00140 
00141   return result;
00142 }
00143 
00144 // ######################################################################
00145 // ##### maxNorm from Itti et al, IEEE-PAMI, 1998:
00146 template <class T>
00147 Image<T> maxNormalizeStd(const Image<T>& src, const T mi, const T ma)
00148 {
00149 GVX_TRACE(__PRETTY_FUNCTION__);
00150   ASSERT(src.initialized());
00151   T zero = T();
00152 
00153   Image<T> result = src;
00154 
00155   // first clamp negative values to zero
00156   inplaceRectify(result);
00157 
00158   // then, normalize between mi and ma if not zero
00159   if (mi != zero || ma != zero) inplaceNormalize(result, mi, ma);
00160 
00161   const int w = result.getWidth();
00162   const int h = result.getHeight();
00163 
00164   // normalize between mi and ma and multiply by (max - mean)^2
00165 
00166   // we want to detect quickly local maxes, but avoid getting local mins
00167   T thresh = T(mi + (ma - mi) / 10.0);
00168 
00169   // then get the mean value of the local maxima:
00170   double lm_sum = 0.0;
00171   int lm_nb = 0;
00172   for (int j = 1; j < h - 1; j ++)
00173     for (int i = 1; i < w - 1; i ++)
00174       {
00175         int index = i + w * j;
00176         T val = result.getVal(index);
00177         if (val >= thresh &&
00178             val >= result.getVal(index - w) &&
00179             val >= result.getVal(index + w) &&
00180             val >= result.getVal(index - 1) &&
00181             val >= result.getVal(index + 1))  // local max
00182           {
00183             lm_sum += double(val);
00184             lm_nb ++;
00185           }
00186       }
00187   // scale factor is (max - mean_local_max)^2:
00188   if (lm_nb > 1)
00189     {
00190       double factor = ma - (T)(lm_sum / double(lm_nb));
00191       result *= T(factor * factor);
00192     }
00193   else if (lm_nb == 1)  // a single narrow peak
00194     result *= (ma * ma);
00195   else
00196     {
00197       /* LERROR("No local maxes found !!"); */
00198     }
00199 
00200   return result;
00201 }
00202 
00203 // ######################################################################
00204 // ##### fancyNorm from Itti et al, JEI, 2001 -- FAST implementation:
00205 template <class T>
00206 Image<T> maxNormalizeFancyFast(const Image<T>& src, const T mi, const T ma,
00207                                const int nbiter)
00208 {
00209 GVX_TRACE(__PRETTY_FUNCTION__);
00210   ASSERT(src.initialized());
00211   T zero = T();
00212 
00213   Image<T> result = src;
00214 
00215   // first clamp negative values to zero
00216   inplaceRectify(result);
00217 
00218   // then, normalize between mi and ma if not zero
00219   if (mi != zero || ma != zero) inplaceNormalize(result, mi, ma);
00220 
00221   const int w = result.getWidth();
00222   const int h = result.getHeight();
00223 
00224   int wh = std::max(w, h);
00225   // we want an inhibitory 1D sigma of at least FANCYISIG % of wh
00226   // we know that 1D sigma of the lowpass9 filter is 1.5 pixel
00227   // each level down a pyramid, 1D sigma increases by sqrt(5)
00228   int ilev = 1+(int)(log(float(wh) / 1.5 * FANCYISIG / 100.0) /
00229                      log(sqrt(5)));
00230 
00231   // This is needed for log() <= -2*log(sqrt(5)), i.e. wh <= 1.2 = 6 / 5
00232   if (ilev < 0) ilev = 0;
00233 
00234   int elev = (int)(log(float(wh) / 1.5 * FANCYESIG / 100.0) /
00235                    log(sqrt(5)));
00236 
00237   // This is needed for log() <= -log(sqrt(5)), i.e. wh <= 33.5 = 75 / sqrt(5)
00238   if (elev < 0) elev = 0;
00239 
00240   for (int i = 0; i < nbiter; ++i)
00241     {
00242       ImageSet<T> inhibPyr = buildPyrGaussian(result, 0, ilev+1, 9);
00243       Image<T> excit = inhibPyr[elev]; // excitatory center
00244       Image<T> inhib = inhibPyr[ilev]; // inhibitory surround
00245       excit *= T(FANCYCOEX); inhib *= T(FANCYCOIN);
00246       excit = rescale(excit, w, h);
00247       inplaceAttenuateBorders(excit, wh/16);
00248       inhib = rescale(inhib, w, h);
00249       excit -= inhib;
00250 
00251       T globinhi, minim, maxim; getMinMax(result, minim, maxim);
00252       globinhi = (T)(0.01 * FANCYINHI * maxim);
00253 
00254       result += excit;        // we get broad inhibition from everywhere
00255       result += -globinhi;    // we get fixed global inhibition
00256       inplaceRectify(result);
00257     }
00258 
00259   return result;
00260 }
00261 
00262 // ######################################################################
00263 // ##### fancyNorm from Itti et al, JEI, 2001 -- FULL implementation:
00264 template <class T>
00265 Image<T> maxNormalizeFancy(const Image<T>& src, const T mi, const T ma,
00266                            const int nbiter, const double weakness,
00267                            const Image<float>* lrexcit)
00268 {
00269 GVX_TRACE(__PRETTY_FUNCTION__);
00270   // Normalize using fancy normalization: multiple iterations of
00271   // filtering by a DoG
00272 
00273   ASSERT(src.initialized());
00274   T zero = T();
00275 
00276   Image<T> result = src;
00277 
00278   // first clamp negative values to zero
00279   inplaceRectify(result);
00280 
00281   // then, normalize between mi and ma if not zero
00282   if (mi != zero || ma != zero) inplaceNormalize(result, mi, ma);
00283 
00284   const int w = result.getWidth();
00285   const int h = result.getHeight();
00286 
00287   int siz = std::max(w, h);
00288   int maxhw = std::max(0, std::min(w, h) / 2 - 1);
00289   // build separable Gaussians for DoG computation:
00290   float esig = (float(siz) * FANCYESIG) * 0.01F;
00291   float isig = (float(siz) * FANCYISIG) * 0.01F;
00292   Image<float> gExc =
00293     gaussian<float>(FANCYCOEX/(esig*sqrt(2.0*M_PI)) * weakness, esig, maxhw);
00294   Image<float> gInh =
00295     gaussian<float>(FANCYCOIN/(isig*sqrt(2.0*M_PI)) * weakness, isig, maxhw);
00296 
00297   for (int i = 0; i < nbiter; ++i)
00298     {
00299       if (lrexcit)           // tuned long-range excitation
00300         {
00301           Image<T> tmp(result);
00302           tmp = downSize(tmp, w / (1<<LRLEVEL), h / (1<<LRLEVEL));
00303           tmp = convolve(tmp, *lrexcit, CONV_BOUNDARY_ZERO);  // full influence
00304           tmp += T(1.0);     // will be used as multiplicative excitation
00305           inplaceClamp(tmp, T(1.0), T(1.25));  // avoid crazyness
00306           tmp = rescale(tmp, w, h);
00307           T tmi, tma; getMinMax(tmp, tmi,tma);
00308           LDEBUG("lrexcit(%d): [%f..%f]", i, double(tmi), double(tma));
00309           result *= tmp;
00310         }
00311 
00312       Image<T> excit = sepFilter(result, gExc, gExc, CONV_BOUNDARY_CLEAN); // excitatory part
00313       Image<T> inhib = sepFilter(result, gInh, gInh, CONV_BOUNDARY_CLEAN); // inhibitory part
00314       excit -= inhib;
00315       T minim, maxim; getMinMax(result, minim, maxim);
00316       T globinhi = (T)(0.01 * FANCYINHI * maxim);
00317 
00318       result += excit;        // we get broad inhibition from everywhere
00319       result += -globinhi;    // we get fixed global inhibition
00320       inplaceRectify(result);
00321       //      sigmoid(FANCYG, FANCYH, FANCYS);
00322     }
00323 
00324   return result;
00325 }
00326 
00327 // ######################################################################
00328 // ##### fancyNorm from Itti et al, JEI, 2001 -- FULL implementation:
00329 // adapted to find landmarks
00330 template <class T>
00331 Image<T> maxNormalizeFancyLandmark(const Image<T>& src, const T mi, const T ma,
00332                            const int nbiter)
00333 {
00334 GVX_TRACE(__PRETTY_FUNCTION__);
00335   // Normalize using fancy normalization: multiple iterations of
00336   // filtering by a DoG
00337 
00338   ASSERT(src.initialized());
00339   T zero = T();
00340 
00341   Image<T> result = src;
00342 
00343   // first clamp negative values to zero
00344   inplaceRectify(result);
00345 
00346   // then, normalize between mi and ma if not zero
00347   if (mi != zero || ma != zero) inplaceNormalize(result, mi, ma);
00348 
00349   const int w = result.getWidth();
00350   const int h = result.getHeight();
00351 
00352   int siz = std::max(w, h);
00353   int maxhw = std::max(0, std::min(w, h) / 2 - 1);
00354   // build separable Gaussians for DoG computation:
00355   float esig = (float(siz)*2)*0.01;
00356   float isig = (float(siz)*3)*0.01;
00357   Image<float> gExc = gaussian<float>(FANCYCOEX/(esig*sqrt(2.0*M_PI)),
00358                                       esig, maxhw);
00359   Image<float> gInh = gaussian<float>(FANCYCOIN/(isig*sqrt(2.0*M_PI)),
00360                                       isig, maxhw);
00361 
00362   for (int i = 0; i < nbiter; ++i)
00363     {
00364       Image<T> excit = sepFilter(result, gExc, gExc, CONV_BOUNDARY_CLEAN); // excitatory part
00365       Image<T> inhib = sepFilter(result, gInh, gInh, CONV_BOUNDARY_CLEAN); // inhibitory part
00366       excit -= inhib;
00367       T minim, maxim; getMinMax(result, minim, maxim);
00368       T globinhi = (T)(0.01 * FANCYINHI * maxim);
00369 
00370       result += excit;        // we get broad inhibition from everywhere
00371       result += -globinhi;    // we get fixed global inhibition
00372       inplaceRectify(result);
00373       //      sigmoid(FANCYG, FANCYH, FANCYS);
00374     }
00375 
00376   return result;
00377 }
00378 
00379 // ######################################################################
00380 
00381 template <class T>
00382 Image<T> maxNormalizeLandmark(const Image<T>& src, const T mi, const T ma)
00383 {
00384 GVX_TRACE(__PRETTY_FUNCTION__);
00385   ASSERT(src.initialized());
00386   Image<T> result = src;
00387   inplaceNormalize(result, (T)MAXNORMMIN, (T)MAXNORMLANDMARK);
00388 
00389   // AIM: to find goodness of map
00390   // compare maps b4 and after maxnormalization fancy
00391   // comp_next = # components after maxnormalisation of map
00392   // area_prev = area of component b4 maxnorm
00393   // area_next = "     "         after "
00394   // activity_prev = activity of component b4 maxnorm
00395 
00396   Image<byte> target;
00397   Image<T> comp_map;
00398   T max, thresh;
00399   float area_prev = 0.0f;
00400   int comp_next = 0;
00401   double activity_prev = 0.0, real_activity = 0.0, standout = 0.0;
00402   double sum_prev = 0.0, sum_next = 0.0;
00403   float goodness_map = 0.0f; // is this a good map for landmarks?
00404   float landmarkness = 0.0f; // is this a good landmark?
00405 
00406   thresh = (T) MAXNORMMIN;
00407   Point2D<int> max_locn;
00408   findMax(result, max_locn, max);
00409 
00410   // find values b4 maxnorm
00411   while(max > thresh)
00412     {
00413       area_prev = 0.0f;
00414       activity_prev = 0.0;
00415       int val = segmentLandmark(result, max_locn, target, activity_prev,
00416                                standout, area_prev);
00417 
00418       if (val != -1)
00419         {
00420           result =  result - result * (Image<T>)target;
00421           real_activity = (double)src.getVal(max_locn);
00422           findMax(result, max_locn, max);
00423 
00424            if(area_prev > 0.125)
00425             {
00426               sum_prev += (double)area_prev * activity_prev;
00427 
00428               // find peaks within this component
00429               int peaks = findPeaks((Image<T>)target,(T) MAXNORMMIN,
00430                                     (T) MAXNORMLANDMARK,
00431                                     sum_next);
00432               if(peaks == 0)
00433                 {
00434                   peaks = 10; // very irregular, hence cancelled
00435                 }
00436 
00437               // compute landmarkness value
00438               LINFO("area_prev = %f, peaks = %d",
00439                     area_prev, peaks);
00440               LINFO("real_activity  = %f, activity_prev = %f, standout = %f",
00441                     real_activity, activity_prev, standout);
00442               landmarkness = (float) (real_activity * standout);
00443               //landmarkness = (float)real_activity /
00444               //  (area_prev * peaks * peaks);
00445               //landmarkness *= 10.0f;
00446               LINFO("-----landmarkness = %f", landmarkness);
00447 
00448               if (!comp_map.initialized())
00449                 comp_map = (Image<T>)target / 255.0f * (T)landmarkness ;
00450               else comp_map += (Image<T>)target / 255.0f * (T)landmarkness;
00451             }
00452         }
00453       else break;
00454     }
00455 
00456   // find peaks in this image
00457   result = src;
00458   comp_next = findPeaks(result,(T) MAXNORMMIN, (T) MAXNORMLANDMARK,
00459                                 sum_next);
00460 
00461   // compute goodness
00462   if(comp_next == 0)
00463     {
00464       comp_next = 10; // very irregular, hence cancelled
00465     }
00466   if (sum_prev != 0.0)
00467     goodness_map = (float)(sum_next / (sum_prev * comp_next * comp_next)) ;
00468 
00469   goodness_map = pow(goodness_map, 0.5);
00470   LINFO("# of comps = %d", comp_next);
00471 
00472   LINFO("goodness_map = %f", goodness_map);
00473 
00474   // all components found
00475   if (comp_map.initialized())
00476     comp_map *= (T)(goodness_map);
00477 
00478   else comp_map.resize(src.getDims(), true);
00479   return comp_map;
00480 }
00481 
00482 // ######################################################################
00483 template <class T>
00484 int findPeaks(const Image<T>& src, const T mi, const T ma,
00485               double& sum_activity)
00486 {
00487 GVX_TRACE(__PRETTY_FUNCTION__);
00488   Image<T> result = src;
00489   result = maxNormalize(result, mi, ma, VCXNORM_FANCY);
00490   T max, thresh; Point2D<int> max_locn; double standout = 0.0;
00491   int peaks = 0;
00492   thresh = (T)((ma - mi)/10 + mi);
00493   sum_activity = 0.0;
00494 
00495   findMax(result, max_locn, max);
00496   while(max > thresh)
00497     {
00498       float area = 0.0f; double activity = 0.0; Image<byte> target;
00499       int val = segmentLandmark(result, max_locn, target,
00500                                    activity, standout, area);
00501       if(val != -1)
00502         {
00503           if(area > 0.0675)
00504             {
00505               peaks++;
00506               sum_activity += (double)area * activity;
00507             }
00508           result = result - result * (Image<T>)target;
00509           findMax(result, max_locn, max);
00510         }
00511       else break;
00512     }
00513   return peaks;
00514 }
00515 
00516 //******************************************************************
00517 template <class T>
00518 float goodness_map(const Image<T>& src)
00519 {
00520 GVX_TRACE(__PRETTY_FUNCTION__);
00521   ASSERT(src.initialized());
00522 
00523   Image<T> result = src;
00524   inplaceNormalize(result, (T)MAXNORMMIN, (T)MAXNORMLANDMARK);
00525 
00526   // AIM: to find goodness of map
00527   // compare maps b4 and after maxnormalization fancy
00528   // comp_next = # components after maxnormalisation of map
00529   // area_prev = area of component b4 maxnorm
00530   // area_next = "     "         after "
00531   // activity_prev = activity of component b4 maxnorm
00532 
00533   Image<byte> target;
00534   Image<T> comp_map;
00535   T max, thresh;
00536   float area_prev = 0.0f;
00537   int comp_next = 0;
00538   double standout = 0.0, activity_prev = 0.0;
00539   double sum_prev = 0.0, sum_next = 0.0;
00540   float goodness_map = 0.0f; // is this a good map for landmarks?
00541 
00542 
00543   thresh = (T) MAXNORMMIN;
00544   Point2D<int> max_locn;
00545   findMax(result, max_locn, max);
00546 
00547   // find values b4 maxnorm
00548   while(max > thresh)
00549     {
00550       area_prev = 0.0f;
00551       activity_prev = 0.0, standout = 0.0 ;
00552       int val = segmentLandmark(result, max_locn, target, activity_prev,
00553                                 standout, area_prev);
00554 
00555       if (val != -1)
00556         {
00557           result =  result - result * (Image<T>)target;
00558           findMax(result, max_locn, max);
00559 
00560            if(area_prev > 0.125)
00561             {
00562               sum_prev += (double)area_prev * activity_prev;
00563             }
00564         }
00565       else break;
00566     }
00567   result = src;
00568   comp_next = findPeaks(result,(T) MAXNORMMIN, (T) MAXNORMLANDMARK,
00569                         sum_next);
00570 
00571   // compute goodness
00572   if(comp_next == 0)
00573     {
00574       comp_next = 10; // very irregular, hence cancelled
00575     }
00576   if (sum_prev != 0.0)
00577     goodness_map = (float)(sum_next / (sum_prev * comp_next * comp_next)) ;
00578   LINFO("# of comps = %d", comp_next);
00579   LINFO("goodness_map = %f", goodness_map);
00580 
00581   return goodness_map;
00582 }
00583 
00584 // ######################################################################
00585 template <class T>
00586 Image<T> maxNormalizeStdev(const Image<T>& src)
00587 {
00588   // renormalize the image to have stdev=1 and minval=0
00589 
00590   const float s = float(stdev(src));
00591 
00592   if (s == 0.0f)
00593     return Image<T>(src.getDims(), ZEROS);
00594 
00595   typedef typename promote_trait<T, float>::TP TF;
00596 
00597   Image<TF> result(src);
00598   result /= s;
00599 
00600   TF mini, maxi; getMinMax(result, mini, maxi);
00601   result -= mini;
00602 
00603   return Image<T>(result);
00604 }
00605 
00606 // ######################################################################
00607 template <class T>
00608 Image<T> maxNormalizeStdev0(const Image<T>& src)
00609 {
00610   // renormalize the image to have mean=0 and stdev=1
00611 
00612   const float s = float(stdev(src));
00613   const float u = float(mean(src));
00614 
00615   if (s == 0.0f)
00616     return Image<T>(src.getDims(), ZEROS);
00617 
00618   typedef typename promote_trait<T, float>::TP TF;
00619 
00620   Image<TF> result(src);
00621   result -= u; // mean -> 0
00622   result /= s; // stdev -> 1
00623 
00624   return Image<T>(result);
00625 }
00626 
00627 
00628 // ######################################################################
00629 // converters for MaxNormType
00630 // ######################################################################
00631 
00632 std::string convertToString(const MaxNormType val)
00633 {
00634 GVX_TRACE(__PRETTY_FUNCTION__);
00635   return maxNormTypeName(val);
00636 }
00637 
00638 void convertFromString(const std::string& str, MaxNormType& val)
00639 {
00640 GVX_TRACE(__PRETTY_FUNCTION__);
00641   // CAUTION: assumes types are numbered and ordered!
00642   for (int i = 0; i < NBMAXNORMTYPES; i ++)
00643     if (str.compare(maxNormTypeName(MaxNormType(i))) == 0)
00644       { val = MaxNormType(i); return; }
00645 
00646   conversion_error::raise<MaxNormType>(str);
00647 }
00648 
00649 
00650 
00651 // ######################################################################
00652 #include "inst/Image/fancynorm.I"
00653 
00654 // ######################################################################
00655 /* So things look consistent in everyone's emacs... */
00656 /* Local Variables: */
00657 /* indent-tabs-mode: nil */
00658 /* End: */
Generated on Sun May 8 08:05:07 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3