SurpriseControl.C

Go to the documentation of this file.
00001 /*!@file Surprise/SurpriseControl.C attempt to control surprise in an 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/SurpriseControl.C $
00035 // $Id: SurpriseControl.C 14376 2011-01-11 02:44:34Z pez $
00036 //
00037 
00038 #ifndef SURPRISE_CONTROL_C_DEFINED
00039 #define SURPRISE_CONTROL_C_DEFINED
00040 
00041 #include "Surprise/SurpriseControl.H"
00042 
00043 #include <typeinfo>
00044 #include <climits>
00045 #include <cfloat>
00046 
00047 /*************************************************************************/
00048 
00049 template <class PIXTYPE, class BETATYPE, class FLOAT>
00050 SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SurpriseControl(const ushort sizeX,
00051                                                          const ushort sizeY)
00052 {
00053   LINFO("Creating SurpriseControl Object");
00054 
00055 
00056   SCinit(sizeX,sizeY);
00057   SCuseMaxLevel(false);
00058 
00059   if(typeid(BETATYPE).name() != typeid(itsHyper).name())
00060   {
00061     LFATAL("Run time type error. Type: %s is not supported",
00062            typeid(BETATYPE).name());
00063   }
00064 }
00065 
00066 /*************************************************************************/
00067 
00068 template <class PIXTYPE, class BETATYPE, class FLOAT>
00069 SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SurpriseControl()
00070 {
00071   LINFO("Creating SurpriseControl Object NOTE: Call init()");
00072 
00073   if(typeid(BETATYPE).name() != typeid(itsHyper).name())
00074   {
00075     LFATAL("Run time type error. Type: %s is not supported",
00076            typeid(BETATYPE).name());
00077   }
00078 }
00079 
00080 /*************************************************************************/
00081 
00082 template <class PIXTYPE, class BETATYPE, class FLOAT>
00083 SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::~SurpriseControl()
00084 {}
00085 
00086 /*************************************************************************/
00087 
00088 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00089 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCuseMaxLevel(const bool useML)
00090 {
00091   LINFO("Setting itsUseMaxLevel");
00092   itsUseMaxLevel = useML;
00093 }
00094 
00095 /*************************************************************************/
00096 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00097 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCuseTemporal(const bool useTMP)
00098 {
00099   LINFO("Setting itsUseTemporal");
00100   itsUseTemporal = useTMP;
00101 }
00102 
00103 /*************************************************************************/
00104 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00105 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>:: SCnormalizeBiasWithScale(
00106                                                         const bool useNBS)
00107 {
00108   LINFO("Setting itsNormalizeBiasWithScale");
00109   itsNormalizeBiasWithScale = useNBS;
00110 }
00111 
00112 /*************************************************************************/
00113 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00114 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCsetMasterConspicBias(
00115                                                     const FLOAT bias)
00116 {
00117   itsMasterConspicBias = bias;
00118 }
00119 
00120 /*************************************************************************/
00121 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00122 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCsetConspicBias(
00123                                               const FLOAT chan,
00124                                               const int chan_enum)
00125 {
00126   //LINFO("Using %s map - bias %f",sc_channel_name[chan_enum].c_str(),chan);
00127   itsConspicMapBias[chan_enum] = chan;
00128   itsUseConspicMap[chan_enum]  = true;
00129 }
00130 /*************************************************************************/
00131 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00132 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCsetMyScale(const ushort scale)
00133 {
00134   itsScale = scale;
00135 }
00136 
00137 /*************************************************************************/
00138 
00139 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00140 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCsetAxisBias(const FLOAT X,
00141                                                             const FLOAT Y,
00142                                                             const FLOAT Z)
00143 {
00144   itsXBias = X; itsYBias = Y; itsZBias = Z;
00145 }
00146 /*************************************************************************/
00147 
00148 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00149 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCsetH2SVBias(const FLOAT H1,
00150                                                             const FLOAT H2,
00151                                                             const FLOAT S,
00152                                                             const FLOAT V)
00153 {
00154   itsH1Bias = H1; itsH2Bias = H2; itsSBias = S; itsVBias = V;
00155 }
00156 
00157 /*************************************************************************/
00158 
00159 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00160 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCinit(const ushort sizeX,
00161                                                      const ushort sizeY)
00162 {
00163   LINFO("INIT: image size %d x %d",sizeX,sizeY);
00164 
00165   for(ushort i = 0; i < SC_MAX_CHANNELS; i++)
00166   {
00167     itsConspicMapBias[i]  = 1.0F;
00168     itsUseConspicMap[i]   = false;
00169   }
00170 
00171   itsIterCounter = 0;
00172   itsScale       = 0;
00173 
00174   itsXBias = 1.0F; itsYBias = 1.0F; itsZBias = 1.0F;
00175 
00176   itsLambda                 = 0.1;
00177   itsInitBuffer             = false;
00178   itsUseCorrMatrixSet       = false;
00179   itsUseBayesWeightImage    = false;
00180   itsUseMaskImage           = false;
00181   itsUseTargetFrame         = false;
00182   itsUseTemporal            = true;
00183   itsBufferFull             = false;
00184   itsNormalizeBiasWithScale = false;
00185   itsImageSizeX             = sizeX;
00186   itsImageSizeY             = sizeY;
00187 
00188   itsTargetFrame         = 0;
00189 
00190   itsInImage.resize(sizeX,sizeY);
00191   itsOutImage.resize(sizeX,sizeY);
00192   itsFinalImage.resize(sizeX,sizeY);
00193   itsLocalBiasH1.resize(sizeX,sizeY);
00194   itsLocalBiasH2.resize(sizeX,sizeY);
00195   itsLocalBiasS.resize(sizeX,sizeY);
00196   itsLocalBiasV.resize(sizeX,sizeY);
00197   itsSmallSaliency.resize(sizeX,sizeY);
00198   BETATYPE blank(0.0F);
00199   PIXTYPE  blank2(0.0F);
00200 
00201   Image<BETATYPE> initBeta; initBeta.resize(sizeX,sizeY);
00202   typename Image<BETATYPE>::iterator betaImageItr = initBeta.beginw();
00203   Image<PIXTYPE> tempImage;
00204   tempImage.resize(sizeX,sizeY);
00205   typename Image<PIXTYPE>::iterator tempImageItr = tempImage.beginw();
00206   while(betaImageItr != initBeta.endw())
00207   {
00208     *betaImageItr = blank;
00209     *tempImageItr = blank2;
00210     ++betaImageItr; ++tempImageItr;
00211   }
00212 
00213   itsBetaImage.push_front(initBeta);
00214 
00215   // resize intermediate images, set equal to the blank beta image
00216 
00217   itsInterImage.resize(2,tempImage);
00218 }
00219 
00220 /*************************************************************************/
00221 
00222 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00223 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCsetLambda(const FLOAT lambda)
00224 {
00225   itsLambda = lambda;
00226 }
00227 // 1. create a guassian filtered frame of the current movie
00228 /*************************************************************************/
00229 
00230 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00231 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCsetTargetFrame(const uint frame)
00232 {
00233   itsTargetFrame    = frame;
00234   itsUseTargetFrame = true;
00235 }
00236 // 2. merge the guassian filtered frame with the current frame giving more
00237 //    weight to filtered pixels if the surprise is higher.
00238 
00239 /*************************************************************************/
00240 
00241 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00242 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCsetOriginalImageWeight(
00243                                               const FLOAT origImageWeight)
00244 {
00245   itsOriginalImageWeight = origImageWeight;
00246 }
00247 
00248 /*************************************************************************/
00249 
00250 template <class PIXTYPE, class BETATYPE, class FLOAT>
00251 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCcreateAndersonSepFilters(
00252                                                              const ushort size)
00253 {
00254   const ushort basesize = 5;
00255 
00256   if(size%basesize != 0)
00257     LFATAL("This kernel size must be evenly divisable by 5 got %d",size);
00258 
00259   const FLOAT anderson[basesize] = {1.0/16.0, 4.0/16.0, 6.0/16.0,
00260                                     4.0/16.0, 1.0/16.0};
00261   for(ushort i = 0; i < basesize; i++)
00262   {
00263     LINFO("%f",anderson[i]);
00264   }
00265   const short div = size/basesize;
00266 
00267   bool evensize;
00268 
00269   if(size%2 == 0)
00270   {
00271     evensize = true;
00272     itsKernelSizeX = size + 1;
00273     itsKernelSizeY = size + 1;
00274   }
00275   else
00276   {
00277     itsKernelSizeX = size;
00278     itsKernelSizeY = size;
00279     evensize = false;
00280   }
00281   itsKernelSizeZ = basesize;
00282 
00283   itsKalmanKernelX.resize(itsKernelSizeX,0.0F);
00284   itsKalmanKernelY.resize(itsKernelSizeY,0.0F);
00285   itsKalmanKernelZ.resize(itsKernelSizeZ,0.0F);
00286 
00287   const FLOAT centerX = floor((FLOAT)itsKernelSizeX/2.0F);
00288 
00289   ushort offset = 0;
00290   LINFO("Kernel (Anderson Variant) size %d",itsKernelSizeX);
00291   for(ushort i = 0; i < itsKernelSizeX; i++)
00292   {
00293     if((i < centerX) || (evensize == false))
00294     {
00295       if((i%div == 0) && (i != 0))
00296         offset++;
00297     }
00298     else
00299     {
00300       if((i - 1)%div == 0)
00301         offset++;
00302     }
00303 
00304     itsKalmanKernelX[i] = anderson[offset];
00305     itsKalmanKernelY[i] = anderson[offset];
00306     std::cerr << i << " : " << itsKalmanKernelX[i] << "\n";
00307   }
00308 
00309   for(ushort i = 0; i < itsKernelSizeZ; i++)
00310   {
00311     itsKalmanKernelZ[i] = anderson[i];
00312   }
00313 
00314   itsImageSizeZ = itsKernelSizeZ;
00315   itsTemporalOffset = (ushort)floor(itsKernelSizeZ/2.0);
00316 }
00317 
00318 /*************************************************************************/
00319 template <class PIXTYPE, class BETATYPE, class FLOAT>
00320 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCcreateSepFilters(
00321                                               const FLOAT spatSigma,
00322                                               const FLOAT tempSigma,
00323                                               const FLOAT stdDevSize)
00324 {
00325   LINFO("ASAC SETTING UP KERNELS");
00326   // create three components for a std seperable guassian kernel
00327   ushort rs1 = (ushort)ceil(spatSigma*stdDevSize*2.0F);
00328   ushort rs2 = (ushort)floor(spatSigma*stdDevSize*2.0F);
00329   // make sure the kernel is odd sized spatial
00330   if(rs1%2 == 0)
00331   {
00332     if(rs2%2 == 0)
00333     {
00334       itsKernelSizeX = rs2 + 1;
00335       itsKernelSizeY = rs2 + 1;
00336     }
00337     else
00338     {
00339       itsKernelSizeX = rs2;
00340       itsKernelSizeY = rs2;
00341     }
00342   }
00343   else
00344   {
00345     itsKernelSizeX = rs1;
00346     itsKernelSizeY = rs1;
00347   }
00348   itsKalmanKernelX.resize(itsKernelSizeX,0.0F);
00349   itsKalmanKernelY.resize(itsKernelSizeY,0.0F);
00350 
00351   rs1 = (ushort)ceil((tempSigma*stdDevSize*2.0F));
00352   rs2 = (ushort)floor((tempSigma*stdDevSize*2.0F));
00353   // make sure the kernel is odd sized temporal
00354   if(rs1%2 == 0)
00355   {
00356     if(rs2%2 == 0)
00357     {
00358       itsKernelSizeZ = rs2 + 1;
00359     }
00360     else
00361     {
00362       itsKernelSizeZ = rs2;
00363     }
00364   }
00365   else
00366   {
00367     itsKernelSizeZ = rs1;
00368   }
00369   itsKalmanKernelZ.resize(itsKernelSizeZ,0.0F);
00370 
00371   itsImageSizeZ = itsKernelSizeZ;
00372 
00373   // find the kernel center
00374 
00375   const FLOAT centerX = floor((FLOAT)itsKernelSizeX/2.0F);
00376   const FLOAT centerY = floor((FLOAT)itsKernelSizeY/2.0F);
00377   const FLOAT centerZ = floor((FLOAT)itsKernelSizeZ/2.0F);
00378 
00379   FLOAT gmod = 1.0F/sqrt(2.0F*M_PI*pow(spatSigma,2));
00380 
00381   LINFO("Kernel X size %d",itsKernelSizeX);
00382   for(ushort i = 0; i < itsKernelSizeX; i++)
00383   {
00384     const FLOAT dist = pow((i - centerX),2);
00385     itsKalmanKernelX[i] =
00386       (gmod*exp((-1.0F*dist)/pow(2*spatSigma,2)));
00387     std::cerr << i << " : " << itsKalmanKernelX[i] << "\n";
00388   }
00389   LINFO("Kernel Y size %d",itsKernelSizeY);
00390   for(ushort i = 0; i < itsKernelSizeY; i++)
00391   {
00392     const FLOAT dist = pow((i - centerY),2);
00393     itsKalmanKernelY[i] =
00394       (gmod*exp((-1.0F*dist)/pow(2*spatSigma,2)));
00395     std::cerr << i << " : " << itsKalmanKernelY[i] << "\n";
00396   }
00397 
00398   gmod = 1.0F/sqrt(2.0F*M_PI*pow(tempSigma,2));
00399   LINFO("Kernel Z size %d",itsKernelSizeZ);
00400   for(ushort i = 0; i < itsKernelSizeZ; i++)
00401   {
00402     const FLOAT dist = pow((i - centerZ),2);
00403     itsKalmanKernelZ[i] =
00404       (gmod*exp((-1.0F*dist)/pow(2*tempSigma,2)));
00405     std::cerr << i << " : " << itsKalmanKernelZ[i] << "\n";
00406   }
00407 
00408   itsTemporalOffset = (ushort)floor(itsKernelSizeZ/2.0);
00409 }
00410 
00411 /*************************************************************************/
00412 template <class PIXTYPE, class BETATYPE, class FLOAT>
00413 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCfindConvolutionEndPoints()
00414 {
00415   LINFO("SETTING UP CONVOLUTION END POINTS");
00416 
00417   itsXStart.resize(itsImageSizeX,itsImageSizeY);
00418   itsYStart.resize(itsImageSizeX,itsImageSizeY);
00419   itsZStart.resize(itsImageSizeX,itsImageSizeY);
00420   itsXStop.resize( itsImageSizeX,itsImageSizeY);
00421   itsYStop.resize( itsImageSizeX,itsImageSizeY);
00422   itsZStop.resize( itsImageSizeX,itsImageSizeY);
00423   itsKXStart.resize(itsImageSizeX,itsImageSizeY);
00424   itsKYStart.resize(itsImageSizeX,itsImageSizeY);
00425   itsKZStart.resize(itsImageSizeX,itsImageSizeY);
00426 
00427   Image<ushort>::iterator itsZStartItr  = itsZStart.beginw();
00428   Image<ushort>::iterator itsZStopItr   = itsZStop.beginw();
00429   Image<ushort>::iterator itsKZStartItr = itsKZStart.beginw();
00430 
00431   Image<ushort>::iterator itsYStartItr  = itsYStart.beginw();
00432   Image<ushort>::iterator itsYStopItr   = itsYStop.beginw();
00433   Image<ushort>::iterator itsKYStartItr = itsKYStart.beginw();
00434 
00435   Image<ushort>::iterator itsXStartItr  = itsXStart.beginw();
00436   Image<ushort>::iterator itsXStopItr   = itsXStop.beginw();
00437   Image<ushort>::iterator itsKXStartItr = itsKXStart.beginw();
00438 
00439   for(ushort y = 0; y < itsImageSizeY; y++)
00440   {
00441     for(ushort x = 0; x < itsImageSizeX; x++)
00442     {
00443       // Z is not interesting, its starts at the current frame and
00444       // runs the size of the deque
00445 
00446       *itsKZStartItr = 0;
00447       *itsZStartItr  = 0;
00448       *itsZStopItr   = itsKernelSizeZ;
00449 
00450       const ushort yhalf = (ushort)floor((FLOAT)itsKernelSizeY/2.0F);
00451       const ushort yend  = itsImageSizeY - yhalf;
00452       if(y < yhalf + 1)
00453       {
00454         *itsYStartItr  = 0;
00455         *itsKYStartItr = yhalf - y;
00456         *itsYStopItr   = y + yhalf;
00457       }
00458       else if(y > yend)
00459       {
00460         *itsYStartItr  = y - yhalf;
00461         *itsKYStartItr = 0;
00462         *itsYStopItr   = itsImageSizeY;
00463       }
00464       else
00465       {
00466         *itsYStartItr  = y - yhalf;
00467         *itsKYStartItr = 0;
00468         *itsYStopItr   = y + yhalf;
00469       }
00470 
00471       const ushort xhalf = (ushort)floor((FLOAT)itsKernelSizeX/2.0F);
00472       const ushort xend  = itsImageSizeX - xhalf;
00473       if(x < xhalf + 1)
00474       {
00475         *itsXStartItr  = 0;
00476         *itsKXStartItr = xhalf - x;
00477         *itsXStopItr   = x + xhalf;
00478       }
00479       else if(x > xend)
00480       {
00481         *itsXStartItr  = x - xhalf;
00482         *itsKXStartItr = 0;
00483         *itsXStopItr   = itsImageSizeX;
00484       }
00485       else
00486       {
00487         *itsXStartItr  = x - xhalf;
00488         *itsKXStartItr = 0;
00489         *itsXStopItr   = x + xhalf;
00490       }
00491 
00492       ++itsZStartItr; ++itsZStopItr; ++itsKZStartItr;
00493       ++itsYStartItr; ++itsYStopItr; ++itsKYStartItr;
00494       ++itsXStartItr; ++itsXStopItr; ++itsKXStartItr;
00495     }
00496   }
00497 }
00498 
00499 
00500 /*************************************************************************/
00501 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00502 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCinputRawImage(
00503                                      const Image<PixRGB<FLOAT> >& rawImage)
00504 {
00505   //LINFO("INPUT RAW IMAGE");
00506 
00507   if(rawImage.getHeight() != itsImageSizeY)
00508   {
00509     LINFO("Input raw image is not the correct size");
00510     LFATAL("Raw %d != sizeY %d",rawImage.getHeight(),itsImageSizeY);
00511   }
00512   if(rawImage.getWidth() != itsImageSizeX)
00513   {
00514     LINFO("Input raw image is not the correct size");
00515     LFATAL("Raw %d != sizeX %d",rawImage.getWidth(),itsImageSizeX);
00516   }
00517 
00518   typename Image<PIXTYPE >::iterator inImageItr =
00519     itsInImage.beginw();
00520   typename Image<PixRGB<FLOAT> >::const_iterator rawImageItr =
00521     rawImage.begin();
00522 
00523   // convert the input image to H2SV2
00524   while(inImageItr != itsInImage.endw())
00525   {
00526     *inImageItr = PIXTYPE(*rawImageItr);
00527     ++inImageItr; ++rawImageItr;
00528   }
00529 
00530   itsFrameBuffer.push_front(itsInImage);
00531   itsInitBuffer = true;
00532 
00533   //if we get to big, pop off the back image
00534   if(itsFrameBuffer.size() > (unsigned)(itsImageSizeZ + 1))
00535   {
00536     itsFrameBuffer.pop_back();
00537     itsBufferFull = true;
00538   }
00539 }
00540 
00541 /*************************************************************************/
00542 
00543 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00544 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCinputSalMap(
00545                                               const Image<FLOAT>& salMap)
00546 {
00547   if(itsInImage.getWidth() != salMap.getWidth())
00548   {
00549     LINFO("Saliency map is the wrong size or raw image not initalized");
00550     LFATAL("Sal Map Width %d != Raw Image Width %d",salMap.getWidth(),
00551            itsInImage.getWidth());
00552   }
00553   if(itsInImage.getHeight() != salMap.getHeight())
00554   {
00555     LINFO("Saliency map is the wrong size or raw image not initalized");
00556     LFATAL("Sal Map Height %d != Raw Image Height %d",salMap.getHeight(),
00557            itsInImage.getHeight());
00558   }
00559 
00560   // normalize from 0 to 1
00561   itsSalMap = salMap/255.0F;
00562 }
00563 
00564 /*************************************************************************/
00565 
00566 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00567 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCinputConspicMap(
00568                                               const Image<FLOAT>& cmap,
00569                                               const int cmap_enum)
00570 {
00571   if(itsUseConspicMap[cmap_enum] != true)
00572   {
00573     LINFO("Called to input %s image, but did not expect it",
00574           sc_channel_name[cmap_enum].c_str());
00575     LFATAL("Be sure to set the bias first!");
00576   }
00577   if(itsInImage.getWidth() != cmap.getWidth())
00578   {
00579     LINFO("Saliency map is the wrong size or raw image not initalized");
00580     LFATAL("Conspic Width %d != Raw Width %d",cmap.getWidth(),
00581            itsInImage.getWidth());
00582   }
00583   if(itsInImage.getHeight() != cmap.getHeight())
00584   {
00585     LINFO("Saliency map is the wrong size or raw image not initalized");
00586     LFATAL("Conspic Height %d != Raw Height %d",cmap.getHeight(),
00587            itsInImage.getHeight());
00588   }
00589   // normalize from 0 to 1
00590   itsConspicMap[cmap_enum] = cmap/255.0F;
00591   itsConspicMap[cmap_enum] = itsConspicMap[cmap_enum] *
00592                              itsConspicMapBias[cmap_enum];
00593 
00594   itsConspicMap[cmap_enum] = itsConspicMap[cmap_enum] * itsMasterConspicBias;
00595 
00596 
00597   // if we use a bayes image, weight here
00598   if(itsUseBayesWeightImage)
00599   {
00600     if(itsConspicMap[cmap_enum].getWidth() != itsBayesWeightImage.getWidth())
00601       LFATAL("Bayes image must be same width as conspicuity maps");
00602     if(itsConspicMap[cmap_enum].getHeight() != itsBayesWeightImage.getHeight())
00603       LFATAL("Bayes image must be same height as conspicuity maps");
00604 
00605     typename Image<FLOAT>::iterator icmap = itsConspicMap[cmap_enum].beginw();
00606     typename Image<FLOAT>::const_iterator bayes = itsBayesWeightImage.begin();
00607     while(icmap != itsConspicMap[cmap_enum].endw())
00608     {
00609       *icmap = (*icmap) * (*bayes);
00610       ++icmap; ++bayes;
00611     }
00612   }
00613   // if we use a mask, modify conspic maps here
00614   if(itsUseMaskImage)
00615   {
00616     if(itsConspicMap[cmap_enum].getWidth() != itsMaskImage.getWidth())
00617       LFATAL("Mask image must be same width as conspicuity maps");
00618     if(itsConspicMap[cmap_enum].getHeight() != itsMaskImage.getHeight())
00619       LFATAL("Mask image must be same height as conspicuity maps");
00620 
00621     typename Image<FLOAT>::iterator icmap = itsConspicMap[cmap_enum].beginw();
00622     typename Image<FLOAT>::const_iterator mask  = itsMaskImage.begin();
00623     while(icmap != itsConspicMap[cmap_enum].endw())
00624     {
00625       *icmap = (*icmap) * (*mask);
00626 
00627       ++icmap; ++mask;
00628     }
00629   }
00630 
00631   if(SC_DEBUG)
00632   {
00633     char name[100];
00634     sprintf(name,"debug-conspic-%d-%d-%d.png",itsScale,itsIterCounter,cmap_enum);
00635     std::string prefix    = name;
00636     Image<PixRGB<FLOAT> > temp =
00637       normalizeScaleRainbow(itsConspicMap[cmap_enum],0,5);
00638     Raster::WriteRGB(temp, prefix);
00639   }
00640 
00641 }
00642 
00643 /*************************************************************************/
00644 
00645 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00646 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCinputBayesWeightImage(
00647                                               const Image<FLOAT> &bayesImage)
00648 {
00649   LINFO("INPUT Bayes Weight Image");
00650   itsUseBayesWeightImage = true;
00651   itsBayesWeightImage = bayesImage;
00652 }
00653 /*************************************************************************/
00654 
00655 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00656 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCinputMaskImage(
00657                                               const Image<FLOAT> &maskImage)
00658 
00659 {
00660   FLOAT mi, ma;
00661   getMinMax(maskImage,mi,ma);
00662   if(mi < 0)
00663   {
00664     LINFO("Mask Image value too low = %f",mi);
00665     LFATAL("Mask Image pixel values must be from 0 to 1");
00666   }
00667   if(ma > 1)
00668   {
00669     LINFO("Mask Image value too high = %f",ma);
00670     LFATAL("Mask Image pixel values must be from 0 to 1");
00671   }
00672   LINFO("INPUT independant mask image");
00673   itsUseMaskImage = true;
00674   itsMaskImage = maskImage;
00675 }
00676 /*************************************************************************/
00677 
00678 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
00679 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCcomputeNewBeta()
00680 {
00681 
00682 
00683   // Go through each conspicuity map and if we are using it, compute
00684   // beta as a kalman smoothed set of frames.
00685   // buffer beta so that it can align with the temporal components
00686 
00687   Image<BETATYPE> betaImage; betaImage.resize(itsImageSizeX,itsImageSizeY);
00688   for(ushort i = 0; i < SC_MAX_CHANNELS; i++)
00689   {
00690     if(itsUseConspicMap[i])
00691     {
00692       typename Image<BETATYPE>::iterator betaImageItr;
00693       typename Image<FLOAT>::iterator consMapItr               =
00694         itsConspicMap[i].beginw();
00695       typename Image<BETATYPE>::const_iterator betaImageOldItr =
00696         itsBetaImage[0].begin();
00697       typename Image<FLOAT>::const_iterator itsBayesWeightItr  =
00698         itsBayesWeightImage.begin();
00699 
00700       for(betaImageItr = betaImage.beginw();
00701           betaImageItr != betaImage.endw();
00702           ++betaImageItr,      ++consMapItr,
00703           ++itsBayesWeightItr, ++betaImageOldItr)
00704       {
00705         if(itsUseBayesWeightImage)
00706         {
00707           *consMapItr = *consMapItr * (*itsBayesWeightItr);
00708         }
00709 
00710         betaImageItr->p[i] =
00711           (betaImageOldItr->p[i] * itsLambda + *consMapItr)/
00712           (1 + 1 * itsLambda);
00713       }
00714 
00715       if(SC_DEBUG)
00716       {
00717         Image<FLOAT> ftemp; ftemp.resize(betaImage.getWidth(),
00718                                          betaImage.getHeight());
00719 
00720         typename Image<FLOAT>::iterator itmp = ftemp.beginw();
00721 
00722         for(betaImageItr = betaImage.beginw();
00723             betaImageItr != betaImage.endw();
00724             ++betaImageItr, ++itmp)
00725           *itmp = betaImageItr->p[i];
00726 
00727         char name[100];
00728         sprintf(name,"debug-beta-%d-%d-%d.png",itsScale,itsIterCounter,i);
00729         std::string prefix    = name;
00730         Image<PixRGB<FLOAT> > temp =
00731           normalizeScaleRainbow(ftemp,0,5);
00732         Raster::WriteRGB(temp, prefix);
00733       }
00734     }
00735   }
00736   itsBetaImage.push_front(betaImage);
00737 
00738   //if we get to big, pop off the back image
00739   if(itsBetaImage.size() > (unsigned)(itsImageSizeZ + 1))
00740     itsBetaImage.pop_back();
00741 }
00742 
00743 /*************************************************************************/
00744 
00745 template <class PIXTYPE, class BETATYPE, class FLOAT>
00746 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCprocessFrameSeperable()
00747 {
00748   LINFO("PROCESSING FRAME Kernel Size X - %d Y - %d Z - %d",
00749         itsKernelSizeX,
00750         itsKernelSizeY,
00751         itsKernelSizeZ);
00752 
00753   typename Image<PixRGB<FLOAT> >::iterator   finalImageItr =
00754     itsFinalImage.beginw();
00755 
00756   // copy itsInImage to itsOutImage so we can take the conspicuity weighted
00757   // average of the two
00758 
00759   // Derive the new bias with low pass smoothing
00760 
00761   SCcomputeNewBeta();
00762 
00763   LINFO("Buffer %"ZU" ksize %d",itsFrameBuffer.size(),itsKernelSizeZ);
00764   if(itsFrameBuffer.size() > (uint)itsTemporalOffset)
00765   {
00766     itsOutputReady  = true;
00767     itsFrameCurrent = &itsFrameBuffer[(uint)itsTemporalOffset];
00768     itsBetaCurrent  = &itsBetaImage[(uint)itsTemporalOffset];
00769 
00770     SCcomputeLocalBias();
00771 
00772     if(itsUseTemporal)
00773     {
00774       LINFO("Convolving image x,y,z");
00775       SCseperateConvXYZ();
00776     }
00777     else
00778     {
00779       LINFO("Convolving image x,y");
00780       SCseperateConvXY();
00781     }
00782 
00783     LINFO("FINISHING image");
00784     typename Image<PIXTYPE >::const_iterator outImageItr = itsOutImage.begin();
00785     for(finalImageItr  = itsFinalImage.beginw();
00786         finalImageItr != itsFinalImage.endw();
00787         ++finalImageItr, ++outImageItr)
00788     {
00789       *finalImageItr = PixRGB<FLOAT>(*outImageItr);
00790     }
00791     LINFO("DONE");
00792   }
00793   else
00794   {
00795     LINFO("FRAME BUFFER NOT YET HALF FULL");
00796     itsOutputReady = false;
00797     for(finalImageItr  = itsFinalImage.beginw();
00798         finalImageItr != itsFinalImage.endw();
00799         ++finalImageItr)
00800     {
00801       *finalImageItr = PixRGB<FLOAT>(0,0,0);
00802     }
00803   }
00804   itsIterCounter++;
00805 }
00806 
00807 /*************************************************************************/
00808 template <class PIXTYPE, class BETATYPE, class FLOAT>
00809 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCcomputeLocalBias()
00810 {
00811 
00812   if(!(itsUseConspicMap[SC_DR0] == itsUseConspicMap[SC_DR1] &&
00813        itsUseConspicMap[SC_DR0] == itsUseConspicMap[SC_DR2] &&
00814        itsUseConspicMap[SC_DR0] == itsUseConspicMap[SC_DR3]))
00815     LFATAL("You must use all four direction channels or none!");
00816 
00817   if(!(itsUseConspicMap[SC_GA0] == itsUseConspicMap[SC_GA1] &&
00818        itsUseConspicMap[SC_GA0] == itsUseConspicMap[SC_GA2] &&
00819        itsUseConspicMap[SC_GA0] == itsUseConspicMap[SC_GA3]))
00820     LFATAL("You must use all four orientation channels or none!");
00821 
00822   if(!(itsUseConspicMap[SC_H1] == itsUseConspicMap[SC_H2] &&
00823        itsUseConspicMap[SC_H1] == itsUseConspicMap[SC_HS] &&
00824        itsUseConspicMap[SC_H1] == itsUseConspicMap[SC_HV]))
00825     LFATAL("You must use all four H2SV channels or none!");
00826 
00827   if(!(itsUseConspicMap[SC_RG] == itsUseConspicMap[SC_BY]))
00828     LFATAL("You must use both RG and BY channels or none!");
00829   Image<bool>::iterator  iSmallS;
00830 
00831   // find if any parts have a very small surprise
00832   iSmallS = itsSmallSaliency.beginw();
00833   for(typename Image<BETATYPE>::const_iterator betaImageItr =
00834         itsBetaCurrent->begin(); betaImageItr != itsBetaCurrent->end();
00835       ++betaImageItr, ++iSmallS)
00836   {
00837     // get the surprise biases smoothed
00838     //*iSmallS = false;
00839     *iSmallS = true;
00840 
00841     for(ushort i = 0; i < SC_MAX_CHANNELS; i++)
00842     {
00843       if(betaImageItr->p[i] > SMALL_SALIENCY)
00844         *iSmallS = false;
00845     }
00846   }
00847 
00848   // reset all localbias maps, set to zero
00849   typename Image<FLOAT>::iterator iBiasH1 = itsLocalBiasH1.beginw();
00850   typename Image<FLOAT>::iterator iBiasH2 = itsLocalBiasH2.beginw();
00851   typename Image<FLOAT>::iterator iBiasS  = itsLocalBiasS.beginw();
00852   typename Image<FLOAT>::iterator iBiasV  = itsLocalBiasV.beginw();
00853 
00854   for(typename Image<BETATYPE>::const_iterator betaImageItr =
00855         itsBetaCurrent->begin(); betaImageItr != itsBetaCurrent->end();
00856       ++betaImageItr,
00857         ++iBiasH1, ++iBiasH2, ++iBiasS, ++iBiasV, ++iSmallS)
00858   {
00859     *iBiasH1 = 0; *iBiasH2 = 0; *iBiasS = 0; *iBiasV = 0;
00860   }
00861 
00862   // compute bias using maximum saliency value
00863   if(itsUseMaxLevel)
00864   {
00865 
00866     iBiasH1 = itsLocalBiasH1.beginw();
00867     iBiasH2 = itsLocalBiasH2.beginw();
00868     iBiasS  = itsLocalBiasS.beginw();
00869     iBiasV  = itsLocalBiasV.beginw();
00870 
00871     for(typename Image<BETATYPE>::const_iterator betaImageItr =
00872           itsBetaCurrent->begin(); betaImageItr != itsBetaCurrent->end();
00873         ++betaImageItr,
00874           ++iBiasH1, ++iBiasH2, ++iBiasS, ++iBiasV)
00875     {
00876       // compute the surprise bias combinations with the axis bias
00877       /* If we use max level then surprise removal is scaled by the max
00878          level of all conspicuity maps, this limits reduction to be no more
00879          than the highest conspicuity map and prevents to much application
00880          at certian locations. However, it may not scale properly
00881       */
00882 
00883       // Bias color by RG/BY or H2SV
00884 
00885       const FLOAT *betaImg = betaImageItr->p;
00886 
00887       if(itsUseConspicMap[SC_H1])
00888       {
00889         *iBiasH1 = betaImg[SC_H1];
00890         *iBiasH2 = betaImg[SC_H2];
00891         *iBiasS  = betaImg[SC_HS];
00892         *iBiasV  = betaImg[SC_HV];
00893       }
00894       else
00895       {
00896         if(itsUseConspicMap[SC_BY])
00897         {
00898           if(betaImageItr->p[SC_BY] > betaImageItr->p[SC_RG])
00899           {
00900             *iBiasH1 = betaImg[SC_BY];
00901             *iBiasH2 = betaImg[SC_BY];
00902             *iBiasS  = betaImg[SC_BY];
00903           }
00904           else
00905           {
00906             *iBiasH1 = betaImg[SC_RG];
00907             *iBiasH2 = betaImg[SC_RG];
00908             *iBiasS  = betaImg[SC_RG];
00909           }
00910         }
00911       }
00912       // Bias Value by the max of all feature types
00913       FLOAT newVal = 0;
00914       for(ushort i = 0; i < SC_MAX_CHANNELS; i++)
00915       {
00916         if(betaImg[i] > newVal && itsUseConspicMap[i])
00917           newVal = betaImg[i];
00918       }
00919       *iBiasV = newVal;
00920     }
00921   }
00922   else
00923   {
00924     iBiasH1 = itsLocalBiasH1.beginw();
00925     iBiasH2 = itsLocalBiasH2.beginw();
00926     iBiasS  = itsLocalBiasS.beginw();
00927     iBiasV  = itsLocalBiasV.beginw();
00928 
00929     for(typename Image<BETATYPE>::const_iterator betaImageItr =
00930           itsBetaCurrent->begin(); betaImageItr != itsBetaCurrent->end();
00931         ++betaImageItr,
00932           ++iBiasH1, ++iBiasH2, ++iBiasS, ++iBiasV)
00933     {
00934       // compute the surprise bias combinations with the axis bias
00935       /* If we use max level then surprise removal is scaled by the max
00936          level of all conspicuity maps, this limits reduction to be no more
00937          than the highest conspicuity map and prevents to much application
00938          at certian locations. However, it may not scale properly
00939       */
00940 
00941       const FLOAT *betaImg = betaImageItr->p;
00942       // get the surprise biases smoothed
00943       // First bias by each feature type if we have it
00944       if(itsUseConspicMap[SC_H1])
00945       {
00946         *iBiasH1 = betaImg[SC_H1];
00947         *iBiasH2 = betaImg[SC_H2];
00948         *iBiasS  = betaImg[SC_HS];
00949         *iBiasV  = betaImg[SC_HV];
00950       }
00951       else
00952       {
00953         if(itsUseConspicMap[SC_BY])
00954         {
00955           *iBiasH1 = (betaImg[SC_BY] + betaImg[SC_RG]);
00956           *iBiasH2 = (betaImg[SC_BY] + betaImg[SC_RG]);
00957           *iBiasS  = (betaImg[SC_BY] + betaImg[SC_RG]);
00958           *iBiasV  = (betaImg[SC_BY] + betaImg[SC_RG]);
00959         }
00960 
00961         if(itsUseConspicMap[SC_IN])
00962           *iBiasV  += betaImg[SC_IN];
00963       }
00964 
00965       if(itsUseConspicMap[SC_FL])
00966         *iBiasV  += betaImg[SC_FL];
00967       if(itsUseConspicMap[SC_DR0])
00968         *iBiasV  += betaImg[SC_DR0] + betaImg[SC_DR1] +
00969                     betaImg[SC_DR2] + betaImg[SC_DR3];
00970       if(itsUseConspicMap[SC_GA0])
00971         *iBiasV  += betaImg[SC_GA0] + betaImg[SC_GA1] +
00972                     betaImg[SC_GA2] + betaImg[SC_GA3];
00973     }
00974   }
00975 
00976   if(itsNormalizeBiasWithScale)
00977   {
00978     FLOAT miH1, maH1, miH2, maH2, miS, maS, miV, maV;
00979     FLOAT fmaxH1, fmaxH2, fmaxS, fmaxV;
00980     getMinMax(itsLocalBiasH1,miH1,maH1);
00981     getMinMax(itsLocalBiasH2,miH2,maH2);
00982     getMinMax(itsLocalBiasS, miS, maS);
00983     getMinMax(itsLocalBiasV, miV, maV);
00984 
00985     // normalize but maintain relative scale between H1,H2,S and V
00986 
00987     if((maH1 > maH2) && (maH1 > maS) && (maH1 > maV))
00988     {
00989       const FLOAT adj = 1.0 / maH1;
00990       fmaxH1 = 1.0;
00991       fmaxH2 = maH2 * adj;
00992       fmaxS  = maS  * adj;
00993       fmaxV  = maV  * adj;
00994     }
00995     else if((maH2 > maS) && (maH2 > maV))
00996     {
00997       const FLOAT adj = 1.0 / maH2;
00998       fmaxH2 = 1.0;
00999       fmaxH1 = maH1 * adj;
01000       fmaxS  = maS  * adj;
01001       fmaxV  = maV  * adj;
01002     }
01003     else if(maS > maV)
01004     {
01005       const FLOAT adj = 1.0 / maS;
01006       fmaxS  = 1.0;
01007       fmaxH1 = maH1 * adj;
01008       fmaxH2 = maH2 * adj;
01009       fmaxV  = maV  * adj;
01010     }
01011     else
01012     {
01013       const FLOAT adj = 1.0 / maV;
01014       fmaxV  = 1.0;
01015       fmaxH1 = maH1 * adj;
01016       fmaxH2 = maH2 * adj;
01017       fmaxS  = maS  * adj;
01018     }
01019 
01020     for(iBiasH1 = itsLocalBiasH1.beginw(); iBiasH1 != itsLocalBiasH1.endw();
01021         ++iBiasH1)
01022     {
01023       *iBiasH1 = ((*iBiasH1 - miH1) / (maH1 - miH1)) * fmaxH1;
01024     }
01025 
01026     for(iBiasH2 = itsLocalBiasH2.beginw(); iBiasH2 != itsLocalBiasH2.endw();
01027         ++iBiasH2)
01028     {
01029       *iBiasH2 = ((*iBiasH2 - miH2) / (maH2 - miH2)) * fmaxH2;
01030     }
01031 
01032     for(iBiasS  = itsLocalBiasS.beginw();  iBiasS  != itsLocalBiasS.endw();
01033         ++iBiasS)
01034     {
01035       *iBiasS  = ((*iBiasS  - miS)  / (maS  - miS))  * fmaxS;
01036     }
01037 
01038     for(iBiasV  = itsLocalBiasV.beginw();  iBiasV  != itsLocalBiasV.endw();
01039         ++iBiasV)
01040     {
01041       *iBiasV  = ((*iBiasV  - miV)  / (maV  - miV))  * fmaxV;
01042     }
01043   }
01044 
01045   // put in the final bias over each channel
01046 
01047   for(iBiasH1 = itsLocalBiasH1.beginw(); iBiasH1 != itsLocalBiasH1.endw();
01048       ++iBiasH1)
01049   {
01050     *iBiasH1 = itsH1Bias * *iBiasH1;
01051   }
01052 
01053   for(iBiasH2 = itsLocalBiasH2.beginw(); iBiasH2 != itsLocalBiasH2.endw();
01054       ++iBiasH2)
01055   {
01056     *iBiasH2 = itsH2Bias * *iBiasH2;
01057   }
01058 
01059   for(iBiasS  = itsLocalBiasS.beginw();  iBiasS  != itsLocalBiasS.endw();
01060       ++iBiasS)
01061   {
01062     *iBiasS  = itsSBias * *iBiasS;
01063   }
01064 
01065   for(iBiasV  = itsLocalBiasV.beginw();  iBiasV  != itsLocalBiasV.endw();
01066       ++iBiasV)
01067   {
01068     *iBiasV  = itsVBias * *iBiasV;
01069   }
01070 
01071   if(SC_DEBUG)
01072   {
01073     char name[100];
01074     sprintf(name,"debug-biasParts-H1-%d-%d.png",itsScale,itsIterCounter);
01075     std::string prefix    = name;
01076     Image<PixRGB<FLOAT> > temp =
01077       normalizeScaleRainbow(itsLocalBiasH1,0,5);
01078     Raster::WriteRGB(temp, prefix);
01079 
01080     sprintf(name,"debug-biasParts-H2-%d-%d.png",itsScale,itsIterCounter);
01081     prefix    = name;
01082     temp = normalizeScaleRainbow(itsLocalBiasH2,0,5);
01083     Raster::WriteRGB(temp, prefix);
01084 
01085     sprintf(name,"debug-biasParts-S-%d-%d.png",itsScale,itsIterCounter);
01086     prefix    = name;
01087     temp = normalizeScaleRainbow(itsLocalBiasS,0,5);
01088     Raster::WriteRGB(temp, prefix);
01089 
01090     sprintf(name,"debug-biasParts-V-%d-%d.png",itsScale,itsIterCounter);
01091     prefix    = name;
01092     temp = normalizeScaleRainbow(itsLocalBiasV,0,5);
01093     Raster::WriteRGB(temp, prefix);
01094   }
01095 }
01096 
01097 /*************************************************************************/
01098 
01099 template <class PIXTYPE, class BETATYPE, class FLOAT>
01100 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCseperateConvXYZ()
01101 {
01102   SCseperateConv('z');
01103   SCseperateConv('y');
01104   SCseperateConv('x');
01105 }
01106 
01107 /*************************************************************************/
01108 
01109 template <class PIXTYPE, class BETATYPE, class FLOAT>
01110 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCseperateConvXY()
01111 {
01112   // skip over the z layer convolution and start at y
01113   // we need to set the starting point where z would have left off
01114   itsInterImage[0] = *itsFrameCurrent;
01115   SCseperateConv('y');
01116   SCseperateConv('x');
01117 }
01118 
01119 /*************************************************************************/
01120 
01121 template <class PIXTYPE, class BETATYPE, class FLOAT>
01122 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCseperateConv(const char axis)
01123 {
01124   const typename std::deque<Image<PIXTYPE > >::const_iterator
01125     frameBufferBegin = itsFrameBuffer.begin();
01126   //const typename std::deque<Image<PIXTYPE > >::const_iterator
01127   //  frameBufferEnd   = itsFrameBuffer.end();
01128 
01129   typename Image<PIXTYPE >::iterator       outImageItr;
01130   typename Image<PIXTYPE >::iterator       outImageBegin;
01131   typename Image<PIXTYPE >::iterator       outImageEnd;
01132   typename Image<PIXTYPE >::const_iterator inImageItr;
01133   typename Image<PIXTYPE >::const_iterator inImageTrueItr;
01134 
01135   Image<ushort>::const_iterator      itsStartItr;
01136   Image<ushort>::const_iterator      itsStopItr;
01137   Image<ushort>::const_iterator      itsKStartItr;
01138 
01139   typename std::deque<Image<PIXTYPE > >::const_iterator frameBufferItr;
01140   typename std::vector<FLOAT>::const_iterator           kalmanKernelbegin;
01141   FLOAT axisBias;
01142 
01143   if(axis == 'z')
01144   {
01145     //inImageItr        = itsInImage.beginw();
01146     // Pick the image in the middle of the frame buffer
01147     // We use floor so that it points to an array index which starts at 0
01148     inImageItr        = itsFrameCurrent->begin();
01149     outImageBegin     = itsInterImage[0].beginw();
01150     outImageEnd       = itsInterImage[0].endw();
01151     itsStartItr       = itsZStart.begin();
01152     itsStopItr        = itsZStop.begin();
01153     itsKStartItr      = itsKZStart.begin();
01154     kalmanKernelbegin = itsKalmanKernelZ.begin();
01155     axisBias          = itsZBias;
01156   }
01157   else if(axis == 'y')
01158   {
01159     // blank the output image
01160     inImageItr        = itsInterImage[0].begin();
01161     outImageBegin     = itsInterImage[1].beginw();
01162     outImageEnd       = itsInterImage[1].endw();
01163     itsStartItr       = itsYStart.begin();
01164     itsStopItr        = itsYStop.begin();
01165     itsKStartItr      = itsKYStart.begin();
01166     kalmanKernelbegin = itsKalmanKernelY.begin();
01167     axisBias          = itsYBias;
01168   }
01169   else if(axis == 'x')
01170   {
01171     inImageItr        = itsInterImage[1].begin();
01172     outImageBegin     = itsOutImage.beginw();
01173     outImageEnd       = itsOutImage.endw();
01174     itsStartItr       = itsXStart.begin();
01175     itsStopItr        = itsXStop.begin();
01176     itsKStartItr      = itsKXStart.begin();
01177     kalmanKernelbegin = itsKalmanKernelX.begin();
01178     axisBias          = itsXBias;
01179   }
01180   else
01181   {
01182     LINFO("Must use axis as z,x then y in that order");
01183     LFATAL("Unknown axis specified %c",axis);
01184     // put values here to make to compiler shut the %*&! up
01185     inImageItr        = itsInterImage[1].begin();
01186     outImageBegin     = itsOutImage.beginw();
01187     outImageEnd       = itsOutImage.endw();
01188     itsStartItr       = itsXStart.begin();
01189     itsStopItr        = itsXStop.begin();
01190     itsKStartItr      = itsKXStart.begin();
01191     kalmanKernelbegin = itsKalmanKernelX.begin();
01192     axisBias          = itsXBias;
01193   }
01194 
01195   // blank the output image and the norm image
01196   for(outImageItr = outImageBegin; outImageItr != outImageEnd; ++outImageItr)
01197   {
01198     outImageItr->p[0]     = 0.0F;
01199     outImageItr->p[1]     = 0.0F;
01200     outImageItr->p[2]     = 0.0F;
01201     outImageItr->p[3]     = 0.0F;
01202   }
01203 
01204   typename Image<FLOAT>::const_iterator iBiasH1 = itsLocalBiasH1.begin();
01205   typename Image<FLOAT>::const_iterator iBiasH2 = itsLocalBiasH2.begin();
01206   typename Image<FLOAT>::const_iterator iBiasS  = itsLocalBiasS.begin();
01207   typename Image<FLOAT>::const_iterator iBiasV  = itsLocalBiasV.begin();
01208 
01209   inImageTrueItr = itsFrameCurrent->begin();
01210   // We have the biases now convolve by the biases
01211 
01212   int      pos = 0;
01213   ushort Zstop = 0;
01214 
01215   if(axis == 'z')
01216   {
01217     if(itsFrameBuffer.size() > itsKernelSizeZ)
01218       Zstop = itsKernelSizeZ;
01219     else
01220       Zstop = itsFrameBuffer.size();
01221   }
01222 
01223   for(outImageItr  = outImageBegin;
01224       outImageItr != outImageEnd; pos++,
01225         ++outImageItr, ++inImageItr,
01226         ++itsStartItr, ++itsStopItr, ++itsKStartItr, ++inImageTrueItr,
01227         ++iBiasH1, ++iBiasH2, ++iBiasS, ++iBiasV)
01228   {
01229 
01230     //LINFO("POS %d",pos);
01231     FLOAT npixH1 = 0.0F;
01232     FLOAT npixH2 = 0.0F;
01233     FLOAT npixS  = 0.0F;
01234     FLOAT npixV  = 0.0F;
01235 
01236     const FLOAT H1bias = *iBiasH1 * axisBias;
01237     const FLOAT H2bias = *iBiasH2 * axisBias;
01238     const FLOAT Sbias  = *iBiasS  * axisBias;
01239     const FLOAT Vbias  = *iBiasV  * axisBias;
01240 
01241     ushort start,stop;
01242 
01243     if(axis == 'z')
01244     {
01245       start = 0;
01246       stop  = Zstop;
01247     }
01248     else
01249     {
01250       start = *itsStartItr;
01251       stop  = *itsStopItr;
01252     }
01253 
01254     // figure out where we are in the image and the kernel
01255     frameBufferItr                 = frameBufferBegin;
01256 
01257     int posMod = 0;
01258     if(axis == 'y')
01259       posMod = pos%itsImageSizeX;
01260     else if(axis == 'x')
01261       posMod = pos/itsImageSizeX;
01262 
01263     typename std::vector<FLOAT>::const_iterator k = kalmanKernelbegin +
01264                                                       (*itsKStartItr);
01265 
01266     // iterate over the kernel
01267     for(ushort i = start; i < stop; i++, ++k)
01268     {
01269       // get the current other pixel x,y,z
01270       PIXTYPE curr;
01271       if(axis == 'z')
01272       {
01273         curr = frameBufferItr->getVal(pos);
01274         frameBufferItr++;
01275       }
01276       else if(axis == 'y')
01277         curr = itsInterImage[0].getVal(posMod,i);
01278       else
01279         curr = itsInterImage[1].getVal(i,posMod);
01280 
01281       // if other pixel is to dim, don't use its color
01282       // this avoids H2SV (and HSV) singularities at black for hue
01283 
01284       if(curr.p[3] > SC_NEAR_BLACK)
01285       {
01286         const FLOAT H1      = (*k)      * H1bias * curr.p[2];
01287         outImageItr->p[0]  += curr.p[0] * H1;
01288         npixH1             += H1;
01289 
01290         const FLOAT H2      = (*k)      * H2bias * curr.p[2];
01291         outImageItr->p[1]  += curr.p[1] * H2;
01292         npixH2             += H2;
01293       }
01294 
01295       // saturation is biased by color, intensity,
01296       // orientation and motion
01297       const FLOAT S       = (*k)       * Sbias;
01298       outImageItr->p[2]  += curr.p[2]  * S;
01299       npixS              += S;
01300 
01301       const FLOAT V       = (*k)       * Vbias;
01302       outImageItr->p[3]  += curr.p[3]  * V;
01303       npixV              += V;
01304     }
01305 
01306     // accumulate the normalization
01307 
01308     // at x, the final iteration normalize the final image
01309     if(axis == 'x')
01310     {
01311       // add in the original image to average (in a sense) with the
01312       // blurred image
01313       outImageItr->p[0] += inImageTrueItr->p[0] * itsOriginalImageWeight;
01314       outImageItr->p[1] += inImageTrueItr->p[1] * itsOriginalImageWeight;
01315       outImageItr->p[2] += inImageTrueItr->p[2] * itsOriginalImageWeight;
01316       outImageItr->p[3] += inImageTrueItr->p[3] * itsOriginalImageWeight;
01317 
01318       npixH1 += itsOriginalImageWeight;
01319       npixH2 += itsOriginalImageWeight;
01320       npixS  += itsOriginalImageWeight;
01321       npixV  += itsOriginalImageWeight;
01322     }
01323     if(npixH1 != 0)
01324       outImageItr->p[0] = outImageItr->p[0]/npixH1;
01325     if(npixH2 != 0)
01326       outImageItr->p[1] = outImageItr->p[1]/npixH2;
01327     if(npixS != 0)
01328       outImageItr->p[2] = outImageItr->p[2]/npixS;
01329     if(npixV != 0)
01330       outImageItr->p[3] = outImageItr->p[3]/npixV;
01331   }
01332 
01333   // clamp just in case to at least 0
01334   if(axis == 'x')
01335   {
01336     if(outImageItr->p[0] < 0)
01337       outImageItr->p[0] = 0;
01338     if(outImageItr->p[1] < 0)
01339       outImageItr->p[1] = 0;
01340     if(outImageItr->p[2] < 0)
01341       outImageItr->p[2] = 0;
01342     if(outImageItr->p[3] < 0)
01343       outImageItr->p[3] = 0;
01344   }
01345 }
01346 
01347 
01348 /*************************************************************************/
01349 
01350 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
01351 Image<PixRGB<FLOAT> > SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCgetSharpened(
01352                                                    const PIXTYPE scale_factor)
01353   const
01354 {
01355   if(itsOutputReady)
01356   {
01357     const Image<PIXTYPE> fbuffer  = *itsFrameCurrent;
01358 
01359     // get img 1 - img 2 as a difference image
01360     const Image<PIXTYPE> diffimg  = fbuffer - itsOutImage;
01361 
01362     // add back the original with a scaling factor
01363     Image<PIXTYPE> finalimg;
01364     finalimg.resize(fbuffer.getWidth(), fbuffer.getHeight());
01365 
01366 
01367     // clamp values just in case
01368     typename Image<PIXTYPE>::const_iterator dimg = diffimg.begin();
01369     typename Image<PIXTYPE>::const_iterator fimg = fbuffer.begin();
01370 
01371     typename Image<FLOAT>::const_iterator iBiasH1 = itsLocalBiasH1.begin();
01372     typename Image<FLOAT>::const_iterator iBiasH2 = itsLocalBiasH2.begin();
01373     typename Image<FLOAT>::const_iterator iBiasS  = itsLocalBiasS.begin();
01374     typename Image<FLOAT>::const_iterator iBiasV  = itsLocalBiasV.begin();
01375 
01376     for(typename Image<PIXTYPE>::iterator aptr = finalimg.beginw();
01377         aptr != finalimg.endw();
01378         ++aptr, ++dimg, ++fimg , ++iBiasH1, ++iBiasH2, ++iBiasS, ++iBiasV)
01379     {
01380       aptr->p[0] = ((dimg->p[0] * scale_factor.p[0] * *iBiasH1) + fimg->p[0]);
01381       if(aptr->p[0] > 1) aptr->p[0] = 1;
01382       aptr->p[1] = ((dimg->p[1] * scale_factor.p[1] * *iBiasH2) + fimg->p[1]);
01383       if(aptr->p[1] > 1) aptr->p[1] = 1;
01384       aptr->p[2] = ((dimg->p[2] * scale_factor.p[2] * *iBiasS) + fimg->p[2]);
01385       if(aptr->p[2] > 1) aptr->p[2] = 1;
01386       aptr->p[3] = ((dimg->p[3] * scale_factor.p[3] * *iBiasV) + fimg->p[3]);
01387       if(aptr->p[3] > 1) aptr->p[3] = 1;
01388     }
01389 
01390     return static_cast<Image<PixRGB<FLOAT> > >(finalimg);
01391   }
01392   else
01393   {
01394     Image<PixRGB<FLOAT> > blank; blank.resize(itsImageSizeX,itsImageSizeY);
01395     typename Image<PixRGB<FLOAT> >::iterator ib = blank.beginw();
01396 
01397     PixRGB<FLOAT>bp = PixRGB<FLOAT>(0,0,0);
01398 
01399     while(ib != blank.endw()) {*ib = bp; ++ib;}
01400 
01401     return blank;
01402   }
01403 }
01404 
01405 /*************************************************************************/
01406 
01407 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
01408 Image<PixRGB<FLOAT> > SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCgetFrame()
01409 const
01410 {
01411   if(itsOutputReady)
01412   {
01413     return itsFinalImage;
01414   }
01415   else
01416   {
01417     Image<PixRGB<FLOAT> > blank; blank.resize(itsImageSizeX,itsImageSizeY);
01418     typename Image<PixRGB<FLOAT> >::iterator ib = blank.beginw();
01419 
01420     PixRGB<FLOAT>bp = PixRGB<FLOAT>(0,0,0);
01421 
01422     while(ib != blank.endw()) {*ib = bp; ++ib;}
01423 
01424     return blank;
01425   }
01426 }
01427 
01428 /*************************************************************************/
01429 
01430 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
01431 Image<PixRGB<FLOAT> > SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCgetOutImage()
01432 const
01433 {
01434   Image<PixRGB<FLOAT> > returnImage;
01435   returnImage.resize(itsOutImage.getWidth(),itsOutImage.getHeight());
01436   typename Image<PixRGB<FLOAT> >::iterator returnImageItr =
01437     returnImage.beginw();
01438   typename Image<PIXTYPE>::const_iterator outImageItr =
01439     itsOutImage.begin();
01440   while(returnImageItr != returnImage.endw())
01441   {
01442     *returnImageItr = PixRGB<FLOAT>(*outImageItr);
01443     ++returnImageItr; ++outImageItr;
01444   }
01445 
01446   return returnImage;
01447 }
01448 
01449 /*************************************************************************/
01450 
01451 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
01452 Image<PixRGB<FLOAT> > SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCgetInImage()
01453 const
01454 {
01455   if(itsOutputReady)
01456   {
01457     Image<PixRGB<FLOAT> > returnImage;
01458     const Image<PIXTYPE> fbuffer = *itsFrameCurrent;
01459     returnImage.resize(itsFrameCurrent->getWidth(),
01460                        itsFrameCurrent->getHeight());
01461     typename Image<PixRGB<FLOAT> >::iterator returnImageItr =
01462       returnImage.beginw();
01463     typename Image<PIXTYPE>::const_iterator inImageItr = fbuffer.begin();
01464 
01465     while(returnImageItr != returnImage.endw())
01466     {
01467       *returnImageItr = PixRGB<FLOAT>(*inImageItr);
01468       ++returnImageItr; ++inImageItr;
01469     }
01470     return returnImage;
01471   }
01472   else
01473   {
01474     Image<PixRGB<FLOAT> > blank; blank.resize(itsImageSizeX,itsImageSizeY);
01475     typename Image<PixRGB<FLOAT> >::iterator ib = blank.beginw();
01476 
01477     PixRGB<FLOAT>bp = PixRGB<FLOAT>(0,0,0);
01478 
01479     while(ib != blank.endw()) {*ib = bp; ++ib;}
01480 
01481     return blank;
01482   }
01483 }
01484 /*************************************************************************/
01485 
01486 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
01487 Image<PIXTYPE> SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCgetRawOutImage() const
01488 {
01489   return itsOutImage;
01490 }
01491 
01492 /*************************************************************************/
01493 
01494 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
01495 Image<PIXTYPE> SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCgetRawInImage() const
01496 {
01497   if(itsOutputReady)
01498   {
01499     return *itsFrameCurrent;
01500   }
01501   else
01502   {
01503     Image<PIXTYPE> blank; blank.resize(itsImageSizeX,itsImageSizeY);
01504     typename Image<PIXTYPE>::iterator ib = blank.beginw();
01505 
01506     PIXTYPE bp = PIXTYPE(0,0,0,0);
01507     while(ib != blank.endw()) {*ib = bp; ++ib;}
01508 
01509     return blank;
01510   }
01511 }
01512 
01513 /*************************************************************************/
01514 
01515 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
01516 Image<BETATYPE> SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCgetBetaImage() const
01517 {
01518   if(itsOutputReady)
01519   {
01520     return *itsBetaCurrent;
01521   }
01522   else
01523   {
01524     Image<BETATYPE> blank; blank.resize(itsImageSizeX,itsImageSizeY);
01525     typename Image<BETATYPE>::iterator ib = blank.beginw();
01526 
01527     PixHyper<FLOAT,SC_MAX_CHANNELS> bp = PixHyper<FLOAT,SC_MAX_CHANNELS>(0);
01528 
01529     while(ib != blank.endw()) {*ib = bp; ++ib;}
01530 
01531     return blank;
01532   }
01533 }
01534 
01535 /*************************************************************************/
01536 
01537 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
01538 ushort SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCgetTemporalOffset() const
01539 {
01540   return itsTemporalOffset;
01541 }
01542 
01543 /*************************************************************************/
01544 
01545 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
01546 bool SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCisOutputReady() const
01547 {
01548   return itsOutputReady;
01549 }
01550 
01551 /*************************************************************************/
01552 
01553 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
01554 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCgetLocalBiasImages(
01555                                    Image<FLOAT> &H1, Image<FLOAT> &H2,
01556                                    Image<FLOAT> &S, Image<FLOAT>  &V) const
01557 {
01558   if(itsOutputReady)
01559   {
01560     H1 = itsLocalBiasH1; H2 = itsLocalBiasH2;
01561     S  = itsLocalBiasS;  V  = itsLocalBiasV;
01562   }
01563   else
01564   {
01565     Image<FLOAT> blank;  blank.resize(itsImageSizeX,itsImageSizeY);
01566     typename Image<FLOAT>::iterator ib = blank.beginw();
01567     FLOAT bp = 0;
01568 
01569     while(ib != blank.endw()) {*ib = bp; ++ib;}
01570 
01571     H1 = blank; H2 = blank; S = blank; V = blank;
01572   }
01573 }
01574 
01575 /*************************************************************************/
01576 
01577 template <class PIXTYPE, class BETATYPE, class FLOAT> inline
01578 void SurpriseControl<PIXTYPE,BETATYPE,FLOAT>::SCgetSeperableParts(
01579                                               Image<PIXTYPE> &Zimg,
01580                                               Image<PIXTYPE> &Yimg) const
01581 {
01582   if(itsOutputReady)
01583   {
01584     Zimg = itsInterImage[0];
01585     Yimg = itsInterImage[1];
01586   }
01587   else
01588   {
01589     Image<PIXTYPE> blank; blank.resize(itsImageSizeX,itsImageSizeY);
01590     typename Image<PIXTYPE>::iterator ib = blank.beginw();
01591 
01592     PIXTYPE bp = PIXTYPE(0,0,0,0);
01593     while(ib != blank.endw()) {*ib = bp; ++ib;}
01594 
01595     Zimg = blank; Yimg = blank;
01596   }
01597 }
01598 
01599 /*************************************************************************/
01600 
01601 template class SurpriseControl<PixH2SV1<float>,
01602                                PixHyper<float,SC_MAX_CHANNELS>,float>;
01603 template class SurpriseControl<PixH2SV2<float>,
01604                                PixHyper<float,SC_MAX_CHANNELS>,float>;
01605 
01606 #endif
Generated on Sun May 8 08:06:52 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3