MotionOpticalFlowChannel.C

Go to the documentation of this file.
00001 /*!@file Channels/MotionOpticalFlowChannel.C */
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: Christian Siagian <siagian@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Channels/MotionOpticalFlowChannel.C $
00035 // $Id: $
00036 //
00037 
00038 #ifndef MOTION_OPTICALFLOW_CHANNEL_C_DEFINED
00039 #define MOTION_OPTICALFLOW_CHANNEL_C_DEFINED
00040 
00041 #include "Channels/MotionOpticalFlowChannel.H"
00042 
00043 #include "Channels/ChannelOpts.H"
00044 #include "Component/ModelOptionDef.H"
00045 
00046 #include "Image/ShapeOps.H"
00047 
00048 #include "rutz/trace.h"
00049 #include "Util/Timer.H"
00050 
00051 #define OF_SELF_MOTION_WEIGHT     1.0F
00052 #define OF_OBJECT_MOTION_WEIGHT   1.0F
00053 #define OF_MAX_FIRING_RATE        100.0F
00054 
00055 // Used by: MotionOpticalFlowChannel
00056 const ModelOptionDef OPT_OpticalFlowType =
00057   { MODOPT_ARG(OpticalFlowType), "OpticalFlowType", &MOC_CHANNEL, OPTEXP_CORE,
00058     "Type of computation used to compute the optical flow",
00059     "optical-flow-type", '\0', "<LucasKanade|HornSchunck>",
00060     "LucasKanade" };
00061 
00062 // ######################################################################
00063 // MotionOpticalFlowChannel member definitions:
00064 // ######################################################################
00065 
00066 // ######################################################################
00067 MotionOpticalFlowChannel::MotionOpticalFlowChannel(OptionManager& mgr) :
00068   ComplexChannel(mgr, 
00069                  "MotionOpticalFlow", 
00070                  "motionOpticalFlow", 
00071                  MOTIONOPTICALFLOW),
00072   itsOpticalFlowType(&OPT_OpticalFlowType, this), // see Channels/ChannelOpts.{H,C}
00073   itsNumDirs(&OPT_NumOpticalFlowDirections, this), // see Channels/ChannelOpts.{H,C}
00074   itsFoeDetector(new FoeDetector(mgr))
00075 {
00076 GVX_TRACE(__PRETTY_FUNCTION__);
00077 
00078   // let's create our subchannels (may be reconfigured later if our
00079   // number of directions changes):
00080   buildSubChans();
00081 
00082   itsWin.reset();
00083 }
00084 
00085 // ######################################################################
00086 MotionOpticalFlowChannel::~MotionOpticalFlowChannel()
00087 {
00088 GVX_TRACE(__PRETTY_FUNCTION__);
00089 }
00090 
00091 // ######################################################################
00092 DirectionOpticalFlowChannel& MotionOpticalFlowChannel::dirChan
00093 (const uint idx) const
00094 {
00095 GVX_TRACE(__PRETTY_FUNCTION__);
00096   return *(dynCast<DirectionOpticalFlowChannel>(subChan(idx)));
00097 }
00098 
00099 // ######################################################################
00100 void MotionOpticalFlowChannel::buildSubChans()
00101 {
00102 GVX_TRACE(__PRETTY_FUNCTION__);
00103   // kill any subchans we may have had...
00104   this->removeAllSubChans();
00105 
00106   // let's instantiate our subchannels now that we know how many we
00107   // want. They will inherit the current values (typically
00108   // post-command-line parsing) of all their options as they are
00109   // constructed:
00110   LINFO("Using %d directions spanning [0..360]deg", itsNumDirs.getVal());
00111 
00112   itsDirectionOpticalFlowChannels.clear();
00113 
00114   // go through the different directions
00115   for (uint i = 0; i < itsNumDirs.getVal(); i++)
00116     {
00117       nub::ref<DirectionOpticalFlowChannel> chan =
00118         makeSharedComp(new DirectionOpticalFlowChannel
00119                        (getManager(), i,
00120                         360.0 * double(i)/double(itsNumDirs.getVal()),
00121                         itsOpticalFlowType.getVal()));
00122       
00123       itsDirectionOpticalFlowChannels.push_back(chan);
00124       
00125       this->addSubChan(chan);      
00126       chan->exportOptions(MC_RECURSE);
00127     }
00128 }
00129 
00130 // ######################################################################
00131 void MotionOpticalFlowChannel::paramChanged(ModelParamBase* const param,
00132                                  const bool valueChanged,
00133                                  ParamClient::ChangeStatus* status)
00134 {
00135 GVX_TRACE(__PRETTY_FUNCTION__);
00136   ComplexChannel::paramChanged(param, valueChanged, status);
00137 
00138   // if the param is our number of orientations and it has become
00139   // different from our number of channels, let's reconfigure:
00140   if (param == &itsNumDirs &&
00141       numChans() != itsNumDirs.getVal())
00142     buildSubChans();
00143 }
00144 
00145 // ######################################################################
00146 void MotionOpticalFlowChannel::doInput(const InputFrame& inframe)
00147 {
00148 GVX_TRACE(__PRETTY_FUNCTION__);
00149   ASSERT(inframe.grayFloat().initialized());
00150 
00151   Image<byte> image(inframe.grayFloat());
00152   if(!itsCurrentImage.initialized())
00153     {
00154       itsCurrentImage = image; return;
00155     }
00156   else
00157     itsPreviousImage = itsCurrentImage;
00158   itsCurrentImage = image;
00159 
00160   // compute optical flow
00161   itsOpticalFlow =
00162     getLucasKanadeOpticFlow(itsPreviousImage, itsCurrentImage);  
00163 
00164   // compute directional optical flow
00165   // into several directions
00166   for (uint i = 0; i < numChans(); i++)
00167     {
00168       itsDirectionOpticalFlowChannels[i]
00169         ->setLucasKanadeOpticalFlow(itsOpticalFlow);
00170       subChan(i)->input(inframe);
00171 
00172       LINFO("Motion Optical flow pyramid (%d/%d) ok.", i+1, numChans());
00173     }
00174 
00175   // compute motion conspicuity map
00176   computeConspicuityMap();
00177 }
00178 
00179 // ######################################################################
00180 void MotionOpticalFlowChannel::computeConspicuityMap()
00181 {
00182 GVX_TRACE(__PRETTY_FUNCTION__);
00183 
00184   uint cmWidth  = subChan(0)->getMapDims().w();
00185   uint cmHeight = subChan(0)->getMapDims().h();
00186   Image<float> result(cmWidth, cmHeight, ZEROS);
00187 
00188   Dims imDims = itsOpticalFlow->getImageDims();
00189   uint mtWidth  = imDims.w()/4; 
00190   uint mtHeight = imDims.h()/4;
00191 
00192   for (uint i = 0; i < itsNumDirs.getVal(); i++)
00193     {
00194       Image<float> tmap = itsDirectionOpticalFlowChannels[i]
00195         ->getDirectionalOpticalFlow();
00196 
00197       Image<float> submap = downSizeClean(tmap, Dims(cmWidth, cmHeight));
00198 
00199       Image<float> psubmap;
00200       if (itsUseOlderVersion.getVal())
00201         {
00202           LDEBUG("%s[%d]: applying %s(%f .. %f)", 
00203                  tagName().c_str(), i, 
00204                  maxNormTypeName(itsNormType.getVal()), MAXNORMMIN, MAXNORMMAX);
00205           psubmap = maxNormalize(submap, MAXNORMMIN, MAXNORMMAX,
00206                                  itsNormType.getVal());
00207         }
00208       else
00209         {
00210           LDEBUG("%s[%d]: applying %s(0.0 .. 0.0)", tagName().c_str(), i, 
00211                  maxNormTypeName(itsNormType.getVal()));
00212           psubmap = maxNormalize(submap, 0.0f, 0.0f, itsNormType.getVal());
00213         }
00214 
00215       result += psubmap;
00216      }
00217   Image<float> tsubmap = maxNormalize(result, MAXNORMMIN, MAXNORMMAX,
00218                                       itsNormType.getVal());
00219   result = tsubmap * numChans();
00220   Image<float> tres = result;
00221   result = rescale(tres, Dims(mtWidth, mtHeight));
00222 
00223   // May add a map that comes from higher level Motion areas
00224   //  : MST: FOE, planar motion  
00225   //  : STS: Biological motion  
00226 
00227   // NOTE:  FOE_METHOD_TEMPLATE and AVERAGE 
00228   //        is still fooled by Planar movement!!! 
00229   Image<float> foeMap = 
00230     itsFoeDetector->getFoeMap
00231     (itsOpticalFlow, FOE_METHOD_AVERAGE, false);  //FOE_METHOD_TEMPLATE
00232 
00233 
00234   // LINFO("ORIGINAL MAP");
00235   // if(itsWin.is_invalid())
00236   //   itsWin.reset(new XWinManaged(Dims(mtWidth*4, mtHeight*4), 
00237   //                                10, 0, "MotSpch: conspicuity map"));
00238   // else itsWin->setDims(Dims(mtWidth*4, mtHeight*4));
00239   // itsWin->drawImage(zoomXY(foeMap,4),0,0); Raster::waitForKey();
00240 
00241   // float orgMax = mx;
00242   // float firingRate = 0.0;
00243   // if(orgMax > .5) 
00244   //   firingRate = MAX_FIRING_RATE;  
00245   // else if(orgMax >= .1 && orgMax <= .5)
00246   //   firingRate = (orgMax - .1)/.4 * MAX_FIRING_RATE;  
00247 
00248   // crazy normalizer
00249   float mn, mx; getMinMax(foeMap, mn,mx);
00250   //LINFO("org   MSTd : %f %f",mn,mx);
00251   inplaceNormalize(foeMap, 0.0F, 1.0F);
00252   foeMap = toPower(foeMap, 40.0F);
00253   foeMap *= mx;
00254 
00255   // weight the firing rate to the maximum possible firing rate
00256   foeMap *= (OF_SELF_MOTION_WEIGHT *  OF_MAX_FIRING_RATE * numChans());
00257 
00258   // getMinMax(result,mn,mx);
00259   // LINFO("FINAL MSTv : %f %f",mn,mx);
00260 
00261   // getMinMax(foeMap,mn,mx);
00262   // LINFO("FINAL MSTd : %f %f",mn,mx);
00263 
00264   // if(itsWin.is_invalid())
00265   //   itsWin.reset(new XWinManaged(Dims(mtWidth*4, mtHeight*4), 
00266   //                                10, 0, "MotSpch: conspicuity map"));
00267   // else itsWin->setDims(Dims(mtWidth*4, mtHeight*4));
00268 
00269   // itsWin->drawImage(zoomXY(result,4),0,0); Raster::waitForKey();
00270   // itsWin->drawImage(zoomXY(foeMap,4),0,0); Raster::waitForKey();
00271 
00272   result += foeMap;
00273 
00274   // itsWin->drawImage(zoomXY(result,4),0,0); Raster::waitForKey();
00275 
00276   // resize submap to fixed scale if necessary:
00277   getMinMax(result,mn,mx);
00278   if (mtWidth > cmWidth)
00279     result = downSize(result, Dims(cmWidth, cmHeight));
00280   else if (mtWidth < cmWidth)
00281     result = rescale(result, Dims(cmWidth, cmHeight));
00282   inplaceNormalize(result,0.0F,mx);
00283   LINFO("Final cmap mn: %f mx: %f", mn, mx);
00284 
00285   itsConspicuityMap = result;
00286 }
00287 
00288 // ######################################################################
00289 Image<float> MotionOpticalFlowChannel::getOutput()
00290 {
00291 GVX_TRACE(__PRETTY_FUNCTION__);
00292  return itsConspicuityMap;
00293 }
00294 
00295 // ######################################################################
00296 /* So things look consistent in everyone's emacs... */
00297 /* Local Variables: */
00298 /* indent-tabs-mode: nil */
00299 /* End: */
00300 
00301 #endif // MOTION_OPTICALFLOW_CHANNEL_C_DEFINED
Generated on Sun May 8 08:40:22 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3