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