| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #if defined(CL_SIFTGPU_ENABLED) |
|
|
|
|
| #include "GL/glew.h" |
| #include <CL/OpenCL.h> |
| #include <iostream> |
| #include <vector> |
| #include <algorithm> |
| #include <stdlib.h> |
| #include <math.h> |
| using namespace std; |
|
|
| #include "GlobalUtil.h" |
| #include "GLTexImage.h" |
| #include "CLTexImage.h" |
| #include "SiftGPU.h" |
| #include "SiftPyramid.h" |
| #include "ProgramCL.h" |
| #include "PyramidCL.h" |
|
|
|
|
| #define USE_TIMING() double t, t0, tt; |
| #define OCTAVE_START() if(GlobalUtil::_timingO){ t = t0 = CLOCK(); cout<<"#"<<i+_down_sample_factor<<"\t"; } |
| #define LEVEL_FINISH() if(GlobalUtil::_timingL){ _OpenCL->FinishCL(); tt = CLOCK();cout<<(tt-t)<<"\t"; t = CLOCK();} |
| #define OCTAVE_FINISH() if(GlobalUtil::_timingO)cout<<"|\t"<<(CLOCK()-t0)<<endl; |
|
|
|
|
| PyramidCL::PyramidCL(SiftParam& sp) : SiftPyramid(sp) |
| { |
| _allPyramid = NULL; |
| _histoPyramidTex = NULL; |
| _featureTex = NULL; |
| _descriptorTex = NULL; |
| _orientationTex = NULL; |
| _bufferTEX = NULL; |
| if(GlobalUtil::_usePackedTex) _OpenCL = new ProgramBagCL(); |
| else _OpenCL = new ProgramBagCLN(); |
| _OpenCL->InitProgramBag(sp); |
| _inputTex = new CLTexImage( _OpenCL->GetContextCL(), |
| _OpenCL->GetCommandQueue()); |
| |
| InitializeContext(); |
| } |
|
|
| PyramidCL::~PyramidCL() |
| { |
| DestroyPerLevelData(); |
| DestroySharedData(); |
| DestroyPyramidData(); |
| if(_OpenCL) delete _OpenCL; |
| if(_inputTex) delete _inputTex; |
| if(_bufferTEX) delete _bufferTEX; |
| } |
|
|
| void PyramidCL::InitializeContext() |
| { |
| GlobalUtil::InitGLParam(1); |
| } |
|
|
| void PyramidCL::InitPyramid(int w, int h, int ds) |
| { |
| int wp, hp, toobig = 0; |
| if(ds == 0) |
| { |
| _down_sample_factor = 0; |
| if(GlobalUtil::_octave_min_default>=0) |
| { |
| wp = w >> _octave_min_default; |
| hp = h >> _octave_min_default; |
| }else |
| { |
| |
| _octave_min_default = max(-3, _octave_min_default); |
| |
| wp = w << (-_octave_min_default); |
| hp = h << (-_octave_min_default); |
| } |
| _octave_min = _octave_min_default; |
| }else |
| { |
| |
| _octave_min = 0; |
| _down_sample_factor = ds; |
| w >>= ds; |
| h >>= ds; |
| wp = w; |
| hp = h; |
| } |
|
|
| while(wp > GlobalUtil::_texMaxDim || hp > GlobalUtil::_texMaxDim ) |
| { |
| _octave_min ++; |
| wp >>= 1; |
| hp >>= 1; |
| toobig = 1; |
| } |
| if(toobig && GlobalUtil::_verbose && _octave_min > 0) |
| { |
| std::cout<< "**************************************************************\n" |
| "Image larger than allowed dimension, data will be downsampled!\n" |
| "use -maxd to change the settings\n" |
| "***************************************************************\n"; |
| } |
|
|
| if( wp == _pyramid_width && hp == _pyramid_height && _allocated ) |
| { |
| FitPyramid(wp, hp); |
| }else if(GlobalUtil::_ForceTightPyramid || _allocated ==0) |
| { |
| ResizePyramid(wp, hp); |
| } |
| else if( wp > _pyramid_width || hp > _pyramid_height ) |
| { |
| ResizePyramid(max(wp, _pyramid_width), max(hp, _pyramid_height)); |
| if(wp < _pyramid_width || hp < _pyramid_height) FitPyramid(wp, hp); |
| } |
| else |
| { |
| |
| FitPyramid(wp, hp); |
| } |
|
|
| _OpenCL->SelectInitialSmoothingFilter(_octave_min + _down_sample_factor, param); |
| } |
|
|
| void PyramidCL::ResizePyramid(int w, int h) |
| { |
| |
| unsigned int totalkb = 0; |
| int _octave_num_new, input_sz, i, j; |
| |
|
|
| if(_pyramid_width == w && _pyramid_height == h && _allocated) return; |
|
|
| if(w > GlobalUtil::_texMaxDim || h > GlobalUtil::_texMaxDim) return ; |
|
|
| if(GlobalUtil::_verbose && GlobalUtil::_timingS) std::cout<<"[Allocate Pyramid]:\t" <<w<<"x"<<h<<endl; |
| |
| _pyramid_octave_first = 0; |
|
|
| |
| |
| input_sz = min(w,h) ; |
| _pyramid_width = w; |
| _pyramid_height = h; |
|
|
| |
| _octave_num_new = GlobalUtil::_octave_num_default; |
|
|
| if(_octave_num_new < 1) _octave_num_new = GetRequiredOctaveNum(input_sz) ; |
|
|
| if(_pyramid_octave_num != _octave_num_new) |
| { |
| |
| if(_octave_num >0) |
| { |
| DestroyPerLevelData(); |
| DestroyPyramidData(); |
| } |
| _pyramid_octave_num = _octave_num_new; |
| } |
|
|
| _octave_num = _pyramid_octave_num; |
|
|
| int noct = _octave_num; |
| int nlev = param._level_num; |
| int texNum = noct* nlev * DATA_NUM; |
|
|
| |
| if(_allPyramid==NULL) |
| { |
| _allPyramid = new CLTexImage[ texNum]; |
| cl_context context = _OpenCL->GetContextCL(); |
| cl_command_queue queue = _OpenCL->GetCommandQueue(); |
| for(i = 0; i < texNum; ++i) _allPyramid[i].SetContext(context, queue); |
| } |
|
|
|
|
|
|
| CLTexImage * gus = GetBaseLevel(_octave_min, DATA_GAUSSIAN); |
| CLTexImage * dog = GetBaseLevel(_octave_min, DATA_DOG); |
| CLTexImage * grd = GetBaseLevel(_octave_min, DATA_GRAD); |
| CLTexImage * rot = GetBaseLevel(_octave_min, DATA_ROT); |
| CLTexImage * key = GetBaseLevel(_octave_min, DATA_KEYPOINT); |
|
|
| |
|
|
|
|
|
|
| for(i = 0; i< noct; i++) |
| { |
| for( j = 0; j< nlev; j++, gus++, dog++, grd++, rot++, key++) |
| { |
| gus->InitPackedTex(w, h, GlobalUtil::_usePackedTex); |
| if(j==0)continue; |
| dog->InitPackedTex(w, h, GlobalUtil::_usePackedTex); |
| if(j < 1 + param._dog_level_num) |
| { |
| grd->InitPackedTex(w, h, GlobalUtil::_usePackedTex); |
| rot->InitPackedTex(w, h, GlobalUtil::_usePackedTex); |
| } |
| if(j > 1 && j < nlev -1) key->InitPackedTex(w, h, GlobalUtil::_usePackedTex); |
| } |
| |
| int tsz = (gus -1)->GetTexPixelCount() * 16; |
| totalkb += ((nlev *5 -6)* tsz / 1024); |
| |
| w>>=1; |
| h>>=1; |
| } |
|
|
| totalkb += ResizeFeatureStorage(); |
|
|
| _allocated = 1; |
|
|
| if(GlobalUtil::_verbose && GlobalUtil::_timingS) std::cout<<"[Allocate Pyramid]:\t" <<(totalkb/1024)<<"MB\n"; |
|
|
| } |
|
|
| void PyramidCL::FitPyramid(int w, int h) |
| { |
| _pyramid_octave_first = 0; |
| |
| _octave_num = GlobalUtil::_octave_num_default; |
|
|
| int _octave_num_max = GetRequiredOctaveNum(min(w, h)); |
|
|
| if(_octave_num < 1 || _octave_num > _octave_num_max) |
| { |
| _octave_num = _octave_num_max; |
| } |
|
|
|
|
| int pw = _pyramid_width>>1, ph = _pyramid_height>>1; |
| while(_pyramid_octave_first + _octave_num < _pyramid_octave_num && |
| pw >= w && ph >= h) |
| { |
| _pyramid_octave_first++; |
| pw >>= 1; |
| ph >>= 1; |
| } |
|
|
| |
| for(int i = 0; i < _octave_num; i++) |
| { |
| CLTexImage * tex = GetBaseLevel(i + _octave_min); |
| CLTexImage * dog = GetBaseLevel(i + _octave_min, DATA_DOG); |
| CLTexImage * grd = GetBaseLevel(i + _octave_min, DATA_GRAD); |
| CLTexImage * rot = GetBaseLevel(i + _octave_min, DATA_ROT); |
| CLTexImage * key = GetBaseLevel(i + _octave_min, DATA_KEYPOINT); |
| for(int j = param._level_min; j <= param._level_max; j++, tex++, dog++, grd++, rot++, key++) |
| { |
| tex->SetPackedSize(w, h, GlobalUtil::_usePackedTex); |
| if(j == param._level_min) continue; |
| dog->SetPackedSize(w, h, GlobalUtil::_usePackedTex); |
| if(j < param._level_max - 1) |
| { |
| grd->SetPackedSize(w, h, GlobalUtil::_usePackedTex); |
| rot->SetPackedSize(w, h, GlobalUtil::_usePackedTex); |
| } |
| if(j > param._level_min + 1 && j < param._level_max) key->SetPackedSize(w, h, GlobalUtil::_usePackedTex); |
| } |
| w>>=1; |
| h>>=1; |
| } |
| } |
|
|
|
|
| void PyramidCL::SetLevelFeatureNum(int idx, int fcount) |
| { |
| _featureTex[idx].InitBufferTex(fcount, 1, 4); |
| _levelFeatureNum[idx] = fcount; |
| } |
|
|
| int PyramidCL::ResizeFeatureStorage() |
| { |
| int totalkb = 0; |
| if(_levelFeatureNum==NULL) _levelFeatureNum = new int[_octave_num * param._dog_level_num]; |
| std::fill(_levelFeatureNum, _levelFeatureNum+_octave_num * param._dog_level_num, 0); |
|
|
| cl_context context = _OpenCL->GetContextCL(); |
| cl_command_queue queue = _OpenCL->GetCommandQueue(); |
| int wmax = GetBaseLevel(_octave_min)->GetImgWidth() * 2; |
| int hmax = GetBaseLevel(_octave_min)->GetImgHeight() * 2; |
| int whmax = max(wmax, hmax); |
| int w, i; |
|
|
| |
| int num = (int)ceil(log(double(whmax))/log(4.0)); |
|
|
| if( _hpLevelNum != num) |
| { |
| _hpLevelNum = num; |
| if(_histoPyramidTex ) delete [] _histoPyramidTex; |
| _histoPyramidTex = new CLTexImage[_hpLevelNum]; |
| for(i = 0; i < _hpLevelNum; ++i) _histoPyramidTex[i].SetContext(context, queue); |
| } |
|
|
| for(i = 0, w = 1; i < _hpLevelNum; i++) |
| { |
| _histoPyramidTex[i].InitBufferTex(w, whmax, 4); |
| w<<=2; |
| } |
|
|
| |
| totalkb += (((1 << (2 * _hpLevelNum)) -1) / 3 * 16 / 1024); |
|
|
| |
| int idx = 0, n = _octave_num * param._dog_level_num; |
| if(_featureTex==NULL) |
| { |
| _featureTex = new CLTexImage[n]; |
| for(i = 0; i <n; ++i) _featureTex[i].SetContext(context, queue); |
| } |
| if(GlobalUtil::_MaxOrientation >1 && GlobalUtil::_OrientationPack2==0 && _orientationTex== NULL) |
| { |
| _orientationTex = new CLTexImage[n]; |
| for(i = 0; i < n; ++i) _orientationTex[i].SetContext(context, queue); |
| } |
|
|
|
|
| for(i = 0; i < _octave_num; i++) |
| { |
| CLTexImage * tex = GetBaseLevel(i+_octave_min); |
| int fmax = int(4 * tex->GetTexWidth() * tex->GetTexHeight()*GlobalUtil::_MaxFeaturePercent); |
| |
| if(fmax > GlobalUtil::_MaxLevelFeatureNum) fmax = GlobalUtil::_MaxLevelFeatureNum; |
| else if(fmax < 32) fmax = 32; |
|
|
| for(int j = 0; j < param._dog_level_num; j++, idx++) |
| { |
| _featureTex[idx].InitBufferTex(fmax, 1, 4); |
| totalkb += fmax * 16 /1024; |
| |
| if(GlobalUtil::_MaxOrientation>1 && GlobalUtil::_OrientationPack2 == 0) |
| { |
| _orientationTex[idx].InitBufferTex(fmax, 1, 4); |
| totalkb += fmax * 16 /1024; |
| } |
| } |
| } |
|
|
| |
| if(_descriptorTex==NULL) |
| { |
| |
| int fmax = _featureTex->GetImgWidth(); |
| _descriptorTex = new CLTexImage(context, queue); |
| totalkb += ( fmax /2); |
| _descriptorTex->InitBufferTex(fmax *128, 1, 1); |
| }else |
| { |
| totalkb += _descriptorTex->GetDataSize()/1024; |
| } |
| return totalkb; |
| } |
|
|
| void PyramidCL::GetFeatureDescriptors() |
| { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
|
|
| void PyramidCL::GenerateFeatureListTex() |
| { |
|
|
| vector<float> list; |
| int idx = 0; |
| const double twopi = 2.0*3.14159265358979323846; |
| float sigma_half_step = powf(2.0f, 0.5f / param._dog_level_num); |
| float octave_sigma = _octave_min>=0? float(1<<_octave_min): 1.0f/(1<<(-_octave_min)); |
| float offset = GlobalUtil::_LoweOrigin? 0 : 0.5f; |
| if(_down_sample_factor>0) octave_sigma *= float(1<<_down_sample_factor); |
|
|
| _keypoint_index.resize(0); |
| for(int i = 0; i < _octave_num; i++, octave_sigma*= 2.0f) |
| { |
| for(int j = 0; j < param._dog_level_num; j++, idx++) |
| { |
| list.resize(0); |
| float level_sigma = param.GetLevelSigma(j + param._level_min + 1) * octave_sigma; |
| float sigma_min = level_sigma / sigma_half_step; |
| float sigma_max = level_sigma * sigma_half_step; |
| int fcount = 0 ; |
| for(int k = 0; k < _featureNum; k++) |
| { |
| float * key = &_keypoint_buffer[k*4]; |
| if( (key[2] >= sigma_min && key[2] < sigma_max) |
| ||(key[2] < sigma_min && i ==0 && j == 0) |
| ||(key[2] > sigma_max && i == _octave_num -1 && j == param._dog_level_num - 1)) |
| { |
| |
| list.push_back((key[0] - offset) / octave_sigma + 0.5f); |
| list.push_back((key[1] - offset) / octave_sigma + 0.5f); |
| list.push_back(key[2] / octave_sigma); |
| list.push_back((float)fmod(twopi-key[3], twopi)); |
| fcount ++; |
| |
| _keypoint_index.push_back(k); |
| } |
|
|
| } |
|
|
| _levelFeatureNum[idx] = fcount; |
| if(fcount==0)continue; |
| CLTexImage * ftex = _featureTex+idx; |
|
|
| SetLevelFeatureNum(idx, fcount); |
| ftex->CopyFromHost(&list[0]); |
| } |
| } |
|
|
| if(GlobalUtil::_verbose) |
| { |
| std::cout<<"#Features:\t"<<_featureNum<<"\n"; |
| } |
|
|
| } |
|
|
| void PyramidCL::ReshapeFeatureListCPU() |
| { |
| int i, szmax =0, sz; |
| int n = param._dog_level_num*_octave_num; |
| for( i = 0; i < n; i++) |
| { |
| sz = _levelFeatureNum[i]; |
| if(sz > szmax ) szmax = sz; |
| } |
| float * buffer = new float[szmax*16]; |
| float * buffer1 = buffer; |
| float * buffer2 = buffer + szmax*4; |
|
|
|
|
|
|
| _featureNum = 0; |
|
|
| #ifdef NO_DUPLICATE_DOWNLOAD |
| const double twopi = 2.0*3.14159265358979323846; |
| _keypoint_buffer.resize(0); |
| float os = _octave_min>=0? float(1<<_octave_min): 1.0f/(1<<(-_octave_min)); |
| if(_down_sample_factor>0) os *= float(1<<_down_sample_factor); |
| float offset = GlobalUtil::_LoweOrigin? 0 : 0.5f; |
| #endif |
|
|
|
|
| for(i = 0; i < n; i++) |
| { |
| if(_levelFeatureNum[i]==0)continue; |
|
|
| _featureTex[i].CopyToHost(buffer1); |
| |
| int fcount =0; |
| float * src = buffer1; |
| float * des = buffer2; |
| const static double factor = 2.0*3.14159265358979323846/65535.0; |
| for(int j = 0; j < _levelFeatureNum[i]; j++, src+=4) |
| { |
| unsigned short * orientations = (unsigned short*) (&src[3]); |
| if(orientations[0] != 65535) |
| { |
| des[0] = src[0]; |
| des[1] = src[1]; |
| des[2] = src[2]; |
| des[3] = float( factor* orientations[0]); |
| fcount++; |
| des += 4; |
| if(orientations[1] != 65535 && orientations[1] != orientations[0]) |
| { |
| des[0] = src[0]; |
| des[1] = src[1]; |
| des[2] = src[2]; |
| des[3] = float(factor* orientations[1]); |
| fcount++; |
| des += 4; |
| } |
| } |
| } |
| |
| SetLevelFeatureNum(i, fcount); |
| _featureTex[i].CopyFromHost(buffer2); |
| |
| if(fcount == 0) continue; |
|
|
| #ifdef NO_DUPLICATE_DOWNLOAD |
| float oss = os * (1 << (i / param._dog_level_num)); |
| _keypoint_buffer.resize((_featureNum + fcount) * 4); |
| float* ds = &_keypoint_buffer[_featureNum * 4]; |
| float* fs = buffer2; |
| for(int k = 0; k < fcount; k++, ds+=4, fs+=4) |
| { |
| ds[0] = oss*(fs[0]-0.5f) + offset; |
| ds[1] = oss*(fs[1]-0.5f) + offset; |
| ds[2] = oss*fs[2]; |
| ds[3] = (float)fmod(twopi-fs[3], twopi); |
| } |
| #endif |
| _featureNum += fcount; |
| } |
| delete[] buffer; |
| if(GlobalUtil::_verbose) |
| { |
| std::cout<<"#Features MO:\t"<<_featureNum<<endl; |
| } |
| } |
|
|
| void PyramidCL::GenerateFeatureDisplayVBO() |
| { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
|
|
| void PyramidCL::DestroySharedData() |
| { |
| |
| if(_histoPyramidTex) |
| { |
| delete[] _histoPyramidTex; |
| _hpLevelNum = 0; |
| _histoPyramidTex = NULL; |
| } |
| |
| if(_descriptorTex) |
| { |
| delete _descriptorTex; |
| _descriptorTex = NULL; |
| } |
| |
| if(_histo_buffer) |
| { |
| delete[] _histo_buffer; |
| _histo_buffer = 0; |
| } |
| } |
|
|
| void PyramidCL::DestroyPerLevelData() |
| { |
| |
| if(_levelFeatureNum) |
| { |
| delete [] _levelFeatureNum; |
| _levelFeatureNum = NULL; |
| } |
| |
| if( _featureTex) |
| { |
| delete [] _featureTex; |
| _featureTex = NULL; |
| } |
| |
| if(_orientationTex) |
| { |
| delete [] _orientationTex; |
| _orientationTex = NULL; |
| } |
| int no = _octave_num* param._dog_level_num; |
|
|
| |
| if(_featureDisplayVBO) |
| { |
| glDeleteBuffers(no, _featureDisplayVBO); |
| delete [] _featureDisplayVBO; |
| _featureDisplayVBO = NULL; |
| } |
| if( _featurePointVBO) |
| { |
| glDeleteBuffers(no, _featurePointVBO); |
| delete [] _featurePointVBO; |
| _featurePointVBO = NULL; |
| } |
| } |
|
|
| void PyramidCL::DestroyPyramidData() |
| { |
| if(_allPyramid) |
| { |
| delete [] _allPyramid; |
| _allPyramid = NULL; |
| } |
| } |
|
|
| void PyramidCL::DownloadKeypoints() |
| { |
| const double twopi = 2.0*3.14159265358979323846; |
| int idx = 0; |
| float * buffer = &_keypoint_buffer[0]; |
| vector<float> keypoint_buffer2; |
| |
| |
| if(_keypoint_index.size() > 0) |
| { |
| keypoint_buffer2.resize(_keypoint_buffer.size()); |
| buffer = &keypoint_buffer2[0]; |
| } |
| float * p = buffer, *ps; |
| CLTexImage * ftex = _featureTex; |
| |
| float os = _octave_min>=0? float(1<<_octave_min): 1.0f/(1<<(-_octave_min)); |
| if(_down_sample_factor>0) os *= float(1<<_down_sample_factor); |
| float offset = GlobalUtil::_LoweOrigin? 0 : 0.5f; |
| |
| for(int i = 0; i < _octave_num; i++, os *= 2.0f) |
| { |
| |
| for(int j = 0; j < param._dog_level_num; j++, idx++, ftex++) |
| { |
|
|
| if(_levelFeatureNum[idx]>0) |
| { |
| ftex->CopyToHost(ps = p); |
| for(int k = 0; k < _levelFeatureNum[idx]; k++, ps+=4) |
| { |
| ps[0] = os*(ps[0]-0.5f) + offset; |
| ps[1] = os*(ps[1]-0.5f) + offset; |
| ps[2] = os*ps[2]; |
| ps[3] = (float)fmod(twopi-ps[3], twopi); |
| } |
| p+= 4* _levelFeatureNum[idx]; |
| } |
| } |
| } |
|
|
| |
| if(_keypoint_index.size() > 0) |
| { |
| for(int i = 0; i < _featureNum; ++i) |
| { |
| int index = _keypoint_index[i]; |
| memcpy(&_keypoint_buffer[index*4], &keypoint_buffer2[i*4], 4 * sizeof(float)); |
| } |
| } |
| } |
|
|
| void PyramidCL::GenerateFeatureListCPU() |
| { |
| |
| GenerateFeatureList(); |
| } |
|
|
| void PyramidCL::GenerateFeatureList(int i, int j, int reduction_count, vector<int>& hbuffer) |
| { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
|
|
| void PyramidCL::GenerateFeatureList() |
| { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
|
|
| GLTexImage* PyramidCL::GetLevelTexture(int octave, int level) |
| { |
| return GetLevelTexture(octave, level, DATA_GAUSSIAN); |
| } |
|
|
| GLTexImage* PyramidCL::ConvertTexCL2GL(CLTexImage* tex, int dataName) |
| { |
| |
| if(_bufferTEX == NULL) _bufferTEX = new GLTexImage; |
|
|
| |
| int ratio = GlobalUtil::_usePackedTex ? 2 : 1; |
| int width = tex->GetImgWidth() * ratio; |
| int height = tex->GetImgHeight() * ratio; |
| int tw = max(width, _bufferTEX->GetTexWidth()); |
| int th = max(height, _bufferTEX->GetTexHeight()); |
| _bufferTEX->InitTexture(tw, th, 1, GL_RGBA); |
| _bufferTEX->SetImageSize(width, height); |
|
|
| |
| CLTexImage texCL(_OpenCL->GetContextCL(), _OpenCL->GetCommandQueue()); |
| texCL.InitTextureGL(*_bufferTEX, width, height, 4); |
|
|
| switch(dataName) |
| { |
| case DATA_GAUSSIAN: _OpenCL->UnpackImage(tex, &texCL); break; |
| case DATA_DOG:_OpenCL->UnpackImageDOG(tex, &texCL); break; |
| case DATA_GRAD:_OpenCL->UnpackImageGRD(tex, &texCL); break; |
| case DATA_KEYPOINT:_OpenCL->UnpackImageKEY(tex, |
| tex - param._level_num * _pyramid_octave_num, &texCL);break; |
| default: |
| break; |
| } |
|
|
|
|
| return _bufferTEX; |
| } |
|
|
| GLTexImage* PyramidCL::GetLevelTexture(int octave, int level, int dataName) |
| { |
| CLTexImage* tex = GetBaseLevel(octave, dataName) + (level - param._level_min); |
| return ConvertTexCL2GL(tex, dataName); |
| } |
|
|
| void PyramidCL::ConvertInputToCL(GLTexInput* input, CLTexImage* output) |
| { |
| int ws = input->GetImgWidth(), hs = input->GetImgHeight(); |
| |
| if(input->_pixel_data) |
| { |
| output->InitTexture(ws, hs, 1); |
| output->CopyFromHost(input->_pixel_data); |
| }else |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| { |
| std::cerr<< "Unable To Convert Intput\n"; |
| } |
| } |
|
|
| void PyramidCL::BuildPyramid(GLTexInput * input) |
| { |
|
|
| USE_TIMING(); |
|
|
| int i, j; |
| |
| for ( i = _octave_min; i < _octave_min + _octave_num; i++) |
| { |
|
|
| CLTexImage *tex = GetBaseLevel(i); |
| CLTexImage *buf = GetBaseLevel(i, DATA_DOG) +2; |
| FilterCL ** filter = _OpenCL->f_gaussian_step; |
| j = param._level_min + 1; |
|
|
| OCTAVE_START(); |
|
|
| if( i == _octave_min ) |
| { |
| if(GlobalUtil::_usePackedTex) |
| { |
| ConvertInputToCL(input, _inputTex); |
| if(i < 0) _OpenCL->SampleImageU(tex, _inputTex, -i- 1); |
| else _OpenCL->SampleImageD(tex, _inputTex, i + 1); |
| }else |
| { |
| if(i == 0) ConvertInputToCL(input, tex); |
| else |
| { |
| ConvertInputToCL(input, _inputTex); |
| if(i < 0) _OpenCL->SampleImageU(tex, _inputTex, -i); |
| else _OpenCL->SampleImageD(tex, _inputTex, i); |
| } |
| } |
| _OpenCL->FilterInitialImage(tex, buf); |
| }else |
| { |
| _OpenCL->SampleImageD(tex, GetBaseLevel(i - 1) + param._level_ds - param._level_min); |
| _OpenCL->FilterSampledImage(tex, buf); |
| } |
| LEVEL_FINISH(); |
| for( ; j <= param._level_max ; j++, tex++, filter++) |
| { |
| |
| _OpenCL->FilterImage(*filter, tex + 1, tex, buf); |
| LEVEL_FINISH(); |
| } |
| OCTAVE_FINISH(); |
| } |
| if(GlobalUtil::_timingS) _OpenCL->FinishCL(); |
| } |
|
|
| void PyramidCL::DetectKeypointsEX() |
| { |
| int i, j; |
| double t0, t, ts, t1, t2; |
| |
| if(GlobalUtil::_timingS && GlobalUtil::_verbose) ts = CLOCK(); |
|
|
| for(i = _octave_min; i < _octave_min + _octave_num; i++) |
| { |
| CLTexImage * gus = GetBaseLevel(i) + 1; |
| CLTexImage * dog = GetBaseLevel(i, DATA_DOG) + 1; |
| CLTexImage * grd = GetBaseLevel(i, DATA_GRAD) + 1; |
| CLTexImage * rot = GetBaseLevel(i, DATA_ROT) + 1; |
| |
| for(j = param._level_min +1; j <= param._level_max ; j++, gus++, dog++, grd++, rot++) |
| { |
| |
| |
| _OpenCL->ComputeDOG(gus, gus - 1, dog, grd, rot); |
| } |
| } |
| if(GlobalUtil::_timingS && GlobalUtil::_verbose) |
| { |
| _OpenCL->FinishCL(); |
| t1 = CLOCK(); |
| } |
| |
| |
| |
|
|
| for ( i = _octave_min; i < _octave_min + _octave_num; i++) |
| { |
| if(GlobalUtil::_timingO) |
| { |
| t0 = CLOCK(); |
| std::cout<<"#"<<(i + _down_sample_factor)<<"\t"; |
| } |
| CLTexImage * dog = GetBaseLevel(i, DATA_DOG) + 2; |
| CLTexImage * key = GetBaseLevel(i, DATA_KEYPOINT) +2; |
|
|
|
|
| for( j = param._level_min +2; j < param._level_max ; j++, dog++, key++) |
| { |
| if(GlobalUtil::_timingL)t = CLOCK(); |
| |
| |
| _OpenCL->ComputeKEY(dog, key, param._dog_threshold, param._edge_threshold); |
| if(GlobalUtil::_timingL) |
| { |
| std::cout<<(CLOCK()-t)<<"\t"; |
| } |
| } |
| if(GlobalUtil::_timingO) |
| { |
| std::cout<<"|\t"<<(CLOCK()-t0)<<"\n"; |
| } |
| } |
|
|
| if(GlobalUtil::_timingS) |
| { |
| _OpenCL->FinishCL(); |
| if(GlobalUtil::_verbose) |
| { |
| t2 = CLOCK(); |
| std::cout <<"<Gradient, DOG >\t"<<(t1-ts)<<"\n" |
| <<"<Get Keypoints >\t"<<(t2-t1)<<"\n"; |
| } |
| } |
| } |
|
|
| void PyramidCL::CopyGradientTex() |
| { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
|
|
| void PyramidCL::ComputeGradient() |
| { |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
|
|
| int PyramidCL::FitHistogramPyramid(CLTexImage* tex) |
| { |
| CLTexImage *htex; |
| int hist_level_num = _hpLevelNum - _pyramid_octave_first / 2; |
| htex = _histoPyramidTex + hist_level_num - 1; |
| int w = (tex->GetImgWidth() + 2) >> 2; |
| int h = tex->GetImgHeight(); |
| int count = 0; |
| for(int k = 0; k < hist_level_num; k++, htex--) |
| { |
| |
| htex->InitTexture(w, h, 4); |
| ++count; |
| if(w == 1) |
| break; |
| w = (w + 3)>>2; |
| } |
| return count; |
| } |
|
|
| void PyramidCL::GetFeatureOrientations() |
| { |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| } |
|
|
| void PyramidCL::GetSimplifiedOrientation() |
| { |
| |
| GetFeatureOrientations(); |
| } |
|
|
| CLTexImage* PyramidCL::GetBaseLevel(int octave, int dataName) |
| { |
| if(octave <_octave_min || octave > _octave_min + _octave_num) return NULL; |
| int offset = (_pyramid_octave_first + octave - _octave_min) * param._level_num; |
| int num = param._level_num * _pyramid_octave_num; |
| return _allPyramid + num * dataName + offset; |
| } |
|
|
| #endif |
|
|
|
|