Project

General

Profile

Statistics
| Branch: | Revision:

root / rgbdslam / external / siftgpu / src / SiftGPU / PyramidCL.cpp @ 9240aaa3

History | View | Annotate | Download (29.7 KB)

1 9240aaa3 Alex
////////////////////////////////////////////////////////////////////////////
2
//        File:                PyramidCL.cpp
3
//        Author:                Changchang Wu
4
//        Description : implementation of the PyramidCL class.
5
//                                OpenCL-based implementation of SiftPyramid
6
//
7
//        Copyright (c) 2007 University of North Carolina at Chapel Hill
8
//        All Rights Reserved
9
//
10
//        Permission to use, copy, modify and distribute this software and its
11
//        documentation for educational, research and non-profit purposes, without
12
//        fee, and without a written agreement is hereby granted, provided that the
13
//        above copyright notice and the following paragraph appear in all copies.
14
//        
15
//        The University of North Carolina at Chapel Hill make no representations
16
//        about the suitability of this software for any purpose. It is provided
17
//        'as is' without express or implied warranty. 
18
//
19
//        Please send BUG REPORTS to ccwu@cs.unc.edu
20
//
21
////////////////////////////////////////////////////////////////////////////
22
23
#if defined(CL_SIFTGPU_ENABLED)
24
25
26
#include "GL/glew.h"
27
#include <CL/OpenCL.h>
28
#include <iostream>
29
#include <vector>
30
#include <algorithm>
31
#include <stdlib.h>
32
#include <math.h>
33
using namespace std;
34
35
#include "GlobalUtil.h"
36
#include "GLTexImage.h"
37
#include "CLTexImage.h" 
38
#include "SiftGPU.h"
39
#include "SiftPyramid.h"
40
#include "ProgramCL.h"
41
#include "PyramidCL.h"
42
43
44
#define USE_TIMING()                double t, t0, tt;
45
#define OCTAVE_START()                if(GlobalUtil::_timingO){        t = t0 = CLOCK();        cout<<"#"<<i+_down_sample_factor<<"\t";        }
46
#define LEVEL_FINISH()                if(GlobalUtil::_timingL){        _OpenCL->FinishCL();        tt = CLOCK();cout<<(tt-t)<<"\t";        t = CLOCK();}
47
#define OCTAVE_FINISH()                if(GlobalUtil::_timingO)cout<<"|\t"<<(CLOCK()-t0)<<endl;
48
49
50
PyramidCL::PyramidCL(SiftParam& sp) : SiftPyramid(sp)
51
{
52
        _allPyramid = NULL;
53
        _histoPyramidTex = NULL;
54
        _featureTex = NULL;
55
        _descriptorTex = NULL;
56
        _orientationTex = NULL;
57
    _bufferTEX = NULL;
58
    if(GlobalUtil::_usePackedTex)    _OpenCL = new ProgramBagCL();
59
    else                             _OpenCL = new ProgramBagCLN();
60
    _OpenCL->InitProgramBag(sp);
61
        _inputTex = new CLTexImage( _OpenCL->GetContextCL(),
62
                                _OpenCL->GetCommandQueue());
63
    /////////////////////////
64
    InitializeContext();
65
}
66
67
PyramidCL::~PyramidCL()
68
{
69
        DestroyPerLevelData();
70
        DestroySharedData();
71
        DestroyPyramidData();
72
    if(_OpenCL)   delete _OpenCL;
73
        if(_inputTex) delete _inputTex;
74
    if(_bufferTEX) delete _bufferTEX;
75
}
76
77
void PyramidCL::InitializeContext()
78
{
79
    GlobalUtil::InitGLParam(1);
80
}
81
82
void PyramidCL::InitPyramid(int w, int h, int ds)
83
{
84
        int wp, hp, toobig = 0;
85
        if(ds == 0)
86
        {
87
                _down_sample_factor = 0;
88
                if(GlobalUtil::_octave_min_default>=0)
89
                {
90
                        wp = w >> _octave_min_default;
91
                        hp = h >> _octave_min_default;
92
                }else
93
                {
94
                        //can't upsample by more than 8
95
                        _octave_min_default = max(-3, _octave_min_default);
96
                        //
97
                        wp = w << (-_octave_min_default);
98
                        hp = h << (-_octave_min_default);
99
                }
100
                _octave_min = _octave_min_default;
101
        }else
102
        {
103
                //must use 0 as _octave_min; 
104
                _octave_min = 0;
105
                _down_sample_factor = ds;
106
                w >>= ds;
107
                h >>= ds;
108
                wp = w;
109
                hp = h; 
110
        }
111
112
        while(wp > GlobalUtil::_texMaxDim  || hp > GlobalUtil::_texMaxDim )
113
        {
114
                _octave_min ++;
115
                wp >>= 1;
116
                hp >>= 1;
117
                toobig = 1;
118
        }
119
        if(toobig && GlobalUtil::_verbose && _octave_min > 0)
120
        {
121
                std::cout<< "**************************************************************\n"
122
                                        "Image larger than allowed dimension, data will be downsampled!\n"
123
                                        "use -maxd to change the settings\n"
124
                                        "***************************************************************\n";
125
        }
126
127
        if( wp == _pyramid_width && hp == _pyramid_height && _allocated )
128
        {
129
                FitPyramid(wp, hp);
130
        }else if(GlobalUtil::_ForceTightPyramid || _allocated ==0)
131
        {
132
                ResizePyramid(wp, hp);
133
        }
134
        else if( wp > _pyramid_width || hp > _pyramid_height )
135
        {
136
                ResizePyramid(max(wp, _pyramid_width), max(hp, _pyramid_height));
137
                if(wp < _pyramid_width || hp < _pyramid_height)  FitPyramid(wp, hp);
138
        }
139
        else
140
        {
141
                //try use the pyramid allocated for large image on small input images
142
                FitPyramid(wp, hp);
143
        }
144
145
    _OpenCL->SelectInitialSmoothingFilter(_octave_min + _down_sample_factor, param);
146
}
147
148
void PyramidCL::ResizePyramid(int w, int h)
149
{
150
        //
151
        unsigned int totalkb = 0;
152
        int _octave_num_new, input_sz, i, j;
153
        //
154
155
        if(_pyramid_width == w && _pyramid_height == h && _allocated) return;
156
157
        if(w > GlobalUtil::_texMaxDim || h > GlobalUtil::_texMaxDim) return ;
158
159
        if(GlobalUtil::_verbose && GlobalUtil::_timingS) std::cout<<"[Allocate Pyramid]:\t" <<w<<"x"<<h<<endl;
160
        //first octave does not change
161
        _pyramid_octave_first = 0;
162
163
        
164
        //compute # of octaves
165
        input_sz = min(w,h) ;
166
        _pyramid_width =  w;
167
        _pyramid_height =  h;
168
169
        //reset to preset parameters
170
        _octave_num_new  = GlobalUtil::_octave_num_default;
171
172
        if(_octave_num_new < 1) _octave_num_new = GetRequiredOctaveNum(input_sz) ;
173
174
        if(_pyramid_octave_num != _octave_num_new)
175
        {
176
                //destroy the original pyramid if the # of octave changes
177
                if(_octave_num >0) 
178
                {
179
                        DestroyPerLevelData();
180
                        DestroyPyramidData();
181
                }
182
                _pyramid_octave_num = _octave_num_new;
183
        }
184
185
        _octave_num = _pyramid_octave_num;
186
187
        int noct = _octave_num;
188
        int nlev = param._level_num;
189
    int texNum = noct* nlev * DATA_NUM;
190
191
        //        //initialize the pyramid
192
        if(_allPyramid==NULL)
193
    {
194
        _allPyramid = new CLTexImage[ texNum];
195
        cl_context       context  = _OpenCL->GetContextCL();
196
        cl_command_queue queue    = _OpenCL->GetCommandQueue();
197
        for(i = 0; i < texNum; ++i)   _allPyramid[i].SetContext(context, queue);
198
    }
199
200
201
202
        CLTexImage * gus =  GetBaseLevel(_octave_min, DATA_GAUSSIAN);
203
        CLTexImage * dog =  GetBaseLevel(_octave_min, DATA_DOG);
204
        CLTexImage * grd =  GetBaseLevel(_octave_min, DATA_GRAD);
205
    CLTexImage * rot =  GetBaseLevel(_octave_min, DATA_ROT);
206
        CLTexImage * key =  GetBaseLevel(_octave_min, DATA_KEYPOINT);
207
208
        ////////////there could be "out of memory" happening during the allocation
209
210
211
212
        for(i = 0; i< noct; i++)
213
        {
214
                for( j = 0; j< nlev; j++, gus++, dog++, grd++, rot++, key++)
215
                {
216
            gus->InitPackedTex(w, h, GlobalUtil::_usePackedTex);
217
                        if(j==0)continue;
218
                        dog->InitPackedTex(w, h, GlobalUtil::_usePackedTex);
219
            if(j < 1 + param._dog_level_num)
220
                        {
221
                            grd->InitPackedTex(w, h, GlobalUtil::_usePackedTex);
222
                            rot->InitPackedTex(w, h, GlobalUtil::_usePackedTex);
223
            }
224
                        if(j > 1 && j < nlev -1) key->InitPackedTex(w, h, GlobalUtil::_usePackedTex);
225
                }
226
        ////////////////////////////////////////
227
                int tsz = (gus -1)->GetTexPixelCount() * 16;
228
                totalkb += ((nlev *5 -6)* tsz / 1024);
229
                //several auxilary textures are not actually required
230
                w>>=1;
231
                h>>=1;
232
        }
233
234
        totalkb += ResizeFeatureStorage();
235
236
        _allocated = 1;
237
238
        if(GlobalUtil::_verbose && GlobalUtil::_timingS) std::cout<<"[Allocate Pyramid]:\t" <<(totalkb/1024)<<"MB\n";
239
240
}
241
242
void PyramidCL::FitPyramid(int w, int h)
243
{
244
        _pyramid_octave_first = 0;
245
        //
246
        _octave_num  = GlobalUtil::_octave_num_default;
247
248
        int _octave_num_max = GetRequiredOctaveNum(min(w, h));
249
250
        if(_octave_num < 1 || _octave_num > _octave_num_max) 
251
        {
252
                _octave_num = _octave_num_max;
253
        }
254
255
256
        int pw = _pyramid_width>>1, ph = _pyramid_height>>1;
257
        while(_pyramid_octave_first + _octave_num < _pyramid_octave_num &&  
258
                pw >= w && ph >= h)
259
        {
260
                _pyramid_octave_first++;
261
                pw >>= 1;
262
                ph >>= 1;
263
        }
264
265
        //////////////////
266
        for(int i = 0; i < _octave_num; i++)
267
        {
268
                CLTexImage * tex = GetBaseLevel(i + _octave_min);
269
                CLTexImage * dog = GetBaseLevel(i + _octave_min, DATA_DOG);
270
                CLTexImage * grd = GetBaseLevel(i + _octave_min, DATA_GRAD);
271
                CLTexImage * rot = GetBaseLevel(i + _octave_min, DATA_ROT);
272
                CLTexImage * key = GetBaseLevel(i + _octave_min, DATA_KEYPOINT);
273
                for(int j = param._level_min; j <= param._level_max; j++, tex++, dog++, grd++, rot++, key++)
274
                {
275
                        tex->SetPackedSize(w, h, GlobalUtil::_usePackedTex);
276
                        if(j == param._level_min) continue;
277
                        dog->SetPackedSize(w, h, GlobalUtil::_usePackedTex);
278
            if(j < param._level_max - 1)
279
            {
280
                            grd->SetPackedSize(w, h, GlobalUtil::_usePackedTex);
281
                            rot->SetPackedSize(w, h, GlobalUtil::_usePackedTex);
282
            }
283
                        if(j > param._level_min + 1 &&  j < param._level_max) key->SetPackedSize(w, h, GlobalUtil::_usePackedTex);
284
                }
285
                w>>=1;
286
                h>>=1;
287
        }
288
}
289
290
291
void PyramidCL::SetLevelFeatureNum(int idx, int fcount)
292
{
293
    _featureTex[idx].InitBufferTex(fcount, 1, 4);
294
        _levelFeatureNum[idx] = fcount;
295
}
296
297
int PyramidCL::ResizeFeatureStorage()
298
{
299
        int totalkb = 0;
300
        if(_levelFeatureNum==NULL)        _levelFeatureNum = new int[_octave_num * param._dog_level_num];
301
        std::fill(_levelFeatureNum, _levelFeatureNum+_octave_num * param._dog_level_num, 0); 
302
303
    cl_context       context  = _OpenCL->GetContextCL();
304
    cl_command_queue queue    = _OpenCL->GetCommandQueue();
305
        int wmax = GetBaseLevel(_octave_min)->GetImgWidth() * 2;
306
        int hmax = GetBaseLevel(_octave_min)->GetImgHeight() * 2;
307
        int whmax = max(wmax, hmax);
308
        int w,  i;
309
310
        //
311
        int num = (int)ceil(log(double(whmax))/log(4.0));
312
313
        if( _hpLevelNum != num)
314
        {
315
                _hpLevelNum = num;
316
                if(_histoPyramidTex ) delete [] _histoPyramidTex;
317
                _histoPyramidTex = new CLTexImage[_hpLevelNum];
318
        for(i = 0; i < _hpLevelNum; ++i) _histoPyramidTex[i].SetContext(context, queue);
319
        }
320
321
        for(i = 0, w = 1; i < _hpLevelNum; i++)
322
        {
323
        _histoPyramidTex[i].InitBufferTex(w, whmax, 4);
324
                w<<=2;
325
        }
326
327
        // (4 ^ (_hpLevelNum) -1 / 3) pixels
328
        totalkb += (((1 << (2 * _hpLevelNum)) -1) / 3 * 16 / 1024);
329
330
        //initialize the feature texture
331
        int idx = 0, n = _octave_num * param._dog_level_num;
332
        if(_featureTex==NULL)        
333
    {
334
        _featureTex = new CLTexImage[n];
335
        for(i = 0; i <n; ++i) _featureTex[i].SetContext(context, queue);
336
    }
337
        if(GlobalUtil::_MaxOrientation >1 && GlobalUtil::_OrientationPack2==0 && _orientationTex== NULL)        
338
    {
339
        _orientationTex = new CLTexImage[n];
340
        for(i = 0; i < n; ++i) _orientationTex[i].SetContext(context, queue);
341
    }
342
343
344
        for(i = 0; i < _octave_num; i++)
345
        {
346
                CLTexImage * tex = GetBaseLevel(i+_octave_min);
347
                int fmax = int(4 * tex->GetTexWidth() * tex->GetTexHeight()*GlobalUtil::_MaxFeaturePercent);
348
                //
349
                if(fmax > GlobalUtil::_MaxLevelFeatureNum) fmax = GlobalUtil::_MaxLevelFeatureNum;
350
                else if(fmax < 32) fmax = 32;        //give it at least a space of 32 feature
351
352
                for(int j = 0; j < param._dog_level_num; j++, idx++)
353
                {
354
                        _featureTex[idx].InitBufferTex(fmax, 1, 4);
355
                        totalkb += fmax * 16 /1024;
356
                        //
357
                        if(GlobalUtil::_MaxOrientation>1 && GlobalUtil::_OrientationPack2 == 0)
358
                        {
359
                                _orientationTex[idx].InitBufferTex(fmax, 1, 4);
360
                                totalkb += fmax * 16 /1024;
361
                        }
362
                }
363
        }
364
365
        //this just need be initialized once
366
        if(_descriptorTex==NULL)
367
        {
368
                //initialize feature texture pyramid
369
                int fmax = _featureTex->GetImgWidth();
370
                _descriptorTex = new CLTexImage(context, queue);
371
                totalkb += ( fmax /2);
372
                _descriptorTex->InitBufferTex(fmax *128, 1, 1);
373
        }else
374
        {
375
                totalkb +=  _descriptorTex->GetDataSize()/1024;
376
        }
377
        return totalkb;
378
}
379
380
void PyramidCL::GetFeatureDescriptors() 
381
{
382
        //descriptors...
383
        /*float* pd =  &_descriptor_buffer[0];
384
        vector<float> descriptor_buffer2;
385

386
        //use another buffer if we need to re-order the descriptors
387
        if(_keypoint_index.size() > 0)
388
        {
389
                descriptor_buffer2.resize(_descriptor_buffer.size());
390
                pd = &descriptor_buffer2[0];
391
        }
392

393
        CLTexImage * got, * ftex= _featureTex;
394
        for(int i = 0, idx = 0; i < _octave_num; i++)
395
        {
396
                got = GetBaseLevel(i + _octave_min, DATA_GRAD) + 1;
397
                for(int j = 0; j < param._dog_level_num; j++, ftex++, idx++, got++)
398
                {
399
                        if(_levelFeatureNum[idx]==0) continue;
400
                        ProgramCL::ComputeDescriptor(ftex, got, _descriptorTex);//process
401
                        _descriptorTex->CopyToHost(pd); //readback descriptor
402
                        pd += 128*_levelFeatureNum[idx];
403
                }
404
        }
405

406
        if(GlobalUtil::_timingS) _OpenCL->FinishCL();
407

408
        if(_keypoint_index.size() > 0)
409
        {
410
            //put the descriptor back to the original order for keypoint list.
411
                for(int i = 0; i < _featureNum; ++i)
412
                {
413
                        int index = _keypoint_index[i];
414
                        memcpy(&_descriptor_buffer[index*128], &descriptor_buffer2[i*128], 128 * sizeof(float));
415
                }
416
        }*/ 
417
}
418
419
void PyramidCL::GenerateFeatureListTex() 
420
{
421
422
        vector<float> list;
423
        int idx = 0;
424
        const double twopi = 2.0*3.14159265358979323846;
425
        float sigma_half_step = powf(2.0f, 0.5f / param._dog_level_num);
426
        float octave_sigma = _octave_min>=0? float(1<<_octave_min): 1.0f/(1<<(-_octave_min));
427
        float offset = GlobalUtil::_LoweOrigin? 0 : 0.5f; 
428
        if(_down_sample_factor>0) octave_sigma *= float(1<<_down_sample_factor); 
429
430
        _keypoint_index.resize(0); // should already be 0
431
        for(int i = 0; i < _octave_num; i++, octave_sigma*= 2.0f)
432
        {
433
                for(int j = 0; j < param._dog_level_num; j++, idx++)
434
                {
435
                        list.resize(0);
436
                        float level_sigma = param.GetLevelSigma(j + param._level_min + 1) * octave_sigma;
437
                        float sigma_min = level_sigma / sigma_half_step;
438
                        float sigma_max = level_sigma * sigma_half_step;
439
                        int fcount = 0 ;
440
                        for(int k = 0; k < _featureNum; k++)
441
                        {
442
                                float * key = &_keypoint_buffer[k*4];
443
                                if(   (key[2] >= sigma_min && key[2] < sigma_max)
444
                                        ||(key[2] < sigma_min && i ==0 && j == 0)
445
                                        ||(key[2] > sigma_max && i == _octave_num -1 && j == param._dog_level_num - 1))
446
                                {
447
                                        //add this keypoint to the list
448
                                        list.push_back((key[0] - offset) / octave_sigma + 0.5f);
449
                                        list.push_back((key[1] - offset) / octave_sigma + 0.5f);
450
                                        list.push_back(key[2] / octave_sigma);
451
                                        list.push_back((float)fmod(twopi-key[3], twopi));
452
                                        fcount ++;
453
                                        //save the index of keypoints
454
                                        _keypoint_index.push_back(k);
455
                                }
456
457
                        }
458
459
                        _levelFeatureNum[idx] = fcount;
460
                        if(fcount==0)continue;
461
                        CLTexImage * ftex = _featureTex+idx;
462
463
                        SetLevelFeatureNum(idx, fcount);
464
                        ftex->CopyFromHost(&list[0]);
465
                }
466
        }
467
468
        if(GlobalUtil::_verbose)
469
        {
470
                std::cout<<"#Features:\t"<<_featureNum<<"\n";
471
        }
472
473
}
474
475
void PyramidCL::ReshapeFeatureListCPU() 
476
{
477
        int i, szmax =0, sz;
478
        int n = param._dog_level_num*_octave_num;
479
        for( i = 0; i < n; i++) 
480
        {
481
                sz = _levelFeatureNum[i];
482
                if(sz > szmax ) szmax = sz;
483
        }
484
        float * buffer = new float[szmax*16];
485
        float * buffer1 = buffer;
486
        float * buffer2 = buffer + szmax*4;
487
488
489
490
        _featureNum = 0;
491
492
#ifdef NO_DUPLICATE_DOWNLOAD
493
        const double twopi = 2.0*3.14159265358979323846;
494
        _keypoint_buffer.resize(0);
495
        float os = _octave_min>=0? float(1<<_octave_min): 1.0f/(1<<(-_octave_min));
496
        if(_down_sample_factor>0) os *= float(1<<_down_sample_factor); 
497
        float offset = GlobalUtil::_LoweOrigin? 0 : 0.5f;
498
#endif
499
500
501
        for(i = 0; i < n; i++)
502
        {
503
                if(_levelFeatureNum[i]==0)continue;
504
505
                _featureTex[i].CopyToHost(buffer1);
506
                
507
                int fcount =0;
508
                float * src = buffer1;
509
                float * des = buffer2;
510
                const static double factor  = 2.0*3.14159265358979323846/65535.0;
511
                for(int j = 0; j < _levelFeatureNum[i]; j++, src+=4)
512
                {
513
                        unsigned short * orientations = (unsigned short*) (&src[3]);
514
                        if(orientations[0] != 65535)
515
                        {
516
                                des[0] = src[0];
517
                                des[1] = src[1];
518
                                des[2] = src[2];
519
                                des[3] = float( factor* orientations[0]);
520
                                fcount++;
521
                                des += 4;
522
                                if(orientations[1] != 65535 && orientations[1] != orientations[0])
523
                                {
524
                                        des[0] = src[0];
525
                                        des[1] = src[1];
526
                                        des[2] = src[2];
527
                                        des[3] = float(factor* orientations[1]);        
528
                                        fcount++;
529
                                        des += 4;
530
                                }
531
                        }
532
                }
533
                //texture size
534
                SetLevelFeatureNum(i, fcount);
535
                _featureTex[i].CopyFromHost(buffer2);
536
                
537
                if(fcount == 0) continue;
538
539
#ifdef NO_DUPLICATE_DOWNLOAD
540
                float oss = os * (1 << (i / param._dog_level_num));
541
                _keypoint_buffer.resize((_featureNum + fcount) * 4);
542
                float* ds = &_keypoint_buffer[_featureNum * 4];
543
                float* fs = buffer2;
544
                for(int k = 0;  k < fcount; k++, ds+=4, fs+=4)
545
                {
546
                        ds[0] = oss*(fs[0]-0.5f) + offset;        //x
547
                        ds[1] = oss*(fs[1]-0.5f) + offset;        //y
548
                        ds[2] = oss*fs[2];  //scale
549
                        ds[3] = (float)fmod(twopi-fs[3], twopi);        //orientation, mirrored
550
                }
551
#endif
552
                _featureNum += fcount;
553
        }
554
        delete[] buffer;
555
        if(GlobalUtil::_verbose)
556
        {
557
                std::cout<<"#Features MO:\t"<<_featureNum<<endl;
558
        }
559
}
560
561
void PyramidCL::GenerateFeatureDisplayVBO() 
562
{
563
        //it is weried that this part is very slow.
564
        //use a big VBO to save all the SIFT box vertices
565
        /*int nvbo = _octave_num * param._dog_level_num;
566
        if(_featureDisplayVBO==NULL)
567
        {
568
                //initialize the vbos
569
                _featureDisplayVBO = new GLuint[nvbo];
570
                _featurePointVBO = new GLuint[nvbo];
571
                glGenBuffers(nvbo, _featureDisplayVBO);        
572
                glGenBuffers(nvbo, _featurePointVBO);
573
        }
574
        for(int i = 0; i < nvbo; i++)
575
        {
576
                if(_levelFeatureNum[i]<=0)continue;
577
                CLTexImage * ftex  = _featureTex + i;
578
                CLTexImage texPBO1( _levelFeatureNum[i]* 10, 1, 4, _featureDisplayVBO[i]);
579
                CLTexImage texPBO2(_levelFeatureNum[i], 1, 4, _featurePointVBO[i]);
580
                _OpenCL->DisplayKeyBox(ftex, &texPBO1);
581
                _OpenCL->DisplayKeyPoint(ftex, &texPBO2);        
582
        }*/
583
}
584
585
void PyramidCL::DestroySharedData() 
586
{
587
        //histogram reduction
588
        if(_histoPyramidTex)
589
        {
590
                delete[]        _histoPyramidTex;
591
                _hpLevelNum = 0;
592
                _histoPyramidTex = NULL;
593
        }
594
        //descriptor storage shared by all levels
595
        if(_descriptorTex)
596
        {
597
                delete _descriptorTex;
598
                _descriptorTex = NULL;
599
        }
600
        //cpu reduction buffer.
601
        if(_histo_buffer)
602
        {
603
                delete[] _histo_buffer;
604
                _histo_buffer = 0;
605
        }
606
}
607
608
void PyramidCL::DestroyPerLevelData() 
609
{
610
        //integers vector to store the feature numbers.
611
        if(_levelFeatureNum)
612
        {
613
                delete [] _levelFeatureNum;
614
                _levelFeatureNum = NULL;
615
        }
616
        //texture used to store features
617
        if(        _featureTex)
618
        {
619
                delete [] _featureTex;
620
                _featureTex =        NULL;
621
        }
622
        //texture used for multi-orientation 
623
        if(_orientationTex)
624
        {
625
                delete [] _orientationTex;
626
                _orientationTex = NULL;
627
        }
628
        int no = _octave_num* param._dog_level_num;
629
630
        //two sets of vbos used to display the features
631
        if(_featureDisplayVBO)
632
        {
633
                glDeleteBuffers(no, _featureDisplayVBO);
634
                delete [] _featureDisplayVBO;
635
                _featureDisplayVBO = NULL;
636
        }
637
        if( _featurePointVBO)
638
        {
639
                glDeleteBuffers(no, _featurePointVBO);
640
                delete [] _featurePointVBO;
641
                _featurePointVBO = NULL;
642
        }
643
}
644
645
void PyramidCL::DestroyPyramidData()
646
{
647
        if(_allPyramid)
648
        {
649
                delete [] _allPyramid;
650
                _allPyramid = NULL;
651
        }
652
}
653
654
void PyramidCL::DownloadKeypoints() 
655
{
656
        const double twopi = 2.0*3.14159265358979323846;
657
        int idx = 0;
658
        float * buffer = &_keypoint_buffer[0];
659
        vector<float> keypoint_buffer2;
660
        //use a different keypoint buffer when processing with an exisint features list
661
        //without orientation information. 
662
        if(_keypoint_index.size() > 0)
663
        {
664
                keypoint_buffer2.resize(_keypoint_buffer.size());
665
                buffer = &keypoint_buffer2[0];
666
        }
667
        float * p = buffer, *ps;
668
        CLTexImage * ftex = _featureTex;
669
        /////////////////////
670
        float os = _octave_min>=0? float(1<<_octave_min): 1.0f/(1<<(-_octave_min));
671
        if(_down_sample_factor>0) os *= float(1<<_down_sample_factor); 
672
        float offset = GlobalUtil::_LoweOrigin? 0 : 0.5f;
673
        /////////////////////
674
        for(int i = 0; i < _octave_num; i++, os *= 2.0f)
675
        {
676
        
677
                for(int j = 0; j  < param._dog_level_num; j++, idx++, ftex++)
678
                {
679
680
                        if(_levelFeatureNum[idx]>0)
681
                        {        
682
                                ftex->CopyToHost(ps = p);
683
                                for(int k = 0;  k < _levelFeatureNum[idx]; k++, ps+=4)
684
                                {
685
                                        ps[0] = os*(ps[0]-0.5f) + offset;        //x
686
                                        ps[1] = os*(ps[1]-0.5f) + offset;        //y
687
                                        ps[2] = os*ps[2]; 
688
                                        ps[3] = (float)fmod(twopi-ps[3], twopi);        //orientation, mirrored
689
                                }
690
                                p+= 4* _levelFeatureNum[idx];
691
                        }
692
                }
693
        }
694
695
        //put the feature into their original order for existing keypoint 
696
        if(_keypoint_index.size() > 0)
697
        {
698
                for(int i = 0; i < _featureNum; ++i)
699
                {
700
                        int index = _keypoint_index[i];
701
                        memcpy(&_keypoint_buffer[index*4], &keypoint_buffer2[i*4], 4 * sizeof(float));
702
                }
703
        }
704
}
705
706
void PyramidCL::GenerateFeatureListCPU()
707
{
708
        //no cpu version provided
709
        GenerateFeatureList();
710
}
711
712
void PyramidCL::GenerateFeatureList(int i, int j, int reduction_count, vector<int>& hbuffer)
713
{
714
    /*int fcount = 0, idx = i * param._dog_level_num  + j;
715
        int hist_level_num = _hpLevelNum - _pyramid_octave_first /2; 
716
        int ii, k, len; 
717

718
        CLTexImage * htex, * ftex, * tex, *got;
719
        ftex = _featureTex + idx;
720
        htex = _histoPyramidTex + hist_level_num -1;
721
        tex = GetBaseLevel(_octave_min + i, DATA_KEYPOINT) + 2 + j;
722
        got = GetBaseLevel(_octave_min + i, DATA_GRAD) + 2 + j;
723

724
        _OpenCL->InitHistogram(tex, htex);
725

726
        for(k = 0; k < reduction_count - 1; k++, htex--)
727
        {
728
                ProgramCL::ReduceHistogram(htex, htex -1);        
729
        }
730
        
731
        //htex has the row reduction result
732
        len = htex->GetImgHeight() * 4;
733
        hbuffer.resize(len);
734
        _OpenCL->FinishCL();
735
        htex->CopyToHost(&hbuffer[0]);
736
        //
737
        for(ii = 0; ii < len; ++ii)                fcount += hbuffer[ii];
738
        SetLevelFeatureNum(idx, fcount);
739
        
740
    //build the feature list
741
        if(fcount > 0)
742
        {
743
                _featureNum += fcount;
744
                _keypoint_buffer.resize(fcount * 4);
745
                //vector<int> ikbuf(fcount*4);
746
                int* ibuf = (int*) (&_keypoint_buffer[0]);
747

748
                for(ii = 0; ii < len; ++ii)
749
                {
750
                        int x = ii%4, y = ii / 4;
751
                        for(int jj = 0 ; jj < hbuffer[ii]; ++jj, ibuf+=4)
752
                        {
753
                                ibuf[0] = x; ibuf[1] = y; ibuf[2] = jj; ibuf[3] = 0;
754
                        }
755
                }
756
                _featureTex[idx].CopyFromHost(&_keypoint_buffer[0]);
757
        
758
                ////////////////////////////////////////////
759
                ProgramCL::GenerateList(_featureTex + idx, ++htex);
760
                for(k = 2; k < reduction_count; k++)
761
                {
762
                        ProgramCL::GenerateList(_featureTex + idx, ++htex);
763
                }
764
        }*/
765
}
766
767
void PyramidCL::GenerateFeatureList()
768
{
769
        /*double t1, t2; 
770
        int ocount = 0, reduction_count;
771
    int reverse = (GlobalUtil::_TruncateMethod == 1);
772

773
        vector<int> hbuffer;
774
        _featureNum = 0;
775

776
        //for(int i = 0, idx = 0; i < _octave_num; i++)
777
    FOR_EACH_OCTAVE(i, reverse)
778
        {
779
        CLTexImage* tex = GetBaseLevel(_octave_min + i, DATA_KEYPOINT) + 2;
780
                reduction_count = FitHistogramPyramid(tex);
781

782
                if(GlobalUtil::_timingO)
783
                {
784
                        t1 = CLOCK(); 
785
                        ocount = 0;
786
                        std::cout<<"#"<<i+_octave_min + _down_sample_factor<<":\t";
787
                }
788
                //for(int j = 0; j < param._dog_level_num; j++, idx++)
789
        FOR_EACH_LEVEL(j, reverse)
790
                {
791
            if(GlobalUtil::_TruncateMethod && GlobalUtil::_FeatureCountThreshold > 0 && _featureNum > GlobalUtil::_FeatureCountThreshold) continue;
792

793
                GenerateFeatureList(i, j, reduction_count, hbuffer);
794

795
                        /////////////////////////////
796
                        if(GlobalUtil::_timingO)
797
                        {
798
                int idx = i * param._dog_level_num + j;
799
                                ocount += _levelFeatureNum[idx];
800
                                std::cout<< _levelFeatureNum[idx] <<"\t";
801
                        }
802
                }
803
                if(GlobalUtil::_timingO)
804
                {        
805
                        t2 = CLOCK(); 
806
                        std::cout << "| \t" << int(ocount) << " :\t(" << (t2 - t1) << ")\n";
807
                }
808
        }
809
        /////
810
        CopyGradientTex();
811
        /////
812
        if(GlobalUtil::_timingS)_OpenCL->FinishCL();
813

814
        if(GlobalUtil::_verbose)
815
        {
816
                std::cout<<"#Features:\t"<<_featureNum<<"\n";
817
        }*/
818
}
819
820
GLTexImage* PyramidCL::GetLevelTexture(int octave, int level)
821
{
822
        return GetLevelTexture(octave, level, DATA_GAUSSIAN);
823
}
824
825
GLTexImage* PyramidCL::ConvertTexCL2GL(CLTexImage* tex, int dataName)
826
{
827
   
828
    if(_bufferTEX == NULL) _bufferTEX = new GLTexImage;
829
830
    ///////////////////////////////////////////
831
    int ratio = GlobalUtil::_usePackedTex ? 2 : 1; 
832
    int width  = tex->GetImgWidth() * ratio;
833
    int height = tex->GetImgHeight() * ratio; 
834
    int tw = max(width,  _bufferTEX->GetTexWidth());
835
    int th = max(height, _bufferTEX->GetTexHeight());
836
    _bufferTEX->InitTexture(tw, th, 1, GL_RGBA);
837
    _bufferTEX->SetImageSize(width, height); 
838
839
    //////////////////////////////////
840
    CLTexImage texCL(_OpenCL->GetContextCL(), _OpenCL->GetCommandQueue()); 
841
    texCL.InitTextureGL(*_bufferTEX, width, height, 4); 
842
843
        switch(dataName)
844
        {
845
        case DATA_GAUSSIAN: _OpenCL->UnpackImage(tex, &texCL); break;
846
        case DATA_DOG:_OpenCL->UnpackImageDOG(tex, &texCL); break;
847
        case DATA_GRAD:_OpenCL->UnpackImageGRD(tex, &texCL); break;
848
        case DATA_KEYPOINT:_OpenCL->UnpackImageKEY(tex,
849
        tex - param._level_num * _pyramid_octave_num, &texCL);break;
850
        default:
851
                        break;
852
        }
853
854
855
        return _bufferTEX;
856
}
857
858
GLTexImage* PyramidCL::GetLevelTexture(int octave, int level, int dataName) 
859
{
860
        CLTexImage* tex = GetBaseLevel(octave, dataName) + (level - param._level_min);
861
        return ConvertTexCL2GL(tex, dataName);
862
}
863
864
void PyramidCL::ConvertInputToCL(GLTexInput* input, CLTexImage* output)
865
{
866
        int ws = input->GetImgWidth(), hs = input->GetImgHeight();
867
        //copy the input image to pixel buffer object
868
    if(input->_pixel_data)
869
    {
870
        output->InitTexture(ws, hs, 1);
871
        output->CopyFromHost(input->_pixel_data); 
872
    }else /*if(input->_rgb_converted && input->CopyToPBO(_bufferPBO, ws, hs, GL_LUMINANCE))
873
    {
874
                output->InitTexture(ws, hs, 1);
875
        output->CopyFromPBO(ws, hs, _bufferPBO); 
876
    }else if(input->CopyToPBO(_bufferPBO, ws, hs))
877
        {
878
                CLTexImage texPBO(ws, hs, 4, _bufferPBO);
879
                output->InitTexture(ws, hs, 1);
880
                ProgramCL::ReduceToSingleChannel(output, &texPBO, !input->_rgb_converted);
881
        }else*/
882
        {
883
                std::cerr<< "Unable To Convert Intput\n";
884
        }
885
}
886
887
void PyramidCL::BuildPyramid(GLTexInput * input)
888
{
889
890
        USE_TIMING();
891
892
        int i, j;
893
        
894
        for ( i = _octave_min; i < _octave_min + _octave_num; i++)
895
        {
896
897
                CLTexImage *tex = GetBaseLevel(i);
898
                CLTexImage *buf = GetBaseLevel(i, DATA_DOG) +2;
899
        FilterCL ** filter  = _OpenCL->f_gaussian_step; 
900
                j = param._level_min + 1;
901
902
                OCTAVE_START();
903
904
                if( i == _octave_min )
905
                {        
906
            if(GlobalUtil::_usePackedTex)
907
            {
908
                            ConvertInputToCL(input, _inputTex);
909
                            if(i < 0)        _OpenCL->SampleImageU(tex, _inputTex, -i- 1);                        
910
                            else                _OpenCL->SampleImageD(tex, _inputTex, i + 1);
911
            }else
912
            {
913
                if(i == 0) ConvertInputToCL(input, tex);
914
                else
915
                {
916
                    ConvertInputToCL(input, _inputTex);
917
                    if(i < 0) _OpenCL->SampleImageU(tex, _inputTex, -i);
918
                    else      _OpenCL->SampleImageD(tex, _inputTex,  i);
919
                }
920
            }
921
            _OpenCL->FilterInitialImage(tex, buf);   
922
                }else
923
                {
924
                        _OpenCL->SampleImageD(tex, GetBaseLevel(i - 1) + param._level_ds - param._level_min); 
925
            _OpenCL->FilterSampledImage(tex, buf);
926
                }
927
                LEVEL_FINISH();
928
                for( ; j <=  param._level_max ; j++, tex++, filter++)
929
                {
930
                        // filtering
931
                        _OpenCL->FilterImage(*filter, tex + 1, tex, buf);
932
                        LEVEL_FINISH();
933
                }
934
                OCTAVE_FINISH();
935
        }
936
        if(GlobalUtil::_timingS) _OpenCL->FinishCL();
937
}
938
939
void PyramidCL::DetectKeypointsEX()
940
{
941
        int i, j;
942
        double t0, t, ts, t1, t2;
943
    
944
        if(GlobalUtil::_timingS && GlobalUtil::_verbose) ts = CLOCK();
945
946
        for(i = _octave_min; i < _octave_min + _octave_num; i++)
947
        {
948
                CLTexImage * gus = GetBaseLevel(i) + 1;
949
                CLTexImage * dog = GetBaseLevel(i, DATA_DOG) + 1;
950
                CLTexImage * grd = GetBaseLevel(i, DATA_GRAD) + 1;
951
        CLTexImage * rot = GetBaseLevel(i, DATA_ROT) + 1;
952
                //compute the gradient
953
                for(j = param._level_min +1; j <=  param._level_max ; j++, gus++, dog++, grd++, rot++)
954
                {
955
                        //input: gus and gus -1
956
                        //output: gradient, dog, orientation
957
                        _OpenCL->ComputeDOG(gus, gus - 1, dog, grd, rot);
958
                }
959
        }
960
        if(GlobalUtil::_timingS && GlobalUtil::_verbose)
961
        {
962
                _OpenCL->FinishCL();
963
                t1 = CLOCK();
964
        }
965
    //if(GlobalUtil::_timingS) _OpenCL->FinishCL();
966
    //if(!GlobalUtil::_usePackedTex) return; //not finished
967
    //return; 
968
969
        for ( i = _octave_min; i < _octave_min + _octave_num; i++)
970
        {
971
                if(GlobalUtil::_timingO)
972
                {
973
                        t0 = CLOCK();
974
                        std::cout<<"#"<<(i + _down_sample_factor)<<"\t";
975
                }
976
                CLTexImage * dog = GetBaseLevel(i, DATA_DOG) + 2;
977
                CLTexImage * key = GetBaseLevel(i, DATA_KEYPOINT) +2;
978
979
980
                for( j = param._level_min +2; j <  param._level_max ; j++, dog++, key++)
981
                {
982
                        if(GlobalUtil::_timingL)t = CLOCK();
983
                        //input, dog, dog + 1, dog -1
984
                        //output, key
985
                        _OpenCL->ComputeKEY(dog, key, param._dog_threshold, param._edge_threshold);
986
                        if(GlobalUtil::_timingL)
987
                        {
988
                                std::cout<<(CLOCK()-t)<<"\t";
989
                        }
990
                }
991
                if(GlobalUtil::_timingO)
992
                {
993
                        std::cout<<"|\t"<<(CLOCK()-t0)<<"\n";
994
                }
995
        }
996
997
        if(GlobalUtil::_timingS)
998
        {
999
                _OpenCL->FinishCL();
1000
                if(GlobalUtil::_verbose) 
1001
                {        
1002
                        t2 = CLOCK();
1003
                        std::cout        <<"<Gradient, DOG  >\t"<<(t1-ts)<<"\n"
1004
                                                <<"<Get Keypoints  >\t"<<(t2-t1)<<"\n";
1005
                }                                
1006
        }
1007
}
1008
1009
void PyramidCL::CopyGradientTex()
1010
{
1011
        /*double ts, t1;
1012

1013
        if(GlobalUtil::_timingS && GlobalUtil::_verbose)ts = CLOCK();
1014

1015
        for(int i = 0, idx = 0; i < _octave_num; i++)
1016
        {
1017
                CLTexImage * got = GetBaseLevel(i + _octave_min, DATA_GRAD) +  1;
1018
                //compute the gradient
1019
                for(int j = 0; j <  param._dog_level_num ; j++, got++, idx++)
1020
                {
1021
                        if(_levelFeatureNum[idx] > 0)        got->CopyToTexture2D();
1022
                }
1023
        }
1024
        if(GlobalUtil::_timingS)
1025
        {
1026
                ProgramCL::FinishCLDA();
1027
                if(GlobalUtil::_verbose)
1028
                {
1029
                        t1 = CLOCK();
1030
                        std::cout        <<"<Copy Grad/Orientation>\t"<<(t1-ts)<<"\n";
1031
                }
1032
        }*/
1033
}
1034
1035
void PyramidCL::ComputeGradient() 
1036
{
1037
1038
        /*int i, j;
1039
        double ts, t1;
1040

1041
        if(GlobalUtil::_timingS && GlobalUtil::_verbose)ts = CLOCK();
1042

1043
        for(i = _octave_min; i < _octave_min + _octave_num; i++)
1044
        {
1045
                CLTexImage * gus = GetBaseLevel(i) +  1;
1046
                CLTexImage * dog = GetBaseLevel(i, DATA_DOG) +  1;
1047
                CLTexImage * got = GetBaseLevel(i, DATA_GRAD) +  1;
1048

1049
                //compute the gradient
1050
                for(j = 0; j <  param._dog_level_num ; j++, gus++, dog++, got++)
1051
                {
1052
                        ProgramCL::ComputeDOG(gus, dog, got);
1053
                }
1054
        }
1055
        if(GlobalUtil::_timingS)
1056
        {
1057
                ProgramCL::FinishCLDA();
1058
                if(GlobalUtil::_verbose)
1059
                {
1060
                        t1 = CLOCK();
1061
                        std::cout        <<"<Gradient, DOG  >\t"<<(t1-ts)<<"\n";
1062
                }
1063
        }*/
1064
}
1065
1066
int PyramidCL::FitHistogramPyramid(CLTexImage* tex)
1067
{
1068
        CLTexImage *htex;
1069
        int hist_level_num = _hpLevelNum - _pyramid_octave_first / 2; 
1070
        htex = _histoPyramidTex + hist_level_num - 1;
1071
        int w = (tex->GetImgWidth() + 2) >> 2;
1072
        int h = tex->GetImgHeight();
1073
        int count = 0; 
1074
        for(int k = 0; k < hist_level_num; k++, htex--)
1075
        {
1076
                //htex->SetImageSize(w, h);        
1077
                htex->InitTexture(w, h, 4); 
1078
                ++count;
1079
                if(w == 1)
1080
            break;
1081
                w = (w + 3)>>2; 
1082
        }
1083
        return count;
1084
}
1085
1086
void PyramidCL::GetFeatureOrientations() 
1087
{
1088
1089
/*
1090
        CLTexImage * ftex = _featureTex;
1091
        int * count         = _levelFeatureNum;
1092
        float sigma, sigma_step = powf(2.0f, 1.0f/param._dog_level_num);
1093

1094
        for(int i = 0; i < _octave_num; i++)
1095
        {
1096
                CLTexImage* got = GetBaseLevel(i + _octave_min, DATA_GRAD) + 1;
1097
                CLTexImage* key = GetBaseLevel(i + _octave_min, DATA_KEYPOINT) + 2;
1098

1099
                for(int j = 0; j < param._dog_level_num; j++, ftex++, count++, got++, key++)
1100
                {
1101
                        if(*count<=0)continue;
1102

1103
                        //if(ftex->GetImgWidth() < *count) ftex->InitTexture(*count, 1, 4);
1104

1105
                        sigma = param.GetLevelSigma(j+param._level_min+1);
1106

1107
                        ProgramCL::ComputeOrientation(ftex, got, key, sigma, sigma_step, _existing_keypoints);                
1108
                }
1109
        }
1110

1111
        if(GlobalUtil::_timingS)ProgramCL::FinishCL();
1112
        */
1113
1114
1115
}
1116
1117
void PyramidCL::GetSimplifiedOrientation() 
1118
{
1119
        //no simplified orientation
1120
        GetFeatureOrientations();
1121
}
1122
1123
CLTexImage* PyramidCL::GetBaseLevel(int octave, int dataName)
1124
{
1125
        if(octave <_octave_min || octave > _octave_min + _octave_num) return NULL;
1126
        int offset = (_pyramid_octave_first + octave - _octave_min) * param._level_num;
1127
        int num = param._level_num * _pyramid_octave_num;
1128
        return _allPyramid + num * dataName + offset;
1129
}
1130
1131
#endif