root / rgbdslam / external / siftgpu / src / SiftGPU / SiftGPU.cpp @ 9240aaa3
History | View | Annotate | Download (38.3 KB)
1 | 9240aaa3 | Alex | ////////////////////////////////////////////////////////////////////////////
|
---|---|---|---|
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 | } |