OptimalGains.C

Go to the documentation of this file.
00001 /*!@file Channels/OptimalGains.C Compute the optimal gains that maximize SNR */
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:
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Channels/OptimalGains.C $
00035 // $Id: OptimalGains.C 10794 2009-02-08 06:21:09Z itti $
00036 //
00037 
00038 #ifndef CHANNELS_OPTIMALGAINS_C_DEFINED
00039 #define CHANNELS_OPTIMALGAINS_C_DEFINED
00040 
00041 #include "Channels/OptimalGains.H"
00042 
00043 #include "Channels/ChannelFacets.H"
00044 #include "Channels/ComplexChannel.H"
00045 #include "Channels/SingleChannel.H"
00046 #include "Component/ParamMap.H"
00047 #include "Image/MathOps.H"
00048 #include "Image/ShapeOps.H" // for rescale()
00049 #include "Util/sformat.H"
00050 
00051 #include <vector>
00052 
00053 // ######################################################################
00054 OptimalGainsFinder::OptimalGainsFinder(const Image<byte>& targetMask,
00055                                        const Image<byte>& distractorMask,
00056                                        rutz::shared_ptr<ParamMap> pmap,
00057                                        const bool doMax)
00058   :
00059   itsTargetMask(targetMask),
00060   itsDistractorMask(distractorMask),
00061   itsPmap(pmap),
00062   itsDoMax(doMax)
00063 { }
00064 
00065 // ######################################################################
00066 OptimalGainsFinder::~OptimalGainsFinder()
00067 { }
00068 
00069 // ######################################################################
00070 void OptimalGainsFinder::visitChannelBase(ChannelBase& chan)
00071 { LFATAL("don't know how to handle %s", chan.tagName().c_str()); }
00072 
00073 // ######################################################################
00074 void OptimalGainsFinder::visitSingleChannel(SingleChannel& chan)
00075 {
00076   // get or install some ChannelFacet for the gains:
00077   rutz::shared_ptr<ChannelFacetGainSingle> gfacet;
00078   if (chan.hasFacet<ChannelFacetGainSingle>())
00079     gfacet = chan.getFacet<ChannelFacetGainSingle>();
00080   else
00081     { gfacet.reset(new ChannelFacetGainSingle(chan)); chan.setFacet(gfacet); }
00082 
00083   /* 1. for each submap i, find sT and sD, the salience of the target T
00084         and distractors D
00085      2. find SNR
00086      3. find g = SNR / (sum(SNR_j) / n) where n is the number of submaps. */
00087 
00088   const uint num = chan.numSubmaps();
00089   float sumSNR = 0.0f, SNR[num];
00090 
00091   Image<byte> tmap, dmap;
00092   if (itsTargetMask.initialized())
00093     tmap = rescale(itsTargetMask, chan.getMapDims());
00094   if (itsDistractorMask.initialized())
00095     dmap = rescale(itsDistractorMask, chan.getMapDims());
00096 
00097   for (uint idx = 0; idx < num; idx ++)
00098     {
00099       const Image<float> submap = chan.getSubmap(idx);
00100       float sT = 0.0f, sD = 0.0f; // default values if some mask is missing
00101       float junk1, junk2, junk3;
00102 
00103       // how to compute SNR? max(sT) / max(sD) or mean(sT) / mean(sD)??
00104       if (itsDoMax)
00105         {
00106           // SNR = max(sT) / max(sD)
00107           // sT is max salience within target object
00108           if (tmap.initialized())
00109             getMaskedMinMax(submap, tmap, junk1, sT, junk2, junk3);
00110           // sD is max salience within distractor object
00111           if (dmap.initialized())
00112             getMaskedMinMax(submap, dmap, junk1, sD, junk2, junk3);
00113         }
00114       else
00115         {
00116           // SNR = mean(sT) / mean(sD)
00117           // sT is mean salience within target object
00118           if (tmap.initialized())
00119             getMaskedMinMaxAvg(submap, tmap, junk1, junk2, sT);
00120           // sD is mean salience within distractor object
00121           if (dmap.initialized())
00122             getMaskedMinMaxAvg(submap, dmap, junk1, junk2, sD);
00123         }
00124 
00125       SNR[idx] = (sT + OPTIGAIN_BG_FIRING) / (sD + OPTIGAIN_BG_FIRING);
00126       sumSNR += SNR[idx];
00127 
00128       // store these salience values so that they can be written out later
00129       itsPmap->putDoubleParam(sformat("salienceT(%d)", idx), sT);
00130       itsPmap->putDoubleParam(sformat("salienceD(%d)", idx), sD);
00131 
00132       uint c = 0, s = 0; chan.getLevelSpec().indexToCS(idx, c, s);
00133       LDEBUG("%s(%d,%d): sT=%f, sD=%f", chan.tagName().c_str(), c, s, sT, sD);
00134     }
00135   sumSNR /= num;
00136 
00137   // find the optimal gains g
00138   for (uint idx = 0; idx < num; idx ++)
00139     {
00140       const float gain = SNR[idx] / sumSNR;
00141       uint clev = 0, slev = 0; chan.getLevelSpec().indexToCS(idx, clev, slev);
00142       LINFO("%s(%d,%d): gain = %f, SNR = %f", chan.tagName().c_str(),
00143             clev, slev, gain, SNR[idx]);
00144       gfacet->setVal(idx, gain);
00145     }
00146 
00147   // find the biased saliency map for this single channel and cache it
00148   // so that the parent complex channels can use it to find SNR:
00149   chan.killCaches();
00150   (void) chan.getOutput();
00151 }
00152 
00153 // ######################################################################
00154 void OptimalGainsFinder::visitComplexChannel(ComplexChannel& chan)
00155 {
00156   // get or install some ChannelFacet for the gains:
00157   rutz::shared_ptr<ChannelFacetGainComplex> gfacet;
00158   if (chan.hasFacet<ChannelFacetGainComplex>())
00159     gfacet = chan.getFacet<ChannelFacetGainComplex>();
00160   else
00161     { gfacet.reset(new ChannelFacetGainComplex(chan)); chan.setFacet(gfacet); }
00162 
00163   // first find the optimal gains within sub channels
00164   const uint num = chan.numChans();
00165   rutz::shared_ptr<ParamMap> pmapsave = itsPmap;
00166   for (uint idx = 0; idx < num; idx ++)
00167     {
00168       // visit the subchan, it will update itsPmap:
00169       itsPmap.reset(new ParamMap());
00170       chan.subChan(idx)->accept(*this);
00171 
00172       // store subchan index, for human consumption:
00173       itsPmap->putIntParam("subchanidx", idx);
00174 
00175       // store the submap for the subchan:
00176       pmapsave->putSubpmap(chan.subChan(idx)->tagName(), itsPmap);
00177     }
00178   itsPmap.swap(pmapsave);
00179 
00180   /* 1. for each subchannel i, find sT and sD, the salience of the target T
00181         and distractors D
00182      2. find SNR
00183      3. find g = SNR / (sum(SNR_j) / n) where n is the number of subchannels */
00184   float sumSNR = 0.0f, SNR[num];
00185 
00186   Image<byte> tmap, dmap;
00187   if (itsTargetMask.initialized())
00188     tmap = rescale(itsTargetMask, chan.getMapDims());
00189   if (itsDistractorMask.initialized())
00190     dmap = rescale(itsDistractorMask, chan.getMapDims());
00191 
00192   // next, find the optimal gains for the sub channels
00193   for (uint idx = 0; idx < num; idx ++)
00194     {
00195       // find the biased saliency maps for the sub channels
00196       const Image<float> submap = chan.subChan(idx)->getOutput();
00197       float sT = 0.0f, sD = 0.0f; // default values if some mask is missing
00198       float junk1, junk2, junk3;
00199 
00200       // how to compute SNR? max(sT) / max(sD) or mean(sT) / mean(sD)??
00201       if (itsDoMax)
00202         {
00203           // SNR = max(sT) / max(sD)
00204           // sT is max salience within target object
00205           if (tmap.initialized())
00206             getMaskedMinMax(submap, tmap, junk1, sT, junk2, junk3);
00207           // sD is max salience within distractor object
00208           if (dmap.initialized())
00209             getMaskedMinMax(submap, dmap, junk1, sD, junk2, junk3);
00210         }
00211       else
00212         {
00213           // SNR = mean(sT) / mean(sD)
00214           // sT is mean salience within target object
00215           if (tmap.initialized())
00216             getMaskedMinMaxAvg(submap, tmap, junk1, junk2, sT);
00217           // sD is mean salience within distractor object
00218           if (dmap.initialized())
00219             getMaskedMinMaxAvg(submap, dmap, junk1, junk2, sD);
00220         }
00221 
00222       SNR[idx] = (sT + OPTIGAIN_BG_FIRING) / (sD + OPTIGAIN_BG_FIRING);
00223       sumSNR += SNR[idx];
00224 
00225       // store these salience values so that they can be written out later
00226       itsPmap->putDoubleParam(sformat("salienceT(%d)", idx), sT);
00227       itsPmap->putDoubleParam(sformat("salienceD(%d)", idx), sD);
00228 
00229       LDEBUG("%s: sT=%f, sD=%f", chan.subChan(idx)->tagName().c_str(), sT, sD);
00230     }
00231   sumSNR /= num;
00232 
00233   // find the optimal gains
00234   for (uint idx = 0; idx < num; idx ++)
00235     {
00236       const float gain = SNR[idx] / sumSNR;
00237       LINFO("%s: gain = %f, SNR = %f", chan.subChan(idx)->tagName().c_str(),
00238             gain, SNR[idx]);
00239       gfacet->setVal(idx, gain);
00240     }
00241 
00242   // find the biased saliency map and cache it so that visual cortex
00243   // may use it to compute SNR:
00244   chan.killCaches();
00245   (void) chan.getOutput();
00246 }
00247 
00248 // ######################################################################
00249 rutz::shared_ptr<ParamMap> OptimalGainsFinder::pmap() const
00250 { return itsPmap; }
00251 
00252 
00253 // ######################################################################
00254 /* So things look consistent in everyone's emacs... */
00255 /* Local Variables: */
00256 /* mode: c++ */
00257 /* indent-tabs-mode: nil */
00258 /* End: */
00259 
00260 #endif // CHANNELS_OPTIMALGAINS_C_DEFINED
Generated on Sun May 8 08:40:22 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3