DirectionOpticalFlowChannel.C

Go to the documentation of this file.
00001 /*!@file Channels/DirectionOpticalFlowChannel.C */
00002 // //////////////////////////////////////////////////////////////////// //
00003 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00004 // by the University of Southern California (USC) and the iLab at USC.  //
00005 // See http://iLab.usc.edu for information about this project.          //
00006 // //////////////////////////////////////////////////////////////////// //
00007 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00008 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00009 // in Visual Environments, and Applications'' by Christof Koch and      //
00010 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00011 // pending; application number 09/912,225 filed July 23, 2001; see      //
00012 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00013 // //////////////////////////////////////////////////////////////////// //
00014 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00015 //                                                                      //
00016 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00017 // redistribute it and/or modify it under the terms of the GNU General  //
00018 // Public License as published by the Free Software Foundation; either  //
00019 // version 2 of the License, or (at your option) any later version.     //
00020 //                                                                      //
00021 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00022 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00023 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00024 // PURPOSE.  See the GNU General Public License for more details.       //
00025 //                                                                      //
00026 // You should have received a copy of the GNU General Public License    //
00027 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00028 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00029 // Boston, MA 02111-1307 USA.                                           //
00030 // //////////////////////////////////////////////////////////////////// //
00031 //
00032 // Primary maintainer for this file:
00033 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Channels/DirectionOpticalFlowChannel.C $
00034 // $Id:$
00035 //
00036 
00037 #ifndef DIRECTION_OPTICALFLOW_CHANNEL_C_DEFINED
00038 #define DIRECTION_OPTICALFLOW_CHANNEL_C_DEFINED
00039 
00040 #include "Channels/DirectionOpticalFlowChannel.H"
00041 
00042 #include "rutz/trace.h"
00043 #include "Image/Image.H"
00044 #include "Raster/Raster.H"
00045 
00046 #define OF_WINDOW_SIZE   4
00047 #define OF_VALUE_RADIUS  1
00048 
00049 // ######################################################################
00050 // DirectionOpticalFlowChannel member definitions:
00051 // ######################################################################
00052 
00053 // ######################################################################
00054 DirectionOpticalFlowChannel::DirectionOpticalFlowChannel
00055 (OptionManager& mgr, 
00056  const uint dirIndex, const double direction, 
00057  const OpticalFlowType type):
00058   SingleChannel(mgr, "", "", MOTIONSPATIOTEMPORAL,
00059                 rutz::make_shared(new GaussianPyrBuilder<float>(1))), // no actual pyrbuilder
00060   itsDirIndex("DirectionChannelDirectionIndex", this, dirIndex),
00061   itsDirection("DirectionChannelDirection", this, direction),
00062   itsOpticalFlowType(type)
00063 {
00064 GVX_TRACE(__PRETTY_FUNCTION__);
00065 
00066   setDescriptiveName(sformat("DirectionSpeed(%d)", int(direction)));
00067   setTagName(sformat("dir_%d", dirIndex));
00068 }
00069 
00070 // ######################################################################
00071 void DirectionOpticalFlowChannel::start1()
00072 {
00073 GVX_TRACE(__PRETTY_FUNCTION__);
00074  itsLevelSpec.setVal(LevelSpec(0,0,0,0,4) );  // only 1 level
00075  SingleChannel::start1();
00076 }
00077 
00078 // ######################################################################
00079 void DirectionOpticalFlowChannel::start2()
00080 {
00081 GVX_TRACE(__PRETTY_FUNCTION__);
00082 
00083 }
00084 
00085 // ######################################################################
00086 DirectionOpticalFlowChannel::~DirectionOpticalFlowChannel()
00087 {
00088 GVX_TRACE(__PRETTY_FUNCTION__);
00089 }
00090 
00091 // ######################################################################
00092 bool DirectionOpticalFlowChannel::outputAvailable() const
00093 { 
00094   return itsDirectionalOpticalFlow.initialized();
00095 }
00096 
00097 // ######################################################################
00098   //! different ways to input different optical flow algorithms
00099 void DirectionOpticalFlowChannel::setLucasKanadeOpticalFlow
00100 (rutz::shared_ptr<OpticalFlow> flow)
00101 {
00102   ASSERT(itsOpticalFlowType == LucasKanade);
00103   itsOpticalFlow = flow;
00104 }
00105 
00106 // ######################################################################
00107 void DirectionOpticalFlowChannel::doInput(const InputFrame& inframe)
00108 {
00109 GVX_TRACE(__PRETTY_FUNCTION__);
00110 
00111   if (!this->started())
00112     CLFATAL("must be start()-ed before using receiving any input");
00113 
00114   // so that the visual cortex think we can produce a conspicuity map
00115   // FIXXX: really stupid hack
00116   SingleChannel::doInput(inframe); // will store the new pyramid
00117 
00118   // check if the optical flow input is already provided
00119   switch(itsOpticalFlowType)
00120     {
00121     case LucasKanade:
00122       if(itsOpticalFlow.is_invalid()) 
00123         LFATAL("need to provide optical flow. "
00124                "Use setLucasKanadeOpticalFlow(flow)");
00125       computeDirectionalOpticalFlow();
00126       break;
00127     case HornSchunck:
00128       break;
00129     default: LERROR("Unknown optical flow mode");
00130     }
00131 }
00132 
00133 // ######################################################################
00134 void DirectionOpticalFlowChannel::computeDirectionalOpticalFlow()
00135 {
00136   Dims d = itsOpticalFlow->getImageDims();
00137   itsDirectionalOpticalFlow = 
00138     Image<float>(d.w()/ OF_WINDOW_SIZE, d.h()/ OF_WINDOW_SIZE, ZEROS);
00139 
00140   // go through each flowVector using std::vector
00141   // FIXXX: for now. We know that Lucas Kanade produces sparse vectors. 
00142  
00143   std::vector<rutz::shared_ptr<FlowVector> > flow =
00144     itsOpticalFlow->getFlowVectors();
00145 
00146   for(uint i = 0; i < flow.size(); i++)
00147     {
00148       Point2D<int> pt1((int)flow[i]->p1.i, (int)flow[i]->p1.j); 
00149       Point2D<int> pt2((int)flow[i]->p2.i, (int)flow[i]->p2.j); 
00150 
00151       float ang  = flow[i]->angle;
00152       //float mag  = flow[i]->mag;
00153       float fval = flow[i]->val;
00154  
00155       // get the response value of the
00156       float rv = getResponseValue(ang);            
00157       computeDirectionalOpticalFlow(pt1.i, pt1.j, rv*fval);
00158 
00159       //LINFO("[%3d %3d]: ang: %f mag: %f fval: %f ---> %f", 
00160       //      pt1.i, pt1.j, ang, mag, fval, rv*fval);
00161     }
00162 }
00163 
00164 // ######################################################################
00165 float DirectionOpticalFlowChannel::getResponseValue(float angle)
00166 {
00167   float pangle = itsDirection.getVal();
00168   
00169   //  map to to 0 - 360 deg
00170   float nangle = fmod(angle +360.0, 360.0);
00171 
00172   // find difference in direction
00173   float diff1 = fabs(nangle - pangle);
00174   float diff2 = 360.0 - diff1;
00175   float diff = diff1; if(diff1 > diff2) diff = diff2;
00176 
00177   // we are going to focus to between +/- 30 deg diff
00178   float val = 0.0;
00179   float stdang = 15.0;
00180 
00181   // difference between 0 and 15 degrees
00182   if(diff >= 0 && diff < stdang)
00183     val = (stdang - diff)/stdang *    0.2 + 0.8;
00184 
00185    // difference between 15 and 30 degrees
00186    else if(diff >= stdang && diff < 2*stdang)
00187      val = (2*stdang - diff)/stdang *  0.8 + 0.0;
00188 
00189   // difference farther than 30 degrees
00190   else
00191     val = 0.0;
00192 
00193    return val;
00194 }
00195 
00196 // ######################################################################
00197 void DirectionOpticalFlowChannel::computeDirectionalOpticalFlow
00198 (uint i, uint j, float val)
00199 {
00200   // scale down to the actual directional flow map
00201   uint ii = i/OF_WINDOW_SIZE;
00202   uint jj = j/OF_WINDOW_SIZE;
00203 
00204 
00205   //itsDirectionalOpticalFlow.setVal(ii, jj, val);
00206 
00207   uint ri = OF_VALUE_RADIUS;
00208   uint rj = OF_VALUE_RADIUS;
00209 
00210   uint width  = itsDirectionalOpticalFlow.getWidth();
00211   uint height = itsDirectionalOpticalFlow.getHeight();
00212   
00213   uint lm =  0;        if(ii > ri-1)        lm = ii - ri; 
00214   uint rm =  width-1;  if(ii < width-1-ri)  rm = ii + ri;
00215   uint tm =  0;        if(jj > rj-1)        tm = jj - rj; 
00216   uint bm =  height-1; if(jj < height-1-ri) bm = jj + rj;
00217 
00218   // set the values
00219   float max = double (ri*2);
00220   for(uint bi = lm; bi <= rm; bi++)
00221     {
00222       for(uint bj = tm; bj <= bm; bj++)
00223         {
00224           // FIX: pre-compute the weights later 
00225           float di = float(bi) - float(ii);
00226           float dj = float(bj) - float(jj);
00227           float w = 1.0 - (sqrt(di*di + dj*dj))/max;
00228           float ov = itsDirectionalOpticalFlow.getVal(bi, bj);
00229           itsDirectionalOpticalFlow.setVal(bi, bj, ov+w*val);
00230           //LINFO("%d %d: %f", bi, bj, w*val);
00231         }
00232     }
00233 }
00234 
00235 // ######################################################################
00236 Image<float> DirectionOpticalFlowChannel::getDirectionalOpticalFlow()
00237 {
00238   return itsDirectionalOpticalFlow;
00239 }
00240 
00241 // ######################################################################
00242 /* So things look consistent in everyone's emacs... */
00243 /* Local Variables: */
00244 /* indent-tabs-mode: nil */
00245 /* End: */
00246 
00247 #endif // DIRECTION_OPTICALFLOW_CHANNEL_C_DEFINED
Generated on Sun May 8 08:04:34 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3