Project

General

Profile

Statistics
| Branch: | Revision:

root / rgbdslam / external / siftgpu / src / TestWin / SimpleSIFT.cpp @ 9240aaa3

History | View | Annotate | Download (12.1 KB)

1
////////////////////////////////////////////////////////////////////////////
2
//    File:        SimpleSIFT.cpp
3
//    Author:      Changchang Wu
4
//    Description : A simple example shows how to use SiftGPU and SiftMatchGPU
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 <stdlib.h>
26
#include <vector>
27
#include <iostream>
28
using std::vector;
29
using std::iostream;
30

    
31

    
32
////////////////////////////////////////////////////////////////////////////
33
#if !defined(SIFTGPU_STATIC) && !defined(SIFTGPU_DLL_RUNTIME) 
34
// SIFTGPU_STATIC comes from compiler
35
#define SIFTGPU_DLL_RUNTIME
36
// Load at runtime if the above macro defined
37
// comment the macro above to use static linking
38
#endif
39

    
40
////////////////////////////////////////////////////////////////////////////
41
// define REMOTE_SIFTGPU to run computation in multi-process (Or remote) mode
42
// in order to run on a remote machine, you need to start the server manually
43
// This mode allows you use Multi-GPUs by creating multiple servers
44
// #define REMOTE_SIFTGPU
45
// #define REMOTE_SERVER        NULL
46
// #define REMOTE_SERVER_PORT   7777
47

    
48

    
49
///////////////////////////////////////////////////////////////////////////
50
//#define DEBUG_SIFTGPU  //define this to use the debug version in windows
51

    
52
#ifdef _WIN32
53
    #ifdef SIFTGPU_DLL_RUNTIME
54
        #define WIN32_LEAN_AND_MEAN
55
        #include <windows.h>
56
        #define FREE_MYLIB FreeLibrary
57
        #define GET_MYPROC GetProcAddress
58
    #else
59
        //define this to get dll import definition for win32
60
        #define SIFTGPU_DLL
61
        #ifdef _DEBUG 
62
            #pragma comment(lib, "../../lib/siftgpu_d.lib")
63
        #else
64
            #pragma comment(lib, "../../lib/siftgpu.lib")
65
        #endif
66
    #endif
67
#else
68
    #ifdef SIFTGPU_DLL_RUNTIME
69
        #include <dlfcn.h>
70
        #define FREE_MYLIB dlclose
71
        #define GET_MYPROC dlsym
72
    #endif
