Project

General

Profile

Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (38.3 KB)

1
////////////////////////////////////////////////////////////////////////////
2
//        File:                SiftGPU.cpp
3
//        Author:                Changchang Wu
4
//        Description :        Implementation of the SIFTGPU classes.
5
//                                        SiftGPU:        The SiftGPU Tool.  
6
//                                        SiftGPUEX:        SiftGPU + viewer
7
//                                        SiftParam:        Sift Parameters
8
//
9
//        Copyright (c) 2007 University of North Carolina at Chapel Hill
10
//        All Rights Reserved
11
//
12
//        Permission to use, copy, modify and distribute this software and its
13
//        documentation for educational, research and non-profit purposes, without
14
//        fee, and without a written agreement is hereby granted, provided that the
15
//        above copyright notice and the following paragraph appear in all copies.
16
//        
17
//        The University of North Carolina at Chapel Hill make no representations
18
//        about the suitability of this software for any purpose. It is provided
19
//        'as is' without express or implied warranty. 
20
//
21
//        Please send BUG REPORTS to ccwu@cs.unc.edu
22
//
23
////////////////////////////////////////////////////////////////////////////
24

    
25
#include "GL/glew.h"
26
#include <iostream>
27
#include <fstream>
28
#include <string>
29
#include <iomanip>
30
#include <vector>
31
#include <algorithm>
32
#include <math.h>
33

    
34
#include <time.h>
35
using namespace std;
36

    
37

    
38
#include "GlobalUtil.h"
39
#include "SiftGPU.h"
40
#include "GLTexImage.h"
41
#include "ShaderMan.h"
42
#include "FrameBufferObject.h"
43
#include "SiftPyramid.h"
44
#include "PyramidGL.h"
45

    
46
//CUDA works only with vc8 or higher
47
#if defined(CUDA_SIFTGPU_ENABLED)
48
#include "PyramidCU.h"
49
#endif
50

    
51
#if defined(CL_SIFTGPU_ENABLED)
52
#include "PyramidCL.h"
53
#endif
54

    
55

    
56
////
57
#if  defined(_WIN32) 
58
        #include "direct.h"
59
        #pragma warning (disable : 4786) 
60
        #pragma warning (disable : 4996) 
61
#else
62
        //compatible with linux
63
        #define _stricmp strcasecmp
64
    #include <stdlib.h>
65
    #include <string.h>
66
#endif
67

    
68
#if !defined(_MAX_PATH)
69
        #if defined (PATH_MAX)
70
                #define _MAX_PATH PATH_MAX
71
        #else
72
                #define _MAX_PATH 512
73
        #endif
