00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "CUDA/CudaHmaxFL.H"
00039 #include "CUDA/CudaHmax.H"
00040 #include "CUDA/CudaFilterOps.H"
00041 #include "CUDA/CudaImage.H"
00042
00043 #include "Image/Kernels.H"
00044 #include "CUDA/CudaMathOps.H"
00045 #include "CUDA/CudaConvolutions.H"
00046 #include "Image/Normalize.H"
00047 #include "CUDA/CudaCutPaste.H"
00048 #include "Raster/Raster.H"
00049 #include "Raster/RasterFileFormat.H"
00050 #include "Util/MathFunctions.H"
00051 #include "Util/Timer.H"
00052 #include "Util/Types.H"
00053 #include "Util/log.H"
00054 #include "Util/safecopy.H"
00055
00056 #include <cmath>
00057 #include <cstdio>
00058 #include <cstdlib>
00059 #include <cfloat>
00060 #include <limits>
00061 #include <sstream>
00062 #include <stdexcept>
00063
00064
00065 CudaHmaxFL::CudaHmaxFL()
00066 { initialized = false; }
00067
00068
00069 CudaHmaxFL::CudaHmaxFL(MemoryPolicy mp, int dev, const int nori, const std::vector<int>& spacess,
00070 const std::vector<int>& scaless, const int c1spaceol,
00071 const bool angleflag, const float s2t, const float s2s,
00072 const float gamma, const float divstart, const float divstep,
00073 const int fsmin, const int fsstep)
00074 {
00075 initialized = false;
00076 init(mp,dev,nori, spacess, scaless, c1spaceol, angleflag, s2t, s2s, gamma, divstart, divstep, fsmin, fsstep);
00077 }
00078
00079
00080 void CudaHmaxFL::init(MemoryPolicy mp, int dev, const int nori, const std::vector<int>& spacess,
00081 const std::vector<int>& scaless, const int c1spaceol,
00082 const bool angleflag, const float s2t, const float s2s,
00083 const float gamma, const float divstart, const float divstep,
00084 const int fsmin, const int fsstep)
00085 {
00086 CudaHmax::init(mp,dev,nori,spacess,scaless,c1spaceol,angleflag,s2t,s2s);
00087 int curNSWB;
00088 c1Patches = 0;
00089 nswb = 0;
00090
00091 for (int sb = 0; sb < nsb; sb ++) {
00092 curNSWB = 0;
00093 for(int s = scaleSS[sb]; s < scaleSS[sb + 1]; s++) {
00094 curNSWB+=1;
00095 }
00096 nswb = std::max(nswb,curNSWB);
00097 }
00098 initFilters(gamma,divstart,divstep,fsmin,fsstep);
00099 }
00100
00101 void CudaHmaxFL::initFilters(const float gamma, const float divstart, const float divstep, const int fsmin, const int fsstep)
00102 {
00103
00104 typedef CudaImage<float>* FloatImagePtr;
00105 filter = new FloatImagePtr[ns];
00106 for(int s = 0; s < ns; s++)
00107 {
00108 filter[s] = new CudaImage<float>[no];
00109 for(int o = 0; o < no; o ++)
00110 {
00111
00112 Image<float> tmp = dogFilterHmax<float>((float)o * 180.0F / (float) no, gamma,
00113 fsmin + fsstep * s, divstart + divstep * s);
00114 filter[s][o] = CudaImage<float>(tmp,itsMp,itsDev);
00115
00116
00117
00118 filter[s][o] -= cudaGetAvg(filter[s][o]);
00119
00120
00121 filter[s][o] /= cudaSqrt(cudaGetSum(cudaSquared(filter[s][o])));
00122 }
00123 }
00124 }
00125
00126
00127 void CudaHmaxFL::freeMem()
00128 {
00129 if (initialized)
00130 {
00131 freeC1Patches();
00132 CudaHmax::freeMem();
00133 initialized = false;
00134 }
00135 }
00136
00137
00138 CudaHmaxFL::~CudaHmaxFL()
00139 { freeMem(); }
00140
00141
00142
00143 void CudaHmaxFL::freeC1Patches()
00144 {
00145 if(c1Patches != 0){
00146 for(unsigned int i=0;i<c1PatchSizes.size();i++){
00147 delete [] c1Patches[i];
00148 delete [] sumPSq[i];
00149 }
00150 delete [] c1Patches;
00151 delete [] sumPSq;
00152 c1Patches = 0;
00153 }
00154 }
00155
00156
00157 void CudaHmaxFL::setC1Patches(CudaImage<float>***&patches,std::vector<int> patchSizes,int nPatchesPerSize)
00158 {
00159 c1Patches = patches;
00160 c1PatchSizes = patchSizes;
00161 nC1PatchesPerSize = nPatchesPerSize;
00162 sumPSq = new float*[c1PatchSizes.size()];
00163 CudaImage<float> cSum(1,1,NO_INIT,itsMp,itsDev);
00164 for(unsigned int i=0;i<c1PatchSizes.size();i++)
00165 {
00166 sumPSq[i] = new float[nC1PatchesPerSize];
00167 for(int j=0;j<nC1PatchesPerSize;j++) {
00168 cSum.clear();
00169 for(int k=0;k<no;k++) {
00170 cSum += cudaGetSum(cudaSquared(patches[i][j][k]));
00171 }
00172 sumPSq[i][j] = cudaGetScalar(cSum);
00173 }
00174 }
00175 }
00176
00177 void CudaHmaxFL::writeOutC1Patches(std::string dirName)
00178 {
00179 if(c1Patches == 0){
00180 throw std::runtime_error("Cannot write out patches, patches undefined");
00181 }
00182 std::string fname;
00183 std::stringstream fnamestr;
00184 for(unsigned int i=0;i<c1PatchSizes.size();i++) {
00185 for(int j=0;j<nC1PatchesPerSize;j++) {
00186 for(int k=0;k<no;k++) {
00187 fnamestr.str("");
00188 fnamestr << dirName << C1_PATCH_FILE_NAME << "." << i << "." << j << "." << k;
00189 fname = fnamestr.str();
00190 std::cout << fname << std::endl;
00191 Raster::WriteFloat(c1Patches[i][j][k].exportToImage(),FLOAT_NORM_0_255,fname,RASFMT_PNM);
00192 }
00193 }
00194 }
00195 }
00196
00197 void CudaHmaxFL::readInC1Patches(std::string dirName)
00198 {
00199 std::string fname;
00200 std::stringstream fnamestr;
00201
00202 int i,j,k;
00203
00204
00205
00206
00207 int mi,mj,mk;
00208 Image<byte> input;
00209
00210 i=j=k=0;
00211 mi=mj=mk=0;
00212
00213 while(1){
00214 while(1){
00215 while(1){
00216 fnamestr.str("");
00217 fnamestr << dirName << C1_PATCH_FILE_NAME << "." << i << "." << j << "." << k;
00218 fname = fnamestr.str();
00219 if(Raster::fileExists(fname,RASFMT_PNM))
00220 k++;
00221 else
00222 break;
00223 }
00224 if(mk==0 && k>0){
00225 mk=k;
00226 }
00227 if(k == 0){
00228 j--;
00229 break;
00230 }
00231 else if(mk != k){
00232 throw std::runtime_error("Unexpected jagged array of patches in 3rd dimension");
00233 }
00234 else {
00235 k=0;
00236 j++;
00237 }
00238 }
00239 if(mj==0 && j>0){
00240 mj=j;
00241 }
00242 if(j<=0){
00243 i--;
00244 break;
00245 }
00246 else if(mj != j){
00247 throw std::runtime_error("Unexpected jagged array of patches in 2nd dimension");
00248 }
00249 else{
00250 j=0;
00251 i++;
00252 }
00253 }
00254 if(mi==0 && i>0){
00255 mi=i;
00256 }
00257
00258 mi+=1;
00259 mj+=1;
00260 printf("Patches of %d,%d,%d Found\n",mi,mj,mk);
00261 if(mi==0 || mj==0 || mk==0){
00262 throw std::runtime_error("No patches found");
00263 }
00264
00265 std::vector<int> patchSizes(mi);
00266
00267
00268 CudaImage<float> ***patches = new CudaImage<float>**[mi];
00269 for(i=0;i<mi;i++){
00270 patches[i] = new CudaImage<float>*[mj];
00271 for(j=0;j<mj;j++) {
00272 patches[i][j] = new CudaImage<float>[mk];
00273 }
00274 }
00275
00276 std::cout << mi << " " << mj << " " << mk << std::endl;
00277
00278
00279 int w,h;
00280 for(i=0;i<mi;i++){
00281 for(j=0;j<mj;j++){
00282 for(k=0;k<mk;k++){
00283 fnamestr.str("");
00284 fnamestr << dirName << C1_PATCH_FILE_NAME << "." << i << "." << j << "." << k;
00285 fname = fnamestr.str();
00286 input=Raster::ReadGray(fname,RASFMT_PNM);
00287 patches[i][j][k]=CudaImage<float>(Image<float>(input),itsMp,itsDev);
00288 w=patches[i][j][k].getWidth();
00289 h=patches[i][j][k].getHeight();
00290 if(w != h){
00291
00292 throw std::runtime_error("Patches are expected to be square");
00293 }
00294 if(j==0 && k==0){
00295 patchSizes[i] = w;
00296 }
00297 else if(patchSizes[i] != w){
00298
00299 throw std::runtime_error("Patches in same band should all be the same size");
00300 }
00301 }
00302 }
00303 }
00304
00305 freeC1Patches();
00306
00307 setC1Patches(patches,patchSizes,mj);
00308 }
00309
00310 CudaImage<float>***& CudaHmaxFL::getC1Patches()
00311 {
00312 return c1Patches;
00313 }
00314
00315 std::vector<int> CudaHmaxFL::getC1PatchSizes()
00316 {
00317 return c1PatchSizes;
00318 }
00319
00320 int CudaHmaxFL::getC1PatchesPerSize()
00321 {
00322 return nC1PatchesPerSize;
00323 }
00324
00325 void CudaHmaxFL::extractRandC1Patches(Image<float> *& posTrainingImages, int numPosTrainImages, std::vector<int> patchSizes, int numPatchesPerSize, int no)
00326 {
00327
00328 std::vector<int> c1ScaleSS(2);
00329 c1ScaleSS[0] = 1; c1ScaleSS[1] = 3;
00330 std::vector<int> c1SpaceSS(2);
00331 c1SpaceSS[0] = 10; c1SpaceSS[1] = 11;
00332
00333 CudaHmaxFL hmax(itsMp,itsDev,no,c1SpaceSS,c1ScaleSS,2,true,1.0F,1.0F,0.3F,4.05F,-0.05F,11,2);
00334
00335
00336 CudaImage<float> ***patches = new CudaImage<float>**[patchSizes.size()];
00337 for(unsigned int i=0;i<patchSizes.size();i++){
00338 patches[i] = new CudaImage<float>*[numPatchesPerSize];
00339 for(int j=0;j<numPatchesPerSize;j++) {
00340 patches[i][j] = new CudaImage<float>[no];
00341 for(int k=0;k<no;k++) {
00342
00343 patches[i][j][k].resize(patchSizes[i],patchSizes[i],ZEROS);
00344 }
00345 }
00346 }
00347
00348 CudaImage<float> **c1Res;
00349 CudaImage<float> stim;
00350 std::srand(time(0));
00351 int sb = 0;
00352
00353 for(int i=0;i<numPatchesPerSize;i++){
00354
00355 unsigned int imInd = static_cast<unsigned int>(floor((rand()-1.0F)/RAND_MAX*numPosTrainImages));
00356 stim = CudaImage<float>(posTrainingImages[imInd],itsMp,itsDev);
00357 hmax.initC1(c1Res);
00358 hmax.getC1(stim,c1Res);
00359
00360 int bsize1 = c1Res[sb][0].getWidth();
00361 int bsize2 = c1Res[sb][0].getHeight();
00362 hmax.printCorners("input",stim,i<5);
00363 for(unsigned int j=0;j<patchSizes.size();j++) {
00364 int xy1 = int(floor((rand()-1.0F)/RAND_MAX*(bsize1-patchSizes[j])));
00365 int xy2 = int(floor((rand()-1.0F)/RAND_MAX*(bsize2-patchSizes[j])));
00366 Rectangle r = Rectangle::tlbrI(xy2,xy1,xy2+patchSizes[j]-1,xy1+patchSizes[j]-1);
00367 for(int k=0;k<no;k++) {
00368 patches[j][i][k] = cudaCrop(c1Res[sb][k],r);
00369 patches[j][i][k] *= 255*10;
00370 }
00371 }
00372 hmax.printCorners("patch[0][i][0]",patches[0][i][0],i<5);
00373 hmax.clearC1(c1Res);
00374
00375 }
00376
00377 setC1Patches(patches,patchSizes,numPatchesPerSize);
00378
00379
00380
00381
00382
00383
00384 }
00385
00386
00387
00388 void CudaHmaxFL::windowedPatchDistance(CudaImage <float>* &images, int nimages, CudaImage <float> *& patches, int npatches, CudaImage<float>& D, float sumSquaredPatch)
00389 {
00390
00391
00392
00393
00394
00395 if(nimages != npatches) {
00396
00397 throw std::invalid_argument("Number of layers must be equal between patches and images");
00398 }
00399
00400 CudaImage<float> imSq(images[0].getWidth(),images[0].getHeight(),ZEROS,itsMp,itsDev);
00401 CudaImage<float> imSqFiltered;
00402 CudaImage<float> pi(images[0].getWidth(),images[0].getHeight(),ZEROS,itsMp,itsDev);
00403
00404
00405 int s1 = patches[0].getWidth();
00406 int s2 = patches[0].getHeight();
00407
00408 for(int i=0;i<nimages;i++) {
00409
00410
00411
00412
00413
00414
00415 imSq += cudaSquared(images[i]);
00416 }
00417
00418
00419 Rectangle sumSupport = Rectangle::tlbrI(int(ceil(s2/2)-1),int(ceil(s1/2)-1),int(floor(s2/2)),int(floor(s1/2)));
00420
00421 sumFilter(imSq,sumSupport,imSqFiltered);
00422 for(int i=0;i<nimages;i++) {
00423
00424 pi += cudaConvolve(images[i],patches[i],CONV_BOUNDARY_ZERO);
00425 }
00426
00427
00428
00429 D = imSqFiltered - (pi*2 + sumSquaredPatch + 10E-10F);
00430
00431 }
00432
00433
00434
00435 void CudaHmaxFL::getC2(const CudaImage<float>& input, float**& c2Res)
00436 {
00437 if(c1Patches == 0){
00438 throw std::runtime_error("C1Patches must be initialized before determining c2 layer response");
00439 }
00440
00441
00442
00443 CudaImage<float> **c1Res;
00444 initC1(c1Res);
00445 Timer tim;
00446 tim.reset();
00447
00448
00449
00450 getC1(input,c1Res);
00451
00452
00453
00454
00455
00456
00457 CudaImage<float> s2Res;
00458
00459
00460 for(unsigned int ps = 0; ps < c1PatchSizes.size(); ps++) {
00461 for(int pi = 0; pi <nC1PatchesPerSize; pi++) {
00462 c2Res[ps][pi] = FLT_MAX;
00463 for(int sb = 0; sb < nsb; sb++){
00464 windowedPatchDistance(c1Res[sb],no,c1Patches[ps][pi],no,s2Res,sumPSq[ps][pi]);
00465
00466 CudaImage<float> cmi;
00467 cudaGetMin(s2Res,cmi);
00468 float mi = cudaGetScalar(cmi);
00469 c2Res[ps][pi] = std::min(c2Res[ps][pi],mi);
00470 }
00471 }
00472 }
00473 printf("S2/C2 Layers %f secs\n",tim.getSecs());
00474
00475 clearC1(c1Res);
00476 }
00477
00478
00479
00480
00481
00482
00483
00484