00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
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
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
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
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
00189 if(_levelFeatureNum)
00190 {
00191 delete [] _levelFeatureNum;
00192 _levelFeatureNum = NULL;
00193 }
00194
00195 if( _featureTex)
00196 {
00197 delete [] _featureTex;
00198 _featureTex = NULL;
00199 }
00200
00201 if(_orientationTex)
00202 {
00203 delete [] _orientationTex;
00204 _orientationTex = NULL;
00205 }
00206 int no = _octave_num* param._dog_level_num;
00207
00208
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
00227 if(_histoPyramidTex)
00228 {
00229 delete[] _histoPyramidTex;
00230 _hpLevelNum = 0;
00231 _histoPyramidTex = NULL;
00232 }
00233
00234
00235 if(_descriptorTex)
00236 {
00237 delete [] _descriptorTex;
00238 _descriptorTex = NULL;
00239 }
00240
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
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
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
00374 FitPyramid(wp, hp);
00375 }
00376
00377
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
00396 _pyramid_octave_first = 0;
00397
00398
00399
00400
00401 input_sz = min(w,h) ;
00402
00403
00404 _pyramid_width = w;
00405 _pyramid_height = h;
00406
00407
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
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
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
00442 }
00443
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
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
00479 FrameBufferObject fbo;
00480
00481
00482 if(_histo_buffer == NULL) _histo_buffer = new float[((size_t)1) << (2 + 2 * GlobalUtil::_ListGenSkipGPU)];
00483
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
00506 if(GlobalUtil::_ListGenGPU) totalkb += (((1 << (2 * _hpLevelNum)) -1) / 3 * 16 / 1024);
00507
00508
00509
00510
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;
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
00548 if(_descriptorTex==NULL)
00549 {
00550
00551 wmax = _featureTex->GetImgWidth();
00552 hmax = _featureTex->GetImgHeight();
00553
00554 int nf, ns;
00555 if(GlobalUtil::_DescriptorPPT)
00556 {
00557
00558 nf = 32 / GlobalUtil::_DescriptorPPT;
00559 ns = max(4, GlobalUtil::_DescriptorPPT);
00560 }else
00561 {
00562
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
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
00662
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
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
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
00835 htex->DrawQuadReduction();
00836
00837
00838 htex--;
00839
00840
00841
00842
00843
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
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
00878 ftex->AttachToFBO(0);
00879 if(GlobalUtil::_MaxOrientation>1)
00880 {
00881
00882 ftex->FitRealTexViewPort();
00883 glClear(GL_COLOR_BUFFER_BIT);
00884 glFinish();
00885 }else
00886 {
00887 ftex->FitTexViewPort();
00888
00889 }
00890
00891
00892 ShaderMan::UseShaderGenListStart((float)ftex->GetImgWidth(), htex->GetTexID());
00893
00894 ftex->DrawQuad();
00895
00896 ftex->DetachFBO(0);
00897
00898
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
00967 void PyramidNaive::GenerateFeatureList()
00968 {
00969
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
00980 FOR_EACH_OCTAVE(i, reverse)
00981 {
00982
00983 if(GlobalUtil::_timingO)
00984 {
00985 t1= CLOCK();
00986 ocount = 0;
00987 std::cout<<"#"<<i+_octave_min + _down_sample_factor<<":\t";
00988 }
00989
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
01026 int w, h, esize; GLint bsize;
01027 int nvbo = _octave_num * param._dog_level_num;
01028
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
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
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
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
01081 int count = _levelFeatureNum[idx]* 10;
01082 GetAlignedStorageSize(count, _alignment, w, h);
01083 w = (int)ceil(double(count)/ h);
01084
01085
01086 fbo.BindFBO();
01087 ftex->BindTex();
01088
01089
01090 tempTex.AttachToFBO(0);
01091 GlobalUtil::FitViewPort(w, h);
01092
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
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
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
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
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
01209
01210
01211
01212
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
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
01267
01268
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
01318 _orientationTex[i].AttachToFBO(0);
01319 glReadPixels(0, 0, _orientationTex[i].GetImgWidth(), _orientationTex[i].GetImgHeight(),GL_RGBA, GL_FLOAT, buffer2);
01320
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
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;
01414 ds[1] = oss*(fs[1]-0.5f) + offset;
01415 ds[3] = (float)fmod(twopi-fs[2], twopi);
01416 ds[2] = oss*fs[3];
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
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
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
01548 sq = dotproduct_128d(pd); sq = 1.0f / sqrtf(sq);
01549 multiply_and_truncate_128d(pd, sq);
01550
01551
01552 sq = dotproduct_128d(pd); sq = 1.0f / sqrtf(sq);
01553 multiply_128d(pd, sq);
01554 }
01555 #else
01556
01557 for(int k = 0; k < num; k++, pd +=128)
01558 {
01559 int v;
01560 float* ppd, sq = 0;
01561
01562
01563 ppd = pd;
01564 for(v = 0 ; v < 128; v++, ppd++) sq += (*ppd)*(*ppd);
01565 sq = 1.0f / sqrtf(sq);
01566
01567 ppd = pd;
01568 for(v = 0; v < 128; v ++, ppd++) *ppd = min(*ppd*sq, 0.2f);
01569
01570
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
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 if(GlobalUtil::_DescriptorPPR == 8)
01618 {
01619
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
01669 float sigma;
01670 int idx, i, j, k, w, h;
01671 int ndf = 32 / GlobalUtil::_DescriptorPPT;
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
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
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
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
01740 for(k = 0; k < ndf; k++, pbuf+=step)
01741 {
01742 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + k);
01743 if(GlobalUtil::_IsNvidia || w * h <= 16384)
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
01755
01756
01757 InterlaceDescriptorF2(w / block_width, h / block_height, &read_buffer[0], pd, step);
01758
01759
01760
01761 if(GlobalUtil::_NormalizedSIFT) NormalizeDescriptor(_levelFeatureNum[idx], pd);
01762
01763 pd += 128*_levelFeatureNum[idx];
01764 glReadBuffer(GL_NONE);
01765 }
01766 }
01767
01768
01769
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
01796
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;
01825 ps[1] = os*(ps[1]-0.5f) + offset;
01826 sigma = os*ps[3];
01827 ps[3] = (float)fmod(twopi-ps[2], twopi);
01828 ps[2] = sigma;
01829 }
01830 p+= 4* _levelFeatureNum[idx];
01831 }
01832 }
01833 }
01834
01835
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
01851
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);
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
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
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
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;
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
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
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
02018 for(j = 0; j < param._dog_level_num ; j++, gus++, dog++, grd++, rot++)
02019 {
02020
02021 glActiveTexture(GL_TEXTURE0);
02022 gus->BindTex();
02023 glActiveTexture(GL_TEXTURE1);
02024 (gus-1)->BindTex();
02025
02026 dog->AttachToFBO(0);
02027 grd->AttachToFBO(1);
02028 rot->AttachToFBO(2);
02029 ShaderMan::UseShaderGradientPass((gus-1)->GetTexID());
02030
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
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
02074 for(j = param._level_min +1; j <= param._level_max ; j++, gus++, dog++, grd++, rot++)
02075 {
02076
02077 glActiveTexture(GL_TEXTURE0);
02078 gus->BindTex();
02079 glActiveTexture(GL_TEXTURE1);
02080 (gus-1)->BindTex();
02081
02082 dog->AttachToFBO(0);
02083 grd->AttachToFBO(1);
02084 rot->AttachToFBO(2);
02085 ShaderMan::UseShaderGradientPass((gus-1)->GetTexID());
02086
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
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
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
02182 htex->DrawQuadReduction();
02183
02184 htex--;
02185
02186
02187
02188
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
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
02210 _featureNum += int(fcount);
02211
02212
02213 if(fcount < 1.0) return;;
02214
02215
02217 htex= _histoPyramidTex;
02218
02219 htex->BindTex();
02220
02221
02222 ftex->AttachToFBO(0);
02223 if(GlobalUtil::_MaxOrientation>1)
02224 {
02225
02226 ftex->FitRealTexViewPort();
02227 glClear(GL_COLOR_BUFFER_BIT);
02228 glFinish();
02229 }else
02230 {
02231 ftex->FitTexViewPort();
02232
02233 }
02234
02235
02236 ShaderMan::UseShaderGenListStart((float)ftex->GetImgWidth(), htex->GetTexID());
02237
02238 ftex->DrawQuad();
02239
02240 ftex->DetachFBO(0);
02241
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
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
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
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
02385
02386
02387
02388
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
02399
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
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
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
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
02603 FitPyramid(wp, hp);
02604 }
02605
02606
02607 ShaderMan::SelectInitialSmoothingFilter(_octave_min + _down_sample_factor, param);
02608 }
02609
02610
02611
02612 void PyramidPacked::FitPyramid(int w, int h)
02613 {
02614
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
02673 _pyramid_octave_first = 0;
02674
02675
02676
02677
02678 input_sz = min(w,h) ;
02679 _pyramid_width = w;
02680 _pyramid_height = h;
02681
02682
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
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
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
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
02769
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
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