📄 pyramidcu.cpp
字号:
void PyramidCU::DestroyPerLevelData()
{
//integers vector to store the feature numbers.
if(_levelFeatureNum)
{
delete [] _levelFeatureNum;
_levelFeatureNum = NULL;
}
//texture used to store features
if( _featureTex)
{
delete [] _featureTex;
_featureTex = NULL;
}
//texture used for multi-orientation
if(_orientationTex)
{
delete [] _orientationTex;
_orientationTex = NULL;
}
int no = _octave_num* param._dog_level_num;
//two sets of vbos used to display the features
if(_featureDisplayVBO)
{
glDeleteBuffers(no, _featureDisplayVBO);
delete [] _featureDisplayVBO;
_featureDisplayVBO = NULL;
}
if( _featurePointVBO)
{
glDeleteBuffers(no, _featurePointVBO);
delete [] _featurePointVBO;
_featurePointVBO = NULL;
}
}
void PyramidCU::DestroyPyramidData()
{
if(_allPyramid)
{
delete [] _allPyramid;
_allPyramid = NULL;
}
}
void PyramidCU::DownloadKeypoints()
{
const double twopi = 2.0*3.14159265358979323846;
int idx = 0;
float * buffer = &_keypoint_buffer[0];
vector<float> keypoint_buffer2;
//use a different keypoint buffer when processing with an exisint features list
//without orientation information.
if(_keypoint_index.size() > 0)
{
keypoint_buffer2.resize(_keypoint_buffer.size());
buffer = &keypoint_buffer2[0];
}
float * p = buffer, *ps;
CuTexImage * ftex = _featureTex;
/////////////////////
float os = _octave_min>=0? float(1<<_octave_min): 1.0f/(1<<(-_octave_min));
if(_down_sample_factor>0) os *= float(1<<_down_sample_factor);
float offset = GlobalUtil::_LoweOrigin? 0 : 0.5f;
/////////////////////
for(int i = 0; i < _octave_num; i++, os *= 2.0f)
{
for(int j = 0; j < param._dog_level_num; j++, idx++, ftex++)
{
if(_levelFeatureNum[idx]>0)
{
ftex->CopyToHost(ps = p);
for(int k = 0; k < _levelFeatureNum[idx]; k++, ps+=4)
{
ps[0] = os*(ps[0]-0.5f) + offset; //x
ps[1] = os*(ps[1]-0.5f) + offset; //y
ps[2] = os*ps[2];
ps[3] = (float)fmod(twopi-ps[3], twopi); //orientation, mirrored
}
p+= 4* _levelFeatureNum[idx];
}
}
}
//put the feature into their original order for existing keypoint
if(_keypoint_index.size() > 0)
{
for(int i = 0; i < _featureNum; ++i)
{
int index = _keypoint_index[i];
memcpy(&_keypoint_buffer[index*4], &keypoint_buffer2[i*4], 4 * sizeof(float));
}
}
}
void PyramidCU::GenerateFeatureListCPU()
{
//no cpu version provided
GenerateFeatureList();
}
void PyramidCU::GenerateFeatureList()
{
CuTexImage * htex, * ftex, * tex, *got;
double t1, t2, t3, ot1, ot2, ts1 = 0, ts2 = 0;
int ocount = 0, idx = 0, reduction_count;
int hist_level_num = _hpLevelNum - _pyramid_octave_first;
//int hist_skip_gpu = GlobalUtil::_ListGenSkipGPU;
int ii, k, len;
vector<int> hbuffer;
_featureNum = 0;
for(int i = 0; i < _octave_num; i++)
{
tex = GetBaseLevel(_octave_min + i, DATA_KEYPOINT) + 2;
got = GetBaseLevel(_octave_min + i, DATA_GRAD) + 2;
//output
reduction_count = FitHistogramPyramid(tex);
if(GlobalUtil::_timingO)
{
ot1 = ot2 = 0;
ocount = 0;
std::cout<<"#"<<i+_octave_min + _down_sample_factor<<":\t";
}
for(int j = 0; j < param._dog_level_num; j++, tex++, got++, idx++)
{
int fcount = 0;
ftex = _featureTex + idx;
htex = _histoPyramidTex + hist_level_num -1;
if(GlobalUtil::_timingL) t1= CLOCK();
ProgramCU::InitHistogram(tex, htex);
for(k = 0; k < reduction_count - 1; k++, htex--)
{
ProgramCU::ReduceHistogram(htex, htex -1);
}
if(GlobalUtil::_timingL) t2= CLOCK();
//htex has the row reduction result
len = htex->GetImgHeight() * 4;
hbuffer.resize(len);
htex->CopyToHost(&hbuffer[0]);
//
for(ii = 0; ii < len; ++ii) fcount += hbuffer[ii];
SetLevelFeatureNum(idx, fcount);
//build the feature list
#ifdef _DEBUG
// ProgramCU::CheckErrorCUDA("Generate List Level");
#endif
///
if(fcount > 0)
{
_featureNum += fcount;
_keypoint_buffer.resize(fcount * 4);
//vector<int> ikbuf(fcount*4);
int* ibuf = (int*) (&_keypoint_buffer[0]);
for(ii = 0; ii < len; ++ii)
{
int x = ii%4, y = ii / 4;
for(int jj = 0 ; jj < hbuffer[ii]; ++jj, ibuf+=4)
{
ibuf[0] = x; ibuf[1] = y; ibuf[2] = jj; ibuf[3] = 0;
}
}
_featureTex[idx].CopyFromHost(&_keypoint_buffer[0]);
////////////////////////////////////////////
ProgramCU::GenerateList(_featureTex + idx, ++htex);
for(k = 2; k < reduction_count; k++)
{
ProgramCU::GenerateList(_featureTex + idx, ++htex);
}
}
/////////////////////////////
if(GlobalUtil::_timingL)
{
ProgramCU::FinishCUDA();
t3 = CLOCK();
ot1 += (t2 - t1); ot2 += ( t3 - t2);
std::cout<<int(fcount)<<"\t";
}
ocount += fcount;
}
if(GlobalUtil::_timingO)
{
ts1 += ot1; ts2 += ot2;
std::cout << "| \t" << int(ocount) << " :\t(" << ot1 <<",\t" << ot2 << ")\n";
}
}
/////
CopyGradientTex();
/////
if(GlobalUtil::_timingS)ProgramCU::FinishCUDA();
if(GlobalUtil::_verbose)
{
std::cout<<"#Features:\t"<<_featureNum<<"\n";
}
ProgramCU::CheckErrorCUDA("PyramidCU::GenerateFeatureList");
}
GLTexImage* PyramidCU::GetLevelTexture(int octave, int level)
{
return GetLevelTexture(octave, level, DATA_GAUSSIAN);
}
GLTexImage* PyramidCU::ConvertTexCU2GL(CuTexImage* tex, int dataName)
{
static GLTexImage texGL;
GLenum format = GL_LUMINANCE;
int convert_done = 1;
switch(dataName)
{
case DATA_GAUSSIAN:
{
convert_done = tex->CopyToPBO(_bufferPBO);
break;
}
case DATA_DOG:
{
CuTexImage texPBO(tex->GetImgWidth(), tex->GetImgHeight(), 1, _bufferPBO);
if(texPBO._cuData == 0 || tex->_cuData == NULL) convert_done = 0;
else ProgramCU::DisplayConvertDOG(tex, &texPBO);
break;
}
case DATA_GRAD:
{
CuTexImage texPBO(tex->GetImgWidth(), tex->GetImgHeight(), 1, _bufferPBO);
if(texPBO._cuData == 0 || tex->_cuData == NULL) convert_done = 0;
else ProgramCU::DisplayConvertGRD(tex, &texPBO);
break;
}
case DATA_KEYPOINT:
{
CuTexImage * dog = tex - param._level_num * _pyramid_octave_num;
format = GL_RGBA;
CuTexImage texPBO(tex->GetImgWidth(), tex->GetImgHeight(), 4, _bufferPBO);
if(texPBO._cuData == 0 || tex->_cuData == NULL) convert_done = 0;
else ProgramCU::DisplayConvertKEY(tex, dog, &texPBO);
break;
}
default:
convert_done = 0;
break;
}
if(convert_done)
{
texGL.InitTexture(max(texGL.GetTexWidth(), tex->GetImgWidth()), max(texGL.GetTexHeight(), tex->GetImgHeight()));
texGL.CopyFromPBO(_bufferPBO, tex->GetImgWidth(), tex->GetImgHeight(), format);
}else
{
texGL.SetImageSize(0, 0);
}
return &texGL;
}
GLTexImage* PyramidCU::GetLevelTexture(int octave, int level, int dataName)
{
CuTexImage* tex = GetBaseLevel(octave, dataName) + (level - param._level_min);
//CuTexImage* gus = GetBaseLevel(octave, DATA_GAUSSIAN) + (level - param._level_min);
return ConvertTexCU2GL(tex, dataName);
}
void PyramidCU::ConvertInputToCU(GLTexInput* input)
{
int ws = input->GetImgWidth(), hs = input->GetImgHeight();
TruncateWidth(ws);
//copy the input image to pixel buffer object
if(input->CopyToPBO(_bufferPBO, ws, hs))
{
CuTexImage texPBO(ws, hs, 4, _bufferPBO);
_inputTex->InitTexture(ws, hs, 1);
ProgramCU::ReduceToSingleChannel(_inputTex, &texPBO, !input->_rgb_converted);
//delete original texture to save some memory
//glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, _bufferPBO);
//glBufferData(GL_PIXEL_PACK_BUFFER_ARB, 1, NULL, GL_STATIC_DRAW_ARB);
//glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
}else
{
std::cerr<< "Unable To Convert Intput\n";
}
}
void PyramidCU::BuildPyramid(GLTexInput * input)
{
USE_TIMING();
int i, j;
for ( i = _octave_min; i < _octave_min + _octave_num; i++)
{
float* filter_sigma = param._sigma;
CuTexImage *tex = GetBaseLevel(i);
CuTexImage *buf = GetBaseLevel(i, DATA_KEYPOINT) +2;
j = param._level_min + 1;
OCTAVE_START();
if( i == _octave_min )
{
ConvertInputToCU(input);
if(i == 0)
{
ProgramCU::FilterImage(tex, _inputTex, buf, param.GetInitialSmoothSigma(_octave_min));
}else
{
if(i < 0) ProgramCU::SampleImageU(tex, _inputTex, -i);
else ProgramCU::SampleImageD(tex, _inputTex, i);
ProgramCU::FilterImage(tex, tex, buf, param.GetInitialSmoothSigma(_octave_min));
}
LEVEL_FINISH();
}else
{
ProgramCU::SampleImageD(tex, GetBaseLevel(i - 1) + param._level_ds - param._level_min);
LEVEL_FINISH();
if(param._sigma_skip1 > 0)
{
ProgramCU::FilterImage(tex, tex, buf, param._sigma_skip1);
LEVEL_FINISH();
}
}
for( ; j <= param._level_max ; j++, tex++, filter_sigma++)
{
// filtering
ProgramCU::FilterImage(tex + 1, tex, buf, *filter_sigma);
LEVEL_FINISH();
}
OCTAVE_FINISH();
}
if(GlobalUtil::_timingS) ProgramCU::FinishCUDA();
ProgramCU::CheckErrorCUDA("PyramidCU::BuildPyramid");
}
void PyramidCU::DetectKeypointsEX()
{
int i, j;
double t0, t, ts, t1, t2;
if(GlobalUtil::_timingS && GlobalUtil::_verbose)ts = CLOCK();
for(i = _octave_min; i < _octave_min + _octave_num; i++)
{
CuTexImage * gus = GetBaseLevel(i) + 1;
CuTexImage * dog = GetBaseLevel(i, DATA_DOG) + 1;
CuTexImage * got = GetBaseLevel(i, DATA_GRAD) + 1;
//compute the gradient
for(j = param._level_min +1; j <= param._level_max ; j++, gus++, dog++, got++)
{
//input: gus and gus -1
//output: gradient, dog, orientation
ProgramCU::ComputeDOG(gus, dog, got);
}
}
if(GlobalUtil::_timingS && GlobalUtil::_verbose)
{
ProgramCU::FinishCUDA();
t1 = CLOCK();
}
for ( i = _octave_min; i < _octave_min + _octave_num; i++)
{
if(GlobalUtil::_timingO)
{
t0 = CLOCK();
std::cout<<"#"<<(i + _down_sample_factor)<<"\t";
}
CuTexImage * dog = GetBaseLevel(i, DATA_DOG) + 2;
CuTexImage * key = GetBaseLevel(i, DATA_KEYPOINT) +2;
for( j = param._level_min +2; j < param._level_max ; j++, dog++, key++)
{
if(GlobalUtil::_timingL)t = CLOCK();
//input, dog, dog + 1, dog -1
//output, key
ProgramCU::ComputeKEY(dog, key, param._dog_threshold, param._edge_threshold);
if(GlobalUtil::_timingL)
{
std::cout<<(CLOCK()-t)<<"\t";
}
}
if(GlobalUtil::_timingO)
{
std::cout<<"|\t"<<(CLOCK()-t0)<<"\n";
}
}
if(GlobalUtil::_timingS)
{
ProgramCU::FinishCUDA();
if(GlobalUtil::_verbose)
{
t2 = CLOCK();
std::cout <<"<Gradient, DOG >\t"<<(t1-ts)<<"\n"
<<"<Get Keypoints >\t"<<(t2-t1)<<"\n";
}
}
}
void PyramidCU::CopyGradientTex()
{
double ts, t1;
if(GlobalUtil::_timingS && GlobalUtil::_verbose)ts = CLOCK();
for(int i = 0, idx = 0; i < _octave_num; i++)
{
CuTexImage * got = GetBaseLevel(i + _octave_min, DATA_GRAD) + GlobalUtil::_GradientLevelOffset;
//compute the gradient
for(int j = 0; j < param._dog_level_num ; j++, got++, idx++)
{
if(_levelFeatureNum[idx] > 0) got->CopyToTexture2D();
}
}
if(GlobalUtil::_timingS)
{
ProgramCU::FinishCUDA();
if(GlobalUtil::_verbose)
{
t1 = CLOCK();
std::cout <<"<Copy Grad/Orientation>\t"<<(t1-ts)<<"\n";
}
}
}
void PyramidCU::ComputeGradient()
{
int i, j;
double ts, t1;
if(GlobalUtil::_timingS && GlobalUtil::_verbose)ts = CLOCK();
for(i = _octave_min; i < _octave_min + _octave_num; i++)
{
CuTexImage * gus = GetBaseLevel(i) + GlobalUtil::_GradientLevelOffset;
CuTexImage * dog = GetBaseLevel(i, DATA_DOG) + GlobalUtil::_GradientLevelOffset;
CuTexImage * got = GetBaseLevel(i, DATA_GRAD) + GlobalUtil::_GradientLevelOffset;
//compute the gradient
for(j = 0; j < param._dog_level_num ; j++, gus++, dog++, got++)
{
ProgramCU::ComputeDOG(gus, dog, got);
}
}
if(GlobalUtil::_timingS)
{
ProgramCU::FinishCUDA();
if(GlobalUtil::_verbose)
{
t1 = CLOCK();
std::cout <<"<Gradient, DOG >\t"<<(t1-ts)<<"\n";
}
}
}
int PyramidCU::FitHistogramPyramid(CuTexImage* tex)
{
CuTexImage *htex;
int hist_level_num = _hpLevelNum - _pyramid_octave_first;
htex = _histoPyramidTex + hist_level_num - 1;
int w = (tex->GetImgWidth() + 2) >> 2;
int h = tex->GetImgHeight();
int count = 0;
for(int k = 0; k < hist_level_num; k++, htex--)
{
htex->SetImageSize(w, h); ++count;
if(w == 1) break;
w = (w + 3)>>2;
}
return count;
}
void PyramidCU::GetFeatureOrientations()
{
CuTexImage * ftex = _featureTex;
int * count = _levelFeatureNum;
float sigma, sigma_step = powf(2.0f, 1.0f/param._dog_level_num);
for(int i = 0; i < _octave_num; i++)
{
CuTexImage* got = GetBaseLevel(i + _octave_min, DATA_GRAD) + GlobalUtil::_GradientLevelOffset;
CuTexImage* key = GetBaseLevel(i + _octave_min, DATA_KEYPOINT) + 2;
for(int j = 0; j < param._dog_level_num; j++, ftex++, count++, got++, key++)
{
if(*count<=0)continue;
//if(ftex->GetImgWidth() < *count) ftex->InitTexture(*count, 1, 4);
sigma = param.GetLevelSigma(j+param._level_min+1);
ProgramCU::ComputeOrientation(ftex, got, key, sigma, sigma_step, _existing_keypoints);
}
}
if(GlobalUtil::_timingS)ProgramCU::FinishCUDA();
ProgramCU::CheckErrorCUDA("PyramidCU::GetFeatureOrientations");
}
void PyramidCU::GetSimplifiedOrientation()
{
//no simplified orientation
GetFeatureOrientations();
}
CuTexImage* PyramidCU::GetBaseLevel(int octave, int dataName)
{
if(octave <_octave_min || octave > _octave_min + _octave_num) return NULL;
int offset = (_pyramid_octave_first + octave - _octave_min) * param._level_num;
int num = param._level_num * _pyramid_octave_num;
if (dataName == DATA_ROT) dataName = DATA_GRAD;
return _allPyramid + num * dataName + offset;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -