DirectFeedChannel.C

Go to the documentation of this file.
00001 /*!@file Channels/DirectFeedChannel.C the source for DirectFeedChannel and
00002 MultiDirectFeedChannel */
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2002   //
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: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Channels/DirectFeedChannel.C $
00035 // $Id: DirectFeedChannel.C 10746 2009-02-03 07:09:00Z itti $
00036 //
00037 
00038 #include "Channels/DirectFeedChannel.H"
00039 
00040 #include "Channels/ChannelOpts.H"
00041 #include "Component/OptionManager.H"
00042 #include "Image/ShapeOps.H"
00043 #include "Util/Assert.H"
00044 #include "Util/MathFunctions.H"
00045 #include "Util/StringConversions.H"
00046 #include "Util/sformat.H"
00047 
00048 // ######################################################################
00049 DirectFeedChannel::DirectFeedChannel(OptionManager& mgr, int id)
00050   : ChannelBase(mgr, "DirectFeed", "DirectFeed", DIRECTFEED),
00051     itsMapLevel(&OPT_MapLevel, this),
00052     itsNormType(&OPT_MaxNormType, this),
00053     itsUseOlderVersion(&OPT_UseOlderVersion, this), // see Channels/ChannelOpts.{H,C}
00054     itsOutputRangeMin(&OPT_ChannelOutputRangeMin, this),
00055     itsOutputRangeMax(&OPT_ChannelOutputRangeMax, this)
00056 {
00057   if (id >= 0)
00058     {
00059       std::string name("DirectFeed_No_");
00060       name += toStr(id);
00061       setTagName(name);
00062       setDescriptiveName(name);
00063     }
00064 }
00065 
00066 // ######################################################################
00067 DirectFeedChannel::~DirectFeedChannel()
00068 {}
00069 
00070 // ######################################################################
00071 void DirectFeedChannel::start1()
00072 {
00073   // in the new version, leave our output range open rather than
00074   // forcing it to a given range of values:
00075   if (itsUseOlderVersion.getVal() == false)
00076     {
00077       itsOutputRangeMin.setVal(0.0f);
00078       itsOutputRangeMax.setVal(0.0f);
00079     }
00080 
00081   // in the older version, we used to set the map range as we would
00082   // also apply spatial competition for salience to the output map,
00083   // only if using the MAXNORM type of competition, and otherwise we
00084   // would not touch the range:
00085   if (itsUseOlderVersion.getVal() && itsNormType.getVal() != VCXNORM_MAXNORM)
00086     {
00087       itsOutputRangeMin.setVal(0.0f);
00088       itsOutputRangeMax.setVal(0.0f);
00089     }
00090 }
00091 
00092 // ######################################################################
00093 void DirectFeedChannel::reset1()
00094 {
00095   itsMapDims = Dims();
00096   itsPyr.reset();
00097   itsInputTime = SimTime::ZERO();
00098   itsPyrTime = SimTime::SECS(-1.0);
00099   itsCoeff.clear();
00100   itsOutputCache.freeMem();
00101 
00102   ChannelBase::reset1();
00103 }
00104 
00105 // ######################################################################
00106 void DirectFeedChannel::readFrom(const ParamMap& pmap)
00107 {
00108   //FIXME
00109   ChannelBase::readFrom(pmap);
00110 }
00111 
00112 // ######################################################################
00113 void DirectFeedChannel::writeTo(ParamMap& pmap) const
00114 {
00115   //FIXME
00116   ChannelBase::writeTo(pmap);
00117 }
00118 
00119 // ######################################################################
00120 void DirectFeedChannel::clampCoeffs(const double cmin, const double cmax)
00121 {
00122   killCaches();
00123   for (uint i = 0; i < itsCoeff.size(); ++i)
00124     itsCoeff[i] = clampValue(itsCoeff[i], cmin, cmax);
00125 }
00126 
00127 // ######################################################################
00128 double DirectFeedChannel::absSumCoeffs() const
00129 {
00130   double sum = 0.0;
00131   for (uint i = 0; i < itsCoeff.size(); ++i)
00132     sum += std::abs(itsCoeff[i]);
00133   return sum;
00134 }
00135 
00136 // ######################################################################
00137 void DirectFeedChannel::normalizeCoeffs(const double div)
00138 {
00139   killCaches();
00140   for (uint i = 0; i < itsCoeff.size(); ++i)
00141     itsCoeff[i] /=div;
00142 }
00143 
00144 // ######################################################################
00145 void DirectFeedChannel::setCoeff(const uint idx, const double val)
00146 {
00147   if (itsPyr.isEmpty()) initializeCoeffs(idx+1,1.0);
00148   else ASSERT(idx < numSubmaps());
00149 
00150   killCaches();
00151   itsCoeff[idx] = val;
00152 }
00153 
00154 // ######################################################################
00155 double DirectFeedChannel::getCoeff(const uint idx) const
00156 {
00157   ASSERT(idx < numSubmaps());
00158   return itsCoeff[idx];
00159 }
00160 
00161 // ######################################################################
00162 void DirectFeedChannel::initializeCoeffs(const uint numCoeffs,
00163                                          const double val)
00164 {
00165   itsCoeff.resize(numCoeffs,val);
00166 }
00167 
00168 // ######################################################################
00169 void DirectFeedChannel::inputPyramid(const ImageSet<float>& pyramid,
00170                                      const SimTime& t)
00171 {
00172   if (itsCoeff.empty()) initializeCoeffs(pyramid.size());
00173   else ASSERT(itsCoeff.size() == pyramid.size());
00174 
00175   itsPyr = pyramid;
00176   itsPyrTime = t;
00177   LDEBUG("itsPyrTime: %fms", itsPyrTime.msecs());
00178 }
00179 
00180 // ######################################################################
00181 void DirectFeedChannel::doInput(const InputFrame& inframe)
00182 {
00183   if (inframe.grayFloat().initialized()) LINFO("using bwimg");
00184   else if (inframe.colorFloat().initialized()) LINFO("using colimg");
00185   else LFATAL("Need to have either colimg or bwimg as input!");
00186 
00187   itsInputTime = inframe.time();
00188 
00189   LDEBUG("itsInputTime: %fms", itsInputTime.msecs());
00190 
00191   if (itsInputTime != itsPyrTime)
00192     LFATAL("I don't have any direct-feed input for time=%fms "
00193            "(last input was at time=%fms)",
00194            itsInputTime.msecs(), itsPyrTime.msecs());
00195 
00196   const float fac = pow(0.5f,float(itsMapLevel.getVal()));
00197   itsMapDims = Dims(int(this->getInputDims().w()*fac),
00198                     int(this->getInputDims().h()*fac));
00199   LDEBUG("itsMapDims = %s; itsInputDims = %s",toStr(itsMapDims).c_str(),
00200         toStr(this->getInputDims()).c_str());
00201 }
00202 
00203 // ######################################################################
00204 bool DirectFeedChannel::outputAvailable() const
00205 {
00206   LDEBUG("itsPyrTime: %fms; itsInputTime: %fms",
00207          itsPyrTime.msecs(), itsInputTime.msecs());
00208   return (itsInputTime == itsPyrTime);
00209 }
00210 
00211 // ######################################################################
00212 Dims DirectFeedChannel::getMapDims() const
00213 { return itsMapDims; }
00214 
00215 // ######################################################################
00216 uint DirectFeedChannel::numSubmaps() const
00217 { return itsPyr.size(); }
00218 
00219 // ######################################################################
00220 Image<float> DirectFeedChannel::getSubmap(const uint index) const
00221 {
00222   ASSERT(index < numSubmaps());
00223   return itsPyr[index];
00224 }
00225 
00226 // ######################################################################
00227 std::string DirectFeedChannel::getSubmapName(const uint index) const
00228 {
00229   ASSERT(index < numSubmaps());
00230   return sformat("%s lev: %d", descriptiveName().c_str(),index);
00231 }
00232 
00233 // ######################################################################
00234 void DirectFeedChannel::getFeatures(const Point2D<int>& locn,
00235                            std::vector<float>& mean) const
00236 {
00237   //FIXME
00238   LFATAL("Not implemented yet.");
00239 }
00240 
00241 // ######################################################################
00242 Image<float> DirectFeedChannel::getOutput()
00243 {
00244   ASSERT(itsInputTime == itsPyrTime);
00245   if (!itsOutputCache.initialized()) computeOutput();
00246   return itsOutputCache;
00247 }
00248 
00249 
00250 // ######################################################################
00251 void DirectFeedChannel::computeOutput()
00252 {
00253   ASSERT(itsInputTime == itsPyrTime);
00254   Image<float> output(getMapDims(),ZEROS);
00255 
00256   for (uint i = 0; i < itsPyr.size(); ++i)
00257     {
00258       Image<float> submap = rescale(itsPyr[i], getMapDims());
00259       applyMaxNorm(submap);
00260       output += (submap * itsCoeff[i]);
00261     }
00262   itsOutputCache = applyMaxNorm(output);
00263 }
00264 
00265 
00266 // ######################################################################
00267 Image<float> DirectFeedChannel::applyMaxNorm(Image<float>& map)
00268 {
00269   ASSERT(map.initialized());
00270   map =  maxNormalize(map, itsOutputRangeMin.getVal(),
00271                       itsOutputRangeMax.getVal(),
00272                       itsNormType.getVal());
00273   return map;
00274 }
00275 
00276 // ######################################################################
00277 void DirectFeedChannel::killCaches()
00278 {
00279   itsOutputCache.freeMem();
00280   itsPyrTime = SimTime::SECS(-1.0);
00281 }
00282 
00283 
00284 // ######################################################################
00285 // ##### MultiDirecFeedChannel
00286 // ######################################################################
00287 
00288 // ######################################################################
00289 MultiDirectFeedChannel::MultiDirectFeedChannel(OptionManager& mgr,
00290                                                uint num)
00291   : ComplexChannel(mgr,"MultiDirectFeed","MultiDirectFeed",MULTIDIRECTFEED)
00292 {
00293   setNumChans(num);
00294 }
00295 
00296 MultiDirectFeedChannel::~MultiDirectFeedChannel()
00297 {}
00298 
00299 // ######################################################################
00300 void MultiDirectFeedChannel::setNumChans(uint num)
00301 {
00302   if (num == 0) LFATAL("Need at least one subchannel.");
00303 
00304   // Same number that we already have? Nothing to do then
00305   if (num == numChans()) return;
00306 
00307   // Need to add additional channels?
00308   if (num > numChans())
00309     for (uint i = numChans(); i < num; ++i)
00310       addSubChan(makeSharedComp(new DirectFeedChannel(getManager(),i)));
00311 
00312   // Need to remove channels?
00313   else
00314     for (uint i = numChans()-1; i >= num; --i)
00315       removeSubComponent(i);
00316 }
00317 
00318 // ######################################################################
00319 void MultiDirectFeedChannel::inputPyramid(uint chanNum,
00320                                           const ImageSet<float>& pyramid,
00321                                           const SimTime& t)
00322 {
00323   ASSERT(chanNum < numChans());
00324   directFeed(chanNum).inputPyramid(pyramid,t);
00325 }
00326 
00327 // ######################################################################
00328 void MultiDirectFeedChannel::inputPyramidVector(const PyrVec& pvec,
00329                                                 const SimTime& t)
00330 {
00331   ASSERT (pvec.size() == numChans());
00332   for (uint i = 0; i < numChans(); ++i)
00333     inputPyramid(i,pvec[i],t);
00334 }
00335 
00336 // ######################################################################
00337 DirectFeedChannel& MultiDirectFeedChannel::directFeed(uint idx)
00338 {
00339   ASSERT(idx < numChans());
00340   return *(dynCast<DirectFeedChannel>(subChan(idx)));
00341 }
00342 
00343 
00344 // ######################################################################
00345 Image<float> MultiDirectFeedChannel::combineOutputs()
00346 {
00347   ASSERT(numChans() > 0);
00348 
00349   if (numChans() == 1) return directFeed(0).getOutput();
00350 
00351   Image<float> output(getMapDims(),ZEROS);
00352 
00353   for (uint i = 0; i < numChans(); ++i)
00354     output += directFeed(i).getOutput();
00355 
00356   return  maxNormalize(output, itsOutputRangeMin.getVal(),
00357                        itsOutputRangeMax.getVal(),
00358                        itsNormType.getVal());
00359 }
00360 
00361 
00362 // ######################################################################
00363 void MultiDirectFeedChannel::doInput(const InputFrame& inframe)
00364 {
00365   ASSERT(inframe.colorFloat().initialized()
00366          || inframe.grayFloat().initialized());
00367   for (uint i = 0; i < numChans(); ++i)
00368     directFeed(i).input(inframe);
00369 }
00370 
00371 
00372 // ######################################################################
00373 /* So things look consistent in everyone's emacs... */
00374 /* Local Variables: */
00375 /* indent-tabs-mode: nil */
00376 /* End: */
Generated on Sun May 8 08:40:21 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3