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