ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
PyramidCL.cpp
Go to the documentation of this file.
1 // File: PyramidCL.cpp
3 // Author: Changchang Wu
4 // Description : implementation of the PyramidCL class.
5 // OpenCL-based implementation of SiftPyramid
6 //
7 // Copyright (c) 2007 University of North Carolina at Chapel Hill
8 // All Rights Reserved
9 //
10 // Permission to use, copy, modify and distribute this software and its
11 // documentation for educational, research and non-profit purposes, without
12 // fee, and without a written agreement is hereby granted, provided that the
13 // above copyright notice and the following paragraph appear in all copies.
14 //
15 // The University of North Carolina at Chapel Hill make no representations
16 // about the suitability of this software for any purpose. It is provided
17 // 'as is' without express or implied warranty.
18 //
19 // Please send BUG REPORTS to ccwu@cs.unc.edu
20 //
22 
23 #if defined(CL_SIFTGPU_ENABLED)
24 
25 
26 #include "GL/glew.h"
27 #include <CL/OpenCL.h>
28 #include <iostream>
29 #include <vector>
30 #include <algorithm>
31 #include <stdlib.h>
32 #include <math.h>
33 using namespace std;
34 
35 #include "GlobalUtil.h"
36 #include "GLTexImage.h"
37 #include "CLTexImage.h"
38 #include "SiftGPU.h"
39 #include "SiftPyramid.h"
40 #include "ProgramCL.h"
41 #include "PyramidCL.h"
42 
43 
44 #define USE_TIMING() double t, t0, tt;
45 #define OCTAVE_START() if(GlobalUtil::_timingO){ t = t0 = CLOCK(); cout<<"#"<<i+_down_sample_factor<<"\t"; }
46 #define LEVEL_FINISH() if(GlobalUtil::_timingL){ _OpenCL->FinishCL(); tt = CLOCK();cout<<(tt-t)<<"\t"; t = CLOCK();}
47 #define OCTAVE_FINISH() if(GlobalUtil::_timingO)cout<<"|\t"<<(CLOCK()-t0)<<endl;
48 
49 
50 PyramidCL::PyramidCL(SiftParam& sp) : SiftPyramid(sp)
51 {
52  _allPyramid = NULL;
53  _histoPyramidTex = NULL;
54  _featureTex = NULL;
55  _descriptorTex = NULL;
56  _orientationTex = NULL;
57  _bufferTEX = NULL;
58  if(GlobalUtil::_usePackedTex) _OpenCL = new ProgramBagCL();
59  else _OpenCL = new ProgramBagCLN();
60  _OpenCL->InitProgramBag(sp);
61  _inputTex = new CLTexImage( _OpenCL->GetContextCL(),
62  _OpenCL->GetCommandQueue());
64  InitializeContext();
65 }
66 
67 PyramidCL::~PyramidCL()
68 {
69  DestroyPerLevelData();
70  DestroySharedData();
71  DestroyPyramidData();
72  if(_OpenCL) delete _OpenCL;
73  if(_inputTex) delete _inputTex;
74  if(_bufferTEX) delete _bufferTEX;
75 }
76 
77 void PyramidCL::InitializeContext()
78 {
80 }
81 
82 void PyramidCL::InitPyramid(int w, int h, int ds)
83 {
84  int wp, hp, toobig = 0;
85  if(ds == 0)
86  {
87  _down_sample_factor = 0;
89  {
90  wp = w >> _octave_min_default;
91  hp = h >> _octave_min_default;
92  }else
93  {
94  //can't upsample by more than 8
95  _octave_min_default = max(-3, _octave_min_default);
96  //
97  wp = w << (-_octave_min_default);
98  hp = h << (-_octave_min_default);
99  }
100  _octave_min = _octave_min_default;
101  }else
102  {
103  //must use 0 as _octave_min;
104  _octave_min = 0;
105  _down_sample_factor = ds;
106  w >>= ds;
107  h >>= ds;
108  wp = w;
109  hp = h;
110  }
111 
113  {
114  _octave_min ++;
115  wp >>= 1;
116  hp >>= 1;
117  toobig = 1;
118  }
119  if(toobig && GlobalUtil::_verbose && _octave_min > 0)
120  {
121  std::cout<< "**************************************************************\n"
122  "Image larger than allowed dimension, data will be downsampled!\n"
123  "use -maxd to change the settings\n"
124  "***************************************************************\n";
125  }
126 
127  if( wp == _pyramid_width && hp == _pyramid_height && _allocated )
128  {
129  FitPyramid(wp, hp);
130  }else if(GlobalUtil::_ForceTightPyramid || _allocated ==0)
131  {
132  ResizePyramid(wp, hp);
133  }
134  else if( wp > _pyramid_width || hp > _pyramid_height )
135  {
136  ResizePyramid(max(wp, _pyramid_width), max(hp, _pyramid_height));
137  if(wp < _pyramid_width || hp < _pyramid_height) FitPyramid(wp, hp);
138  }
139  else
140  {
141  //try use the pyramid allocated for large image on small input images
142  FitPyramid(wp, hp);
143  }
144 
145  _OpenCL->SelectInitialSmoothingFilter(_octave_min + _down_sample_factor, param);
146 }
147 
148 void PyramidCL::ResizePyramid(int w, int h)
149 {
150  //
151  unsigned int totalkb = 0;
152  int _octave_num_new, input_sz, i, j;
153  //
154 
155  if(_pyramid_width == w && _pyramid_height == h && _allocated) return;
156 
157  if(w > GlobalUtil::_texMaxDim || h > GlobalUtil::_texMaxDim) return ;
158 
159  if(GlobalUtil::_verbose && GlobalUtil::_timingS) std::cout<<"[Allocate Pyramid]:\t" <<w<<"x"<<h<<endl;
160  //first octave does not change
161  _pyramid_octave_first = 0;
162 
163 
164  //compute # of octaves
165  input_sz = min(w,h) ;
166  _pyramid_width = w;
167  _pyramid_height = h;
168 
169  //reset to preset parameters
170  _octave_num_new = GlobalUtil::_octave_num_default;
171 
172  if(_octave_num_new < 1) _octave_num_new = GetRequiredOctaveNum(input_sz) ;
173 
174  if(_pyramid_octave_num != _octave_num_new)
175  {
176  //destroy the original pyramid if the # of octave changes
177  if(_octave_num >0)
178  {
179  DestroyPerLevelData();
180  DestroyPyramidData();
181  }
182  _pyramid_octave_num = _octave_num_new;
183  }
184 
185  _octave_num = _pyramid_octave_num;
186 
187  int noct = _octave_num;
188  int nlev = param._level_num;
189  int texNum = noct* nlev * DATA_NUM;
190 
191  // //initialize the pyramid
192  if(_allPyramid==NULL)
193  {
194  _allPyramid = new CLTexImage[ texNum];
195  cl_context context = _OpenCL->GetContextCL();
196  cl_command_queue queue = _OpenCL->GetCommandQueue();
197  for(i = 0; i < texNum; ++i) _allPyramid[i].SetContext(context, queue);
198  }
199 
200 
201 
202  CLTexImage * gus = GetBaseLevel(_octave_min, DATA_GAUSSIAN);
203  CLTexImage * dog = GetBaseLevel(_octave_min, DATA_DOG);
204  CLTexImage * grd = GetBaseLevel(_octave_min, DATA_GRAD);
205  CLTexImage * rot = GetBaseLevel(_octave_min, DATA_ROT);
206  CLTexImage * key = GetBaseLevel(_octave_min, DATA_KEYPOINT);
207 
209 
210 
211 
212  for(i = 0; i< noct; i++)
213  {
214  for( j = 0; j< nlev; j++, gus++, dog++, grd++, rot++, key++)
215  {
216  gus->InitPackedTex(w, h, GlobalUtil::_usePackedTex);
217  if(j==0)continue;
218  dog->InitPackedTex(w, h, GlobalUtil::_usePackedTex);
219  if(j < 1 + param._dog_level_num)
220  {
221  grd->InitPackedTex(w, h, GlobalUtil::_usePackedTex);
222  rot->InitPackedTex(w, h, GlobalUtil::_usePackedTex);
223  }
224  if(j > 1 && j < nlev -1) key->InitPackedTex(w, h, GlobalUtil::_usePackedTex);
225  }
227  int tsz = (gus -1)->GetTexPixelCount() * 16;
228  totalkb += ((nlev *5 -6)* tsz / 1024);
229  //several auxilary textures are not actually required
230  w>>=1;
231  h>>=1;
232  }
233 
234  totalkb += ResizeFeatureStorage();
235 
236  _allocated = 1;
237 
238  if(GlobalUtil::_verbose && GlobalUtil::_timingS) std::cout<<"[Allocate Pyramid]:\t" <<(totalkb/1024)<<"MB\n";
239 
240 }
241 
242 void PyramidCL::FitPyramid(int w, int h)
243 {
244  _pyramid_octave_first = 0;
245  //
246  _octave_num = GlobalUtil::_octave_num_default;
247 
248  int _octave_num_max = GetRequiredOctaveNum(min(w, h));
249 
250  if(_octave_num < 1 || _octave_num > _octave_num_max)
251  {
252  _octave_num = _octave_num_max;
253  }
254 
255 
256  int pw = _pyramid_width>>1, ph = _pyramid_height>>1;
257  while(_pyramid_octave_first + _octave_num < _pyramid_octave_num &&
258  pw >= w && ph >= h)
259  {
260  _pyramid_octave_first++;
261  pw >>= 1;
262  ph >>= 1;
263  }
264 
266  for(int i = 0; i < _octave_num; i++)
267  {
268  CLTexImage * tex = GetBaseLevel(i + _octave_min);
269  CLTexImage * dog = GetBaseLevel(i + _octave_min, DATA_DOG);
270  CLTexImage * grd = GetBaseLevel(i + _octave_min, DATA_GRAD);
271  CLTexImage * rot = GetBaseLevel(i + _octave_min, DATA_ROT);
272  CLTexImage * key = GetBaseLevel(i + _octave_min, DATA_KEYPOINT);
273  for(int j = param._level_min; j <= param._level_max; j++, tex++, dog++, grd++, rot++, key++)
274  {
275  tex->SetPackedSize(w, h, GlobalUtil::_usePackedTex);
276  if(j == param._level_min) continue;
277  dog->SetPackedSize(w, h, GlobalUtil::_usePackedTex);
278  if(j < param._level_max - 1)
279  {
280  grd->SetPackedSize(w, h, GlobalUtil::_usePackedTex);
281  rot->SetPackedSize(w, h, GlobalUtil::_usePackedTex);
282  }
283  if(j > param._level_min + 1 && j < param._level_max) key->SetPackedSize(w, h, GlobalUtil::_usePackedTex);
284  }
285  w>>=1;
286  h>>=1;
287  }
288 }
289 
290 
291 void PyramidCL::SetLevelFeatureNum(int idx, int fcount)
292 {
293  _featureTex[idx].InitBufferTex(fcount, 1, 4);
294  _levelFeatureNum[idx] = fcount;
295 }
296 
297 int PyramidCL::ResizeFeatureStorage()
298 {
299  int totalkb = 0;
300  if(_levelFeatureNum==NULL) _levelFeatureNum = new int[_octave_num * param._dog_level_num];
301  std::fill(_levelFeatureNum, _levelFeatureNum+_octave_num * param._dog_level_num, 0);
302 
303  cl_context context = _OpenCL->GetContextCL();
304  cl_command_queue queue = _OpenCL->GetCommandQueue();
305  int wmax = GetBaseLevel(_octave_min)->GetImgWidth() * 2;
306  int hmax = GetBaseLevel(_octave_min)->GetImgHeight() * 2;
307  int whmax = max(wmax, hmax);
308  int w, i;
309 
310  //
311  int num = (int)ceil(log(double(whmax))/log(4.0));
312 
313  if( _hpLevelNum != num)
314  {
315  _hpLevelNum = num;
316  if(_histoPyramidTex ) delete [] _histoPyramidTex;
317  _histoPyramidTex = new CLTexImage[_hpLevelNum];
318  for(i = 0; i < _hpLevelNum; ++i) _histoPyramidTex[i].SetContext(context, queue);
319  }
320 
321  for(i = 0, w = 1; i < _hpLevelNum; i++)
322  {
323  _histoPyramidTex[i].InitBufferTex(w, whmax, 4);
324  w<<=2;
325  }
326 
327  // (4 ^ (_hpLevelNum) -1 / 3) pixels
328  totalkb += (((1 << (2 * _hpLevelNum)) -1) / 3 * 16 / 1024);
329 
330  //initialize the feature texture
331  int idx = 0, n = _octave_num * param._dog_level_num;
332  if(_featureTex==NULL)
333  {
334  _featureTex = new CLTexImage[n];
335  for(i = 0; i <n; ++i) _featureTex[i].SetContext(context, queue);
336  }
337  if(GlobalUtil::_MaxOrientation >1 && GlobalUtil::_OrientationPack2==0 && _orientationTex== NULL)
338  {
339  _orientationTex = new CLTexImage[n];
340  for(i = 0; i < n; ++i) _orientationTex[i].SetContext(context, queue);
341  }
342 
343 
344  for(i = 0; i < _octave_num; i++)
345  {
346  CLTexImage * tex = GetBaseLevel(i+_octave_min);
347  int fmax = int(4 * tex->GetTexWidth() * tex->GetTexHeight()*GlobalUtil::_MaxFeaturePercent);
348  //
350  else if(fmax < 32) fmax = 32; //give it at least a space of 32 feature
351 
352  for(int j = 0; j < param._dog_level_num; j++, idx++)
353  {
354  _featureTex[idx].InitBufferTex(fmax, 1, 4);
355  totalkb += fmax * 16 /1024;
356  //
358  {
359  _orientationTex[idx].InitBufferTex(fmax, 1, 4);
360  totalkb += fmax * 16 /1024;
361  }
362  }
363  }
364 
365  //this just need be initialized once
366  if(_descriptorTex==NULL)
367  {
368  //initialize feature texture pyramid
369  int fmax = _featureTex->GetImgWidth();
370  _descriptorTex = new CLTexImage(context, queue);
371  totalkb += ( fmax /2);
372  _descriptorTex->InitBufferTex(fmax *128, 1, 1);
373  }else
374  {
375  totalkb += _descriptorTex->GetDataSize()/1024;
376  }
377  return totalkb;
378 }
379 
380 void PyramidCL::GetFeatureDescriptors()
381 {
382  //descriptors...
383  /*float* pd = &_descriptor_buffer[0];
384  vector<float> descriptor_buffer2;
385 
386  //use another buffer if we need to re-order the descriptors
387  if(_keypoint_index.size() > 0)
388  {
389  descriptor_buffer2.resize(_descriptor_buffer.size());
390  pd = &descriptor_buffer2[0];
391  }
392 
393  CLTexImage * got, * ftex= _featureTex;
394  for(int i = 0, idx = 0; i < _octave_num; i++)
395  {
396  got = GetBaseLevel(i + _octave_min, DATA_GRAD) + 1;
397  for(int j = 0; j < param._dog_level_num; j++, ftex++, idx++, got++)
398  {
399  if(_levelFeatureNum[idx]==0) continue;
400  ProgramCL::ComputeDescriptor(ftex, got, _descriptorTex);//process
401  _descriptorTex->CopyToHost(pd); //readback descriptor
402  pd += 128*_levelFeatureNum[idx];
403  }
404  }
405 
406  if(GlobalUtil::_timingS) _OpenCL->FinishCL();
407 
408  if(_keypoint_index.size() > 0)
409  {
410  //put the descriptor back to the original order for keypoint list.
411  for(int i = 0; i < _featureNum; ++i)
412  {
413  int index = _keypoint_index[i];
414  memcpy(&_descriptor_buffer[index*128], &descriptor_buffer2[i*128], 128 * sizeof(float));
415  }
416  }*/
417 }
418 
419 void PyramidCL::GenerateFeatureListTex()
420 {
421 
422  vector<float> list;
423  int idx = 0;
424  const double twopi = 2.0*3.14159265358979323846;
425  float sigma_half_step = powf(2.0f, 0.5f / param._dog_level_num);
426  float octave_sigma = _octave_min>=0? float(1<<_octave_min): 1.0f/(1<<(-_octave_min));
427  float offset = GlobalUtil::_LoweOrigin? 0 : 0.5f;
428  if(_down_sample_factor>0) octave_sigma *= float(1<<_down_sample_factor);
429 
430  _keypoint_index.resize(0); // should already be 0
431  for(int i = 0; i < _octave_num; i++, octave_sigma*= 2.0f)
432  {
433  for(int j = 0; j < param._dog_level_num; j++, idx++)
434  {
435  list.resize(0);
436  float level_sigma = param.GetLevelSigma(j + param._level_min + 1) * octave_sigma;
437  float sigma_min = level_sigma / sigma_half_step;
438  float sigma_max = level_sigma * sigma_half_step;
439  int fcount = 0 ;
440  for(int k = 0; k < _featureNum; k++)
441  {
442  float * key = &_keypoint_buffer[k*4];
443  if( (key[2] >= sigma_min && key[2] < sigma_max)
444  ||(key[2] < sigma_min && i ==0 && j == 0)
445  ||(key[2] > sigma_max && i == _octave_num -1 && j == param._dog_level_num - 1))
446  {
447  //add this keypoint to the list
448  list.push_back((key[0] - offset) / octave_sigma + 0.5f);
449  list.push_back((key[1] - offset) / octave_sigma + 0.5f);
450  list.push_back(key[2] / octave_sigma);
451  list.push_back((float)fmod(twopi-key[3], twopi));
452  fcount ++;
453  //save the index of keypoints
454  _keypoint_index.push_back(k);
455  }
456 
457  }
458 
459  _levelFeatureNum[idx] = fcount;
460  if(fcount==0)continue;
461  CLTexImage * ftex = _featureTex+idx;
462 
463  SetLevelFeatureNum(idx, fcount);
464  ftex->CopyFromHost(&list[0]);
465  }
466  }
467 
469  {
470  std::cout<<"#Features:\t"<<_featureNum<<"\n";
471  }
472 
473 }
474 
475 void PyramidCL::ReshapeFeatureListCPU()
476 {
477  int i, szmax =0, sz;
478  int n = param._dog_level_num*_octave_num;
479  for( i = 0; i < n; i++)
480  {
481  sz = _levelFeatureNum[i];
482  if(sz > szmax ) szmax = sz;
483  }
484  float * buffer = new float[szmax*16];
485  float * buffer1 = buffer;
486  float * buffer2 = buffer + szmax*4;
487 
488 
489 
490  _featureNum = 0;
491 
492 #ifdef NO_DUPLICATE_DOWNLOAD
493  const double twopi = 2.0*3.14159265358979323846;
494  _keypoint_buffer.resize(0);
495  float os = _octave_min>=0? float(1<<_octave_min): 1.0f/(1<<(-_octave_min));
496  if(_down_sample_factor>0) os *= float(1<<_down_sample_factor);
497  float offset = GlobalUtil::_LoweOrigin? 0 : 0.5f;
498 #endif
499 
500 
501  for(i = 0; i < n; i++)
502  {
503  if(_levelFeatureNum[i]==0)continue;
504 
505  _featureTex[i].CopyToHost(buffer1);
506 
507  int fcount =0;
508  float * src = buffer1;
509  float * des = buffer2;
510  const static double factor = 2.0*3.14159265358979323846/65535.0;
511  for(int j = 0; j < _levelFeatureNum[i]; j++, src+=4)
512  {
513  unsigned short * orientations = (unsigned short*) (&src[3]);
514  if(orientations[0] != 65535)
515  {
516  des[0] = src[0];
517  des[1] = src[1];
518  des[2] = src[2];
519  des[3] = float( factor* orientations[0]);
520  fcount++;
521  des += 4;
522  if(orientations[1] != 65535 && orientations[1] != orientations[0])
523  {
524  des[0] = src[0];
525  des[1] = src[1];
526  des[2] = src[2];
527  des[3] = float(factor* orientations[1]);
528  fcount++;
529  des += 4;
530  }
531  }
532  }
533  //texture size
534  SetLevelFeatureNum(i, fcount);
535  _featureTex[i].CopyFromHost(buffer2);
536 
537  if(fcount == 0) continue;
538 
539 #ifdef NO_DUPLICATE_DOWNLOAD
540  float oss = os * (1 << (i / param._dog_level_num));
541  _keypoint_buffer.resize((_featureNum + fcount) * 4);
542  float* ds = &_keypoint_buffer[_featureNum * 4];
543  float* fs = buffer2;
544  for(int k = 0; k < fcount; k++, ds+=4, fs+=4)
545  {
546  ds[0] = oss*(fs[0]-0.5f) + offset; //x
547  ds[1] = oss*(fs[1]-0.5f) + offset; //y
548  ds[2] = oss*fs[2]; //scale
549  ds[3] = (float)fmod(twopi-fs[3], twopi); //orientation, mirrored
550  }
551 #endif
552  _featureNum += fcount;
553  }
554  delete[] buffer;
556  {
557  std::cout<<"#Features MO:\t"<<_featureNum<<endl;
558  }
559 }
560 
561 void PyramidCL::GenerateFeatureDisplayVBO()
562 {
563  //it is weried that this part is very slow.
564  //use a big VBO to save all the SIFT box vertices
565  /*int nvbo = _octave_num * param._dog_level_num;
566  if(_featureDisplayVBO==NULL)
567  {
568  //initialize the vbos
569  _featureDisplayVBO = new GLuint[nvbo];
570  _featurePointVBO = new GLuint[nvbo];
571  glGenBuffers(nvbo, _featureDisplayVBO);
572  glGenBuffers(nvbo, _featurePointVBO);
573  }
574  for(int i = 0; i < nvbo; i++)
575  {
576  if(_levelFeatureNum[i]<=0)continue;
577  CLTexImage * ftex = _featureTex + i;
578  CLTexImage texPBO1( _levelFeatureNum[i]* 10, 1, 4, _featureDisplayVBO[i]);
579  CLTexImage texPBO2(_levelFeatureNum[i], 1, 4, _featurePointVBO[i]);
580  _OpenCL->DisplayKeyBox(ftex, &texPBO1);
581  _OpenCL->DisplayKeyPoint(ftex, &texPBO2);
582  }*/
583 }
584 
585 void PyramidCL::DestroySharedData()
586 {
587  //histogram reduction
588  if(_histoPyramidTex)
589  {
590  delete[] _histoPyramidTex;
591  _hpLevelNum = 0;
592  _histoPyramidTex = NULL;
593  }
594  //descriptor storage shared by all levels
595  if(_descriptorTex)
596  {
597  delete _descriptorTex;
598  _descriptorTex = NULL;
599  }
600  //cpu reduction buffer.
601  if(_histo_buffer)
602  {
603  delete[] _histo_buffer;
604  _histo_buffer = 0;
605  }
606 }
607 
608 void PyramidCL::DestroyPerLevelData()
609 {
610  //integers vector to store the feature numbers.
611  if(_levelFeatureNum)
612  {
613  delete [] _levelFeatureNum;
614  _levelFeatureNum = NULL;
615  }
616  //texture used to store features
617  if( _featureTex)
618  {
619  delete [] _featureTex;
620  _featureTex = NULL;
621  }
622  //texture used for multi-orientation
623  if(_orientationTex)
624  {
625  delete [] _orientationTex;
626  _orientationTex = NULL;
627  }
628  int no = _octave_num* param._dog_level_num;
629 
630  //two sets of vbos used to display the features
631  if(_featureDisplayVBO)
632  {
633  glDeleteBuffers(no, _featureDisplayVBO);
634  delete [] _featureDisplayVBO;
635  _featureDisplayVBO = NULL;
636  }
637  if( _featurePointVBO)
638  {
639  glDeleteBuffers(no, _featurePointVBO);
640  delete [] _featurePointVBO;
641  _featurePointVBO = NULL;
642  }
643 }
644 
645 void PyramidCL::DestroyPyramidData()
646 {
647  if(_allPyramid)
648  {
649  delete [] _allPyramid;
650  _allPyramid = NULL;
651  }
652 }
653 
654 void PyramidCL::DownloadKeypoints()
655 {
656  const double twopi = 2.0*3.14159265358979323846;
657  int idx = 0;
658  float * buffer = &_keypoint_buffer[0];
659  vector<float> keypoint_buffer2;
660  //use a different keypoint buffer when processing with an exisint features list
661  //without orientation information.
662  if(_keypoint_index.size() > 0)
663  {
664  keypoint_buffer2.resize(_keypoint_buffer.size());
665  buffer = &keypoint_buffer2[0];
666  }
667  float * p = buffer, *ps;
668  CLTexImage * ftex = _featureTex;
670  float os = _octave_min>=0? float(1<<_octave_min): 1.0f/(1<<(-_octave_min));
671  if(_down_sample_factor>0) os *= float(1<<_down_sample_factor);
672  float offset = GlobalUtil::_LoweOrigin? 0 : 0.5f;
674  for(int i = 0; i < _octave_num; i++, os *= 2.0f)
675  {
676 
677  for(int j = 0; j < param._dog_level_num; j++, idx++, ftex++)
678  {
679 
680  if(_levelFeatureNum[idx]>0)
681  {
682  ftex->CopyToHost(ps = p);
683  for(int k = 0; k < _levelFeatureNum[idx]; k++, ps+=4)
684  {
685  ps[0] = os*(ps[0]-0.5f) + offset; //x
686  ps[1] = os*(ps[1]-0.5f) + offset; //y
687  ps[2] = os*ps[2];
688  ps[3] = (float)fmod(twopi-ps[3], twopi); //orientation, mirrored
689  }
690  p+= 4* _levelFeatureNum[idx];
691  }
692  }
693  }
694 
695  //put the feature into their original order for existing keypoint
696  if(_keypoint_index.size() > 0)
697  {
698  for(int i = 0; i < _featureNum; ++i)
699  {
700  int index = _keypoint_index[i];
701  memcpy(&_keypoint_buffer[index*4], &keypoint_buffer2[i*4], 4 * sizeof(float));
702  }
703  }
704 }
705 
706 void PyramidCL::GenerateFeatureListCPU()
707 {
708  //no cpu version provided
709  GenerateFeatureList();
710 }
711 
712 void PyramidCL::GenerateFeatureList(int i, int j, int reduction_count, vector<int>& hbuffer)
713 {
714  /*int fcount = 0, idx = i * param._dog_level_num + j;
715  int hist_level_num = _hpLevelNum - _pyramid_octave_first /2;
716  int ii, k, len;
717 
718  CLTexImage * htex, * ftex, * tex, *got;
719  ftex = _featureTex + idx;
720  htex = _histoPyramidTex + hist_level_num -1;
721  tex = GetBaseLevel(_octave_min + i, DATA_KEYPOINT) + 2 + j;
722  got = GetBaseLevel(_octave_min + i, DATA_GRAD) + 2 + j;
723 
724  _OpenCL->InitHistogram(tex, htex);
725 
726  for(k = 0; k < reduction_count - 1; k++, htex--)
727  {
728  ProgramCL::ReduceHistogram(htex, htex -1);
729  }
730 
731  //htex has the row reduction result
732  len = htex->GetImgHeight() * 4;
733  hbuffer.resize(len);
734  _OpenCL->FinishCL();
735  htex->CopyToHost(&hbuffer[0]);
736  //
737  for(ii = 0; ii < len; ++ii) fcount += hbuffer[ii];
738  SetLevelFeatureNum(idx, fcount);
739 
740  //build the feature list
741  if(fcount > 0)
742  {
743  _featureNum += fcount;
744  _keypoint_buffer.resize(fcount * 4);
745  //vector<int> ikbuf(fcount*4);
746  int* ibuf = (int*) (&_keypoint_buffer[0]);
747 
748  for(ii = 0; ii < len; ++ii)
749  {
750  int x = ii%4, y = ii / 4;
751  for(int jj = 0 ; jj < hbuffer[ii]; ++jj, ibuf+=4)
752  {
753  ibuf[0] = x; ibuf[1] = y; ibuf[2] = jj; ibuf[3] = 0;
754  }
755  }
756  _featureTex[idx].CopyFromHost(&_keypoint_buffer[0]);
757 
759  ProgramCL::GenerateList(_featureTex + idx, ++htex);
760  for(k = 2; k < reduction_count; k++)
761  {
762  ProgramCL::GenerateList(_featureTex + idx, ++htex);
763  }
764  }*/
765 }
766 
767 void PyramidCL::GenerateFeatureList()
768 {
769  /*double t1, t2;
770  int ocount = 0, reduction_count;
771  int reverse = (GlobalUtil::_TruncateMethod == 1);
772 
773  vector<int> hbuffer;
774  _featureNum = 0;
775 
776  //for(int i = 0, idx = 0; i < _octave_num; i++)
777  FOR_EACH_OCTAVE(i, reverse)
778  {
779  CLTexImage* tex = GetBaseLevel(_octave_min + i, DATA_KEYPOINT) + 2;
780  reduction_count = FitHistogramPyramid(tex);
781 
782  if(GlobalUtil::_timingO)
783  {
784  t1 = CLOCK();
785  ocount = 0;
786  std::cout<<"#"<<i+_octave_min + _down_sample_factor<<":\t";
787  }
788  //for(int j = 0; j < param._dog_level_num; j++, idx++)
789  FOR_EACH_LEVEL(j, reverse)
790  {
791  if(GlobalUtil::_TruncateMethod && GlobalUtil::_FeatureCountThreshold > 0 && _featureNum > GlobalUtil::_FeatureCountThreshold) continue;
792 
793  GenerateFeatureList(i, j, reduction_count, hbuffer);
794 
796  if(GlobalUtil::_timingO)
797  {
798  int idx = i * param._dog_level_num + j;
799  ocount += _levelFeatureNum[idx];
800  std::cout<< _levelFeatureNum[idx] <<"\t";
801  }
802  }
803  if(GlobalUtil::_timingO)
804  {
805  t2 = CLOCK();
806  std::cout << "| \t" << int(ocount) << " :\t(" << (t2 - t1) << ")\n";
807  }
808  }
810  CopyGradientTex();
812  if(GlobalUtil::_timingS)_OpenCL->FinishCL();
813 
814  if(GlobalUtil::_verbose)
815  {
816  std::cout<<"#Features:\t"<<_featureNum<<"\n";
817  }*/
818 }
819 
820 GLTexImage* PyramidCL::GetLevelTexture(int octave, int level)
821 {
822  return GetLevelTexture(octave, level, DATA_GAUSSIAN);
823 }
824 
825 GLTexImage* PyramidCL::ConvertTexCL2GL(CLTexImage* tex, int dataName)
826 {
827 
828  if(_bufferTEX == NULL) _bufferTEX = new GLTexImage;
829 
831  int ratio = GlobalUtil::_usePackedTex ? 2 : 1;
832  int width = tex->GetImgWidth() * ratio;
833  int height = tex->GetImgHeight() * ratio;
834  int tw = max(width, _bufferTEX->GetTexWidth());
835  int th = max(height, _bufferTEX->GetTexHeight());
836  _bufferTEX->InitTexture(tw, th, 1, GL_RGBA);
837  _bufferTEX->SetImageSize(width, height);
838 
840  CLTexImage texCL(_OpenCL->GetContextCL(), _OpenCL->GetCommandQueue());
841  texCL.InitTextureGL(*_bufferTEX, width, height, 4);
842 
843  switch(dataName)
844  {
845  case DATA_GAUSSIAN: _OpenCL->UnpackImage(tex, &texCL); break;
846  case DATA_DOG:_OpenCL->UnpackImageDOG(tex, &texCL); break;
847  case DATA_GRAD:_OpenCL->UnpackImageGRD(tex, &texCL); break;
848  case DATA_KEYPOINT:_OpenCL->UnpackImageKEY(tex,
849  tex - param._level_num * _pyramid_octave_num, &texCL);break;
850  default:
851  break;
852  }
853 
854 
855  return _bufferTEX;
856 }
857 
858 GLTexImage* PyramidCL::GetLevelTexture(int octave, int level, int dataName)
859 {
860  CLTexImage* tex = GetBaseLevel(octave, dataName) + (level - param._level_min);
861  return ConvertTexCL2GL(tex, dataName);
862 }
863 
864 void PyramidCL::ConvertInputToCL(GLTexInput* input, CLTexImage* output)
865 {
866  int ws = input->GetImgWidth(), hs = input->GetImgHeight();
867  //copy the input image to pixel buffer object
868  if(input->_pixel_data)
869  {
870  output->InitTexture(ws, hs, 1);
871  output->CopyFromHost(input->_pixel_data);
872  }else /*if(input->_rgb_converted && input->CopyToPBO(_bufferPBO, ws, hs, GL_LUMINANCE))
873  {
874  output->InitTexture(ws, hs, 1);
875  output->CopyFromPBO(ws, hs, _bufferPBO);
876  }else if(input->CopyToPBO(_bufferPBO, ws, hs))
877  {
878  CLTexImage texPBO(ws, hs, 4, _bufferPBO);
879  output->InitTexture(ws, hs, 1);
880  ProgramCL::ReduceToSingleChannel(output, &texPBO, !input->_rgb_converted);
881  }else*/
882  {
883  std::cerr<< "Unable To Convert Intput\n";
884  }
885 }
886 
887 void PyramidCL::BuildPyramid(GLTexInput * input)
888 {
889 
890  USE_TIMING();
891 
892  int i, j;
893 
894  for ( i = _octave_min; i < _octave_min + _octave_num; i++)
895  {
896 
897  CLTexImage *tex = GetBaseLevel(i);
898  CLTexImage *buf = GetBaseLevel(i, DATA_DOG) +2;
899  FilterCL ** filter = _OpenCL->f_gaussian_step;
900  j = param._level_min + 1;
901 
902  OCTAVE_START();
903 
904  if( i == _octave_min )
905  {
907  {
908  ConvertInputToCL(input, _inputTex);
909  if(i < 0) _OpenCL->SampleImageU(tex, _inputTex, -i- 1);
910  else _OpenCL->SampleImageD(tex, _inputTex, i + 1);
911  }else
912  {
913  if(i == 0) ConvertInputToCL(input, tex);
914  else
915  {
916  ConvertInputToCL(input, _inputTex);
917  if(i < 0) _OpenCL->SampleImageU(tex, _inputTex, -i);
918  else _OpenCL->SampleImageD(tex, _inputTex, i);
919  }
920  }
921  _OpenCL->FilterInitialImage(tex, buf);
922  }else
923  {
924  _OpenCL->SampleImageD(tex, GetBaseLevel(i - 1) + param._level_ds - param._level_min);
925  _OpenCL->FilterSampledImage(tex, buf);
926  }
927  LEVEL_FINISH();
928  for( ; j <= param._level_max ; j++, tex++, filter++)
929  {
930  // filtering
931  _OpenCL->FilterImage(*filter, tex + 1, tex, buf);
932  LEVEL_FINISH();
933  }
934  OCTAVE_FINISH();
935  }
936  if(GlobalUtil::_timingS) _OpenCL->FinishCL();
937 }
938 
939 void PyramidCL::DetectKeypointsEX()
940 {
941  int i, j;
942  double t0, t, ts, t1, t2;
943 
944  if(GlobalUtil::_timingS && GlobalUtil::_verbose) ts = CLOCK();
945 
946  for(i = _octave_min; i < _octave_min + _octave_num; i++)
947  {
948  CLTexImage * gus = GetBaseLevel(i) + 1;
949  CLTexImage * dog = GetBaseLevel(i, DATA_DOG) + 1;
950  CLTexImage * grd = GetBaseLevel(i, DATA_GRAD) + 1;
951  CLTexImage * rot = GetBaseLevel(i, DATA_ROT) + 1;
952  //compute the gradient
953  for(j = param._level_min +1; j <= param._level_max ; j++, gus++, dog++, grd++, rot++)
954  {
955  //input: gus and gus -1
956  //output: gradient, dog, orientation
957  _OpenCL->ComputeDOG(gus, gus - 1, dog, grd, rot);
958  }
959  }
961  {
962  _OpenCL->FinishCL();
963  t1 = CLOCK();
964  }
965  //if(GlobalUtil::_timingS) _OpenCL->FinishCL();
966  //if(!GlobalUtil::_usePackedTex) return; //not finished
967  //return;
968 
969  for ( i = _octave_min; i < _octave_min + _octave_num; i++)
970  {
972  {
973  t0 = CLOCK();
974  std::cout<<"#"<<(i + _down_sample_factor)<<"\t";
975  }
976  CLTexImage * dog = GetBaseLevel(i, DATA_DOG) + 2;
977  CLTexImage * key = GetBaseLevel(i, DATA_KEYPOINT) +2;
978 
979 
980  for( j = param._level_min +2; j < param._level_max ; j++, dog++, key++)
981  {
982  if(GlobalUtil::_timingL)t = CLOCK();
983  //input, dog, dog + 1, dog -1
984  //output, key
985  _OpenCL->ComputeKEY(dog, key, param._dog_threshold, param._edge_threshold);
987  {
988  std::cout<<(CLOCK()-t)<<"\t";
989  }
990  }
992  {
993  std::cout<<"|\t"<<(CLOCK()-t0)<<"\n";
994  }
995  }
996 
998  {
999  _OpenCL->FinishCL();
1001  {
1002  t2 = CLOCK();
1003  std::cout <<"<Gradient, DOG >\t"<<(t1-ts)<<"\n"
1004  <<"<Get Keypoints >\t"<<(t2-t1)<<"\n";
1005  }
1006  }
1007 }
1008 
1009 void PyramidCL::CopyGradientTex()
1010 {
1011  /*double ts, t1;
1012 
1013  if(GlobalUtil::_timingS && GlobalUtil::_verbose)ts = CLOCK();
1014 
1015  for(int i = 0, idx = 0; i < _octave_num; i++)
1016  {
1017  CLTexImage * got = GetBaseLevel(i + _octave_min, DATA_GRAD) + 1;
1018  //compute the gradient
1019  for(int j = 0; j < param._dog_level_num ; j++, got++, idx++)
1020  {
1021  if(_levelFeatureNum[idx] > 0) got->CopyToTexture2D();
1022  }
1023  }
1024  if(GlobalUtil::_timingS)
1025  {
1026  ProgramCL::FinishCLDA();
1027  if(GlobalUtil::_verbose)
1028  {
1029  t1 = CLOCK();
1030  std::cout <<"<Copy Grad/Orientation>\t"<<(t1-ts)<<"\n";
1031  }
1032  }*/
1033 }
1034 
1035 void PyramidCL::ComputeGradient()
1036 {
1037 
1038  /*int i, j;
1039  double ts, t1;
1040 
1041  if(GlobalUtil::_timingS && GlobalUtil::_verbose)ts = CLOCK();
1042 
1043  for(i = _octave_min; i < _octave_min + _octave_num; i++)
1044  {
1045  CLTexImage * gus = GetBaseLevel(i) + 1;
1046  CLTexImage * dog = GetBaseLevel(i, DATA_DOG) + 1;
1047  CLTexImage * got = GetBaseLevel(i, DATA_GRAD) + 1;
1048 
1049  //compute the gradient
1050  for(j = 0; j < param._dog_level_num ; j++, gus++, dog++, got++)
1051  {
1052  ProgramCL::ComputeDOG(gus, dog, got);
1053  }
1054  }
1055  if(GlobalUtil::_timingS)
1056  {
1057  ProgramCL::FinishCLDA();
1058  if(GlobalUtil::_verbose)
1059  {
1060  t1 = CLOCK();
1061  std::cout <<"<Gradient, DOG >\t"<<(t1-ts)<<"\n";
1062  }
1063  }*/
1064 }
1065 
1066 int PyramidCL::FitHistogramPyramid(CLTexImage* tex)
1067 {
1068  CLTexImage *htex;
1069  int hist_level_num = _hpLevelNum - _pyramid_octave_first / 2;
1070  htex = _histoPyramidTex + hist_level_num - 1;
1071  int w = (tex->GetImgWidth() + 2) >> 2;
1072  int h = tex->GetImgHeight();
1073  int count = 0;
1074  for(int k = 0; k < hist_level_num; k++, htex--)
1075  {
1076  //htex->SetImageSize(w, h);
1077  htex->InitTexture(w, h, 4);
1078  ++count;
1079  if(w == 1)
1080  break;
1081  w = (w + 3)>>2;
1082  }
1083  return count;
1084 }
1085 
1086 void PyramidCL::GetFeatureOrientations()
1087 {
1088 
1089 /*
1090  CLTexImage * ftex = _featureTex;
1091  int * count = _levelFeatureNum;
1092  float sigma, sigma_step = powf(2.0f, 1.0f/param._dog_level_num);
1093 
1094  for(int i = 0; i < _octave_num; i++)
1095  {
1096  CLTexImage* got = GetBaseLevel(i + _octave_min, DATA_GRAD) + 1;
1097  CLTexImage* key = GetBaseLevel(i + _octave_min, DATA_KEYPOINT) + 2;
1098 
1099  for(int j = 0; j < param._dog_level_num; j++, ftex++, count++, got++, key++)
1100  {
1101  if(*count<=0)continue;
1102 
1103  //if(ftex->GetImgWidth() < *count) ftex->InitTexture(*count, 1, 4);
1104 
1105  sigma = param.GetLevelSigma(j+param._level_min+1);
1106 
1107  ProgramCL::ComputeOrientation(ftex, got, key, sigma, sigma_step, _existing_keypoints);
1108  }
1109  }
1110 
1111  if(GlobalUtil::_timingS)ProgramCL::FinishCL();
1112  */
1113 
1114 
1115 }
1116 
1117 void PyramidCL::GetSimplifiedOrientation()
1118 {
1119  //no simplified orientation
1120  GetFeatureOrientations();
1121 }
1122 
1123 CLTexImage* PyramidCL::GetBaseLevel(int octave, int dataName)
1124 {
1125  if(octave <_octave_min || octave > _octave_min + _octave_num) return NULL;
1126  int offset = (_pyramid_octave_first + octave - _octave_min) * param._level_num;
1127  int num = param._level_num * _pyramid_octave_num;
1128  return _allPyramid + num * dataName + offset;
1129 }
1130 
1131 #endif
1132 
int width
int height
int count
int offset
#define USE_TIMING()
Definition: PyramidGL.cpp:50
#define LEVEL_FINISH()
Definition: PyramidGL.cpp:52
#define OCTAVE_START()
Definition: PyramidGL.cpp:51
#define OCTAVE_FINISH()
Definition: PyramidGL.cpp:53
#define NULL
int GetImgHeight()
Definition: GLTexImage.h:80
int GetImgWidth()
Definition: GLTexImage.h:79
const void * _pixel_data
Definition: GLTexImage.h:104
static int _octave_num_default
Definition: GlobalUtil.h:79
static int _octave_min_default
Definition: GlobalUtil.h:78
static int _timingL
Definition: GlobalUtil.h:47
static int _OrientationPack2
Definition: GlobalUtil.h:60
static int _verbose
Definition: GlobalUtil.h:44
static int _LoweOrigin
Definition: GlobalUtil.h:85
static int _ForceTightPyramid
Definition: GlobalUtil.h:77
static int _texMaxDim
Definition: GlobalUtil.h:39
static int _timingS
Definition: GlobalUtil.h:45
static float _MaxFeaturePercent
Definition: GlobalUtil.h:66
static int _MaxLevelFeatureNum
Definition: GlobalUtil.h:67
static int _usePackedTex
Definition: GlobalUtil.h:48
static int _MaxOrientation
Definition: GlobalUtil.h:59
static int _timingO
Definition: GlobalUtil.h:46
static void InitGLParam(int NotTargetGL=0)
Definition: GlobalUtil.cpp:319
int min(int a, int b)
Definition: cutil_math.h:53
int max(int a, int b)
Definition: cutil_math.h:48
ImGuiContext * context
Definition: Window.cpp:76
QTextStream & endl(QTextStream &stream)
Definition: QtCompat.h:718
MiniVec< float, N > ceil(const MiniVec< float, N > &a)
Definition: MiniVec.h:89
Definition: Eigen.h:85