00001 /*!@file AppNeuro/app-combineOptimalGains.C combine optimal gains files */ 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: Vidhya Navalpakkam <navalpak@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/AppNeuro/app-combineOptimalGains.C $ 00035 // $Id: app-combineOptimalGains.C 11159 2009-05-02 03:04:10Z itti $ 00036 // 00037 00038 #include "Channels/OptimalGains.H" 00039 #include "Component/ModelManager.H" 00040 #include "Component/ParamMap.H" 00041 #include "Component/ModelOptionDef.H" 00042 #include "Neuro/NeuroOpts.H" 00043 #include "Util/sformat.H" 00044 00045 static const ModelOptionDef OPT_SaveTo = 00046 { MODOPT_ARG(std::string), "SaveTo", &MOC_DISPLAY, OPTEXP_SAVE, 00047 "Save output gains to file if name specified (rather than stdout)", 00048 "save-to", '\0', "", "" }; 00049 00050 // ###################################################################### 00051 /* combine params: 00052 1. for each i, find the mean salience s_iT, s_iD across all inputs 00053 2. find SNR_i = s_iT / s_iD 00054 3. find g_i = SNR_i / (sum(SNR_i) / n) 00055 */ 00056 rutz::shared_ptr<ParamMap> 00057 combineParamMaps(std::vector<rutz::shared_ptr<ParamMap> > pmaps, 00058 const uint indent) 00059 { 00060 rutz::shared_ptr<ParamMap> outpmap(new ParamMap()); 00061 const std::string id(indent, ' '); 00062 00063 // take the first pmap as reference for the keys, and loop over keys: 00064 ParamMap::key_iterator 00065 itr = pmaps[0]->keys_begin(), stop = pmaps[0]->keys_end(); 00066 00067 while (itr != stop) { 00068 const std::string name = *itr; 00069 00070 // find a submap or copy the subchanidx info: 00071 if (pmaps[0]->isLeaf(name)) { 00072 if (name.compare("subchanidx") == 0) 00073 outpmap->putIntParam(name, pmaps[0]->getIntParam(name)); 00074 } else { 00075 // it's a subpmap, let's recurse through it: for that, we need 00076 // to extract the subpmaps from all our input pmaps. This will 00077 // LFATAL if there is inconsistency among our input pmaps: 00078 std::vector<rutz::shared_ptr<ParamMap> > subpmaps; 00079 for (uint i = 0; i < pmaps.size(); i ++) 00080 subpmaps.push_back(pmaps[i]->getSubpmap(name)); 00081 00082 // recurse: 00083 LDEBUG("%s%s:", id.c_str(), name.c_str()); 00084 outpmap->putSubpmap(name, combineParamMaps(subpmaps, indent + 2)); 00085 } 00086 ++itr; 00087 } 00088 00089 // now compute the gain at our level: 00090 uint i = 0; 00091 double sumSNR = 0.0; std::vector<double> SNR; 00092 while (pmaps[0]->hasParam(sformat("salienceT(%d)", i))) 00093 { 00094 double sT = 0.0, sD = 0.0; 00095 for (uint j = 0; j < pmaps.size(); j ++) 00096 { 00097 sT += pmaps[j]->getDoubleParam(sformat("salienceT(%d)", i)); 00098 sD += pmaps[j]->getDoubleParam(sformat("salienceD(%d)", i)); 00099 } 00100 sT /= pmaps.size(); sD /= pmaps.size(); 00101 00102 // compute SNR: 00103 const double snr = (sT + OPTIGAIN_BG_FIRING) / (sD + OPTIGAIN_BG_FIRING); 00104 SNR.push_back(snr); 00105 sumSNR += snr; 00106 ++i; 00107 } 00108 sumSNR /= SNR.size(); 00109 00110 // find the optimal gains 00111 for (uint idx = 0; idx < SNR.size(); idx ++) 00112 { 00113 const double g = SNR[idx] / sumSNR; 00114 LDEBUG("%sgain(%d) = %f, SNR = %f", id.c_str(), idx, g, SNR[idx]); 00115 outpmap->putDoubleParam(sformat("gain(%d)", idx), g); 00116 } 00117 00118 return outpmap; 00119 } 00120 00121 // ###################################################################### 00122 //! Combine several stsd.pmap files into a gains.pmap file 00123 /*! The stsd.pmap files should be obtained by running something like: 00124 00125 ezvision --in=xmlfile:testfile.xml --out=display --pfc-type=OG 00126 --vc-type=Std --vc-chans=GNO --stsd-filename=stsd.pmap --nouse-older-version 00127 00128 which will compute the salience of target and distractor and save 00129 those to a ParamMap. Once you have several of these (or just one), 00130 you can use the present program to generate an optimal gains 00131 ParamMap (it is written to stdout). Finally, you can use these 00132 gains for biased saliency computations using a PrefrontalCortexGS, 00133 e.g.: 00134 00135 ezvision --in=image.png --out=display -X --pfc-type=GS --vc-type=Std --vc-chans=GNO 00136 --gains-filename=gains.pmap --nouse-older-version 00137 */ 00138 int main(const int argc, const char **argv) 00139 { 00140 MYLOGVERB = LOG_INFO; // suppress debug messages 00141 00142 // Instantiate a ModelManager: 00143 ModelManager manager("Optimal Gains Combiner"); 00144 00145 OModelParam<std::string> saveTo(&OPT_SaveTo, &manager); 00146 00147 // Parse command-line: 00148 if (manager.parseCommandLine(argc, argv, 00149 "<stsd1.stsd> ... <stsdN.stsd> [--save-to=out.pmap]", 1, -1) == false) 00150 return(1); 00151 00152 // do post-command-line configs: 00153 std::vector<rutz::shared_ptr<ParamMap> > pmaps; 00154 for (uint i = 0; i < manager.numExtraArgs(); ++i) 00155 { 00156 LINFO("Loading: %s", manager.getExtraArg(i).c_str()); 00157 pmaps.push_back(ParamMap::loadPmapFile(manager.getExtraArg(i))); 00158 } 00159 00160 rutz::shared_ptr<ParamMap> outpmap = combineParamMaps(pmaps, 0); 00161 00162 // write output: 00163 if (saveTo.getVal().empty() == false) outpmap->format(saveTo.getVal()); 00164 else outpmap->format(std::cout); 00165 00166 // all done! 00167 return 0; 00168 } 00169 00170 // ###################################################################### 00171 /* So things look consistent in everyone's emacs... */ 00172 /* Local Variables: */ 00173 /* indent-tabs-mode: nil */ 00174 /* End: */