PyramidCL.cpp
Go to the documentation of this file.
00001 
00002 //      File:           PyramidCL.cpp
00003 //      Author:         Changchang Wu
00004 //      Description : implementation of the PyramidCL class.
00005 //                              OpenCL-based implementation of SiftPyramid
00006 //
00007 //      Copyright (c) 2007 University of North Carolina at Chapel Hill
00008 //      All Rights Reserved
00009 //
00010 //      Permission to use, copy, modify and distribute this software and its
00011 //      documentation for educational, research and non-profit purposes, without
00012 //      fee, and without a written agreement is hereby granted, provided that the
00013 //      above copyright notice and the following paragraph appear in all copies.
00014 //      
00015 //      The University of North Carolina at Chapel Hill make no representations
00016 //      about the suitability of this software for any purpose. It is provided
00017 //      'as is' without express or implied warranty. 
00018 //
00019 //      Please send BUG REPORTS to ccwu@cs.unc.edu
00020 //
00022 
00023 #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                         //can't upsample by more than 8
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                 //must use 0 as _octave_min; 
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                 //try use the pyramid allocated for large image on small input images
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         //first octave does not change
00161         _pyramid_octave_first = 0;
00162 
00163         
00164         //compute # of octaves
00165         input_sz = min(w,h) ;
00166         _pyramid_width =  w;
00167         _pyramid_height =  h;
00168 
00169         //reset to preset parameters
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                 //destroy the original pyramid if the # of octave changes
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         //      //initialize the pyramid
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                 //several auxilary textures are not actually required
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         // (4 ^ (_hpLevelNum) -1 / 3) pixels
00328         totalkb += (((1 << (2 * _hpLevelNum)) -1) / 3 * 16 / 1024);
00329 
00330         //initialize the feature texture
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;   //give it at least a space of 32 feature
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         //this just need be initialized once
00366         if(_descriptorTex==NULL)
00367         {
00368                 //initialize feature texture pyramid
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         //descriptors...
00383         /*float* pd =  &_descriptor_buffer[0];
00384         vector<float> descriptor_buffer2;
00385 
00386         //use another buffer if we need to re-order the descriptors
00387         if(_keypoint_index.size() > 0)
00388         {
00389                 descriptor_buffer2.resize(_descriptor_buffer.size());
00390                 pd = &descriptor_buffer2[0];
00391         }
00392 
00393         CLTexImage * got, * ftex= _featureTex;
00394         for(int i = 0, idx = 0; i < _octave_num; i++)
00395         {
00396                 got = GetBaseLevel(i + _octave_min, DATA_GRAD) + 1;
00397                 for(int j = 0; j < param._dog_level_num; j++, ftex++, idx++, got++)
00398                 {
00399                         if(_levelFeatureNum[idx]==0) continue;
00400                         ProgramCL::ComputeDescriptor(ftex, got, _descriptorTex);//process
00401                         _descriptorTex->CopyToHost(pd); //readback descriptor
00402                         pd += 128*_levelFeatureNum[idx];
00403                 }
00404         }
00405 
00406         if(GlobalUtil::_timingS) _OpenCL->FinishCL();
00407 
00408         if(_keypoint_index.size() > 0)
00409         {
00410             //put the descriptor back to the original order for keypoint list.
00411                 for(int i = 0; i < _featureNum; ++i)
00412                 {
00413                         int index = _keypoint_index[i];
00414                         memcpy(&_descriptor_buffer[index*128], &descriptor_buffer2[i*128], 128 * sizeof(float));
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); // should already be 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                                         //add this keypoint to the list
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                                         //save the index of keypoints
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                 //texture size
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;      //x
00547                         ds[1] = oss*(fs[1]-0.5f) + offset;      //y
00548                         ds[2] = oss*fs[2];  //scale
00549                         ds[3] = (float)fmod(twopi-fs[3], twopi);        //orientation, mirrored
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         //it is weried that this part is very slow.
00564         //use a big VBO to save all the SIFT box vertices
00565         /*int nvbo = _octave_num * param._dog_level_num;
00566         if(_featureDisplayVBO==NULL)
00567         {
00568                 //initialize the vbos
00569                 _featureDisplayVBO = new GLuint[nvbo];
00570                 _featurePointVBO = new GLuint[nvbo];
00571                 glGenBuffers(nvbo, _featureDisplayVBO); 
00572                 glGenBuffers(nvbo, _featurePointVBO);
00573         }
00574         for(int i = 0; i < nvbo; i++)
00575         {
00576                 if(_levelFeatureNum[i]<=0)continue;
00577                 CLTexImage * ftex  = _featureTex + i;
00578                 CLTexImage texPBO1( _levelFeatureNum[i]* 10, 1, 4, _featureDisplayVBO[i]);
00579                 CLTexImage texPBO2(_levelFeatureNum[i], 1, 4, _featurePointVBO[i]);
00580                 _OpenCL->DisplayKeyBox(ftex, &texPBO1);
00581                 _OpenCL->DisplayKeyPoint(ftex, &texPBO2);       
00582         }*/
00583 }
00584 
00585 void PyramidCL::DestroySharedData() 
00586 {
00587         //histogram reduction
00588         if(_histoPyramidTex)
00589         {
00590                 delete[]        _histoPyramidTex;
00591                 _hpLevelNum = 0;
00592                 _histoPyramidTex = NULL;
00593         }
00594         //descriptor storage shared by all levels
00595         if(_descriptorTex)
00596         {
00597                 delete _descriptorTex;
00598                 _descriptorTex = NULL;
00599         }
00600         //cpu reduction buffer.
00601         if(_histo_buffer)
00602         {
00603                 delete[] _histo_buffer;
00604                 _histo_buffer = 0;
00605         }
00606 }
00607 
00608 void PyramidCL::DestroyPerLevelData() 
00609 {
00610         //integers vector to store the feature numbers.
00611         if(_levelFeatureNum)
00612         {
00613                 delete [] _levelFeatureNum;
00614                 _levelFeatureNum = NULL;
00615         }
00616         //texture used to store features
00617         if(     _featureTex)
00618         {
00619                 delete [] _featureTex;
00620                 _featureTex =   NULL;
00621         }
00622         //texture used for multi-orientation 
00623         if(_orientationTex)
00624         {
00625                 delete [] _orientationTex;
00626                 _orientationTex = NULL;
00627         }
00628         int no = _octave_num* param._dog_level_num;
00629 
00630         //two sets of vbos used to display the features
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         //use a different keypoint buffer when processing with an exisint features list
00661         //without orientation information. 
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;       //x
00686                                         ps[1] = os*(ps[1]-0.5f) + offset;       //y
00687                                         ps[2] = os*ps[2]; 
00688                                         ps[3] = (float)fmod(twopi-ps[3], twopi);        //orientation, mirrored
00689                                 }
00690                                 p+= 4* _levelFeatureNum[idx];
00691                         }
00692                 }
00693         }
00694 
00695         //put the feature into their original order for existing keypoint 
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         //no cpu version provided
00709         GenerateFeatureList();
00710 }
00711 
00712 void PyramidCL::GenerateFeatureList(int i, int j, int reduction_count, vector<int>& hbuffer)
00713 {
00714     /*int fcount = 0, idx = i * param._dog_level_num  + j;
00715         int hist_level_num = _hpLevelNum - _pyramid_octave_first /2; 
00716         int ii, k, len; 
00717 
00718         CLTexImage * htex, * ftex, * tex, *got;
00719         ftex = _featureTex + idx;
00720         htex = _histoPyramidTex + hist_level_num -1;
00721         tex = GetBaseLevel(_octave_min + i, DATA_KEYPOINT) + 2 + j;
00722         got = GetBaseLevel(_octave_min + i, DATA_GRAD) + 2 + j;
00723 
00724         _OpenCL->InitHistogram(tex, htex);
00725 
00726         for(k = 0; k < reduction_count - 1; k++, htex--)
00727         {
00728                 ProgramCL::ReduceHistogram(htex, htex -1);      
00729         }
00730         
00731         //htex has the row reduction result
00732         len = htex->GetImgHeight() * 4;
00733         hbuffer.resize(len);
00734         _OpenCL->FinishCL();
00735         htex->CopyToHost(&hbuffer[0]);
00736         //
00737         for(ii = 0; ii < len; ++ii)             fcount += hbuffer[ii];
00738         SetLevelFeatureNum(idx, fcount);
00739         
00740     //build the feature list
00741         if(fcount > 0)
00742         {
00743                 _featureNum += fcount;
00744                 _keypoint_buffer.resize(fcount * 4);
00745                 //vector<int> ikbuf(fcount*4);
00746                 int* ibuf = (int*) (&_keypoint_buffer[0]);
00747 
00748                 for(ii = 0; ii < len; ++ii)
00749                 {
00750                         int x = ii%4, y = ii / 4;
00751                         for(int jj = 0 ; jj < hbuffer[ii]; ++jj, ibuf+=4)
00752                         {
00753                                 ibuf[0] = x; ibuf[1] = y; ibuf[2] = jj; ibuf[3] = 0;
00754                         }
00755                 }
00756                 _featureTex[idx].CopyFromHost(&_keypoint_buffer[0]);
00757         
00759                 ProgramCL::GenerateList(_featureTex + idx, ++htex);
00760                 for(k = 2; k < reduction_count; k++)
00761                 {
00762                         ProgramCL::GenerateList(_featureTex + idx, ++htex);
00763                 }
00764         }*/
00765 }
00766 
00767 void PyramidCL::GenerateFeatureList()
00768 {
00769         /*double t1, t2; 
00770         int ocount = 0, reduction_count;
00771     int reverse = (GlobalUtil::_TruncateMethod == 1);
00772 
00773         vector<int> hbuffer;
00774         _featureNum = 0;
00775 
00776         //for(int i = 0, idx = 0; i < _octave_num; i++)
00777     FOR_EACH_OCTAVE(i, reverse)
00778         {
00779         CLTexImage* tex = GetBaseLevel(_octave_min + i, DATA_KEYPOINT) + 2;
00780                 reduction_count = FitHistogramPyramid(tex);
00781 
00782                 if(GlobalUtil::_timingO)
00783                 {
00784                         t1 = CLOCK(); 
00785                         ocount = 0;
00786                         std::cout<<"#"<<i+_octave_min + _down_sample_factor<<":\t";
00787                 }
00788                 //for(int j = 0; j < param._dog_level_num; j++, idx++)
00789         FOR_EACH_LEVEL(j, reverse)
00790                 {
00791             if(GlobalUtil::_TruncateMethod && GlobalUtil::_FeatureCountThreshold > 0 && _featureNum > GlobalUtil::_FeatureCountThreshold) continue;
00792 
00793                 GenerateFeatureList(i, j, reduction_count, hbuffer);
00794 
00796                         if(GlobalUtil::_timingO)
00797                         {
00798                 int idx = i * param._dog_level_num + j;
00799                                 ocount += _levelFeatureNum[idx];
00800                                 std::cout<< _levelFeatureNum[idx] <<"\t";
00801                         }
00802                 }
00803                 if(GlobalUtil::_timingO)
00804                 {       
00805                         t2 = CLOCK(); 
00806                         std::cout << "| \t" << int(ocount) << " :\t(" << (t2 - t1) << ")\n";
00807                 }
00808         }
00810         CopyGradientTex();
00812         if(GlobalUtil::_timingS)_OpenCL->FinishCL();
00813 
00814         if(GlobalUtil::_verbose)
00815         {
00816                 std::cout<<"#Features:\t"<<_featureNum<<"\n";
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         //copy the input image to pixel buffer object
00868     if(input->_pixel_data)
00869     {
00870         output->InitTexture(ws, hs, 1);
00871         output->CopyFromHost(input->_pixel_data); 
00872     }else /*if(input->_rgb_converted && input->CopyToPBO(_bufferPBO, ws, hs, GL_LUMINANCE))
00873     {
00874                 output->InitTexture(ws, hs, 1);
00875         output->CopyFromPBO(ws, hs, _bufferPBO); 
00876     }else if(input->CopyToPBO(_bufferPBO, ws, hs))
00877         {
00878                 CLTexImage texPBO(ws, hs, 4, _bufferPBO);
00879                 output->InitTexture(ws, hs, 1);
00880                 ProgramCL::ReduceToSingleChannel(output, &texPBO, !input->_rgb_converted);
00881         }else*/
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                         // filtering
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                 //compute the gradient
00953                 for(j = param._level_min +1; j <=  param._level_max ; j++, gus++, dog++, grd++, rot++)
00954                 {
00955                         //input: gus and gus -1
00956                         //output: gradient, dog, orientation
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     //if(GlobalUtil::_timingS) _OpenCL->FinishCL();
00966     //if(!GlobalUtil::_usePackedTex) return; //not finished
00967     //return; 
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                         //input, dog, dog + 1, dog -1
00984                         //output, key
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         /*double ts, t1;
01012 
01013         if(GlobalUtil::_timingS && GlobalUtil::_verbose)ts = CLOCK();
01014 
01015         for(int i = 0, idx = 0; i < _octave_num; i++)
01016         {
01017                 CLTexImage * got = GetBaseLevel(i + _octave_min, DATA_GRAD) +  1;
01018                 //compute the gradient
01019                 for(int j = 0; j <  param._dog_level_num ; j++, got++, idx++)
01020                 {
01021                         if(_levelFeatureNum[idx] > 0)   got->CopyToTexture2D();
01022                 }
01023         }
01024         if(GlobalUtil::_timingS)
01025         {
01026                 ProgramCL::FinishCLDA();
01027                 if(GlobalUtil::_verbose)
01028                 {
01029                         t1 = CLOCK();
01030                         std::cout       <<"<Copy Grad/Orientation>\t"<<(t1-ts)<<"\n";
01031                 }
01032         }*/
01033 }
01034 
01035 void PyramidCL::ComputeGradient() 
01036 {
01037 
01038         /*int i, j;
01039         double ts, t1;
01040 
01041         if(GlobalUtil::_timingS && GlobalUtil::_verbose)ts = CLOCK();
01042 
01043         for(i = _octave_min; i < _octave_min + _octave_num; i++)
01044         {
01045                 CLTexImage * gus = GetBaseLevel(i) +  1;
01046                 CLTexImage * dog = GetBaseLevel(i, DATA_DOG) +  1;
01047                 CLTexImage * got = GetBaseLevel(i, DATA_GRAD) +  1;
01048 
01049                 //compute the gradient
01050                 for(j = 0; j <  param._dog_level_num ; j++, gus++, dog++, got++)
01051                 {
01052                         ProgramCL::ComputeDOG(gus, dog, got);
01053                 }
01054         }
01055         if(GlobalUtil::_timingS)
01056         {
01057                 ProgramCL::FinishCLDA();
01058                 if(GlobalUtil::_verbose)
01059                 {
01060                         t1 = CLOCK();
01061                         std::cout       <<"<Gradient, DOG  >\t"<<(t1-ts)<<"\n";
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                 //htex->SetImageSize(w, h);     
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         CLTexImage * ftex = _featureTex;
01091         int * count      = _levelFeatureNum;
01092         float sigma, sigma_step = powf(2.0f, 1.0f/param._dog_level_num);
01093 
01094         for(int i = 0; i < _octave_num; i++)
01095         {
01096                 CLTexImage* got = GetBaseLevel(i + _octave_min, DATA_GRAD) + 1;
01097                 CLTexImage* key = GetBaseLevel(i + _octave_min, DATA_KEYPOINT) + 2;
01098 
01099                 for(int j = 0; j < param._dog_level_num; j++, ftex++, count++, got++, key++)
01100                 {
01101                         if(*count<=0)continue;
01102 
01103                         //if(ftex->GetImgWidth() < *count) ftex->InitTexture(*count, 1, 4);
01104 
01105                         sigma = param.GetLevelSigma(j+param._level_min+1);
01106 
01107                         ProgramCL::ComputeOrientation(ftex, got, key, sigma, sigma_step, _existing_keypoints);          
01108                 }
01109         }
01110 
01111         if(GlobalUtil::_timingS)ProgramCL::FinishCL();
01112         */
01113 
01114 
01115 }
01116 
01117 void PyramidCL::GetSimplifiedOrientation() 
01118 {
01119         //no simplified orientation
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


rgbd_registration
Author(s): Ross Kidson
autogenerated on Thu May 23 2013 15:36:53