SimpleSIFT.cpp
Go to the documentation of this file.
00001 
00002 //    File:        SimpleSIFT.cpp
00003 //    Author:      Changchang Wu
00004 //    Description : A simple example shows how to use SiftGPU and SiftMatchGPU
00005 //
00006 //
00007 //
00008 //    Copyright (c) 2007 University of North Carolina at Chapel Hill
00009 //    All Rights Reserved
00010 //
00011 //    Permission to use, copy, modify and distribute this software and its
00012 //    documentation for educational, research and non-profit purposes, without
00013 //    fee, and without a written agreement is hereby granted, provided that the
00014 //    above copyright notice and the following paragraph appear in all copies.
00015 //    
00016 //    The University of North Carolina at Chapel Hill make no representations
00017 //    about the suitability of this software for any purpose. It is provided
00018 //    'as is' without express or implied warranty. 
00019 //
00020 //    Please send BUG REPORTS to ccwu@cs.unc.edu
00021 //
00023 
00024 
00025 #include <stdlib.h>
00026 #include <vector>
00027 #include <iostream>
00028 using std::vector;
00029 using std::iostream;
00030 
00031 
00033 #if !defined(SIFTGPU_STATIC) && !defined(SIFTGPU_DLL_RUNTIME) 
00034 // SIFTGPU_STATIC comes from compiler
00035 #define SIFTGPU_DLL_RUNTIME
00036 // Load at runtime if the above macro defined
00037 // comment the macro above to use static linking
00038 #endif
00039 
00041 // define REMOTE_SIFTGPU to run computation in multi-process (Or remote) mode
00042 // in order to run on a remote machine, you need to start the server manually
00043 // This mode allows you use Multi-GPUs by creating multiple servers
00044 // #define REMOTE_SIFTGPU
00045 // #define REMOTE_SERVER        NULL
00046 // #define REMOTE_SERVER_PORT   7777
00047 
00048 
00050 //#define DEBUG_SIFTGPU  //define this to use the debug version in windows
00051 
00052 #ifdef _WIN32
00053     #ifdef SIFTGPU_DLL_RUNTIME
00054         #define WIN32_LEAN_AND_MEAN
00055         #include <windows.h>
00056         #define FREE_MYLIB FreeLibrary
00057         #define GET_MYPROC GetProcAddress
00058     #else
00059         //define this to get dll import definition for win32
00060         #define SIFTGPU_DLL
00061         #ifdef _DEBUG 
00062             #pragma comment(lib, "../../lib/siftgpu_d.lib")
00063         #else
00064             #pragma comment(lib, "../../lib/siftgpu.lib")
00065         #endif
00066     #endif
00067 #else
00068     #ifdef SIFTGPU_DLL_RUNTIME
00069         #include <dlfcn.h>
00070         #define FREE_MYLIB dlclose
00071         #define GET_MYPROC dlsym
00072     #endif
00073 #endif
00074 
00075 #include "../SiftGPU/SiftGPU.h"
00076 
00077 
00078 int main()
00079 {
00080 #ifdef SIFTGPU_DLL_RUNTIME
00081     #ifdef _WIN32
00082         #ifdef _DEBUG
00083             HMODULE  hsiftgpu = LoadLibrary("siftgpu_d.dll");
00084         #else
00085             HMODULE  hsiftgpu = LoadLibrary("siftgpu.dll");
00086         #endif
00087     #else
00088         void * hsiftgpu = dlopen("libsiftgpu.so", RTLD_LAZY);
00089     #endif
00090 
00091     if(hsiftgpu == NULL) return 0;
00092 
00093     #ifdef REMOTE_SIFTGPU
00094         ComboSiftGPU* (*pCreateRemoteSiftGPU) (int, char*) = NULL;
00095         pCreateRemoteSiftGPU = (ComboSiftGPU* (*) (int, char*)) GET_MYPROC(hsiftgpu, "CreateRemoteSiftGPU");
00096         ComboSiftGPU * combo = pCreateRemoteSiftGPU(REMOTE_SERVER_PORT, REMOTE_SERVER);
00097         SiftGPU* sift = combo;
00098         SiftMatchGPU* matcher = combo;
00099     #else
00100         SiftGPU* (*pCreateNewSiftGPU)(int) = NULL;
00101         SiftMatchGPU* (*pCreateNewSiftMatchGPU)(int) = NULL;
00102         pCreateNewSiftGPU = (SiftGPU* (*) (int)) GET_MYPROC(hsiftgpu, "CreateNewSiftGPU");
00103         pCreateNewSiftMatchGPU = (SiftMatchGPU* (*)(int)) GET_MYPROC(hsiftgpu, "CreateNewSiftMatchGPU");
00104         SiftGPU* sift = pCreateNewSiftGPU(1);
00105         SiftMatchGPU* matcher = pCreateNewSiftMatchGPU(4096);
00106     #endif
00107 
00108 #elif defined(REMOTE_SIFTGPU)
00109     ComboSiftGPU * combo = CreateRemoteSiftGPU(REMOTE_SERVER_PORT, REMOTE_SERVER);
00110     SiftGPU* sift = combo;
00111     SiftMatchGPU* matcher = combo;
00112 #else
00113     //this will use overloaded new operators
00114     SiftGPU  *sift = new SiftGPU;
00115     SiftMatchGPU *matcher = new SiftMatchGPU(4096);
00116 #endif
00117     vector<float > descriptors1(1), descriptors2(1);
00118     vector<SiftGPU::SiftKeypoint> keys1(1), keys2(1);    
00119     int num1, num2;
00120 
00121     //process parameters
00122     //The following parameters are default in V340
00123     //-m,       up to 2 orientations for each feature (change to single orientation by using -m 1)
00124     //-s        enable subpixel subscale (disable by using -s 0)
00125     
00126 
00127     char * argv[] = {"-fo", "-1",  "-v", "1", "-cuda"};//
00128     //-fo -1    staring from -1 octave 
00129     //-v 1      only print out # feature and overall time
00130     //-loweo    add a (.5, .5) offset
00131     //-tc <num> set a soft limit to number of detected features
00132     
00133     //NEW:  parameters for  GPU-selection
00134     //1. CUDA.                      Use parameter "-cuda", "[device_id]"
00135     //2. OpenGL + Windows.          Use "-winpos", "XxY" to set a location on a specific monitor/GPU
00136     //3. OpenGL + Other OS.         Use "-Display", "display_name" to select monitor/GPU (XLIB/GLUT)
00137 
00139     //You use CUDA for nVidia graphic cards by specifying
00140     //-cuda   : cuda implementation (fastest for smaller images)
00142 
00145     // First, texture reallocation happens when image size increases, and too many 
00146     // reallocation may lead to allocatoin failure.  You should be careful when using 
00147     // siftgpu on a set of images with VARYING imag sizes. It is recommended that you 
00148     // preset the allocation size to the largest width and largest height by using function
00149     // AllocationPyramid or prameter '-p' (e.g. "-p", "1024x768").
00150 
00151     // Second, there is a parameter you may not be aware of: the  allowed maximum working
00152     // dimension. All the SIFT octaves that needs a larger texture size will be skipped.
00153     // The default prameter is 2560 for the unpacked implementation and 3200 for the packed.
00154     // Those two default parameter is tuned to for 768MB of graphic memory. You should adjust
00155     // it for your own GPU memory. You can also use this to keep/skip the small featuers.
00156     // To change this, call function SetMaxDimension or use parameter "-maxd".
00158 
00159 
00160     int argc = sizeof(argv)/sizeof(char*);
00161     sift->ParseParam(argc, argv);
00162     
00164     //Only the following parameters can be changed after initialization (by calling ParseParam). 
00165     //-dw, -ofix, -ofix-not, -fo, -unn, -maxd, -b
00166     //to change other parameters at runtime, you need to first unload the dynamically loaded libaray
00167     //reload the libarary, then create a new siftgpu instance
00168 
00169 
00170     //Create a context for computation, and SiftGPU will be initialized automatically 
00171     //The same context can be used by SiftMatchGPU
00172     if(sift->CreateContextGL() != SiftGPU::SIFTGPU_FULL_SUPPORTED) return 0;
00173 
00174     if(sift->RunSIFT("../data/800-1.jpg"))
00175     {
00176         //Call SaveSIFT to save result to file, the format is the same as Lowe's
00177         //sift->SaveSIFT("../data/800-1.sift"); //Note that saving ASCII format is slow
00178 
00179         //get feature count
00180         num1 = sift->GetFeatureNum();
00181 
00182         //allocate memory
00183         keys1.resize(num1);    descriptors1.resize(128*num1);
00184 
00185         //reading back feature vectors is faster than writing files
00186         //if you dont need keys or descriptors, just put NULLs here
00187         sift->GetFeatureVector(&keys1[0], &descriptors1[0]);
00188         //this can be used to write your own sift file.            
00189     }
00190 
00191     //You can have at most one OpenGL-based SiftGPU (per process).
00192     //Normally, you should just create one, and reuse on all images. 
00193     //NEW: CUDA-implementation allows you to create multiple instances for multiple threads
00194     //Checkout src\TestWin\MultiThreadSIFT
00195     if(sift->RunSIFT("../data/640-1.jpg"))
00196     {
00197         num2 = sift->GetFeatureNum();
00198         keys2.resize(num2);    descriptors2.resize(128*num2);
00199         sift->GetFeatureVector(&keys2[0], &descriptors2[0]);
00200     }
00201 
00202     //Testing code to check how it works when image size varies
00203     //sift->RunSIFT("../data/256.jpg");sift->SaveSIFT("../data/256.sift.1");
00204     //sift->RunSIFT("../data/1024.jpg"); //this will result in pyramid reallocation
00205     //sift->RunSIFT("../data/256.jpg"); sift->SaveSIFT("../data/256.sift.2");
00206     //two sets of features for 256.jpg may have different order due to implementation
00207  
00208     //*************************************************************************
00210 
00211     //Method1, set new keypoints for the image you've just processed with siftgpu
00212     //say vector<SiftGPU::SiftKeypoint> mykeys;
00213     //sift->RunSIFT(mykeys.size(), &mykeys[0]); 
00214     //sift->RunSIFT(num2, &keys2[0], 1);         sift->SaveSIFT("../data/640-1.sift.2");
00215     //sift->RunSIFT(num2, &keys2[0], 0);        sift->SaveSIFT("../data/640-1.sift.3");
00216 
00217     //Method2, set keypoints for the next coming image
00218     //The difference of with method 1 is that method 1 skips gaussian filtering
00219     //SiftGPU::SiftKeypoint mykeys[100];
00220     //for(int i = 0; i < 100; ++i){
00221     //    mykeys[i].s = 1.0f;mykeys[i].o = 0.0f;
00222     //    mykeys[i].x = (i%10)*10.0f+50.0f;
00223     //    mykeys[i].y = (i/10)*10.0f+50.0f;
00224     //}
00225     //sift->SetKeypointList(100, mykeys, 0);
00226     //sift->RunSIFT("../data/800-1.jpg");                    sift->SaveSIFT("../data/800-1.sift.2");
00227     //### for comparing with method1: 
00228     //sift->RunSIFT("../data/800-1.jpg"); 
00229     //sift->RunSIFT(100, mykeys, 0);                          sift->SaveSIFT("../data/800-1.sift.3");
00230     //*********************************************************************************
00231 
00232 
00233     //**********************GPU SIFT MATCHING*********************************
00234     //**************************select shader language*************************
00235     //SiftMatchGPU will use the same shader lanaguage as SiftGPU by default
00236     //Before initialization, you can choose between glsl, and CUDA(if compiled). 
00237     //matcher->SetLanguage(SiftMatchGPU::SIFTMATCH_CUDA); // +i for the (i+1)-th device
00238 
00239     //Verify current OpenGL Context and initialize the Matcher;
00240     //If you don't have an OpenGL Context, call matcher->CreateContextGL instead;
00241     matcher->VerifyContextGL(); //must call once
00242 
00243     //Set descriptors to match, the first argument must be either 0 or 1
00244     //if you want to use more than 4096 or less than 4096
00245     //call matcher->SetMaxSift() to change the limit before calling setdescriptor
00246     matcher->SetDescriptors(0, num1, &descriptors1[0]); //image 1
00247     matcher->SetDescriptors(1, num2, &descriptors2[0]); //image 2
00248 
00249     //match and get result.    
00250     int (*match_buf)[2] = new int[num1][2];
00251     //use the default thresholds. Check the declaration in SiftGPU.h
00252     int num_match = matcher->GetSiftMatch(num1, match_buf);
00253     std::cout << num_match << " sift matches were found;\n";
00254     
00255     //enumerate all the feature matches
00256     for(int i  = 0; i < num_match; ++i)
00257     {
00258         //How to get the feature matches: 
00259         //SiftGPU::SiftKeypoint & key1 = keys1[match_buf[i][0]];
00260         //SiftGPU::SiftKeypoint & key2 = keys2[match_buf[i][1]];
00261         //key1 in the first image matches with key2 in the second image
00262     }
00263 
00264     //*****************GPU Guided SIFT MATCHING***************
00265     //example: define a homography, and use default threshold 32 to search in a 64x64 window
00266     //float h[3][3] = {{0.8f, 0, 0}, {0, 0.8f, 0}, {0, 0, 1.0f}};
00267     //matcher->SetFeatureLocation(0, &keys1[0]); //SetFeatureLocaiton after SetDescriptors
00268     //matcher->SetFeatureLocation(1, &keys2[0]);
00269     //num_match = matcher->GetGuidedSiftMatch(num1, match_buf, h, NULL);
00270     //std::cout << num_match << " guided sift matches were found;\n";
00271     //if you can want to use a Fundamental matrix, check the function definition
00272 
00273     // clean up..
00274     delete[] match_buf;
00275 #ifdef REMOTE_SIFTGPU
00276     delete combo;
00277 #else
00278     delete sift;
00279     delete matcher;
00280 #endif
00281 
00282 #ifdef SIFTGPU_DLL_RUNTIME
00283     FREE_MYLIB(hsiftgpu);
00284 #endif
00285     return 1;
00286 }
00287 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


rgbd_registration
Author(s): Ross Kidson
autogenerated on Thu May 23 2013 15:36:53