00001 /*!@file CUDA/CudaNorm.C C++ wrapper for CUDA normalization methods */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the 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: 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/CUDA/CudaNorm.C $ 00035 // $Id: CudaNorm.C 12962 2010-03-06 02:13:53Z irock $ 00036 // 00037 00038 #include "CUDA/CudaImage.H" 00039 #include "Util/Assert.H" 00040 #include "CUDA/cudadefs.h" 00041 #include "CUDA/CudaConvolutions.H" 00042 #include "CUDA/CudaMathOps.H" 00043 #include "CUDA/CudaShapeOps.H" 00044 #include "CUDA/CudaKernels.H" 00045 #include "Image/fancynorm.H" 00046 #include "CUDA/CudaNorm.H" 00047 #include "CudaDevices.H" 00048 #include "wrap_c_cuda.h" 00049 00050 00051 // ###################################################################### 00052 CudaImage<float> cudaMaxNormalize(const CudaImage<float>& src, 00053 const float mi, const float ma, const MaxNormType normtyp, 00054 int nbiter, const CudaImage<float> *lrexcit) 00055 { 00056 00057 // do normalization depending on desired type: 00058 switch(normtyp) 00059 { 00060 case VCXNORM_FANCY: 00061 return cudaMaxNormalizeFancy(src, mi, ma, nbiter, 1.0, lrexcit); 00062 break; 00063 default: 00064 LFATAL("Unhandled normalization type: %d", int(normtyp)); 00065 } 00066 return CudaImage<float>(); 00067 } 00068 00069 // ###################################################################### 00070 // ##### fancyNorm from Itti et al, JEI, 2001 -- FULL implementation: 00071 CudaImage<float> cudaMaxNormalizeFancy(const CudaImage<float>& src, const float mi, const float ma, 00072 const int nbiter, const float weakness, 00073 const CudaImage<float>* lrexcit) 00074 { 00075 // Normalize using fancy normalization: multiple iterations of 00076 // filtering by a DoG 00077 ASSERT(src.initialized()); 00078 ASSERT(src.getMemoryPolicy() != HOST_MEMORY); 00079 00080 MemoryPolicy mp = src.getMemoryPolicy(); 00081 int dev = src.getMemoryDevice(); 00082 const int w = src.getWidth(); 00083 const int h = src.getHeight(); 00084 int siz = std::max(w, h); 00085 int maxhw = std::max(0, std::min(w, h) / 2 - 1); 00086 00087 // Allocate max buffer so that it can be reused 00088 CudaImage<float> maxim = CudaImage<float>(1,1,NO_INIT,mp,dev); 00089 CudaImage<float> result = src; 00090 // first clamp negative values to zero 00091 cudaInplaceRectify(result); 00092 00093 // then, normalize between mi and ma if not zero 00094 if (mi != 0.0F || ma != 0.0F) cudaInplaceNormalize(result, mi, ma); 00095 00096 00097 // build separable Gaussians for DoG computation: 00098 float esig = (float(siz) * FANCYESIG) * 0.01F; 00099 float isig = (float(siz) * FANCYISIG) * 0.01F; 00100 CudaImage<float> gExc = cudaGaussian(mp,dev,FANCYCOEX/(esig*sqrt(2.0*M_PI)) * weakness, esig, maxhw); 00101 CudaImage<float> gInh = cudaGaussian(mp,dev,FANCYCOIN/(isig*sqrt(2.0*M_PI)) * weakness, isig, maxhw); 00102 00103 for (int i = 0; i < nbiter; ++i) 00104 { 00105 if (lrexcit) // tuned long-range excitation 00106 { 00107 00108 CudaImage<float> tmp = cudaDownSize(result, w / (1<<LRLEVEL), h / (1<<LRLEVEL)); 00109 tmp = cudaConvolve(tmp, *lrexcit, CONV_BOUNDARY_ZERO); // full influence 00110 tmp += 1.0F; // will be used as multiplicative excitation 00111 cudaInplaceClamp(tmp, 1.0F, 1.25F); // avoid crazyness 00112 tmp = cudaRescale(tmp, w, h); 00113 result *= tmp; 00114 } 00115 00116 CudaImage<float> excit = cudaSepFilter(result, gExc, gExc, CONV_BOUNDARY_CLEAN); // excitatory part 00117 CudaImage<float> inhib = cudaSepFilter(result, gInh, gInh, CONV_BOUNDARY_CLEAN); // inhibitory part 00118 excit -= inhib; 00119 cudaGetMax(result, maxim); 00120 00121 result += excit; // we get broad inhibition from everywhere 00122 00123 result += cudaGetScalar(maxim)*(-0.01F * FANCYINHI) ; // we get fixed global inhibition 00124 00125 cudaInplaceRectify(result); 00126 00127 // sigmoid(FANCYG, FANCYH, FANCYS); 00128 } 00129 return result; 00130 }