73
#endif
74

    
75
#include "../SiftGPU/SiftGPU.h"
76

    
77

    
78
int main()
79
{
80
#ifdef SIFTGPU_DLL_RUNTIME
81
    #ifdef _WIN32
82
        #ifdef _DEBUG
83
            HMODULE  hsiftgpu = LoadLibrary("siftgpu_d.dll");
84
        #else
85
            HMODULE  hsiftgpu = LoadLibrary("siftgpu.dll");
86
        #endif
87
    #else
88
        void * hsiftgpu = dlopen("libsiftgpu.so", RTLD_LAZY);
89
    #endif
90

    
91
    if(hsiftgpu == NULL) return 0;
92

    
93
    #ifdef REMOTE_SIFTGPU
94
        ComboSiftGPU* (*pCreateRemoteSiftGPU) (int, char*) = NULL;
95
        pCreateRemoteSiftGPU = (ComboSiftGPU* (*) (int, char*)) GET_MYPROC(hsiftgpu, "CreateRemoteSiftGPU");
96
        ComboSiftGPU * combo = pCreateRemoteSiftGPU(REMOTE_SERVER_PORT, REMOTE_SERVER);
97
        SiftGPU* sift = combo;
98
        SiftMatchGPU* matcher = combo;
99
    #else
100
        SiftGPU* (*pCreateNewSiftGPU)(int) = NULL;
101
        SiftMatchGPU* (*pCreateNewSiftMatchGPU)(int) = NULL;
102
        pCreateNewSiftGPU = (SiftGPU* (*) (int)) GET_MYPROC(hsiftgpu, "CreateNewSiftGPU");
103
        pCreateNewSiftMatchGPU = (SiftMatchGPU* (*)(int)) GET_MYPROC(hsiftgpu, "CreateNewSiftMatchGPU");
104
        SiftGPU* sift = pCreateNewSiftGPU(1);
105
        SiftMatchGPU* matcher = pCreateNewSiftMatchGPU(4096);
106
    #endif
107

    
108
#elif defined(REMOTE_SIFTGPU)
109
    ComboSiftGPU * combo = CreateRemoteSiftGPU(REMOTE_SERVER_PORT, REMOTE_SERVER);
110
    SiftGPU* sift = combo;
111
    SiftMatchGPU* matcher = combo;
112
#else
113
    //this will use overloaded new operators
114
    SiftGPU  *sift = new SiftGPU;
115
    SiftMatchGPU *matcher = new SiftMatchGPU(4096);
116
#endif
117
    vector<float > descriptors1(1), descriptors2(1);
118
    vector<SiftGPU::SiftKeypoint> keys1(1), keys2(1);    
119
    int num1, num2;
120

    
121
    //process parameters
122
    //The following parameters are default in V340
123
    //-m,       up to 2 orientations for each feature (change to single orientation by using -m 1)
124
    //-s        enable subpixel subscale (disable by using -s 0)
125
    
126

    
127
    char * argv[] = {"-fo", "-1",  "-v", "1", "-cuda"};//
128
    //-fo -1    staring from -1 octave 
129
    //-v 1      only print out # feature and overall time
130
    //-loweo    add a (.5, .5) offset
131
    //-tc <num> set a soft limit to number of detected features
132
    
133
    //NEW:  parameters for  GPU-selection
134
    //1. CUDA.                      Use parameter "-cuda", "[device_id]"
135
    //2. OpenGL + Windows.          Use "-winpos", "XxY" to set a location on a specific monitor/GPU
136
    //3. OpenGL + Other OS.         Use "-Display", "display_name" to select monitor/GPU (XLIB/GLUT)
137

    
138
    //////////////////////////////////////////////////////////////////////////////////////
139
    //You use CUDA for nVidia graphic cards by specifying
140
    //-cuda   : cuda implementation (fastest for smaller images)
141
    /////////////////////////////////////////////////////////////////////////////////////
142

    
143
    //////////////////////////////////////////////////////////////////////////////////////
144
    ////////////////////////Two Important Parameters///////////////////////////
145
    // First, texture reallocation happens when image size increases, and too many 
146
    // reallocation may lead to allocatoin failure.  You should be careful when using 
147
    // siftgpu on a set of images with VARYING imag sizes. It is recommended that you 
148
    // preset the allocation size to the largest width and largest height by using function
149
    // AllocationPyramid or prameter '-p' (e.g. "-p", "1024x768").
150

    
151
    // Second, there is a parameter you may not be aware of: the  allowed maximum working
152
    // dimension. All the SIFT octaves that needs a larger texture size will be skipped.
153
    // The default prameter is 2560 for the unpacked implementation and 3200 for the packed.
154
    // Those two default parameter is tuned to for 768MB of graphic memory. You should adjust
155
    // it for your own GPU memory. You can also use this to keep/skip the small featuers.
156
    // To change this, call function SetMaxDimension or use parameter "-maxd".
157
    //////////////////////////////////////////////////////////////////////////////////////
158

    
159

    
160
    int argc = sizeof(argv)/sizeof(char*);
161
    sift->ParseParam(argc, argv);
162
    
163
    ///////////////////////////////////////////////////////////////////////
164
    //Only the following parameters can be changed after initialization (by calling ParseParam). 
165
    //-dw, -ofix, -ofix-not, -fo, -unn, -maxd, -b
166
    //to change other parameters at runtime, you need to first unload the dynamically loaded libaray
167
    //reload the libarary, then create a new siftgpu instance
168

    
169

    
170
    //Create a context for computation, and SiftGPU will be initialized automatically 
171
    //The same context can be used by SiftMatchGPU
172
    if(sift->CreateContextGL() != SiftGPU::SIFTGPU_FULL_SUPPORTED) return 0;
173

    
174
    if(sift->RunSIFT("../data/800-1.jpg"))
175
    {
176
        //Call SaveSIFT to save result to file, the format is the same as Lowe's
177
        //sift->SaveSIFT("../data/800-1.sift"); //Note that saving ASCII format is slow
178

    
179
        //get feature count
180
        num1 = sift->GetFeatureNum();
181

    
182
        //allocate memory
183
        keys1.resize(num1);    descriptors1.resize(128*num1);
184

    
185
        //reading back feature vectors is faster than writing files
186
        //if you dont need keys or descriptors, just put NULLs here
187
        sift->GetFeatureVector(&keys1[0], &descriptors1[0]);
188
        //this can be used to write your own sift file.            
189
    }
190

    
191
    //You can have at most one OpenGL-based SiftGPU (per process).
192
    //Normally, you should just create one, and reuse on all images. 
193
    //NEW: CUDA-implementation allows you to create multiple instances for multiple threads
194
    //Checkout src\TestWin\MultiThreadSIFT
195
    if(sift->RunSIFT("../data/640-1.jpg"))
196
    {
197
        num2 = sift->GetFeatureNum();
198
        keys2.resize(num2);    descriptors2.resize(128*num2);
199
        sift->GetFeatureVector(&keys2[0], &descriptors2[0]);
200
    }
201

    
202
    //Testing code to check how it works when image size varies
203
    //sift->RunSIFT("../data/256.jpg");sift->SaveSIFT("../data/256.sift.1");
204
    //sift->RunSIFT("../data/1024.jpg"); //this will result in pyramid reallocation
205
    //sift->RunSIFT("../data/256.jpg"); sift->SaveSIFT("../data/256.sift.2");
206
    //two sets of features for 256.jpg may have different order due to implementation
207
 
208
    //*************************************************************************
209
    /////compute descriptors for user-specified keypoints (with or without orientations)
210

    
211
    //Method1, set new keypoints for the image you've just processed with siftgpu
212
    //say vector<SiftGPU::SiftKeypoint> mykeys;
213
    //sift->RunSIFT(mykeys.size(), &mykeys[0]); 
214
    //sift->RunSIFT(num2, &keys2[0], 1);         sift->SaveSIFT("../data/640-1.sift.2");
215
    //sift->RunSIFT(num2, &keys2[0], 0);        sift->SaveSIFT("../data/640-1.sift.3");
216

    
217
    //Method2, set keypoints for the next coming image
218
    //The difference of with method 1 is that method 1 skips gaussian filtering
219
    //SiftGPU::SiftKeypoint mykeys[100];
220
    //for(int i = 0; i < 100; ++i){
221
    //    mykeys[i].s = 1.0f;mykeys[i].o = 0.0f;
222
    //    mykeys[i].x = (i%10)*10.0f+50.0f;
223
    //    mykeys[i].y = (i/10)*10.0f+50.0f;
224
    //}
225
    //sift->SetKeypointList(100, mykeys, 0);
226
    //sift->RunSIFT("../data/800-1.jpg");                    sift->SaveSIFT("../data/800-1.sift.2");
227
    //### for comparing with method1: 
228
    //sift->RunSIFT("../data/800-1.jpg"); 
229
    //sift->RunSIFT(100, mykeys, 0);                          sift->SaveSIFT("../data/800-1.sift.3");
230
    //*********************************************************************************
231

    
232

    
233
    //**********************GPU SIFT MATCHING*********************************
234
    //**************************select shader language*************************
235
    //SiftMatchGPU will use the same shader lanaguage as SiftGPU by default
236
    //Before initialization, you can choose between glsl, and CUDA(if compiled). 
237
    //matcher->SetLanguage(SiftMatchGPU::SIFTMATCH_CUDA); // +i for the (i+1)-th device
238

    
239
    //Verify current OpenGL Context and initialize the Matcher;
240
    //If you don't have an OpenGL Context, call matcher->CreateContextGL instead;
241
    matcher->VerifyContextGL(); //must call once
242

    
243
    //Set descriptors to match, the first argument must be either 0 or 1
244
    //if you want to use more than 4096 or less than 4096
245
    //call matcher->SetMaxSift() to change the limit before calling setdescriptor
246
    matcher->SetDescriptors(0, num1, &descriptors1[0]); //image 1
247
    matcher->SetDescriptors(1, num2, &descriptors2[0]); //image 2
248

    
249
    //match and get result.    
250
    int (*match_buf)[2] = new int[num1][2];
251
    //use the default thresholds. Check the declaration in SiftGPU.h
252
    int num_match = matcher->GetSiftMatch(num1, match_buf);
253
    std::cout << num_match << " sift matches were found;\n";
254
    
255
    //enumerate all the feature matches
256
    for(int i  = 0; i < num_match; ++i)
257
    {
258
        //How to get the feature matches: 
259
        //SiftGPU::SiftKeypoint & key1 = keys1[match_buf[i][0]];
260
        //SiftGPU::SiftKeypoint & key2 = keys2[match_buf[i][1]];
261
        //key1 in the first image matches with key2 in the second image
262
    }
263

    
264
    //*****************GPU Guided SIFT MATCHING***************
265
    //example: define a homography, and use default threshold 32 to search in a 64x64 window
266
    //float h[3][3] = {{0.8f, 0, 0}, {0, 0.8f, 0}, {0, 0, 1.0f}};
267
    //matcher->SetFeatureLocation(0, &keys1[0]); //SetFeatureLocaiton after SetDescriptors
268
    //matcher->SetFeatureLocation(1, &keys2[0]);
269
    //num_match = matcher->GetGuidedSiftMatch(num1, match_buf, h, NULL);
270
    //std::cout << num_match << " guided sift matches were found;\n";
271
    //if you can want to use a Fundamental matrix, check the function definition
272

    
273
    // clean up..
274
    delete[] match_buf;
275
#ifdef REMOTE_SIFTGPU
276
    delete combo;
277
#else
278
    delete sift;
279
    delete matcher;
280
#endif
281

    
282
#ifdef SIFTGPU_DLL_RUNTIME
283
    FREE_MYLIB(hsiftgpu);
284
#endif
285
    return 1;
286
}
287