| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | #include "GL/glew.h" |
| | #include <string.h> |
| | #include <iostream> |
| | #include <iomanip> |
| | #include <vector> |
| | #include <algorithm> |
| | #include <fstream> |
| | #include <math.h> |
| | using namespace std; |
| |
|
| | #include "GlobalUtil.h" |
| | #include "SiftPyramid.h" |
| | #include "SiftGPU.h" |
| |
|
| |
|
| | #ifdef DEBUG_SIFTGPU |
| | #include "IL/il.h" |
| | #include "direct.h" |
| | #include "io.h" |
| | #include <sys/stat.h> |
| | #endif |
| |
|
| |
|
| |
|
| | void SiftPyramid::RunSIFT(GLTexInput*input) |
| | { |
| | CleanupBeforeSIFT(); |
| |
|
| | if(_existing_keypoints & SIFT_SKIP_FILTERING) |
| | { |
| |
|
| | }else |
| | { |
| | GlobalUtil::StartTimer("Build Pyramid"); |
| | BuildPyramid(input); |
| | GlobalUtil::StopTimer(); |
| | _timing[0] = GetElapsedTime(); |
| | } |
| |
|
| |
|
| | if(_existing_keypoints) |
| | { |
| | |
| | GlobalUtil::StartTimer("Upload Feature List"); |
| | if(!(_existing_keypoints & SIFT_SKIP_FILTERING)) ComputeGradient(); |
| | GenerateFeatureListTex(); |
| | GlobalUtil::StopTimer(); |
| | _timing[2] = GetElapsedTime(); |
| | }else |
| | { |
| |
|
| | GlobalUtil::StartTimer("Detect Keypoints"); |
| | DetectKeypointsEX(); |
| | GlobalUtil::StopTimer(); |
| | _timing[1] = GetElapsedTime(); |
| |
|
| | if(GlobalUtil::_ListGenGPU ==1) |
| | { |
| | GlobalUtil::StartTimer("Get Feature List"); |
| | GenerateFeatureList(); |
| | GlobalUtil::StopTimer(); |
| |
|
| | }else |
| | { |
| | GlobalUtil::StartTimer("Transfer Feature List"); |
| | GenerateFeatureListCPU(); |
| | GlobalUtil::StopTimer(); |
| | } |
| | LimitFeatureCount(0); |
| | _timing[2] = GetElapsedTime(); |
| | } |
| |
|
| |
|
| |
|
| | if(_existing_keypoints& SIFT_SKIP_ORIENTATION) |
| | { |
| | |
| | }else if(GlobalUtil::_MaxOrientation>0) |
| | { |
| | |
| | GlobalUtil::StartTimer("Feature Orientations"); |
| | GetFeatureOrientations(); |
| | GlobalUtil::StopTimer(); |
| | _timing[3] = GetElapsedTime(); |
| |
|
| | |
| | if(GlobalUtil::_MaxOrientation >1 && !_existing_keypoints && !GlobalUtil::_FixedOrientation) |
| | { |
| | GlobalUtil::StartTimer("MultiO Feature List"); |
| | ReshapeFeatureListCPU(); |
| | LimitFeatureCount(1); |
| | GlobalUtil::StopTimer(); |
| | _timing[4] = GetElapsedTime(); |
| | } |
| | }else |
| | { |
| | GlobalUtil::StartTimer("Feature Orientations"); |
| | GetSimplifiedOrientation(); |
| | GlobalUtil::StopTimer(); |
| | _timing[3] = GetElapsedTime(); |
| | } |
| |
|
| | PrepareBuffer(); |
| |
|
| | if(_existing_keypoints & SIFT_SKIP_ORIENTATION) |
| | { |
| | |
| | }else |
| | { |
| | GlobalUtil::StartTimer("Download Keypoints"); |
| | #ifdef NO_DUPLICATE_DOWNLOAD |
| | if(GlobalUtil::_MaxOrientation < 2 || GlobalUtil::_FixedOrientation) |
| | #endif |
| | DownloadKeypoints(); |
| | GlobalUtil::StopTimer(); |
| | _timing[5] = GetElapsedTime(); |
| | } |
| |
|
| |
|
| |
|
| | if(GlobalUtil::_DescriptorPPT) |
| | { |
| | |
| | GlobalUtil::StartTimer("Get Descriptor"); |
| | GetFeatureDescriptors(); |
| | GlobalUtil::StopTimer(); |
| | _timing[6] = GetElapsedTime(); |
| | } |
| |
|
| | |
| | _existing_keypoints = 0; |
| | _keypoint_index.resize(0); |
| |
|
| | if(GlobalUtil::_UseSiftGPUEX) |
| | { |
| | GlobalUtil::StartTimer("Gen. Display VBO"); |
| | GenerateFeatureDisplayVBO(); |
| | GlobalUtil::StopTimer(); |
| | _timing[7] = GlobalUtil::GetElapsedTime(); |
| | } |
| | |
| | CleanUpAfterSIFT(); |
| | } |
| |
|
| |
|
| | void SiftPyramid::LimitFeatureCount(int have_keylist) |
| | { |
| |
|
| | if(GlobalUtil::_FeatureCountThreshold <= 0 || _existing_keypoints) return; |
| | |
| | |
| |
|
| | if(GlobalUtil::_TruncateMethod == 2) |
| | { |
| | int i = 0, new_feature_num = 0, level_num = param._dog_level_num * _octave_num; |
| | for(; new_feature_num < _FeatureCountThreshold && i < level_num; ++i) new_feature_num += _levelFeatureNum[i]; |
| | for(; i < level_num; ++i) _levelFeatureNum[i] = 0; |
| |
|
| | if(new_feature_num < _featureNum) |
| | { |
| | _featureNum = new_feature_num; |
| | if(GlobalUtil::_verbose ) |
| | { |
| | std::cout<<"#Features Reduced:\t"<<_featureNum<<endl; |
| | } |
| | } |
| | }else |
| | { |
| | int i = 0, num_to_erase = 0; |
| | while(_featureNum - _levelFeatureNum[i] > _FeatureCountThreshold) |
| | { |
| | num_to_erase += _levelFeatureNum[i]; |
| | _featureNum -= _levelFeatureNum[i]; |
| | _levelFeatureNum[i++] = 0; |
| | } |
| | if(num_to_erase > 0 && have_keylist) |
| | { |
| | _keypoint_buffer.erase(_keypoint_buffer.begin(), _keypoint_buffer.begin() + num_to_erase * 4); |
| | } |
| | if(GlobalUtil::_verbose && num_to_erase > 0) |
| | { |
| | std::cout<<"#Features Reduced:\t"<<_featureNum<<endl; |
| | } |
| | } |
| |
|
| |
|
| | } |
| |
|
| | void SiftPyramid::PrepareBuffer() |
| | { |
| | |
| | |
| | if(!(_existing_keypoints & SIFT_SKIP_ORIENTATION)) |
| | { |
| | |
| | _keypoint_buffer.resize(4 * (_featureNum + GlobalUtil::_texMaxDim)); |
| | } |
| | if(GlobalUtil::_DescriptorPPT) |
| | { |
| | |
| | _descriptor_buffer.resize(128 * _featureNum + 16 * GlobalUtil::_texMaxDim); |
| | } |
| |
|
| | } |
| |
|
| | int SiftPyramid:: GetRequiredOctaveNum(int inputsz) |
| | { |
| | |
| | |
| | int num = (int) floor (log ( inputsz * 2.0 / GlobalUtil::_texMinDim )/log(2.0)); |
| | return num <= 0 ? 1 : num; |
| | } |
| |
|
| | void SiftPyramid::CopyFeatureVector(float*keys, float *descriptors) |
| | { |
| | if(keys) memcpy(keys, &_keypoint_buffer[0], 4*_featureNum*sizeof(float)); |
| | if(descriptors) memcpy(descriptors, &_descriptor_buffer[0], 128*_featureNum*sizeof(float)); |
| | } |
| |
|
| | void SiftPyramid:: SetKeypointList(int num, const float * keys, int run_on_current, int skip_orientation) |
| | { |
| | |
| | |
| | if(num <=0) return; |
| | _featureNum = num; |
| | |
| | _keypoint_buffer.resize(num * 4); |
| | memcpy(&_keypoint_buffer[0], keys, 4 * num * sizeof(float)); |
| | |
| | _existing_keypoints = SIFT_SKIP_DETECTION; |
| | |
| | if(run_on_current) _existing_keypoints |= SIFT_SKIP_FILTERING; |
| | |
| | if(skip_orientation) _existing_keypoints |= SIFT_SKIP_ORIENTATION; |
| | |
| | if(skip_orientation == -1) _existing_keypoints |= SIFT_RECT_DESCRIPTION; |
| | } |
| |
|
| |
|
| | void SiftPyramid::SaveSIFT(const char * szFileName) |
| | { |
| | if (_featureNum <=0) return; |
| | float * pk = &_keypoint_buffer[0]; |
| |
|
| | if(GlobalUtil::_BinarySIFT) |
| | { |
| | std::ofstream out(szFileName, ios::binary); |
| | out.write((char* )(&_featureNum), sizeof(int)); |
| |
|
| | if(GlobalUtil::_DescriptorPPT) |
| | { |
| | int dim = 128; |
| | out.write((char* )(&dim), sizeof(int)); |
| | float * pd = &_descriptor_buffer[0] ; |
| | for(int i = 0; i < _featureNum; i++, pk+=4, pd +=128) |
| | { |
| | out.write((char* )(pk +1), sizeof(float)); |
| | out.write((char* )(pk), sizeof(float)); |
| | out.write((char* )(pk+2), 2 * sizeof(float)); |
| | out.write((char* )(pd), 128 * sizeof(float)); |
| | } |
| | }else |
| | { |
| | int dim = 0; |
| | out.write((char* )(&dim), sizeof(int)); |
| | for(int i = 0; i < _featureNum; i++, pk+=4) |
| | { |
| | out.write((char* )(pk +1), sizeof(float)); |
| | out.write((char* )(pk), sizeof(float)); |
| | out.write((char* )(pk+2), 2 * sizeof(float)); |
| | } |
| | } |
| | }else |
| | { |
| | std::ofstream out(szFileName); |
| | out.flags(ios::fixed); |
| |
|
| | if(GlobalUtil::_DescriptorPPT) |
| | { |
| | float * pd = &_descriptor_buffer[0] ; |
| | out<<_featureNum<<" 128"<<endl; |
| |
|
| | for(int i = 0; i < _featureNum; i++) |
| | { |
| | |
| | out<<setprecision(2) << pk[1]<<" "<<setprecision(2) << pk[0]<<" " |
| | <<setprecision(3) << pk[2]<<" " <<setprecision(3) << pk[3]<< endl; |
| |
|
| | |
| | pk+=4; |
| | for(int k = 0; k < 128; k ++, pd++) |
| | { |
| | if(GlobalUtil::_NormalizedSIFT) |
| | out<< ((unsigned int)floor(0.5+512.0f*(*pd)))<<" "; |
| | else |
| | out << setprecision(8) << pd[0] << " "; |
| |
|
| | if ( (k+1)%20 == 0 ) out<<endl; |
| |
|
| | } |
| | out<<endl; |
| |
|
| | } |
| |
|
| | }else |
| | { |
| | out<<_featureNum<<" 0"<<endl; |
| | for(int i = 0; i < _featureNum; i++, pk+=4) |
| | { |
| | out<<pk[1]<<" "<<pk[0]<<" "<<pk[2]<<" " << pk[3]<<endl; |
| | } |
| | } |
| | } |
| | } |
| |
|
| | #ifdef DEBUG_SIFTGPU |
| | void SiftPyramid::BeginDEBUG(const char *imagepath) |
| | { |
| | if(imagepath && imagepath[0]) |
| | { |
| | strcpy(_debug_path, imagepath); |
| | strcat(_debug_path, ".debug"); |
| | }else |
| | { |
| | strcpy(_debug_path, ".debug"); |
| | } |
| |
|
| | mkdir(_debug_path); |
| | chmod(_debug_path, _S_IREAD | _S_IWRITE); |
| | } |
| |
|
| | void SiftPyramid::StopDEBUG() |
| | { |
| | _debug_path[0] = 0; |
| | } |
| |
|
| |
|
| | void SiftPyramid::WriteTextureForDEBUG(GLTexImage * tex, const char *namet, ...) |
| | { |
| | char name[_MAX_PATH]; |
| | char * p = name, * ps = _debug_path; |
| | while(*ps) *p++ = *ps ++; |
| | *p++ = '/'; |
| | va_list marker; |
| | va_start(marker, namet); |
| | vsprintf(p, namet, marker); |
| | va_end(marker); |
| | unsigned int imID; |
| | int width = tex->GetImgWidth(); |
| | int height = tex->GetImgHeight(); |
| | float* buffer1 = new float[ width * height * 4]; |
| | float* buffer2 = new float[ width * height * 4]; |
| |
|
| | |
| | glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); |
| | tex->AttachToFBO(0); |
| | tex->FitTexViewPort(); |
| | glReadPixels(0, 0, width, height, GL_RGBA , GL_FLOAT, buffer1); |
| |
|
| | |
| | for(int i = 0; i < height; i++) |
| | { |
| | memcpy(buffer2 + i * width * 4, |
| | buffer1 + (height - i - 1) * width * 4, |
| | width * 4 * sizeof(float)); |
| | } |
| |
|
| | |
| | ilGenImages(1, &imID); |
| | ilBindImage(imID); |
| | ilEnable(IL_FILE_OVERWRITE); |
| | ilTexImage(width, height, 1, 4, IL_RGBA, IL_FLOAT, buffer2); |
| | ilSave(IL_TIF, name); |
| | ilDeleteImages(1, &imID); |
| |
|
| | delete buffer1; |
| | delete buffer2; |
| | glReadBuffer(GL_NONE); |
| | } |
| |
|
| |
|
| | #endif |
| |
|