contourNeuron.C

Go to the documentation of this file.
00001 /*!@file CINNIC/contourNeuron.C CINNIC classes */
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: T. Nathan Mundhenk <mundhenk@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/CINNIC/contourNeuron.C $
00035 // $Id: contourNeuron.C 12074 2009-11-24 07:51:51Z itti $
00036 //
00037 
00038 #include "CINNIC/contourNeuron.H"
00039 #include "Util/log.H"
00040 
00041 #include <cmath>
00042 #include <cstdlib>
00043 #include <cstdio>
00044 
00045 // ############################################################
00046 // ############################################################
00047 // ##### ---CINNIC---
00048 // ##### Contour Integration:
00049 // ##### T. Nathan Mundhenk nathan@mundhenk.com
00050 // ############################################################
00051 // ############################################################
00052 
00053 
00054 float AngleDropOff,AngleSupress,SupMult,OrthA,OrthB,OrthMult,valueCutOff;
00055 float coLinearCutOff;
00056 float NeuronExSize,NeuronSupSize,NeuronSupStart,NeuronOrthSize;
00057 float CoLinearDiff;
00058 //! How many angles are detected via gabor filter
00059 //float NeuralAngles[AnglesUsed]={0,45,90,135};
00060 float NeuralAngles[AnglesUsed]={CINNIC_ANGLES};
00061 float XCenter, YCenter, ExReach, SupReach,OrthReach;
00062 float linearFactor2e,linearFactor3e,linearFactor2s,linearFactor3s;
00063 float distanceSupFactor2,distanceSupFactor3,distanceExFactor2,distanceExFactor3;
00064 
00065 //This method will return the ratio of XMax to X constrained from 0 to 1
00066 
00067 template <class TC2>
00068 float ContourNeuronCreate<TC2>::FindRatio(TC2& XMax, TC2& X)
00069 {
00070   return ((XMax-X)/XMax);
00071 }
00072 
00073 //General Pythagorian for finding the length of a line
00074 
00075 template <class TC2>
00076 float ContourNeuronCreate<TC2>::FindDistance(TC2& PiX, TC2& PiY)
00077 {
00078   return (sqrt((PiX*PiX)+(PiY*PiY)));
00079 }
00080 
00081 //This method when called will find the center pixel in the neuron, i.e.
00082 // the neuron pixel itself
00083 
00084 template <class TC2>
00085 void ContourNeuronCreate<TC2>::FindCenter()
00086 {
00087   XCenter = XSize/2;
00088   YCenter = YSize/2;
00089 }
00090 
00091 template <class TC2>
00092 void ContourNeuronCreate<TC2>::FindReach()
00093 {
00094   ExReach = NeuronExSize/2;
00095   SupReach = NeuronSupSize/2;
00096   OrthReach = NeuronOrthSize/2;
00097 }
00098 
00099 //This method will find the angle to a pixel from the center neuron
00100 
00101 template <class TC2>
00102 float ContourNeuronCreate<TC2>::FindAngleToRad(TC2& X,TC2& Y)
00103 {
00104 
00105   //Formula is the inverse Tangent of X/Y for X and Y represent the distance from
00106   //The center. Angles are added on depending on the cartesian quadrant the
00107   //line is in
00108 
00109   hold = 0;
00110   if(Y > YCenter) //Quad I or IV
00111   {
00112     if(X > XCenter) //Quad I
00113     {
00114       hold = (atan(fabs(XCenter-X)/fabs(YCenter-Y)));
00115     }
00116     if(X < XCenter) //Quad IV
00117     {
00118       hold = (2*pi)-(atan(fabs(XCenter-X)/fabs(YCenter-Y)));
00119     }
00120     if(X == XCenter) //Vertical vector at 0 degrees
00121     {
00122       hold = 0;
00123     }
00124   }
00125 
00126   if(Y < YCenter) //Quad II or III
00127   {
00128     if(X > XCenter) //Quad II
00129     {
00130       hold = pi-(atan(fabs(XCenter-X)/fabs(YCenter-Y)));
00131     }
00132     if(X < XCenter) //Quad III
00133     {
00134       hold = pi+(atan(fabs(XCenter-X)/fabs(YCenter-Y)));
00135     }
00136     if(X == XCenter) //Vertical vector at 180 degrees
00137     {
00138       hold = pi;
00139     }
00140   }
00141 
00142   if(Y == YCenter) // Horozontal Vector
00143   {
00144     if(X > XCenter)
00145     {
00146       hold = pi/2;
00147     }
00148     if(X < XCenter)
00149     {
00150       hold = pi+(pi/2);
00151     }
00152   }
00153   return hold;
00154 }
00155 
00156 //Convert radians to degrees
00157 
00158 template <class TC2>
00159 float ContourNeuronCreate<TC2>::FindRadToDeg(TC2& r)
00160 {
00161   return ((180/pi) * r);
00162 }
00163 
00164 //find a linear function
00165 
00166 template <class TC2>
00167 float ContourNeuronCreate<TC2>::FindLinear(TC2& m, TC2& n,TC2& o,TC2& x, TC2& b)
00168 {
00169   return ((m*x)+(n*(pow(x,2)))+(o*(pow(x,3)))+b);
00170 }
00171 
00172 template <class TC2>
00173 float ContourNeuronCreate<TC2>::sigmoid(TC2& beta, TC2& v)
00174 {
00175   return (1/(1+pow(2.71828,(-2.0*(beta * v)))));
00176 }
00177 //This method will return the generic neuron once completed
00178 
00179 #if 0
00180 template <class TC2>
00181 PropHold ContourNeuronCreate<TC2>::GetCompleteNeuron()
00182 {
00183   /* NOTE: g++4.4 warns
00184      src/CINNIC/contourNeuron.C: In member function ‘PropHold ContourNeuronCreate<TC2>::GetCompleteNeuron() [with TC2 = float]’:
00185      src/CINNIC/contourNeuron.C:187: warning: array subscript is above array bounds
00186   */
00187 
00188   return FourDNeuralMap[AnglesUsed][AnglesUsed][XSize][YSize];
00189 }
00190 #endif
00191 
00192 //This method will create the contour neuron
00193 
00194 template <class TC2>
00195 void ContourNeuronCreate<TC2>::CreateNeuron(readConfig &config)
00196 {
00197   one = 1;
00198   AngleDropOff = config.getItemValueF("AngleDropOff");
00199   AngleSupress = config.getItemValueF("AngleSupress");
00200   SupMult = config.getItemValueF("SupMult");
00201   OrthMult = config.getItemValueF("OrthMult");
00202   OrthA = config.getItemValueF("AngleOrthRangeA");
00203   OrthB = config.getItemValueF("AngleOrthRangeB");
00204   NeuronExSize = config.getItemValueF("NeuronExSize");
00205   NeuronSupSize = config.getItemValueF("NeuronSupSize");
00206   NeuronSupStart = config.getItemValueF("NeuronSupStart");
00207   NeuronOrthSize = config.getItemValueF("NeuronOrthSize");
00208   valueCutOff = config.getItemValueF("valueCutOff");
00209   CoLinearDiff = config.getItemValueF("CoLinearDiff");
00210   coLinearCutOff =  config.getItemValueF("coLinearCutOff");
00211   linearFactor2e = config.getItemValueF("linearFactor2e");
00212   linearFactor3e =  config.getItemValueF("linearFactor3e");
00213   linearFactor2s = config.getItemValueF("linearFactor2s");
00214   linearFactor3s =  config.getItemValueF("linearFactor3s");
00215   distanceSupFactor2 = config.getItemValueF("distanceSupFactor2");
00216   distanceSupFactor3 = config.getItemValueF("distanceSupFactor3");
00217   distanceExFactor2 = config.getItemValueF("distanceExFactor2");
00218   distanceExFactor3 = config.getItemValueF("distanceExFactor3");
00219 
00220   factor = -1/(1-FindRatio(foo = AngleCenter,bar = AngleDropOff));
00221   factor2 = -1/(1-FindRatio(foo = AngleCenter,bar = AngleSupress));
00222   OFactorA = -1/(1-FindRatio(foo = AngleCenter, bar = OrthA));
00223   OFactorB = -1/(1-FindRatio(foo = AngleCenter, bar = OrthB));
00224   FindCenter();
00225   FloatAngleCenter = AngleCenter;
00226   FindReach();
00227   //LINFO("%f %d %d %f %f factor", factor,AngleCenter,AngleDropOff,foo,bar);
00228   //comes out to -1/.3 here
00229   //iterate through each element in the neuron matrix and set that elements value
00230   LINFO("Starting neuron generation");
00231   for (int i = 0; i < AnglesUsed; i++)
00232   {
00233     printf(".");
00234     for (int j = 0; j < AnglesUsed; j++)
00235     {
00236       for (int k = 0; k <= XSize; k++)
00237       {
00238         for (int l = 0; l <= YSize; l++)
00239         {
00240           if((k == (int)XCenter) && (l == (int)YCenter)) //center is always 0
00241           {
00242             FourDNeuralMap[i][j][k][l].zero = false;
00243             FourDNeuralMap[i][j][k][l].angABD = 0;
00244             FourDNeuralMap[i][j][k][l].angAB = 0;
00245             FourDNeuralMap[i][j][k][l].dis = 0;
00246           }
00247           else
00248           {
00249             ii = i;jj = j;kk = k;ll = l;
00250             //Find the distance to another neuron
00251             distanceX = fabs(XCenter-kk);
00252             distanceY = fabs(YCenter-ll);
00253             distance =  FindDistance(distanceX, distanceY); //input distance from
00254             //center of pixel
00255 
00256             // Find distance ratio from 1 to 0 to a pixel for
00257             // (a) Full template size
00258             // (b) Full excitation reach
00259             // (c) Full supression reach
00260             // take linear distance plus a 2nd and 3rd order term if needed
00261             float exreach =  FindRatio(ExReach, distance);
00262             float supreach = FindRatio(SupReach, distance);
00263             FourDNeuralMap[i][j][k][l].dis = FindRatio(XCenter, distance);
00264             FourDNeuralMap[i][j][k][l].Edis = exreach + (distanceExFactor2*pow(exreach,2))
00265               + (distanceExFactor3*pow(exreach,3));
00266             FourDNeuralMap[i][j][k][l].Sdis = supreach + (distanceSupFactor2*pow(supreach,2))
00267               + (distanceSupFactor3*pow(supreach,3));
00268             FourDNeuralMap[i][j][k][l].Odis = FindRatio(OrthReach, distance);
00269             if(FourDNeuralMap[i][j][k][l].dis < 0)
00270               {FourDNeuralMap[i][j][k][l].dis = 0;}
00271             if(FourDNeuralMap[i][j][k][l].Edis < 0)
00272               {FourDNeuralMap[i][j][k][l].Edis = 0;}
00273             if(FourDNeuralMap[i][j][k][l].Sdis < 0)
00274               {FourDNeuralMap[i][j][k][l].Sdis = 0;}
00275             if(FourDNeuralMap[i][j][k][l].Odis < 0)
00276               {FourDNeuralMap[i][j][k][l].Odis = 0;}
00277 
00278             //find to what degree another neuron "points" at this neuron
00279             Angle = FindRadToDeg(hold = FindAngleToRad(kk,ll));
00280 
00281             //find the angle to the
00282             //neuron in degrees
00283 
00284             //Find the angles complement i.e. find its alignement
00285             //with an angle < 180
00286             if(Angle >= 180)
00287             {
00288               AngleA = Angle - 180;
00289             }
00290             else
00291             {
00292               AngleA = Angle;
00293             }
00294 
00295             //Find the difference
00296             //between the angle pointing the the other
00297             //neuron and the alignment of this neuron
00298             AngleAlpha = fabs(AngleA - NeuralAngles[i]);
00299 
00300             //Find the difference
00301             //between the angle pointing the the other
00302             //neuron and the alignment of that neuron
00303             //This aligns the polarity of the neural map
00304             //This neuron will only pass energy onto another neuron of the same
00305             //polarity. Neurons on one side
00306             //of a specific polarity can only send energy while the other side
00307             //can only recieve
00308             AngleBeta = fabs(AngleA - NeuralAngles[j]);
00309 
00310             //These numbers are shifted by 1 to catch floating point precision
00311             //errors
00312             FourDNeuralMap[i][j][k][l].coLinear = false;
00313             if((Angle <= (NeuralAngles[i]+90+coLinearCutOff))
00314                && (Angle >= (NeuralAngles[i]+90-coLinearCutOff)))
00315             {
00316                FourDNeuralMap[i][j][k][l].coLinear = true;
00317             }
00318             if((Angle <= (NeuralAngles[i]-90.0F+coLinearCutOff))
00319                && (Angle >= (NeuralAngles[i]-90.0F-coLinearCutOff)))
00320             {
00321                FourDNeuralMap[i][j][k][l].coLinear = true;
00322             }
00323             if((Angle <= (NeuralAngles[i]+270.0F+coLinearCutOff))
00324                && (Angle >= (NeuralAngles[i]+270.0F-coLinearCutOff)))
00325             {
00326                FourDNeuralMap[i][j][k][l].coLinear = true;
00327             }
00328 
00329 
00330             //---polarization effect---
00331             //Forward polarity
00332             if((Angle <= (NeuralAngles[i]+1))
00333                || (Angle >= (NeuralAngles[i]+179)))
00334             {
00335               FourDNeuralMap[i][j][k][l].pol = true;
00336 
00337               //This neuron can send energy
00338               if(((NeuralAngles[i] <= 90) &&
00339                   ((Angle < NeuralAngles[i]+270)
00340                    && (Angle >= NeuralAngles[i]+180)))
00341                  || ((NeuralAngles[i] > 90) &&
00342                      ((Angle >= NeuralAngles[i]+180) ||
00343                       (Angle < NeuralAngles[i]-90))))
00344               {
00345                 FourDNeuralMap[i][j][k][l].sender = true;
00346               }
00347               // This neuron can only recieve
00348               else
00349               {
00350                 FourDNeuralMap[i][j][k][l].sender = false;
00351               }
00352             }
00353             //Reverse polarity
00354             else
00355             {
00356               FourDNeuralMap[i][j][k][l].pol = false;
00357               //This neuron can only recieve
00358               if((Angle > NeuralAngles[i]+90)
00359                  || (Angle >= (NeuralAngles[i]+270)))
00360 
00361               {
00362                 FourDNeuralMap[i][j][k][l].sender = false;
00363               }
00364               // This neuron can send energy
00365               else
00366               {
00367                 FourDNeuralMap[i][j][k][l].sender = true;
00368               }
00369             }
00370 
00371             //Find the semetric difference between angles AngleCenter is more then
00372             //likely 90 degrees
00373             AngleAlpha = AngleCenter - fabs(AngleAlpha - AngleCenter);
00374             AngleBeta = AngleCenter - fabs(AngleBeta - AngleCenter);
00375 
00376             phi = fabs(NeuralAngles[i]-NeuralAngles[j]);
00377             theta = fabs(90-AngleAlpha);
00378             OT = 90-theta;
00379             //find if orthogonal values need to be calculated and calculate their
00380             //value
00381             stop = false;
00382             FourDNeuralMap[i][j][k][l].orth = false;
00383 
00384             // find the roughly orthogonal oriented neurons ratios
00385             // this if statement is true for orthogonal pixels within
00386             // the set range
00387             if((OT < OrthA) && ((phi > (90-OrthB)) && (phi < (90+OrthB)))) // <<<BUG?
00388             {
00389               FourDNeuralMap[i][j][k][l].ang2 = FindRatio(OrthA,OT) * OrthMult;
00390               FourDNeuralMap[i][j][k][l].angABD =
00391                 FourDNeuralMap[i][j][k][l].ang2 *
00392                 FourDNeuralMap[i][j][k][l].Odis;
00393               stop = true;
00394               FourDNeuralMap[i][j][k][l].zero = true;
00395               FourDNeuralMap[i][j][k][l].orth = true;
00396             }
00397             else
00398             {
00399               FourDNeuralMap[i][j][k][l].ang2 =
00400                 FindRatio(FloatAngleCenter,AngleAlpha);
00401               FourDNeuralMap[i][j][k][l].ang3 =
00402                 1-FourDNeuralMap[i][j][k][l].ang2;
00403               // FIND LINEAR ANG2
00404               FourDNeuralMap[i][j][k][l].ang2 =
00405                 FindLinear(factor,linearFactor2e,linearFactor3e,
00406                            FourDNeuralMap[i][j][k][l].ang2,one);
00407             }
00408             //find the angle beta that represents the difference
00409             // Between the angle to the other neuron and the alignment of that neuron
00410             FourDNeuralMap[i][j][k][l].ang =
00411               FindRatio(FloatAngleCenter,AngleBeta);
00412             // Find the difference between the idea angle which points
00413             // at the neuron and where this neuron actually points
00414 
00415             // determine this matrix for not angle greater then 30 deg.
00416             FourDNeuralMap[i][j][k][l].zero = false;
00417 
00418             // set 0 or supression angles (e.g. set the value for supression angles)
00419             if(FourDNeuralMap[i][j][k][l].ang2 < 0)
00420             {
00421               // FIND LINEAR ANG2
00422               FourDNeuralMap[i][j][k][l].ang2 =\
00423                 -1*FindLinear(factor2,linearFactor2s,linearFactor3s,
00424                               FourDNeuralMap[i][j][k][l].ang3,one);
00425               if(FourDNeuralMap[i][j][k][l].ang2 > 0)
00426               {
00427                 FourDNeuralMap[i][j][k][l].ang2 = 0;
00428               }
00429             }
00430             // FIND LINEAR ANG
00431             FourDNeuralMap[i][j][k][l].ang =\
00432             FindLinear(factor,linearFactor2e,linearFactor3e,
00433                        FourDNeuralMap[i][j][k][l].ang,one);
00434 
00435             //set 0 or FIND supression angles (e.g. set the value for supression angles)
00436             //else FIND excitation angles (Edis -> excitation, Sdis -> supression)
00437             if(FourDNeuralMap[i][j][k][l].ang2 < 0)
00438             {
00439               float diff;
00440               diff = fabs(NeuralAngles[i]-NeuralAngles[j]);
00441               if((diff < CoLinearDiff) || (diff > (180 - CoLinearDiff))) //<<fixed
00442               {
00443                 //Set Alpha/Beta combo supression if no orthogonal exception?
00444                 if(diff > (180 - CoLinearDiff)) // << This fixed the 0/165 bug
00445                 {
00446                   diff = 180 - diff;
00447                 }
00448                 FourDNeuralMap[i][j][k][l].angAB =
00449                   FourDNeuralMap[i][j][k][l].ang2 *
00450                   FindRatio(CoLinearDiff,diff);
00451 
00452                 // Find supression for angABD
00453                 if((FourDNeuralMap[i][j][k][l].Sdis > 0)
00454                    && (distance >= NeuronSupStart))
00455                 {
00456                   FourDNeuralMap[i][j][k][l].angABD = SupMult*
00457                     (((-1*FourDNeuralMap[i][j][k][l].Sdis)+
00458                       FourDNeuralMap[i][j][k][l].angAB)/2);
00459                 FourDNeuralMap[i][j][k][l].zero = true;
00460                 }
00461               }
00462             }
00463             //eliminate very small amplifications then derive angABD (OR set excitation angles here)
00464             else
00465             {
00466               if((FourDNeuralMap[i][j][k][l].ang > valueCutOff)
00467                  && (stop == false))
00468               {
00469                 //Set alpha/beta combo for excitation
00470                 FourDNeuralMap[i][j][k][l].angAB = \
00471                  (FourDNeuralMap[i][j][k][l].ang2*
00472                   FourDNeuralMap[i][j][k][l].ang);
00473 
00474                 if((FourDNeuralMap[i][j][k][l].angAB > valueCutOff) && \
00475                    (FourDNeuralMap[i][j][k][l].Edis > valueCutOff))
00476                 {
00477                   FourDNeuralMap[i][j][k][l].angABD = \
00478                    ((FourDNeuralMap[i][j][k][l].angAB
00479                      +FourDNeuralMap[i][j][k][l].Edis)/2);
00480                   if(FourDNeuralMap[i][j][k][l].angABD > valueCutOff)
00481                   {
00482                     //ignore small multipliers
00483                     FourDNeuralMap[i][j][k][l].zero = true;
00484                   }
00485                 }
00486               }
00487             }
00488           }
00489         }
00490       }
00491     }
00492   }
00493   printf("\n");
00494 }
00495 
00496 template class ContourNeuronCreate<float>;
00497 
00498 // ######################################################################
00499 /* So things look consistent in everyone's emacs... */
00500 /* Local Variables: */
00501 /* indent-tabs-mode: nil */
00502 /* End: */
Generated on Sun May 8 08:04:42 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3