RemoveSurprise.C

Go to the documentation of this file.
00001 /*!@file Surprise/RemoveSurprise.C attempt to remove surprise from image  */
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/Surprise/RemoveSurprise.C $
00035 // $Id: RemoveSurprise.C 14376 2011-01-11 02:44:34Z pez $
00036 //
00037 
00038 #ifndef REMOVE_SURPRISE_C_DEFINED
00039 #define REMOVE_SURPRISE_C_DEFINED
00040 
00041 #include "Surprise/RemoveSurprise.H"
00042 #include <typeinfo>
00043 
00044 /*************************************************************************/
00045 
00046 template <class PIXTYPE, class BETATYPE, class FLOAT>
00047 RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RemoveSurprise(const ushort sizeX,
00048                                                        const ushort sizeY)
00049 {
00050   LINFO("Creating RemoveSurprise Object");
00051 
00052   itsINbias = 1.0F; itsDRbias = 1.0F; itsFLbias = 1.0F; itsGAbias = 1.0F;
00053   itsRGbias = 1.0F; itsBYbias = 1.0F;
00054 
00055   itsCObias = 1.0F;  itsMObias = 1.0F;  itsORbias = 1.0F;  itsINbias = 1.0F;
00056 
00057   RSinit(sizeX,sizeY);
00058   RSuseTrueKalman(false);
00059   RSuseMaxLevel(false);
00060 
00061   if((typeid(BETATYPE).name() != typeid(itsHyper4).name()) &&
00062      (typeid(BETATYPE).name() != typeid(itsHyper6).name()))
00063   {
00064     LFATAL("Run time type error. Type: %s is not supported",
00065            typeid(BETATYPE).name());
00066   }
00067 }
00068 
00069 /*************************************************************************/
00070 
00071 template <class PIXTYPE, class BETATYPE, class FLOAT>
00072 RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RemoveSurprise()
00073 {
00074   LINFO("Creating RemoveSurprise Object NOTE: Call init()");
00075 
00076   itsINbias = 1.0F; itsDRbias = 1.0F; itsFLbias = 1.0F; itsGAbias = 1.0F;
00077   itsRGbias = 1.0F; itsBYbias = 1.0F;
00078 
00079   itsCObias = 1.0F;  itsMObias = 1.0F;  itsORbias = 1.0F;  itsINbias = 1.0F;
00080   RSuseTrueKalman(false);
00081   if((typeid(BETATYPE).name() != typeid(itsHyper4).name()) &&
00082      (typeid(BETATYPE).name() != typeid(itsHyper6).name()))
00083   {
00084     LFATAL("Run time type error. Type: %s is not supported",
00085            typeid(BETATYPE).name());
00086   }
00087 }
00088 
00089 /*************************************************************************/
00090 
00091 template <class PIXTYPE, class BETATYPE, class FLOAT>
00092 RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::~RemoveSurprise()
00093 {}
00094 
00095 /*************************************************************************/
00096 
00097 template <class PIXTYPE, class BETATYPE, class FLOAT>
00098 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSuseTrueKalman(const bool useTK)
00099 {
00100   LINFO("Setting itsUseTrueKalman");
00101   itsUseTrueKalman = useTK;
00102 }
00103 
00104 /*************************************************************************/
00105 
00106 template <class PIXTYPE, class BETATYPE, class FLOAT>
00107 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSuseMaxLevel(const bool useML)
00108 {
00109   LINFO("Setting itsUseMaxLevel");
00110   itsUseMaxLevel = useML;
00111 }
00112 
00113 /*************************************************************************/
00114 
00115 template <class PIXTYPE, class BETATYPE, class FLOAT>
00116 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSsetConspicBias(const FLOAT CO,
00117                                                               const FLOAT MO,
00118                                                               const FLOAT OR,
00119                                                               const FLOAT IN)
00120 {
00121   LINFO("Setting new biases with 4 maps");
00122   if(typeid(BETATYPE).name() != typeid(itsHyper4).name())
00123   {
00124     LFATAL("Run time type error, expected %s got %s",
00125            typeid(itsHyper4).name(),typeid(BETATYPE).name());
00126   }
00127   itsCObias = CO; itsMObias = MO; itsORbias = OR; itsINbias = IN;
00128 }
00129 
00130 /*************************************************************************/
00131 
00132 template <class PIXTYPE, class BETATYPE, class FLOAT>
00133 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSsetConspicBias(const FLOAT IN,
00134                                                               const FLOAT DR,
00135                                                               const FLOAT FL,
00136                                                               const FLOAT GA,
00137                                                               const FLOAT RG,
00138                                                               const FLOAT BY)
00139 {
00140   LINFO("Setting new biases with 6 maps");
00141   if(typeid(BETATYPE).name() != typeid(itsHyper6).name())
00142   {
00143     LFATAL("Run time type error, expected %s got %s",
00144            typeid(itsHyper6).name(), typeid(BETATYPE).name());
00145   }
00146   itsINbias = IN; itsDRbias = DR; itsFLbias = FL; itsGAbias = GA;
00147   itsRGbias = RG; itsBYbias = BY;
00148 }
00149 
00150 /*************************************************************************/
00151 
00152 template <class PIXTYPE, class BETATYPE, class FLOAT>
00153 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSsetAxisBias(const FLOAT X,
00154                                                            const FLOAT Y,
00155                                                            const FLOAT Z)
00156 {
00157   itsXbias = X; itsYbias = Y; itsZbias = Z;
00158 }
00159 /*************************************************************************/
00160 
00161 template <class PIXTYPE, class BETATYPE, class FLOAT>
00162 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSsetH2SVBias(const FLOAT H1,
00163                                                            const FLOAT H2,
00164                                                            const FLOAT S,
00165                                                            const FLOAT V)
00166 {
00167   itsH1bias = H1; itsH2bias = H2; itsSbias = S; itsVbias = V;
00168 }
00169 
00170 /*************************************************************************/
00171 
00172 template <class PIXTYPE, class BETATYPE, class FLOAT>
00173 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSinit(const ushort sizeX,
00174                                                     const ushort sizeY)
00175 {
00176   LINFO("INIT");
00177   itsLambda              = 0.1;
00178   itsInitBuffer          = false;
00179   itsUseCorrMatrixSet    = false;
00180   itsUseBayesWeightImage = false;
00181   itsImageSizeX          = sizeX;
00182   itsImageSizeY          = sizeY;
00183   itsXbias = 1.0F; itsYbias = 1.0F; itsZbias = 1.0F;
00184   itsInImage.resize(sizeX,sizeY);
00185   itsOutImage.resize(sizeX,sizeY);
00186   itsFinalImage.resize(sizeX,sizeY);
00187 
00188   itsBetaImage.resize(sizeX,sizeY);
00189   BETATYPE blank(0.0F);
00190   PIXTYPE  blank2(0.0F);
00191   typename Image<BETATYPE>::iterator betaImageItr = itsBetaImage.beginw();
00192   Image<PIXTYPE> tempImage;
00193   tempImage.resize(sizeX,sizeY);
00194   typename Image<PIXTYPE>::iterator tempImageItr = tempImage.beginw();
00195   while(betaImageItr != itsBetaImage.endw())
00196   {
00197     *betaImageItr = blank;
00198     *tempImageItr = blank2;
00199     ++betaImageItr; ++tempImageItr;
00200   }
00201 
00202   // resize intermediate images, set equal to the blank beta image
00203 
00204   itsInterImage.resize(2,tempImage);
00205   itsInterImageNorm.resize(1,tempImage);
00206 
00207   if(typeid(BETATYPE).name() == typeid(itsHyper4).name())
00208   {
00209     itsInit.resize(8,false);
00210     itsInitMessage.resize(8,"");
00211     itsInitMessage[0] = "Input Raw Image at method RSinputRawImage";
00212     itsInitMessage[1] = "Input Sal Map at method RSinputSalMap";
00213     itsInitMessage[2] = "Input conspicuity map for color at method RSinputConspicCO";
00214     itsInitMessage[3] = "Input conspicuity map for motion at method RSinputConspicMO";
00215     itsInitMessage[4] = "Input conspicuity map for orientation at method RSinputConspicOR";
00216     itsInitMessage[5] = "Input conspicuity map for intensity at method RSinputConspicIN";
00217     itsInitMessage[6] = "Set up filters at RScreateSepFilters";
00218     itsInitMessage[7] = "Set up convolution bounds at RSfindConvolutionEndPoints";
00219   }
00220 }
00221 
00222 /*************************************************************************/
00223 
00224 template <class PIXTYPE, class BETATYPE, class FLOAT>
00225 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSsetLambda(const FLOAT lambda)
00226 {
00227   itsLambda = lambda;
00228 }
00229 // 1. create a guassian filtered frame of the current movie
00230 /*************************************************************************/
00231 
00232 template <class PIXTYPE, class BETATYPE, class FLOAT>
00233 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSsetDesatBias(const FLOAT desat)
00234 {
00235   itsDesatbias = desat;
00236 }
00237 
00238 // 2. merge the guassian filtered frame with the current frame giving more
00239 //    weight to filtered pixels if the surprise is higher.
00240 
00241 /*************************************************************************/
00242 
00243 template <class PIXTYPE, class BETATYPE, class FLOAT>
00244 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSinputRawImage(
00245                                      const Image<PixRGB<FLOAT> >& rawImage,
00246                                      const uint frame)
00247 {
00248   LINFO("INPUT RAW IMAGE");
00249   itsInit[0] = true;
00250   itsFrameNumber = frame;
00251   if(rawImage.getHeight() != itsImageSizeY)
00252   {
00253     LINFO("Input raw image is not the correct size");
00254     LFATAL("Raw %d != sizeY %d",rawImage.getHeight(),itsImageSizeY);
00255   }
00256   if(rawImage.getWidth() != itsImageSizeX)
00257   {
00258     LINFO("Input raw image is not the correct size");
00259     LFATAL("Raw %d != sizeX %d",rawImage.getWidth(),itsImageSizeX);
00260   }
00261 
00262   typename Image<PIXTYPE >::iterator inImageItr =
00263     itsInImage.beginw();
00264   typename Image<PixRGB<FLOAT> >::const_iterator rawImageItr =
00265     rawImage.begin();
00266 
00267 
00268   // convert the input image to H2SV2
00269   while(inImageItr != itsInImage.endw())
00270   {
00271     *inImageItr = PIXTYPE(*rawImageItr);
00272     ++inImageItr; ++rawImageItr;
00273   }
00274 
00275   // If we wish to use a more proper kalman filter then store the new image
00276   // else just buffer the raw images
00277   if((itsUseTrueKalman) && (itsInitBuffer))
00278   {
00279     itsFrameBuffer.push_front(itsOutImage);
00280   }
00281   else
00282   {
00283     itsFrameBuffer.push_front(itsInImage);
00284     itsInitBuffer = true;
00285   }
00286 
00287   //if we get to big, pop off the back image
00288   if(itsFrameBuffer.size() > itsKernelSizeZ)
00289   {
00290     itsFrameBuffer.pop_back();
00291   }
00292 }
00293 
00294 /*************************************************************************/
00295 
00296 template <class PIXTYPE, class BETATYPE, class FLOAT>
00297 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSinputSalMap(const Image<FLOAT>& salMap)
00298 {
00299   LINFO("INPUT Salmap IMAGE");
00300   itsInit[1] = true;
00301   if(itsInImage.getWidth() != salMap.getWidth())
00302   {
00303     LINFO("Saliency map is the wrong size or raw image not initalized");
00304     LFATAL("Sal Width %d != Raw Width %d",salMap.getWidth(),
00305            itsInImage.getWidth());
00306   }
00307   if(itsInImage.getHeight() != salMap.getHeight())
00308   {
00309     LINFO("Saliency map is the wrong size or raw image not initalized");
00310     LFATAL("Sal Height %d != Raw Height %d",salMap.getHeight(),
00311            itsInImage.getHeight());
00312   }
00313 
00314   // normalize from 0 to 1
00315   itsSalMap = salMap/255.0F;
00316 }
00317 
00318 /*************************************************************************/
00319 
00320 template <class PIXTYPE, class BETATYPE, class FLOAT>
00321 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSinputConspicCO(const Image<FLOAT>& conspicCO)
00322 {
00323   LINFO("INPUT CO IMAGE");
00324   itsInit[2] = true;
00325   if(itsInImage.getWidth() != conspicCO.getWidth())
00326   {
00327     LINFO("Saliency map is the wrong size or raw image not initalized");
00328     LFATAL("Conspic Width %d != Raw Width %d",conspicCO.getWidth(),
00329            itsInImage.getWidth());
00330   }
00331   if(itsInImage.getHeight() != conspicCO.getHeight())
00332   {
00333     LINFO("Saliency map is the wrong size or raw image not initalized");
00334     LFATAL("Conspic Height %d != Raw Height %d",conspicCO.getHeight(),
00335            itsInImage.getHeight());
00336   }
00337   // normalize from 0 to 1
00338   itsConspicCO = conspicCO/255.0F;
00339   itsConspicCO = itsConspicCO*itsCObias;
00340 }
00341 
00342 /*************************************************************************/
00343 
00344 template <class PIXTYPE, class BETATYPE, class FLOAT>
00345 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSinputConspicMO(const Image<FLOAT>& conspicMO)
00346 {
00347   LINFO("INPUT MO IMAGE");
00348   itsInit[3] = true;
00349   if(itsInImage.getWidth() != conspicMO.getWidth())
00350   {
00351     LINFO("Saliency map is the wrong size or raw image not initalized");
00352     LFATAL("Conspic Width %d != Raw Width %d",conspicMO.getWidth(),
00353            itsInImage.getWidth());
00354   }
00355   if(itsInImage.getHeight() != conspicMO.getHeight())
00356   {
00357     LINFO("Saliency map is the wrong size or raw image not initalized");
00358     LFATAL("Conspic Height %d != Raw Height %d",conspicMO.getHeight(),
00359            itsInImage.getHeight());
00360   }
00361   // normalize from 0 to 1
00362   itsConspicMO = conspicMO/255.0F;
00363   itsConspicMO = itsConspicMO*itsMObias;
00364 }
00365 
00366 /*************************************************************************/
00367 
00368 template <class PIXTYPE, class BETATYPE, class FLOAT>
00369 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSinputConspicOR(const Image<FLOAT>& conspicOR)
00370 {
00371   LINFO("INPUT OR IMAGE");
00372   itsInit[4] = true;
00373   if(itsInImage.getWidth() != conspicOR.getWidth())
00374   {
00375     LINFO("Saliency map is the wrong size or raw image not initalized");
00376     LFATAL("Conspic Width %d != Raw Width %d",conspicOR.getWidth(),
00377            itsInImage.getWidth());
00378   }
00379   if(itsInImage.getHeight() != conspicOR.getHeight())
00380   {
00381     LINFO("Saliency map is the wrong size or raw image not initalized");
00382     LFATAL("Conspic Height %d != Raw Height %d",conspicOR.getHeight(),
00383            itsInImage.getHeight());
00384   }
00385   // normalize from 0 to 1
00386   itsConspicOR = conspicOR/255.0F;
00387   itsConspicOR = itsConspicOR*itsORbias;
00388 }
00389 
00390 /*************************************************************************/
00391 
00392 template <class PIXTYPE, class BETATYPE, class FLOAT>
00393 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSinputConspicIN(const Image<FLOAT>& conspicIN)
00394 {
00395   LINFO("INPUT IN IMAGE");
00396   itsInit[5] = true;
00397   if(itsInImage.getWidth() != conspicIN.getWidth())
00398   {
00399     LINFO("Saliency map is the wrong size or raw image not initalized");
00400     LFATAL("Conspic Width %d != Raw Width %d",conspicIN.getWidth(),
00401            itsInImage.getWidth());
00402   }
00403   if(itsInImage.getHeight() != conspicIN.getHeight())
00404   {
00405     LINFO("Saliency map is the wrong size or raw image not initalized");
00406     LFATAL("Conspic Height %d != Raw Height %d",conspicIN.getHeight(),
00407            itsInImage.getHeight());
00408   }
00409   // normalize from 0 to 1
00410   //itsConspicIN = conspicIN/255.0F;
00411   itsConspicIN = conspicIN;
00412   itsConspicIN = itsConspicIN*itsINbias;
00413 }
00414 
00415 /*************************************************************************/
00416 
00417 template <class PIXTYPE, class BETATYPE, class FLOAT>
00418 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSinputConspicDR(const Image<FLOAT>& conspicDR)
00419 {
00420   LINFO("INPUT DR IMAGE");
00421 
00422   if(itsInImage.getWidth() != conspicDR.getWidth())
00423   {
00424     LINFO("Saliency map is the wrong size or raw image not initalized");
00425     LFATAL("Conspic Width %d != Raw Width %d",conspicDR.getWidth(),
00426            itsInImage.getWidth());
00427   }
00428   if(itsInImage.getHeight() != conspicDR.getHeight())
00429   {
00430     LINFO("Saliency map is the wrong size or raw image not initalized");
00431     LFATAL("Conspic Height %d != Raw Height %d",conspicDR.getHeight(),
00432            itsInImage.getHeight());
00433   }
00434   // normalize from 0 to 1
00435   //itsConspicDR = conspicDR/255.0F;
00436   itsConspicDR = conspicDR;
00437   itsConspicDR = itsConspicDR*itsDRbias;
00438 }
00439 
00440 /*************************************************************************/
00441 
00442 template <class PIXTYPE, class BETATYPE, class FLOAT>
00443 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSinputConspicFL(const Image<FLOAT>& conspicFL)
00444 {
00445   LINFO("INPUT FL IMAGE");
00446   itsInit[5] = true;
00447   if(itsInImage.getWidth() != conspicFL.getWidth())
00448   {
00449     LINFO("Saliency map is the wrong size or raw image not initalized");
00450     LFATAL("Conspic Width %d != Raw Width %d",conspicFL.getWidth(),
00451            itsInImage.getWidth());
00452   }
00453   if(itsInImage.getHeight() != conspicFL.getHeight())
00454   {
00455     LINFO("Saliency map is the wrong size or raw image not initalized");
00456     LFATAL("Conspic Height %d != Raw Height %d",conspicFL.getHeight(),
00457            itsInImage.getHeight());
00458   }
00459   // normalize from 0 to 1
00460   //itsConspicFL = conspicFL/255.0F;
00461   itsConspicFL = conspicFL;
00462   itsConspicFL = itsConspicFL*itsFLbias;
00463 }
00464 
00465 /*************************************************************************/
00466 
00467 template <class PIXTYPE, class BETATYPE, class FLOAT>
00468 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSinputConspicGA(const Image<FLOAT>& conspicGA)
00469 {
00470   LINFO("INPUT GA IMAGE");
00471   itsInit[5] = true;
00472   if(itsInImage.getWidth() != conspicGA.getWidth())
00473   {
00474     LINFO("Saliency map is the wrong size or raw image not initalized");
00475     LFATAL("Conspic Width %d != Raw Width %d",conspicGA.getWidth(),
00476            itsInImage.getWidth());
00477   }
00478   if(itsInImage.getHeight() != conspicGA.getHeight())
00479   {
00480     LINFO("Saliency map is the wrong size or raw image not initalized");
00481     LFATAL("Conspic Height %d != Raw Height %d",conspicGA.getHeight(),
00482            itsInImage.getHeight());
00483   }
00484   // normalize from 0 to 1
00485   //itsConspicGA = conspicGA/255.0F;
00486   itsConspicGA = conspicGA;
00487   itsConspicGA = itsConspicGA*itsGAbias;
00488 }
00489 
00490 /*************************************************************************/
00491 
00492 template <class PIXTYPE, class BETATYPE, class FLOAT>
00493 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSinputConspicRG(const Image<FLOAT>& conspicRG)
00494 {
00495   LINFO("INPUT RG IMAGE");
00496   itsInit[5] = true;
00497   if(itsInImage.getWidth() != conspicRG.getWidth())
00498   {
00499     LINFO("Saliency map is the wrong size or raw image not initalized");
00500     LFATAL("Conspic Width %d != Raw Width %d",conspicRG.getWidth(),
00501            itsInImage.getWidth());
00502   }
00503   if(itsInImage.getHeight() != conspicRG.getHeight())
00504   {
00505     LINFO("Saliency map is the wrong size or raw image not initalized");
00506     LFATAL("Conspic Height %d != Raw Height %d",conspicRG.getHeight(),
00507            itsInImage.getHeight());
00508   }
00509   // normalize from 0 to 1
00510   //itsConspicRG = conspicRG/255.0F;
00511   itsConspicRG = conspicRG;
00512   itsConspicRG = itsConspicRG*itsRGbias;
00513 }
00514 
00515 /*************************************************************************/
00516 
00517 template <class PIXTYPE, class BETATYPE, class FLOAT>
00518 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSinputConspicBY(const Image<FLOAT>& conspicBY)
00519 {
00520   LINFO("INPUT BY IMAGE");
00521   itsInit[5] = true;
00522   if(itsInImage.getWidth() != conspicBY.getWidth())
00523   {
00524     LINFO("Saliency map is the wrong size or raw image not initalized");
00525     LFATAL("Conspic Width %d != Raw Width %d",conspicBY.getWidth(),
00526            itsInImage.getWidth());
00527   }
00528   if(itsInImage.getHeight() != conspicBY.getHeight())
00529   {
00530     LINFO("Saliency map is the wrong size or raw image not initalized");
00531     LFATAL("Conspic Height %d != Raw Height %d",conspicBY.getHeight(),
00532            itsInImage.getHeight());
00533   }
00534   // normalize from 0 to 1
00535   //itsConspicBY = conspicBY/255.0F;
00536   itsConspicBY = conspicBY;
00537   itsConspicBY = itsConspicBY*itsBYbias;
00538 }
00539 
00540 /*************************************************************************/
00541 
00542 template <class PIXTYPE, class BETATYPE, class FLOAT>
00543 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSinputBayesWeightImage(
00544                                              const Image<FLOAT> &bayesImage)
00545 {
00546   LINFO("INPUT Bayes Weight Image");
00547   itsUseBayesWeightImage = true;
00548   itsBayesWeightImage = bayesImage;
00549 }
00550 
00551 /*************************************************************************/
00552 
00553 template <class PIXTYPE, class BETATYPE, class FLOAT>
00554 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSsetCorrWeightMat(
00555                           const std::vector<std::vector<FLOAT> > corAnti,
00556                           const std::vector<std::vector<FLOAT> > corBase)
00557 {
00558   LINFO("INPUT Corr Weight Matrix");
00559   itsUseCorrMatrixSet = true;
00560   itsAntiCorrelationMat = corAnti;
00561   itsBaseCorrelationMat = corBase;
00562 }
00563 
00564 /*************************************************************************/
00565 
00566 template <class PIXTYPE, class BETATYPE, class FLOAT>
00567 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RScreateSepFilters(const FLOAT spatSigma,
00568                                         const FLOAT tempSigma,
00569                                         const FLOAT stdDevSize)
00570 {
00571   LINFO("SETTING UP FILTERS");
00572   itsInit[6] = true;
00573   // create three components for a std seperable guassian kernel
00574   ushort rs1 = (ushort)ceil(spatSigma*stdDevSize*2.0F);
00575   ushort rs2 = (ushort)floor(spatSigma*stdDevSize*2.0F);
00576   // make sure the kernel is odd sized spatial
00577   if(rs1%2 == 0)
00578   {
00579     if(rs2%2 == 0)
00580     {
00581       itsKernelSizeX = rs2 + 1;
00582       itsKernelSizeY = rs2 + 1;
00583     }
00584     else
00585     {
00586       itsKernelSizeX = rs2;
00587       itsKernelSizeY = rs2;
00588     }
00589   }
00590   else
00591   {
00592     itsKernelSizeX = rs1;
00593     itsKernelSizeY = rs1;
00594   }
00595   itsKalmanKernelX.resize(itsKernelSizeX,0.0F);
00596   itsKalmanKernelY.resize(itsKernelSizeY,0.0F);
00597 
00598   // the temporal filter is one tailed (we can't smooth into the future)
00599   rs1 = (uint)ceil((tempSigma*stdDevSize));
00600   rs2 = (uint)floor((tempSigma*stdDevSize));
00601   // make sure the kernel is odd sized temporal
00602   if(rs1%2 == 0)
00603   {
00604     if(rs2%2 == 0)
00605     {
00606       itsKernelSizeZ = (ushort)rs2 + 1;
00607     }
00608     else
00609     {
00610       itsKernelSizeZ = (ushort)rs2;
00611     }
00612   }
00613   else
00614   {
00615     itsKernelSizeZ = (ushort)rs1;
00616   }
00617   itsKalmanKernelZ.resize(itsKernelSizeZ,0.0F);
00618 
00619   // find the kernel center
00620 
00621   const FLOAT centerX = floor((FLOAT)itsKernelSizeX/2.0F);
00622   const FLOAT centerY = floor((FLOAT)itsKernelSizeY/2.0F);
00623 
00624   FLOAT gmod = 1.0F/sqrt(2.0F*M_PI*pow(spatSigma,2));
00625 
00626   LINFO("Kernel X size %d",itsKernelSizeX);
00627   for(ushort i = 0; i < itsKernelSizeX; i++)
00628   {
00629     const FLOAT dist = pow((i - centerX),2);
00630     itsKalmanKernelX[i] =
00631       (gmod*exp((-1.0F*dist)/pow(2*spatSigma,2)));
00632     std::cerr << i << " : " << itsKalmanKernelX[i] << "\n";
00633   }
00634   LINFO("Kernel Y size %d",itsKernelSizeY);
00635   for(ushort i = 0; i < itsKernelSizeY; i++)
00636   {
00637     const FLOAT dist = pow((i - centerY),2);
00638     itsKalmanKernelY[i] =
00639       (gmod*exp((-1.0F*dist)/pow(2*spatSigma,2)));
00640     std::cerr << i << " : " << itsKalmanKernelY[i] << "\n";
00641   }
00642 
00643   gmod = 2.0F/sqrt(2.0F*M_PI*pow(spatSigma,2));
00644   LINFO("Kernel Z size %d",itsKernelSizeZ);
00645   for(ushort i = 0; i < itsKernelSizeZ; i++)
00646   {
00647     const FLOAT dist = pow((FLOAT)i,2.0F);
00648     itsKalmanKernelZ[i] =
00649       (gmod*exp((-1.0F*dist)/pow(2*spatSigma,2)));
00650     std::cerr << i << " : " << itsKalmanKernelZ[i] << "\n";
00651   }
00652 }
00653 
00654 /*************************************************************************/
00655 
00656 template <class PIXTYPE, class BETATYPE, class FLOAT>
00657 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSfindConvolutionEndPoints()
00658 {
00659   LINFO("SETTING UP CONVOLUTION END POINTS");
00660   itsInit[7] = true;
00661   itsXStart.resize(itsImageSizeX,itsImageSizeY);
00662   itsYStart.resize(itsImageSizeX,itsImageSizeY);
00663   itsZStart.resize(itsImageSizeX,itsImageSizeY);
00664   itsXStop.resize( itsImageSizeX,itsImageSizeY);
00665   itsYStop.resize( itsImageSizeX,itsImageSizeY);
00666   itsZStop.resize( itsImageSizeX,itsImageSizeY);
00667   itsKXStart.resize(itsImageSizeX,itsImageSizeY);
00668   itsKYStart.resize(itsImageSizeX,itsImageSizeY);
00669   itsKZStart.resize(itsImageSizeX,itsImageSizeY);
00670 
00671   Image<ushort>::iterator itsXStartItr  = itsXStart.beginw();
00672   Image<ushort>::iterator itsXStopItr   = itsXStop.beginw();
00673   Image<ushort>::iterator itsKXStartItr = itsKXStart.beginw();
00674   Image<ushort>::iterator itsYStartItr  = itsYStart.beginw();
00675   Image<ushort>::iterator itsYStopItr   = itsYStop.beginw();
00676   Image<ushort>::iterator itsKYStartItr = itsKYStart.beginw();
00677   Image<ushort>::iterator itsZStartItr  = itsZStart.beginw();
00678   Image<ushort>::iterator itsZStopItr   = itsZStop.beginw();
00679   Image<ushort>::iterator itsKZStartItr = itsKZStart.beginw();
00680 
00681   // foo
00682 
00683   for(ushort y = 0; y < itsImageSizeY; y++)
00684   {
00685     for(ushort x = 0; x < itsImageSizeX; x++)
00686     {
00687       const ushort yhalf = (ushort)floor(itsKernelSizeY/2);
00688       const ushort yend  = itsImageSizeY - yhalf;
00689       if(y < yhalf + 1)
00690       {
00691         *itsYStartItr  = 0;
00692         *itsKYStartItr = yhalf - y;
00693         *itsYStopItr   = y + yhalf;
00694       }
00695       else if(y > yend)
00696       {
00697         *itsYStartItr  = y - yhalf;
00698         *itsKYStartItr = 0;
00699         *itsYStopItr   = itsImageSizeY;
00700       }
00701       else
00702       {
00703         *itsYStartItr  = y - yhalf;
00704         *itsKYStartItr = 0;
00705         *itsYStopItr   = y + yhalf;
00706       }
00707 
00708       const ushort xhalf = (ushort)floor(itsKernelSizeX/2);
00709       const ushort xend  = itsImageSizeX - xhalf;
00710       if(x < xhalf + 1)
00711       {
00712         *itsXStartItr  = 0;
00713         *itsKXStartItr = xhalf - x;
00714         *itsXStopItr   = x + xhalf;
00715       }
00716       else if(x > xend)
00717       {
00718         *itsXStartItr  = x - xhalf;
00719         *itsKXStartItr = 0;
00720         *itsXStopItr   = itsImageSizeX;
00721       }
00722       else
00723       {
00724         *itsXStartItr  = x - xhalf;
00725         *itsKXStartItr = 0;
00726         *itsXStopItr   = x + xhalf;
00727       }
00728 
00729       // Z is not interesting, its starts at the current frame and
00730       // runs the size of the deque
00731       *itsKZStartItr = 0;
00732       *itsZStartItr  = 0;
00733       *itsZStopItr   = itsKernelSizeZ;
00734 
00735       //LINFO("X %d - %d K %d",*itsXStartItr,*itsXStopItr,*itsKXStartItr);
00736       //LINFO("Y %d - %d K %d",*itsYStartItr,*itsYStopItr,*itsKYStartItr);
00737       ++itsXStartItr; ++itsXStopItr; ++itsKXStartItr;
00738       ++itsYStartItr; ++itsYStopItr; ++itsKYStartItr;
00739       ++itsZStartItr; ++itsZStopItr; ++itsKZStartItr;
00740     }
00741   }
00742 }
00743 
00744 /*************************************************************************/
00745 
00746 template <class PIXTYPE, class BETATYPE, class FLOAT>
00747 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSprocessFrame()
00748 {
00749   LINFO("PROCESSING FRAME %d",itsFrameNumber);
00750   for(uint i = 0; i < itsInit.size(); i++)
00751   {
00752     if(!itsInit[i])
00753     {
00754       std::cerr << itsInitMessage[i] << "\n";
00755       LFATAL("One or more nessesary methods not run");
00756     }
00757   }
00758   if(typeid(BETATYPE).name() != typeid(itsHyper4).name())
00759   {
00760     LFATAL("Run time type mismatch. Expected %s got %s",
00761             typeid(itsHyper4).name(),typeid(BETATYPE).name());
00762   }
00763 
00764 
00765   Image<ushort>::iterator            itsXStartItr  = itsXStart.beginw();
00766   Image<ushort>::iterator            itsYStartItr  = itsYStart.beginw();
00767   Image<ushort>::iterator            itsXStopItr   = itsXStop.beginw();
00768   Image<ushort>::iterator            itsYStopItr   = itsYStop.beginw();
00769   Image<ushort>::iterator            itsKXStartItr = itsKXStart.beginw();
00770   Image<ushort>::iterator            itsKYStartItr = itsKYStart.beginw();
00771 
00772   typename Image<PIXTYPE >::iterator outImageItr;
00773   typename Image<PIXTYPE >::iterator inImageItr    = itsInImage.beginw();
00774   typename Image<BETATYPE>::iterator betaImageItr  = itsBetaImage.beginw();
00775 
00776   typename Image<FLOAT>::iterator    itsConsCOItr  = itsConspicCO.beginw();
00777   typename Image<FLOAT>::iterator    itsConsMOItr  = itsConspicMO.beginw();
00778   typename Image<FLOAT>::iterator    itsConsORItr  = itsConspicOR.beginw();
00779   typename Image<FLOAT>::iterator    itsConsINItr  = itsConspicIN.beginw();
00780 
00781   typename Image<PixRGB<FLOAT> >::iterator finalImageItr =
00782     itsFinalImage.beginw();
00783   typename std::deque<Image<PIXTYPE > >::iterator frameBufferItr;
00784 
00785   const typename std::deque<Image<PIXTYPE > >::iterator frameBufferEnd =
00786     itsFrameBuffer.end();
00787   const typename std::deque<Image<PIXTYPE > >::iterator frameBufferBegin =
00788     itsFrameBuffer.begin();
00789 
00790   const typename std::vector<FLOAT>::iterator kalmanKernelXbegin =
00791     itsKalmanKernelX.begin();
00792   const typename std::vector<FLOAT>::iterator kalmanKernelYbegin =
00793     itsKalmanKernelY.begin();
00794   const typename std::vector<FLOAT>::iterator kalmanKernelZbegin =
00795     itsKalmanKernelZ.begin();
00796 
00797   // copy itsInImage to itsOutImage so we can take the conspicuity weighted
00798   // average of the two
00799 
00800   // for the output image pixels
00801   for(outImageItr  = itsOutImage.beginw();
00802       outImageItr != itsOutImage.endw();
00803       ++outImageItr,   ++finalImageItr,  ++inImageItr, ++betaImageItr,
00804       ++itsYStartItr,  ++itsXStartItr,
00805       ++itsYStopItr,   ++itsXStopItr,
00806       ++itsKYStartItr, ++itsKXStartItr,
00807       ++itsConsCOItr,  ++itsConsMOItr,
00808       ++itsConsORItr,  ++itsConsINItr)
00809   {
00810 
00811     PIXTYPE normal(0.0F);
00812 
00813     // reset this pixel
00814     *outImageItr         = normal;
00815 
00816     const FLOAT CO       = *itsConsCOItr;
00817     const FLOAT MO       = *itsConsMOItr;
00818     const FLOAT OR       = *itsConsORItr;
00819     const FLOAT IN       = *itsConsINItr;
00820     const ushort XStart  = *itsXStartItr;
00821     const ushort YStart  = *itsYStartItr;
00822     const ushort KXStart = *itsKXStartItr;
00823     const ushort KYStart = *itsKYStartItr;
00824     const ushort XStop   = *itsXStopItr;
00825     const ushort YStop   = *itsYStopItr;
00826 
00827     // copy these variables into a more register friendly data structure
00828 
00829     FLOAT outH1 = inImageItr->H1();
00830     FLOAT outH2 = inImageItr->H2();
00831     FLOAT outS  = inImageItr->S();
00832     FLOAT outV  = inImageItr->V();
00833 
00834     // use normal to hold the final divisor for the convolution
00835 
00836     FLOAT npixS  = normal.p[2]; npixS++;
00837     FLOAT npixV  = normal.p[3]; npixV++;
00838     FLOAT npixH1 = normal.p[0]; npixH1++;
00839     FLOAT npixH2 = normal.p[1]; npixH2++;
00840 
00841     // smooth bias over iterations with a decay term
00842 
00843 
00844     const FLOAT betaCO =
00845       (betaImageItr->p[0] * itsLambda + CO)/(1 + 1 * itsLambda);
00846 
00847     betaImageItr->p[0] = betaCO;
00848 
00849     const FLOAT betaMO =
00850       (betaImageItr->p[1] * itsLambda + MO)/(1 + 1 * itsLambda);
00851     betaImageItr->p[1] = betaMO;
00852 
00853     const FLOAT betaOR =
00854       (betaImageItr->p[2] * itsLambda + OR)/(1 + 1 * itsLambda);
00855     betaImageItr->p[2] = betaOR;
00856 
00857     const FLOAT betaIN =
00858       (betaImageItr->p[3] * itsLambda + IN)/(1 + 1 * itsLambda);
00859     betaImageItr->p[3] = betaIN;
00860 
00861 
00862     if((betaCO > SMALL_SALIENCY) || (betaMO > SMALL_SALIENCY) ||
00863        (betaOR > SMALL_SALIENCY) || (betaIN > SMALL_SALIENCY))
00864     {
00865       // iterate over Y
00866       const typename std::vector<FLOAT>::iterator kalmanKernelXbeginLoc =
00867         kalmanKernelXbegin + KXStart;
00868 
00869 
00870 
00871       typename std::vector<FLOAT>::iterator ky = kalmanKernelYbegin + KYStart;
00872 
00873       for(ushort j = YStart; j < YStop; j++, ++ky)
00874       {
00875         const FLOAT COky = betaCO * (*ky);
00876         const FLOAT MOky = betaMO * (*ky);
00877         const FLOAT ORky = betaOR * (*ky);
00878         const FLOAT INky = betaIN * (*ky);
00879         const int   posy = j * itsImageSizeX;
00880         // iterate over X
00881         typename std::vector<FLOAT>::iterator kx = kalmanKernelXbeginLoc;
00882         for(ushort i = XStart; i < XStop; i++, ++kx)
00883         {
00884           const FLOAT COkx     = (*kx) * COky;
00885           const FLOAT MOkx     = (*kx) * MOky;
00886           const FLOAT ORkx     = (*kx) * ORky;
00887           const FLOAT INkx     = (*kx) * INky;
00888           const FLOAT COMO     = COkx  + MOkx;
00889           const FLOAT COINORMO = COMO  + ORkx + INkx;
00890           const int   posx     = posy  + i;
00891           // iterate through each frame in the buffer Z
00892           typename std::vector<FLOAT>::iterator kz = kalmanKernelZbegin;
00893 
00894           for(frameBufferItr =  frameBufferBegin;
00895               frameBufferItr != frameBufferEnd;
00896               ++frameBufferItr, ++kz)
00897           {
00898             const PIXTYPE *curr = &frameBufferItr->getVal(posx);
00899 
00900             // Hue is biased by color and motion
00901             // if intensity is very low, don't bother with color since
00902             // HSV is singular for hue if color is black
00903             if(curr->p[3] > 0.15F)
00904             {
00905               const FLOAT COMOkz  = (*kz) * COMO;
00906               outH1  += curr->p[0] * COMOkz;
00907               outH2  += curr->p[1] * COMOkz;
00908               npixH1 += COMOkz;
00909             }
00910 
00911             // saturation is biased by color, intensity,
00912             // orientation and motion
00913             const FLOAT COINORMOkz = (*kz) * COINORMO;
00914             outS  += curr->p[2] * COINORMOkz;
00915             npixS += COINORMOkz;
00916 
00917             // intensity is biased by color, intensity,
00918             // orientation and motion
00919             outV  += curr->p[3] * COINORMOkz;
00920           }
00921         }
00922       }
00923     }
00924 
00925     outImageItr->p[0] = outH1/npixH1;
00926     outImageItr->p[1] = outH2/npixH1;
00927     outImageItr->p[2] = outS /npixS;
00928     outImageItr->p[3] = outV /npixS;
00929 
00930     *finalImageItr = PixRGB<FLOAT>(*outImageItr);
00931     // final image is a combination of the current image and
00932     // the convolved image weighted by surprise
00933   }
00934 }
00935 
00936 
00937 /*************************************************************************/
00938 
00939 template <class PIXTYPE, class BETATYPE, class FLOAT>
00940 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSprocessFrameSeperable()
00941 {
00942   LINFO("PROCESSING FRAME %d",itsFrameNumber);
00943   typename Image<BETATYPE>::iterator betaImageItr;
00944   typename Image<PixRGB<FLOAT> >::iterator   finalImageItr =
00945     itsFinalImage.beginw();
00946 
00947   if(typeid(BETATYPE).name() == typeid(itsHyper4).name())
00948   {
00949     LINFO("Non-Scale 4 Channel Model");
00950     typename Image<FLOAT>::iterator    itsConsCOItr  = itsConspicCO.beginw();
00951     typename Image<FLOAT>::iterator    itsConsMOItr  = itsConspicMO.beginw();
00952     typename Image<FLOAT>::iterator    itsConsORItr  = itsConspicOR.beginw();
00953     typename Image<FLOAT>::iterator    itsConsINItr  = itsConspicIN.beginw();
00954 
00955     const PIXTYPE ZERO(0.0F);
00956     PIXTYPE normal;
00957     // copy itsInImage to itsOutImage so we can take the conspicuity weighted
00958     // average of the two
00959     // Derive the new bias with low pass smoothing
00960     for(betaImageItr = itsBetaImage.beginw();
00961         betaImageItr != itsBetaImage.endw();
00962         ++betaImageItr,
00963         ++itsConsCOItr,  ++itsConsMOItr,
00964         ++itsConsORItr,  ++itsConsINItr)
00965     {
00966       const FLOAT CO       = *itsConsCOItr;
00967       const FLOAT MO       = *itsConsMOItr;
00968       const FLOAT OR       = *itsConsORItr;
00969       const FLOAT IN       = *itsConsINItr;
00970 
00971       betaImageItr->p[0] =
00972         (betaImageItr->p[0] * itsLambda + CO)/(1 + 1 * itsLambda);
00973 
00974       betaImageItr->p[1] =
00975         (betaImageItr->p[1] * itsLambda + MO)/(1 + 1 * itsLambda);
00976 
00977       betaImageItr->p[2] =
00978         (betaImageItr->p[2] * itsLambda + OR)/(1 + 1 * itsLambda);
00979 
00980       betaImageItr->p[3] =
00981         (betaImageItr->p[3] * itsLambda + IN)/(1 + 1 * itsLambda);
00982     }
00983   }
00984   else
00985   {
00986     LINFO("Scale 6 Channel Model");
00987     typename Image<FLOAT>::iterator    itsConsINItr  = itsConspicIN.beginw();
00988     typename Image<FLOAT>::iterator    itsConsDRItr  = itsConspicDR.beginw();
00989     typename Image<FLOAT>::iterator    itsConsFLItr  = itsConspicFL.beginw();
00990     typename Image<FLOAT>::iterator    itsConsGAItr  = itsConspicGA.beginw();
00991     typename Image<FLOAT>::iterator    itsConsRGItr  = itsConspicRG.beginw();
00992     typename Image<FLOAT>::iterator    itsConsBYItr  = itsConspicBY.beginw();
00993     typename Image<FLOAT>::iterator    itsBayesWeightItr =
00994       itsBayesWeightImage.beginw();
00995 
00996     const PIXTYPE ZERO(0.0F);
00997     PIXTYPE normal;
00998     // copy itsInImage to itsOutImage so we can take the conspicuity weighted
00999     // average of the two
01000 
01001     // Derive the new bias with low pass smoothing
01002     for(betaImageItr = itsBetaImage.beginw();
01003         betaImageItr != itsBetaImage.endw();
01004         ++betaImageItr,
01005         ++itsConsINItr,  ++itsConsDRItr,
01006         ++itsConsFLItr,  ++itsConsGAItr,
01007         ++itsConsRGItr,  ++itsConsBYItr,
01008         ++itsBayesWeightItr)
01009     {
01010       if(itsUseBayesWeightImage)
01011       {
01012         *itsConsINItr = *itsConsINItr * *itsBayesWeightItr;
01013         *itsConsDRItr = *itsConsDRItr * *itsBayesWeightItr;
01014         *itsConsFLItr = *itsConsFLItr * *itsBayesWeightItr;
01015         *itsConsGAItr = *itsConsGAItr * *itsBayesWeightItr;
01016         *itsConsRGItr = *itsConsRGItr * *itsBayesWeightItr;
01017         *itsConsBYItr = *itsConsBYItr * *itsBayesWeightItr;
01018       }
01019       if(itsUseCorrMatrixSet)
01020       {
01021         const FLOAT IN       = *itsConsINItr;
01022         const FLOAT DR       = *itsConsDRItr;
01023         const FLOAT FL       = *itsConsFLItr;
01024         const FLOAT GA       = *itsConsGAItr;
01025         const FLOAT RG       = *itsConsRGItr;
01026         const FLOAT BY       = *itsConsBYItr;
01027 
01028         const FLOAT INnew = pow(RScomputeCor(IN,DR,FL,GA,RG,BY,0),20) * IN;
01029         //LINFO("IN old %f new %f",IN,INnew);
01030         betaImageItr->p[0] =
01031           (betaImageItr->p[0] * itsLambda + INnew)/
01032           (1 + 1 * itsLambda);
01033 
01034         const FLOAT DRnew = pow(RScomputeCor(IN,DR,FL,GA,RG,BY,1),20) * DR;
01035         //LINFO("DR old %f new %f",DR,DRnew);
01036         betaImageItr->p[1] =
01037           (betaImageItr->p[1] * itsLambda + DRnew)/
01038           (1 + 1 * itsLambda);
01039 
01040         const FLOAT FLnew = pow(RScomputeCor(IN,DR,FL,GA,RG,BY,2),20) * FL;
01041         //LINFO("FL old %f new %f",FL,FLnew);
01042         betaImageItr->p[2] =
01043           (betaImageItr->p[2] * itsLambda + FLnew)/
01044           (1 + 1 * itsLambda);
01045 
01046         const FLOAT GAnew = pow(RScomputeCor(IN,DR,FL,GA,RG,BY,3),20) * GA;
01047         //LINFO("GA old %f new %f",GA,GAnew);
01048         betaImageItr->p[3] =
01049           (betaImageItr->p[3] * itsLambda + GAnew)/
01050           (1 + 1 * itsLambda);
01051 
01052         const FLOAT RGnew = pow(RScomputeCor(IN,DR,FL,GA,RG,BY,4),20) * RG;
01053         //LINFO("RG old %f new %f",RG,RGnew);
01054         betaImageItr->p[4] =
01055           (betaImageItr->p[4] * itsLambda + RGnew)/
01056           (1 + 1 * itsLambda);
01057 
01058         const FLOAT BYnew = pow(RScomputeCor(IN,DR,FL,GA,RG,BY,5),20) * BY;
01059         //LINFO("BY old %f new %f",BY,BYnew);
01060         betaImageItr->p[5] =
01061           (betaImageItr->p[5] * itsLambda + BYnew)/
01062           (1 + 1 * itsLambda);
01063       }
01064       else
01065       {
01066         betaImageItr->p[0] =
01067           (betaImageItr->p[0] * itsLambda + *itsConsINItr)/
01068           (1 + 1 * itsLambda);
01069 
01070         betaImageItr->p[1] =
01071           (betaImageItr->p[1] * itsLambda + *itsConsDRItr)/
01072           (1 + 1 * itsLambda);
01073 
01074         betaImageItr->p[2] =
01075           (betaImageItr->p[2] * itsLambda + *itsConsFLItr)/
01076           (1 + 1 * itsLambda);
01077 
01078         betaImageItr->p[3] =
01079           (betaImageItr->p[3] * itsLambda + *itsConsGAItr)/
01080           (1 + 1 * itsLambda);
01081 
01082         betaImageItr->p[4] =
01083           (betaImageItr->p[4] * itsLambda + *itsConsRGItr)/
01084           (1 + 1 * itsLambda);
01085 
01086         betaImageItr->p[5] =
01087           (betaImageItr->p[5] * itsLambda + *itsConsBYItr)/
01088           (1 + 1 * itsLambda);
01089       }
01090     }
01091   }
01092   LINFO("BETA done");
01093   // do x,y and z seperate convolutions
01094   RSseperateConv('z'); RSseperateConv('y'); RSseperateConv('x');
01095   LINFO("FINISHING image");
01096   typename Image<PIXTYPE >::iterator outImageItr    = itsOutImage.beginw();
01097   for(finalImageItr  = itsFinalImage.beginw();
01098       finalImageItr != itsFinalImage.endw();
01099       ++finalImageItr, ++outImageItr)
01100   {
01101     *finalImageItr = PixRGB<FLOAT>(*outImageItr);
01102   }
01103   LINFO("DONE");
01104 }
01105 
01106 
01107 /*************************************************************************/
01108 
01109 template <class PIXTYPE, class BETATYPE, class FLOAT>
01110 void RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSseperateConv(const char axis)
01111 {
01112   typename Image<BETATYPE>::iterator betaImageItr = itsBetaImage.beginw();
01113 
01114   const typename std::deque<Image<PIXTYPE > >::iterator frameBufferBegin =
01115     itsFrameBuffer.begin();
01116   // const typename std::deque<Image<PIXTYPE > >::iterator frameBufferEnd   =
01117   //  itsFrameBuffer.end();
01118 
01119   typename Image<PIXTYPE >::iterator outImageItr;
01120   typename Image<PIXTYPE >::iterator outImageBegin;
01121   typename Image<PIXTYPE >::iterator outImageEnd;
01122   //typename Image<PIXTYPE >::iterator outImageNormItr;
01123   typename Image<PIXTYPE >::iterator inImageItr;
01124   typename Image<PIXTYPE >::iterator inImageTrueItr;
01125 
01126   Image<ushort>::iterator           itsStartItr;
01127   Image<ushort>::iterator           itsStopItr;
01128   Image<ushort>::iterator           itsKStartItr;
01129 
01130   typename std::deque<Image<PIXTYPE > >::iterator frameBufferItr;
01131   typename std::vector<FLOAT>::iterator           kalmanKernelbegin;
01132   FLOAT axisBias;
01133 
01134   if(axis == 'z')
01135   {
01136     inImageItr        = itsInImage.beginw();
01137     outImageBegin     = itsInterImage[0].beginw();
01138     outImageEnd       = itsInterImage[0].endw();
01139     //outImageNormItr   = itsInterImageNorm[0].beginw();
01140     itsStartItr       = itsZStart.beginw();
01141     itsStopItr        = itsZStop.beginw();
01142     itsKStartItr      = itsKZStart.beginw();
01143     kalmanKernelbegin = itsKalmanKernelZ.begin();
01144     axisBias          = itsZbias;
01145 
01146     // blank the output image and the norm image
01147     for(outImageItr  = outImageBegin;
01148         outImageItr != outImageEnd;
01149         ++outImageItr)
01150     {
01151       outImageItr->p[0]     = 0.0F;
01152       outImageItr->p[1]     = 0.0F;
01153       outImageItr->p[2]     = 0.0F;
01154       outImageItr->p[3]     = 0.0F;
01155       /*
01156       outImageNormItr->p[0] = 0.0F;
01157       outImageNormItr->p[1] = 0.0F;
01158       outImageNormItr->p[2] = 0.0F;
01159       outImageNormItr->p[3] = 0.0F;
01160       */
01161     }
01162     //outImageNormItr   = itsInterImageNorm[0].beginw();
01163 
01164   }
01165   else if(axis == 'y')
01166   {
01167     // blank the output image
01168     inImageItr        = itsInterImage[0].beginw();
01169     outImageBegin     = itsInterImage[1].beginw();
01170     outImageEnd       = itsInterImage[1].endw();
01171     //outImageNormItr   = itsInterImageNorm[0].beginw();
01172     itsStartItr       = itsYStart.beginw();
01173     itsStopItr        = itsYStop.beginw();
01174     itsKStartItr      = itsKYStart.beginw();
01175     kalmanKernelbegin = itsKalmanKernelY.begin();
01176     axisBias          = itsYbias;
01177 
01178     // blank the output image
01179     for(outImageItr = outImageBegin; outImageItr != outImageEnd; ++outImageItr)
01180     {
01181       outImageItr->p[0]     = 0.0F;
01182       outImageItr->p[1]     = 0.0F;
01183       outImageItr->p[2]     = 0.0F;
01184       outImageItr->p[3]     = 0.0F;
01185     }
01186   }
01187   else if(axis == 'x')
01188   {
01189     inImageItr        = itsInterImage[1].beginw();
01190     outImageBegin     = itsOutImage.beginw();
01191     outImageEnd       = itsOutImage.endw();
01192     //outImageNormItr   = itsInterImageNorm[0].beginw();
01193     itsStartItr       = itsXStart.beginw();
01194     itsStopItr        = itsXStop.beginw();
01195     itsKStartItr      = itsKXStart.beginw();
01196     kalmanKernelbegin = itsKalmanKernelX.begin();
01197     axisBias          = itsXbias;
01198 
01199     // blank the output image
01200     for(outImageItr = outImageBegin; outImageItr != outImageEnd; ++outImageItr)
01201     {
01202       outImageItr->p[0]     = 0.0F;
01203       outImageItr->p[1]     = 0.0F;
01204       outImageItr->p[2]     = 0.0F;
01205       outImageItr->p[3]     = 0.0F;
01206     }
01207   }
01208   else
01209   {
01210     LINFO("Must use axis as z,x then y in that order");
01211     LFATAL("Unknown axis specified %c",axis);
01212     // put values here to make to compiler shut the %*&! up
01213     inImageItr        = itsInterImage[1].beginw();
01214     outImageBegin     = itsOutImage.beginw();
01215     outImageEnd       = itsOutImage.endw();
01216     //outImageNormItr   = itsInterImageNorm[0].beginw();
01217     itsStartItr       = itsXStart.beginw();
01218     itsStopItr        = itsXStop.beginw();
01219     itsKStartItr      = itsKXStart.beginw();
01220     kalmanKernelbegin = itsKalmanKernelX.begin();
01221     axisBias          = itsXbias;
01222   }
01223 
01224   int pos = 0;
01225   FLOAT localBiasH1 = 0.0F;
01226   FLOAT localBiasH2 = 0.0F;
01227   FLOAT localBiasS  = 0.0F;
01228   FLOAT localBiasV  = 0.0F;
01229 
01230   const bool hyper6 = (typeid(BETATYPE).name() == typeid(itsHyper6).name());
01231   inImageTrueItr = itsInImage.beginw();
01232 
01233   for(outImageItr  = outImageBegin;
01234       outImageItr != outImageEnd; pos++,
01235         ++outImageItr, ++inImageItr, ++betaImageItr,
01236         ++itsStartItr, ++itsStopItr, ++itsKStartItr, ++inImageTrueItr)
01237   {
01238     FLOAT npixH1 = 0.0F;
01239     FLOAT npixH2 = 0.0F;
01240     FLOAT npixS  = 0.0F;
01241     FLOAT npixV  = 0.0F;
01242 
01243     if(hyper6)
01244     {
01245       // get the surprise biases smoothed
01246       const FLOAT betaIN = betaImageItr->p[0];
01247       const FLOAT betaDR = betaImageItr->p[1];
01248       const FLOAT betaFL = betaImageItr->p[2];
01249       const FLOAT betaGA = betaImageItr->p[3];
01250 
01251       LFATAL("two lines following this message do not compile. FIXME");
01252       const FLOAT betaRG = 0; ///////betaImageItr->p[4];
01253       const FLOAT betaBY = 0; ///////betaImageItr->p[5];
01254 
01255       // compute the surprise bias combinations with the axis bias
01256       /* If we use max level then surprise removal is scaled by the max
01257          level of all conspicuity maps, this limits reduction to be no more
01258          than the highest conspicuity map and prevents to much application
01259          at certian locations. However, it may not scale properly
01260       */
01261 
01262       if(itsUseMaxLevel)
01263       {
01264         if(betaBY > betaRG)
01265         {
01266           localBiasH1 = betaBY * axisBias * itsH1bias;
01267           localBiasH2 = betaBY * axisBias * itsH2bias;
01268           localBiasS  = betaBY * axisBias * itsSbias;
01269         }
01270         else
01271         {
01272           localBiasH1 = betaRG * axisBias * itsH1bias;
01273           localBiasH2 = betaRG * axisBias * itsH2bias;
01274           localBiasS  = betaRG * axisBias * itsSbias;
01275         }
01276         FLOAT newVal = betaBY;
01277         if(betaRG > newVal) newVal = betaRG;
01278         if(betaDR > newVal) newVal = betaDR;
01279         if(betaIN > newVal) newVal = betaIN;
01280         if(betaFL > newVal) newVal = betaFL;
01281         if(betaGA > newVal) newVal = betaGA;
01282         localBiasV = newVal * axisBias * itsVbias;
01283       }
01284       else
01285       {
01286         localBiasH1 = (betaBY + betaRG) * axisBias * itsH1bias;
01287         localBiasH2 = (betaBY + betaRG) * axisBias * itsH2bias;
01288         localBiasS  = (betaBY + betaRG) * axisBias * itsSbias;
01289         localBiasV  = (betaDR + betaBY + betaRG +
01290                        betaIN + betaFL + betaGA) * axisBias *
01291                       itsVbias;
01292       }
01293 
01294       const FLOAT colorBias = (betaRG * betaBY) / (itsBYbias * itsRGbias);
01295       FLOAT desat           = 1.0F - (colorBias * itsDesatbias);
01296 
01297       //make sure desat stays normal positive
01298       if(desat < 0.0F)
01299         desat = 0.0F;
01300 
01301       // Make sure that the values here are not sooo small as to not matter
01302       if((betaIN > SMALL_SALIENCY) || (betaDR > SMALL_SALIENCY) ||
01303          (betaFL > SMALL_SALIENCY) || (betaGA > SMALL_SALIENCY) ||
01304          (betaBY > SMALL_SALIENCY) || (betaRG > SMALL_SALIENCY))
01305       {
01306         // figure out where we are in the image and the kernel
01307         frameBufferItr                 = frameBufferBegin;
01308         typename std::vector<FLOAT>::iterator k = kalmanKernelbegin +
01309                                                  (*itsKStartItr);
01310         int posMod = 0;
01311         if(axis == 'y')
01312           posMod = pos%itsImageSizeX;
01313         else if(axis == 'x')
01314           posMod = pos/itsImageSizeX;
01315         else if(axis == 'z')
01316           *itsStopItr = itsFrameBuffer.size();
01317         // iterate over the kernel
01318         for(ushort i = *itsStartItr; i < *itsStopItr; i++, ++k)
01319         {
01320           // get the current other pixel x,y,z
01321           PIXTYPE curr;
01322           if(axis == 'z')
01323           {
01324             curr = frameBufferItr->getVal(pos);
01325             frameBufferItr++;
01326           }
01327           else if(axis == 'y')
01328             curr = itsInterImage[0].getVal(posMod,i);
01329           else
01330             curr = itsInterImage[1].getVal(i,posMod);
01331 
01332           // if other pixel is to dim, don't use its color
01333           // this avoids H2SV (and HSV) singularities at black for hue
01334           if(curr.p[3] > NEAR_BLACK)
01335           {
01336             const FLOAT H1      = (*k)      * localBiasH1;
01337             outImageItr->p[0]  += curr.p[0] * H1;
01338             npixH1             += H1;
01339 
01340             const FLOAT H2      = (*k)      * localBiasH2;
01341             outImageItr->p[1]  += curr.p[1] * H2;
01342             npixH2             += H2;
01343           }
01344 
01345           // saturation is biased by color, intensity,
01346           // orientation and motion
01347           const FLOAT S       = (*k)       * localBiasS;
01348           outImageItr->p[2]  += (curr.p[2] * desat) * S;
01349           npixS              += S;
01350 
01351           const FLOAT V       = (*k)       * localBiasV;
01352           // simple desaturation can increase intensity so we compensate
01353           // V' = (V - V*S)/(1 - S')
01354           const FLOAT newV    = (curr.p[3] - curr.p[3]*curr.p[2])/
01355                                 (1 - (curr.p[2] * desat));
01356             //outImageItr->p[3]  += curr.p[3]  * V;
01357           outImageItr->p[3]  += newV * V;
01358           npixV              += V;
01359         }
01360       }
01361     }
01362     else
01363     {
01364       // get the surprise biases smoothed
01365       const FLOAT betaCO = betaImageItr->p[0];
01366       const FLOAT betaMO = betaImageItr->p[1];
01367       const FLOAT betaOR = betaImageItr->p[2];
01368       const FLOAT betaIN = betaImageItr->p[3];
01369 
01370       // compute the surprise bias combinations with the axis bias
01371       const FLOAT COMO     = (betaCO + betaMO) * axisBias;
01372       const FLOAT COINORMO = (betaCO + betaIN + betaOR + betaMO) * axisBias;
01373 
01374       // Make sure that the values here are not sooo small as to not matter
01375       if((betaCO > SMALL_SALIENCY) || (betaMO > SMALL_SALIENCY) ||
01376          (betaOR > SMALL_SALIENCY) || (betaIN > SMALL_SALIENCY))
01377       {
01378         // figure out where we are in the image and the kernel
01379         frameBufferItr                 = frameBufferBegin;
01380         typename std::vector<FLOAT>::iterator k = kalmanKernelbegin +
01381                                                  (*itsKStartItr);
01382         int posMod = 0;
01383         if(axis == 'y')
01384           posMod = pos%itsImageSizeX;
01385         else if(axis == 'x')
01386           posMod = pos/itsImageSizeX;
01387         else if(axis == 'z')
01388           *itsStopItr = itsFrameBuffer.size();
01389 
01390         // iterate over the kernel
01391         for(ushort i = *itsStartItr; i < *itsStopItr; i++, ++k)
01392         {
01393           // get the current other pixel x,y,z
01394           PIXTYPE curr;
01395           if(axis == 'z')
01396           {
01397             curr = frameBufferItr->getVal(pos);
01398             frameBufferItr++;
01399           }
01400           else if(axis == 'y')
01401             curr = itsInterImage[0].getVal(posMod,i);
01402           else
01403             curr = itsInterImage[1].getVal(i,posMod);
01404 
01405           // if other pixel is to dim, don't use its color
01406           // this avoids H2SV (and HSV) singularities at black for hue
01407           if(curr.p[3] > NEAR_BLACK)
01408           {
01409             const FLOAT COMOk  = (*k) * COMO;
01410             outImageItr->p[0]  += curr.p[0] * COMOk;
01411             outImageItr->p[1]  += curr.p[1] * COMOk;
01412             npixH1 += COMOk;
01413           }
01414 
01415           // saturation is biased by color, intensity,
01416           // orientation and motion
01417           const FLOAT COINORMOk = (*k) * COINORMO;
01418           outImageItr->p[2]  += curr.p[2] * COINORMOk;
01419           outImageItr->p[3]  += curr.p[3] * COINORMOk;
01420           npixS += COINORMOk;
01421         }
01422       }
01423     }
01424     // accumulate the normalization
01425 
01426     /*
01427     outImageNormItr->p[0] += npixH1;
01428     outImageNormItr->p[1] += npixH1;
01429     outImageNormItr->p[2] += npixS;
01430     outImageNormItr->p[3] += npixS;
01431     */
01432 
01433     // at x, the final iteration normalize the final image
01434     if(axis == 'x')
01435     {
01436       // add in the original image to average (in a sense) with the
01437       // blurred image
01438       outImageItr->p[0]     += inImageTrueItr->p[0];
01439       outImageItr->p[1]     += inImageTrueItr->p[1];
01440       outImageItr->p[2]     += inImageTrueItr->p[2];
01441       outImageItr->p[3]     += inImageTrueItr->p[3];
01442 
01443       npixH1++; npixH2++; npixS++; npixV++;
01444 
01445       /*
01446       outImageNormItr->p[0] += 1.0F;
01447       outImageNormItr->p[1] += 1.0F;
01448       outImageNormItr->p[2] += 1.0F;
01449       outImageNormItr->p[3] += 1.0F;
01450       */
01451     }
01452 
01453 
01454     /*
01455     outImageItr->p[0] = outImageItr->p[0]/(outImageNormItr->p[0]);
01456     outImageItr->p[1] = outImageItr->p[1]/(outImageNormItr->p[1]);
01457     outImageItr->p[2] = outImageItr->p[2]/(outImageNormItr->p[2]);
01458     outImageItr->p[3] = outImageItr->p[3]/(outImageNormItr->p[3]);
01459 
01460     outImageNormItr->p[0] = 0.0F;
01461     outImageNormItr->p[1] = 0.0F;
01462     outImageNormItr->p[2] = 0.0F;
01463     outImageNormItr->p[3] = 0.0F;
01464     */
01465 
01466     outImageItr->p[0] = outImageItr->p[0]/npixH1;
01467     outImageItr->p[1] = outImageItr->p[1]/npixH2;
01468     outImageItr->p[2] = outImageItr->p[2]/npixS;
01469     outImageItr->p[3] = outImageItr->p[3]/npixV;
01470 
01471     // We should never increase saturation
01472     if(axis == 'x')
01473       if(outImageItr->p[2] > inImageTrueItr->p[2])
01474         outImageItr->p[2] = inImageTrueItr->p[2];
01475 
01476 
01477     // balance intensity by the change in saturation
01478     /*
01479     if(axis == 'x')
01480     {
01481       // V' = (V - V*S)/(1 - S')
01482       outImageItr->p[3] = fabs((outImageItr->p[3] -
01483                                 outImageItr->p[3]*inImageTrueItr->p[2])/
01484                                (1 - outImageItr->p[2]));
01485     }
01486     */
01487   }
01488 
01489   //LINFO("B");
01490 }
01491 
01492 /*************************************************************************/
01493 
01494 template <class PIXTYPE, class BETATYPE, class FLOAT>
01495 FLOAT RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RScomputeCor(const FLOAT IN,
01496                                                            const FLOAT DR,
01497                                                            const FLOAT FL,
01498                                                            const FLOAT GA,
01499                                                            const FLOAT RG,
01500                                                            const FLOAT BY,
01501                                                            const short idx) const
01502 {
01503   const FLOAT C1 = IN*itsAntiCorrelationMat[idx][0] +
01504                    DR*itsAntiCorrelationMat[idx][1] +
01505                    FL*itsAntiCorrelationMat[idx][2] +
01506                    GA*itsAntiCorrelationMat[idx][3] +
01507                    RG*itsAntiCorrelationMat[idx][4] +
01508                    BY*itsAntiCorrelationMat[idx][5];
01509 
01510   const FLOAT C2 = IN*itsBaseCorrelationMat[idx][0] +
01511                    DR*itsBaseCorrelationMat[idx][1] +
01512                    FL*itsBaseCorrelationMat[idx][2] +
01513                    GA*itsBaseCorrelationMat[idx][3] +
01514                    RG*itsBaseCorrelationMat[idx][4] +
01515                    BY*itsBaseCorrelationMat[idx][5];
01516   /*
01517   LINFO("BASE %f %f %f %f %f %f",
01518         IN*itsBaseCorrelationMat[idx][0],
01519         DR*itsBaseCorrelationMat[idx][1],
01520         FL*itsBaseCorrelationMat[idx][2],
01521         GA*itsBaseCorrelationMat[idx][3],
01522         RG*itsBaseCorrelationMat[idx][4],
01523         BY*itsBaseCorrelationMat[idx][5]
01524         );
01525 
01526   LINFO("ANTI %f %f %f %f %f %f",
01527         IN*itsAntiCorrelationMat[idx][0],
01528         DR*itsAntiCorrelationMat[idx][1],
01529         FL*itsAntiCorrelationMat[idx][2],
01530         GA*itsAntiCorrelationMat[idx][3],
01531         RG*itsAntiCorrelationMat[idx][4],
01532         BY*itsAntiCorrelationMat[idx][5]
01533         );
01534 
01535   LINFO("PARTS %f %f %f %f %f %f",
01536         itsBaseCorrelationMat[idx][0],
01537         itsBaseCorrelationMat[idx][1],
01538         itsBaseCorrelationMat[idx][2],
01539         itsBaseCorrelationMat[idx][3],
01540         itsBaseCorrelationMat[idx][4],
01541         itsBaseCorrelationMat[idx][5]);
01542 
01543   LINFO("BETA %f %f %f %f %f %f",IN,DR,FL,GA,RG,BY);
01544   */
01545   if(C1 > 0)
01546     return C2/C1;
01547   else
01548     return 0;
01549 }
01550 
01551 /*************************************************************************/
01552 
01553 template <class PIXTYPE, class BETATYPE, class FLOAT>
01554 Image<PixRGB<FLOAT> > RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSgetFrame()
01555 {
01556   itsInit[0] = false;
01557   itsInit[1] = false;
01558   itsInit[2] = false;
01559   itsInit[3] = false;
01560   itsInit[4] = false;
01561   itsInit[5] = false;
01562   return itsFinalImage;
01563 }
01564 
01565 /*************************************************************************/
01566 
01567 template <class PIXTYPE, class BETATYPE, class FLOAT>
01568 Image<PixRGB<FLOAT> > RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSgetOutImage()
01569 const
01570 {
01571   Image<PixRGB<FLOAT> > returnImage;
01572   returnImage.resize(itsOutImage.getWidth(),itsOutImage.getHeight());
01573   typename Image<PixRGB<FLOAT> >::iterator returnImageItr =
01574     returnImage.beginw();
01575   typename Image<PIXTYPE>::const_iterator outImageItr =
01576     itsOutImage.begin();
01577   while(returnImageItr != returnImage.endw())
01578   {
01579     *returnImageItr = PixRGB<FLOAT>(*outImageItr);
01580     ++returnImageItr; ++outImageItr;
01581   }
01582 
01583   return returnImage;
01584 }
01585 
01586 /*************************************************************************/
01587 
01588 template <class PIXTYPE, class BETATYPE, class FLOAT>
01589 Image<PIXTYPE> RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSgetRawOutImage() const
01590 {
01591   return itsOutImage;
01592 }
01593 
01594 /*************************************************************************/
01595 
01596 template <class PIXTYPE, class BETATYPE, class FLOAT>
01597 Image<PIXTYPE> RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSgetRawInImage() const
01598 {
01599   return itsInImage;
01600 }
01601 
01602 /*************************************************************************/
01603 
01604 template <class PIXTYPE, class BETATYPE, class FLOAT>
01605 Image<BETATYPE> RemoveSurprise<PIXTYPE,BETATYPE,FLOAT>::RSgetBetaImage() const
01606 {
01607   return itsBetaImage;
01608 }
01609 
01610 /*************************************************************************/
01611 
01612 template class RemoveSurprise<PixH2SV1<float>,PixHyper<float,4>,float>;
01613 template class RemoveSurprise<PixH2SV2<float>,PixHyper<float,4>,float>;
01614 template class RemoveSurprise<PixH2SV1<float>,PixHyper<float,6>,float>;
01615 template class RemoveSurprise<PixH2SV2<float>,PixHyper<float,6>,float>;
01616 
01617 #endif
Generated on Sun May 8 08:06:52 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3