00001 /*!@file Image/ConvolutionMap.C */ 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/Image/ConvolutionMap.C $ 00035 // $Id: ConvolutionMap.C 8631 2007-07-25 23:26:37Z rjpeters $ 00036 // 00037 00038 #include "Image/ConvolutionMap.H" 00039 00040 #include "rutz/trace.h" 00041 00042 #include <algorithm> 00043 #include <cmath> 00044 00045 // ###################################################################### 00046 template <class T> 00047 void computeConvolutionMaps(convolutionMap<T> &cMap) 00048 { 00049 GVX_TRACE(__PRETTY_FUNCTION__); 00050 cMap.CMcheckInit1(); 00051 cMap.CMinit2 = true; 00052 // Resize the static Image and attach an array 00053 unsigned int totalSize = cMap.CMorigImage.getWidth() * 00054 cMap.CMorigImage.getHeight(); 00055 00056 cMap.CMimageArrayHandle = new T[totalSize]; 00057 cMap.CMstaticImage.attach(&cMap.CMimageArrayHandle[0], 00058 cMap.CMorigImage.getWidth(), 00059 cMap.CMorigImage.getHeight()); 00060 00061 // resize convolution maps 00062 cMap.CMimageMap.resize( cMap.CMstaticImage.getWidth(), 00063 cMap.CMstaticImage.getHeight(),true); 00064 cMap.CMkernelMap.resize( cMap.CMstaticImage.getWidth(), 00065 cMap.CMstaticImage.getHeight(),true); 00066 cMap.CMindexMap.resize( cMap.CMstaticImage.getWidth(), 00067 cMap.CMstaticImage.getHeight(),true); 00068 cMap.CMkWeightNorm.resize(cMap.CMstaticImage.getWidth(), 00069 cMap.CMstaticImage.getHeight(),true); 00070 00071 // set up the offset from kernel for convolution 00072 const unsigned int imageX = 00073 (unsigned int)floor(((double)cMap.CMkernel.getWidth())/2); 00074 const unsigned int imageY = 00075 (unsigned int)floor(((double)cMap.CMkernel.getHeight())/2); 00076 00077 // initalize memory for convolution maps 00078 T zero = 0; 00079 unsigned int initVectorSize; 00080 00081 if(cMap.CMinitVecSize == 0) 00082 initVectorSize = (cMap.CMkernel.getWidth() * cMap.CMkernel.getHeight()); 00083 else 00084 initVectorSize = cMap.CMinitVecSize; 00085 00086 typename std::vector<T*> Ifiller(initVectorSize,&zero); 00087 typename std::vector<T> Tfiller(initVectorSize,0); 00088 00089 // Assign default image values for each map 00090 for(int x = 0; x < cMap.CMstaticImage.getWidth(); x++) 00091 { 00092 for(int y = 0; y < cMap.CMstaticImage.getHeight(); y++) 00093 { 00094 cMap.CMimageMap.setVal(x,y,Ifiller); 00095 cMap.CMkernelMap.setVal(x,y,Tfiller); 00096 cMap.CMkWeightNorm.setVal(x,y,0); 00097 } 00098 } 00099 00100 00101 // For each pixel in the image and the kernel 00102 for(int x = 0; x < cMap.CMstaticImage.getWidth(); x++) 00103 { 00104 for(int y = 0; y < cMap.CMstaticImage.getHeight(); y++) 00105 { 00106 for(int i = 0; i < cMap.CMkernel.getWidth(); i++) 00107 { 00108 for(int j = 0; j < cMap.CMkernel.getHeight(); j++) 00109 { 00110 // weed out any kernel elements smaller than smallNumber 00111 // We assume a gray scale kernel image 00112 if(cMap.CMkernel.getVal(i,j) > cMap.CMsmallNumber) 00113 { 00114 unsigned int Pos = y * cMap.CMimageMap.getWidth() + x; 00115 00116 // if the vector needs to be expanded because we need more elements 00117 if(cMap.CMindexMap.getVal(x,y) == cMap.CMimageMap.getVal(x,y).size()) 00118 { 00119 unsigned int m1 = cMap.CMimageMap.getVal(x,y).size() + 00120 initVectorSize; 00121 unsigned int m2 = cMap.CMkernelMap.getVal(x,y).size() + 00122 initVectorSize; 00123 cMap.CMimageMap[Pos].resize(m1,0); 00124 cMap.CMkernelMap[Pos].resize(m2,0); 00125 } 00126 int inspX = x + (i - imageX); 00127 int inspY = y + (j - imageY); 00128 // range check on X 00129 if((inspX >= 0) && (inspX < cMap.CMstaticImage.getWidth())) 00130 { 00131 // range check on Y 00132 if((inspY >= 0) && (inspY < cMap.CMstaticImage.getHeight())) 00133 { 00134 // if Ok, map other image pixel to this one 00135 cMap.CMimageMap[Pos][cMap.CMindexMap.getVal(x,y)] = 00136 &cMap.CMstaticImage[ 00137 inspY*cMap.CMstaticImage.getWidth() + inspX]; 00138 // if OK, map kernel pixel to this image pair 00139 cMap.CMkernelMap[Pos][cMap.CMindexMap.getVal(x,y)] = 00140 cMap.CMkernel.getVal(i,j); 00141 // sum the kernel values for normalization 00142 cMap.CMkWeightNorm[Pos] += cMap.CMkernel.getVal(i,j); 00143 // increment counter 00144 cMap.CMindexMap.setVal(x,y,cMap.CMindexMap.getVal(x,y) + 1); 00145 } 00146 } 00147 } 00148 } 00149 } 00150 } 00151 } 00152 } 00153 00154 // ###################################################################### 00155 template <class T> 00156 Image<T> convolveWithMaps(convolutionMap<T> &cMap) 00157 { 00158 GVX_TRACE(__PRETTY_FUNCTION__); 00159 cMap.CMcheckInit2(); 00160 // create and init a return image, set to zero. It will hold 00161 //the results of the convolution 00162 Image<T> returnImage(cMap.CMstaticImage.getWidth(), 00163 cMap.CMstaticImage.getHeight(),ZEROS); 00164 00165 // set up iterators to each important thing in convolution. 00166 // These include 00167 // (A) the image map from the static image 00168 // (B) the image map from the kernel 00169 // (C) the counter for the maps 00170 // (D) the normalization image for each pixel 00171 // (E) the clean return image 00172 00173 typename Image<std::vector<T*> >::iterator iimg = 00174 cMap.CMimageMap.beginw(); 00175 typename Image<std::vector<T> >::iterator iker = 00176 cMap.CMkernelMap.beginw(); 00177 Image<unsigned int>::iterator iindx = 00178 cMap.CMindexMap.beginw(); 00179 typename Image<T>::iterator inorm = 00180 cMap.CMkWeightNorm.beginw(); 00181 typename Image<T>::iterator iret = 00182 returnImage.beginw(); 00183 00184 typename std::vector<T*>::iterator iiimg; 00185 typename std::vector<T>::iterator iiker; 00186 00187 // For each pixel, while not at the end of the return image 00188 if(cMap.CMpreciseVectors == false) 00189 { 00190 while(iret != returnImage.endw()) 00191 { 00192 iiimg = iimg->begin(); 00193 iiker = iker->begin(); 00194 // For each item in the map at each pixel 00195 for(unsigned int z = 0; z < *iindx; z++, ++iiimg, ++iiker) 00196 { 00197 *iret = ((**iiimg) * (*iiker)) + (*iret); 00198 } 00199 // normalize the results 00200 *iret = (*iret) / (*inorm); 00201 // increment all the iterators to the next pixel 00202 ++iimg; ++iker; ++iindx; ++iret; ++inorm; 00203 } 00204 } 00205 else 00206 { 00207 while(iret != returnImage.endw()) 00208 { 00209 iiimg = iimg->begin(); 00210 iiker = iker->begin(); 00211 while(iiimg != iimg->end()) 00212 { 00213 *iret = ((**iiimg) * (*iiker)) + (*iret); 00214 ++iiimg, ++iiker; 00215 } 00216 // normalize the results 00217 *iret = (*iret) / (*inorm); 00218 // increment all the iterators to the next pixel 00219 ++iimg; ++iker; ++iindx; ++iret; ++inorm; 00220 } 00221 } 00222 return returnImage; 00223 } 00224 00225 // Include the explicit instantiations 00226 #include "inst/Image/ConvolutionMap.I" 00227 00228 // ###################################################################### 00229 /* So things look consistent in everyone's emacs... */ 00230 /* Local Variables: */ 00231 /* indent-tabs-mode: nil */ 00232 /* End: */