00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00022
00023 #if defined(CL_SIFTGPU_ENABLED)
00024
00025
00026 #include "GL/glew.h"
00027 #include <CL/OpenCL.h>
00028 #include <iostream>
00029 #include <vector>
00030 #include <algorithm>
00031 #include <stdlib.h>
00032 #include <math.h>
00033 using namespace std;
00034
00035 #include "GlobalUtil.h"
00036 #include "GLTexImage.h"
00037 #include "CLTexImage.h"
00038 #include "SiftGPU.h"
00039 #include "SiftPyramid.h"
00040 #include "ProgramCL.h"
00041 #include "PyramidCL.h"
00042
00043
00044 #define USE_TIMING() double t, t0, tt;
00045 #define OCTAVE_START() if(GlobalUtil::_timingO){ t = t0 = CLOCK(); cout<<"#"<<i+_down_sample_factor<<"\t"; }
00046 #define LEVEL_FINISH() if(GlobalUtil::_timingL){ _OpenCL->FinishCL(); tt = CLOCK();cout<<(tt-t)<<"\t"; t = CLOCK();}
00047 #define OCTAVE_FINISH() if(GlobalUtil::_timingO)cout<<"|\t"<<(CLOCK()-t0)<<endl;
00048
00049
00050 PyramidCL::PyramidCL(SiftParam& sp) : SiftPyramid(sp)
00051 {
00052 _allPyramid = NULL;
00053 _histoPyramidTex = NULL;
00054 _featureTex = NULL;
00055 _descriptorTex = NULL;
00056 _orientationTex = NULL;
00057 _bufferTEX = NULL;
00058 if(GlobalUtil::_usePackedTex) _OpenCL = new ProgramBagCL();
00059 else _OpenCL = new ProgramBagCLN();
00060 _OpenCL->InitProgramBag(sp);
00061 _inputTex = new CLTexImage( _OpenCL->GetContextCL(),
00062 _OpenCL->GetCommandQueue());
00064 InitializeContext();
00065 }
00066
00067 PyramidCL::~PyramidCL()
00068 {
00069 DestroyPerLevelData();
00070 DestroySharedData();
00071 DestroyPyramidData();
00072 if(_OpenCL) delete _OpenCL;
00073 if(_inputTex) delete _inputTex;
00074 if(_bufferTEX) delete _bufferTEX;
00075 }
00076
00077 void PyramidCL::InitializeContext()
00078 {
00079 GlobalUtil::InitGLParam(1);
00080 }
00081
00082 void PyramidCL::InitPyramid(int w, int h, int ds)
00083 {
00084 int wp, hp, toobig = 0;
00085 if(ds == 0)
00086 {
00087 _down_sample_factor = 0;
00088 if(GlobalUtil::_octave_min_default>=0)
00089 {
00090 wp = w >> _octave_min_default;
00091 hp = h >> _octave_min_default;
00092 }else
00093 {
00094
00095 _octave_min_default = max(-3, _octave_min_default);
00096
00097 wp = w << (-_octave_min_default);
00098 hp = h << (-_octave_min_default);
00099 }
00100 _octave_min = _octave_min_default;
00101 }else
00102 {
00103
00104 _octave_min = 0;
00105 _down_sample_factor = ds;
00106 w >>= ds;
00107 h >>= ds;
00108 wp = w;
00109 hp = h;
00110 }
00111
00112 while(wp > GlobalUtil::_texMaxDim || hp > GlobalUtil::_texMaxDim )
00113 {
00114 _octave_min ++;
00115 wp >>= 1;
00116 hp >>= 1;
00117 toobig = 1;
00118 }
00119 if(toobig && GlobalUtil::_verbose && _octave_min > 0)
00120 {
00121 std::cout<< "**************************************************************\n"
00122 "Image larger than allowed dimension, data will be downsampled!\n"
00123 "use -maxd to change the settings\n"
00124 "***************************************************************\n";
00125 }
00126
00127 if( wp == _pyramid_width && hp == _pyramid_height && _allocated )
00128 {
00129 FitPyramid(wp, hp);
00130 }else if(GlobalUtil::_ForceTightPyramid || _allocated ==0)
00131 {
00132 ResizePyramid(wp, hp);
00133 }
00134 else if( wp > _pyramid_width || hp > _pyramid_height )
00135 {
00136 ResizePyramid(max(wp, _pyramid_width), max(hp, _pyramid_height));
00137 if(wp < _pyramid_width || hp < _pyramid_height) FitPyramid(wp, hp);
00138 }
00139 else
00140 {
00141
00142 FitPyramid(wp, hp);
00143 }
00144
00145 _OpenCL->SelectInitialSmoothingFilter(_octave_min + _down_sample_factor, param);
00146 }
00147
00148 void PyramidCL::ResizePyramid(int w, int h)
00149 {
00150
00151 unsigned int totalkb = 0;
00152 int _octave_num_new, input_sz, i, j;
00153
00154
00155 if(_pyramid_width == w && _pyramid_height == h && _allocated) return;
00156
00157 if(w > GlobalUtil::_texMaxDim || h > GlobalUtil::_texMaxDim) return ;
00158
00159 if(GlobalUtil::_verbose && GlobalUtil::_timingS) std::cout<<"[Allocate Pyramid]:\t" <<w<<"x"<<h<<endl;
00160
00161 _pyramid_octave_first = 0;
00162
00163
00164
00165 input_sz = min(w,h) ;
00166 _pyramid_width = w;
00167 _pyramid_height = h;
00168
00169
00170 _octave_num_new = GlobalUtil::_octave_num_default;
00171
00172 if(_octave_num_new < 1) _octave_num_new = GetRequiredOctaveNum(input_sz) ;
00173
00174 if(_pyramid_octave_num != _octave_num_new)
00175 {
00176
00177 if(_octave_num >0)
00178 {
00179 DestroyPerLevelData();
00180 DestroyPyramidData();
00181 }
00182 _pyramid_octave_num = _octave_num_new;
00183 }
00184
00185 _octave_num = _pyramid_octave_num;
00186
00187 int noct = _octave_num;
00188 int nlev = param._level_num;
00189 int texNum = noct* nlev * DATA_NUM;
00190
00191
00192 if(_allPyramid==NULL)
00193 {
00194 _allPyramid = new CLTexImage[ texNum];
00195 cl_context context = _OpenCL->GetContextCL();
00196 cl_command_queue queue = _OpenCL->GetCommandQueue();
00197 for(i = 0; i < texNum; ++i) _allPyramid[i].SetContext(context, queue);
00198 }
00199
00200
00201
00202 CLTexImage * gus = GetBaseLevel(_octave_min, DATA_GAUSSIAN);
00203 CLTexImage * dog = GetBaseLevel(_octave_min, DATA_DOG);
00204 CLTexImage * grd = GetBaseLevel(_octave_min, DATA_GRAD);
00205 CLTexImage * rot = GetBaseLevel(_octave_min, DATA_ROT);
00206 CLTexImage * key = GetBaseLevel(_octave_min, DATA_KEYPOINT);
00207
00209
00210
00211
00212 for(i = 0; i< noct; i++)
00213 {
00214 for( j = 0; j< nlev; j++, gus++, dog++, grd++, rot++, key++)
00215 {
00216 gus->InitPackedTex(w, h, GlobalUtil::_usePackedTex);
00217 if(j==0)continue;
00218 dog->InitPackedTex(w, h, GlobalUtil::_usePackedTex);
00219 if(j < 1 + param._dog_level_num)
00220 {
00221 grd->InitPackedTex(w, h, GlobalUtil::_usePackedTex);
00222 rot->InitPackedTex(w, h, GlobalUtil::_usePackedTex);
00223 }
00224 if(j > 1 && j < nlev -1) key->InitPackedTex(w, h, GlobalUtil::_usePackedTex);
00225 }
00227 int tsz = (gus -1)->GetTexPixelCount() * 16;
00228 totalkb += ((nlev *5 -6)* tsz / 1024);
00229
00230 w>>=1;
00231 h>>=1;
00232 }
00233
00234 totalkb += ResizeFeatureStorage();
00235
00236 _allocated = 1;
00237
00238 if(GlobalUtil::_verbose && GlobalUtil::_timingS) std::cout<<"[Allocate Pyramid]:\t" <<(totalkb/1024)<<"MB\n";
00239
00240 }
00241
00242 void PyramidCL::FitPyramid(int w, int h)
00243 {
00244 _pyramid_octave_first = 0;
00245
00246 _octave_num = GlobalUtil::_octave_num_default;
00247
00248 int _octave_num_max = GetRequiredOctaveNum(min(w, h));
00249
00250 if(_octave_num < 1 || _octave_num > _octave_num_max)
00251 {
00252 _octave_num = _octave_num_max;
00253 }
00254
00255
00256 int pw = _pyramid_width>>1, ph = _pyramid_height>>1;
00257 while(_pyramid_octave_first + _octave_num < _pyramid_octave_num &&
00258 pw >= w && ph >= h)
00259 {
00260 _pyramid_octave_first++;
00261 pw >>= 1;
00262 ph >>= 1;
00263 }
00264
00266 for(int i = 0; i < _octave_num; i++)
00267 {
00268 CLTexImage * tex = GetBaseLevel(i + _octave_min);
00269 CLTexImage * dog = GetBaseLevel(i + _octave_min, DATA_DOG);
00270 CLTexImage * grd = GetBaseLevel(i + _octave_min, DATA_GRAD);
00271 CLTexImage * rot = GetBaseLevel(i + _octave_min, DATA_ROT);
00272 CLTexImage * key = GetBaseLevel(i + _octave_min, DATA_KEYPOINT);
00273 for(int j = param._level_min; j <= param._level_max; j++, tex++, dog++, grd++, rot++, key++)
00274 {
00275 tex->SetPackedSize(w, h, GlobalUtil::_usePackedTex);
00276 if(j == param._level_min) continue;
00277 dog->SetPackedSize(w, h, GlobalUtil::_usePackedTex);
00278 if(j < param._level_max - 1)
00279 {
00280 grd->SetPackedSize(w, h, GlobalUtil::_usePackedTex);
00281 rot->SetPackedSize(w, h, GlobalUtil::_usePackedTex);
00282 }
00283 if(j > param._level_min + 1 && j < param._level_max) key->SetPackedSize(w, h, GlobalUtil::_usePackedTex);
00284 }
00285 w>>=1;
00286 h>>=1;
00287 }
00288 }
00289
00290
00291 void PyramidCL::SetLevelFeatureNum(int idx, int fcount)
00292 {
00293 _featureTex[idx].InitBufferTex(fcount, 1, 4);
00294 _levelFeatureNum[idx] = fcount;
00295 }
00296
00297 int PyramidCL::ResizeFeatureStorage()
00298 {
00299 int totalkb = 0;
00300 if(_levelFeatureNum==NULL) _levelFeatureNum = new int[_octave_num * param._dog_level_num];
00301 std::fill(_levelFeatureNum, _levelFeatureNum+_octave_num * param._dog_level_num, 0);
00302
00303 cl_context context = _OpenCL->GetContextCL();
00304 cl_command_queue queue = _OpenCL->GetCommandQueue();
00305 int wmax = GetBaseLevel(_octave_min)->GetImgWidth() * 2;
00306 int hmax = GetBaseLevel(_octave_min)->GetImgHeight() * 2;
00307 int whmax = max(wmax, hmax);
00308 int w, i;
00309
00310
00311 int num = (int)ceil(log(double(whmax))/log(4.0));
00312
00313 if( _hpLevelNum != num)
00314 {
00315 _hpLevelNum = num;
00316 if(_histoPyramidTex ) delete [] _histoPyramidTex;
00317 _histoPyramidTex = new CLTexImage[_hpLevelNum];
00318 for(i = 0; i < _hpLevelNum; ++i) _histoPyramidTex[i].SetContext(context, queue);
00319 }
00320
00321 for(i = 0, w = 1; i < _hpLevelNum; i++)
00322 {
00323 _histoPyramidTex[i].InitBufferTex(w, whmax, 4);
00324 w<<=2;
00325 }
00326
00327
00328 totalkb += (((1 << (2 * _hpLevelNum)) -1) / 3 * 16 / 1024);
00329
00330
00331 int idx = 0, n = _octave_num * param._dog_level_num;
00332 if(_featureTex==NULL)
00333 {
00334 _featureTex = new CLTexImage[n];
00335 for(i = 0; i <n; ++i) _featureTex[i].SetContext(context, queue);
00336 }
00337 if(GlobalUtil::_MaxOrientation >1 && GlobalUtil::_OrientationPack2==0 && _orientationTex== NULL)
00338 {
00339 _orientationTex = new CLTexImage[n];
00340 for(i = 0; i < n; ++i) _orientationTex[i].SetContext(context, queue);
00341 }
00342
00343
00344 for(i = 0; i < _octave_num; i++)
00345 {
00346 CLTexImage * tex = GetBaseLevel(i+_octave_min);
00347 int fmax = int(4 * tex->GetTexWidth() * tex->GetTexHeight()*GlobalUtil::_MaxFeaturePercent);
00348
00349 if(fmax > GlobalUtil::_MaxLevelFeatureNum) fmax = GlobalUtil::_MaxLevelFeatureNum;
00350 else if(fmax < 32) fmax = 32;
00351
00352 for(int j = 0; j < param._dog_level_num; j++, idx++)
00353 {
00354 _featureTex[idx].InitBufferTex(fmax, 1, 4);
00355 totalkb += fmax * 16 /1024;
00356
00357 if(GlobalUtil::_MaxOrientation>1 && GlobalUtil::_OrientationPack2 == 0)
00358 {
00359 _orientationTex[idx].InitBufferTex(fmax, 1, 4);
00360 totalkb += fmax * 16 /1024;
00361 }
00362 }
00363 }
00364
00365
00366 if(_descriptorTex==NULL)
00367 {
00368
00369 int fmax = _featureTex->GetImgWidth();
00370 _descriptorTex = new CLTexImage(context, queue);
00371 totalkb += ( fmax /2);
00372 _descriptorTex->InitBufferTex(fmax *128, 1, 1);
00373 }else
00374 {
00375 totalkb += _descriptorTex->GetDataSize()/1024;
00376 }
00377 return totalkb;
00378 }
00379
00380 void PyramidCL::GetFeatureDescriptors()
00381 {
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 }
00418
00419 void PyramidCL::GenerateFeatureListTex()
00420 {
00421
00422 vector<float> list;
00423 int idx = 0;
00424 const double twopi = 2.0*3.14159265358979323846;
00425 float sigma_half_step = powf(2.0f, 0.5f / param._dog_level_num);
00426 float octave_sigma = _octave_min>=0? float(1<<_octave_min): 1.0f/(1<<(-_octave_min));
00427 float offset = GlobalUtil::_LoweOrigin? 0 : 0.5f;
00428 if(_down_sample_factor>0) octave_sigma *= float(1<<_down_sample_factor);
00429
00430 _keypoint_index.resize(0);
00431 for(int i = 0; i < _octave_num; i++, octave_sigma*= 2.0f)
00432 {
00433 for(int j = 0; j < param._dog_level_num; j++, idx++)
00434 {
00435 list.resize(0);
00436 float level_sigma = param.GetLevelSigma(j + param._level_min + 1) * octave_sigma;
00437 float sigma_min = level_sigma / sigma_half_step;
00438 float sigma_max = level_sigma * sigma_half_step;
00439 int fcount = 0 ;
00440 for(int k = 0; k < _featureNum; k++)
00441 {
00442 float * key = &_keypoint_buffer[k*4];
00443 if( (key[2] >= sigma_min && key[2] < sigma_max)
00444 ||(key[2] < sigma_min && i ==0 && j == 0)
00445 ||(key[2] > sigma_max && i == _octave_num -1 && j == param._dog_level_num - 1))
00446 {
00447
00448 list.push_back((key[0] - offset) / octave_sigma + 0.5f);
00449 list.push_back((key[1] - offset) / octave_sigma + 0.5f);
00450 list.push_back(key[2] / octave_sigma);
00451 list.push_back((float)fmod(twopi-key[3], twopi));
00452 fcount ++;
00453
00454 _keypoint_index.push_back(k);
00455 }
00456
00457 }
00458
00459 _levelFeatureNum[idx] = fcount;
00460 if(fcount==0)continue;
00461 CLTexImage * ftex = _featureTex+idx;
00462
00463 SetLevelFeatureNum(idx, fcount);
00464 ftex->CopyFromHost(&list[0]);
00465 }
00466 }
00467
00468 if(GlobalUtil::_verbose)
00469 {
00470 std::cout<<"#Features:\t"<<_featureNum<<"\n";
00471 }
00472
00473 }
00474
00475 void PyramidCL::ReshapeFeatureListCPU()
00476 {
00477 int i, szmax =0, sz;
00478 int n = param._dog_level_num*_octave_num;
00479 for( i = 0; i < n; i++)
00480 {
00481 sz = _levelFeatureNum[i];
00482 if(sz > szmax ) szmax = sz;
00483 }
00484 float * buffer = new float[szmax*16];
00485 float * buffer1 = buffer;
00486 float * buffer2 = buffer + szmax*4;
00487
00488
00489
00490 _featureNum = 0;
00491
00492 #ifdef NO_DUPLICATE_DOWNLOAD
00493 const double twopi = 2.0*3.14159265358979323846;
00494 _keypoint_buffer.resize(0);
00495 float os = _octave_min>=0? float(1<<_octave_min): 1.0f/(1<<(-_octave_min));
00496 if(_down_sample_factor>0) os *= float(1<<_down_sample_factor);
00497 float offset = GlobalUtil::_LoweOrigin? 0 : 0.5f;
00498 #endif
00499
00500
00501 for(i = 0; i < n; i++)
00502 {
00503 if(_levelFeatureNum[i]==0)continue;
00504
00505 _featureTex[i].CopyToHost(buffer1);
00506
00507 int fcount =0;
00508 float * src = buffer1;
00509 float * des = buffer2;
00510 const static double factor = 2.0*3.14159265358979323846/65535.0;
00511 for(int j = 0; j < _levelFeatureNum[i]; j++, src+=4)
00512 {
00513 unsigned short * orientations = (unsigned short*) (&src[3]);
00514 if(orientations[0] != 65535)
00515 {
00516 des[0] = src[0];
00517 des[1] = src[1];
00518 des[2] = src[2];
00519 des[3] = float( factor* orientations[0]);
00520 fcount++;
00521 des += 4;
00522 if(orientations[1] != 65535 && orientations[1] != orientations[0])
00523 {
00524 des[0] = src[0];
00525 des[1] = src[1];
00526 des[2] = src[2];
00527 des[3] = float(factor* orientations[1]);
00528 fcount++;
00529 des += 4;
00530 }
00531 }
00532 }
00533
00534 SetLevelFeatureNum(i, fcount);
00535 _featureTex[i].CopyFromHost(buffer2);
00536
00537 if(fcount == 0) continue;
00538
00539 #ifdef NO_DUPLICATE_DOWNLOAD
00540 float oss = os * (1 << (i / param._dog_level_num));
00541 _keypoint_buffer.resize((_featureNum + fcount) * 4);
00542 float* ds = &_keypoint_buffer[_featureNum * 4];
00543 float* fs = buffer2;
00544 for(int k = 0; k < fcount; k++, ds+=4, fs+=4)
00545 {
00546 ds[0] = oss*(fs[0]-0.5f) + offset;
00547 ds[1] = oss*(fs[1]-0.5f) + offset;
00548 ds[2] = oss*fs[2];
00549 ds[3] = (float)fmod(twopi-fs[3], twopi);
00550 }
00551 #endif
00552 _featureNum += fcount;
00553 }
00554 delete[] buffer;
00555 if(GlobalUtil::_verbose)
00556 {
00557 std::cout<<"#Features MO:\t"<<_featureNum<<endl;
00558 }
00559 }
00560
00561 void PyramidCL::GenerateFeatureDisplayVBO()
00562 {
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583 }
00584
00585 void PyramidCL::DestroySharedData()
00586 {
00587
00588 if(_histoPyramidTex)
00589 {
00590 delete[] _histoPyramidTex;
00591 _hpLevelNum = 0;
00592 _histoPyramidTex = NULL;
00593 }
00594
00595 if(_descriptorTex)
00596 {
00597 delete _descriptorTex;
00598 _descriptorTex = NULL;
00599 }
00600
00601 if(_histo_buffer)
00602 {
00603 delete[] _histo_buffer;
00604 _histo_buffer = 0;
00605 }
00606 }
00607
00608 void PyramidCL::DestroyPerLevelData()
00609 {
00610
00611 if(_levelFeatureNum)
00612 {
00613 delete [] _levelFeatureNum;
00614 _levelFeatureNum = NULL;
00615 }
00616
00617 if( _featureTex)
00618 {
00619 delete [] _featureTex;
00620 _featureTex = NULL;
00621 }
00622
00623 if(_orientationTex)
00624 {
00625 delete [] _orientationTex;
00626 _orientationTex = NULL;
00627 }
00628 int no = _octave_num* param._dog_level_num;
00629
00630
00631 if(_featureDisplayVBO)
00632 {
00633 glDeleteBuffers(no, _featureDisplayVBO);
00634 delete [] _featureDisplayVBO;
00635 _featureDisplayVBO = NULL;
00636 }
00637 if( _featurePointVBO)
00638 {
00639 glDeleteBuffers(no, _featurePointVBO);
00640 delete [] _featurePointVBO;
00641 _featurePointVBO = NULL;
00642 }
00643 }
00644
00645 void PyramidCL::DestroyPyramidData()
00646 {
00647 if(_allPyramid)
00648 {
00649 delete [] _allPyramid;
00650 _allPyramid = NULL;
00651 }
00652 }
00653
00654 void PyramidCL::DownloadKeypoints()
00655 {
00656 const double twopi = 2.0*3.14159265358979323846;
00657 int idx = 0;
00658 float * buffer = &_keypoint_buffer[0];
00659 vector<float> keypoint_buffer2;
00660
00661
00662 if(_keypoint_index.size() > 0)
00663 {
00664 keypoint_buffer2.resize(_keypoint_buffer.size());
00665 buffer = &keypoint_buffer2[0];
00666 }
00667 float * p = buffer, *ps;
00668 CLTexImage * ftex = _featureTex;
00670 float os = _octave_min>=0? float(1<<_octave_min): 1.0f/(1<<(-_octave_min));
00671 if(_down_sample_factor>0) os *= float(1<<_down_sample_factor);
00672 float offset = GlobalUtil::_LoweOrigin? 0 : 0.5f;
00674 for(int i = 0; i < _octave_num; i++, os *= 2.0f)
00675 {
00676
00677 for(int j = 0; j < param._dog_level_num; j++, idx++, ftex++)
00678 {
00679
00680 if(_levelFeatureNum[idx]>0)
00681 {
00682 ftex->CopyToHost(ps = p);
00683 for(int k = 0; k < _levelFeatureNum[idx]; k++, ps+=4)
00684 {
00685 ps[0] = os*(ps[0]-0.5f) + offset;
00686 ps[1] = os*(ps[1]-0.5f) + offset;
00687 ps[2] = os*ps[2];
00688 ps[3] = (float)fmod(twopi-ps[3], twopi);
00689 }
00690 p+= 4* _levelFeatureNum[idx];
00691 }
00692 }
00693 }
00694
00695
00696 if(_keypoint_index.size() > 0)
00697 {
00698 for(int i = 0; i < _featureNum; ++i)
00699 {
00700 int index = _keypoint_index[i];
00701 memcpy(&_keypoint_buffer[index*4], &keypoint_buffer2[i*4], 4 * sizeof(float));
00702 }
00703 }
00704 }
00705
00706 void PyramidCL::GenerateFeatureListCPU()
00707 {
00708
00709 GenerateFeatureList();
00710 }
00711
00712 void PyramidCL::GenerateFeatureList(int i, int j, int reduction_count, vector<int>& hbuffer)
00713 {
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00759
00760
00761
00762
00763
00764
00765 }
00766
00767 void PyramidCL::GenerateFeatureList()
00768 {
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00810
00812
00813
00814
00815
00816
00817
00818 }
00819
00820 GLTexImage* PyramidCL::GetLevelTexture(int octave, int level)
00821 {
00822 return GetLevelTexture(octave, level, DATA_GAUSSIAN);
00823 }
00824
00825 GLTexImage* PyramidCL::ConvertTexCL2GL(CLTexImage* tex, int dataName)
00826 {
00827
00828 if(_bufferTEX == NULL) _bufferTEX = new GLTexImage;
00829
00831 int ratio = GlobalUtil::_usePackedTex ? 2 : 1;
00832 int width = tex->GetImgWidth() * ratio;
00833 int height = tex->GetImgHeight() * ratio;
00834 int tw = max(width, _bufferTEX->GetTexWidth());
00835 int th = max(height, _bufferTEX->GetTexHeight());
00836 _bufferTEX->InitTexture(tw, th, 1, GL_RGBA);
00837 _bufferTEX->SetImageSize(width, height);
00838
00840 CLTexImage texCL(_OpenCL->GetContextCL(), _OpenCL->GetCommandQueue());
00841 texCL.InitTextureGL(*_bufferTEX, width, height, 4);
00842
00843 switch(dataName)
00844 {
00845 case DATA_GAUSSIAN: _OpenCL->UnpackImage(tex, &texCL); break;
00846 case DATA_DOG:_OpenCL->UnpackImageDOG(tex, &texCL); break;
00847 case DATA_GRAD:_OpenCL->UnpackImageGRD(tex, &texCL); break;
00848 case DATA_KEYPOINT:_OpenCL->UnpackImageKEY(tex,
00849 tex - param._level_num * _pyramid_octave_num, &texCL);break;
00850 default:
00851 break;
00852 }
00853
00854
00855 return _bufferTEX;
00856 }
00857
00858 GLTexImage* PyramidCL::GetLevelTexture(int octave, int level, int dataName)
00859 {
00860 CLTexImage* tex = GetBaseLevel(octave, dataName) + (level - param._level_min);
00861 return ConvertTexCL2GL(tex, dataName);
00862 }
00863
00864 void PyramidCL::ConvertInputToCL(GLTexInput* input, CLTexImage* output)
00865 {
00866 int ws = input->GetImgWidth(), hs = input->GetImgHeight();
00867
00868 if(input->_pixel_data)
00869 {
00870 output->InitTexture(ws, hs, 1);
00871 output->CopyFromHost(input->_pixel_data);
00872 }else
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882 {
00883 std::cerr<< "Unable To Convert Intput\n";
00884 }
00885 }
00886
00887 void PyramidCL::BuildPyramid(GLTexInput * input)
00888 {
00889
00890 USE_TIMING();
00891
00892 int i, j;
00893
00894 for ( i = _octave_min; i < _octave_min + _octave_num; i++)
00895 {
00896
00897 CLTexImage *tex = GetBaseLevel(i);
00898 CLTexImage *buf = GetBaseLevel(i, DATA_DOG) +2;
00899 FilterCL ** filter = _OpenCL->f_gaussian_step;
00900 j = param._level_min + 1;
00901
00902 OCTAVE_START();
00903
00904 if( i == _octave_min )
00905 {
00906 if(GlobalUtil::_usePackedTex)
00907 {
00908 ConvertInputToCL(input, _inputTex);
00909 if(i < 0) _OpenCL->SampleImageU(tex, _inputTex, -i- 1);
00910 else _OpenCL->SampleImageD(tex, _inputTex, i + 1);
00911 }else
00912 {
00913 if(i == 0) ConvertInputToCL(input, tex);
00914 else
00915 {
00916 ConvertInputToCL(input, _inputTex);
00917 if(i < 0) _OpenCL->SampleImageU(tex, _inputTex, -i);
00918 else _OpenCL->SampleImageD(tex, _inputTex, i);
00919 }
00920 }
00921 _OpenCL->FilterInitialImage(tex, buf);
00922 }else
00923 {
00924 _OpenCL->SampleImageD(tex, GetBaseLevel(i - 1) + param._level_ds - param._level_min);
00925 _OpenCL->FilterSampledImage(tex, buf);
00926 }
00927 LEVEL_FINISH();
00928 for( ; j <= param._level_max ; j++, tex++, filter++)
00929 {
00930
00931 _OpenCL->FilterImage(*filter, tex + 1, tex, buf);
00932 LEVEL_FINISH();
00933 }
00934 OCTAVE_FINISH();
00935 }
00936 if(GlobalUtil::_timingS) _OpenCL->FinishCL();
00937 }
00938
00939 void PyramidCL::DetectKeypointsEX()
00940 {
00941 int i, j;
00942 double t0, t, ts, t1, t2;
00943
00944 if(GlobalUtil::_timingS && GlobalUtil::_verbose) ts = CLOCK();
00945
00946 for(i = _octave_min; i < _octave_min + _octave_num; i++)
00947 {
00948 CLTexImage * gus = GetBaseLevel(i) + 1;
00949 CLTexImage * dog = GetBaseLevel(i, DATA_DOG) + 1;
00950 CLTexImage * grd = GetBaseLevel(i, DATA_GRAD) + 1;
00951 CLTexImage * rot = GetBaseLevel(i, DATA_ROT) + 1;
00952
00953 for(j = param._level_min +1; j <= param._level_max ; j++, gus++, dog++, grd++, rot++)
00954 {
00955
00956
00957 _OpenCL->ComputeDOG(gus, gus - 1, dog, grd, rot);
00958 }
00959 }
00960 if(GlobalUtil::_timingS && GlobalUtil::_verbose)
00961 {
00962 _OpenCL->FinishCL();
00963 t1 = CLOCK();
00964 }
00965
00966
00967
00968
00969 for ( i = _octave_min; i < _octave_min + _octave_num; i++)
00970 {
00971 if(GlobalUtil::_timingO)
00972 {
00973 t0 = CLOCK();
00974 std::cout<<"#"<<(i + _down_sample_factor)<<"\t";
00975 }
00976 CLTexImage * dog = GetBaseLevel(i, DATA_DOG) + 2;
00977 CLTexImage * key = GetBaseLevel(i, DATA_KEYPOINT) +2;
00978
00979
00980 for( j = param._level_min +2; j < param._level_max ; j++, dog++, key++)
00981 {
00982 if(GlobalUtil::_timingL)t = CLOCK();
00983
00984
00985 _OpenCL->ComputeKEY(dog, key, param._dog_threshold, param._edge_threshold);
00986 if(GlobalUtil::_timingL)
00987 {
00988 std::cout<<(CLOCK()-t)<<"\t";
00989 }
00990 }
00991 if(GlobalUtil::_timingO)
00992 {
00993 std::cout<<"|\t"<<(CLOCK()-t0)<<"\n";
00994 }
00995 }
00996
00997 if(GlobalUtil::_timingS)
00998 {
00999 _OpenCL->FinishCL();
01000 if(GlobalUtil::_verbose)
01001 {
01002 t2 = CLOCK();
01003 std::cout <<"<Gradient, DOG >\t"<<(t1-ts)<<"\n"
01004 <<"<Get Keypoints >\t"<<(t2-t1)<<"\n";
01005 }
01006 }
01007 }
01008
01009 void PyramidCL::CopyGradientTex()
01010 {
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033 }
01034
01035 void PyramidCL::ComputeGradient()
01036 {
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064 }
01065
01066 int PyramidCL::FitHistogramPyramid(CLTexImage* tex)
01067 {
01068 CLTexImage *htex;
01069 int hist_level_num = _hpLevelNum - _pyramid_octave_first / 2;
01070 htex = _histoPyramidTex + hist_level_num - 1;
01071 int w = (tex->GetImgWidth() + 2) >> 2;
01072 int h = tex->GetImgHeight();
01073 int count = 0;
01074 for(int k = 0; k < hist_level_num; k++, htex--)
01075 {
01076
01077 htex->InitTexture(w, h, 4);
01078 ++count;
01079 if(w == 1)
01080 break;
01081 w = (w + 3)>>2;
01082 }
01083 return count;
01084 }
01085
01086 void PyramidCL::GetFeatureOrientations()
01087 {
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115 }
01116
01117 void PyramidCL::GetSimplifiedOrientation()
01118 {
01119
01120 GetFeatureOrientations();
01121 }
01122
01123 CLTexImage* PyramidCL::GetBaseLevel(int octave, int dataName)
01124 {
01125 if(octave <_octave_min || octave > _octave_min + _octave_num) return NULL;
01126 int offset = (_pyramid_octave_first + octave - _octave_min) * param._level_num;
01127 int num = param._level_num * _pyramid_octave_num;
01128 return _allPyramid + num * dataName + offset;
01129 }
01130
01131 #endif
01132