PyramidGL.cpp
Go to the documentation of this file.
00001 #pragma GCC diagnostic warning "-Wuninitialized"
00002 
00003 //      File:           PyramidGL.cpp
00004 //      Author:         Changchang Wu
00005 //      Description : implementation of PyramidGL/PyramidNaive/PyramidPackdc .
00006 //
00007 //
00008 //      Copyright (c) 2007 University of North Carolina at Chapel Hill
00009 //      All Rights Reserved
00010 //
00011 //      Permission to use, copy, modify and distribute this software and its
00012 //      documentation for educational, research and non-profit purposes, without
00013 //      fee, and without a written agreement is hereby granted, provided that the
00014 //      above copyright notice and the following paragraph appear in all copies.
00015 //      
00016 //      The University of North Carolina at Chapel Hill make no representations
00017 //      about the suitability of this software for any purpose. It is provided
00018 //      'as is' without express or implied warranty. 
00019 //
00020 //      Please send BUG REPORTS to ccwu@cs.unc.edu
00021 //
00023 
00024 #include "GL/glew.h"
00025 #include <iostream>
00026 #include <iomanip>
00027 #include <vector>
00028 #include <algorithm>
00029 #include <fstream>
00030 #include <math.h>
00031 #include <string.h>
00032 using namespace std;
00033 
00034 #include "GlobalUtil.h"
00035 #include "GLTexImage.h"
00036 #include "SiftGPU.h"
00037 #include "ShaderMan.h"
00038 #include "SiftPyramid.h"
00039 #include "ProgramGLSL.h"
00040 #include "PyramidGL.h"
00041 #include "FrameBufferObject.h"
00042 
00043 
00044 #if defined(__SSE__) || _MSC_VER > 1200
00045 #define USE_SSE_FOR_SIFTGPU
00046 #include <xmmintrin.h>
00047 #else
00048 //#pragma message( "SSE optimization off!\n" )
00049 #endif
00050 
00051 
00052 #define USE_TIMING()            double t, t0, tt;
00053 #define OCTAVE_START()          if(GlobalUtil::_timingO){       t = t0 = CLOCK();       cout<<"#"<<i+_down_sample_factor<<"\t"; }
00054 #define LEVEL_FINISH()          if(GlobalUtil::_timingL){       glFinish();     tt = CLOCK();cout<<(tt-t)<<"\t";        t = CLOCK();}
00055 #define OCTAVE_FINISH()         if(GlobalUtil::_timingO)cout<<"|\t"<<(CLOCK()-t0)<<endl;
00056 
00057 
00059 // Construction/Destruction
00061 PyramidNaive::PyramidNaive(SiftParam& sp): PyramidGL(sp)
00062 {
00063         _texPyramid = NULL;
00064         _auxPyramid = NULL;
00065 }
00066 
00067 PyramidNaive::~PyramidNaive()
00068 {
00069         DestroyPyramidData();
00070 }
00071 
00072 //align must be 2^i
00073 void PyramidGL::	GetAlignedStorageSize(int num, int align,  int &fw, int &fh)
00074 {
00075         if(num <=0)
00076         {
00077                 fw = fh = 0;
00078         }else if(num < align*align)
00079         {
00080                 fw = align;
00081                 fh = (int)ceil(double(num) / fw);
00082         }else if(GlobalUtil::_NarrowFeatureTex)
00083         {
00084                 double dn = double(num);
00085                 int nb = (int) ceil(dn/GlobalUtil::_texMaxDim/align);   
00086                 fw = align * nb;        
00087                 fh = (int)ceil(dn /fw);
00088         }else
00089         {
00090                 double dn = double(num);
00091                 int nb = (int) ceil(dn/GlobalUtil::_texMaxDim/align);
00092                 fh = align * nb;
00093                 if(nb <=1)
00094                 {
00095                         fw = (int)ceil(dn / fh);
00096                         //align this dimension to blocksize
00097                         fw = ((int) ceil(double(fw) /align))*align;
00098                 }else
00099                 {
00100                         fw = GlobalUtil::_texMaxDim;
00101                 }
00102 
00103         }
00104 
00105 
00106 }
00107 
00108 void PyramidGL::GetTextureStorageSize(int num, int &fw, int& fh)
00109 {
00110         if(num <=0)
00111         {
00112                 fw = fh = 0;
00113         }else if(num <= GlobalUtil::_FeatureTexBlock)
00114         {
00115                 fw = num;
00116                 fh = 1;
00117         }else if(GlobalUtil::_NarrowFeatureTex)
00118         {
00119                 double dn = double(num);
00120                 int nb = (int) ceil(dn/GlobalUtil::_texMaxDim/GlobalUtil::_FeatureTexBlock);    
00121                 fw = GlobalUtil::_FeatureTexBlock * nb; 
00122                 fh = (int)ceil(dn /fw);
00123         }else
00124         {
00125                 double dn = double(num);
00126                 int nb = (int) ceil(dn/GlobalUtil::_texMaxDim/GlobalUtil::_FeatureTexBlock);
00127                 fh = GlobalUtil::_FeatureTexBlock * nb;
00128                 if(nb <=1)
00129                 {
00130                         fw = (int)ceil(dn / fh);
00131 
00132                         //align this dimension to blocksize
00133 
00134                         //
00135                         if( fw < fh)
00136                         {
00137                                 int temp = fh;
00138                                 fh = fw;
00139                                 fw = temp;
00140                         }
00141                 }else
00142                 {
00143                         fw = GlobalUtil::_texMaxDim;
00144                 }
00145         }
00146 }
00147 
00148 void PyramidNaive::DestroyPyramidData()
00149 {
00150         if(_texPyramid)
00151         {
00152                 delete [] _texPyramid;
00153                 _texPyramid = NULL;
00154         }
00155         if(_auxPyramid)
00156         {
00157                 delete [] _auxPyramid;  
00158                 _auxPyramid = NULL;
00159         }
00160 }
00161 PyramidGL::PyramidGL(SiftParam &sp):SiftPyramid(sp)
00162 {
00163         _featureTex = NULL;
00164         _orientationTex = NULL;
00165         _descriptorTex = NULL;
00166         _histoPyramidTex = NULL;        
00168     InitializeContext();
00169 }
00170 
00171 PyramidGL::~PyramidGL()
00172 {
00173         DestroyPerLevelData();
00174         DestroySharedData();
00175         ShaderMan::DestroyShaders();
00176 }
00177 
00178 void PyramidGL::InitializeContext()
00179 {
00180     GlobalUtil::InitGLParam(0);
00181     if(!GlobalUtil::_GoodOpenGL) return;
00182 
00184         ShaderMan::InitShaderMan(param);
00185 }
00186 
00187 void PyramidGL::DestroyPerLevelData()
00188 {
00189         //integers vector to store the feature numbers.
00190         if(_levelFeatureNum)
00191         {
00192                 delete [] _levelFeatureNum;
00193                 _levelFeatureNum = NULL;
00194         }
00195         //texture used to store features
00196         if(     _featureTex)
00197         {
00198                 delete [] _featureTex;
00199                 _featureTex =   NULL;
00200         }
00201         //texture used for multi-orientation 
00202         if(_orientationTex)
00203         {
00204                 delete [] _orientationTex;
00205                 _orientationTex = NULL;
00206         }
00207         int no = _octave_num* param._dog_level_num;
00208 
00209         //two sets of vbos used to display the features
00210         if(_featureDisplayVBO)
00211         {
00212                 glDeleteBuffers(no, _featureDisplayVBO);
00213                 delete [] _featureDisplayVBO;
00214                 _featureDisplayVBO = NULL;
00215         }
00216         if( _featurePointVBO)
00217         {
00218                 glDeleteBuffers(no, _featurePointVBO);
00219                 delete [] _featurePointVBO;
00220                 _featurePointVBO = NULL;
00221         }
00222 
00223 }
00224 
00225 void PyramidGL::DestroySharedData()
00226 {
00227         //histogram reduction
00228         if(_histoPyramidTex)
00229         {
00230                 delete[]        _histoPyramidTex;
00231                 _hpLevelNum = 0;
00232                 _histoPyramidTex = NULL;
00233         }
00234 
00235         //descriptor storage shared by all levels
00236         if(_descriptorTex)
00237         {
00238                 delete [] _descriptorTex;
00239                 _descriptorTex = NULL;
00240         }
00241         //cpu reduction buffer.
00242         if(_histo_buffer)
00243         {
00244                 delete[] _histo_buffer;
00245                 _histo_buffer = 0;
00246         }
00247 }
00248 
00249 void PyramidNaive::FitHistogramPyramid()
00250 {
00251         GLTexImage * tex, *htex;
00252         int hist_level_num = _hpLevelNum - _pyramid_octave_first; 
00253 
00254         tex = GetBaseLevel(_octave_min , DATA_KEYPOINT) + 2;
00255         htex = _histoPyramidTex + hist_level_num - 1;
00256         int w = tex->GetImgWidth() >> 1;
00257         int h = tex->GetImgHeight() >> 1;
00258 
00259         for(int k = 0; k <hist_level_num -1; k++, htex--)
00260         {
00261                 if(htex->GetImgHeight()!= h || htex->GetImgWidth() != w)
00262                 {       
00263                         htex->SetImageSize(w, h);
00264                         htex->ZeroHistoMargin();
00265                 }
00266 
00267                 w = (w + 1)>>1; h = (h + 1) >> 1;
00268         }
00269 }
00270 
00271 void PyramidNaive::FitPyramid(int w, int h)
00272 {
00273         //(w, h) <= (_pyramid_width, _pyramid_height);
00274 
00275         _pyramid_octave_first = 0;
00276         //
00277         _octave_num  = GlobalUtil::_octave_num_default;
00278 
00279         int _octave_num_max = GetRequiredOctaveNum(min(w, h));
00280 
00281         if(_octave_num < 1 || _octave_num > _octave_num_max) 
00282         {
00283                 _octave_num = _octave_num_max;
00284         }
00285 
00286 
00287         int pw = _pyramid_width>>1, ph = _pyramid_height>>1;
00288         while(_pyramid_octave_first + _octave_num < _pyramid_octave_num &&  
00289                 pw >= w && ph >= h)
00290         {
00291                 _pyramid_octave_first++;
00292                 pw >>= 1;
00293                 ph >>= 1;
00294         }
00295 
00296         for(int i = 0; i < _octave_num; i++)
00297         {
00298                 GLTexImage * tex = GetBaseLevel(i + _octave_min);
00299                 GLTexImage * aux = GetBaseLevel(i + _octave_min, DATA_KEYPOINT);
00300                 for(int j = param._level_min; j <= param._level_max; j++, tex++, aux++)
00301                 {
00302                         tex->SetImageSize(w, h);
00303                         aux->SetImageSize(w, h);
00304                 }
00305                 w>>=1;
00306                 h>>=1;
00307         }
00308 }
00309 void PyramidNaive::InitPyramid(int w, int h, int ds)
00310 {
00311         int wp, hp, toobig = 0;
00312         if(ds == 0)
00313         {
00314                 _down_sample_factor = 0;
00315                 if(GlobalUtil::_octave_min_default>=0)
00316                 {
00317                         wp = w >> GlobalUtil::_octave_min_default;
00318                         hp = h >> GlobalUtil::_octave_min_default;
00319                 }else 
00320                 {
00321                         wp = w << (-GlobalUtil::_octave_min_default);
00322                         hp = h << (-GlobalUtil::_octave_min_default);
00323                 }
00324                 _octave_min = _octave_min_default;
00325         }else
00326         {
00327                 //must use 0 as _octave_min; 
00328                 _octave_min = 0;
00329                 _down_sample_factor = ds;
00330                 w >>= ds;
00331                 h >>= ds;
00332                 wp = w;
00333                 hp = h; 
00334 
00335         }
00336 
00337         while(wp > GlobalUtil::_texMaxDim || hp > GlobalUtil::_texMaxDim)
00338         {
00339                 _octave_min ++;
00340                 wp >>= 1;
00341                 hp >>= 1;
00342                 toobig = 1;
00343         }
00344 
00345         while(GlobalUtil::_MemCapGPU > 0 && GlobalUtil::_FitMemoryCap  && (wp >_pyramid_width || hp > _pyramid_height) &&
00346                 max(max(wp, hp), max(_pyramid_width, _pyramid_height)) >  1024 * sqrt(GlobalUtil::_MemCapGPU / 140.0))
00347         {
00348                 _octave_min ++;
00349                 wp >>= 1;
00350                 hp >>= 1;
00351                 toobig = 2;
00352         }
00353 
00354         if(toobig && GlobalUtil::_verbose)
00355         {
00356                 std::cout<<(toobig == 2 ? "[**SKIP OCTAVES**]:\tExceeding Memory Cap (-nomc)\n" :
00357                                         "[**SKIP OCTAVES**]:\tReaching the dimension limit (-maxd)!\n");
00358         }
00359 
00360         if( wp == _pyramid_width && hp == _pyramid_height && _allocated )
00361         {
00362                 FitPyramid(wp, hp);
00363         }else if(GlobalUtil::_ForceTightPyramid || _allocated ==0)
00364         {
00365                 ResizePyramid(wp, hp);
00366         }
00367         else if( wp > _pyramid_width || hp > _pyramid_height )
00368         {
00369                 ResizePyramid(max(wp, _pyramid_width), max(hp, _pyramid_height));
00370                 if(wp < _pyramid_width || hp < _pyramid_height)  FitPyramid(wp, hp);
00371         }
00372         else
00373         {
00374                 //try use the pyramid allocated for large image on small input images
00375                 FitPyramid(wp, hp);
00376         }
00377 
00378         //select the initial smoothing filter according to the new _octave_min
00379         ShaderMan::SelectInitialSmoothingFilter(_octave_min + _down_sample_factor, param);
00380 }
00381 
00382 void PyramidNaive::ResizePyramid( int w,  int h)
00383 {
00384         //
00385         unsigned int totalkb = 0;
00386         int _octave_num_new, input_sz;
00387         int i, j;
00388         GLTexImage * tex, *aux;
00389         //
00390 
00391         if(_pyramid_width == w && _pyramid_height == h && _allocated) return;
00392 
00393         if(w > GlobalUtil::_texMaxDim || h > GlobalUtil::_texMaxDim) return ;
00394 
00395         if(GlobalUtil::_verbose && GlobalUtil::_timingS) std::cout<<"[Allocate Pyramid]:\t" <<w<<"x"<<h<<endl;
00396         //first octave does not change
00397         _pyramid_octave_first = 0;
00398 
00399         
00400         //compute # of octaves
00401 
00402         input_sz = min(w,h) ;
00403 
00404 
00405         _pyramid_width =  w;
00406         _pyramid_height =  h;
00407 
00408         //reset to preset parameters
00409         _octave_num_new  = GlobalUtil::_octave_num_default;
00410 
00411         if(_octave_num_new < 1) _octave_num_new = GetRequiredOctaveNum(input_sz)  ;
00412 
00413         if(_pyramid_octave_num != _octave_num_new)
00414         {
00415                 //destroy the original pyramid if the # of octave changes
00416                 if(_octave_num >0)
00417                 {
00418                         DestroyPerLevelData();
00419                         DestroyPyramidData();
00420                 }
00421                 _pyramid_octave_num = _octave_num_new;
00422         }
00423 
00424         _octave_num = _pyramid_octave_num;
00425 
00426         int noct = _octave_num;
00427         int nlev = param._level_num;
00428 
00429         //      //initialize the pyramid
00430         if(_texPyramid==NULL)   _texPyramid = new GLTexImage[ noct* nlev ];
00431         if(_auxPyramid==NULL)   _auxPyramid = new GLTexImage[ noct* nlev ];
00432 
00433 
00434         tex = GetBaseLevel(_octave_min, DATA_GAUSSIAN);
00435         aux = GetBaseLevel(_octave_min, DATA_KEYPOINT);
00436         for(i = 0; i< noct; i++)
00437         {
00438                 totalkb += (nlev * w * h * 16 / 1024);
00439                 for( j = 0; j< nlev; j++, tex++)
00440                 {
00441                         tex->InitTexture(w, h);
00442                         //tex->AttachToFBO(0);
00443                 }
00444                 //several auxilary textures are not actually required
00445                 totalkb += ((nlev - 3) * w * h * 16 /1024);
00446                 for( j = 0; j< nlev ; j++, aux++)
00447                 {
00448                         if(j < 2) continue;
00449                         if(j >= nlev - 1) continue;
00450                         aux->InitTexture(w, h, 0);
00451                         //aux->AttachToFBO(0);
00452                 }
00453 
00454                 w>>=1;
00455                 h>>=1;
00456         }
00457 
00458         totalkb += ResizeFeatureStorage();
00459 
00460 
00461         //
00462         _allocated = 1;
00463 
00464         if(GlobalUtil::_verbose && GlobalUtil::_timingS) std::cout<<"[Allocate Pyramid]:\t" <<(totalkb/1024)<<"MB\n";
00465 
00466 }
00467 
00468 
00469 int PyramidGL::ResizeFeatureStorage()
00470 {
00471         int totalkb = 0;
00472         if(_levelFeatureNum==NULL)      _levelFeatureNum = new int[_octave_num * param._dog_level_num];
00473         std::fill(_levelFeatureNum, _levelFeatureNum+_octave_num * param._dog_level_num, 0); 
00474 
00475         int wmax = GetBaseLevel(_octave_min)->GetDrawWidth();
00476         int hmax = GetBaseLevel(_octave_min)->GetDrawHeight();
00477         int w ,h, i;
00478 
00479         //use a fbo to initialize textures..
00480         FrameBufferObject fbo;
00481         
00482         //
00483         if(_histo_buffer == NULL) _histo_buffer = new float[((size_t)1) << (2 + 2 * GlobalUtil::_ListGenSkipGPU)];
00484         //histogram for feature detection
00485 
00486         int num = (int)ceil(log(double(max(wmax, hmax)))/log(2.0));
00487 
00488         if( _hpLevelNum != num)
00489         {
00490                 _hpLevelNum = num;
00491                 if(GlobalUtil::_ListGenGPU)
00492                 {
00493                         if(_histoPyramidTex ) delete [] _histoPyramidTex;
00494                         _histoPyramidTex = new GLTexImage[_hpLevelNum];
00495                         w = h = 1 ;
00496                         for(i = 0; i < _hpLevelNum; i++)
00497                         {
00498                                 _histoPyramidTex[i].InitTexture(w, h, 0);
00499                                 _histoPyramidTex[i].AttachToFBO(0);
00500                                 w<<=1;
00501                                 h<<=1;
00502                         }
00503                 }
00504         }
00505 
00506         // (4 ^ (_hpLevelNum) -1 / 3) pixels
00507         if(GlobalUtil::_ListGenGPU) totalkb += (((1 << (2 * _hpLevelNum)) -1) / 3 * 16 / 1024);
00508 
00509 
00510 
00511         //initialize the feature texture
00512 
00513         int idx = 0, n = _octave_num * param._dog_level_num;
00514         if(_featureTex==NULL)   _featureTex = new GLTexImage[n];
00515         if(GlobalUtil::_MaxOrientation >1 && GlobalUtil::_OrientationPack2==0)
00516         {
00517                 if(_orientationTex== NULL)              _orientationTex = new GLTexImage[n];
00518         }
00519 
00520 
00521         for(i = 0; i < _octave_num; i++)
00522         {
00523                 GLTexImage * tex = GetBaseLevel(i+_octave_min);
00524                 int fmax = int(tex->GetImgWidth()*tex->GetImgHeight()*GlobalUtil::_MaxFeaturePercent);
00525                 int fw, fh;
00526                 //
00527                 if(fmax > GlobalUtil::_MaxLevelFeatureNum) fmax = GlobalUtil::_MaxLevelFeatureNum;
00528                 else if(fmax < 32) fmax = 32;   //give it at least a space of 32 feature
00529 
00530                 GetTextureStorageSize(fmax, fw, fh);
00531                 
00532                 for(int j = 0; j < param._dog_level_num; j++, idx++)
00533                 {
00534 
00535                         _featureTex[idx].InitTexture(fw, fh, 0);
00536                         _featureTex[idx].AttachToFBO(0);
00537                         //
00538                         if(_orientationTex)
00539                         {
00540                                 _orientationTex[idx].InitTexture(fw, fh, 0);
00541                                 _orientationTex[idx].AttachToFBO(0);
00542                         }
00543                 }
00544                 totalkb += fw * fh * 16 * param._dog_level_num * (_orientationTex? 2 : 1) /1024;
00545         }
00546 
00547 
00548         //this just need be initialized once
00549         if(_descriptorTex==NULL)
00550         {
00551                 //initialize feature texture pyramid
00552                 wmax = _featureTex->GetImgWidth();
00553                 hmax = _featureTex->GetImgHeight();
00554 
00555                 int nf, ns;
00556                 if(GlobalUtil::_DescriptorPPT)
00557                 {
00558                         //32*4 = 128. 
00559                         nf = 32 / GlobalUtil::_DescriptorPPT;   // how many textures we need
00560                         ns = max(4, GlobalUtil::_DescriptorPPT);                    // how many point in one texture for one descriptor
00561                 }else
00562                 {
00563                         //at least one, resue for visualization and other work
00564                         nf = 1; ns = 4;
00565                 }
00566                 //
00567                 _alignment = ns;
00568                 //
00569                 _descriptorTex = new GLTexImage[nf];
00570 
00571                 int fw, fh;
00572                 GetAlignedStorageSize(hmax*wmax* max(ns, 10), _alignment, fw, fh);
00573 
00574                 if(fh < hmax ) fh = hmax;
00575                 if(fw < wmax ) fw = wmax;
00576 
00577                 totalkb += ( fw * fh * nf * 16 /1024);
00578                 for(i =0; i < nf; i++)
00579                 {
00580                         _descriptorTex[i].InitTexture(fw, fh);
00581                 }
00582         }else
00583         {
00584                 int nf = GlobalUtil::_DescriptorPPT? 32 / GlobalUtil::_DescriptorPPT: 1;
00585                 totalkb += nf * _descriptorTex[0].GetTexWidth() * _descriptorTex[0].GetTexHeight() * 16 /1024;
00586         }
00587         return totalkb;
00588 }
00589 
00590 
00591 void PyramidNaive::BuildPyramid(GLTexInput *input)
00592 {
00593         USE_TIMING();
00594         GLTexPacked * tex;
00595         FilterProgram** filter;
00596         FrameBufferObject fbo;
00597 
00598         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
00599         input->FitTexViewPort();
00600 
00601         for (int i = _octave_min; i < _octave_min + _octave_num; i++)
00602         {
00603 
00604                 tex = (GLTexPacked*)GetBaseLevel(i);
00605                 filter = ShaderMan::s_bag->f_gaussian_step;
00606 
00607                 OCTAVE_START();
00608 
00609                 if( i == _octave_min )
00610                 {
00611                         if(i < 0)       TextureUpSample(tex, input, 1<<(-i)     );                      
00612                         else        TextureDownSample(tex, input, 1<<i);
00613                 ShaderMan::FilterInitialImage(tex, NULL);
00614                 }else
00615                 {
00616                         TextureDownSample(tex, GetLevelTexture(i-1, param._level_ds)); 
00617             ShaderMan::FilterSampledImage(tex, NULL); 
00618         }
00619                 LEVEL_FINISH();
00620 
00621                 for(int j = param._level_min + 1; j <=  param._level_max ; j++, tex++, filter++)
00622                 {
00623                         // filtering
00624             ShaderMan::FilterImage(*filter, tex+1, tex, NULL);
00625                         LEVEL_FINISH();
00626                 }
00627                 OCTAVE_FINISH();
00628 
00629         }
00630         if(GlobalUtil::_timingS)        glFinish();
00631         UnloadProgram();
00632 }
00633 
00634 
00635 
00636 
00637 
00638 
00639 GLTexImage*  PyramidNaive::GetLevelTexture(int octave, int level, int dataName)
00640 {
00641         if(octave <_octave_min || octave > _octave_min + _octave_num) return NULL;
00642         switch(dataName)
00643         {
00644                 case DATA_GAUSSIAN:
00645                 case DATA_DOG:
00646                 case DATA_GRAD:
00647                 case DATA_ROT:
00648                         return _texPyramid+ (_pyramid_octave_first + octave - _octave_min) * param._level_num + (level - param._level_min);
00649                 case DATA_KEYPOINT:
00650                         return _auxPyramid + (_pyramid_octave_first + octave - _octave_min) * param._level_num + (level - param._level_min);
00651                 default:
00652                         return NULL;
00653         }
00654 }
00655 
00656 GLTexImage*  PyramidNaive::GetLevelTexture(int octave, int level)
00657 {
00658         return _texPyramid+ (_pyramid_octave_first + octave - _octave_min) * param._level_num 
00659                 + (level - param._level_min);
00660 }
00661 
00662 //in the packed implementation
00663 // DATA_GAUSSIAN, DATA_DOG, DATA_GAD will be stored in different textures.
00664 GLTexImage*  PyramidNaive::GetBaseLevel(int octave, int dataName)
00665 {
00666         if(octave <_octave_min || octave > _octave_min + _octave_num) return NULL;
00667         switch(dataName)
00668         {
00669                 case DATA_GAUSSIAN:
00670                 case DATA_DOG:
00671                 case DATA_GRAD:
00672                 case DATA_ROT:
00673                         return _texPyramid+ (_pyramid_octave_first + octave - _octave_min) * param._level_num;
00674                 case DATA_KEYPOINT:
00675                         return _auxPyramid + (_pyramid_octave_first + octave - _octave_min) * param._level_num;
00676                 default:
00677                         return NULL;
00678         }
00679 }
00680 
00681 
00682 
00683 
00684 
00685 
00686 
00687 
00688 
00689 void PyramidNaive::ComputeGradient()
00690 {
00691 
00692         int i, j;
00693         double  ts, t1;
00694         GLTexImage * tex;
00695         FrameBufferObject fbo;
00696 
00697 
00698         if(GlobalUtil::_timingS && GlobalUtil::_verbose)ts = CLOCK();
00699         
00700         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
00701 
00702         for ( i = _octave_min; i < _octave_min + _octave_num; i++)
00703         {
00704                 for( j = param._level_min + 1 ; j < param._level_max ; j++)
00705                 {
00706                         tex = GetLevelTexture(i, j);
00707                         tex->FitTexViewPort();
00708                         tex->AttachToFBO(0);
00709                         tex->BindTex();
00710                         ShaderMan::UseShaderGradientPass();
00711                         tex->DrawQuadMT4();
00712                 }
00713         }               
00714 
00715         if(GlobalUtil::_timingS && GlobalUtil::_verbose)
00716         {
00717                 glFinish();
00718                 t1 = CLOCK();   
00719                 std::cout<<"<Compute Gradient>\t"<<(t1-ts)<<"\n";
00720         }
00721 
00722         UnloadProgram();
00723         GLTexImage::UnbindMultiTex(3);
00724         fbo.UnattachTex(GL_COLOR_ATTACHMENT1_EXT);
00725 }
00726 
00727 
00728 //keypoint detection with subpixel localization
00729 void PyramidNaive::DetectKeypointsEX()
00730 {
00731         int i, j;
00732         double t0, t, ts, t1, t2;
00733         GLTexImage * tex, *aux;
00734         FrameBufferObject fbo;
00735 
00736         if(GlobalUtil::_timingS && GlobalUtil::_verbose)ts = CLOCK();
00737         
00738         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
00739         //extra gradient data required for visualization
00740         int gradient_only_levels[2] = {param._level_min +1, param._level_max};
00741         int n_gradient_only_level = GlobalUtil::_UseSiftGPUEX ? 2 : 1;
00742         for ( i = _octave_min; i < _octave_min + _octave_num; i++)
00743         {
00744                 for( j =0; j < n_gradient_only_level ; j++)
00745                 {
00746                         tex = GetLevelTexture(i, gradient_only_levels[j]);
00747                         tex->FitTexViewPort();
00748                         tex->AttachToFBO(0);
00749                         tex->BindTex();
00750                         ShaderMan::UseShaderGradientPass();
00751                         tex->DrawQuadMT4();
00752                 }
00753         }               
00754 
00755         if(GlobalUtil::_timingS && GlobalUtil::_verbose)
00756         {
00757                 glFinish();
00758                 t1 = CLOCK();
00759         }
00760 
00761         GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT };
00762         glDrawBuffers(2, buffers);
00763         for ( i = _octave_min; i < _octave_min + _octave_num; i++)
00764         {
00765                 if(GlobalUtil::_timingO)
00766                 {
00767                         t0 = CLOCK();
00768                         std::cout<<"#"<<(i + _down_sample_factor)<<"\t";
00769                 }
00770                 tex = GetBaseLevel(i) + 2;
00771                 aux = GetBaseLevel(i, DATA_KEYPOINT) +2;
00772                 aux->FitTexViewPort();
00773 
00774                 for( j = param._level_min + 2; j <  param._level_max ; j++, aux++, tex++)
00775                 {
00776                         if(GlobalUtil::_timingL)t = CLOCK();            
00777                         tex->AttachToFBO(0);
00778                         aux->AttachToFBO(1);
00779                         glActiveTexture(GL_TEXTURE0);
00780                         tex->BindTex();
00781                         glActiveTexture(GL_TEXTURE1);
00782                         (tex+1)->BindTex();
00783                         glActiveTexture(GL_TEXTURE2);
00784                         (tex-1)->BindTex();
00785                         ShaderMan::UseShaderKeypoint((tex+1)->GetTexID(), (tex-1)->GetTexID());
00786                         aux->DrawQuadMT8();
00787         
00788                         if(GlobalUtil::_timingL)
00789                         {
00790                                 glFinish();
00791                                 std::cout<<(CLOCK()-t)<<"\t";
00792                         }
00793                         tex->DetachFBO(0);
00794                         aux->DetachFBO(1);
00795                 }
00796                 if(GlobalUtil::_timingO)
00797                 {
00798                         std::cout<<"|\t"<<(CLOCK()-t0)<<"\n";
00799                 }
00800         }
00801 
00802         if(GlobalUtil::_timingS)
00803         {
00804                 glFinish();
00805                 t2 = CLOCK();
00806                 if(GlobalUtil::_verbose) 
00807                         std::cout       <<"<Get Keypoints ..  >\t"<<(t2-t1)<<"\n"
00808                                                 <<"<Extra Gradient..  >\t"<<(t1-ts)<<"\n";
00809         }
00810         UnloadProgram();
00811         GLTexImage::UnbindMultiTex(3);
00812         fbo.UnattachTex(GL_COLOR_ATTACHMENT1_EXT);
00813 
00814 
00815 }
00816 
00817 void PyramidNaive::GenerateFeatureList(int i, int j)
00818 {
00819         int hist_level_num = _hpLevelNum - _pyramid_octave_first; 
00820         int hist_skip_gpu = GlobalUtil::_ListGenSkipGPU; 
00821     int idx = i * param._dog_level_num + j;
00822     GLTexImage* htex, *ftex, *tex;
00823         tex = GetBaseLevel(_octave_min + i, DATA_KEYPOINT) + 2 + j;
00824     ftex = _featureTex + idx;
00825         htex = _histoPyramidTex + hist_level_num - 1 - i;
00826 
00828         glActiveTexture(GL_TEXTURE0);
00829         tex->BindTex();
00830         htex->AttachToFBO(0);
00831         int tight = ((htex->GetImgWidth() * 2 == tex->GetImgWidth() -1 || tex->GetTexWidth() == tex->GetImgWidth()) &&
00832                                  (htex->GetImgHeight() *2 == tex->GetImgHeight()-1 || tex->GetTexHeight() == tex->GetImgHeight()));
00833         ShaderMan::UseShaderGenListInit(tex->GetImgWidth(), tex->GetImgHeight(), tight);
00834         htex->FitTexViewPort();
00835         //this uses the fact that no feature is on the edge.
00836         htex->DrawQuadReduction();
00837 
00838         //reduction..
00839         htex--;
00840 
00841         //this part might have problems on several GPUS
00842         //because the output of one pass is the input of the next pass
00843         //need to call glFinish to make it right
00844         //but too much glFinish makes it slow
00845         for(int k = 0; k <hist_level_num - i - 1 - hist_skip_gpu; k++, htex--)
00846         {
00847                 htex->AttachToFBO(0);
00848                 htex->FitTexViewPort();
00849                 (htex+1)->BindTex();
00850                 ShaderMan::UseShaderGenListHisto();
00851                 htex->DrawQuadReduction();                                      
00852         }
00853 
00854         //
00855         if(hist_skip_gpu == 0)
00856         {       
00857                 //read back one pixel
00858                 float fn[4], fcount;
00859                 glReadPixels(0, 0, 1, 1, GL_RGBA , GL_FLOAT, fn);
00860                 fcount = (fn[0] + fn[1] + fn[2] + fn[3]);
00861                 if(fcount < 1) fcount = 0;
00862 
00863 
00864                 _levelFeatureNum[ idx] = (int)(fcount);
00865                 SetLevelFeatureNum(idx, (int)fcount);
00866                 _featureNum += int(fcount);
00867 
00868                 //
00869                 if(fcount < 1.0) return;
00870         
00871 
00873 
00874                 htex=  _histoPyramidTex;
00875 
00876                 htex->BindTex();
00877 
00878                 //first pass
00879                 ftex->AttachToFBO(0);
00880                 if(GlobalUtil::_MaxOrientation>1)
00881                 {
00882                         //this is very important...
00883                         ftex->FitRealTexViewPort();
00884                         glClear(GL_COLOR_BUFFER_BIT);
00885                         glFinish();
00886                 }else
00887                 {
00888                         ftex->FitTexViewPort();
00889             //glFinish();
00890                 }
00891 
00892 
00893                 ShaderMan::UseShaderGenListStart((float)ftex->GetImgWidth(), htex->GetTexID());
00894 
00895                 ftex->DrawQuad();
00896                 //make sure it finishes before the next step
00897                 ftex->DetachFBO(0);
00898 
00899                 //pass on each pyramid level
00900                 htex++;
00901         }else
00902         {
00903 
00904                 int tw = htex[1].GetDrawWidth(), th = htex[1].GetDrawHeight();
00905                 int fc = 0;
00906                 glReadPixels(0, 0, tw, th, GL_RGBA , GL_FLOAT, _histo_buffer);  
00907                 _keypoint_buffer.resize(0);
00908                 for(int y = 0, pos = 0; y < th; y++)
00909                 {
00910                         for(int x= 0; x < tw; x++)
00911                         {
00912                                 for(int c = 0; c < 4; c++, pos++)
00913                                 {
00914                                         int ss =  (int) _histo_buffer[pos]; 
00915                                         if(ss == 0) continue;
00916                                         float ft[4] = {2 * x + (c%2? 1.5f:  0.5f), 2 * y + (c>=2? 1.5f: 0.5f), 0, 1 };
00917                                         for(int t = 0; t < ss; t++)
00918                                         {
00919                                                 ft[2] = (float) t; 
00920                                                 _keypoint_buffer.insert(_keypoint_buffer.end(), ft, ft+4);
00921                                         }
00922                                         fc += (int)ss; 
00923                                 }
00924                         }
00925                 }
00926                 _levelFeatureNum[ idx] = fc;
00927                 SetLevelFeatureNum(idx, fc);
00928                 if(fc == 0)  return;
00929         _featureNum += fc;
00931                 ftex->AttachToFBO(0);
00932                 if(GlobalUtil::_MaxOrientation>1)
00933                 {
00934                         ftex->FitRealTexViewPort();
00935                         glClear(GL_COLOR_BUFFER_BIT);
00936                         glFlush();
00937                 }else
00938                 {                                       
00939                         ftex->FitTexViewPort();
00940                         glFlush();
00941                 }
00942                 _keypoint_buffer.resize(ftex->GetDrawWidth() * ftex->GetDrawHeight()*4, 0);
00944                 glActiveTexture(GL_TEXTURE0);
00945                 ftex->BindTex();
00946                 glTexSubImage2D(GlobalUtil::_texTarget, 0, 0, 0, ftex->GetDrawWidth(),
00947                         ftex->GetDrawHeight(), GL_RGBA, GL_FLOAT, &_keypoint_buffer[0]);
00948                 htex += 2;
00949         }
00950 
00951         for(int lev = 1 + hist_skip_gpu; lev < hist_level_num  - i; lev++, htex++)
00952         {
00953 
00954                 glActiveTexture(GL_TEXTURE0);
00955                 ftex->BindTex();
00956                 ftex->AttachToFBO(0);
00957                 glActiveTexture(GL_TEXTURE1);
00958                 htex->BindTex();
00959                 ShaderMan::UseShaderGenListStep(ftex->GetTexID(), htex->GetTexID());
00960                 ftex->DrawQuad();
00961                 ftex->DetachFBO(0);     
00962         }
00963         GLTexImage::UnbindMultiTex(2);
00964 
00965 }
00966 
00967 //generate feature list on GPU
00968 void PyramidNaive::GenerateFeatureList()
00969 {
00970         //generate the histogram0pyramid
00971         FrameBufferObject fbo;
00972         glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
00973         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
00974         double t1, t2; 
00975         int ocount, reverse = (GlobalUtil::_TruncateMethod == 1);
00976         _featureNum = 0;
00977 
00978         FitHistogramPyramid();
00979 
00980         //for(int i = 0, idx = 0; i < _octave_num; i++)
00981     FOR_EACH_OCTAVE(i, reverse)
00982         {
00983                 //output
00984                 if(GlobalUtil::_timingO)
00985                 {
00986             t1= CLOCK();
00987                         ocount = 0;
00988                         std::cout<<"#"<<i+_octave_min + _down_sample_factor<<":\t";
00989                 }
00990                 //for(int j = 0; j < param._dog_level_num; j++, idx++)
00991         FOR_EACH_LEVEL(j, reverse)
00992         {
00993 
00994             if(GlobalUtil::_TruncateMethod && GlobalUtil::_FeatureCountThreshold > 0
00995                                 && _featureNum > GlobalUtil::_FeatureCountThreshold) 
00996                         {
00997                                 _levelFeatureNum[i * param._dog_level_num + j] = 0;
00998                                 continue;
00999                         }else
01000                         {
01001                                 GenerateFeatureList(i, j); 
01002                                 if(GlobalUtil::_timingO)        
01003                                 {
01004                                         int idx = i * param._dog_level_num + j;
01005                                         std::cout<< _levelFeatureNum[idx] <<"\t";
01006                                         ocount += _levelFeatureNum[idx];
01007                                 }
01008                         }
01009                 }
01010                 if(GlobalUtil::_timingO)
01011                 {       
01012                         t2 = CLOCK(); 
01013                         std::cout << "| \t" << int(ocount) << " :\t(" << (t2 - t1) << ")\n";
01014                 }
01015         }
01016         if(GlobalUtil::_timingS)glFinish();
01017         if(GlobalUtil::_verbose)
01018         {
01019                 std::cout<<"#Features:\t"<<_featureNum<<"\n";
01020         }
01021 }
01022 
01023 
01024 void PyramidGL::GenerateFeatureDisplayVBO()
01025 {
01026         //use a big VBO to save all the SIFT box vertices
01027         int w, h, esize; GLint bsize;
01028         int nvbo = _octave_num * param._dog_level_num;
01029         //initialize the vbos
01030         if(_featureDisplayVBO==NULL)
01031         {
01032                 _featureDisplayVBO = new GLuint[nvbo];
01033                 glGenBuffers( nvbo, _featureDisplayVBO );
01034     }
01035     if(_featurePointVBO == NULL)
01036     {
01037                 _featurePointVBO = new GLuint[nvbo];
01038                 glGenBuffers(nvbo, _featurePointVBO);
01039         }
01040 
01041         FrameBufferObject fbo;
01042         glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
01043         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
01044         glActiveTexture(GL_TEXTURE0);
01045         //
01046         GLTexImage & tempTex = *_descriptorTex;
01047         //
01048         for(int i = 0, idx = 0; i < _octave_num; i++)
01049         {
01050                 for(int j = 0; j < param._dog_level_num; j ++, idx++)
01051                 {
01052                         GLTexImage * ftex  = _featureTex + idx;
01053                         if(_levelFeatureNum[idx]<=0)continue;
01054 
01055                         //copy the texture into vbo
01056                         fbo.BindFBO();
01057                         tempTex.AttachToFBO(0);
01058 
01059                         ftex->BindTex();
01060                         ftex->FitTexViewPort();
01061                         ShaderMan::UseShaderCopyKeypoint();
01062                         ftex->DrawQuad();
01063 
01064                         glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB,  _featurePointVBO[ idx]);
01065                         glGetBufferParameteriv(GL_PIXEL_PACK_BUFFER_ARB, GL_BUFFER_SIZE, &bsize);
01066                         esize = ftex->GetImgHeight() * ftex->GetImgWidth()*sizeof(float) *4;
01067 
01068                         //increase size when necessary
01069                         if(bsize < esize)
01070                         {
01071                                 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, esize*3/2 ,      NULL, GL_STATIC_DRAW_ARB);
01072                                 glGetBufferParameteriv(GL_PIXEL_PACK_BUFFER_ARB, GL_BUFFER_SIZE, &bsize);
01073                         }
01074 
01075                         //read back if we have enough buffer
01076                         if(bsize >= esize) glReadPixels(0, 0, ftex->GetImgWidth(), ftex->GetImgHeight(), GL_RGBA, GL_FLOAT, 0);
01077                         else  glBufferData(GL_PIXEL_PACK_BUFFER_ARB, 0, NULL, GL_STATIC_DRAW_ARB);
01078                         glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
01079 
01080 
01081                         //box display vbo
01082                         int count = _levelFeatureNum[idx]* 10;
01083                         GetAlignedStorageSize(count, _alignment, w, h);
01084                         w = (int)ceil(double(count)/ h);
01085 
01086                         //input
01087                         fbo.BindFBO();
01088                         ftex->BindTex();
01089 
01090                         //output
01091                         tempTex.AttachToFBO(0);
01092                         GlobalUtil::FitViewPort(w, h);
01093                         //shader
01094                         ShaderMan::UseShaderGenVBO(     (float)ftex->GetImgWidth(),  (float) w, 
01095                                 param.GetLevelSigma(j + param._level_min + 1));
01096                         GLTexImage::DrawQuad(0,  (float)w, 0, (float)h);
01097                 
01098                         //
01099                         glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, _featureDisplayVBO[ idx]);
01100                         glGetBufferParameteriv(GL_PIXEL_PACK_BUFFER_ARB, GL_BUFFER_SIZE, &bsize);
01101                         esize = w*h * sizeof(float)*4;
01102                         //increase size when necessary
01103                         if(bsize < esize)
01104                         {
01105                                 glBufferData(GL_PIXEL_PACK_BUFFER_ARB, esize*3/2,       NULL, GL_STATIC_DRAW_ARB);
01106                                 glGetBufferParameteriv(GL_PIXEL_PACK_BUFFER_ARB, GL_BUFFER_SIZE, &bsize);
01107                         }
01108                         
01109                         //read back if we have enough buffer    
01110                         if(bsize >= esize)      glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, 0);
01111                         else glBufferData(GL_PIXEL_PACK_BUFFER_ARB, 0,  NULL, GL_STATIC_DRAW_ARB);
01112                         glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
01113 
01114 
01115 
01116                         
01117                 }
01118         }
01119         glReadBuffer(GL_NONE);
01120         glFinish();
01121 
01122 }
01123 
01124 
01125 
01126 
01127 
01128 void PyramidNaive::GetFeatureOrientations()
01129 {
01130         GLTexImage * gtex;
01131         GLTexImage * stex = NULL;
01132         GLTexImage * ftex = _featureTex;
01133         GLTexImage * otex = _orientationTex;
01134         int sid = 0; 
01135         int * count      = _levelFeatureNum;
01136         float sigma, sigma_step = powf(2.0f, 1.0f/param._dog_level_num);
01137         FrameBufferObject fbo;
01138         if(_orientationTex)
01139         {
01140                 GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT };
01141                 glDrawBuffers(2, buffers);
01142         }else
01143         {
01144                 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
01145         }
01146         for(int i = 0; i < _octave_num; i++)
01147         {
01148                 gtex = GetLevelTexture(i+_octave_min, param._level_min + 1);
01149                 if(GlobalUtil::_SubpixelLocalization || GlobalUtil::_KeepExtremumSign)
01150                         stex = GetBaseLevel(i+_octave_min, DATA_KEYPOINT) + 2;
01151 
01152                 for(int j = 0; j < param._dog_level_num; j++, ftex++, otex++, count++, gtex++, stex++)
01153                 {
01154                         if(*count<=0)continue;
01155 
01156                         sigma = param.GetLevelSigma(j+param._level_min+1);
01157 
01158                         //
01159                         ftex->FitTexViewPort();
01160 
01161                         glActiveTexture(GL_TEXTURE0);
01162                         ftex->BindTex();
01163                         glActiveTexture(GL_TEXTURE1);
01164                         gtex->BindTex();
01165                         //
01166                         ftex->AttachToFBO(0);
01167                         if(_orientationTex)             otex->AttachToFBO(1);
01168                         if(!_existing_keypoints && (GlobalUtil::_SubpixelLocalization|| GlobalUtil::_KeepExtremumSign))
01169                         {
01170                                 glActiveTexture(GL_TEXTURE2);
01171                                 stex->BindTex();
01172                                 sid = * stex;
01173                         }
01174                         ShaderMan::UseShaderOrientation(gtex->GetTexID(),
01175                                 gtex->GetImgWidth(), gtex->GetImgHeight(),
01176                                 sigma, sid, sigma_step, _existing_keypoints);
01177                         ftex->DrawQuad();
01178         //              glFinish();
01179                         
01180                 }
01181         }
01182 
01183         GLTexImage::UnbindMultiTex(3);
01184         if(GlobalUtil::_timingS)glFinish();
01185 
01186         if(_orientationTex)     fbo.UnattachTex(GL_COLOR_ATTACHMENT1_EXT);
01187 
01188 }
01189 
01190 
01191 
01192 //to compare with GPU feature list generation
01193 void PyramidNaive::GenerateFeatureListCPU()
01194 {
01195 
01196         FrameBufferObject fbo;
01197         _featureNum = 0;
01198         GLTexImage * tex = GetBaseLevel(_octave_min);
01199         float * mem = new float [tex->GetTexWidth()*tex->GetTexHeight()];
01200         vector<float> list;
01201         int idx = 0;
01202         for(int i = 0; i < _octave_num; i++)
01203         {
01204                 for(int j = 0; j < param._dog_level_num; j++, idx++)
01205                 {
01206                         tex = GetBaseLevel(_octave_min + i, DATA_KEYPOINT) + j + 2;
01207                         tex->BindTex();
01208                         glGetTexImage(GlobalUtil::_texTarget, 0, GL_RED, GL_FLOAT, mem);
01209                         //tex->AttachToFBO(0);
01210                         //tex->FitTexViewPort();
01211                         //glReadPixels(0, 0, tex->GetTexWidth(), tex->GetTexHeight(), GL_RED, GL_FLOAT, mem);
01212                         //
01213                         //make a list of 
01214                         list.resize(0);
01215                         float * p = mem;
01216                         int fcount = 0 ;
01217                         for(int k = 0; k < tex->GetTexHeight(); k++)
01218                         {
01219                                 for( int m = 0; m < tex->GetTexWidth(); m ++, p++)
01220                                 {
01221                                         if(*p==0)continue;
01222                                         if(m ==0 || k ==0 || k >= tex->GetImgHeight() -1 || m >= tex->GetImgWidth() -1 ) continue;
01223                                         list.push_back(m+0.5f);
01224                                         list.push_back(k+0.5f);
01225                                         list.push_back(0);
01226                                         list.push_back(1);
01227                                         fcount ++;
01228 
01229 
01230                                 }
01231                         }
01232                         if(fcount==0)continue;
01233 
01234 
01235                         
01236                         GLTexImage * ftex = _featureTex+idx;
01237                         _levelFeatureNum[idx] = (fcount);
01238                         SetLevelFeatureNum(idx, fcount);
01239 
01240                         _featureNum += (fcount);
01241 
01242 
01243                         int fw = ftex->GetImgWidth();
01244                         int fh = ftex->GetImgHeight();
01245 
01246                         list.resize(4*fh*fw);
01247 
01248                         ftex->BindTex();
01249                         ftex->AttachToFBO(0);
01250         //              glTexImage2D(GlobalUtil::_texTarget, 0, GlobalUtil::_iTexFormat, fw, fh, 0, GL_BGRA, GL_FLOAT, &list[0]);
01251                         glTexSubImage2D(GlobalUtil::_texTarget, 0, 0, 0, fw, fh, GL_RGBA, GL_FLOAT, &list[0]);
01252                         //
01253                 }
01254         }
01255         GLTexImage::UnbindTex();
01256         delete[] mem;
01257         if(GlobalUtil::_verbose)
01258         {
01259                 std::cout<<"#Features:\t"<<_featureNum<<"\n";
01260         }
01261 }
01262 
01263 #define FEATURELIST_USE_PBO
01264 
01265 void PyramidGL::ReshapeFeatureListCPU()
01266 {
01267         //make a compact feature list, each with only one orientation
01268         //download orientations and the featue list
01269         //reshape it and upload it
01270 
01271         FrameBufferObject fbo;
01272         int i, szmax =0, sz;
01273         int n = param._dog_level_num*_octave_num;
01274         for( i = 0; i < n; i++)
01275         {
01276                 sz = _featureTex[i].GetImgWidth() * _featureTex[i].GetImgHeight();
01277                 if(sz > szmax ) szmax = sz;
01278         }
01279         float * buffer = new float[szmax*24];
01280         float * buffer1 = buffer;
01281         float * buffer2 = buffer + szmax*4;
01282         float * buffer3 = buffer + szmax*8;
01283 
01284         glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
01285         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
01286 
01287 #ifdef FEATURELIST_USE_PBO
01288     GLuint ListUploadPBO;
01289     glGenBuffers(1, &ListUploadPBO); 
01290         glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,  ListUploadPBO);
01291         glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, szmax * 8 * sizeof(float),     NULL, GL_STREAM_DRAW);
01292 #endif
01293 
01294         _featureNum = 0;
01295 
01296 #ifdef NO_DUPLICATE_DOWNLOAD
01297         const double twopi = 2.0*3.14159265358979323846;
01298         _keypoint_buffer.resize(0);
01299         float os = _octave_min>=0? float(1<<_octave_min): 1.0f/(1<<(-_octave_min));
01300         if(_down_sample_factor>0) os *= float(1<<_down_sample_factor); 
01301         float offset = GlobalUtil::_LoweOrigin? 0 : 0.5f;
01302 #endif
01303 
01304         for(i = 0; i < n; i++)
01305         {
01306                 if(_levelFeatureNum[i]==0)continue;
01307 
01308                 _featureTex[i].AttachToFBO(0);
01309                 _featureTex[i].FitTexViewPort();
01310                 glReadPixels(0, 0, _featureTex[i].GetImgWidth(), _featureTex[i].GetImgHeight(),GL_RGBA, GL_FLOAT, buffer1);
01311                 
01312                 int fcount =0, ocount;
01313                 float * src = buffer1;
01314                 float * orientation  = buffer2;
01315                 float * des = buffer3;
01316                 if(GlobalUtil::_OrientationPack2 == 0)
01317                 {       
01318                         //read back orientations from another texture
01319                         _orientationTex[i].AttachToFBO(0);
01320                         glReadPixels(0, 0, _orientationTex[i].GetImgWidth(), _orientationTex[i].GetImgHeight(),GL_RGBA, GL_FLOAT, buffer2);
01321                         //make the feature list
01322                         for(int j = 0; j < _levelFeatureNum[i]; j++, src+=4, orientation+=4)
01323                         {
01324                                 if(_existing_keypoints) 
01325                                 {
01326                                         des[0] = src[0];
01327                                         des[1] = src[1];
01328                                         des[2] = orientation[0];
01329                                         des[3] = src[3];                        
01330                                         fcount++;
01331                                         des += 4;
01332                                 }else
01333                                 {
01334                                         ocount = (int)src[2];
01335                                         for(int k = 0 ; k < ocount; k++, des+=4)
01336                                         {
01337                                                 des[0] = src[0];
01338                                                 des[1] = src[1];
01339                                                 des[2] = orientation[k];
01340                                                 des[3] = src[3];                        
01341                                                 fcount++;
01342                                         }
01343                                 }
01344                         }
01345                 }else
01346                 {
01347                         _featureTex[i].DetachFBO(0);
01348                         const static double factor  = 2.0*3.14159265358979323846/65535.0;
01349                         for(int j = 0; j < _levelFeatureNum[i]; j++, src+=4)
01350                         {
01351                                 unsigned short * orientations = (unsigned short*) (&src[2]);
01352                                 if(_existing_keypoints) 
01353                                 {
01354                                         des[0] = src[0];
01355                                         des[1] = src[1];
01356                                         des[2] = float( factor* orientations[0]);
01357                                         des[3] = src[3];                        
01358                                         fcount++;
01359                                         des += 4;
01360                                 }else
01361                                 {
01362                                         if(orientations[0] != 65535)
01363                                         {
01364                                                 des[0] = src[0];
01365                                                 des[1] = src[1];
01366                                                 des[2] = float( factor* orientations[0]);
01367                                                 des[3] = src[3];                        
01368                                                 fcount++;
01369                                                 des += 4;
01370 
01371                                                 if(orientations[1] != 65535)
01372                                                 {
01373                                                         des[0] = src[0];
01374                                                         des[1] = src[1];
01375                                                         des[2] = float(factor* orientations[1]);
01376                                                         des[3] = src[3];                        
01377                                                         fcount++;
01378                                                         des += 4;
01379                                                 }
01380                                         }
01381                                 }
01382                         }
01383                 }
01384 
01385                 //texture size --------------
01386                 SetLevelFeatureNum(i, fcount);
01387                 int nfw = _featureTex[i].GetImgWidth();
01388                 int nfh = _featureTex[i].GetImgHeight();
01389                 int sz = nfh * nfw;
01390                 if(sz > fcount) memset(des, 0, sizeof(float) * (sz - fcount) * 4);
01391 
01392 #ifndef FEATURELIST_USE_PBO
01393                 _featureTex[i].BindTex();
01394                 glTexSubImage2D(GlobalUtil::_texTarget, 0, 0, 0, nfw, nfh, GL_RGBA, GL_FLOAT, buffer3);
01395                 _featureTex[i].UnbindTex();
01396 #else
01397         float* mem = (float*) glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,  GL_WRITE_ONLY);
01398         memcpy(mem, buffer3,  sz * 4 * sizeof(float) );
01399         glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
01400                 _featureTex[i].BindTex();
01401                 glTexSubImage2D(GlobalUtil::_texTarget, 0, 0, 0, nfw, nfh, GL_RGBA, GL_FLOAT, 0);
01402                 _featureTex[i].UnbindTex();
01403 #endif
01404 
01405 #ifdef NO_DUPLICATE_DOWNLOAD
01406                 if(fcount > 0)
01407                 {
01408                         float oss = os * (1 << (i / param._dog_level_num));
01409                         _keypoint_buffer.resize((_featureNum + fcount) * 4);
01410                         float* ds = &_keypoint_buffer[_featureNum * 4];
01411                         float* fs = buffer3;
01412                         for(int k = 0;  k < fcount; k++, ds+=4, fs+=4)
01413                         {
01414                                 ds[0] = oss*(fs[0]-0.5f) + offset;      //x
01415                                 ds[1] = oss*(fs[1]-0.5f) + offset;      //y
01416                                 ds[3] = (float)fmod(twopi-fs[2], twopi);        //orientation, mirrored
01417                                 ds[2] = oss*fs[3];  //scale
01418                         }
01419                 }
01420 #endif
01421                 _levelFeatureNum[i] = fcount;
01422                 _featureNum += fcount;
01423         }
01424 
01425         delete[] buffer;
01426         if(GlobalUtil::_verbose)
01427         {
01428                 std::cout<<"#Features MO:\t"<<_featureNum<<endl;
01429         }
01431 #ifdef FEATURELIST_USE_PBO
01432         glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB,  0);
01433     glDeleteBuffers(1, &ListUploadPBO);
01434 #endif
01435 }
01436 
01437 
01438 
01439 inline void PyramidGL::SetLevelFeatureNum(int idx, int fcount)
01440 {
01441         int fw, fh;
01442         GLTexImage * ftex = _featureTex + idx;
01443         //set feature texture size. normally fh will be one
01444         GetTextureStorageSize(fcount, fw, fh);
01445         if(fcount >  ftex->GetTexWidth()*ftex->GetTexHeight())
01446         {
01447                 ftex->InitTexture(fw, fh, 0);
01448                 if(_orientationTex)                     _orientationTex[idx].InitTexture(fw, fh, 0);
01449 
01450         }
01451         if(GlobalUtil::_NarrowFeatureTex)
01452                 fh = fcount ==0? 0:(int)ceil(double(fcount)/fw);
01453         else
01454                 fw = fcount ==0? 0:(int)ceil(double(fcount)/fh);
01455         ftex->SetImageSize(fw, fh);
01456         if(_orientationTex)             _orientationTex[idx].SetImageSize(fw, fh);
01457 }
01458 
01459 void PyramidGL::CleanUpAfterSIFT()
01460 {
01461         GLTexImage::UnbindMultiTex(3);
01462         ShaderMan::UnloadProgram();
01463         FrameBufferObject::DeleteGlobalFBO();
01464         GlobalUtil::CleanupOpenGL();
01465 }
01466 
01467 void PyramidNaive::GetSimplifiedOrientation()
01468 {
01469         //
01470         int idx = 0;
01471 //      int n = _octave_num  * param._dog_level_num;
01472         float sigma, sigma_step = powf(2.0f, 1.0f/param._dog_level_num); 
01473         GLTexImage * ftex = _featureTex;
01474 
01475         FrameBufferObject fbo;
01476         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
01477         for(int i = 0; i < _octave_num; i++)
01478         {
01479                 GLTexImage *gtex = GetLevelTexture(i+_octave_min, 2+param._level_min);
01480                 for(int j = 0; j < param._dog_level_num; j++, ftex++,  gtex++, idx ++)
01481                 {
01482                         if(_levelFeatureNum[idx]<=0)continue;
01483                         sigma = param.GetLevelSigma(j+param._level_min+1);
01484 
01485                         //
01486                         ftex->AttachToFBO(0);
01487                         ftex->FitTexViewPort();
01488 
01489                         glActiveTexture(GL_TEXTURE0);
01490                         ftex->BindTex();
01491                         glActiveTexture(GL_TEXTURE1);
01492                         gtex->BindTex();
01493 
01494                         ShaderMan::UseShaderSimpleOrientation(gtex->GetTexID(), sigma, sigma_step);
01495                         ftex->DrawQuad();
01496                 }
01497         }
01498 
01499         GLTexImage::UnbindMultiTex(2);
01500 
01501 }
01502 
01503 
01504 #ifdef USE_SSE_FOR_SIFTGPU
01505         static inline float dotproduct_128d(float * p)
01506         {
01507                 float z = 0.0f;
01508                 __m128 sse =_mm_load_ss(&z);
01509                 float* pf = (float*) (&sse);
01510                 for( int i = 0; i < 32; i++, p+=4)
01511                 {
01512                         __m128 ps = _mm_loadu_ps(p);
01513                         sse = _mm_add_ps(sse,  _mm_mul_ps(ps, ps));
01514                 }
01515                 return pf[0] + pf[1] + pf[2] + pf[3];
01516 
01517         }
01518         static inline void multiply_and_truncate_128d(float* p, float m)
01519         {
01520                 float z = 0.2f;
01521                 __m128 t = _mm_load_ps1(&z);
01522                 __m128 r = _mm_load_ps1(&m);
01523                 for(int i = 0; i < 32; i++, p+=4)
01524                 {
01525                         __m128 ps = _mm_loadu_ps(p);
01526                         _mm_storeu_ps(p, _mm_min_ps(_mm_mul_ps(ps, r), t));
01527                 }
01528         }
01529         static inline void multiply_128d(float* p, float m)
01530         {
01531                 __m128 r = _mm_load_ps1(&m);
01532                 for(int i = 0; i < 32; i++, p+=4)
01533                 {
01534                         __m128 ps = _mm_loadu_ps(p);
01535                         _mm_storeu_ps(p, _mm_mul_ps(ps, r));
01536                 }
01537         }
01538 #endif
01539 
01540 
01541 inline void PyramidGL::NormalizeDescriptor(int num, float*pd)
01542 {
01543 
01544 #ifdef USE_SSE_FOR_SIFTGPU
01545         for(int k = 0; k < num; k++, pd +=128)
01546         {
01547                 float sq;
01548                 //normalize and truncate to .2
01549                 sq = dotproduct_128d(pd);               sq = 1.0f / sqrtf(sq);
01550                 multiply_and_truncate_128d(pd, sq);
01551 
01552                 //renormalize
01553                 sq = dotproduct_128d(pd);               sq = 1.0f / sqrtf(sq);
01554                 multiply_128d(pd, sq);
01555         }
01556 #else
01557         //descriptor normalization runs on cpu for OpenGL implemenations
01558         for(int k = 0; k < num; k++, pd +=128)
01559         {
01560                 int v;
01561                 float* ppd, sq = 0;
01562                 //int v;
01563                 //normalize
01564                 ppd = pd;
01565                 for(v = 0 ; v < 128; v++, ppd++)        sq += (*ppd)*(*ppd);
01566                 sq = 1.0f / sqrtf(sq);
01567                 //truncate to .2
01568                 ppd = pd;
01569                 for(v = 0; v < 128; v ++, ppd++)        *ppd = min(*ppd*sq, 0.2f);
01570 
01571                 //renormalize
01572                 ppd = pd; sq = 0;
01573                 for(v = 0; v < 128; v++, ppd++) sq += (*ppd)*(*ppd);
01574                 sq = 1.0f / sqrtf(sq);
01575 
01576                 ppd = pd;
01577                 for(v = 0; v < 128; v ++, ppd++)        *ppd = *ppd*sq;
01578         }
01579 
01580 #endif
01581 }
01582 
01583 inline void PyramidGL::InterlaceDescriptorF2(int w, int h, float* buf, float* pd, int step)
01584 {
01585         /*
01586         if(GlobalUtil::_DescriptorPPR == 8)
01587         {
01588                 const int dstep = w * 128;
01589                 float* pp1 = buf;
01590                 float* pp2 = buf + step;
01591 
01592                 for(int u = 0; u < h ; u++, pd+=dstep)
01593                 {
01594                         int v; 
01595                         float* ppd = pd;
01596                         for(v= 0; v < w; v++)
01597                         {
01598                                 for(int t = 0; t < 8; t++)
01599                                 {
01600                                         *ppd++ = *pp1++;*ppd++ = *pp1++;*ppd++ = *pp1++;*ppd++ = *pp1++;
01601                                         *ppd++ = *pp2++;*ppd++ = *pp2++;*ppd++ = *pp2++;*ppd++ = *pp2++;
01602                                 }
01603                                 ppd += 64;
01604                         }
01605                         ppd = pd + 64;
01606                         for(v= 0; v < w; v++)
01607                         {
01608                                 for(int t = 0; t < 8; t++)
01609                                 {
01610                                         *ppd++ = *pp1++;*ppd++ = *pp1++;*ppd++ = *pp1++;*ppd++ = *pp1++;
01611                                         *ppd++ = *pp2++;*ppd++ = *pp2++;*ppd++ = *pp2++;*ppd++ = *pp2++;
01612                                 }
01613                                 ppd += 64;
01614                         }
01615                 }
01616 
01617         }else */
01618         if(GlobalUtil::_DescriptorPPR == 8)
01619         {
01620                 //interlace
01621                 for(int k = 0; k < 2; k++)
01622                 {
01623                         float* pp = buf + k * step;
01624                         float* ppd = pd + k * 4;
01625                         for(int u = 0; u < h ; u++)
01626                         {
01627                                 int v; 
01628                                 for(v= 0; v < w; v++)
01629                                 {
01630                                         for(int t = 0; t < 8; t++)
01631                                         {
01632                                                 ppd[0] = pp[0];
01633                                                 ppd[1] = pp[1];
01634                                                 ppd[2] = pp[2];
01635                                                 ppd[3] = pp[3];
01636                                                 ppd += 8;
01637                                                 pp+= 4;
01638                                         }
01639                                         ppd += 64;
01640                                 }
01641                                 ppd += ( 64 - 128 * w );
01642                                 for(v= 0; v < w; v++)
01643                                 {
01644                                         for(int t = 0; t < 8; t++)
01645                                         {
01646                                                 ppd[0] = pp[0];
01647                                                 ppd[1] = pp[1];
01648                                                 ppd[2] = pp[2];
01649                                                 ppd[3] = pp[3];
01650 
01651                                                 ppd += 8;
01652                                                 pp+= 4;
01653                                         }
01654                                         ppd += 64;
01655                                 }
01656                                 ppd -=64;
01657                         }
01658                 }
01659         }else if(GlobalUtil::_DescriptorPPR == 4)
01660         {
01661 
01662         }
01663 
01664 
01665 
01666 }
01667 void PyramidGL::GetFeatureDescriptors()
01668 {
01669         //descriptors...
01670         float sigma;
01671         int idx, i, j, k, w, h;
01672         int ndf = 32 / GlobalUtil::_DescriptorPPT; //number of textures
01673         int block_width = GlobalUtil::_DescriptorPPR;
01674         int block_height = GlobalUtil::_DescriptorPPT/GlobalUtil::_DescriptorPPR;
01675         float* pd =  &_descriptor_buffer[0], * pbuf  = NULL;
01676         vector<float>read_buffer, descriptor_buffer2;
01677 
01678         //use another buffer, if we need to re-order the descriptors
01679         if(_keypoint_index.size() > 0)
01680         {
01681                 descriptor_buffer2.resize(_descriptor_buffer.size());
01682                 pd = &descriptor_buffer2[0];
01683         }
01684         FrameBufferObject fbo;
01685 
01686         GLTexImage * gtex, *otex, * ftex;
01687         GLenum buffers[8] = { 
01688                 GL_COLOR_ATTACHMENT0_EXT,               GL_COLOR_ATTACHMENT1_EXT ,
01689                 GL_COLOR_ATTACHMENT2_EXT,               GL_COLOR_ATTACHMENT3_EXT ,
01690                 GL_COLOR_ATTACHMENT4_EXT,               GL_COLOR_ATTACHMENT5_EXT ,
01691                 GL_COLOR_ATTACHMENT6_EXT,               GL_COLOR_ATTACHMENT7_EXT ,
01692         };
01693 
01694         glDrawBuffers(ndf, buffers);
01695         glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
01696 
01697 
01698         for( i = 0, idx = 0, ftex = _featureTex; i < _octave_num; i++)
01699         {
01700                 gtex = GetBaseLevel(i + _octave_min, DATA_GRAD) + 1;
01701                 otex = GetBaseLevel(i + _octave_min, DATA_ROT)  + 1;
01702                 for( j = 0; j < param._dog_level_num; j++, ftex++, idx++, gtex++, otex++)
01703                 {
01704                         if(_levelFeatureNum[idx]==0)continue;
01705 
01706             sigma = IsUsingRectDescription()?  0 : param.GetLevelSigma(j+param._level_min+1);
01707                         int count = _levelFeatureNum[idx] * block_width;
01708                         GetAlignedStorageSize(count, block_width, w, h);
01709                         h = ((int)ceil(double(count) / w)) * block_height;
01710 
01711                         //not enought space for holding the descriptor data
01712                         if(w > _descriptorTex[0].GetTexWidth() || h > _descriptorTex[0].GetTexHeight())
01713                         {
01714                                 for(k = 0; k < ndf; k++)_descriptorTex[k].InitTexture(w, h);
01715                         }
01716                         for(k = 0; k < ndf; k++)        _descriptorTex[k].AttachToFBO(k);
01717                         GlobalUtil::FitViewPort(w, h);
01718                         glActiveTexture(GL_TEXTURE0);
01719                         ftex->BindTex();
01720                         glActiveTexture(GL_TEXTURE1);
01721                         gtex->BindTex();
01722                         if(otex!=gtex)
01723                         {
01724                                 glActiveTexture(GL_TEXTURE2);
01725                                 otex->BindTex();
01726                         }
01727 
01728                         ShaderMan::UseShaderDescriptor(gtex->GetTexID(), otex->GetTexID(), 
01729                                 w, ftex->GetImgWidth(), gtex->GetImgWidth(), gtex->GetImgHeight(), sigma);
01730                         GLTexImage::DrawQuad(0, (float)w, 0, (float)h);
01731 
01732                          //read back float format descriptors and do normalization on CPU
01733                         int step = w*h*4;
01734                         if((unsigned int)step*ndf > read_buffer.size())
01735                         {
01736                                 read_buffer.resize(ndf*step);
01737                         }
01738                         pbuf = &read_buffer[0];
01739                         
01740                         //read back
01741                         for(k = 0; k < ndf; k++, pbuf+=step)
01742                         {
01743                                 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + k);
01744                                 if(GlobalUtil::_IsNvidia ||  w * h <=  16384) //were
01745                                 {
01746                                         glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, pbuf);
01747                                 }else
01748                                 {
01749                                         int hstep = 16384 / w; 
01750                                         for(int kk = 0; kk < h; kk += hstep)
01751                                                 glReadPixels(0, kk, w, min(hstep, h - kk), GL_RGBA, GL_FLOAT, pbuf + w * kk * 4);
01752                                 }
01753                         }
01754         
01755                         //the following two steps run on cpu, so better cpu better speed
01756                         //and release version can be a lot faster than debug version
01757                         //interlace data on the two texture to get the descriptor
01758                         InterlaceDescriptorF2(w / block_width, h / block_height, &read_buffer[0], pd, step);
01759                         
01760                         //need to do normalization
01761                         //the new version uses SSE to speed up this part
01762                         if(GlobalUtil::_NormalizedSIFT) NormalizeDescriptor(_levelFeatureNum[idx], pd);
01763 
01764                         pd += 128*_levelFeatureNum[idx];
01765                         glReadBuffer(GL_NONE);
01766                 }
01767         }
01768 
01769 
01770         //finally, put the descriptor back to their original order for existing keypoint list.
01771         if(_keypoint_index.size() > 0)
01772         {
01773                 for(i = 0; i < _featureNum; ++i)
01774                 {
01775                         int index = _keypoint_index[i];
01776                         memcpy(&_descriptor_buffer[index*128], &descriptor_buffer2[i*128], 128 * sizeof(float));
01777                 }
01778         }
01779 
01781         GLTexImage::UnbindMultiTex(3); 
01782         glDrawBuffer(GL_NONE);
01783         ShaderMan::UnloadProgram();
01784         if(GlobalUtil::_timingS)glFinish();
01785         for(i = 0; i < ndf; i++) fbo.UnattachTex(GL_COLOR_ATTACHMENT0_EXT +i);
01786 
01787 }
01788 
01789 
01790 void PyramidGL::DownloadKeypoints()
01791 {
01792         const double twopi = 2.0*3.14159265358979323846;
01793         int idx = 0;
01794         float * buffer = &_keypoint_buffer[0];
01795         vector<float> keypoint_buffer2;
01796         //use a different keypoint buffer when processing with an exisint features list
01797         //without orientation information. 
01798         if(_keypoint_index.size() > 0)
01799         {
01800                 keypoint_buffer2.resize(_keypoint_buffer.size());
01801                 buffer = &keypoint_buffer2[0];
01802         }
01803         float * p = buffer, *ps, sigma;
01804         GLTexImage * ftex = _featureTex;
01805         FrameBufferObject fbo;
01806         ftex->FitRealTexViewPort();
01808         float os = _octave_min>=0? float(1<<_octave_min): 1.0f/(1<<(-_octave_min));
01809         if(_down_sample_factor>0) os *= float(1<<_down_sample_factor); 
01810         float offset = GlobalUtil::_LoweOrigin? 0 : 0.5f;
01812         for(int i = 0; i < _octave_num; i++, os *= 2.0f)
01813         {
01814                 
01815                 for(int j = 0; j  < param._dog_level_num; j++, idx++, ftex++)
01816                 {
01817 
01818                         if(_levelFeatureNum[idx]>0)
01819                         {       
01820                                 ftex->AttachToFBO(0);
01821                                 glReadPixels(0, 0, ftex->GetImgWidth(), ftex->GetImgHeight(),GL_RGBA, GL_FLOAT, p);
01822                                 ps = p;
01823                                 for(int k = 0;  k < _levelFeatureNum[idx]; k++, ps+=4)
01824                                 {
01825                                         ps[0] = os*(ps[0]-0.5f) + offset;       //x
01826                                         ps[1] = os*(ps[1]-0.5f) + offset;       //y
01827                                         sigma = os*ps[3]; 
01828                                         ps[3] = (float)fmod(twopi-ps[2], twopi);        //orientation, mirrored
01829                                         ps[2] = sigma;  //scale
01830                                 }
01831                                 p+= 4* _levelFeatureNum[idx];
01832                         }
01833                 }
01834         }
01835 
01836         //put the feature into their original order
01837 
01838         if(_keypoint_index.size() > 0)
01839         {
01840                 for(int i = 0; i < _featureNum; ++i)
01841                 {
01842                         int index = _keypoint_index[i];
01843                         memcpy(&_keypoint_buffer[index*4], &keypoint_buffer2[i*4], 4 * sizeof(float));
01844                 }
01845         }
01846 }
01847 
01848 
01849 void PyramidGL::GenerateFeatureListTex()
01850 {
01851         //generate feature list texture from existing keypoints
01852         //do feature sorting in the same time?
01853 
01854         FrameBufferObject fbo;
01855         vector<float> list;
01856         int idx = 0;
01857         const double twopi = 2.0*3.14159265358979323846;
01858         float sigma_half_step = powf(2.0f, 0.5f / param._dog_level_num);
01859         float octave_sigma = _octave_min>=0? float(1<<_octave_min): 1.0f/(1<<(-_octave_min));
01860         float offset = GlobalUtil::_LoweOrigin? 0 : 0.5f; 
01861         if(_down_sample_factor>0) octave_sigma *= float(1<<_down_sample_factor); 
01862 
01863     
01864     std::fill(_levelFeatureNum, _levelFeatureNum + _octave_num * param._dog_level_num, 0);
01865 
01866         _keypoint_index.resize(0); // should already be 0
01867         for(int i = 0; i < _octave_num; i++, octave_sigma*= 2.0f)
01868         {
01869                 for(int j = 0; j < param._dog_level_num; j++, idx++)
01870                 {
01871                         list.resize(0);
01872                         float level_sigma = param.GetLevelSigma(j + param._level_min + 1) * octave_sigma;
01873                         float sigma_min = level_sigma / sigma_half_step;
01874                         float sigma_max = level_sigma * sigma_half_step;
01875                         int fcount = 0 ;
01876                         for(int k = 0; k < _featureNum; k++)
01877                         {
01878                                 float * key = &_keypoint_buffer[k*4];
01879                 float sigmak = key[2]; 
01880 
01882                 if(IsUsingRectDescription()) sigmak = min(key[2], key[3]) / 12.0f; 
01883 
01884                 if( (sigmak >= sigma_min && sigmak < sigma_max)
01885                                         ||(sigmak < sigma_min && i ==0 && j == 0)
01886                                         ||(sigmak > sigma_max && j == param._dog_level_num - 1&& 
01887                             (i == _octave_num -1  || GlobalUtil::_KeyPointListForceLevel0)))
01888                                 {
01889                                         //add this keypoint to the list
01890                                         list.push_back((key[0] - offset) / octave_sigma + 0.5f);
01891                                         list.push_back((key[1] - offset) / octave_sigma + 0.5f);
01892                     if(IsUsingRectDescription())
01893                     {
01894                         list.push_back(key[2] / octave_sigma);
01895                         list.push_back(key[3] / octave_sigma);
01896                     }else
01897                     {
01898                                             list.push_back((float)fmod(twopi-key[3], twopi));
01899                                             list.push_back(key[2] / octave_sigma);
01900                     }
01901                                         fcount ++;
01902                                         //save the index of keypoints
01903                                         _keypoint_index.push_back(k);
01904                                 }
01905                         }
01906 
01907                         _levelFeatureNum[idx] = fcount;
01908                         if(fcount==0)continue;
01909                         GLTexImage * ftex = _featureTex+idx;
01910 
01911                         SetLevelFeatureNum(idx, fcount);
01912 
01913                         int fw = ftex->GetImgWidth();
01914                         int fh = ftex->GetImgHeight();
01915 
01916                         list.resize(4*fh*fw);
01917 
01918                         ftex->BindTex();
01919                         ftex->AttachToFBO(0);
01920                         glTexSubImage2D(GlobalUtil::_texTarget, 0, 0, 0, fw, fh, GL_RGBA, GL_FLOAT, &list[0]);
01921 
01922             if( fcount == _featureNum) _keypoint_index.resize(0);
01923                 }
01924         if( GlobalUtil::_KeyPointListForceLevel0 ) break;
01925         }
01926         GLTexImage::UnbindTex();
01927         if(GlobalUtil::_verbose)
01928         {
01929                 std::cout<<"#Features:\t"<<_featureNum<<"\n";
01930         }
01931 }
01932 
01933 
01934 
01935 PyramidPacked::PyramidPacked(SiftParam& sp): PyramidGL(sp)
01936 {
01937         _allPyramid = NULL;
01938 }
01939 
01940 PyramidPacked::~PyramidPacked()
01941 {
01942         DestroyPyramidData();
01943 }
01944 
01945 
01946 //build the gaussian pyrmaid
01947 
01948 void PyramidPacked::BuildPyramid(GLTexInput * input)
01949 {
01950         //
01951         USE_TIMING();
01952         GLTexImage * tex, *tmp;
01953         FilterProgram ** filter;
01954         FrameBufferObject fbo;
01955 
01956         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
01957         input->FitTexViewPort();
01958 
01959         for (int i = _octave_min; i < _octave_min + _octave_num; i++)
01960         {
01961                 tex = GetBaseLevel(i);
01962                 tmp = GetBaseLevel(i, DATA_DOG) + 2; //use this as a temperory texture
01963 
01964                 
01965                 filter = ShaderMan::s_bag->f_gaussian_step;
01966 
01967                 OCTAVE_START();
01968 
01969                 if( i == _octave_min )
01970                 {
01971                         if(i < 0)       TextureUpSample(tex, input, 1<<(-i-1));                 
01972                         else        TextureDownSample(tex, input, 1<<(i+1));
01973             ShaderMan::FilterInitialImage(tex, tmp); 
01974                 }else
01975                 {
01976                         TextureDownSample(tex, GetLevelTexture(i-1, param._level_ds)); 
01977                         ShaderMan::FilterSampledImage(tex, tmp); 
01978                 }
01979                 LEVEL_FINISH();         
01980 
01981                 for(int j = param._level_min + 1; j <=  param._level_max ; j++, tex++, filter++)
01982                 {
01983                         // filtering
01984             ShaderMan::FilterImage(*filter, tex+1, tex, tmp);
01985                         LEVEL_FINISH();
01986                 }
01987 
01988                 OCTAVE_FINISH();
01989 
01990         }
01991         if(GlobalUtil::_timingS)        glFinish();
01992         UnloadProgram();        
01993 }
01994 
01995 void PyramidPacked::ComputeGradient()
01996 {
01997         
01998         //first pass, compute dog, gradient, orientation
01999         GLenum buffers[4] = { 
02000                 GL_COLOR_ATTACHMENT0_EXT,               GL_COLOR_ATTACHMENT1_EXT ,
02001                 GL_COLOR_ATTACHMENT2_EXT,               GL_COLOR_ATTACHMENT3_EXT
02002         };
02003 
02004         int i, j;
02005         double ts, t1;
02006         FrameBufferObject fbo;
02007 
02008         if(GlobalUtil::_timingS && GlobalUtil::_verbose)ts = CLOCK();
02009 
02010         for(i = _octave_min; i < _octave_min + _octave_num; i++)
02011         {
02012                 GLTexImage * gus = GetBaseLevel(i) +  1;
02013                 GLTexImage * dog = GetBaseLevel(i, DATA_DOG) +  1;
02014                 GLTexImage * grd = GetBaseLevel(i, DATA_GRAD) +  1;
02015                 GLTexImage * rot = GetBaseLevel(i, DATA_ROT) +  1;
02016                 glDrawBuffers(3, buffers);
02017                 gus->FitTexViewPort();
02018                 //compute the gradient
02019                 for(j = 0; j <  param._dog_level_num ; j++, gus++, dog++, grd++, rot++)
02020                 {
02021                         //gradient, dog, orientation
02022                         glActiveTexture(GL_TEXTURE0);
02023                         gus->BindTex();
02024                         glActiveTexture(GL_TEXTURE1);
02025                         (gus-1)->BindTex();
02026                         //output
02027                         dog->AttachToFBO(0);
02028                         grd->AttachToFBO(1);
02029                         rot->AttachToFBO(2);
02030                         ShaderMan::UseShaderGradientPass((gus-1)->GetTexID());
02031                         //compute
02032                         dog->DrawQuadMT4();
02033                 }
02034         }
02035         if(GlobalUtil::_timingS)
02036         {
02037                 glFinish();
02038                 if(GlobalUtil::_verbose)
02039                 {
02040                         t1 = CLOCK();
02041                         std::cout       <<"<Gradient, DOG  >\t"<<(t1-ts)<<"\n";
02042                 }
02043         }
02044         GLTexImage::DetachFBO(1);
02045         GLTexImage::DetachFBO(2);
02046         UnloadProgram();
02047         GLTexImage::UnbindMultiTex(3);
02048         fbo.UnattachTex(GL_COLOR_ATTACHMENT1_EXT);
02049 }
02050 
02051 void PyramidPacked::DetectKeypointsEX()
02052 {
02053 
02054         //first pass, compute dog, gradient, orientation
02055         GLenum buffers[4] = { 
02056                 GL_COLOR_ATTACHMENT0_EXT,               GL_COLOR_ATTACHMENT1_EXT ,
02057                 GL_COLOR_ATTACHMENT2_EXT,               GL_COLOR_ATTACHMENT3_EXT
02058         };
02059 
02060         int i, j;
02061         double t0, t, ts, t1, t2;
02062         FrameBufferObject fbo;
02063 
02064         if(GlobalUtil::_timingS && GlobalUtil::_verbose)ts = CLOCK();
02065 
02066         for(i = _octave_min; i < _octave_min + _octave_num; i++)
02067         {
02068                 GLTexImage * gus = GetBaseLevel(i) + 1;
02069                 GLTexImage * dog = GetBaseLevel(i, DATA_DOG) + 1;
02070                 GLTexImage * grd = GetBaseLevel(i, DATA_GRAD) + 1;
02071                 GLTexImage * rot = GetBaseLevel(i, DATA_ROT) + 1;
02072                 glDrawBuffers(3, buffers);
02073                 gus->FitTexViewPort();
02074                 //compute the gradient
02075                 for(j = param._level_min +1; j <=  param._level_max ; j++, gus++, dog++, grd++, rot++)
02076                 {
02077                         //gradient, dog, orientation
02078                         glActiveTexture(GL_TEXTURE0);
02079                         gus->BindTex();
02080                         glActiveTexture(GL_TEXTURE1);
02081                         (gus-1)->BindTex();
02082                         //output
02083                         dog->AttachToFBO(0);
02084                         grd->AttachToFBO(1);
02085                         rot->AttachToFBO(2);
02086                         ShaderMan::UseShaderGradientPass((gus-1)->GetTexID());
02087                         //compute
02088                         dog->DrawQuadMT4();
02089                 }
02090         }
02091         if(GlobalUtil::_timingS && GlobalUtil::_verbose)
02092         {
02093                 glFinish();
02094                 t1 = CLOCK();
02095         }
02096         GLTexImage::DetachFBO(1);
02097         GLTexImage::DetachFBO(2);
02098         //glDrawBuffers(1, buffers);
02099         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
02100         
02101 
02102         GlobalUtil::CheckErrorsGL();
02103 
02104         for ( i = _octave_min; i < _octave_min + _octave_num; i++)
02105         {
02106                 if(GlobalUtil::_timingO)
02107                 {
02108                         t0 = CLOCK();
02109                         std::cout<<"#"<<(i + _down_sample_factor)<<"\t";
02110                 }
02111                 GLTexImage * dog = GetBaseLevel(i, DATA_DOG) + 2;
02112                 GLTexImage * key = GetBaseLevel(i, DATA_KEYPOINT) +2;
02113                 GLTexImage * gus = GetBaseLevel(i) +  2;
02114                 key->FitTexViewPort();
02115 
02116                 for( j = param._level_min +2; j <  param._level_max ; j++, dog++, key++, gus++)
02117                 {
02118                         if(GlobalUtil::_timingL)t = CLOCK();            
02119                         key->AttachToFBO(0);
02120                         glActiveTexture(GL_TEXTURE0);
02121                         dog->BindTex();
02122                         glActiveTexture(GL_TEXTURE1);
02123                         (dog+1)->BindTex();
02124                         glActiveTexture(GL_TEXTURE2);
02125                         (dog-1)->BindTex();
02126                         if(GlobalUtil::_DarknessAdaption)
02127                         {
02128                                 glActiveTexture(GL_TEXTURE3);
02129                                 gus->BindTex();
02130                         }
02131                         ShaderMan::UseShaderKeypoint((dog+1)->GetTexID(), (dog-1)->GetTexID());
02132                         key->DrawQuadMT8();
02133                         if(GlobalUtil::_timingL)
02134                         {
02135                                 glFinish();
02136                                 std::cout<<(CLOCK()-t)<<"\t";
02137                         }
02138                 }
02139                 if(GlobalUtil::_timingO)
02140                 {
02141                         glFinish();
02142                         std::cout<<"|\t"<<(CLOCK()-t0)<<"\n";
02143                 }
02144         }
02145 
02146         if(GlobalUtil::_timingS)
02147         {
02148                 glFinish();
02149                 if(GlobalUtil::_verbose) 
02150                 {       
02151                         t2 = CLOCK();
02152                         std::cout       <<"<Gradient, DOG  >\t"<<(t1-ts)<<"\n"
02153                                                 <<"<Get Keypoints  >\t"<<(t2-t1)<<"\n";
02154                 }
02155                                                 
02156         }
02157         UnloadProgram();
02158         GLTexImage::UnbindMultiTex(3);
02159         fbo.UnattachTex(GL_COLOR_ATTACHMENT1_EXT);
02160 }
02161 
02162 
02163 void PyramidPacked::GenerateFeatureList(int i, int j)
02164 {
02165         float fcount = 0.0f; 
02166         int hist_skip_gpu = GlobalUtil::_ListGenSkipGPU;
02167     int idx = i * param._dog_level_num + j; 
02168     int hist_level_num = _hpLevelNum - _pyramid_octave_first;
02169         GLTexImage * htex, * ftex, * tex;
02170         htex = _histoPyramidTex + hist_level_num - 1 - i;
02171         ftex = _featureTex + idx;
02172         tex = GetBaseLevel(_octave_min + i, DATA_KEYPOINT) + 2 + j;
02173 
02174 
02175         //fill zero to an extra row/col if the height/width is odd
02176         glActiveTexture(GL_TEXTURE0);
02177         tex->BindTex();
02178         htex->AttachToFBO(0);
02179         int tight = (htex->GetImgWidth() * 4 == tex->GetImgWidth() -1 && htex->GetImgHeight() *4 == tex->GetImgHeight()-1 );
02180         ShaderMan::UseShaderGenListInit(tex->GetImgWidth(), tex->GetImgHeight(), tight);
02181         htex->FitTexViewPort();
02182         //this uses the fact that no feature is on the edge.
02183         htex->DrawQuadReduction();
02184         //reduction..
02185         htex--;
02186         
02187         //this part might have problems on several GPUS
02188         //because the output of one pass is the input of the next pass
02189         //may require glFinish to make it right, but too much glFinish makes it slow
02190         for(int k = 0; k <hist_level_num - i-1 - hist_skip_gpu; k++, htex--)
02191         {
02192                 htex->AttachToFBO(0);
02193                 htex->FitTexViewPort();
02194                 (htex+1)->BindTex();
02195                 ShaderMan::UseShaderGenListHisto();
02196                 htex->DrawQuadReduction();              
02197         }
02198 
02199         if(hist_skip_gpu == 0)
02200         {               
02201                 //read back one pixel
02202                 float fn[4];
02203                 glReadPixels(0, 0, 1, 1, GL_RGBA , GL_FLOAT, fn);
02204                 fcount = (fn[0] + fn[1] + fn[2] + fn[3]);
02205                 if(fcount < 1) fcount = 0;
02206 
02207                 _levelFeatureNum[ idx] = (int)(fcount);
02208                 SetLevelFeatureNum(idx, (int)fcount);
02209 
02210                 //save  number of features
02211                 _featureNum += int(fcount);
02212 
02213                 //
02214                 if(fcount < 1.0)                                return;;
02215 
02216 
02218                 htex=  _histoPyramidTex;
02219 
02220                 htex->BindTex();
02221 
02222                 //first pass
02223                 ftex->AttachToFBO(0);
02224                 if(GlobalUtil::_MaxOrientation>1)
02225                 {
02226                         //this is very important...
02227                         ftex->FitRealTexViewPort();
02228                         glClear(GL_COLOR_BUFFER_BIT);
02229                         glFinish();
02230                 }else
02231                 {       
02232                         ftex->FitTexViewPort();
02233                         //glFinish();
02234                 }
02235 
02236 
02237                 ShaderMan::UseShaderGenListStart((float)ftex->GetImgWidth(), htex->GetTexID());
02238 
02239                 ftex->DrawQuad();
02240                 //make sure it finishes before the next step
02241                 ftex->DetachFBO(0);
02242                 //pass on each pyramid level
02243                 htex++;
02244         }else
02245         {
02246 
02247                 int tw = htex[1].GetDrawWidth(), th = htex[1].GetDrawHeight();
02248                 int fc = 0;
02249                 glReadPixels(0, 0, tw, th, GL_RGBA , GL_FLOAT, _histo_buffer);  
02250                 _keypoint_buffer.resize(0);
02251                 for(int y = 0, pos = 0; y < th; y++)
02252                 {
02253                         for(int x= 0; x < tw; x++)
02254                         {
02255                                 for(int c = 0; c < 4; c++, pos++)
02256                                 {
02257                                         int ss =  (int) _histo_buffer[pos]; 
02258                                         if(ss == 0) continue;
02259                                         float ft[4] = {2 * x + (c%2? 1.5f:  0.5f), 2 * y + (c>=2? 1.5f: 0.5f), 0, 1 };
02260                                         for(int t = 0; t < ss; t++)
02261                                         {
02262                                                 ft[2] = (float) t; 
02263                                                 _keypoint_buffer.insert(_keypoint_buffer.end(), ft, ft+4);
02264                                         }
02265                                         fc += (int)ss; 
02266                                 }
02267                         }
02268                 }
02269                 _levelFeatureNum[ idx] = fc;
02270                 SetLevelFeatureNum(idx, fc);
02271                 if(fc == 0)  return; 
02272 
02273                 fcount = (float) fc;    
02274                 _featureNum += fc;
02276                 ftex->AttachToFBO(0);
02277                 if(GlobalUtil::_MaxOrientation>1)
02278                 {
02279                         ftex->FitRealTexViewPort();
02280                         glClear(GL_COLOR_BUFFER_BIT);
02281                         glFlush();
02282                 }else
02283                 {                                       
02284                         ftex->FitTexViewPort();
02285             glFlush();
02286                 }
02287                 _keypoint_buffer.resize(ftex->GetDrawWidth() * ftex->GetDrawHeight()*4, 0);
02289                 glActiveTexture(GL_TEXTURE0);
02290                 ftex->BindTex();
02291                 glTexSubImage2D(GlobalUtil::_texTarget, 0, 0, 0, ftex->GetDrawWidth(),
02292                         ftex->GetDrawHeight(), GL_RGBA, GL_FLOAT, &_keypoint_buffer[0]);
02293                 htex += 2; 
02294         }
02295 
02296         for(int lev = 1 + hist_skip_gpu; lev < hist_level_num  - i; lev++, htex++)
02297         {
02298                 glActiveTexture(GL_TEXTURE0);
02299                 ftex->BindTex();
02300                 ftex->AttachToFBO(0);
02301                 glActiveTexture(GL_TEXTURE1);
02302                 htex->BindTex();
02303                 ShaderMan::UseShaderGenListStep(ftex->GetTexID(), htex->GetTexID());
02304                 ftex->DrawQuad();
02305                 ftex->DetachFBO(0);     
02306         }
02307 
02308         ftex->AttachToFBO(0);
02309         glActiveTexture(GL_TEXTURE1);
02310         tex->BindTex();
02311         ShaderMan::UseShaderGenListEnd(tex->GetTexID());
02312         ftex->DrawQuad();
02313         GLTexImage::UnbindMultiTex(2);
02314 
02315 }
02316 
02317 void PyramidPacked::GenerateFeatureList()
02318 {
02319         //generate the histogram pyramid
02320         FrameBufferObject fbo;
02321         glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
02322         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
02323         double t1, t2; 
02324         int ocount= 0, reverse = (GlobalUtil::_TruncateMethod == 1);
02325         _featureNum = 0;
02326 
02327         FitHistogramPyramid();
02328         //for(int i = 0, idx = 0; i < _octave_num; i++)
02329     FOR_EACH_OCTAVE(i, reverse)
02330         {
02331                 if(GlobalUtil::_timingO)
02332                 {
02333             t1= CLOCK();
02334                         ocount = 0;
02335                         std::cout<<"#"<<i+_octave_min + _down_sample_factor<<":\t";
02336                 }
02337                 //for(int j = 0; j < param._dog_level_num; j++, idx++)
02338         FOR_EACH_LEVEL(j, reverse)
02339                 {
02340             if(GlobalUtil::_TruncateMethod && GlobalUtil::_FeatureCountThreshold > 0
02341                                 && _featureNum > GlobalUtil::_FeatureCountThreshold) 
02342                         {
02343                                 _levelFeatureNum[i * param._dog_level_num + j] = 0;
02344                                 continue;
02345                         }
02346             
02347             GenerateFeatureList(i, j); 
02348 
02349                         if(GlobalUtil::_timingO)
02350                         {
02351                 int idx = i * param._dog_level_num + j;
02352                 ocount += _levelFeatureNum[idx];
02353                                 std::cout<< _levelFeatureNum[idx] <<"\t";
02354                         }
02355                 }
02356                 if(GlobalUtil::_timingO)
02357                 {       
02358             t2 = CLOCK();
02359                         std::cout << "| \t" << int(ocount) << " :\t(" << (t2 - t1) << ")\n";
02360                 }
02361         }
02362         if(GlobalUtil::_timingS)glFinish();
02363         if(GlobalUtil::_verbose)
02364         {
02365                 std::cout<<"#Features:\t"<<_featureNum<<"\n";
02366         }
02367 
02368 }
02369 
02370 void PyramidPacked::GenerateFeatureListCPU()
02371 {
02372         FrameBufferObject fbo;
02373         _featureNum = 0;
02374         GLTexImage * tex = GetBaseLevel(_octave_min);
02375         float * mem = new float [tex->GetTexWidth()*tex->GetTexHeight()*4];
02376         vector<float> list;
02377         int idx = 0;
02378         for(int i = 0; i < _octave_num; i++)
02379         {
02380                 for(int j = 0; j < param._dog_level_num; j++, idx++)
02381                 {
02382                         tex = GetBaseLevel(_octave_min + i, DATA_KEYPOINT) + j + 2;
02383                         tex->BindTex();
02384                         glGetTexImage(GlobalUtil::_texTarget, 0, GL_RGBA, GL_FLOAT, mem);
02385                         //tex->AttachToFBO(0);
02386                         //tex->FitTexViewPort();
02387                         //glReadPixels(0, 0, tex->GetTexWidth(), tex->GetTexHeight(), GL_RED, GL_FLOAT, mem);
02388                         //
02389                         //make a list of 
02390                         list.resize(0);
02391                         float *pl = mem;
02392                         int fcount = 0 ;
02393                         for(int k = 0; k < tex->GetDrawHeight(); k++)
02394                         {
02395                                 float * p = pl; 
02396                                 pl += tex->GetTexWidth() * 4;
02397                                 for( int m = 0; m < tex->GetDrawWidth(); m ++, p+=4)
02398                                 {
02399                                 //      if(m ==0 || k ==0 || k == tex->GetDrawHeight() -1 || m == tex->GetDrawWidth() -1) continue;
02400                                 //      if(*p == 0) continue;
02401                                         int t = ((int) fabs(p[0])) - 1;
02402                                         if(t < 0) continue;
02403                                         int xx = m + m + ( (t %2)? 1 : 0);
02404                                         int yy = k + k + ( (t <2)? 0 : 1);
02405                                         if(xx ==0 || yy == 0) continue;
02406                                         if(xx >= tex->GetImgWidth() - 1 || yy >= tex->GetImgHeight() - 1)continue;
02407                                         list.push_back(xx + 0.5f + p[1]);
02408                                         list.push_back(yy + 0.5f + p[2]);
02409                                         list.push_back(GlobalUtil::_KeepExtremumSign && p[0] < 0 ? -1.0f : 1.0f);
02410                                         list.push_back(p[3]);
02411                                         fcount ++;
02412                                 }
02413                         }
02414                         if(fcount==0)continue;
02415 
02416                         if(GlobalUtil::_timingL) std::cout<<fcount<<".";
02417                         
02418                         GLTexImage * ftex = _featureTex+idx;
02419                         _levelFeatureNum[idx] = (fcount);
02420                         SetLevelFeatureNum(idx, fcount);
02421 
02422                         _featureNum += (fcount);
02423 
02424 
02425                         int fw = ftex->GetImgWidth();
02426                         int fh = ftex->GetImgHeight();
02427 
02428                         list.resize(4*fh*fw);
02429 
02430                         ftex->BindTex();
02431                         ftex->AttachToFBO(0);
02432         //              glTexImage2D(GlobalUtil::_texTarget, 0, GlobalUtil::_iTexFormat, fw, fh, 0, GL_BGRA, GL_FLOAT, &list[0]);
02433                         glTexSubImage2D(GlobalUtil::_texTarget, 0, 0, 0, fw, fh, GL_RGBA, GL_FLOAT, &list[0]);
02434                         //
02435                 }
02436         }
02437         GLTexImage::UnbindTex();
02438         delete[] mem;
02439         if(GlobalUtil::_verbose)
02440         {
02441                 std::cout<<"#Features:\t"<<_featureNum<<"\n";
02442         }
02443 }
02444 
02445 
02446 
02447 void PyramidPacked::GetFeatureOrientations()
02448 {
02449         GLTexImage * gtex, * otex;
02450         GLTexImage * ftex = _featureTex;
02451         GLTexImage * fotex = _orientationTex; 
02452         int * count      = _levelFeatureNum;
02453         float sigma, sigma_step = powf(2.0f, 1.0f/param._dog_level_num);
02454 
02455 
02456         FrameBufferObject fbo;
02457         if(_orientationTex)
02458         {
02459                 GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT };
02460                 glDrawBuffers(2, buffers);
02461         }else
02462         {
02463                 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
02464         }
02465 
02466         for(int i = 0; i < _octave_num; i++)
02467         {
02468                 gtex = GetBaseLevel(i+_octave_min, DATA_GRAD) + 1;
02469                 otex = GetBaseLevel(i+_octave_min, DATA_ROT) + 1;
02470 
02471                 for(int j = 0; j < param._dog_level_num; j++, ftex++, otex++, count++, gtex++, fotex++)
02472                 {
02473                         if(*count<=0)continue;
02474 
02475                         sigma = param.GetLevelSigma(j+param._level_min+1);
02476 
02477 
02478                         ftex->FitTexViewPort();
02479 
02480                         glActiveTexture(GL_TEXTURE0);
02481                         ftex->BindTex();
02482                         glActiveTexture(GL_TEXTURE1);
02483                         gtex->BindTex();
02484                         glActiveTexture(GL_TEXTURE2);
02485                         otex->BindTex();
02486                         //
02487                         ftex->AttachToFBO(0);
02488                         if(_orientationTex)             fotex->AttachToFBO(1);
02489 
02490                         GlobalUtil::CheckFramebufferStatus();
02491 
02492                         ShaderMan::UseShaderOrientation(gtex->GetTexID(),
02493                                 gtex->GetImgWidth(), gtex->GetImgHeight(),
02494                                 sigma, otex->GetTexID(), sigma_step, _existing_keypoints);
02495                         ftex->DrawQuad();
02496                 }
02497         }
02498 
02499         GLTexImage::UnbindMultiTex(3);
02500         if(GlobalUtil::_timingS)glFinish();
02501         if(_orientationTex)     fbo.UnattachTex(GL_COLOR_ATTACHMENT1_EXT);
02502 
02503 }
02504 
02505 
02506 void PyramidPacked::GetSimplifiedOrientation()
02507 {
02508         //
02509         int idx = 0;
02510 //      int n = _octave_num  * param._dog_level_num;
02511         float sigma, sigma_step = powf(2.0f, 1.0f/param._dog_level_num); 
02512         GLTexImage * ftex = _featureTex;
02513 
02514         FrameBufferObject fbo;
02515         glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
02516         for(int i = 0; i < _octave_num; i++)
02517         {
02518                 GLTexImage *otex = GetBaseLevel(i + _octave_min, DATA_ROT) + 2;
02519                 for(int j = 0; j < param._dog_level_num; j++, ftex++,  otex++, idx ++)
02520                 {
02521                         if(_levelFeatureNum[idx]<=0)continue;
02522                         sigma = param.GetLevelSigma(j+param._level_min+1);
02523                         //
02524                         ftex->AttachToFBO(0);
02525                         ftex->FitTexViewPort();
02526 
02527                         glActiveTexture(GL_TEXTURE0);
02528                         ftex->BindTex();
02529                         glActiveTexture(GL_TEXTURE1);
02530                         otex->BindTex();
02531 
02532                         ShaderMan::UseShaderSimpleOrientation(otex->GetTexID(), sigma, sigma_step);
02533                         ftex->DrawQuad();
02534                 }
02535         }
02536         GLTexImage::UnbindMultiTex(2);
02537 }
02538 
02539 void PyramidPacked::InitPyramid(int w, int h, int ds)
02540 {
02541         int wp, hp, toobig = 0;
02542         if(ds == 0)
02543         {
02544                 _down_sample_factor = 0;
02545                 if(GlobalUtil::_octave_min_default>=0)
02546                 {
02547                         wp = w >> GlobalUtil::_octave_min_default;
02548                         hp = h >> GlobalUtil::_octave_min_default;
02549                 }else 
02550                 {
02551                         wp = w << (-GlobalUtil::_octave_min_default);
02552                         hp = h << (-GlobalUtil::_octave_min_default);
02553                 }
02554                 _octave_min = _octave_min_default;
02555         }else
02556         {
02557                 //must use 0 as _octave_min; 
02558                 _octave_min = 0;
02559                 _down_sample_factor = ds;
02560                 w >>= ds;
02561                 h >>= ds;
02562                 wp = w;
02563                 hp = h; 
02564         }
02565 
02566         while(wp > GlobalUtil::_texMaxDim  || hp > GlobalUtil::_texMaxDim )
02567         {
02568                 _octave_min ++;
02569                 wp >>= 1;
02570                 hp >>= 1;
02571                 toobig = 1;
02572         }
02573 
02574         while(GlobalUtil::_MemCapGPU > 0 && GlobalUtil::_FitMemoryCap && (wp >_pyramid_width || hp > _pyramid_height) &&
02575                 max(max(wp, hp), max(_pyramid_width, _pyramid_height)) >  1024 * sqrt(GlobalUtil::_MemCapGPU / 96.0) )
02576         {
02577                 _octave_min ++;
02578                 wp >>= 1;
02579                 hp >>= 1;
02580                 toobig = 2;
02581         }
02582 
02583         if(toobig && GlobalUtil::_verbose)
02584         {
02585                 std::cout<<(toobig == 2 ? "[**SKIP OCTAVES**]:\tExceeding Memory Cap (-nomc)\n" :
02586                                         "[**SKIP OCTAVES**]:\tReaching the dimension limit (-maxd)!\n");
02587         }
02588 
02589         if( wp == _pyramid_width && hp == _pyramid_height && _allocated )
02590         {
02591                 FitPyramid(wp, hp);
02592         }else if(GlobalUtil::_ForceTightPyramid || _allocated ==0)
02593         {
02594                 ResizePyramid(wp, hp);
02595         }
02596         else if( wp > _pyramid_width || hp > _pyramid_height )
02597         {
02598                 ResizePyramid(max(wp, _pyramid_width), max(hp, _pyramid_height));
02599                 if(wp < _pyramid_width || hp < _pyramid_height)  FitPyramid(wp, hp);
02600         }
02601         else
02602         {
02603                 //try use the pyramid allocated for large image on small input images
02604                 FitPyramid(wp, hp);
02605         }
02606 
02607         //select the initial smoothing filter according to the new _octave_min
02608         ShaderMan::SelectInitialSmoothingFilter(_octave_min + _down_sample_factor, param);
02609 }
02610 
02611 
02612 
02613 void PyramidPacked::FitPyramid(int w, int h)
02614 {
02615         //(w, h) <= (_pyramid_width, _pyramid_height);
02616 
02617         _pyramid_octave_first = 0;
02618         //
02619         _octave_num  = GlobalUtil::_octave_num_default;
02620 
02621         int _octave_num_max = GetRequiredOctaveNum(min(w, h));
02622 
02623         if(_octave_num < 1 || _octave_num > _octave_num_max) 
02624         {
02625                 _octave_num = _octave_num_max;
02626         }
02627 
02628 
02629         int pw = _pyramid_width>>1, ph = _pyramid_height>>1;
02630         while(_pyramid_octave_first + _octave_num < _pyramid_octave_num &&  
02631                 pw >= w && ph >= h)
02632         {
02633                 _pyramid_octave_first++;
02634                 pw >>= 1;
02635                 ph >>= 1;
02636         }
02637 
02638         for(int i = 0; i < _octave_num; i++)
02639         {
02640                 GLTexImage * tex = GetBaseLevel(i + _octave_min);
02641                 GLTexImage * dog = GetBaseLevel(i + _octave_min, DATA_DOG);
02642                 GLTexImage * grd = GetBaseLevel(i + _octave_min, DATA_GRAD);
02643                 GLTexImage * rot = GetBaseLevel(i + _octave_min, DATA_ROT);
02644                 GLTexImage * key = GetBaseLevel(i + _octave_min, DATA_KEYPOINT);
02645                 for(int j = param._level_min; j <= param._level_max; j++, tex++, dog++, grd++, rot++, key++)
02646                 {
02647                         tex->SetImageSize(w, h);
02648                         if(j == param._level_min) continue;
02649                         dog->SetImageSize(w, h);
02650                         grd->SetImageSize(w, h);
02651                         rot->SetImageSize(w, h);
02652                         if(j == param._level_min + 1 || j == param._level_max) continue;
02653                         key->SetImageSize(w, h);
02654                 }
02655                 w>>=1;
02656                 h>>=1;
02657         }
02658 }
02659 
02660 
02661 void PyramidPacked::ResizePyramid( int w,  int h)
02662 {
02663         //
02664         unsigned int totalkb = 0;
02665         int _octave_num_new, input_sz, i, j;
02666         //
02667 
02668         if(_pyramid_width == w && _pyramid_height == h && _allocated) return;
02669 
02670         if(w > GlobalUtil::_texMaxDim || h > GlobalUtil::_texMaxDim) return ;
02671 
02672         if(GlobalUtil::_verbose && GlobalUtil::_timingS) std::cout<<"[Allocate Pyramid]:\t" <<w<<"x"<<h<<endl;
02673         //first octave does not change
02674         _pyramid_octave_first = 0;
02675 
02676         
02677         //compute # of octaves
02678 
02679         input_sz = min(w,h) ;
02680         _pyramid_width =  w;
02681         _pyramid_height =  h;
02682 
02683         //reset to preset parameters
02684         _octave_num_new  = GlobalUtil::_octave_num_default;
02685 
02686         if(_octave_num_new < 1) _octave_num_new = GetRequiredOctaveNum(input_sz) ;
02687 
02688 
02689         if(_pyramid_octave_num != _octave_num_new)
02690         {
02691                 //destroy the original pyramid if the # of octave changes
02692                 if(_octave_num >0) 
02693                 {
02694                         DestroyPerLevelData();
02695                         DestroyPyramidData();
02696                 }
02697                 _pyramid_octave_num = _octave_num_new;
02698         }
02699 
02700         _octave_num = _pyramid_octave_num;
02701 
02702         int noct = _octave_num;
02703         int nlev = param._level_num;
02704 
02705         //      //initialize the pyramid
02706         if(_allPyramid==NULL)   _allPyramid = new GLTexPacked[ noct* nlev * DATA_NUM];
02707 
02708 
02709         GLTexPacked * gus = (GLTexPacked *) GetBaseLevel(_octave_min, DATA_GAUSSIAN);
02710         GLTexPacked * dog = (GLTexPacked *) GetBaseLevel(_octave_min, DATA_DOG);
02711         GLTexPacked * grd = (GLTexPacked *) GetBaseLevel(_octave_min, DATA_GRAD);
02712         GLTexPacked * rot = (GLTexPacked *) GetBaseLevel(_octave_min, DATA_ROT);
02713         GLTexPacked * key = (GLTexPacked *) GetBaseLevel(_octave_min, DATA_KEYPOINT);
02714 
02715 
02717 
02718         for(i = 0; i< noct; i++)
02719         {
02720                 for( j = 0; j< nlev; j++, gus++, dog++, grd++, rot++, key++)
02721                 {
02722                         gus->InitTexture(w, h);
02723                         if(j==0)continue;
02724                         dog->InitTexture(w, h);
02725                         grd->InitTexture(w, h, 0);
02726                         rot->InitTexture(w, h);
02727                         if(j<=1 || j >=nlev -1) continue;
02728                         key->InitTexture(w, h, 0);
02729                 }
02730                 int tsz = (gus -1)->GetTexPixelCount() * 16;
02731                 totalkb += ((nlev *5 -6)* tsz / 1024);
02732                 //several auxilary textures are not actually required
02733                 w>>=1;
02734                 h>>=1;
02735         }
02736 
02737         totalkb += ResizeFeatureStorage();
02738 
02739         _allocated = 1;
02740 
02741         if(GlobalUtil::_verbose && GlobalUtil::_timingS) std::cout<<"[Allocate Pyramid]:\t" <<(totalkb/1024)<<"MB\n";
02742 
02743 }
02744 
02745 void PyramidPacked::DestroyPyramidData()
02746 {
02747         if(_allPyramid)
02748         {
02749                 delete [] _allPyramid;
02750                 _allPyramid = NULL;
02751         }
02752 }
02753 
02754 
02755 GLTexImage*  PyramidPacked::GetLevelTexture(int octave, int level, int dataName)
02756 {
02757         return _allPyramid+ (_pyramid_octave_first + octave - _octave_min) * param._level_num 
02758                 + param._level_num * _pyramid_octave_num * dataName
02759                 + (level - param._level_min);
02760 
02761 }
02762 
02763 GLTexImage*  PyramidPacked::GetLevelTexture(int octave, int level)
02764 {
02765         return _allPyramid+ (_pyramid_octave_first + octave - _octave_min) * param._level_num 
02766                 + (level - param._level_min);
02767 }
02768 
02769 //in the packed implementation( still in progress)
02770 // DATA_GAUSSIAN, DATA_DOG, DATA_GAD will be stored in different textures.
02771 
02772 GLTexImage*  PyramidPacked::GetBaseLevel(int octave, int dataName)
02773 {
02774         if(octave <_octave_min || octave > _octave_min + _octave_num) return NULL;
02775         int offset = (_pyramid_octave_first + octave - _octave_min) * param._level_num;
02776         int num = param._level_num * _pyramid_octave_num;
02777         return _allPyramid + num *dataName + offset;
02778 }
02779 
02780 
02781 void PyramidPacked::FitHistogramPyramid()
02782 {
02783         GLTexImage * tex, *htex;
02784         int hist_level_num = _hpLevelNum - _pyramid_octave_first; 
02785 
02786         tex = GetBaseLevel(_octave_min , DATA_KEYPOINT) + 2;
02787         htex = _histoPyramidTex + hist_level_num - 1;
02788         int w = (tex->GetImgWidth() + 2) >> 2;
02789         int h = (tex->GetImgHeight() + 2)>> 2;
02790 
02791 
02792         //4n+1 -> n; 4n+2,2, 3 -> n+1
02793         for(int k = 0; k <hist_level_num -1; k++, htex--)
02794         {
02795                 if(htex->GetImgHeight()!= h || htex->GetImgWidth() != w)
02796                 {       
02797                         htex->SetImageSize(w, h);
02798                         htex->ZeroHistoMargin();
02799                 }
02800 
02801                 w = (w + 1)>>1; h = (h + 1) >> 1;
02802         }
02803 }
02804 


siftgpu
Author(s): Changchang Wu
autogenerated on Wed Aug 26 2015 15:24:06