CudaHmax.C

Go to the documentation of this file.
00001 /*!@file CUDA/CudaHmax.C Riesenhuber & Poggio's HMAX model for object recognition */
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: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/CUDA/CudaHmax.C $
00035 // $Id: CudaHmax.C 12962 2010-03-06 02:13:53Z irock $
00036 //
00037 
00038 #include "CUDA/CudaHmax.H"
00039 
00040 #include "CUDA/CudaFilterOps.H"
00041 #include "CUDA/CudaImage.H"
00042 //#include "CUDA/CudaKernels.H"   // for cudaDogFilter()
00043 #include "Image/Image.H"
00044 #include "Image/Kernels.H"   // for dogFilter()
00045 #include "CUDA/CudaMathOps.H"
00046 #include "CUDA/CudaConvolutions.H" // for cudaConvolve() etc.
00047 #include "Image/MathOps.H"
00048 
00049 #include "Util/MathFunctions.H"
00050 #include "Util/Types.H"
00051 #include "Util/log.H"
00052 #include "Util/safecopy.H"
00053 
00054 #include <cmath>
00055 #include <fstream>
00056 #include <iostream>
00057 #include <iomanip>
00058 #include <cstdio>
00059 #include <cstdlib>
00060 #include <limits>
00061 
00062 // ######################################################################
00063 CudaHmax::CudaHmax()
00064 { initialized = false; }
00065 
00066 // ######################################################################
00067 CudaHmax::CudaHmax(MemoryPolicy mp, int dev, const int nori, const std::vector<int>& spacess,
00068            const std::vector<int>& scaless, const int c1spaceol,
00069            const bool angleflag, const float s2t, const float s2s,
00070            const float stdmin, const float stdstep,
00071            const int fsmin, const int fsstep)
00072 {
00073   initialized = false;
00074   init(mp,dev,nori, spacess, scaless, c1spaceol, angleflag, s2t, s2s);
00075   initFilters(stdmin,stdstep,fsmin,fsstep);
00076 }
00077 
00078 // ######################################################################
00079 void CudaHmax::init(MemoryPolicy mp, int dev, const int nori, const std::vector<int>& spacess,
00080                 const std::vector<int>& scaless, const int c1spaceol,
00081                 const bool angleflag, const float s2t, const float s2s)
00082 {
00083   itsMp = mp;
00084   itsDev = dev;
00085   freeMem(); initialized = true; ns = scaless[scaless.size() - 1]; no = nori;
00086   c1SpaceOL = c1spaceol; angleFlag = angleflag; s2Target = s2t; s2Sigma = s2s;
00087   spaceSS.resize(spacess.size()); scaleSS.resize(scaless.size());
00088 
00089  // detrmine number of scale bands from length of vector scaleSS:
00090   nsb = scaleSS.size() - 1;
00091 
00092   for (unsigned int i = 0; i < spacess.size(); i ++) spaceSS[i] = spacess[i];
00093   for (unsigned int i = 0; i < scaless.size(); i ++) scaleSS[i] = scaless[i];
00094 
00095 }
00096 
00097 void CudaHmax::initFilters(const float stdmin, const float stdstep, const int fsmin, const int fsstep)
00098 {
00099   // create the filters:
00100   typedef CudaImage<float>* FloatImagePtr;
00101   filter = new FloatImagePtr[ns];
00102   for(int s = 0; s < ns; s++)
00103     {
00104       filter[s] = new CudaImage<float>[no];
00105       for(int o = 0; o < no; o ++)
00106         {
00107           // create DoG filter:
00108           Image<float> tmp = dogFilter<float>(stdmin + stdstep * s,
00109                                           (float)o * 180.0F / (float)no,
00110                                           fsmin + fsstep * s);
00111           filter[s][o] = CudaImage<float>(tmp,itsMp,itsDev);
00112           // filter[s][o] = cudaDogFilter(itsMp,itsDev,stdmin + stdstep * s,
00113           //                                 (float)o * 180.0F / (float)no,
00114           //                                 fsmin + fsstep * s);
00115           // normalize to zero mean:
00116           filter[s][o] -= cudaGetAvg(filter[s][o]);
00117 
00118           // normalize to unit of sum-of-squares:
00119           filter[s][o] /= cudaGetSum(cudaSquared(filter[s][o]));
00120         }
00121     }
00122 }
00123 
00124 // ######################################################################
00125 void CudaHmax::freeMem()
00126 {
00127   if (initialized)
00128     {
00129       for(int s = 0; s < ns; s++) delete [] filter[s];
00130       delete [] filter;
00131       initialized = false;
00132     }
00133 }
00134 
00135 // ######################################################################
00136 CudaHmax::~CudaHmax()
00137 { freeMem(); }
00138 
00139 // ######################################################################
00140 std::vector<std::string> CudaHmax::readDir(std::string inName)
00141 {
00142         DIR *dp = opendir(inName.c_str());
00143         if(dp == NULL)
00144         {
00145           LFATAL("Directory does not exist %s",inName.c_str());
00146         }
00147         dirent *dirp;
00148         std::vector<std::string> fList;
00149         while ((dirp = readdir(dp)) != NULL ) {
00150                 if (dirp->d_name[0] != '.')
00151                         fList.push_back(inName + '/' + std::string(dirp->d_name));
00152         }
00153         LINFO("%"ZU" files in the directory\n", fList.size());
00154         LINFO("file list : \n");
00155         for (unsigned int i=0; i<fList.size(); i++)
00156                 LINFO("\t%s", fList[i].c_str());
00157         std::sort(fList.begin(),fList.end());
00158         return fList;
00159 }
00160 
00161 // ######################################################################
00162 std::vector<std::string> CudaHmax::readList(std::string inName)
00163 {
00164   std::ifstream inFile;
00165   inFile.open(inName.c_str(),std::ios::in);
00166   if(!inFile){
00167     LFATAL("Unable to open image path list file: %s",inName.c_str());
00168   }
00169   std::string sLine;
00170   std::vector<std::string> fList;
00171   while (std::getline(inFile, sLine)) {
00172       std::cout << sLine << std::endl;
00173       fList.push_back(sLine);
00174   }
00175   LINFO("%"ZU" paths in the file\n", fList.size());
00176   LINFO("file list : \n");
00177   for (unsigned int i=0; i<fList.size(); i++)
00178     LINFO("\t%s", fList[i].c_str());
00179   inFile.close();
00180   return fList;
00181 }
00182 
00183 
00184 
00185 
00186 // ######################################################################
00187 void CudaHmax::getC1(const CudaImage<float>& input, CudaImage<float>** &c1Res)
00188 {
00189   CudaImage<float> *c1Buff = new CudaImage<float>[no];
00190   CudaImage<float> s1Res;
00191   // loop over scale bands:
00192 
00193 
00194   for(int sb = 0; sb < nsb; sb ++) {
00195 
00196     // clear our buffers:
00197     for(int i = 0; i < no; i ++)
00198       c1Buff[i] = CudaImage<float>(input.getWidth(), input.getHeight(), ZEROS, itsMp, itsDev);;
00199 
00200     // loop over scales within current scale band:
00201     for(int s = scaleSS[sb]; s < scaleSS[sb + 1]; s++) {
00202       // loop over orientations:
00203       for(int o = 0; o < no; o ++) {
00204         // convolve image by filter at current orient & scale:
00205         if (angleFlag) {
00206           s1Res = cudaConvolveHmax(input, filter[s][o]); // normalize by image energy
00207           //printCorners("s1Res",s1Res,s==scaleSS[0]&&sb==0&&o==0);
00208         }
00209         else {
00210           s1Res = cudaConvolve(input, filter[s][o], CONV_BOUNDARY_CLEAN); // no normalization
00211           // take absolute value of the convolution result:
00212           cudaAbs(s1Res);
00213         }
00214 
00215         // take max between this convolution and previous ones for
00216         // that orientation but other scales within current scale band:
00217         c1Buff[o] = cudaTakeMax(c1Buff[o], s1Res);
00218       }
00219     }
00220 
00221     // compute RF spacing (c1R) and pool range (c1PR):
00222     int c1R = (int)ceil((float)spaceSS[sb] / (float)c1SpaceOL);
00223     int c1PR = spaceSS[sb];
00224 
00225     // pool over space for each orientation (and scale band):
00226     for(int o = 0; o < no; o ++){
00227       c1Res[sb][o] = cudaSpatialPoolMax(c1Buff[o], c1R, c1R, c1PR, c1PR);
00228       //printCorners("c1Res",c1Res[sb][o],sb==0&&o==0);
00229     }
00230 
00231   }
00232 
00233   delete [] c1Buff;
00234 }
00235 
00236 void CudaHmax::initC1(CudaImage<float> **&c1Res)
00237 {
00238   c1Res = new CudaImage<float>*[nsb];
00239   for (int sb = 0; sb < nsb; sb ++) c1Res[sb] = new CudaImage<float>[no];
00240 }
00241 
00242 void CudaHmax::clearC1(CudaImage<float> **&c1Res)
00243 {
00244    for (int sb = 0; sb < nsb; sb ++) delete [] c1Res[sb];
00245    delete [] c1Res;
00246 }
00247 
00248 void CudaHmax::printCorners(const char name[], const CudaImage<float>& cim, bool cond)
00249 {
00250   Image<float> im = cim.exportToImage();
00251   if(cond) {
00252     printf("%s\n",name);
00253     int w = im.getWidth();
00254     int h = im.getHeight();
00255     std::string s;
00256     if(w>2 && h>2) {
00257       printf("%f\t%f\t%f\t%f\t%f\n",im.getVal(0,0),im.getVal(1,0),im.getVal(2,0),im.getVal(w-2,0),im.getVal(w-1,0));
00258       printf("%f\t%f\t\t\t%f\t%f\n\n", im.getVal(0,1),im.getVal(1,1),im.getVal(w-2,1),im.getVal(w-1,1));
00259       printf("%f\t%f\t\t\t%f\t%f\n", im.getVal(0,h-2),im.getVal(1,h-2),im.getVal(w-2,h-2),im.getVal(w-1,h-2));
00260       printf("%f\t%f\t%f\t%f\t%f\n",im.getVal(0,h-1),im.getVal(1,h-1),im.getVal(2,h-1),im.getVal(w-2,h-1),im.getVal(w-1,h-1));
00261     }
00262     else if(w>1 && h>1) {
00263       printf("%f\t%f\n",im.getVal(0,0),im.getVal(1,0));
00264       printf("%f\t%f\n", im.getVal(0,1),im.getVal(1,1));
00265     }
00266     else if(w>0 && h>0){
00267       printf("%f\n",im.getVal(0,0));
00268     }
00269     std::cout << "Mean of " << name << " " << mean(im) << std::endl;
00270     std::cout << "Var of " << name << " " << (stdev(im)*stdev(im)) << std::endl;
00271     std::cout << "Width of " << w << " and height of " << h << std::endl;
00272     //float mi,ma; getMinMax(input,mi,ma);
00273     //writeOutImage(inputf,name);
00274     //std::cout << "Min " << mi << " Max " << ma << std::endl;
00275   }
00276 }
00277 
00278 void CudaHmax::writeOutImage(const CudaImage<float>& cim,std::string & fName)
00279 {
00280   std::ofstream oFile;
00281   Image<float> d;
00282   oFile.open(fName.c_str(),std::ios::out);
00283   d = cim.exportToImage();
00284   int w,h;
00285   w = d.getWidth();
00286   h = d.getHeight();
00287   for(int i=0;i<w;i++){
00288     for(int j=0;j<h;j++){
00289       oFile << d.getVal(i,j) <<" ";
00290     }
00291     if(i!=w-1)
00292       oFile << std::endl;
00293   }
00294   oFile.close();
00295 
00296 }
00297 
00298 
00299 // ######################################################################
00300 CudaImage<float> CudaHmax::getC2(const CudaImage<float>& input)
00301 {
00302 
00303   // allocate buffers for intermediary results:
00304   CudaImage<float> **c1Res;
00305   initC1(c1Res);
00306 
00307   // ******************************
00308   // *** Compute S1/C1 output:
00309   // ******************************
00310   getC1(input, c1Res);
00311 
00312   // ******************************
00313   // *** Compute S2/C2 output:
00314   // ******************************
00315   CudaImage<float> c2Res(no * no, no * no, NO_INIT,itsMp,itsDev);
00316   cudaClear(c2Res,-1.0E10F);
00317 
00318   // // detrmine number of scale bands from length of vector scaleSS:
00319   // int nsb = scaleSS.size() - 1;
00320   // int idx = 0;
00321   // // loop over four filters giving inputs to an S2 cell:
00322   // for (int f1 = 0; f1 < no; f1++)
00323   //   for (int f2 = 0; f2 < no; f2++)
00324   //     for (int f3 = 0; f3 < no; f3++)
00325   //       for (int f4 = 0; f4 < no; f4++) {
00326 
00327   //         float c2r = -1.0E10;
00328   //         // loop over scale band:
00329   //         for (int sb = 0; sb < nsb; sb ++) {
00330 
00331   //           float s2r = featurePoolHmax(c1Res[sb][f1], c1Res[sb][f2],
00332   //                                       c1Res[sb][f3], c1Res[sb][f4],
00333   //                                       c1SpaceOL, c1SpaceOL, s2Target);
00334   //           if (s2r > c2r) c2r = s2r;
00335   //         }
00336   //         c2Res.setVal(idx, c2r); idx ++;
00337   //       }
00338 
00339   // // free allocated temporary images:
00340   // clearC1(c1Res);
00341 
00342   // return hmaxActivation(c2Res, s2Sigma);
00343 
00344   LFATAL("Generic HMAX C2 Calculation not supported");
00345   return c2Res;
00346 }
00347 
00348 void CudaHmax::sumFilter(const CudaImage<float>& image, const float radius, CudaImage<float>& newImage)
00349 {
00350   Rectangle sumSupport = Rectangle::tlbrI(0,0,int(radius*2.0F),int(radius*2.0F));
00351   sumFilter(image,sumSupport,newImage);
00352 }
00353 
00354 void CudaHmax::sumFilter(const CudaImage<float>& image, const Rectangle& support, CudaImage<float>& newImage)
00355 {
00356 
00357   Dims d(support.top()+support.bottomI()+1,support.left()+support.rightI()+1);
00358   //Dims d(support.bottomI()-support.top()+1,support.rightI()-support.left()+1);
00359   CudaImage<float> a(d,NO_INIT,itsMp,itsDev);
00360   cudaClear(a,1.0F);
00361 
00362   //convolve the image with a matrix of 1's that is as big as the rectangle
00363   // This two step process is doing effectively the same thing by taking the center part of the convolution
00364   //I2 = conv2(ones(1,radius(2)+radius(4)+1), ones(radius(1)+radius(3)+1,1), I);
00365   //I3 = I2((radius(4)+1:radius(4)+size(I,1)), (radius(3)+1:radius(3)+size(I,2)));
00366   //CudaImage<float> i;
00367   //i = convolution(image,a,MATLAB_STYLE_CONVOLUTION);
00368   //Rectangle r = Rectangle::tlbrI(support.bottomI()+1,support.rightI()+1,support.bottomI()+image.getHeight(),support.rightI()+image.getWidth());
00369   //newImage = crop(i,r);
00370   // Can be done in one step
00371   newImage = cudaConvolve(image,a,CONV_BOUNDARY_ZERO);
00372 }
00373 
00374 
00375 // ######################################################################
00376 /* So things look consistent in everyone's emacs... */
00377 /* Local Variables: */
00378 /* indent-tabs-mode: nil */
00379 /* End: */
Generated on Sun May 8 08:40:36 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3