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 |
|