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
26 #include "GL/glew.h"
27 #include <iostream>
28 #include <fstream>
29 #include <string>
30 #include <iomanip>
31 #include <vector>
32 #include <algorithm>
33 #include <math.h>
34
35 #include <time.h>
36 using namespace std;
37
38
39 #include "GlobalUtil.h"
40 #include "SiftGPU.h"
41 #include "GLTexImage.h"
42 #include "ShaderMan.h"
43 #include "FrameBufferObject.h"
44 #include "SiftPyramid.h"
45 #include "PyramidGL.h"
46
47 //CUDA works only with vc8 or higher
48 #if defined(CUDA_SIFTGPU_ENABLED)
49 #include "PyramidCU.h"
50 #endif
51
52 #if defined(CL_SIFTGPU_ENABLED)
53 #include "PyramidCL.h"
54 #endif
55
56
57 ////
58 #if defined(_WIN32)
59 #include "direct.h"
60 #pragma warning (disable : 4786)
61 #pragma warning (disable : 4996)
62 #else
63 //compatible with linux
64 #define _stricmp strcasecmp
65 #include <stdlib.h>
66 #include <string.h>
67 #include <unistd.h>
68 #endif
69
70 #if !defined(_MAX_PATH)
71 #if defined (PATH_MAX)
72 #define _MAX_PATH PATH_MAX
73 #else
74 #define _MAX_PATH 512
75 #endif
76 #endif
77
78 //////////////////////////////////////////////////////////////////////
79 //////////////////////////////////////////////////////////////////////
80 //
81 //just want to make this class invisible
82 class ImageList:public std::vector<std::string> {};
83
SiftGPU(int np)84 SiftGPU::SiftGPU(int np)
85 {
86 _texImage = new GLTexInput;
87 _imgpath = new char[_MAX_PATH];
88 _outpath = new char[_MAX_PATH];
89 _imgpath[0] = _outpath[0] = 0;
90 _initialized = 0;
91 _image_loaded = 0;
92 _current = 0;
93 _list = new ImageList();
94 _pyramid = NULL;
95 }
96
97
98
SiftGPUEX()99 SiftGPUEX::SiftGPUEX()
100 {
101 _view = _sub_view = 0;
102 _view_debug = 0;
103 GlobalUtil::_UseSiftGPUEX = 1;
104 srand((unsigned int)time(NULL));
105 RandomizeColor();
106 }
107
operator new(size_t size)108 void* SiftGPU::operator new (size_t size){
109 void * p = malloc(size);
110 if (p == 0)
111 {
112 const std::bad_alloc ba;
113 throw ba;
114 }
115 return p;
116 }
117
118
RandomizeColor()119 void SiftGPUEX::RandomizeColor()
120 {
121 float hsv[3] = {0, 0.8f, 1.0f};
122 for(int i = 0; i < COLOR_NUM*3; i+=3)
123 {
124 hsv[0] = (rand()%100)*0.01f; //i/float(COLOR_NUM);
125 HSVtoRGB(hsv, _colors+i);
126 }
127 }
128
~SiftGPU()129 SiftGPU::~SiftGPU()
130 {
131 if(_pyramid) delete _pyramid;
132 delete _texImage;
133 delete _list;
134 delete[] _imgpath;
135 delete[] _outpath;
136 }
137
138
InitSiftGPU()139 inline void SiftGPU::InitSiftGPU()
140 {
141 if(_initialized || GlobalUtil::_GoodOpenGL ==0) return;
142
143 //Parse sift parameters
144 ParseSiftParam();
145
146 #if !defined(CUDA_SIFTGPU_ENABLED)
147 if(GlobalUtil::_UseCUDA)
148 {
149 GlobalUtil::_UseCUDA = 0;
150 std::cerr << "---------------------------------------------------------------------------\n"
151 << "CUDA not supported in this binary! To enable it, please use SiftGPU_CUDA_Enable\n"
152 << "solution for VS2005+ or set siftgpu_enable_cuda to 1 in makefile\n"
153 << "----------------------------------------------------------------------------\n";
154 }
155 #else
156 if(GlobalUtil::_UseCUDA == 0 && GlobalUtil::_UseOpenCL == 0)
157 {
158 // GlobalUtil::InitGLParam(0);
159 }
160 if(GlobalUtil::_GoodOpenGL == 0)
161 {
162 GlobalUtil::_UseCUDA = 1;
163 std::cerr << "Switch from OpenGL to CUDA\n";
164 }
165
166 if(GlobalUtil::_UseCUDA && !PyramidCU::CheckCudaDevice(GlobalUtil::_DeviceIndex))
167 {
168 std::cerr << "Switch from CUDA to OpenGL\n";
169 GlobalUtil::_UseCUDA = 0;
170 }
171 #endif
172
173 if(GlobalUtil::_verbose) std::cout <<"\n[SiftGPU Language]:\t"
174 << (GlobalUtil::_UseCUDA? "CUDA" :
175 (GlobalUtil::_UseOpenCL? "OpenCL" : "GLSL")) <<"\n";
176
177 #if defined(CUDA_SIFTGPU_ENABLED)
178 if(GlobalUtil::_UseCUDA)
179 _pyramid = new PyramidCU(*this);
180 else
181 #endif
182 #if defined(CL_SIFTGPU_ENABLED)
183 if(GlobalUtil::_UseOpenCL)
184 _pyramid = new PyramidCL(*this);
185 else
186 #endif
187 if(GlobalUtil::_usePackedTex)
188 _pyramid = new PyramidPacked(*this);
189 else
190 _pyramid = new PyramidNaive(*this);
191
192
193 if(GlobalUtil::_GoodOpenGL && GlobalUtil::_InitPyramidWidth > 0 && GlobalUtil::_InitPyramidHeight > 0)
194 {
195 GlobalUtil::StartTimer("Initialize Pyramids");
196 _pyramid->InitPyramid(GlobalUtil::_InitPyramidWidth, GlobalUtil::_InitPyramidHeight, 0);
197 GlobalUtil::StopTimer();
198 }
199
200 ClockTimer::InitHighResolution();
201 _initialized = 1;
202 }
203
RunSIFT(int index)204 int SiftGPU::RunSIFT(int index)
205 {
206 if(_list->size()>0 )
207 {
208 index = index % _list->size();
209 if(strcmp(_imgpath, _list->at(index).data()))
210 {
211 strcpy(_imgpath, _list->at(index).data());
212 _image_loaded = 0;
213 _current = index;
214 }
215 return RunSIFT();
216 }else
217 {
218 return 0;
219 }
220
221 }
222
RunSIFT(int width,int height,const void * data,unsigned int gl_format,unsigned int gl_type)223 int SiftGPU::RunSIFT( int width, int height, const void * data, unsigned int gl_format, unsigned int gl_type)
224 {
225
226 if(GlobalUtil::_GoodOpenGL ==0 ) return 0;
227 if(!_initialized) InitSiftGPU();
228 else GlobalUtil::SetGLParam();
229 if(GlobalUtil::_GoodOpenGL ==0 ) return 0;
230
231 if(width > 0 && height >0 && data != NULL)
232 {
233 _imgpath[0] = 0;
234 //try downsample the image on CPU
235 GlobalUtil::StartTimer("Upload Image data");
236 if(_texImage->SetImageData(width, height, data, gl_format, gl_type))
237 {
238 _image_loaded = 2; //gldata;
239 GlobalUtil::StopTimer();
240 _timing[0] = GlobalUtil::GetElapsedTime();
241
242 //if the size of image is different, the pyramid need to be reallocated.
243 GlobalUtil::StartTimer("Initialize Pyramid");
244 _pyramid->InitPyramid(width, height, _texImage->_down_sampled);
245 GlobalUtil::StopTimer();
246 _timing[1] = GlobalUtil::GetElapsedTime();
247
248 return RunSIFT();
249 }else
250 {
251 return 0;
252 }
253 }else
254 {
255 return 0;
256 }
257
258 }
259
RunSIFT(const char * imgpath)260 int SiftGPU::RunSIFT(const char * imgpath)
261 {
262 if(imgpath && imgpath[0])
263 {
264 //set the new image
265 strcpy(_imgpath, imgpath);
266 _image_loaded = 0;
267 return RunSIFT();
268 }else
269 {
270 return 0;
271 }
272
273
274 }
275
RunSIFT(int num,const SiftKeypoint * keys,int keys_have_orientation)276 int SiftGPU::RunSIFT(int num, const SiftKeypoint * keys, int keys_have_orientation)
277 {
278 if(num <=0) return 0;
279 _pyramid->SetKeypointList(num, (const float*) keys, 1, keys_have_orientation);
280 return RunSIFT();
281 }
282
RunSIFT()283 int SiftGPU::RunSIFT()
284 {
285 //check image data
286 if(_imgpath[0]==0 && _image_loaded == 0) return 0;
287
288 //check OpenGL support
289 if(GlobalUtil::_GoodOpenGL ==0 ) return 0;
290
291 ClockTimer timer;
292
293 if(!_initialized)
294 {
295 //initialize SIFT GPU for once
296 InitSiftGPU();
297 if(GlobalUtil::_GoodOpenGL ==0 ) return 0;
298 }else
299 {
300 //in case some OpenGL parameters are changed by users
301 GlobalUtil::SetGLParam();
302 }
303
304 timer.StartTimer("RUN SIFT");
305 //process input image file
306 if( _image_loaded ==0)
307 {
308 int width, height;
309 //load and try down-sample on cpu
310 GlobalUtil::StartTimer("Load Input Image");
311 if(!_texImage->LoadImageFile(_imgpath, width, height)) return 0;
312 _image_loaded = 1;
313 GlobalUtil::StopTimer();
314 _timing[0] = GlobalUtil::GetElapsedTime();
315
316 //make sure the pyrmid can hold the new image.
317 GlobalUtil::StartTimer("Initialize Pyramid");
318 _pyramid->InitPyramid(width, height, _texImage->_down_sampled);
319 GlobalUtil::StopTimer();
320 _timing[1] = GlobalUtil::GetElapsedTime();
321
322 }else
323 {
324 //change some global states
325 if(!GlobalUtil::_UseCUDA && !GlobalUtil::_UseOpenCL)
326 {
327 GlobalUtil::FitViewPort(1,1);
328 _texImage->FitTexViewPort();
329 }
330 if(_image_loaded == 1)
331 {
332 _timing[0] = _timing[1] = 0;
333 }else
334 {//2
335 _image_loaded = 1;
336 }
337 }
338
339 if(_pyramid->_allocated ==0 ) return 0;
340
341
342 #ifdef DEBUG_SIFTGPU
343 _pyramid->BeginDEBUG(_imgpath);
344 #endif
345
346 //process the image
347 _pyramid->RunSIFT(_texImage);
348
349 //read back the timing
350 _pyramid->GetPyramidTiming(_timing + 2);
351
352 //write output once if there is only one input
353 if(_outpath[0] ){ SaveSIFT(_outpath); _outpath[0] = 0;}
354
355 //terminate the process when -exit is provided.
356 if(GlobalUtil::_ExitAfterSIFT && GlobalUtil::_UseSiftGPUEX) exit(0);
357
358 timer.StopTimer();
359 if(GlobalUtil::_verbose)std::cout<<endl;
360
361 return _pyramid->GetSucessStatus();
362 }
363
364
SetKeypointList(int num,const SiftKeypoint * keys,int keys_have_orientation)365 void SiftGPU::SetKeypointList(int num, const SiftKeypoint * keys, int keys_have_orientation)
366 {
367 _pyramid->SetKeypointList(num, (const float*)keys, 0, keys_have_orientation);
368 }
369
DisplayInput()370 void SiftGPUEX::DisplayInput()
371 {
372 if(_texImage==NULL) return;
373 _texImage->VerifyTexture();
374 _texImage->BindTex();
375 _texImage->DrawImage();
376 _texImage->UnbindTex();
377
378 }
379
SetVerbose(int verbose)380 void SiftGPU::SetVerbose(int verbose)
381 {
382 GlobalUtil::_timingO = verbose>2;
383 GlobalUtil::_timingL = verbose>3;
384 if(verbose == -1)
385 {
386 //Loop between verbose level 0, 1, 2
387 if(GlobalUtil::_verbose)
388 {
389 GlobalUtil::_verbose = GlobalUtil::_timingS;
390 GlobalUtil::_timingS = 0;
391 if(GlobalUtil::_verbose ==0 && GlobalUtil::_UseSiftGPUEX)
392 std::cout << "Console output disabled, press Q/V to enable\n\n";
393 }else
394 {
395 GlobalUtil::_verbose = 1;
396 GlobalUtil::_timingS = 1;
397 }
398 }else if(verbose == -2)
399 {
400 //trick for disabling all output (still keeps the timing level)
401 GlobalUtil::_verbose = 0;
402 GlobalUtil::_timingS = 1;
403 }else
404 {
405 GlobalUtil::_verbose = verbose>0;
406 GlobalUtil::_timingS = verbose>1;
407 }
408 }
409
410
SiftParam()411 SiftParam::SiftParam()
412 {
413
414 _level_min = -1;
415 _dog_level_num = 3;
416 _level_max = 0;
417 _sigma0 = 0;
418 _sigman = 0;
419 _edge_threshold = 0;
420 _dog_threshold = 0;
421
422
423 }
424
GetInitialSmoothSigma(int octave_min)425 float SiftParam::GetInitialSmoothSigma(int octave_min)
426 {
427 float sa = _sigma0 * powf(2.0f, float(_level_min)/float(_dog_level_num)) ;
428 float sb = _sigman / powf(2.0f, float(octave_min)) ;//
429 float sigma_skip0 = sa > sb + 0.001?sqrt(sa*sa - sb*sb): 0.0f;
430 return sigma_skip0;
431 }
432
ParseSiftParam()433 void SiftParam::ParseSiftParam()
434 {
435
436 if(_dog_level_num ==0) _dog_level_num = 3;
437 if(_level_max ==0) _level_max = _dog_level_num + 1;
438 if(_sigma0 ==0.0f) _sigma0 = 1.6f * powf(2.0f, 1.0f / _dog_level_num) ;
439 if(_sigman == 0.0f) _sigman = 0.5f;
440
441
442 _level_num = _level_max -_level_min + 1;
443
444 _level_ds = _level_min + _dog_level_num;
445 if(_level_ds > _level_max ) _level_ds = _level_max ;
446
447 ///
448 float _sigmak = powf(2.0f, 1.0f / _dog_level_num) ;
449 float dsigma0 = _sigma0 * sqrt (1.0f - 1.0f / (_sigmak*_sigmak) ) ;
450 float sa, sb;
451
452
453 sa = _sigma0 * powf(_sigmak, (float)_level_min) ;
454 sb = _sigman / powf(2.0f, (float)GlobalUtil::_octave_min_default) ;//
455
456 _sigma_skip0 = sa>sb+ 0.001?sqrt(sa*sa - sb*sb): 0.0f;
457
458 sa = _sigma0 * powf(_sigmak, float(_level_min )) ;
459 sb = _sigma0 * powf(_sigmak, float(_level_ds - _dog_level_num)) ;
460
461 _sigma_skip1 = sa>sb + 0.001? sqrt(sa*sa - sb*sb): 0.0f;
462
463 _sigma_num = _level_max - _level_min;
464 _sigma = new float[_sigma_num];
465
466 for(int i = _level_min + 1; i <= _level_max; i++)
467 {
468 _sigma[i-_level_min -1] = dsigma0 * powf(_sigmak, float(i)) ;
469 }
470
471 if(_dog_threshold ==0) _dog_threshold = 0.02f / _dog_level_num ;
472 if(_edge_threshold==0) _edge_threshold = 10.0f;
473 }
474
475
DisplayOctave(void (* UseDisplayShader)(),int i)476 void SiftGPUEX::DisplayOctave(void (*UseDisplayShader)(), int i)
477 {
478 if(_pyramid == NULL)return;
479 const int grid_sz = (int)ceil(_level_num/2.0);
480 double scale = 1.0/grid_sz ;
481 int gx=0, gy=0, dx, dy;
482
483 if(_pyramid->_octave_min >0) scale *= (1<<_pyramid->_octave_min);
484 else if(_pyramid->_octave_min < 0) scale /= (1<<(-_pyramid->_octave_min));
485
486
487 i = i% _pyramid->_octave_num; //
488 if(i<0 ) i+= _pyramid->_octave_num;
489
490 scale *= ( 1<<(i));
491
492
493
494
495 UseDisplayShader();
496
497 glPushMatrix();
498 glScaled(scale, scale, scale);
499 for(int level = _level_min; level<= _level_max; level++)
500 {
501 GLTexImage * tex = _pyramid->GetLevelTexture(i+_pyramid->_octave_min, level);
502
503 dx = tex->GetImgWidth();
504 dy = tex->GetImgHeight();
505
506 glPushMatrix();
507
508 glTranslated(dx*gx, dy*gy, 0);
509
510 tex->BindTex();
511
512 tex->DrawImage();
513 tex->UnbindTex();
514
515 glPopMatrix();
516
517 gx++;
518 if(gx>=grid_sz)
519 {
520 gx =0;
521 gy++;
522 }
523
524 }
525
526 glPopMatrix();
527 ShaderMan::UnloadProgram();
528 }
529
DisplayPyramid(void (* UseDisplayShader)(),int dataName,int nskip1,int nskip2)530 void SiftGPUEX::DisplayPyramid( void (*UseDisplayShader)(), int dataName, int nskip1, int nskip2)
531 {
532
533 if(_pyramid == NULL)return;
534 int grid_sz = (_level_num -nskip1 - nskip2);
535 if(grid_sz > 4) grid_sz = (int)ceil(grid_sz*0.5);
536 double scale = 1.0/grid_sz;
537 int stepx = 0, stepy = 0, dx, dy=0, nstep;
538
539 if(_pyramid->_octave_min >0) scale *= (1<<_pyramid->_octave_min);
540 else if(_pyramid->_octave_min < 0) scale /= (1<<(-_pyramid->_octave_min));
541
542
543 glPushMatrix();
544 glScaled(scale, scale, scale);
545
546 for(int i = _pyramid->_octave_min; i < _pyramid->_octave_min+_pyramid->_octave_num; i++)
547 {
548
549 nstep = i==_pyramid->_octave_min? grid_sz: _level_num;
550 dx = 0;
551 UseDisplayShader();
552 for(int j = _level_min + nskip1; j <= _level_max-nskip2; j++)
553 {
554 GLTexImage * tex = _pyramid->GetLevelTexture(i, j, dataName);
555 if(tex->GetImgWidth() == 0 || tex->GetImgHeight() == 0) continue;
556 stepx = tex->GetImgWidth();
557 stepy = tex->GetImgHeight();
558 ////
559 if(j == _level_min + nskip1 + nstep)
560 {
561 dy += stepy;
562 dx = 0;
563 }
564
565 glPushMatrix();
566 glTranslated(dx, dy, 0);
567 tex->BindTex();
568 tex->DrawImage();
569 tex->UnbindTex();
570 glPopMatrix();
571
572 dx += stepx;
573
574 }
575
576 ShaderMan::UnloadProgram();
577
578 dy+= stepy;
579 }
580
581 glPopMatrix();
582 }
583
584
DisplayLevel(void (* UseDisplayShader)(),int i)585 void SiftGPUEX::DisplayLevel(void (*UseDisplayShader)(), int i)
586 {
587 if(_pyramid == NULL)return;
588
589 i = i%(_level_num * _pyramid->_octave_num);
590 if (i<0 ) i+= (_level_num * _pyramid->_octave_num);
591 int octave = _pyramid->_octave_min + i/_level_num;
592 int level = _level_min + i%_level_num;
593 double scale = 1.0;
594
595 if(octave >0) scale *= (1<<octave);
596 else if(octave < 0) scale /= (1<<(-octave));
597
598 GLTexImage * tex = _pyramid->GetLevelTexture(octave, level);
599
600 UseDisplayShader();
601
602 glPushMatrix();
603 glScaled(scale, scale, scale);
604 tex->BindTex();
605 tex->DrawImage();
606 tex->UnbindTex();
607 glPopMatrix();
608 ShaderMan::UnloadProgram();
609 }
610
DisplaySIFT()611 void SiftGPUEX::DisplaySIFT()
612 {
613 if(_pyramid == NULL) return;
614 glEnable(GlobalUtil::_texTarget);
615 switch(_view)
616 {
617 case 0:
618 DisplayInput();
619 DisplayFeatureBox(_sub_view);
620 break;
621 case 1:
622 DisplayPyramid(ShaderMan::UseShaderDisplayGaussian, SiftPyramid::DATA_GAUSSIAN);
623 break;
624 case 2:
625 DisplayOctave(ShaderMan::UseShaderDisplayGaussian, _sub_view);
626 break;
627 case 3:
628 DisplayLevel(ShaderMan::UseShaderDisplayGaussian, _sub_view);
629 break;
630 case 4:
631 DisplayPyramid(ShaderMan::UseShaderDisplayDOG, SiftPyramid::DATA_DOG, 1);
632 break;
633 case 5:
634 DisplayPyramid(ShaderMan::UseShaderDisplayGrad, SiftPyramid::DATA_GRAD, 1);
635 break;
636 case 6:
637 DisplayPyramid(ShaderMan::UseShaderDisplayDOG, SiftPyramid::DATA_DOG,2, 1);
638 DisplayPyramid(ShaderMan::UseShaderDisplayKeypoints, SiftPyramid::DATA_KEYPOINT, 2,1);
639 }
640 }
641
642
SetView(int view,int sub_view,char * title)643 void SiftGPUEX::SetView(int view, int sub_view, char *title)
644 {
645 const char* view_titles[] =
646 {
647 "Original Image",
648 "Gaussian Pyramid",
649 "Octave Images",
650 "Level Image",
651 "Difference of Gaussian",
652 "Gradient",
653 "Keypoints"
654 };
655 const int view_num = 7;
656 _view = view % view_num;
657 if(_view <0) _view +=view_num;
658 _sub_view = sub_view;
659
660 if(_view_debug)
661 strcpy(title, "Debug...");
662 else
663 strcpy(title, view_titles[_view]);
664
665 }
666
667
PrintUsage()668 void SiftGPU::PrintUsage()
669 {
670 std::cout
671 <<"SiftGPU Usage:\n"
672 <<"-h -help : Parameter information\n"
673 <<"-i <strings> : Filename(s) of the input image(s)\n"
674 <<"-il <string> : Filename of an image list file\n"
675 <<"-o <string> : Where to save SIFT features\n"
676 <<"-f <float> : Filter width factor; Width will be 2*factor+1 (default : 4.0)\n"
677 <<"-w <float> : Orientation sample window factor (default: 2.0)\n"
678 <<"-dw <float> * : Descriptor grid size factor (default : 3.0)\n"
679 <<"-fo <int> * : First octave to detect DOG keypoints(default : 0)\n"
680 <<"-no <int> : Maximum number of Octaves (default : no limit)\n"
681 <<"-d <int> : Number of DOG levels in an octave (default : 3)\n"
682 <<"-t <float> : DOG threshold (default : 0.02/3)\n"
683 <<"-e <float> : Edge Threshold (default : 10.0)\n"
684 <<"-m <int=2> : Multi Feature Orientations (default : 1)\n"
685 <<"-m2p : 2 Orientations packed as one float\n"
686 <<"-s <int=1> : Sub-Pixel, Sub-Scale Localization, Multi-Refinement(num)\n"
687 <<"-lcpu -lc <int> : CPU/GPU mixed Feature List Generation (default: 6)\n"
688 <<" Use GPU first, and use CPU when reduction size <= pow(2,num)\n"
689 <<" When <num> is missing or equals -1, no GPU will be used\n"
690 <<"-noprep : Upload raw data to GPU (default: RGB->LUM and down-sample on CPU)\n"
691 <<"-sd : Skip descriptor computation if specified\n"
692 <<"-unn * : Write unnormalized descriptor if specified\n"
693 <<"-b * : Write binary sift file if specified\n"
694 <<"-fs <int> : Block Size for freature storage <default : 4>\n"
695 <<"-cuda <int=0> : Use CUDA SiftGPU, and specify the device index\n"
696 <<"-tight : Automatically resize pyramid to fit new images tightly\n"
697 <<"-p <W>x<H> : Inititialize the pyramids to contain image of WxH (eg -p 1024x768)\n"
698 <<"-tc[1|2|3] <int> *: Threshold for limiting the overall number of features (3 methods)\n"
699 <<"-v <int> : Level of timing details. Same as calling Setverbose() function\n"
700 <<"-loweo : (0, 0) at center of top-left pixel (default: corner)\n"
701 <<"-maxd <int> * : Max working dimension (default : 2560 (unpacked) / 3200 (packed))\n"
702 <<"-nomc : Disabling auto-downsamping that try to fit GPU memory cap\n"
703 <<"-exit : Exit program after processing the input image\n"
704 <<"-unpack : Use the old unpacked implementation\n"
705 <<"-di : Use dynamic array indexing if available (default : no)\n"
706 <<" It could make computation faster on cards like GTX 280\n"
707 <<"-ofix * : use 0 as feature orientations.\n"
708 <<"-ofix-not * : disable -ofix.\n"
709 <<"-winpos <X>x<Y> * : Screen coordinate used in Win32 to select monitor/GPU.\n"
710 <<"-display <string>*: Display name used in Linux/Mac to select monitor/GPU.\n"
711 <<"\n"
712 <<"NOTE: parameters marked with * can be changed after initialization\n"
713 <<"\n";
714 }
715
ParseParam(const int argc,const char ** argv)716 void SiftGPU::ParseParam(const int argc, const char **argv)
717 {
718 #define CHAR1_TO_INT(x) ((x >= 'A' && x <= 'Z') ? x + 32 : x)
719 #define CHAR2_TO_INT(str, i) (str[i] ? CHAR1_TO_INT(str[i]) + (CHAR1_TO_INT(str[i+1]) << 8) : 0)
720 #define CHAR3_TO_INT(str, i) (str[i] ? CHAR1_TO_INT(str[i]) + (CHAR2_TO_INT(str, i + 1) << 8) : 0)
721 #define STRING_TO_INT(str) (CHAR1_TO_INT(str[0]) + (CHAR3_TO_INT(str, 1) << 8))
722
723 #ifdef _MSC_VER
724 //charizing is microsoft only
725 #define MAKEINT1(a) (#@a )
726 #else
727 #define mychar0 '0'
728 #define mychar1 '1'
729 #define mychar2 '2'
730 #define mychar3 '3'
731 #define mychara 'a'
732 #define mycharb 'b'
733 #define mycharc 'c'
734 #define mychard 'd'
735 #define mychare 'e'
736 #define mycharf 'f'
737 #define mycharg 'g'
738 #define mycharh 'h'
739 #define mychari 'i'
740 #define mycharj 'j'
741 #define mychark 'k'
742 #define mycharl 'l'
743 #define mycharm 'm'
744 #define mycharn 'n'
745 #define mycharo 'o'
746 #define mycharp 'p'
747 #define mycharq 'q'
748 #define mycharr 'r'
749 #define mychars 's'
750 #define mychart 't'
751 #define mycharu 'u'
752 #define mycharv 'v'
753 #define mycharw 'w'
754 #define mycharx 'x'
755 #define mychary 'y'
756 #define mycharz 'z'
757 #define MAKEINT1(a) (mychar##a )
758 #endif
759 #define MAKEINT2(a, b) (MAKEINT1(a) + (MAKEINT1(b) << 8))
760 #define MAKEINT3(a, b, c) (MAKEINT1(a) + (MAKEINT2(b, c) << 8))
761 #define MAKEINT4(a, b, c, d) (MAKEINT1(a) + (MAKEINT3(b, c, d) << 8))
762
763
764 const char* arg, *param, * opt;
765 int setMaxD = 0, opti;
766 for(int i = 0; i< argc; i++)
767 {
768 arg = argv[i];
769 if(arg == NULL || arg[0] != '-' || !arg[1])continue;
770 opt = arg+1;
771 opti = STRING_TO_INT(opt);
772 param = argv[i+1];
773
774 ////////////////////////////////
775 switch(opti)
776 {
777 case MAKEINT1(h):
778 case MAKEINT4(h, e, l, p):
779 PrintUsage();
780 break;
781 case MAKEINT4(c, u, d, a):
782 #if defined(CUDA_SIFTGPU_ENABLED)
783
784 if(!_initialized)
785 {
786 GlobalUtil::_UseCUDA = 1;
787 int device = -1;
788 if(i+1 <argc && sscanf(param, "%d", &device) && device >=0)
789 {
790 GlobalUtil::_DeviceIndex = device;
791 i++;
792 }
793 }
794 #else
795 std::cerr << "---------------------------------------------------------------------------\n"
796 << "CUDA not supported in this binary! To enable it, please use SiftGPU_CUDA_Enable\n"
797 << "solution for VS2005+ or set siftgpu_enable_cuda to 1 in makefile\n"
798 << "----------------------------------------------------------------------------\n";
799 #endif
800 break;
801 case MAKEINT2(c, l):
802 #if defined(CL_SIFTGPU_ENABLED)
803 if(!_initialized) GlobalUtil::_UseOpenCL = 1;
804 #else
805 std::cerr << "---------------------------------------------------------------------------\n"
806 << "OpenCL not supported in this binary! Define CL_CUDA_SIFTGPU_ENABLED to..\n"
807 << "----------------------------------------------------------------------------\n";
808 #endif
809 break;
810
811 case MAKEINT4(p, a, c, k):
812 if(!_initialized) GlobalUtil::_usePackedTex = 1;
813 break;
814 case MAKEINT4(u, n, p, a): //unpack
815 if(!_initialized)
816 {
817 GlobalUtil::_usePackedTex = 0;
818 if(!setMaxD) GlobalUtil::_texMaxDim = 2560;
819 }
820 break;
821 case MAKEINT4(l, c, p, u):
822 case MAKEINT2(l, c):
823 if(!_initialized)
824 {
825 int gskip = -1;
826 if(i+1 <argc) sscanf(param, "%d", &gskip);
827 if(gskip >= 0)
828 {
829 GlobalUtil::_ListGenSkipGPU = gskip;
830 }else
831 {
832 GlobalUtil::_ListGenGPU = 0;
833 }
834 }
835 break;
836 case MAKEINT4(p, r, e, p):
837 GlobalUtil::_PreProcessOnCPU = 1;
838 break;
839 case MAKEINT4(n, o, p, r): //noprep
840 GlobalUtil::_PreProcessOnCPU = 0;
841 break;
842 case MAKEINT4(f, b, o, 1):
843 FrameBufferObject::UseSingleFBO =1;
844 break;
845 case MAKEINT4(f, b, o, s):
846 FrameBufferObject::UseSingleFBO = 0;
847 break;
848 case MAKEINT2(s, d):
849 if(!_initialized) GlobalUtil::_DescriptorPPT =0;
850 break;
851 case MAKEINT3(u, n, n):
852 GlobalUtil::_NormalizedSIFT =0;
853 break;
854 case MAKEINT4(n, d, e, s):
855 GlobalUtil::_NormalizedSIFT =1;
856 break;
857 case MAKEINT1(b):
858 GlobalUtil::_BinarySIFT = 1;
859 break;
860 case MAKEINT4(t, i, g, h): //tight
861 GlobalUtil::_ForceTightPyramid = 1;
862 break;
863 case MAKEINT4(e, x, i, t):
864 GlobalUtil::_ExitAfterSIFT = 1;
865 break;
866 case MAKEINT2(d, i):
867 GlobalUtil::_UseDynamicIndexing = 1;
868 break;
869 case MAKEINT4(s, i, g, n):
870 if(!_initialized || GlobalUtil::_UseCUDA) GlobalUtil::_KeepExtremumSign = 1;
871 break;
872 case MAKEINT1(m):
873 case MAKEINT2(m, o):
874 if(!_initialized)
875 {
876 int mo = 2; //default multi-orientation
877 if(i+1 <argc) sscanf(param, "%d", &mo);
878 //at least two orientation
879 GlobalUtil::_MaxOrientation = min(max(1, mo), 4);
880 }
881 break;
882 case MAKEINT3(m, 2, p):
883 if(!_initialized)
884 {
885 GlobalUtil::_MaxOrientation = 2;
886 GlobalUtil::_OrientationPack2 = 1;
887 }
888 break;
889 case MAKEINT1(s):
890 if(!_initialized)
891 {
892 int sp = 1; //default refinement
893 if(i+1 <argc) sscanf(param, "%d", &sp);
894 //at least two orientation
895 GlobalUtil::_SubpixelLocalization = min(max(0, sp),5);
896 }
897 break;
898 case MAKEINT4(o, f, i, x):
899 GlobalUtil::_FixedOrientation = (_stricmp(opt, "ofix")==0);
900 break;
901 case MAKEINT4(l, o, w, e): // loweo
902 GlobalUtil::_LoweOrigin = 1;
903 break;
904 case MAKEINT4(n, a, r, r): // narrow
905 GlobalUtil::_NarrowFeatureTex = 1;
906 break;
907 case MAKEINT4(d, e, b, u): // debug
908 GlobalUtil::_debug = 1;
909 break;
910 case MAKEINT2(k, 0):
911 GlobalUtil::_KeyPointListForceLevel0 = 1;
912 break;
913 case MAKEINT2(k, x):
914 GlobalUtil::_KeyPointListForceLevel0 = 0;
915 break;
916 case MAKEINT2(d, a):
917 GlobalUtil::_DarknessAdaption = 1;
918 break;
919 case MAKEINT3(f, m, c):
920 GlobalUtil::_FitMemoryCap = 1;
921 break;
922 case MAKEINT4(n, o, m, c):
923 GlobalUtil::_FitMemoryCap = 0;
924 break;
925 default:
926 if(i + 1 >= argc) break;
927 switch(opti)
928 {
929 case MAKEINT1(i):
930 strcpy(_imgpath, param);
931 i++;
932 //get the file list..
933 _list->push_back(param);
934 while( i+1 < argc && argv[i+1][0] !='-')
935 {
936 _list->push_back(argv[++i]);
937 }
938 break;
939 case MAKEINT2(i, l):
940 LoadImageList(param);
941 i++;
942 break;
943 case MAKEINT1(o):
944 strcpy(_outpath, param);
945 i++;
946 break;
947 case MAKEINT1(f):
948 {
949 float factor = 0.0f;
950 if(sscanf(param, "%f", &factor) && factor > 0 )
951 {
952 GlobalUtil::_FilterWidthFactor = factor;
953 i++;
954 }
955 }
956 break;
957 case MAKEINT2(o, t):
958 {
959 float factor = 0.0f;
960 if(sscanf(param, "%f", &factor) && factor>0 )
961 {
962 GlobalUtil::_MulitiOrientationThreshold = factor;
963 i++;
964 }
965 break;
966 }
967 case MAKEINT1(w):
968 {
969 float factor = 0.0f;
970 if(sscanf(param, "%f", &factor) && factor>0 )
971 {
972 GlobalUtil::_OrientationWindowFactor = factor;
973 i++;
974 }
975 break;
976 }
977 case MAKEINT2(d, w):
978 {
979 float factor = 0.0f;
980 if(sscanf(param, "%f", &factor) && factor > 0 )
981 {
982 GlobalUtil::_DescriptorWindowFactor = factor;
983 i++;
984 }
985 break;
986 }
987 case MAKEINT2(f, o):
988 {
989 int first_octave = -3;
990 if(sscanf(param, "%d", &first_octave) && first_octave >=-2 )
991 {
992 GlobalUtil::_octave_min_default = first_octave;
993 i++;
994 }
995 break;
996 }
997 case MAKEINT2(n, o):
998 if(!_initialized)
999 {
1000 int octave_num=-1;
1001 if(sscanf(param, "%d", &octave_num))
1002 {
1003 octave_num = max(-1, octave_num);
1004 if(octave_num ==-1 || octave_num >=1)
1005 {
1006 GlobalUtil::_octave_num_default = octave_num;
1007 i++;
1008 }
1009 }
1010 }
1011 break;
1012 case MAKEINT1(t):
1013 {
1014 float threshold = 0.0f;
1015 if(sscanf(param, "%f", &threshold) && threshold >0 && threshold < 0.5f)
1016 {
1017 SiftParam::_dog_threshold = threshold;
1018 i++;
1019 }
1020 break;
1021 }
1022 case MAKEINT1(e):
1023 {
1024 float threshold = 0.0f;
1025 if(sscanf(param, "%f", &threshold) && threshold >0 )
1026 {
1027 SiftParam::_edge_threshold = threshold;
1028 i++;
1029 }
1030 break;
1031 }
1032 case MAKEINT1(d):
1033 {
1034 int num = 0;
1035 if(sscanf(param, "%d", &num) && num >=1 && num <=10)
1036 {
1037 SiftParam::_dog_level_num = num;
1038 i++;
1039 }
1040 break;
1041 }
1042 case MAKEINT2(f, s):
1043 {
1044 int num = 0;
1045 if(sscanf(param, "%d", &num) && num >=1)
1046 {
1047 GlobalParam::_FeatureTexBlock = num;
1048 i++;
1049 }
1050 break;
1051 }
1052 case MAKEINT1(p):
1053 {
1054 int w =0, h=0;
1055 if(sscanf(param, "%dx%d", &w, &h) == 2 && w >0 && h>0)
1056 {
1057 GlobalParam::_InitPyramidWidth = w;
1058 GlobalParam::_InitPyramidHeight = h;
1059 i++;
1060 }
1061 break;
1062 }
1063 case MAKEINT4(w, i, n, p): //winpos
1064 {
1065 int x =0, y=0;
1066 if(sscanf(param, "%dx%d", &x, &y) == 2)
1067 {
1068 GlobalParam::_WindowInitX = x;
1069 GlobalParam::_WindowInitY = y;
1070 i++;
1071 }
1072 break;
1073 }
1074 case MAKEINT4(d, i, s, p): //display
1075 {
1076 GlobalParam::_WindowDisplay = param;
1077 i++;
1078 break;
1079 }
1080 case MAKEINT2(l, m):
1081 {
1082 int num = 0;
1083 if(sscanf(param, "%d", &num) && num >=1000)
1084 {
1085 GlobalParam::_MaxLevelFeatureNum = num;
1086 i++;
1087 }
1088 break;
1089 }
1090 case MAKEINT3(l, m, p):
1091 {
1092 float num = 0.0f;
1093 if(sscanf(param, "%f", &num) && num >=0.001)
1094 {
1095 GlobalParam::_MaxFeaturePercent = num;
1096 i++;
1097 }
1098 break;
1099 }
1100 case MAKEINT3(t, c, 2): //downward
1101 case MAKEINT3(t, c, 3):
1102 case MAKEINT2(t, c): //tc
1103 case MAKEINT3(t, c, 1): //
1104 {
1105 switch (opti)
1106 {
1107 case MAKEINT3(t, c, 2): GlobalUtil::_TruncateMethod = 1; break;
1108 case MAKEINT3(t, c, 3): GlobalUtil::_TruncateMethod = 2; break;
1109 default: GlobalUtil::_TruncateMethod = 0; break;
1110 }
1111 int num = -1;
1112 if(sscanf(param, "%d", &num) && num > 0)
1113 {
1114 GlobalParam::_FeatureCountThreshold = num;
1115 i++;
1116 }
1117 break;
1118 }
1119 case MAKEINT1(v):
1120 {
1121 int num = 0;
1122 if(sscanf(param, "%d", &num) && num >=0 && num <= 4)
1123 {
1124 SetVerbose(num);
1125 }
1126 break;
1127 }
1128 case MAKEINT4(m, a, x, d):
1129 {
1130 int num = 0;
1131 if(sscanf(param, "%d", &num) && num > 0)
1132 {
1133 GlobalUtil::_texMaxDim = num;
1134 setMaxD = 1;
1135 }
1136 break;
1137 }
1138 case MAKEINT4(m, i, n, d):
1139 {
1140 int num = 0;
1141 if(sscanf(param, "%d", &num) && num >= 8)
1142 {
1143 GlobalUtil::_texMinDim = num;
1144 }
1145 break;
1146 }
1147 default:
1148 break;
1149 }
1150 break;
1151 }
1152 }
1153
1154 ////////////////////////
1155 GlobalUtil::SelectDisplay();
1156
1157
1158 //do not write result if there are more than one input images
1159 if(_outpath[0] && _list->size()>1) _outpath[0] = 0;
1160
1161 }
1162
SetImageList(int nimage,const char ** filelist)1163 void SiftGPU::SetImageList(int nimage, const char** filelist)
1164 {
1165 _list->resize(0);
1166 for(int i = 0; i < nimage; i++)
1167 {
1168 _list->push_back(filelist[i]);
1169 }
1170 _current = 0;
1171
1172 }
LoadImageList(const char * imlist)1173 void SiftGPU:: LoadImageList(const char *imlist)
1174 {
1175 char filename[_MAX_PATH];
1176 ifstream in(imlist);
1177 while(in>>filename)
1178 {
1179 _list->push_back(filename);
1180 }
1181 in.close();
1182
1183
1184 if(_list->size()>0)
1185 {
1186 strcpy(_imgpath, _list->at(0).data());
1187 strcpy(filename, imlist);
1188 char * slash = strrchr(filename, '\\');
1189 if(slash == 0) slash = strrchr(filename, '/');
1190 if(slash )
1191 {
1192 slash[1] = 0;
1193 chdir(filename);
1194 }
1195 }
1196 _image_loaded = 0;
1197
1198
1199 }
GetLevelSigma(int lev)1200 float SiftParam::GetLevelSigma( int lev)
1201 {
1202 return _sigma0 * powf( 2.0f, float(lev) / float(_dog_level_num )); //bug fix 9/12/2007
1203 }
1204
1205
1206
DisplayFeatureBox(int view)1207 void SiftGPUEX::DisplayFeatureBox(int view )
1208 {
1209 view = view%3;
1210 if(view<0)view+=3;
1211 if(view ==2) return;
1212 int idx = 0;
1213 const int *fnum = _pyramid->GetLevelFeatureNum();
1214 const GLuint *vbo = _pyramid->GetFeatureDipslayVBO();
1215 const GLuint *vbop = _pyramid->GetPointDisplayVBO();
1216 if(vbo == NULL || vbop == NULL) return;
1217 //int nvbo = _dog_level_num * _pyramid->_octave_num;
1218 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1219 glEnableClientState(GL_VERTEX_ARRAY);
1220 glPushMatrix();
1221 // glTranslatef(0.0f, 0.0f, -1.0f);
1222 glPointSize(2.0f);
1223
1224 float scale = 1.0f;
1225 if(_pyramid->_octave_min >0) scale *= (1<<_pyramid->_octave_min);
1226 else if(_pyramid->_octave_min < 0) scale /= (1<<(-_pyramid->_octave_min));
1227 glScalef(scale, scale, 1.0f);
1228
1229
1230 for(int i = 0; i < _pyramid->_octave_num; i++)
1231 {
1232
1233 for(int j = 0; j < _dog_level_num; j++, idx++)
1234 {
1235 if(fnum[idx]>0)
1236 {
1237 if(view ==0)
1238 {
1239 glColor3f(0.2f, 1.0f, 0.2f);
1240 glBindBuffer(GL_ARRAY_BUFFER_ARB, vbop[idx]);
1241 glVertexPointer( 4, GL_FLOAT,4*sizeof(float), (char *) 0);
1242 glDrawArrays( GL_POINTS, 0, fnum[idx]);
1243 glFlush();
1244 }else
1245 {
1246
1247 //glColor3f(1.0f, 0.0f, 0.0f);
1248 glColor3fv(_colors+ (idx%COLOR_NUM)*3);
1249 glBindBuffer(GL_ARRAY_BUFFER_ARB, vbo[idx]);
1250 glVertexPointer( 4, GL_FLOAT,4*sizeof(float), (char *) 0);
1251 glDrawArrays( GL_LINES, 0, fnum[idx]*10 );
1252 glFlush();
1253 }
1254
1255 }
1256
1257 }
1258 glTranslatef(-.5f, -.5f, 0.0f);
1259 glScalef(2.0f, 2.0f, 1.0f);
1260
1261 }
1262 glPopMatrix();
1263 glDisableClientState(GL_VERTEX_ARRAY);
1264 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1265 glPointSize(1.0f);
1266
1267 }
1268
ToggleDisplayDebug()1269 void SiftGPUEX::ToggleDisplayDebug()
1270 {
1271 _view_debug = !_view_debug;
1272 }
1273
DisplayDebug()1274 void SiftGPUEX::DisplayDebug()
1275 {
1276 glPointSize(1.0f);
1277 glColor3f(1.0f, 0.0f, 0.0f);
1278 ShaderMan::UseShaderDebug();
1279 glBegin(GL_POINTS);
1280 for(int i = 0; i < 100; i++)
1281 {
1282 glVertex2f(i*4.0f+0.5f, i*4.0f+0.5f);
1283 }
1284 glEnd();
1285 ShaderMan::UnloadProgram();
1286 }
1287
CreateContextGL()1288 int SiftGPU::CreateContextGL()
1289 {
1290 if(GlobalUtil::_UseOpenCL || GlobalUtil::_UseCUDA)
1291 {
1292 //do nothing
1293 }
1294 else if(!GlobalUtil::CreateWindowEZ())
1295 {
1296 #if CUDA_SIFTGPU_ENABLED
1297 GlobalUtil::_UseCUDA = 1;
1298 #else
1299 return 0;
1300 #endif
1301 }
1302
1303 return VerifyContextGL();
1304 }
1305
VerifyContextGL()1306 int SiftGPU::VerifyContextGL()
1307 {
1308 InitSiftGPU();
1309 return (GlobalUtil::_GoodOpenGL > 0) + GlobalUtil::_FullSupported;
1310 }
1311
IsFullSupported()1312 int SiftGPU::IsFullSupported()
1313 {
1314 return GlobalUtil::_GoodOpenGL > 0 && GlobalUtil::_FullSupported;
1315 }
1316
SaveSIFT(const char * szFileName)1317 void SiftGPU::SaveSIFT(const char * szFileName)
1318 {
1319 _pyramid->SaveSIFT(szFileName);
1320 }
1321
GetFeatureNum()1322 int SiftGPU::GetFeatureNum()
1323 {
1324 return _pyramid->GetFeatureNum();
1325 }
1326
GetFeatureVector(SiftKeypoint * keys,float * descriptors)1327 void SiftGPU::GetFeatureVector(SiftKeypoint * keys, float * descriptors)
1328 {
1329 // keys.resize(_pyramid->GetFeatureNum());
1330 if(GlobalUtil::_DescriptorPPT)
1331 {
1332 // descriptors.resize(128*_pyramid->GetFeatureNum());
1333 _pyramid->CopyFeatureVector((float*) (&keys[0]), &descriptors[0]);
1334 }else
1335 {
1336 //descriptors.resize(0);
1337 _pyramid->CopyFeatureVector((float*) (&keys[0]), NULL);
1338 }
1339 }
1340
SetTightPyramid(int tight)1341 void SiftGPU::SetTightPyramid(int tight)
1342 {
1343 GlobalUtil::_ForceTightPyramid = tight;
1344 }
1345
AllocatePyramid(int width,int height)1346 int SiftGPU::AllocatePyramid(int width, int height)
1347 {
1348 _pyramid->_down_sample_factor = 0;
1349 _pyramid->_octave_min = GlobalUtil::_octave_min_default;
1350 if(GlobalUtil::_octave_min_default>=0)
1351 {
1352 width >>= GlobalUtil::_octave_min_default;
1353 height >>= GlobalUtil::_octave_min_default;
1354 }else
1355 {
1356 width <<= (-GlobalUtil::_octave_min_default);
1357 height <<= (-GlobalUtil::_octave_min_default);
1358 }
1359 _pyramid->ResizePyramid(width, height);
1360 return _pyramid->_pyramid_height == height && width == _pyramid->_pyramid_width ;
1361 }
1362
SetMaxDimension(int sz)1363 void SiftGPU::SetMaxDimension(int sz)
1364 {
1365 if(sz < GlobalUtil::_texMaxDimGL)
1366 {
1367 GlobalUtil::_texMaxDim = sz;
1368 }
1369 }
1370
GetFeatureCountThreshold()1371 int SiftGPU::GetFeatureCountThreshold()
1372 {
1373 return GlobalParam::_FeatureCountThreshold;
1374 }
1375
GetMaxOrientation()1376 int SiftGPU::GetMaxOrientation()
1377 {
1378 return GlobalParam::_MaxOrientation;
1379 }
1380
GetMaxDimension()1381 int SiftGPU::GetMaxDimension()
1382 {
1383 return GlobalUtil::_texMaxDim;
1384 }
1385
GetImageCount()1386 int SiftGPU::GetImageCount()
1387 {
1388 return _list->size();
1389 }
1390
HSVtoRGB(float hsv[3],float rgb[3])1391 void SiftGPUEX::HSVtoRGB(float hsv[3],float rgb[3] )
1392 {
1393
1394 int i;
1395 float q, t, p;
1396 float hh,f, v = hsv[2];
1397 if(hsv[1]==0.0f)
1398 {
1399 rgb[0]=rgb[1]=rgb[2]=v;
1400 }
1401 else
1402 {
1403 //////////////
1404 hh =hsv[0]*6.0f ; // sector 0 to 5
1405 i =(int)hh ;
1406 f = hh- i; // factorial part of h
1407 //////////
1408 p= v * ( 1 - hsv[1] );
1409 q = v * ( 1 - hsv[1] * f );
1410 t = v * ( 1 - hsv[1] * ( 1 - f ) );
1411 switch( i ) {
1412 case 0:rgb[0] = v;rgb[1] = t;rgb[2] = p;break;
1413 case 1:rgb[0] = q;rgb[1] = v;rgb[2] = p;break;
1414 case 2:rgb[0] = p;rgb[1] = v;rgb[2] = t;break;
1415 case 3:rgb[0] = p;rgb[1] = q;rgb[2] = v;break;
1416 case 4:rgb[0] = t;rgb[1] = p;rgb[2] = v;break;
1417 case 5:rgb[0] = v;rgb[1] = p;rgb[2] = q;break;
1418 default:rgb[0]= 0;rgb[1] = 0;rgb[2] = 0;
1419 }
1420 }
1421 }
1422
GetImageDimension(int & w,int & h)1423 void SiftGPUEX::GetImageDimension( int &w, int &h)
1424 {
1425 w = _texImage->GetImgWidth();
1426 h = _texImage->GetImgHeight();
1427
1428 }
1429
GetInitWindowPotition(int & x,int & y)1430 void SiftGPUEX::GetInitWindowPotition(int&x, int&y)
1431 {
1432 x = GlobalUtil::_WindowInitX;
1433 y = GlobalUtil::_WindowInitY;
1434 }
1435
CreateNewSiftGPU(int np)1436 SiftGPU* CreateNewSiftGPU(int np)
1437 {
1438 return new SiftGPU(np);
1439 }
1440
1441 /////////////////////////////////////////////////////
operator new(size_t size)1442 void* ComboSiftGPU::operator new (size_t size){
1443 void * p = malloc(size);
1444 if (p == 0)
1445 {
1446 const std::bad_alloc ba;
1447 throw ba;
1448 }
1449 return p;
1450 }
1451
CreateComboSiftGPU()1452 ComboSiftGPU* CreateComboSiftGPU()
1453 {
1454 return new ComboSiftGPU();
1455 }
1456
1457