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