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


siftgpu
Author(s): Changchang Wu (library), Bence Magyar (ROS wrapper)
autogenerated on Thu Jan 2 2014 11:38:01