📄 siftgpu.cpp
字号:
////////////////////////////////////////////////////////////////////////////
// File: SiftGPU.cpp
// Author: Changchang Wu
// Description : Implementation of the SIFTGPU classes.
// SiftGPU: The SiftGPU Tool.
// SiftGPUEX: SiftGPU + viewer
// SiftParam: Sift Parameters
//
// Copyright (c) 2007 University of North Carolina at Chapel Hill
// All Rights Reserved
//
// Permission to use, copy, modify and distribute this software and its
// documentation for educational, research and non-profit purposes, without
// fee, and without a written agreement is hereby granted, provided that the
// above copyright notice and the following paragraph appear in all copies.
//
// The University of North Carolina at Chapel Hill make no representations
// about the suitability of this software for any purpose. It is provided
// 'as is' without express or implied warranty.
//
// Please send BUG REPORTS to ccwu@cs.unc.edu
//
////////////////////////////////////////////////////////////////////////////
#include "GL/glew.h"
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
#include "GlobalUtil.h"
#include "SiftGPU.h"
#include "IL/il.h"
#include "GLTexImage.h"
#include "ShaderMan.h"
#include "FrameBufferObject.h"
#include "SiftPyramid.h"
#include "PyramidGL.h"
//CUDA works only with vc8 or higher
#if (!defined(_MSC_VER) ||_MSC_VER >= 1400) && defined(CUDA_SIFTGPU_ENABLED)
#include "PyramidCU.h"
#endif
////
#if defined(_WIN32)
#include "direct.h"
#pragma comment(lib, "../lib/DevIL.lib")
#pragma warning (disable : 4786)
#pragma warning (disable : 4996)
#else
//compatible with linux
#define _stricmp strcasecmp
#endif
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//
//just want to make this class invisible
class ImageList:public std::vector<std::string> {};
SiftGPU::SiftGPU(int np)
{
_texImage = new GLTexInput;
_imgpath[0] = 0;
_outpath[0] = 0;
_initialized = 0;
_image_loaded = 0;
GlobalUtil::_UseSiftGPUEX = 0;
_current = 0;
_list = new ImageList();
_nPyramid = np < 1? 1 : np;
_pyramids = NULL;
_pyramid = NULL;
}
SiftGPUEX::SiftGPUEX()
{
_view = _sub_view = 0;
_view_debug = 0;
GlobalUtil::_UseSiftGPUEX = 1;
srand((unsigned int)time(NULL));
RandomizeColor();
}
void* SiftGPU::operator new (size_t size){
void * p = malloc(size);
if (p == 0)
{
const std::bad_alloc ba;
throw ba;
}
return p;
}
void SiftGPU::SetActivePyramid(int index)
{
if(index >=0 && index < _nPyramid)
{
_pyramid = _pyramids[index];
}
}
void SiftGPUEX::RandomizeColor()
{
//
float hsv[3] = {0, 0.8f, 1.0f};
for(int i = 0; i < COLOR_NUM*3; i+=3)
{
hsv[0] = (rand()%100)*0.01f; //i/float(COLOR_NUM);
HSVtoRGB(hsv, _colors+i);
}
}
SiftGPU::~SiftGPU()
{
if(_pyramids)
{
for(int i = 0; i < _nPyramid; i++)
{
delete _pyramids[i];
}
delete _pyramids;
}
delete _texImage;
delete _list;
if(_initialized)
{
//destroy all the shaders?
ShaderMan::DestroyShaders(_sigma_num);
//shutdown iamge loader
ilShutDown();
}
//Calling glutDestroyWindow function will somehow give a heap corruption
//if(_glut_id >0) glutDestroyWindow(_glut_id);
}
inline void SiftGPU::InitSiftGPU()
{
if(_initialized || GlobalUtil::_GoodOpenGL ==0) return;
#if (defined(_MSC_VER) && _MSC_VER < 1400) || !defined(CUDA_SIFTGPU_ENABLED)
if(GlobalUtil::_UseCUDA)
{
GlobalUtil::_UseCUDA = 0;
std::cerr << "---------------------------------------------------------------------------\n"
<< "CUDA is not supported in this binary! To enable CUDA implementation, please\n"
<< "use SiftGPU_CUDA_Enable Project for VS2005 or define CUDA_SIFTGPU_ENABLED\n"
<< "----------------------------------------------------------------------------\n";
GlobalUtil::_usePackedTex = 1;
}
#endif
_pyramids = new SiftPyramid*[_nPyramid];
for(int i = 0; i < _nPyramid; i++)
{
#if (!defined(_MSC_VER) || _MSC_VER >= 1400) && defined(CUDA_SIFTGPU_ENABLED)
if(GlobalUtil::_UseCUDA)
_pyramids[i] = new PyramidCU(*this);
else
#endif
if(GlobalUtil::_usePackedTex)
_pyramids[i] = new PyramidPacked(*this);
else
_pyramids[i] = new PyramidNaive(*this);
}
_pyramid = _pyramids[0];
ilInit();
ilOriginFunc(IL_ORIGIN_UPPER_LEFT);
ilEnable(IL_ORIGIN_SET);
///
//init opengl parameters
GlobalUtil::InitGLParam();
//sift parameters
ParseSiftParam();
if(GlobalUtil::_GoodOpenGL)
{
if(GlobalUtil::_verbose) std::cout<<"\n[GPU Language]:\t"<<
(GlobalUtil::_UseCUDA? "CUDA" : (GlobalUtil::_UseGLSL?"GLSL" : "CG")) <<"\n\n";
//load shaders..
if(!GlobalUtil::_UseCUDA)
{
GlobalUtil::StartTimer("Load OpenGL Shaders");
ShaderMan::InitShaderMan();
ShaderMan::LoadDogShaders(_dog_threshold, _edge_threshold);
ShaderMan::LoadGenListShader(_dog_level_num, 0);
ShaderMan::CreateGaussianFilters(*this);
GlobalUtil::StopTimer();
}
if(GlobalUtil::_InitPyramidWidth >0 && GlobalUtil::_InitPyramidHeight >0)
{
GlobalUtil::StartTimer("Initialize Pyramids");
for(int i = 0; i < _nPyramid; i++)
{
_pyramid[i].InitPyramid(GlobalUtil::_InitPyramidWidth,
GlobalUtil::_InitPyramidHeight, 0);
}
GlobalUtil::StopTimer();
}
}
ClockTimer::InitHighResolution();
_initialized = 1;
}
int SiftGPU::RunSIFT(int index)
{
if(_list->size()>0 )
{
index = index % _list->size();
if(strcmp(_imgpath, _list->at(index).data()))
{
strcpy(_imgpath, _list->at(index).data());
_image_loaded = 0;
_current = index;
}
return RunSIFT();
}else
{
return 0;
}
}
int SiftGPU::RunSIFT( int width, int height, const void * data, unsigned int gl_format, unsigned int gl_type)
{
if(GlobalUtil::_GoodOpenGL ==0 ) return 0;
if(!_initialized) InitSiftGPU();
if(GlobalUtil::_GoodOpenGL ==0 ) return 0;
if(width > 0 && height >0 && data != NULL)
{
_imgpath[0] = 0;
//try downsample on CPU
GlobalUtil::StartTimer("Upload Image data");
if(_texImage->SetImageData(width, height, data, gl_format, gl_type))
{
_image_loaded = 2; //gldata;
GlobalUtil::StopTimer();
_timing[0] = GlobalUtil::GetElapsedTime();
//if the size of image is different
//pyramid need to be reallocated.
GlobalUtil::StartTimer("Initialize Pyramid");
_pyramid->InitPyramid(width, height, _texImage->_down_sampled);
GlobalUtil::StopTimer();
_timing[1] = GlobalUtil::GetElapsedTime();
return RunSIFT();
}else
{
return 0;
}
}else
{
return 0;
}
}
int SiftGPU::RunSIFT(char * imgpath)
{
if(imgpath && imgpath[0])
{
if(strcmp(_imgpath, imgpath))
{
//set the new image
strcpy(_imgpath, imgpath);
_image_loaded = 0;
}
return RunSIFT();
}else
{
return 0;
}
}
int SiftGPU::RunSIFT(int num, const SiftKeypoint * keys, int keys_have_orientation)
{
if(num <=0) return 0;
_pyramid->SetKeypointList(num, (const float*) keys, 1, keys_have_orientation);
return RunSIFT();
}
int SiftGPU::RunSIFT()
{
//check image data
if(_imgpath[0]==0 && _image_loaded == 0) return 0;
//check OpenGL support
if(GlobalUtil::_GoodOpenGL ==0 ) return 0;
ClockTimer timer;
//initialize SIFT GPU for once
if(!_initialized)
{
InitSiftGPU();
if(GlobalUtil::_GoodOpenGL ==0 ) return 0;
}
timer.StartTimer("RUN SIFT");
//process input image file
if( _image_loaded ==0)
{
//load image
GlobalUtil::StartTimer("Load Input Image");
//try to down-sample on cpu
int width, height;
if(_texImage->LoadImageFile(_imgpath, width, height)==0)
{
return 0;
}
_image_loaded = 1;
GlobalUtil::StopTimer();
_timing[0] = GlobalUtil::GetElapsedTime();
//make sure the pyrmid can hold the new image.
GlobalUtil::StartTimer("Initialize Pyramid");
_pyramid->InitPyramid(width, height, _texImage->_down_sampled);
GlobalUtil::StopTimer();
_timing[1] = GlobalUtil::GetElapsedTime();
}else
{
//change some global states
if(!GlobalUtil::_UseCUDA)
{
GlobalUtil::FitViewPort(1,1);
_texImage->FitTexViewPort();
}
if(_image_loaded == 1)
{
_timing[0] = _timing[1] = 0;
}else
{//2
_image_loaded = 1;
}
}
if(_pyramid->_allocated ==0 ) return 0;
//process the image
#ifdef DEBUG_SIFTGPU
_pyramid->BeginDEBUG(_imgpath);
#endif
_pyramid->RunSIFT(_texImage);
_pyramid->GetPyramidTiming(_timing + 2); //
//write output once if there is only one input
if(_outpath[0] )
{
SaveSIFT(_outpath);
_outpath[0] = 0;
}
//if you just want to call TestWin(Glut) as a sift processor
//now we end the process
if(GlobalUtil::_ExitAfterSIFT && GlobalUtil::_UseSiftGPUEX) exit(0);
if(GlobalUtil::_UseCUDA == 0)
{
//clean up OpenGL stuff
GLTexImage::UnbindMultiTex(3);
ShaderMan::UnloadProgram();
FrameBufferObject::DeleteGlobalFBO();
GlobalUtil::CleanupOpenGL();
}
timer.StopTimer();
if(GlobalUtil::_verbose)std::cout<<endl;
return 1;
}
void SiftGPU::SetKeypointList(int num, const SiftKeypoint * keys, int keys_have_orientation)
{
_pyramid->SetKeypointList(num, (const float*)keys, 0, keys_have_orientation);
}
void SiftGPUEX::DisplayInput()
{
if(_texImage==NULL) return;
_texImage->BindTex();
_texImage->DrawImage();
_texImage->UnbindTex();
}
void SiftGPU::GetImageDimension( int &w, int &h)
{
w = _texImage->GetImgWidth();
h = _texImage->GetImgHeight();
}
void SiftGPU::SetVerbose(int verbose)
{
GlobalUtil::_timingO = verbose>2;
GlobalUtil::_timingL = verbose>3;
if(verbose == -1)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -