Scorer.C

Go to the documentation of this file.
00001 /*!@file TIGS/Scorer.C Score the fit between predicted and actual eye positions */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00005 // by the 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: Rob Peters <rjpeters at usc dot edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/TIGS/Scorer.C $
00035 // $Id: Scorer.C 9412 2008-03-10 23:10:15Z farhan $
00036 //
00037 
00038 #ifndef TIGS_SCORER_C_DEFINED
00039 #define TIGS_SCORER_C_DEFINED
00040 
00041 #include "TIGS/Scorer.H"
00042 
00043 #include "Image/MathOps.H"
00044 #include "Util/MathFunctions.H" // for clampValue()
00045 #include "Util/sformat.H"
00046 #include "rutz/trace.h"
00047 
00048 #include <ostream>
00049 
00050 Scorer::~Scorer() {}
00051 
00052 KLScorer::KLScorer(int nbins, int nrand)
00053   :
00054   itsNbins(nbins),
00055   itsNrand(nrand),
00056   itsObservedBins(1, nbins, ZEROS),
00057   itsRandomBins(nrand, nbins, ZEROS),
00058   itsNtrials(0)
00059 {}
00060 
00061 KLScorer::~KLScorer() {}
00062 
00063 void KLScorer::accum(const Image<float>& eyeposmap, int pos)
00064 {
00065   GVX_TRACE(__PRETTY_FUNCTION__);
00066 
00067   float mi, ma; getMinMax(eyeposmap, mi, ma);
00068 
00069   // rescale into the range [0..nbins]
00070   Image<float> scaledmap = eyeposmap - mi;
00071   if ((ma-mi) > 0.0f)
00072     scaledmap /= ((ma-mi) / itsNbins);
00073 
00074   ASSERT(pos >= 0);
00075   ASSERT(pos < scaledmap.getSize());
00076   const int humanval = clampValue(int(scaledmap[pos]), 0, itsNbins - 1);
00077 
00078   ASSERT(humanval >= 0);
00079   ASSERT(humanval < itsObservedBins.getSize());
00080   itsObservedBins[humanval] += 1;
00081 
00082   for (int i = 0; i < itsNrand; ++i)
00083     {
00084       const int randpos = theirGenerator.idraw(scaledmap.getSize());
00085 
00086       ASSERT(randpos >= 0);
00087       ASSERT(randpos < scaledmap.getSize());
00088       const int randval = clampValue(int(scaledmap[randpos]), 0, itsNbins - 1);
00089 
00090       ASSERT(i >= 0);
00091       ASSERT(i < itsRandomBins.getWidth());
00092       ASSERT(randval >= 0);
00093       ASSERT(randval < itsRandomBins.getHeight());
00094       itsRandomBins[Point2D<int>(i, randval)] += 1;
00095     }
00096 
00097   ++itsNtrials;
00098 }
00099 
00100 std::string KLScorer::getScoreString(const std::string& name)
00101 {
00102   if (itsNtrials == 0)
00103     {
00104       return sformat("[%s] no klscore observations", name.c_str());
00105     }
00106 
00107   Image<double> scores(itsNrand, 1, ZEROS);
00108 
00109   // count how many zeros we encounter in the histograms; we only
00110   // have a "non-tainted" kl score if there are no zeros
00111   int tainted = 0;
00112 
00113   for (int i = 0; i < itsNrand; ++i)
00114     {
00115       double currentscore = 0.0;
00116 
00117       for (int j = 0; j < itsNbins; ++j)
00118         {
00119           ASSERT(j < itsObservedBins.getSize());
00120           const double aa = itsObservedBins[j] / double(itsNtrials);
00121           ASSERT(i < itsRandomBins.getWidth());
00122           ASSERT(j < itsRandomBins.getHeight());
00123           const double bb = itsRandomBins[Point2D<int>(i,j)] / double(itsNtrials);
00124 
00125           if (aa != 0.0 && bb != 0.0)
00126             {
00127               currentscore += 0.5 * (aa*log(aa/bb) + bb*log(bb/aa));
00128             }
00129           else
00130             {
00131               ++tainted;
00132             }
00133         }
00134 
00135       ASSERT(i < scores.getSize());
00136       scores[i] = currentscore;
00137     }
00138 
00139   const double klmean = mean(scores);
00140   const double klstdev = stdev(scores);
00141 
00142   return sformat("[%s] %s (nt=%d) klscore: %10.5f +/- %10.5f",
00143                  name.c_str(), tainted > 0 ? "tainted" : "notaint",
00144                  tainted, klmean, klstdev);
00145 }
00146 
00147 rutz::urand KLScorer::theirGenerator(time((time_t*)0)+getpid());
00148 
00149 NssScorer::NssScorer()
00150   :
00151   currentZscore(0.0),
00152   observedZscore(0.0),
00153   maxZscore(0.0),
00154   observedCount(0)
00155 {}
00156 
00157 void NssScorer::accum(const Image<float>& eyeposmap, int pos)
00158 {
00159   GVX_TRACE(__PRETTY_FUNCTION__);
00160 
00161   float mi, ma, me; getMinMaxAvg(eyeposmap, mi, ma, me);
00162 
00163   float std = stdev(eyeposmap);
00164 
00165   if (std > 0.0)
00166     {
00167       currentZscore   = (eyeposmap[pos] - me) / std;
00168       observedZscore += currentZscore;
00169       maxZscore      += (ma - me) / std;
00170     }
00171   else
00172     {
00173       currentZscore = 0.0;
00174     }
00175 
00176   ++observedCount;
00177 }
00178 
00179 std::string NssScorer::getScoreString(const std::string& name)
00180 {
00181   if (observedCount > 0)
00182     return sformat("[%s] observed zscore: %10.5f max zscore: %10.5f",
00183                    name.c_str(), observedZscore / observedCount,
00184                    maxZscore / observedCount);
00185   // else...
00186   return sformat("[%s] no zscore observations", name.c_str());
00187 }
00188 
00189 SwpeScorer::SwpeScorer()
00190   :
00191   itsDims(),
00192   itsEyeScore(0.0),
00193   itsRandEyeScore(0.0),
00194   itsRandMapScore(0.0),
00195   itsObservedCount(0),
00196   itsGenerator(time((time_t*)0)+getpid())
00197 {}
00198 
00199 namespace
00200 {
00201   double getSwpe(const Image<float>& smap, const Point2D<int>& pos)
00202   {
00203     const int w = smap.getWidth();
00204     const int h = smap.getHeight();
00205 
00206     double result = 0.0;
00207     double mapsum = 0.0;
00208 
00209     for (int y = 0; y < h; ++y)
00210       for (int x = 0; x < w; ++x)
00211         {
00212           const double dist =
00213             sqrt((double(x-pos.i) * double(x-pos.i)) +
00214                  (double(y-pos.j) * double(y-pos.j)));
00215 
00216           const double mapval = smap.getVal(x,y);
00217 
00218           result += mapval * dist;
00219           mapsum += mapval;
00220         }
00221 
00222     return (result / mapsum);
00223   }
00224 }
00225 
00226 void SwpeScorer::accum(const Image<float>& eyeposmap, int pos)
00227 {
00228   GVX_TRACE(__PRETTY_FUNCTION__);
00229 
00230   if (itsDims.isEmpty())
00231     {
00232       itsDims = eyeposmap.getDims();
00233     }
00234   else
00235     {
00236       if (itsDims != eyeposmap.getDims())
00237         LFATAL("wrong eyeposmap dims (expected %dx%d, got %dx%d)",
00238                itsDims.w(), itsDims.h(),
00239                eyeposmap.getWidth(), eyeposmap.getHeight());
00240     }
00241 
00242   const Point2D<int> eye(pos % eyeposmap.getWidth(),
00243                     pos / eyeposmap.getWidth());
00244 
00245   const Point2D<int> randpos(itsGenerator.idraw_range(0, eyeposmap.getWidth()),
00246                         itsGenerator.idraw_range(0, eyeposmap.getHeight()));
00247 
00248   Image<float> randmap(eyeposmap.getDims(), NO_INIT);
00249   for (Image<float>::iterator itr = randmap.beginw(), stop = randmap.endw();
00250        itr != stop; ++itr)
00251     *itr = itsGenerator.fdraw();
00252 
00253   Image<float> flatmap(eyeposmap.getDims(), NO_INIT);
00254   flatmap.clear(1.0f);
00255 
00256   itsEyeScore += getSwpe(eyeposmap, eye);
00257   itsRandEyeScore += getSwpe(eyeposmap, randpos);
00258   itsRandMapScore += getSwpe(randmap, eye);
00259   itsFlatMapScore += getSwpe(flatmap, eye);
00260 
00261   ++itsObservedCount;
00262 }
00263 
00264 std::string SwpeScorer::getScoreString(const std::string& name)
00265 {
00266   if (itsObservedCount > 0)
00267     return sformat("[%s] swpe (dims %dx%d) "
00268                    "eye@smap: %10.5f "
00269                    "eye@randmap: %10.5f "
00270                    "eye@flatmap: %10.5f "
00271                    "rand@smap: %10.5f ",
00272                    name.c_str(),
00273                    itsDims.w(), itsDims.h(),
00274                    itsEyeScore / itsObservedCount,
00275                    itsRandMapScore / itsObservedCount,
00276                    itsFlatMapScore / itsObservedCount,
00277                    itsRandEyeScore / itsObservedCount);
00278 
00279   // else...
00280   return sformat("[%s] swpe no data", name.c_str());
00281 }
00282 
00283 PercentileScorer::PercentileScorer()
00284   :
00285   currentPrctile(0.0),
00286   observedPrctile(0.0),
00287   observedCount(0)
00288 {}
00289 
00290 void PercentileScorer::accum(const Image<float>& eyeposmap, int pos)
00291 {
00292   GVX_TRACE(__PRETTY_FUNCTION__);
00293   const float observed = eyeposmap[pos];
00294 
00295   int nless = 0, nequal = 0;
00296   for (int i = 0; i < eyeposmap.getSize(); ++i)
00297     {
00298       if (eyeposmap[i] < observed) ++nless;
00299       else if (eyeposmap[i] == observed) ++nequal;
00300     }
00301 
00302   ASSERT(eyeposmap.getSize() > 0);
00303 
00304   currentPrctile =
00305     (nless + nequal/2.0)/double(eyeposmap.getSize());
00306 
00307   observedPrctile += currentPrctile;
00308 
00309   ++observedCount;
00310 }
00311 
00312 std::string PercentileScorer::getScoreString(const std::string& name)
00313 {
00314   if (observedCount > 0)
00315     return sformat("[%s] current prctile: %10.5f overall prctile: %10.5f",
00316                    name.c_str(), currentPrctile,
00317                    observedPrctile / observedCount);
00318   // else...
00319   return sformat("[%s] no prctile observations", name.c_str());
00320 }
00321 
00322 MulticastScorer::MulticastScorer()
00323   :
00324   observedCount(0),
00325   itsPrctileScorer(),
00326   itsNssScorer(),
00327   itsKLScorer(10, 100),
00328   itsSwpeScorer()
00329 {}
00330 
00331 void MulticastScorer::score(const std::string& name,
00332                             const Image<float>& eyeposmap, int pos)
00333 {
00334   ++observedCount;
00335 
00336   itsPrctileScorer.accum(eyeposmap, pos);
00337   itsNssScorer.accum(eyeposmap, pos);
00338   itsKLScorer.accum(eyeposmap, pos);
00339   itsSwpeScorer.accum(eyeposmap, pos);
00340 
00341   if (observedCount % 100 == 1)
00342     this->showScore(name);
00343 }
00344 
00345 void MulticastScorer::showScore(const std::string& name)
00346 {
00347   if (observedCount > 0)
00348     {
00349       LINFO("%s", itsPrctileScorer.getScoreString(name).c_str());
00350       LINFO("%s", itsNssScorer.getScoreString(name).c_str());
00351       LINFO("%s", itsKLScorer.getScoreString(name).c_str());
00352       LINFO("%s", itsSwpeScorer.getScoreString(name).c_str());
00353     }
00354 }
00355 
00356 void MulticastScorer::writeScore(const std::string& name,
00357                                  std::ostream& os)
00358 {
00359   if (observedCount > 0)
00360     {
00361       os << itsPrctileScorer.getScoreString(name) << std::endl;
00362       os << itsNssScorer.getScoreString(name) << std::endl;
00363       os << itsKLScorer.getScoreString(name) << std::endl;
00364       os << itsSwpeScorer.getScoreString(name) << std::endl;
00365     }
00366 }
00367 
00368 // ######################################################################
00369 /* So things look consistent in everyone's emacs... */
00370 /* Local Variables: */
00371 /* mode: c++ */
00372 /* indent-tabs-mode: nil */
00373 /* End: */
00374 
00375 #endif // TIGS_SCORER_C_DEFINED
Generated on Sun May 8 08:06:56 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3