00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00023
00024
00025 #include "GL/glew.h"
00026 #include <string.h>
00027 #include <iostream>
00028 #include <iomanip>
00029 #include <vector>
00030 #include <algorithm>
00031 #include <fstream>
00032 #include <math.h>
00033 using namespace std;
00034
00035 #include "GlobalUtil.h"
00036 #include "SiftPyramid.h"
00037 #include "SiftGPU.h"
00038
00039
00040 #ifdef DEBUG_SIFTGPU
00041 #include "IL/il.h"
00042 #include "direct.h"
00043 #include "io.h"
00044 #include <sys/stat.h>
00045 #endif
00046
00047
00048
00049 void SiftPyramid::RunSIFT(GLTexInput*input)
00050 {
00051 CleanupBeforeSIFT();
00052
00053 if(_existing_keypoints & SIFT_SKIP_FILTERING)
00054 {
00055
00056 }else
00057 {
00058 GlobalUtil::StartTimer("Build Pyramid");
00059 BuildPyramid(input);
00060 GlobalUtil::StopTimer();
00061 _timing[0] = GetElapsedTime();
00062 }
00063
00064
00065 if(_existing_keypoints)
00066 {
00067
00068 GlobalUtil::StartTimer("Upload Feature List");
00069 if(!(_existing_keypoints & SIFT_SKIP_FILTERING)) ComputeGradient();
00070 GenerateFeatureListTex();
00071 GlobalUtil::StopTimer();
00072 _timing[2] = GetElapsedTime();
00073 }else
00074 {
00075
00076 GlobalUtil::StartTimer("Detect Keypoints");
00077 DetectKeypointsEX();
00078 GlobalUtil::StopTimer();
00079 _timing[1] = GetElapsedTime();
00080
00081 if(GlobalUtil::_ListGenGPU ==1)
00082 {
00083 GlobalUtil::StartTimer("Get Feature List");
00084 GenerateFeatureList();
00085 GlobalUtil::StopTimer();
00086
00087 }else
00088 {
00089 GlobalUtil::StartTimer("Transfer Feature List");
00090 GenerateFeatureListCPU();
00091 GlobalUtil::StopTimer();
00092 }
00093 LimitFeatureCount(0);
00094 _timing[2] = GetElapsedTime();
00095 }
00096
00097
00098
00099 if(_existing_keypoints& SIFT_SKIP_ORIENTATION)
00100 {
00101
00102 }else if(GlobalUtil::_MaxOrientation>0)
00103 {
00104
00105 GlobalUtil::StartTimer("Feature Orientations");
00106 GetFeatureOrientations();
00107 GlobalUtil::StopTimer();
00108 _timing[3] = GetElapsedTime();
00109
00110
00111 if(GlobalUtil::_MaxOrientation >1 && !_existing_keypoints && !GlobalUtil::_FixedOrientation)
00112 {
00113 GlobalUtil::StartTimer("MultiO Feature List");
00114 ReshapeFeatureListCPU();
00115 LimitFeatureCount(1);
00116 GlobalUtil::StopTimer();
00117 _timing[4] = GetElapsedTime();
00118 }
00119 }else
00120 {
00121 GlobalUtil::StartTimer("Feature Orientations");
00122 GetSimplifiedOrientation();
00123 GlobalUtil::StopTimer();
00124 _timing[3] = GetElapsedTime();
00125 }
00126
00127 PrepareBuffer();
00128
00129 if(_existing_keypoints & SIFT_SKIP_ORIENTATION)
00130 {
00131
00132 }else
00133 {
00134 GlobalUtil::StartTimer("Download Keypoints");
00135 #ifdef NO_DUPLICATE_DOWNLOAD
00136 if(GlobalUtil::_MaxOrientation < 2 || GlobalUtil::_FixedOrientation)
00137 #endif
00138 DownloadKeypoints();
00139 GlobalUtil::StopTimer();
00140 _timing[5] = GetElapsedTime();
00141 }
00142
00143
00144
00145 if(GlobalUtil::_DescriptorPPT)
00146 {
00147
00148 GlobalUtil::StartTimer("Get Descriptor");
00149 GetFeatureDescriptors();
00150 GlobalUtil::StopTimer();
00151 _timing[6] = GetElapsedTime();
00152 }
00153
00154
00155 _existing_keypoints = 0;
00156 _keypoint_index.resize(0);
00157
00158 if(GlobalUtil::_UseSiftGPUEX)
00159 {
00160 GlobalUtil::StartTimer("Gen. Display VBO");
00161 GenerateFeatureDisplayVBO();
00162 GlobalUtil::StopTimer();
00163 _timing[7] = GlobalUtil::GetElapsedTime();
00164 }
00165
00166 CleanUpAfterSIFT();
00167 }
00168
00169
00170 void SiftPyramid::LimitFeatureCount(int have_keylist)
00171 {
00172
00173 if(GlobalUtil::_FeatureCountThreshold <= 0 || _existing_keypoints) return;
00175
00176
00177 if(GlobalUtil::_TruncateMethod == 2)
00178 {
00179 int i = 0, new_feature_num = 0, level_num = param._dog_level_num * _octave_num;
00180 for(; new_feature_num < _FeatureCountThreshold && i < level_num; ++i) new_feature_num += _levelFeatureNum[i];
00181 for(; i < level_num; ++i) _levelFeatureNum[i] = 0;
00182
00183 if(new_feature_num < _featureNum)
00184 {
00185 _featureNum = new_feature_num;
00186 if(GlobalUtil::_verbose )
00187 {
00188 std::cout<<"#Features Reduced:\t"<<_featureNum<<endl;
00189 }
00190 }
00191 }else
00192 {
00193 int i = 0, num_to_erase = 0;
00194 while(_featureNum - _levelFeatureNum[i] > _FeatureCountThreshold)
00195 {
00196 num_to_erase += _levelFeatureNum[i];
00197 _featureNum -= _levelFeatureNum[i];
00198 _levelFeatureNum[i++] = 0;
00199 }
00200 if(num_to_erase > 0 && have_keylist)
00201 {
00202 _keypoint_buffer.erase(_keypoint_buffer.begin(), _keypoint_buffer.begin() + num_to_erase * 4);
00203 }
00204 if(GlobalUtil::_verbose && num_to_erase > 0)
00205 {
00206 std::cout<<"#Features Reduced:\t"<<_featureNum<<endl;
00207 }
00208 }
00209
00210
00211 }
00212
00213 void SiftPyramid::PrepareBuffer()
00214 {
00215
00216
00217 if(!(_existing_keypoints & SIFT_SKIP_ORIENTATION))
00218 {
00219
00220 _keypoint_buffer.resize(4 * (_featureNum + GlobalUtil::_texMaxDim));
00221 }
00222 if(GlobalUtil::_DescriptorPPT)
00223 {
00224
00225 _descriptor_buffer.resize(128 * _featureNum + 16 * GlobalUtil::_texMaxDim);
00226 }
00227
00228 }
00229
00230 int SiftPyramid:: GetRequiredOctaveNum(int inputsz)
00231 {
00232
00233
00234 int num = (int) floor (log ( inputsz * 2.0 / GlobalUtil::_texMinDim )/log(2.0));
00235 return num <= 0 ? 1 : num;
00236 }
00237
00238 void SiftPyramid::CopyFeatureVector(float*keys, float *descriptors)
00239 {
00240 if(keys) memcpy(keys, &_keypoint_buffer[0], 4*_featureNum*sizeof(float));
00241 if(descriptors) memcpy(descriptors, &_descriptor_buffer[0], 128*_featureNum*sizeof(float));
00242 }
00243
00244 void SiftPyramid:: SetKeypointList(int num, const float * keys, int run_on_current, int skip_orientation)
00245 {
00246
00247
00248 if(num <=0) return;
00249 _featureNum = num;
00251 _keypoint_buffer.resize(num * 4);
00252 memcpy(&_keypoint_buffer[0], keys, 4 * num * sizeof(float));
00253
00254 _existing_keypoints = SIFT_SKIP_DETECTION;
00255
00256 if(run_on_current) _existing_keypoints |= SIFT_SKIP_FILTERING;
00257
00258 if(skip_orientation) _existing_keypoints |= SIFT_SKIP_ORIENTATION;
00259
00260 if(skip_orientation == -1) _existing_keypoints |= SIFT_RECT_DESCRIPTION;
00261 }
00262
00263
00264 void SiftPyramid::SaveSIFT(const char * szFileName)
00265 {
00266 if (_featureNum <=0) return;
00267 float * pk = &_keypoint_buffer[0];
00268
00269 if(GlobalUtil::_BinarySIFT)
00270 {
00271 std::ofstream out(szFileName, ios::binary);
00272 out.write((char* )(&_featureNum), sizeof(int));
00273
00274 if(GlobalUtil::_DescriptorPPT)
00275 {
00276 int dim = 128;
00277 out.write((char* )(&dim), sizeof(int));
00278 float * pd = &_descriptor_buffer[0] ;
00279 for(int i = 0; i < _featureNum; i++, pk+=4, pd +=128)
00280 {
00281 out.write((char* )(pk +1), sizeof(float));
00282 out.write((char* )(pk), sizeof(float));
00283 out.write((char* )(pk+2), 2 * sizeof(float));
00284 out.write((char* )(pd), 128 * sizeof(float));
00285 }
00286 }else
00287 {
00288 int dim = 0;
00289 out.write((char* )(&dim), sizeof(int));
00290 for(int i = 0; i < _featureNum; i++, pk+=4)
00291 {
00292 out.write((char* )(pk +1), sizeof(float));
00293 out.write((char* )(pk), sizeof(float));
00294 out.write((char* )(pk+2), 2 * sizeof(float));
00295 }
00296 }
00297 }else
00298 {
00299 std::ofstream out(szFileName);
00300 out.flags(ios::fixed);
00301
00302 if(GlobalUtil::_DescriptorPPT)
00303 {
00304 float * pd = &_descriptor_buffer[0] ;
00305 out<<_featureNum<<" 128"<<endl;
00306
00307 for(int i = 0; i < _featureNum; i++)
00308 {
00309
00310 out<<setprecision(2) << pk[1]<<" "<<setprecision(2) << pk[0]<<" "
00311 <<setprecision(3) << pk[2]<<" " <<setprecision(3) << pk[3]<< endl;
00312
00314 pk+=4;
00315 for(int k = 0; k < 128; k ++, pd++)
00316 {
00317 if(GlobalUtil::_NormalizedSIFT)
00318 out<< ((unsigned int)floor(0.5+512.0f*(*pd)))<<" ";
00319 else
00320 out << setprecision(8) << pd[0] << " ";
00321
00322 if ( (k+1)%20 == 0 ) out<<endl;
00323
00324 }
00325 out<<endl;
00326
00327 }
00328
00329 }else
00330 {
00331 out<<_featureNum<<" 0"<<endl;
00332 for(int i = 0; i < _featureNum; i++, pk+=4)
00333 {
00334 out<<pk[1]<<" "<<pk[0]<<" "<<pk[2]<<" " << pk[3]<<endl;
00335 }
00336 }
00337 }
00338 }
00339
00340 #ifdef DEBUG_SIFTGPU
00341 void SiftPyramid::BeginDEBUG(const char *imagepath)
00342 {
00343 if(imagepath && imagepath[0])
00344 {
00345 strcpy(_debug_path, imagepath);
00346 strcat(_debug_path, ".debug");
00347 }else
00348 {
00349 strcpy(_debug_path, ".debug");
00350 }
00351
00352 mkdir(_debug_path);
00353 chmod(_debug_path, _S_IREAD | _S_IWRITE);
00354 }
00355
00356 void SiftPyramid::StopDEBUG()
00357 {
00358 _debug_path[0] = 0;
00359 }
00360
00361
00362 void SiftPyramid::WriteTextureForDEBUG(GLTexImage * tex, const char *namet, ...)
00363 {
00364 char name[_MAX_PATH];
00365 char * p = name, * ps = _debug_path;
00366 while(*ps) *p++ = *ps ++;
00367 *p++ = '/';
00368 va_list marker;
00369 va_start(marker, namet);
00370 vsprintf(p, namet, marker);
00371 va_end(marker);
00372 unsigned int imID;
00373 int width = tex->GetImgWidth();
00374 int height = tex->GetImgHeight();
00375 float* buffer1 = new float[ width * height * 4];
00376 float* buffer2 = new float[ width * height * 4];
00377
00378
00379 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
00380 tex->AttachToFBO(0);
00381 tex->FitTexViewPort();
00382 glReadPixels(0, 0, width, height, GL_RGBA , GL_FLOAT, buffer1);
00383
00384
00385 for(int i = 0; i < height; i++)
00386 {
00387 memcpy(buffer2 + i * width * 4,
00388 buffer1 + (height - i - 1) * width * 4,
00389 width * 4 * sizeof(float));
00390 }
00391
00392
00393 ilGenImages(1, &imID);
00394 ilBindImage(imID);
00395 ilEnable(IL_FILE_OVERWRITE);
00396 ilTexImage(width, height, 1, 4, IL_RGBA, IL_FLOAT, buffer2);
00397 ilSave(IL_TIF, name);
00398 ilDeleteImages(1, &imID);
00399
00400 delete[] buffer1;
00401 delete[] buffer2;
00402 glReadBuffer(GL_NONE);
00403 }
00404
00405
00406 #endif