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: */