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 |
|