Statistics
| Branch: | Revision:

root / rgbdslam / external / siftgpu / src / SiftGPU / SiftPyramid.cpp @ 9240aaa3

History | View | Annotate | Download (10.6 KB)

1
////////////////////////////////////////////////////////////////////////////
2
//        File:                SiftPyramid.cpp
3
//        Author:                Changchang Wu
4
//        Description :        Implementation of the SiftPyramid class.
5
//                                        
6
//
7
//
8
//        Copyright (c) 2007 University of North Carolina at Chapel Hill
9
//        All Rights Reserved
10
//
11
//        Permission to use, copy, modify and distribute this software and its
12
//        documentation for educational, research and non-profit purposes, without
13
//        fee, and without a written agreement is hereby granted, provided that the
14
//        above copyright notice and the following paragraph appear in all copies.        
15
//
16
//        The University of North Carolina at Chapel Hill make no representations
17
//        about the suitability of this software for any purpose. It is provided
18
//        'as is' without express or implied warranty. 
19
//
20
//        Please send BUG REPORTS to ccwu@cs.unc.edu
21
//
22
////////////////////////////////////////////////////////////////////////////
23

    
24

    
25
#include "GL/glew.h"
26
#include <string.h>
27
#include <iostream>
28
#include <iomanip>
29
#include <vector>
30
#include <algorithm>
31
#include <fstream>
32
#include <math.h>
33
using namespace std;
34

    
35
#include "GlobalUtil.h"
36
#include "SiftPyramid.h"
37
#include "SiftGPU.h"
38

    
39

    
40
#ifdef DEBUG_SIFTGPU
41
#include "IL/il.h"
42
#include "direct.h"
43
#include "io.h"
44
#include <sys/stat.h> 
45
#endif
46

    
47

    
48

    
49
void SiftPyramid::RunSIFT(GLTexInput*input)
50
{
51
    CleanupBeforeSIFT(); 
52

    
53
        if(_existing_keypoints & SIFT_SKIP_FILTERING)
54
        {
55
                
56
        }else
57
        {
58
                GlobalUtil::StartTimer("Build    Pyramid");
59
                BuildPyramid(input);
60
                GlobalUtil::StopTimer();
61
                _timing[0] = GetElapsedTime();
62
        }
63

    
64

    
65
        if(_existing_keypoints)
66
        {
67
                //existing keypoint list should at least have the locations and scale
68
                GlobalUtil::StartTimer("Upload Feature List");
69
                if(!(_existing_keypoints & SIFT_SKIP_FILTERING)) ComputeGradient();
70
                GenerateFeatureListTex();
71
                GlobalUtil::StopTimer();
72
                _timing[2] = GetElapsedTime();
73
        }else
74
        {
75

    
76
                GlobalUtil::StartTimer("Detect Keypoints");
77
                DetectKeypointsEX();
78
                GlobalUtil::StopTimer();
79
                _timing[1] = GetElapsedTime();
80

    
81
                if(GlobalUtil::_ListGenGPU ==1)
82
                {
83
                        GlobalUtil::StartTimer("Get Feature List");
84
                        GenerateFeatureList();
85
                        GlobalUtil::StopTimer();
86

    
87
                }else
88
                {
89
                        GlobalUtil::StartTimer("Transfer Feature List");
90
                        GenerateFeatureListCPU();
91
                        GlobalUtil::StopTimer();
92
                }
93
            LimitFeatureCount(0);
94
                _timing[2] = GetElapsedTime();
95
        }
96

    
97

    
98
        
99
        if(_existing_keypoints& SIFT_SKIP_ORIENTATION)
100
        {
101
                //use exisitng feature orientation or
102
        }else         if(GlobalUtil::_MaxOrientation>0)
103
        {
104
                //some extra tricks are done to handle existing keypoint list
105
                GlobalUtil::StartTimer("Feature Orientations");
106
                GetFeatureOrientations();
107
                GlobalUtil::StopTimer();
108
                _timing[3] = GetElapsedTime();
109

    
110
                //for existing keypoint list, only the strongest orientation is kept.
111
                if(GlobalUtil::_MaxOrientation >1 && !_existing_keypoints && !GlobalUtil::_FixedOrientation)
112
                {
113
                        GlobalUtil::StartTimer("MultiO Feature List");
114
                        ReshapeFeatureListCPU();
115
            LimitFeatureCount(1);
116
                        GlobalUtil::StopTimer();        
117
                        _timing[4] = GetElapsedTime();
118
                }
119
        }else
120
        {
121
                GlobalUtil::StartTimer("Feature Orientations");
122
                GetSimplifiedOrientation();
123
                GlobalUtil::StopTimer();
124
                _timing[3] = GetElapsedTime();
125
        }
126

    
127
        PrepareBuffer();
128

    
129
        if(_existing_keypoints & SIFT_SKIP_ORIENTATION)
130
        {
131
                //no need to read back feature if all fields of keypoints are already specified
132
        }else
133
        {
134
                GlobalUtil::StartTimer("Download Keypoints");
135
#ifdef NO_DUPLICATE_DOWNLOAD
136
                if(GlobalUtil::_MaxOrientation < 2 || GlobalUtil::_FixedOrientation)
137
#endif
138
                DownloadKeypoints();
139
                GlobalUtil::StopTimer();
140
                _timing[5] =  GetElapsedTime(); 
141
        }
142

    
143

    
144

    
145
        if(GlobalUtil::_DescriptorPPT)
146
        {
147
                //desciprotrs are downloaded in descriptor computation of each level
148
                GlobalUtil::StartTimer("Get Descriptor");
149
                GetFeatureDescriptors();
150
                GlobalUtil::StopTimer();
151
                _timing[6] =  GetElapsedTime(); 
152
        }
153

    
154
        //reset the existing keypoints
155
        _existing_keypoints = 0;
156
        _keypoint_index.resize(0);
157

    
158
    if(GlobalUtil::_UseSiftGPUEX)
159
        {
160
                GlobalUtil::StartTimer("Gen. Display VBO");
161
                GenerateFeatureDisplayVBO();
162
                GlobalUtil::StopTimer();
163
                _timing[7] = GlobalUtil::GetElapsedTime();
164
        }
165
    //clean up
166
    CleanUpAfterSIFT();
167
}
168

    
169

    
170
void SiftPyramid::LimitFeatureCount(int have_keylist)
171
{
172

    
173
        if(GlobalUtil::_FeatureCountThreshold <= 0 || _existing_keypoints) return;
174
        ///////////////////////////////////////////////////////////////
175
        //skip the lowest levels to reduce number of features. 
176

    
177
    if(GlobalUtil::_TruncateMethod == 2)
178
    {
179
        int i = 0, new_feature_num = 0, level_num = param._dog_level_num * _octave_num;
180
        for(; new_feature_num < _FeatureCountThreshold && i < level_num; ++i) new_feature_num += _levelFeatureNum[i];
181
        for(; i < level_num; ++i)            _levelFeatureNum[i] = 0; 
182

    
183
        if(new_feature_num < _featureNum)
184
        {
185
            _featureNum = new_feature_num;
186
            if(GlobalUtil::_verbose )
187
            {
188
                    std::cout<<"#Features Reduced:\t"<<_featureNum<<endl;
189
            }
190
        }
191
    }else
192
    {
193
        int i = 0, num_to_erase = 0;
194
        while(_featureNum - _levelFeatureNum[i] > _FeatureCountThreshold)
195
        {
196
            num_to_erase += _levelFeatureNum[i];
197
                _featureNum -= _levelFeatureNum[i];
198
                _levelFeatureNum[i++] = 0;
199
        }
200
        if(num_to_erase > 0 && have_keylist)
201
        {
202
            _keypoint_buffer.erase(_keypoint_buffer.begin(), _keypoint_buffer.begin() + num_to_erase * 4);
203
        }
204
        if(GlobalUtil::_verbose &&  num_to_erase > 0)
205
        {
206
                std::cout<<"#Features Reduced:\t"<<_featureNum<<endl;
207
        }
208
    }
209

    
210

    
211
}
212

    
213
void SiftPyramid::PrepareBuffer()
214
{
215
        //when there is no existing keypoint list, the feature list need to be downloaded
216
        //when an existing keypoint list does not have orientaiton, we need to download them again.
217
        if(!(_existing_keypoints & SIFT_SKIP_ORIENTATION)) 
218
        {
219
                //_keypoint_buffer.resize(4 * (_featureNum +align));
220
                _keypoint_buffer.resize(4 * (_featureNum + GlobalUtil::_texMaxDim)); //11/19/2008
221
        }
222
        if(GlobalUtil::_DescriptorPPT)
223
        {
224
                //_descriptor_buffer.resize(128*(_featureNum + align)); 
225
                _descriptor_buffer.resize(128 * _featureNum + 16 * GlobalUtil::_texMaxDim);//11/19/2008
226
        }
227

    
228
}
229

    
230
int SiftPyramid:: GetRequiredOctaveNum(int inputsz)
231
{
232
    //[2 ^ i,  2 ^ (i + 1)) -> i - 3...
233
    //768 in [2^9, 2^10)  -> 6 -> smallest will be 768 / 32 = 24
234
    int num =  (int) floor (log ( inputsz * 2.0 / GlobalUtil::_texMinDim )/log(2.0));
235
    return num <= 0 ? 1 : num; 
236
}
237

    
238
void SiftPyramid::CopyFeatureVector(float*keys, float *descriptors)
239
{
240
        if(keys)                memcpy(keys, &_keypoint_buffer[0], 4*_featureNum*sizeof(float));
241
        if(descriptors)        memcpy(descriptors, &_descriptor_buffer[0], 128*_featureNum*sizeof(float));
242
}
243

    
244
void SiftPyramid:: SetKeypointList(int num, const float * keys, int run_on_current, int skip_orientation)
245
{
246
        //for each input keypoint
247
        //sort the key point list by size, and assign them to corresponding levels
248
        if(num <=0) return;
249
        _featureNum = num;
250
        ///copy the keypoints
251
        _keypoint_buffer.resize(num * 4);
252
        memcpy(&_keypoint_buffer[0], keys, 4 * num * sizeof(float));
253
        //location and scale can be skipped
254
        _existing_keypoints = SIFT_SKIP_DETECTION;
255
        //filtering is skipped if it is running on the same image
256
        if(run_on_current) _existing_keypoints |= SIFT_SKIP_FILTERING;
257
        //orientation can be skipped if specified
258
        if(skip_orientation) _existing_keypoints |= SIFT_SKIP_ORIENTATION;
259
    //hacking parameter for using rectangle description mode
260
    if(skip_orientation == -1) _existing_keypoints |= SIFT_RECT_DESCRIPTION;
261
}
262

    
263

    
264
void SiftPyramid::SaveSIFT(const char * szFileName)
265
{
266
        if (_featureNum <=0) return;
267
        float * pk = &_keypoint_buffer[0];
268

    
269
        if(GlobalUtil::_BinarySIFT)
270
        {
271
                std::ofstream out(szFileName, ios::binary);
272
                out.write((char* )(&_featureNum), sizeof(int));
273

    
274
                if(GlobalUtil::_DescriptorPPT)
275
                {
276
                        int dim = 128;
277
                        out.write((char* )(&dim), sizeof(int));
278
                        float * pd = &_descriptor_buffer[0] ;
279
                        for(int i = 0; i < _featureNum; i++, pk+=4, pd +=128)
280
                        {
281
                                out.write((char* )(pk +1), sizeof(float));
282
                                out.write((char* )(pk), sizeof(float));
283
                                out.write((char* )(pk+2), 2 * sizeof(float));
284
                                out.write((char* )(pd), 128 * sizeof(float));
285
                        }
286
                }else
287
                {
288
                        int dim = 0;
289
                        out.write((char* )(&dim), sizeof(int));
290
                        for(int i = 0; i < _featureNum; i++, pk+=4)
291
                        {
292
                                out.write((char* )(pk +1), sizeof(float));
293
                                out.write((char* )(pk), sizeof(float));
294
                                out.write((char* )(pk+2), 2 * sizeof(float));
295
                        }
296
                }
297
        }else
298
        {
299
                std::ofstream out(szFileName);
300
                out.flags(ios::fixed);
301

    
302
                if(GlobalUtil::_DescriptorPPT)
303
                {
304
                        float * pd = &_descriptor_buffer[0] ;
305
                        out<<_featureNum<<" 128"<<endl;
306

    
307
                        for(int i = 0; i < _featureNum; i++)
308
                        {
309
                                //in y, x, scale, orientation order
310
                                out<<setprecision(2) << pk[1]<<" "<<setprecision(2) << pk[0]<<" "
311
                                        <<setprecision(3) << pk[2]<<" " <<setprecision(3) <<  pk[3]<< endl; 
312

    
313
                                ////out << setprecision(12) << pk[1] <<  " " << pk[0] << " " << pk[2] << " " << pk[3] << endl;
314
                                pk+=4;
315
                                for(int k = 0; k < 128; k ++, pd++) 
316
                                {
317
                                        if(GlobalUtil::_NormalizedSIFT)
318
                                                out<< ((unsigned int)floor(0.5+512.0f*(*pd)))<<" ";
319
                                        else
320
                                                out << setprecision(8) << pd[0] << " ";
321

    
322
                                        if ( (k+1)%20 == 0 ) out<<endl; //suggested by Martin Schneider
323

    
324
                                }
325
                                out<<endl;
326

    
327
                        }
328
                
329
                }else
330
                {
331
                        out<<_featureNum<<" 0"<<endl;
332
                        for(int i = 0; i < _featureNum; i++, pk+=4)
333
                        {
334
                                out<<pk[1]<<" "<<pk[0]<<" "<<pk[2]<<" " << pk[3]<<endl;
335
                        }
336
                }
337
        }
338
}
339

    
340
#ifdef DEBUG_SIFTGPU
341
void SiftPyramid::BeginDEBUG(const char *imagepath)
342
{
343
        if(imagepath && imagepath[0])
344
        {
345
                strcpy(_debug_path, imagepath);
346
                strcat(_debug_path, ".debug");
347
        }else
348
        {
349
                strcpy(_debug_path, ".debug");
350
        }
351

    
352
        mkdir(_debug_path);
353
        chmod(_debug_path, _S_IREAD | _S_IWRITE);
354
}
355

    
356
void SiftPyramid::StopDEBUG()
357
{
358
        _debug_path[0] = 0;
359
}
360

    
361

    
362
void SiftPyramid::WriteTextureForDEBUG(GLTexImage * tex, const char *namet, ...)
363
{
364
        char name[_MAX_PATH];
365
        char * p = name, * ps = _debug_path;
366
        while(*ps) *p++ = *ps ++;
367
        *p++ = '/';
368
        va_list marker;
369
        va_start(marker, namet);
370
        vsprintf(p, namet, marker);
371
        va_end(marker);
372
        unsigned int imID;
373
        int width = tex->GetImgWidth();
374
        int height = tex->GetImgHeight();
375
        float* buffer1 = new float[ width * height  * 4];
376
        float* buffer2 = new float[ width * height  * 4];
377

    
378
        //read data back
379
        glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
380
        tex->AttachToFBO(0);
381
        tex->FitTexViewPort();
382
        glReadPixels(0, 0, width, height, GL_RGBA , GL_FLOAT, buffer1);
383

    
384
        //Tiffs saved with IL are flipped
385
        for(int i = 0; i < height; i++)
386
        {
387
                memcpy(buffer2 + i * width * 4, 
388
                        buffer1 + (height - i - 1) * width * 4,  
389
                        width * 4 * sizeof(float));
390
        }
391

    
392
        //save data as floating point tiff file
393
        ilGenImages(1, &imID);
394
        ilBindImage(imID); 
395
        ilEnable(IL_FILE_OVERWRITE);
396
        ilTexImage(width, height, 1, 4, IL_RGBA, IL_FLOAT, buffer2);
397
        ilSave(IL_TIF, name); 
398
        ilDeleteImages(1, &imID); 
399

    
400
        delete buffer1;
401
        delete buffer2;
402
        glReadBuffer(GL_NONE);
403
}
404

    
405

    
406
#endif