Skip to content

Commit 7be0e89

Browse files
author
Carsten Griwodz
committed
[popsift] add VLFeat-like descriptor extraction
1 parent 2956630 commit 7be0e89

6 files changed

Lines changed: 233 additions & 0 deletions

File tree

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ CUDA_ADD_LIBRARY(popsift
2323
popsift/s_desc_grid.cu popsift/s_desc_grid.h
2424
popsift/s_desc_igrid.cu popsift/s_desc_igrid.h
2525
popsift/s_desc_notile.cu popsift/s_desc_notile.h
26+
popsift/s_desc_vlfeat.cu popsift/s_desc_vlfeat.h
2627
popsift/s_desc_norm_rs.h
2728
popsift/s_desc_norm_l2.h
2829
popsift/s_desc_normalize.h

src/popsift/s_desc_vlfeat.cu

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
/*
2+
* Copyright 2016-2017, Simula Research Laboratory
3+
* 2018-2020, University of Oslo
4+
*
5+
* This Source Code Form is subject to the terms of the Mozilla Public
6+
* License, v. 2.0. If a copy of the MPL was not distributed with this
7+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
8+
*/
9+
#include "common/assist.h"
10+
#include "common/debug_macros.h"
11+
#include "common/vec_macros.h"
12+
#include "s_desc_vlfeat.h"
13+
#include "s_gradiant.h"
14+
#include "sift_constants.h"
15+
#include "sift_pyramid.h"
16+
17+
#include <cstdio>
18+
19+
using namespace popsift;
20+
21+
__device__ static inline
22+
void ext_desc_vlfeat_sub( const float ang,
23+
const Extremum* ext,
24+
float* __restrict__ features,
25+
cudaTextureObject_t layer_tex,
26+
const int width,
27+
const int height )
28+
{
29+
const float x = ext->xpos;
30+
const float y = ext->ypos;
31+
const int level = ext->lpos; // old_level;
32+
const float sig = ext->sigma;
33+
const float SBP = fabsf(DESC_MAGNIFY * sig);
34+
35+
if( SBP == 0 ) {
36+
return;
37+
}
38+
39+
float cos_t;
40+
float sin_t;
41+
__sincosf( ang, &sin_t, &cos_t );
42+
43+
const float csbp = cos_t * SBP;
44+
const float ssbp = sin_t * SBP;
45+
const float crsbp = cos_t / SBP;
46+
const float srsbp = sin_t / SBP;
47+
48+
// We have 4x4*16 bins.
49+
// There centers have the offsets -1.5, -0.5, 0.5, 1.5 from the
50+
// keypoint. The points that support them stretch from -2 to 2
51+
const float2 maxdist = make_float2( -2.0f, -2.0f );
52+
53+
// We rotate the corner of the maximum range by the keypoint orientation.
54+
const float ptx = fabsf( ::fmaf( csbp, maxdist.x, ::fmaf( -ssbp, maxdist.y, x )) );
55+
const float pty = fabsf( ::fmaf( csbp, maxdist.y, ::fmaf( ssbp, maxdist.x, y ) ) );
56+
57+
const float bsz = fabsf(csbp) + fabsf(ssbp);
58+
const int xmin = max(1, (int)floorf(x - ptx - bsz));
59+
const int ymin = max(1, (int)floorf(y - pty - bsz));
60+
const int xmax = min(width - 2, (int)floorf(x + ptx + bsz));
61+
const int ymax = min(height - 2, (int)floorf(y + pty + bsz));
62+
63+
__shared__ float dpt[4][128];
64+
for( int i=threadIdx.x; i<128; i+=blockDim.x )
65+
{
66+
dpt[0][i] = 0.0f;
67+
dpt[1][i] = 0.0f;
68+
dpt[2][i] = 0.0f;
69+
dpt[3][i] = 0.0f;
70+
}
71+
__syncthreads();
72+
73+
// we have 32 threads in a warp, how to use them?
74+
const int tx = ( ( threadIdx.x >> 0 ) & 0x1 ); // 0 - 1
75+
const int ty = ( ( threadIdx.x >> 1 ) & 0x1 ); // 0 - 1
76+
const int tt = ( ( threadIdx.x >> 2 ) & 0x1 ); // 0 - 1
77+
const int loop = threadIdx.x >> 3; // 0 - 3
78+
79+
for( int pix_y = ymin+loop; popsift::any(pix_y <= ymax); pix_y += 4 )
80+
{
81+
for( int pix_x = xmin; pix_x <= xmax; pix_x++ )
82+
{
83+
if( pix_y <= ymax )
84+
{
85+
// d : distance from keypoint
86+
const float2 d = make_float2( pix_x - x, pix_y - y );
87+
88+
// n : normalized distance from keypoint
89+
const float2 n = make_float2( ::fmaf( crsbp, d.x, srsbp * d.y ),
90+
::fmaf( crsbp, d.y, -srsbp * d.x ) );
91+
92+
float mod;
93+
float th;
94+
95+
get_gradiant( mod, th, pix_x, pix_y, layer_tex, level );
96+
97+
mod /= 2; // Our mod is double that of vlfeat. Huh.
98+
99+
const float ww = __expf( -scalbnf(n.x*n.x + n.y*n.y, -3));
100+
101+
th -= ang;
102+
while( th > M_PI2 ) th -= M_PI2;
103+
while( th < 0.0f ) th += M_PI2;
104+
105+
const float nt = 8.0f * th / M_PI2;
106+
107+
// neighbouring tile on the lower side: -2, -1, 0 or 1
108+
// (must use floorf because casting rounds towards zero
109+
const int3 t0 = make_int3( (int)floorf(n.x - 0.5f),
110+
(int)floorf(n.y - 0.5f),
111+
(int)nt );
112+
float wgt_x = - ( n.x - ( t0.x + 0.5f ) );
113+
float wgt_y = - ( n.y - ( t0.y + 0.5f ) );
114+
float wgt_t = - ( nt - t0.z );
115+
116+
if( ( t0.y + ty >= -2 ) &&
117+
( t0.y + ty < 2 ) &&
118+
( t0.x + tx >= -2 ) &&
119+
( t0.x + tx < 2 ) )
120+
{
121+
wgt_x = ( tx == 0 ) ? 1.0f + wgt_x : wgt_x;
122+
wgt_y = ( ty == 0 ) ? 1.0f + wgt_y : wgt_y;
123+
wgt_t = ( tt == 0 ) ? 1.0f + wgt_t : wgt_t;
124+
125+
wgt_x = fabsf( wgt_x );
126+
wgt_y = fabsf( wgt_y );
127+
wgt_t = fabsf( wgt_t );
128+
129+
const float val = ww
130+
* mod
131+
* wgt_x
132+
* wgt_y
133+
* wgt_t;
134+
135+
const int offset = 80
136+
+ ( t0.y + ty ) * 32
137+
+ ( t0.x + tx ) * 8
138+
+ ( t0.z + tt ) % 8;
139+
140+
dpt[loop][offset] += val;
141+
}
142+
}
143+
__syncthreads();
144+
}
145+
}
146+
147+
for( int i=threadIdx.x; i<128; i+=blockDim.x )
148+
{
149+
float f = dpt[0][i] + dpt[1][i] + dpt[2][i] + dpt[3][i];
150+
features[i] = f;
151+
}
152+
}
153+
154+
__global__ void ext_desc_vlfeat(int octave, cudaTextureObject_t layer_tex, int w, int h)
155+
{
156+
const int o_offset = dct.ori_ps[octave] + blockIdx.x;
157+
Descriptor* desc = &dbuf.desc [o_offset];
158+
const int ext_idx = dobuf.feat_to_ext_map[o_offset];
159+
Extremum* ext = dobuf.extrema + ext_idx;
160+
161+
const int ext_base = ext->idx_ori;
162+
const int ori_num = o_offset - ext_base;
163+
const float ang = ext->orientation[ori_num];
164+
165+
ext_desc_vlfeat_sub( ang,
166+
ext,
167+
desc->features,
168+
layer_tex,
169+
w,
170+
h );
171+
}
172+
173+
namespace popsift
174+
{
175+
176+
bool start_ext_desc_vlfeat( const int octave, Octave& oct_obj )
177+
{
178+
dim3 block;
179+
dim3 grid;
180+
grid.x = hct.ori_ct[octave];
181+
grid.y = 1;
182+
grid.z = 1;
183+
184+
if( grid.x == 0 ) return false;
185+
186+
block.x = 32;
187+
block.y = 1;
188+
block.z = 1;
189+
190+
size_t shared_size = 4 * 128 * sizeof(float);
191+
192+
ext_desc_vlfeat
193+
<<<grid,block,shared_size,oct_obj.getStream()>>>
194+
( octave,
195+
oct_obj.getDataTexPoint( ),
196+
oct_obj.getWidth(),
197+
oct_obj.getHeight() );
198+
199+
POP_SYNC_CHK;
200+
201+
return true;
202+
}
203+
204+
}; // namespace popsift
205+

src/popsift/s_desc_vlfeat.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright 2016-2017, Simula Research Laboratory
3+
* 2018-2020, University of Oslo
4+
*
5+
* This Source Code Form is subject to the terms of the Mozilla Public
6+
* License, v. 2.0. If a copy of the MPL was not distributed with this
7+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
8+
*/
9+
#pragma once
10+
#include "sift_octave.h"
11+
12+
namespace popsift
13+
{
14+
15+
bool start_ext_desc_vlfeat( const int octave, Octave& oct_obj );
16+
17+
}; // namespace popsift
18+

src/popsift/sift_conf.cu

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ void Config::setDescMode( const std::string& text )
8080
setDescMode( Config::IGrid );
8181
else if( text == "notile" )
8282
setDescMode( Config::NoTile );
83+
else if( text == "vlfeat" )
84+
setDescMode( Config::VLFeat_Desc );
8385
else
8486
POP_FATAL( "specified descriptor extraction mode must be one of loop, grid or igrid" );
8587
}

src/popsift/sift_conf.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ struct Config
9595
IGrid,
9696
/// loop-compatible; variant of IGrid, no duplicate gradient fetching
9797
NoTile,
98+
/** extraction code according to VLFeat, similar to loop, weight goes into
99+
* up to 8 histogram bins
100+
*/
101+
VLFeat_Desc
98102
};
99103

100104
/**

src/popsift/sift_desc.cu

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "s_desc_loop.h"
1414
#include "s_desc_normalize.h"
1515
#include "s_desc_notile.h"
16+
#include "s_desc_vlfeat.h"
1617
#include "s_gradiant.h"
1718
#include "sift_config.h"
1819
#include "sift_constants.h"
@@ -77,6 +78,8 @@ void Pyramid::descriptors( const Config& conf )
7778
start_ext_desc_igrid( octave, oct_obj );
7879
} else if( conf.getDescMode() == Config::NoTile ) {
7980
start_ext_desc_notile( octave, oct_obj );
81+
} else if( conf.getDescMode() == Config::VLFeat_Desc ) {
82+
start_ext_desc_vlfeat( octave, oct_obj );
8083
} else {
8184
POP_FATAL( "not yet" );
8285
}

0 commit comments

Comments
 (0)