74
#endif
75

    
76
//////////////////////////////////////////////////////////////////////
77
//////////////////////////////////////////////////////////////////////
78
//
79
//just want to make this class invisible
80
class ImageList:public std::vector<std::string> {};
81

    
82
SiftGPU::SiftGPU(int np)
83
{ 
84
        _texImage = new GLTexInput;
85
        _imgpath =  new char[_MAX_PATH];
86
        _outpath = new char[_MAX_PATH];
87
    _imgpath[0] = _outpath[0] = 0;
88
        _initialized = 0;
89
        _image_loaded = 0;
90
        _current = 0;
91
        _list = new ImageList();
92
        _pyramid = NULL;
93
}
94

    
95

    
96

    
97
SiftGPUEX::SiftGPUEX() 
98
{
99
        _view = _sub_view = 0;
100
        _view_debug = 0;
101
        GlobalUtil::_UseSiftGPUEX = 1;
102
        srand((unsigned int)time(NULL));
103
        RandomizeColor();
104
}
105

    
106
void* SiftGPU::operator new (size_t  size){
107
  void * p = malloc(size);
108
  if (p == 0)  
109
  {
110
          const std::bad_alloc ba;
111
          throw ba; 
112
  }
113
  return p; 
114
}
115

    
116

    
117
void SiftGPUEX::RandomizeColor()
118
{
119
        float hsv[3] = {0, 0.8f, 1.0f};
120
        for(int i = 0; i < COLOR_NUM*3; i+=3)
121
        {
122
                hsv[0] = (rand()%100)*0.01f; //i/float(COLOR_NUM);
123
                HSVtoRGB(hsv, _colors+i);                
124
        }
125
}
126

    
127
SiftGPU::~SiftGPU()
128
{
129
        if(_pyramid) delete _pyramid; 
130
        delete _texImage;
131
        delete _list;
132
    delete[] _imgpath;
133
    delete[] _outpath;
134
}
135

    
136

    
137
inline void SiftGPU::InitSiftGPU()
138
{
139
        if(_initialized || GlobalUtil::_GoodOpenGL ==0) return;
140

    
141
        //Parse sift parameters
142
        ParseSiftParam();
143

    
144
#if !defined(CUDA_SIFTGPU_ENABLED)
145
        if(GlobalUtil::_UseCUDA)
146
        {
147
                GlobalUtil::_UseCUDA = 0;
148
                std::cerr        << "---------------------------------------------------------------------------\n"
149
                                        << "CUDA not supported in this binary! To enable it, please use SiftGPU_CUDA_Enable\n" 
150
                                        << "solution for VS2005+ or set siftgpu_enable_cuda to 1 in makefile\n"
151
                                        << "----------------------------------------------------------------------------\n";
152
        }
153
#else
154
        if(GlobalUtil::_UseCUDA == 0  && GlobalUtil::_UseOpenCL == 0) 
155
        {
156
                GlobalUtil::InitGLParam(0);
157
        }
158
    if(GlobalUtil::_GoodOpenGL == 0)
159
    {
160
        GlobalUtil::_UseCUDA = 1;
161
        std::cerr << "Switch from OpenGL to CUDA\n";
162
    }
163

    
164
    if(GlobalUtil::_UseCUDA && !PyramidCU::CheckCudaDevice(GlobalUtil::_DeviceIndex))
165
    {
166
        std::cerr << "Switch from CUDA to OpenGL\n"; 
167
        GlobalUtil::_UseCUDA = 0;
168
    }
169
#endif
170

    
171
        if(GlobalUtil::_verbose)        std::cout   <<"\n[SiftGPU Language]:\t" 
172
                                            << (GlobalUtil::_UseCUDA? "CUDA" : 
173
                                            (GlobalUtil::_UseOpenCL? "OpenCL" : "GLSL")) <<"\n";
174

    
175
#if defined(CUDA_SIFTGPU_ENABLED)
176
        if(GlobalUtil::_UseCUDA)
177
                _pyramid = new PyramidCU(*this);
178
        else 
179
#endif
180
#if defined(CL_SIFTGPU_ENABLED)
181
    if(GlobalUtil::_UseOpenCL)
182
        _pyramid = new PyramidCL(*this);
183
    else 
184
#endif
185

    
186
    if(GlobalUtil::_usePackedTex) {
187
                _pyramid = new PyramidPacked(*this);
188
    }
189
        else
190
                _pyramid = new PyramidNaive(*this);
191

    
192
        if(GlobalUtil::_GoodOpenGL && GlobalUtil::_InitPyramidWidth > 0 && GlobalUtil::_InitPyramidHeight > 0)
193
        {
194
                GlobalUtil::StartTimer("Initialize Pyramids");
195
                _pyramid->InitPyramid(GlobalUtil::_InitPyramidWidth, GlobalUtil::_InitPyramidHeight, 0);
196
                GlobalUtil::StopTimer();
197
        }
198

    
199
        ClockTimer::InitHighResolution();
200
        _initialized = 1;
201
}
202

    
203
int         SiftGPU::RunSIFT(int index)
204
{
205
        if(_list->size()>0 )
206
        {
207
                index = index % _list->size();
208
                if(strcmp(_imgpath, _list->at(index).data()))
209
                {
210
                        strcpy(_imgpath, _list->at(index).data());
211
                        _image_loaded = 0;
212
                        _current = index;
213
                }
214
                return RunSIFT();
215
        }else
216
        {
217
                return 0;
218
        }
219

    
220
}
221

    
222
int  SiftGPU::RunSIFT( int width,  int height, const void * data, unsigned int gl_format, unsigned int gl_type)
223
{
224
        //makes opengl context active
225
        //GlobalUtil::CreateWindowEZ();
226

    
227
        if(GlobalUtil::_GoodOpenGL ==0 ) return 0;
228
        if(!_initialized) {
229
                InitSiftGPU();
230
        }
231
        else {
232
                GlobalUtil::SetGLParam();
233
        }
234
        if(GlobalUtil::_GoodOpenGL ==0 ) return 0;
235
        if(width > 0 && height >0 && data != NULL)
236
        {
237
                _imgpath[0] = 0;
238
                //try downsample the image on CPU
239
                GlobalUtil::StartTimer("Upload Image data");
240
                if(_texImage->SetImageData(width, height, data, gl_format, gl_type))
241
                {
242
                        _image_loaded = 2; //gldata;
243
                        GlobalUtil::StopTimer();
244
                        _timing[0] = GlobalUtil::GetElapsedTime();
245
                        
246
                        //if the size of image is different, the pyramid need to be reallocated.
247
                        GlobalUtil::StartTimer("Initialize Pyramid");
248
                        _pyramid->InitPyramid(width, height, _texImage->_down_sampled);
249
                        GlobalUtil::StopTimer();
250
                        _timing[1] = GlobalUtil::GetElapsedTime();
251

    
252
                        return RunSIFT();
253
                }else
254
                {
255
                        return 0;
256
                }
257
        }else
258
        {
259
                return 0;
260
        }
261

    
262
}
263

    
264
int  SiftGPU::RunSIFT(const char * imgpath)
265
{
266
        if(imgpath && imgpath[0])
267
        {
268
                //set the new image
269
                strcpy(_imgpath, imgpath);
270
                _image_loaded = 0;
271
                return RunSIFT();
272
        }else
273
        {
274
                return 0;
275
        }
276

    
277

    
278
}
279

    
280
int SiftGPU::RunSIFT(int num, const SiftKeypoint * keys, int keys_have_orientation)
281
{
282
        if(num <=0) return 0;
283
        _pyramid->SetKeypointList(num, (const float*) keys, 1, keys_have_orientation);
284
        return RunSIFT();
285
}
286

    
287
int SiftGPU::RunSIFT()
288
{
289
        //check image data
290
        if(_imgpath[0]==0 && _image_loaded == 0) return 0;
291

    
292
        //check OpenGL support
293
        if(GlobalUtil::_GoodOpenGL ==0 ) return 0;
294

    
295
        ClockTimer timer;
296

    
297
        if(!_initialized)
298
        {
299
            //initialize SIFT GPU for once
300
                InitSiftGPU();
301
                if(GlobalUtil::_GoodOpenGL ==0 ) return 0;
302
        }else
303
        {
304
                //in case some OpenGL parameters are changed by users
305
                GlobalUtil::SetGLParam();
306
        }
307

    
308
        timer.StartTimer("RUN SIFT");
309
        //process input image file
310
        if( _image_loaded ==0)
311
        {
312
                int width, height; 
313
                //load and try down-sample on cpu
314
                GlobalUtil::StartTimer("Load Input Image");
315
                if(!_texImage->LoadImageFile(_imgpath, width, height)) return 0;
316
                _image_loaded = 1;
317
                GlobalUtil::StopTimer();
318
                _timing[0] = GlobalUtil::GetElapsedTime();
319

    
320
                //make sure the pyrmid can hold the new image.
321
                GlobalUtil::StartTimer("Initialize Pyramid");
322
                _pyramid->InitPyramid(width, height, _texImage->_down_sampled);
323
                GlobalUtil::StopTimer();
324
                _timing[1] = GlobalUtil::GetElapsedTime();
325

    
326
        }else
327
        {
328
                //change some global states
329
        if(!GlobalUtil::_UseCUDA && !GlobalUtil::_UseOpenCL)
330
                {
331
                        GlobalUtil::FitViewPort(1,1);
332
                        _texImage->FitTexViewPort();
333
                }
334
                if(_image_loaded == 1)
335
                {
336
                        _timing[0] = _timing[1] = 0;
337
                }else
338
                {//2
339
                        _image_loaded = 1; 
340
                }
341
        }
342

    
343
        if(_pyramid->_allocated ==0 ) return 0;
344

    
345

    
346
#ifdef DEBUG_SIFTGPU
347
        _pyramid->BeginDEBUG(_imgpath);
348
#endif
349

    
350
        //process the image
351
        _pyramid->RunSIFT(_texImage);
352

    
353
    //read back the timing
354
        _pyramid->GetPyramidTiming(_timing + 2);
355

    
356
        //write output once if there is only one input
357
        if(_outpath[0] ){   SaveSIFT(_outpath);        _outpath[0] = 0;}
358
        
359
        //terminate the process when -exit is provided. 
360
        if(GlobalUtil::_ExitAfterSIFT && GlobalUtil::_UseSiftGPUEX) exit(0); 
361

    
362
        timer.StopTimer();
363
        if(GlobalUtil::_verbose)std::cout<<endl;
364

    
365
    return _pyramid->GetSucessStatus();
366
}
367

    
368

    
369
void SiftGPU::SetKeypointList(int num, const SiftKeypoint * keys, int keys_have_orientation)
370
{
371
        _pyramid->SetKeypointList(num, (const float*)keys, 0, keys_have_orientation);
372
}
373

    
374
void SiftGPUEX::DisplayInput() 
375
{
376
        if(_texImage==NULL) return;
377
    _texImage->VerifyTexture();
378
        _texImage->BindTex();
379
        _texImage->DrawImage();
380
        _texImage->UnbindTex();
381

    
382
}
383

    
384
void SiftGPU::SetVerbose(int verbose)
385
{
386
        GlobalUtil::_timingO = verbose>2;
387
        GlobalUtil::_timingL = verbose>3;
388
        if(verbose == -1)
389
        {
390
                //Loop between verbose level 0, 1, 2
391
                if(GlobalUtil::_verbose)
392
                {
393
                        GlobalUtil::_verbose  = GlobalUtil::_timingS;
394
                        GlobalUtil::_timingS = 0;
395
                        if(GlobalUtil::_verbose ==0 && GlobalUtil::_UseSiftGPUEX)
396
                                std::cout << "Console ouput disabled, press Q/V to enable\n\n";
397
                }else
398
                {
399
                        GlobalUtil::_verbose = 1;
400
                        GlobalUtil::_timingS = 1;
401
                }
402
        }else if(verbose == -2)
403
        {
404
                //trick for disabling all output (still keeps the timing level)
405
                GlobalUtil::_verbose = 0;
406
                GlobalUtil::_timingS = 1;
407
        }else 
408
        {
409
                GlobalUtil::_verbose = verbose>0;
410
                GlobalUtil::_timingS = verbose>1;
411
        }
412
}
413

    
414
SiftParam::SiftParam()
415
{
416

    
417
        _level_min = -1;
418
        _dog_level_num  = 3;
419
        _level_max = 0;
420
        _sigma0 = 0;
421
        _sigman = 0;
422
        _edge_threshold = 0;
423
        _dog_threshold =  0;
424

    
425

    
426
}
427

    
428
float SiftParam::GetInitialSmoothSigma(int octave_min)
429
{
430
        float        sa = _sigma0 * powf(2.0f, float(_level_min)/float(_dog_level_num)) ; 
431
        float   sb = _sigman / powf(2.0f,  float(octave_min)) ;//
432
        float   sigma_skip0 = sa > sb + 0.001?sqrt(sa*sa - sb*sb): 0.0f;
433
        return  sigma_skip0; 
434
}
435

    
436
void SiftParam::ParseSiftParam()
437
{ 
438

    
439
        if(_dog_level_num ==0) _dog_level_num = 3;
440
        if(_level_max ==0) _level_max = _dog_level_num + 1;
441
        if(_sigma0 ==0.0f) _sigma0 = 1.6f * powf(2.0f, 1.0f / _dog_level_num) ;
442
        if(_sigman == 0.0f) _sigman = 0.5f;
443

    
444

    
445
        _level_num = _level_max -_level_min + 1;
446

    
447
        _level_ds  = _level_min + _dog_level_num;
448
        if(_level_ds > _level_max ) _level_ds = _level_max ;
449

    
450
        ///
451
        float _sigmak = powf(2.0f, 1.0f / _dog_level_num) ;
452
        float dsigma0 = _sigma0 * sqrt (1.0f - 1.0f / (_sigmak*_sigmak) ) ;
453
        float sa, sb;
454

    
455
 
456
        sa = _sigma0 * powf(_sigmak, (float)_level_min) ; 
457
        sb = _sigman / powf(2.0f,   (float)GlobalUtil::_octave_min_default) ;//
458

    
459
        _sigma_skip0 = sa>sb+ 0.001?sqrt(sa*sa - sb*sb): 0.0f;
460

    
461
    sa = _sigma0 * powf(_sigmak, float(_level_min )) ;
462
    sb = _sigma0 * powf(_sigmak, float(_level_ds - _dog_level_num)) ;
463

    
464
        _sigma_skip1 = sa>sb + 0.001? sqrt(sa*sa - sb*sb): 0.0f;
465

    
466
        _sigma_num = _level_max - _level_min;
467
        _sigma = new float[_sigma_num];
468

    
469
        for(int i = _level_min + 1; i <= _level_max; i++)
470
        {
471
                _sigma[i-_level_min -1] =  dsigma0 * powf(_sigmak, float(i)) ;
472
        }
473

    
474
        if(_dog_threshold ==0)        _dog_threshold      = 0.02f / _dog_level_num ;
475
        if(_edge_threshold==0) _edge_threshold                = 10.0f;
476
}
477

    
478

    
479
void SiftGPUEX::DisplayOctave(void (*UseDisplayShader)(), int i)
480
{
481
        if(_pyramid == NULL)return;
482
        const int grid_sz = (int)ceil(_level_num/2.0);
483
        double scale = 1.0/grid_sz ;
484
        int gx=0, gy=0, dx, dy;
485

    
486
        if(_pyramid->_octave_min >0) scale *= (1<<_pyramid->_octave_min);
487
        else if(_pyramid->_octave_min < 0) scale /= (1<<(-_pyramid->_octave_min));
488

    
489

    
490
        i = i% _pyramid->_octave_num;  //
491
        if(i<0 ) i+= _pyramid->_octave_num;
492

    
493
        scale *= ( 1<<(i));
494

    
495

    
496

    
497

    
498
        UseDisplayShader();
499

    
500
        glPushMatrix();
501
        glScaled(scale, scale, scale);
502
        for(int level = _level_min; level<= _level_max; level++)
503
        {
504
                GLTexImage * tex = _pyramid->GetLevelTexture(i+_pyramid->_octave_min, level);
505
                dx = tex->GetImgWidth();
506
                dy = tex->GetImgHeight();
507

    
508
                glPushMatrix();
509

    
510
                glTranslated(dx*gx, dy*gy, 0);
511

    
512
                tex->BindTex();
513

    
514
                tex->DrawImage();
515
                tex->UnbindTex();
516

    
517
                glPopMatrix();
518

    
519
                gx++;
520
                if(gx>=grid_sz) 
521
                {
522
                        gx =0;
523
                        gy++;
524
                }
525

    
526
        }
527

    
528
        glPopMatrix();
529
        ShaderMan::UnloadProgram();
530
}
531

    
532
void SiftGPUEX::DisplayPyramid( void (*UseDisplayShader)(), int dataName, int nskip1, int nskip2)
533
{
534

    
535
        if(_pyramid == NULL)return;
536
        int grid_sz = (_level_num -nskip1 - nskip2);
537
        if(grid_sz > 4) grid_sz = (int)ceil(grid_sz*0.5);
538
        double scale = 1.0/grid_sz;
539
        int stepx = 0, stepy = 0, dx, dy=0, nstep;
540

    
541
        if(_pyramid->_octave_min >0) scale *= (1<<_pyramid->_octave_min);
542
        else if(_pyramid->_octave_min < 0) scale /= (1<<(-_pyramid->_octave_min));
543

    
544

    
545
        glPushMatrix();
546
        glScaled(scale, scale, scale);
547

    
548
        for(int i = _pyramid->_octave_min; i < _pyramid->_octave_min+_pyramid->_octave_num; i++)
549
        {
550
        
551
                nstep = i==_pyramid->_octave_min? grid_sz: _level_num;
552
                dx = 0;
553
                UseDisplayShader();
554
                for(int j = _level_min + nskip1; j <= _level_max-nskip2; j++)
555
                {
556
                        GLTexImage * tex = _pyramid->GetLevelTexture(i, j, dataName);
557
                        if(tex->GetImgWidth() == 0 || tex->GetImgHeight() == 0) continue;
558
                        stepx = tex->GetImgWidth();
559
                        stepy = tex->GetImgHeight();        
560
                        ////
561
                        if(j == _level_min + nskip1 + nstep)
562
                        {
563
                                dy += stepy;
564
                                dx = 0;
565
                        }
566

    
567
                        glPushMatrix();
568
                        glTranslated(dx, dy, 0);
569
                        tex->BindTex();
570
                        tex->DrawImage();
571
                        tex->UnbindTex();
572
                        glPopMatrix();
573

    
574
                        dx += stepx;
575

    
576
                }
577

    
578
                ShaderMan::UnloadProgram();
579

    
580
                dy+= stepy;
581
        }
582

    
583
        glPopMatrix();
584
}
585

    
586

    
587
void SiftGPUEX::DisplayLevel(void (*UseDisplayShader)(), int i)
588
{
589
        if(_pyramid == NULL)return;
590

    
591
        i = i%(_level_num * _pyramid->_octave_num);
592
        if (i<0 ) i+= (_level_num * _pyramid->_octave_num);
593
        int octave = _pyramid->_octave_min + i/_level_num;
594
        int level  = _level_min + i%_level_num;
595
        double scale = 1.0;
596

    
597
        if(octave >0) scale *= (1<<octave);
598
        else if(octave < 0) scale /= (1<<(-octave));
599

    
600
        GLTexImage * tex = _pyramid->GetLevelTexture(octave, level);
601

    
602
        UseDisplayShader();
603

    
604
        glPushMatrix();
605
        glScaled(scale, scale, scale);
606
        tex->BindTex();
607
        tex->DrawImage();
608
        tex->UnbindTex();
609
        glPopMatrix();
610
        ShaderMan::UnloadProgram();
611
}
612

    
613
void SiftGPUEX::DisplaySIFT()
614
{
615
        if(_pyramid == NULL) return;
616
    glEnable(GlobalUtil::_texTarget);
617
        switch(_view)
618
        {
619
        case 0:
620
                DisplayInput();
621
                DisplayFeatureBox(_sub_view);
622
                break;
623
        case 1:
624
                DisplayPyramid(ShaderMan::UseShaderDisplayGaussian, SiftPyramid::DATA_GAUSSIAN);
625
                break;
626
        case 2:
627
                DisplayOctave(ShaderMan::UseShaderDisplayGaussian, _sub_view);        
628
                break;
629
        case 3:
630
                DisplayLevel(ShaderMan::UseShaderDisplayGaussian, _sub_view);
631
                break;
632
        case 4:
633
                DisplayPyramid(ShaderMan::UseShaderDisplayDOG, SiftPyramid::DATA_DOG, 1);
634
                break;
635
        case 5:
636
                DisplayPyramid(ShaderMan::UseShaderDisplayGrad, SiftPyramid::DATA_GRAD, 1);
637
                break;
638
        case 6:
639
                DisplayPyramid(ShaderMan::UseShaderDisplayDOG, SiftPyramid::DATA_DOG,2, 1);
640
                DisplayPyramid(ShaderMan::UseShaderDisplayKeypoints, SiftPyramid::DATA_KEYPOINT, 2,1);
641
        }
642
}
643

    
644

    
645
void SiftGPUEX::SetView(int view, int sub_view, char *title)
646
{
647
        const char* view_titles[] =
648
        {
649
                "Original Image",
650
                "Gaussian Pyramid",
651
                "Octave Images",
652
                "Level Image",
653
                "Difference of Gaussian",
654
                "Gradient",
655
                "Keypoints"
656
        };
657
        const int view_num = 7;
658
        _view = view % view_num;
659
        if(_view <0) _view +=view_num;
660
        _sub_view = sub_view;
661

    
662
        if(_view_debug)
663
                strcpy(title, "Debug...");
664
        else
665
                strcpy(title, view_titles[_view]);
666

    
667
}
668

    
669

    
670
void SiftGPU::PrintUsage()
671
{
672
        std::cout
673
        <<"SiftGPU Usage:\n"
674
        <<"-h -help          : Parameter information\n"
675
        <<"-i <strings>      : Filename(s) of the input image(s)\n"
676
        <<"-il <string>      : Filename of an image list file\n"
677
        <<"-o <string>       : Where to save SIFT features\n"
678
        <<"-f <float>        : Filter width factor; Width will be 2*factor+1 (default : 4.0)\n"
679
        <<"-w  <float>       : Orientation sample window factor (default: 2.0)\n"
680
        <<"-dw <float>  *    : Descriptor grid size factor (default : 3.0)\n"
681
        <<"-fo <int>    *    : First octave to detect DOG keypoints(default : 0)\n"
682
        <<"-no <int>         : Maximum number of Octaves (default : no limit)\n"
683
        <<"-d <int>          : Number of DOG levels in an octave (default : 3)\n"
684
        <<"-t <float>        : DOG threshold (default : 0.02/3)\n"
685
        <<"-e <float>        : Edge Threshold (default : 10.0)\n"
686
        <<"-m  <int=2>       : Multi Feature Orientations (default : 1)\n"
687
        <<"-m2p              : 2 Orientations packed as one float\n"
688
        <<"-s  <int=1>       : Sub-Pixel, Sub-Scale Localization, Multi-Refinement(num)\n"
689
        <<"-lcpu -lc <int>   : CPU/GPU mixed Feature List Generation (defaut : 6)\n"
690
        <<"                    Use GPU first, and use CPU when reduction size <= pow(2,num)\n"
691
        <<"                    When <num> is missing or equals -1, no GPU will be used\n"
692
        <<"-noprep           : Upload raw data to GPU (default: RGB->LUM and down-sample on CPU)\n"
693
        <<"-sd               : Skip descriptor computation if specified\n"
694
        <<"-unn    *         : Write unnormalized descriptor if specified\n"
695
        <<"-b      *         : Write binary sift file if specified\n"
696
        <<"-fs <int>         : Block Size for freature storage <default : 4>\n"
697
    <<"-cuda <int=0>     : Use CUDA SiftGPU, and specifiy the device index\n"
698
        <<"-tight            : Automatically resize pyramid to fit new images tightly\n"
699
        <<"-p  <W>x<H>       : Inititialize the pyramids to contain image of WxH (eg -p 1024x768)\n"
700
        <<"-lm  <int>        : Maximum feature count for a level (for pre-allocation)\n"
701
        <<"-lmp <float>      : Maximum percent of pixels as features (for pre-allocaton)\n"
702
        <<"-tc[1|2|3] <int> *: Threshold for limiting the overall number of features (3 methods)\n"
703
        <<"-v <int>          : Level of timing details. Same as calling Setverbose() function\n"
704
        <<"-loweo            : (0, 0) at center of top-left pixel (defaut: corner)\n"
705
        <<"-maxd <int> *     : Max working dimension (default : 2560 (unpacked) / 3200 (packed))\n"
706
        <<"-exit             : Exit program after processing the input image\n"
707
        <<"-unpack           : Use the old unpacked implementation\n"
708
        <<"-di               : Use dynamic array indexing if available (defualt : no)\n"
709
        <<"                    It could make computation faster on cards like GTX 280\n"
710
        <<"-ofix     *       : use 0 as feature orientations.\n"
711
        <<"-ofix-not *       : disable -ofix.\n"
712
        <<"-winpos <X>x<Y> * : Screen coordinate used in Win32 to select monitor/GPU.\n"
713
    <<"-display <string>*: Display name used in Linux/Mac to select monitor/GPU.\n"
714
    <<"\n"
715
    <<"NOTE: parameters marked with * can be changed after initialization\n"
716
        <<"\n";
717
}
718

    
719
void SiftGPU::ParseParam(int argc, char **argv)
720
{
721
    #define CHAR1_TO_INT(x)         ((x >= 'A' && x <= 'Z') ? x + 32 : x)
722
    #define CHAR2_TO_INT(str, i)    (str[i] ? CHAR1_TO_INT(str[i]) + (CHAR1_TO_INT(str[i+1]) << 8) : 0)  
723
    #define CHAR3_TO_INT(str, i)    (str[i] ? CHAR1_TO_INT(str[i]) + (CHAR2_TO_INT(str, i + 1) << 8) : 0)
724
    #define STRING_TO_INT(str)      (CHAR1_TO_INT(str[0]) +  (CHAR3_TO_INT(str, 1) << 8))
725

    
726
#ifdef _MSC_VER
727
    //charizing is microsoft only
728
    #define MAKEINT1(a)             (#@a )
729
#else
730
    #define mychar0    '0'
731
    #define mychar1    '1'
732
    #define mychar2    '2'
733
    #define mychar3    '3'
734
    #define mychara    'a'
735
    #define mycharb    'b'
736
    #define mycharc    'c'
737
    #define mychard    'd'
738
    #define mychare    'e'
739
    #define mycharf    'f'
740
    #define mycharg    'g'
741
    #define mycharh    'h'
742
    #define mychari    'i'
743
    #define mycharj    'j'
744
    #define mychark    'k'
745
    #define mycharl    'l'
746
    #define mycharm    'm'
747
    #define mycharn    'n'
748
    #define mycharo    'o'
749
    #define mycharp    'p'
750
    #define mycharq    'q'
751
    #define mycharr    'r'
752
    #define mychars    's'
753
    #define mychart    't'
754
    #define mycharu    'u'
755
    #define mycharv    'v'
756
    #define mycharw    'w'
757
    #define mycharx    'x'
758
    #define mychary    'y'
759
    #define mycharz    'z'
760
    #define MAKEINT1(a)             (mychar##a )
761
#endif
762
    #define MAKEINT2(a, b)          (MAKEINT1(a) + (MAKEINT1(b) << 8))
763
    #define MAKEINT3(a, b, c)       (MAKEINT1(a) + (MAKEINT2(b, c) << 8))
764
    #define MAKEINT4(a, b, c, d)    (MAKEINT1(a) + (MAKEINT3(b, c, d) << 8))
765

    
766

    
767
        char* arg, *param, * opt;
768
        int  setMaxD = 0, opti;
769
        for(int i = 0; i< argc; i++)
770
        {
771
                arg = argv[i];
772
                if(arg == NULL || arg[0] != '-' || !arg[1])continue;
773
                opt = arg+1;
774
        opti = STRING_TO_INT(opt);
775
                param = argv[i+1];
776
 
777
        ////////////////////////////////
778
        switch(opti)
779
        {
780
        case MAKEINT1(h):
781
        case MAKEINT4(h, e, l, p):
782
                        PrintUsage();
783
            break;            
784
        case MAKEINT4(c, u, d, a):
785
#if defined(CUDA_SIFTGPU_ENABLED)
786

    
787
            if(!_initialized) 
788
            {
789
                            GlobalUtil::_UseCUDA = 1;
790
                int device =  -1; 
791
                            if(i+1 <argc && sscanf(param, "%d", &device) && device >=0)
792
                {
793
                    GlobalUtil::_DeviceIndex = device; 
794
                    i++;
795
                }
796
            }
797
#else
798
                 std::cerr        << "---------------------------------------------------------------------------\n"
799
                                        << "CUDA not supported in this binary! To enable it, please use SiftGPU_CUDA_Enable\n" 
800
                                        << "solution for VS2005+ or set siftgpu_enable_cuda to 1 in makefile\n"
801
                                        << "----------------------------------------------------------------------------\n";
802
#endif
803
            break;  
804
        case MAKEINT2(c, l):
805
#if defined(CL_SIFTGPU_ENABLED)
806
            if(!_initialized) GlobalUtil::_UseOpenCL = 1;
807
#else
808
                    std::cerr        << "---------------------------------------------------------------------------\n"
809
                                            << "OpenCL not supported in this binary! Define CL_CUDA_SIFTGPU_ENABLED to..\n"
810
                                            << "----------------------------------------------------------------------------\n";
811
#endif
812
            break;
813

    
814
        case MAKEINT4(p, a, c, k):
815
                        if(!_initialized) GlobalUtil::_usePackedTex = 1;
816
            break;            
817
        case MAKEINT4(u, n, p, a): //unpack
818
                        if(!_initialized) 
819
            {
820
                GlobalUtil::_usePackedTex = 0;
821
                if(!setMaxD) GlobalUtil::_texMaxDim = 2560;
822
            }
823
            break;            
824
        case MAKEINT4(l, c, p, u):
825
        case MAKEINT2(l, c):
826
            if(!_initialized) 
827
            {
828
                            int gskip = -1;
829
                            if(i+1 <argc)        sscanf(param, "%d", &gskip);
830
                            if(gskip >= 0)
831
                            {
832
                                    GlobalUtil::_ListGenSkipGPU = gskip;
833
                            }else
834
                            {
835
                                    GlobalUtil::_ListGenGPU = 0;
836
                            }
837
            }
838
            break;            
839
        case MAKEINT4(p, r, e, p):
840
                        GlobalUtil::_PreProcessOnCPU = 1;
841
            break;            
842
        case MAKEINT4(n, o, p, r): //noprep
843
                        GlobalUtil::_PreProcessOnCPU = 0;
844
            break;            
845
        case MAKEINT4(f, b, o, 1):
846
                        FrameBufferObject::UseSingleFBO =1;
847
            break;            
848
        case MAKEINT4(f, b, o, s):
849
                        FrameBufferObject::UseSingleFBO = 0;
850
            break;            
851
                case MAKEINT2(s, d):
852
                        if(!_initialized) GlobalUtil::_DescriptorPPT =0;
853
            break;            
854
        case MAKEINT3(u, n, n):
855
                        GlobalUtil::_NormalizedSIFT =0;
856
            break;    
857
        case MAKEINT4(n, d, e, s):
858
                        GlobalUtil::_NormalizedSIFT =1;
859
            break;  
860
        case MAKEINT1(b):
861
                        GlobalUtil::_BinarySIFT = 1;
862
            break;            
863
        case MAKEINT4(t, i, g, h): //tight
864
                        GlobalUtil::_ForceTightPyramid = 1;
865
            break;            
866
        case MAKEINT4(e, x, i, t):
867
                        GlobalUtil::_ExitAfterSIFT = 1;
868
            break;            
869
        case MAKEINT2(d, i):
870
                        GlobalUtil::_UseDynamicIndexing = 1;
871
            break;            
872
        case MAKEINT4(s, i, g, n):
873
            if(!_initialized || GlobalUtil::_UseCUDA) GlobalUtil::_KeepExtremumSign = 1;
874
            break;    
875
                case MAKEINT1(m):
876
        case MAKEINT2(m, o):
877
            if(!_initialized) 
878
            {
879
                            int mo = 2; //default multi-orientation
880
                            if(i+1 <argc)        sscanf(param, "%d", &mo);
881
                            //at least two orientation
882
                            GlobalUtil::_MaxOrientation = min(max(1, mo), 4);
883
            }
884
            break;            
885
        case MAKEINT3(m, 2, p):
886
            if(!_initialized) 
887
            {
888
                            GlobalUtil::_MaxOrientation = 2;
889
                            GlobalUtil::_OrientationPack2 = 1;
890
            }
891
            break;            
892
        case MAKEINT1(s):
893
            if(!_initialized) 
894
            {
895
                int sp = 1; //default refinement
896
                if(i+1 <argc)        sscanf(param, "%d", &sp);
897
                //at least two orientation
898
                GlobalUtil::_SubpixelLocalization = min(max(0, sp),5);
899
            }
900
            break;            
901
        case MAKEINT4(o, f, i, x):
902
                        GlobalUtil::_FixedOrientation = (_stricmp(opt, "ofix")==0);
903
            break;            
904
                case MAKEINT4(l, o, w, e): // loweo
905
                        GlobalUtil::_LoweOrigin = 1;
906
            break;              
907
        case MAKEINT4(n, a, r, r): // narrow
908
                        GlobalUtil::_NarrowFeatureTex = 1;
909
            break;            
910
        case MAKEINT4(d, e, b, u): // debug
911
                        GlobalUtil::_debug = 1;
912
            break;
913
        case MAKEINT2(k, 0):
914
            GlobalUtil::_KeyPointListForceLevel0 = 1;
915
            break;
916
        case MAKEINT2(k, x):
917
            GlobalUtil::_KeyPointListForceLevel0 = 0;
918
            break;
919
        default:
920
            if(i + 1 >= argc) break;
921
            switch(opti)
922
            {
923
            case MAKEINT1(i):
924
                strcpy(_imgpath, param);
925
                i++;
926
                //get the file list..
927
                _list->push_back(param);
928
                while( i+1 < argc && argv[i+1][0] !='-')
929
                {
930
                    _list->push_back(argv[++i]);
931
                }
932
                break;            
933
            case MAKEINT2(i, l):
934
                LoadImageList(param);
935
                i++;
936
                break;            
937
            case MAKEINT1(o):
938
                strcpy(_outpath, param);
939
                i++;
940
                break;
941
            case MAKEINT1(f):
942
                {
943
                    float factor = 0.0f;
944
                    if(sscanf(param, "%f", &factor) && factor > 0 )
945
                    {
946
                        GlobalUtil::_FilterWidthFactor  = factor;
947
                        i++;
948
                    }
949
                }
950
                break;  
951
            case MAKEINT2(o, t): 
952
                {
953
                    float factor = 0.0f;
954
                    if(sscanf(param, "%f", &factor) && factor>0 )
955
                    {
956
                        GlobalUtil::_MulitiOrientationThreshold  = factor;
957
                        i++;
958
                    }
959
                    break;                
960
                }
961
            case MAKEINT1(w): 
962
                {
963
                    float factor = 0.0f;
964
                    if(sscanf(param, "%f", &factor) && factor>0 )
965
                    {
966
                        GlobalUtil::_OrientationWindowFactor  = factor;
967
                        i++;
968
                    }
969
                    break;                
970
                }
971
            case MAKEINT2(d, w): 
972
                {
973
                    float factor = 0.0f;
974
                    if(sscanf(param, "%f", &factor) && factor > 0 )
975
                    {
976
                        GlobalUtil::_DescriptorWindowFactor  = factor;
977
                        i++;
978
                    }
979
                    break;                
980
                }
981
            case MAKEINT2(f, o): 
982
                {
983
                    int first_octave = -3;
984
                    if(sscanf(param, "%d", &first_octave) && first_octave >=-2 )
985
                    {
986
                        GlobalUtil::_octave_min_default = first_octave;
987
                        i++;
988
                    }
989
                    break;
990
                }
991
            case MAKEINT2(n, o): 
992
                if(!_initialized)
993
                {
994
                    int octave_num=-1;
995
                    if(sscanf(param, "%d", &octave_num))
996
                    {
997
                        octave_num = max(-1, octave_num);
998
                        if(octave_num ==-1 || octave_num >=1)
999
                        {
1000
                            GlobalUtil::_octave_num_default = octave_num;
1001
                            i++;
1002
                        }
1003
                    }
1004
                }
1005
                break;
1006
            case MAKEINT1(t): 
1007
                {
1008
                    float threshold = 0.0f;
1009
                    if(sscanf(param, "%f", &threshold) && threshold >0 && threshold < 0.5f)
1010
                    {
1011
                        SiftParam::_dog_threshold = threshold;
1012
                        i++;
1013
                    }
1014
                    break;                
1015
                }
1016
            case MAKEINT1(e):
1017
                {
1018
                    float threshold = 0.0f;
1019
                    if(sscanf(param, "%f", &threshold) && threshold >0 )
1020
                    {
1021
                        SiftParam::_edge_threshold = threshold;
1022
                        i++;
1023
                    }
1024
                    break;                
1025
                }
1026
            case MAKEINT1(d): 
1027
                {
1028
                    int num = 0;
1029
                    if(sscanf(param, "%d", &num) && num >=1 && num <=10)
1030
                    {
1031
                        SiftParam::_dog_level_num = num;
1032
                        i++;
1033
                    }
1034
                    break;
1035
                }
1036
            case MAKEINT2(f, s): 
1037
                {
1038
                    int num = 0;
1039
                    if(sscanf(param, "%d", &num) && num >=1)
1040
                    {
1041
                        GlobalParam::_FeatureTexBlock = num;
1042
                        i++;
1043
                    }
1044
                    break;
1045
                }
1046
            case MAKEINT1(p): 
1047
                {
1048
                    int w =0, h=0;
1049
                    if(sscanf(param, "%dx%d", &w, &h) == 2 && w >0 &&  h>0)
1050
                    {
1051
                        GlobalParam::_InitPyramidWidth = w;
1052
                        GlobalParam::_InitPyramidHeight = h;
1053
                        i++;
1054
                    }
1055
                    break;                
1056
                }
1057
            case MAKEINT4(w, i, n, p): //winpos
1058
                {
1059
                    int x =0, y=0;
1060
                    if(sscanf(param, "%dx%d", &x, &y) == 2)
1061
                    {
1062
                        GlobalParam::_WindowInitX = x;
1063
                        GlobalParam::_WindowInitY = y;
1064
                        i++;
1065
                    }
1066
                    break;                
1067
                }
1068
            case MAKEINT4(d, i, s, p): //display
1069
                {
1070
                    GlobalParam::_WindowDisplay = param;
1071
                    i++;
1072
                    break;                
1073
                }
1074
            case MAKEINT2(l, m): 
1075
                {
1076
                    int num = 0;
1077
                    if(sscanf(param, "%d", &num) && num >=1000)
1078
                    {
1079
                        GlobalParam::_MaxLevelFeatureNum = num;
1080
                        i++;
1081
                    }
1082
                    break;                
1083
                }
1084
            case MAKEINT3(l, m, p): 
1085
                {
1086
                    float num = 0.0f;
1087
                    if(sscanf(param, "%f", &num) && num >=0.001)
1088
                    {
1089
                        GlobalParam::_MaxFeaturePercent = num;
1090
                        i++;
1091
                    }
1092
                    break;                
1093
                }
1094
            case MAKEINT3(t, c, 2): //downward
1095
            case MAKEINT3(t, c, 3):
1096
            case MAKEINT2(t, c):  //tc
1097
            case MAKEINT3(t, c, 1):  //
1098
                {
1099
                    switch (opti)
1100
                    {
1101
                        case MAKEINT3(t, c, 2): GlobalUtil::_TruncateMethod = 1; break;
1102
                        case MAKEINT3(t, c, 3): GlobalUtil::_TruncateMethod = 2; break;
1103
                        default:                GlobalUtil::_TruncateMethod = 0; break;
1104
                    }
1105
                    int num = -1;
1106
                    if(sscanf(param, "%d", &num) && num > 0)
1107
                    {
1108
                        GlobalParam::_FeatureCountThreshold = num;
1109
                        i++;
1110
                    }
1111
                    break;                
1112
                }
1113
            case MAKEINT1(v):
1114
                {
1115
                    int num = 0;
1116
                    if(sscanf(param, "%d", &num) && num >=0 && num <= 4)
1117
                    {
1118
                        SetVerbose(num);
1119
                    }
1120
                    break;                
1121
                }
1122
            case MAKEINT4(m, a, x, d):   
1123
                {
1124
                    int num = 0;
1125
                    if(sscanf(param, "%d", &num) && num > 0)
1126
                    {
1127
                        GlobalUtil::_texMaxDim = num; 
1128
                        setMaxD = 1;
1129
                    }
1130
                    break;
1131
                } 
1132
           case MAKEINT4(m, i, n, d):   
1133
                {
1134
                    int num = 0;
1135
                    if(sscanf(param, "%d", &num) && num >= 8)
1136
                    {
1137
                        GlobalUtil::_texMinDim = num; 
1138
                    }
1139
                    break;
1140
                } 
1141
            default:
1142
                break;
1143
            }                
1144
            break;
1145
        }
1146
        }
1147
        //do not write result if there are more than one input images
1148
        if(_outpath[0] && _list->size()>1)                _outpath[0] = 0;
1149
} 
1150

    
1151
void SiftGPU::SetImageList(int nimage, const char** filelist)
1152
{
1153
        _list->resize(0);
1154
        for(int i = 0; i < nimage; i++)
1155
        {
1156
                _list->push_back(filelist[i]);
1157
        }
1158
        _current = 0;
1159

    
1160
}
1161
void SiftGPU:: LoadImageList(char *imlist)
1162
{
1163
        char filename[_MAX_PATH];
1164
        ifstream in(imlist);
1165
        while(in>>filename)
1166
        {
1167
                _list->push_back(filename);
1168
        }
1169
        in.close();
1170

    
1171

    
1172
        if(_list->size()>0)
1173
        {
1174
                strcpy(_imgpath, _list->at(0).data());
1175
                strcpy(filename, imlist);
1176
                char * slash = strrchr(filename, '\\');
1177
                if(slash == 0) slash = strrchr(filename, '/');
1178
                if(slash )
1179
                {
1180
                        slash[1] = 0;
1181
                        chdir(filename);
1182
                }
1183
        }
1184
        _image_loaded = 0;
1185

    
1186

    
1187
}
1188
float SiftParam::GetLevelSigma( int lev)
1189
{
1190
        return _sigma0 * powf( 2.0f,  float(lev) / float(_dog_level_num )); //bug fix 9/12/2007
1191
}
1192

    
1193

    
1194

    
1195
void SiftGPUEX::DisplayFeatureBox(int view )
1196
{
1197
        view = view%3;
1198
        if(view<0)view+=3;
1199
        if(view ==2) return;
1200
        int idx = 0;
1201
        const int *fnum = _pyramid->GetLevelFeatureNum();
1202
        const GLuint *vbo = _pyramid->GetFeatureDipslayVBO();
1203
        const GLuint *vbop = _pyramid->GetPointDisplayVBO();
1204
        if(vbo == NULL || vbop == NULL) return;
1205
        //int  nvbo = _dog_level_num * _pyramid->_octave_num;
1206
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1207
        glEnableClientState(GL_VERTEX_ARRAY);
1208
        glPushMatrix();
1209
//        glTranslatef(0.0f, 0.0f, -1.0f);
1210
        glPointSize(2.0f);
1211

    
1212
        float scale = 1.0f;
1213
        if(_pyramid->_octave_min >0) scale *= (1<<_pyramid->_octave_min);
1214
        else if(_pyramid->_octave_min < 0) scale /= (1<<(-_pyramid->_octave_min));
1215
        glScalef(scale, scale, 1.0f);
1216

    
1217

    
1218
        for(int i = 0; i < _pyramid->_octave_num; i++)
1219
        {
1220

    
1221
                for(int j = 0; j < _dog_level_num; j++, idx++)
1222
                {
1223
                        if(fnum[idx]>0)
1224
                        {
1225
                                if(view ==0)
1226
                                {
1227
                                        glColor3f(0.2f, 1.0f, 0.2f);
1228
                                        glBindBuffer(GL_ARRAY_BUFFER_ARB, vbop[idx]);
1229
                                        glVertexPointer( 4, GL_FLOAT,4*sizeof(float), (char *) 0);
1230
                                        glDrawArrays( GL_POINTS, 0, fnum[idx]);
1231
                                        glFlush();
1232
                                }else
1233
                                {
1234
                                                
1235
                                        //glColor3f(1.0f, 0.0f, 0.0f);
1236
                                        glColor3fv(_colors+ (idx%COLOR_NUM)*3);
1237
                                        glBindBuffer(GL_ARRAY_BUFFER_ARB, vbo[idx]);
1238
                                        glVertexPointer( 4, GL_FLOAT,4*sizeof(float), (char *) 0);
1239
                                        glDrawArrays( GL_LINES, 0, fnum[idx]*10 );
1240
                                        glFlush();
1241
                                }
1242

    
1243
                        }
1244
                
1245
                }
1246
                glTranslatef(-.5f, -.5f, 0.0f);
1247
                glScalef(2.0f, 2.0f, 1.0f);
1248

    
1249
        }
1250
        glPopMatrix();
1251
        glDisableClientState(GL_VERTEX_ARRAY);
1252
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1253
        glPointSize(1.0f);
1254
                                                        
1255
}
1256

    
1257
void SiftGPUEX::ToggleDisplayDebug()
1258
{
1259
        _view_debug = !_view_debug;
1260
}
1261

    
1262
void SiftGPUEX::DisplayDebug()
1263
{
1264
        glPointSize(1.0f);
1265
        glColor3f(1.0f, 0.0f, 0.0f);
1266
        ShaderMan::UseShaderDebug();
1267
        glBegin(GL_POINTS);
1268
        for(int i = 0; i < 100; i++)
1269
        {
1270
                glVertex2f(i*4.0f+0.5f, i*4.0f+0.5f);
1271
        }
1272
        glEnd();
1273
        ShaderMan::UnloadProgram();
1274
}
1275

    
1276
int SiftGPU::CreateContextGL()
1277
{
1278
    if(GlobalUtil::_UseOpenCL || GlobalUtil::_UseCUDA)
1279
    {
1280
        //do nothing
1281
    }
1282
    else if(!GlobalUtil::CreateWindowEZ()) 
1283
    {
1284
#if CUDA_SIFTGPU_ENABLED
1285
                GlobalUtil::_UseCUDA = 1;
1286
#else
1287
        return 0;
1288
#endif
1289
    }
1290

    
1291
        return VerifyContextGL();
1292
}
1293

    
1294
int SiftGPU::VerifyContextGL()
1295
{
1296
        InitSiftGPU();
1297
        return (GlobalUtil::_GoodOpenGL > 0) + GlobalUtil::_FullSupported;
1298
}
1299

    
1300
int SiftGPU::IsFullSupported()
1301
{
1302
        return GlobalUtil::_GoodOpenGL > 0 &&  GlobalUtil::_FullSupported;
1303
}
1304

    
1305
void SiftGPU::SaveSIFT(const char * szFileName)
1306
{
1307
        _pyramid->SaveSIFT(szFileName);
1308
}
1309

    
1310
int SiftGPU::GetFeatureNum()
1311
{
1312
        return _pyramid->GetFeatureNum();
1313
}
1314

    
1315
void SiftGPU::GetFeatureVector(SiftKeypoint * keys, float * descriptors)
1316
{
1317
//        keys.resize(_pyramid->GetFeatureNum());
1318
        if(GlobalUtil::_DescriptorPPT)
1319
        {
1320
        //        descriptors.resize(128*_pyramid->GetFeatureNum());
1321
                _pyramid->CopyFeatureVector((float*) (&keys[0]), &descriptors[0]);
1322
        }else
1323
        {
1324
                //descriptors.resize(0);
1325
                _pyramid->CopyFeatureVector((float*) (&keys[0]), NULL);
1326
        }
1327
}
1328

    
1329
void SiftGPU::SetTightPyramid(int tight)
1330
{
1331
        GlobalUtil::_ForceTightPyramid = tight;
1332
}
1333

    
1334
int SiftGPU::AllocatePyramid(int width, int height)
1335
{
1336
        _pyramid->_down_sample_factor = 0;
1337
        _pyramid->_octave_min = GlobalUtil::_octave_min_default;
1338
        if(GlobalUtil::_octave_min_default>=0)
1339
        {
1340
                width >>= GlobalUtil::_octave_min_default;
1341
                height >>= GlobalUtil::_octave_min_default;
1342
        }else
1343
        {
1344
                width <<= (-GlobalUtil::_octave_min_default);
1345
                height <<= (-GlobalUtil::_octave_min_default);
1346
        }
1347
        _pyramid->ResizePyramid(width, height);
1348
        return _pyramid->_pyramid_height == height && width == _pyramid->_pyramid_width ;
1349
}
1350

    
1351
void SiftGPU::SetMaxDimension(int sz)
1352
{
1353
        if(sz < GlobalUtil::_texMaxDimGL)
1354
        {
1355
                GlobalUtil::_texMaxDim = sz;
1356
        }
1357
}
1358
int SiftGPU::GetImageCount()
1359
{
1360
        return _list->size();
1361
}
1362

    
1363
void SiftGPUEX::HSVtoRGB(float hsv[3],float rgb[3] )
1364
{
1365

    
1366
        int i;
1367
        float q, t, p;
1368
        float hh,f, v = hsv[2];
1369
        if(hsv[1]==0.0f)
1370
        {
1371
                rgb[0]=rgb[1]=rgb[2]=v;
1372
        }
1373
        else
1374
        {
1375
                //////////////
1376
                hh =hsv[0]*6.0f ;   // sector 0 to 5
1377
                i =(int)hh ;
1378
                f = hh- i;   // factorial part of h
1379
                //////////
1380
                p=  v * ( 1 - hsv[1] );
1381
                q = v * ( 1 - hsv[1] * f );
1382
                t = v * ( 1 - hsv[1] * ( 1 - f ) );
1383
                switch( i ) {
1384
                        case 0:rgb[0] = v;rgb[1] = t;rgb[2] = p;break;
1385
                        case 1:rgb[0] = q;rgb[1] = v;rgb[2] = p;break;
1386
                        case 2:rgb[0] = p;rgb[1] = v;rgb[2] = t;break;
1387
                        case 3:rgb[0] = p;rgb[1] = q;rgb[2] = v;break;
1388
                        case 4:rgb[0] = t;rgb[1] = p;rgb[2] = v;break;
1389
                        case 5:rgb[0] = v;rgb[1] = p;rgb[2] = q;break;
1390
                        default:rgb[0]= 0;rgb[1] = 0;rgb[2] = 0;
1391
                }
1392
        }
1393
}
1394

    
1395
void SiftGPUEX::GetImageDimension( int &w,  int &h)
1396
{
1397
        w = _texImage->GetImgWidth();
1398
        h = _texImage->GetImgHeight();
1399

    
1400
}
1401

    
1402
void SiftGPUEX::GetInitWindowPotition(int&x, int&y)
1403
{
1404
        x = GlobalUtil::_WindowInitX;
1405
        y = GlobalUtil::_WindowInitY;
1406
}
1407

    
1408
SiftGPU* CreateNewSiftGPU(int np)
1409
{
1410
        return new SiftGPU(np);
1411
}
1412

    
1413
/////////////////////////////////////////////////////
1414
void* ComboSiftGPU::operator new (size_t  size){
1415
  void * p = malloc(size);
1416
  if (p == 0)  
1417
  {
1418
          const std::bad_alloc ba;
1419
          throw ba; 
1420
  }
1421
  return p; 
1422
}
1423

    
1424
ComboSiftGPU* CreateComboSiftGPU()
1425
{
1426
        return new ComboSiftGPU();
1427
}
1428