Skip to content

Commit 9a20c15

Browse files
author
Carsten Griwodz
committed
Remove Gaussian blur code alternatives that are never used or didn't
work very well. Remove the config param ScalingMode (always use default). Remove fixed scaling code. Remove code to downscale everything directly from input image. Remove the narrower gauss filter width called "OpenCV mode". Remove functions to interpolate from first image plane. Remove specialized version to create very first level from input image. Remove Gauss filter tables for direct downscaling using absolute tables. Removed deprecated scaling mode "OpenCV". OpenCV was buggy when this code was written. It has improved since then. Also downscaling by interpolation, which could not be called with any parameter, is removed. Restructure the calling code for the last 2 pyramid building functions Move host code for normalized source kernel into kernel's file. Normalized source mode is only used for the input image. It uses the normalization feature of CUDA textures to scale the input image while creating the first octave. Simplify the solution with absolute sources. Return to a solution without shuffle and identical code structure for horizontal and vertical Gaussian filtering. Host functions to call Gaussian filtering from point textures moved in kernels' code file. Host functions to call Gaussian filtering from interpolated textures moved in kernels' code file. Simplified and unified code for absolute source interpolated Gaussian filtering. Use horiz_from_input_image exclusively for octave 0. Direct downscaling is not only use for the input image. Note that initial blur is assumed for every input image, even when it is later interpreted as initially unblurred. That does make a difference, but is apparently recommended. Extrema refinement modes have more intuitive names and are no longer tied to PopSift vs VLFeat. (except that the command line parameters of the test code retains the old terms so far)
1 parent 8623b69 commit 9a20c15

20 files changed

+292
-1463
lines changed

src/CMakeLists.txt

+3-4
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@ add_library(popsift
1010
popsift/sift_pyramid.cu popsift/sift_pyramid.h
1111
popsift/sift_octave.cu popsift/sift_octave.h
1212
popsift/s_pyramid_build.cu
13-
popsift/s_pyramid_build_aa.cu popsift/s_pyramid_build_aa.h
14-
popsift/s_pyramid_build_ai.cu popsift/s_pyramid_build_ai.h
15-
popsift/s_pyramid_build_ra.cu popsift/s_pyramid_build_ra.h
16-
popsift/s_pyramid_fixed.cu
13+
popsift/s_pyramid_build_aa.cu
14+
popsift/s_pyramid_build_ai.cu
15+
popsift/s_pyramid_build_ra.cu
1716
popsift/sift_extremum.h
1817
popsift/sift_extremum.cu popsift/s_extrema.cu
1918
popsift/s_orientation.cu

src/application/main.cpp

+4-12
Original file line numberDiff line numberDiff line change
@@ -71,28 +71,20 @@ static void parseargs(int argc, char** argv, popsift::Config& config, string& in
7171
( "gauss-mode", value<std::string>()->notifier([&](const std::string& s) { config.setGaussMode(s); }),
7272
popsift::Config::getGaussModeUsage() )
7373
// "Choice of span (1-sided) for Gauss filters. Default is VLFeat-like computation depending on sigma. "
74-
// "Options are: vlfeat, relative, relative-all, opencv, fixed9, fixed15"
74+
// "Options are: vlfeat, relative, relative-all, opencv"
7575
("desc-mode", value<std::string>()->notifier([&](const std::string& s) { config.setDescMode(s); }),
7676
"Choice of descriptor extraction modes:\n"
7777
"loop, iloop, grid, igrid, notile\n"
78-
"Default is loop\n"
78+
"Default is loop\n"
7979
"loop is OpenCV-like horizontal scanning, computing only valid points, grid extracts only useful points but rounds them, iloop uses linear texture and rotated gradiant fetching. igrid is grid with linear interpolation. notile is like igrid but avoids redundant gradiant fetching.")
80-
("popsift-mode", bool_switch()->notifier([&](bool b) { if(b) config.setMode(popsift::Config::PopSift); }),
80+
("popsift-mode", bool_switch()->notifier([&](bool b) { if(b) config.setMode(popsift::Config::RefineInOctave); }),
8181
"During the initial upscale, shift pixels by 1. In extrema refinement, steps up to 0.6, do not reject points when reaching max iterations, "
8282
"first contrast threshold is .8 * peak thresh. Shift feature coords octave 0 back to original pos.")
83-
("vlfeat-mode", bool_switch()->notifier([&](bool b) { if(b) config.setMode(popsift::Config::VLFeat); }),
83+
("vlfeat-mode", bool_switch()->notifier([&](bool b) { if(b) config.setMode(popsift::Config::RefineInLevel); }),
8484
"During the initial upscale, shift pixels by 1. That creates a sharper upscaled image. "
8585
"In extrema refinement, steps up to 0.6, levels remain unchanged, "
8686
"do not reject points when reaching max iterations, "
8787
"first contrast threshold is .8 * peak thresh.")
88-
("opencv-mode", bool_switch()->notifier([&](bool b) { if(b) config.setMode(popsift::Config::OpenCV); }),
89-
"During the initial upscale, shift pixels by 0.5. "
90-
"In extrema refinement, steps up to 0.5, "
91-
"reject points when reaching max iterations, "
92-
"first contrast threshold is floor(.5 * peak thresh). "
93-
"Computed filter width are lower than VLFeat/PopSift")
94-
("direct-scaling", bool_switch()->notifier([&](bool b) { if(b) config.setScalingMode(popsift::Config::ScaleDirect); }),
95-
"Direct each octave from upscaled orig instead of blurred level.")
9688
("norm-multi", value<int>()->notifier([&](int i) {config.setNormalizationMultiplier(i); }), "Multiply the descriptor by pow(2,<int>).")
9789
( "norm-mode", value<std::string>()->notifier([&](const std::string& s) { config.setNormMode(s); }),
9890
popsift::Config::getNormModeUsage() )

src/application/match.cpp

+7-19
Original file line numberDiff line numberDiff line change
@@ -70,28 +70,16 @@ static void parseargs(int argc, char** argv, popsift::Config& config, string& lF
7070
modes.add_options()
7171
( "gauss-mode", value<std::string>()->notifier([&](const std::string& s) { config.setGaussMode(s); }),
7272
popsift::Config::getGaussModeUsage() )
73-
("desc-mode", value<std::string>()->notifier([&](const std::string& s) { config.setDescMode(s); }),
73+
( "desc-mode", value<std::string>()->notifier([&](const std::string& s) { config.setDescMode(s); }),
7474
"Choice of descriptor extraction modes:\n"
7575
"loop, iloop, grid, igrid, notile\n"
76-
"Default is loop\n"
76+
"Default is loop\n"
7777
"loop is OpenCV-like horizontal scanning, computing only valid points, grid extracts only useful points but rounds them, iloop uses linear texture and rotated gradiant fetching. igrid is grid with linear interpolation. notile is like igrid but avoids redundant gradiant fetching.")
78-
("popsift-mode", bool_switch()->notifier([&](bool b) { if(b) config.setMode(popsift::Config::PopSift); }),
79-
"During the initial upscale, shift pixels by 1. In extrema refinement, steps up to 0.6, do not reject points when reaching max iterations, "
80-
"first contrast threshold is .8 * peak thresh. Shift feature coords octave 0 back to original pos.")
81-
("vlfeat-mode", bool_switch()->notifier([&](bool b) { if(b) config.setMode(popsift::Config::VLFeat); }),
82-
"During the initial upscale, shift pixels by 1. That creates a sharper upscaled image. "
83-
"In extrema refinement, steps up to 0.6, levels remain unchanged, "
84-
"do not reject points when reaching max iterations, "
85-
"first contrast threshold is .8 * peak thresh.")
86-
("opencv-mode", bool_switch()->notifier([&](bool b) { if(b) config.setMode(popsift::Config::OpenCV); }),
87-
"During the initial upscale, shift pixels by 0.5. "
88-
"In extrema refinement, steps up to 0.5, "
89-
"reject points when reaching max iterations, "
90-
"first contrast threshold is floor(.5 * peak thresh). "
91-
"Computed filter width are lower than VLFeat/PopSift")
92-
("direct-scaling", bool_switch()->notifier([&](bool b) { if(b) config.setScalingMode(popsift::Config::ScaleDirect); }),
93-
"Direct each octave from upscaled orig instead of blurred level.")
94-
("norm-multi", value<int>()->notifier([&](int i) {config.setNormalizationMultiplier(i); }), "Multiply the descriptor by pow(2,<int>).")
78+
( "popsift-mode", bool_switch()->notifier([&](bool b) { if(b) config.setMode(popsift::Config::RefineInOctave); }),
79+
"In extrema refinement, it is possible to move extrema within a level but also between the levels of an octave.")
80+
( "vlfeat-mode", bool_switch()->notifier([&](bool b) { if(b) config.setMode(popsift::Config::RefineInLevel); }),
81+
"In extrema refinement, it is possible to move extrema within a level only.")
82+
( "norm-multi", value<int>()->notifier([&](int i) {config.setNormalizationMultiplier(i); }), "Multiply the descriptor by pow(2,<int>).")
9583
( "norm-mode", value<std::string>()->notifier([&](const std::string& s) { config.setNormMode(s); }),
9684
popsift::Config::getNormModeUsage() )
9785
( "root-sift", bool_switch()->notifier([&](bool b) { if(b) config.setNormMode(popsift::Config::RootSift); }),

src/popsift/gauss_filter.cu

+6-93
Original file line numberDiff line numberDiff line change
@@ -67,42 +67,7 @@ void print_gauss_filter_symbol( int columns )
6767

6868
printf( "\n"
6969
"Gauss tables\n"
70-
" level span sigma : center value -> edge value\n"
71-
" absolute filters octave 0 (compute level 0, all other levels directly from level 0)\n");
72-
73-
for( int lvl=0; lvl<d_gauss.required_filter_stages; lvl++ ) {
74-
int span = d_gauss.abs_o0.span[lvl] + d_gauss.abs_o0.span[lvl] - 1;
75-
76-
printf(" %d %d %2.6f: ", lvl, span, d_gauss.abs_o0.sigma[lvl] );
77-
int m = min( d_gauss.abs_o0.span[lvl], columns );
78-
for( int x=0; x<m; x++ ) {
79-
printf("%0.8f ", d_gauss.abs_o0.filter[lvl*GAUSS_ALIGN+x] );
80-
}
81-
if( m < d_gauss.abs_o0.span[lvl] )
82-
printf("...\n");
83-
else
84-
printf("\n");
85-
}
86-
printf( "\n"
87-
" absolute filters other octaves\n"
88-
" (level 0 via downscaling, all other levels directly from level 0)\n");
89-
90-
for( int lvl=0; lvl<d_gauss.required_filter_stages; lvl++ ) {
91-
int span = d_gauss.abs_oN.span[lvl] + d_gauss.abs_oN.span[lvl] - 1;
92-
93-
printf(" %d %d %2.6f: ", lvl, span, d_gauss.abs_oN.sigma[lvl] );
94-
int m = min( d_gauss.abs_oN.span[lvl], columns );
95-
for( int x=0; x<m; x++ ) {
96-
printf("%0.8f ", d_gauss.abs_oN.filter[lvl*GAUSS_ALIGN+x] );
97-
}
98-
if( m < d_gauss.abs_oN.span[lvl] )
99-
printf("...\n");
100-
else
101-
printf("\n");
102-
}
103-
printf("\n");
104-
105-
printf(" level 0-filters for direct downscaling\n");
70+
" level 0-filters for direct downscaling\n");
10671

10772
for( int lvl=0; lvl<MAX_OCTAVES; lvl++ ) {
10873
int span = d_gauss.dd.span[lvl] + d_gauss.dd.span[lvl] - 1;
@@ -187,33 +152,6 @@ void init_filter( const Config& conf,
187152

188153
h_gauss.inc.computeBlurTable( &h_gauss );
189154

190-
/* abs_o0 :
191-
* Gauss table to create octave 0 of the absolute filters directly from
192-
* input images.
193-
*/
194-
for( int lvl=0; lvl<h_gauss.required_filter_stages; lvl++ ) {
195-
const float sigmaS = sigma0 * pow( 2.0f, (float)(lvl)/(float)levels );
196-
h_gauss.abs_o0.sigma[lvl] = sqrt( fabs( sigmaS * sigmaS - initial_blur * initial_blur ) );
197-
}
198-
199-
h_gauss.abs_o0.computeBlurTable( &h_gauss );
200-
201-
/* abs_oN :
202-
* Gauss tables to create levels 1 and above directly from level 0 of every
203-
* octave. Could be used on octave 0, but abs_o0 is better.
204-
* Level 0 must be created by other means (downscaling from previous octave,
205-
* direct downscaling from input image, ...) before using abs_oN.
206-
*
207-
*/
208-
h_gauss.abs_oN.sigma[0] = 0;
209-
for( int lvl=1; lvl<h_gauss.required_filter_stages; lvl++ ) {
210-
const float sigmaP = sigma0; // level 0 has already reached sigma0 blur
211-
const float sigmaS = sigma0 * pow( 2.0f, (float)(lvl)/(float)levels );
212-
h_gauss.abs_oN.sigma[lvl] = sqrt( sigmaS * sigmaS - sigmaP * sigmaP );
213-
}
214-
215-
h_gauss.abs_oN.computeBlurTable( &h_gauss );
216-
217155
/* dd :
218156
* The direct-downscaling kernels make use of the assumption that downscaling
219157
* from MAX_LEVEL-3 is identical to applying 2*sigma on the identical image
@@ -224,17 +162,13 @@ void init_filter( const Config& conf,
224162
* octaves, where it is also good for performance.
225163
* dd is only for creating level 0 of all octave directly from the input image.
226164
*/
227-
for( int oct=0; oct<MAX_OCTAVES; oct++ ) {
228-
// sigma * 2^i
229-
float oct_sigma = scalbnf( sigma0, oct );
230165

231-
// subtract initial blur
232-
float b = sqrt( fabs( oct_sigma * oct_sigma - initial_blur * initial_blur ) );
166+
// subtract initial blur
167+
const float b = sqrt( fabs( sigma0 * sigma0 - initial_blur * initial_blur ) );
233168

234-
// sigma / 2^i
235-
h_gauss.dd.sigma[oct] = scalbnf( b, -oct );
236-
h_gauss.dd.computeBlurTable( &h_gauss );
237-
}
169+
// sigma / 2^i
170+
h_gauss.dd.sigma[0] = b;
171+
h_gauss.dd.computeBlurTable( &h_gauss );
238172

239173
cudaError_t err;
240174
err = cudaMemcpyToSymbol( d_gauss,
@@ -260,8 +194,6 @@ __host__
260194
void GaussInfo::clearTables( )
261195
{
262196
inc .clearTables();
263-
abs_o0 .clearTables();
264-
abs_oN .clearTables();
265197
dd .clearTables();
266198
}
267199

@@ -276,20 +208,10 @@ int GaussInfo::getSpan( float sigma ) const
276208
{
277209
switch( _span_mode )
278210
{
279-
case Config::VLFeat_Relative_All :
280-
// return GaussInfo::vlFeatRelativeSpan( sigma );
281-
return GaussInfo::vlFeatSpan( sigma );
282-
283211
case Config::VLFeat_Compute :
284212
return GaussInfo::vlFeatSpan( sigma );
285213
case Config::VLFeat_Relative :
286214
return GaussInfo::vlFeatRelativeSpan( sigma );
287-
case Config::OpenCV_Compute :
288-
return GaussInfo::openCVSpan( sigma );
289-
case Config::Fixed9 :
290-
return 5;
291-
case Config::Fixed15 :
292-
return 8;
293215
default :
294216
stringstream ss;
295217
ss << "ERROR: The mode for computing Gauss filter scan is invalid";
@@ -317,15 +239,6 @@ int GaussInfo::vlFeatRelativeSpan( float sigma )
317239
return spn;
318240
}
319241

320-
__host__
321-
int GaussInfo::openCVSpan( float sigma )
322-
{
323-
int span = int( roundf( 2.0f * 4.0f * sigma + 1.0f ) ) | 1;
324-
span >>= 1;
325-
span += 1;
326-
return std::min<int>( span, GAUSS_ALIGN - 1 );
327-
}
328-
329242
template<int LEVELS>
330243
__host__
331244
void GaussTable<LEVELS>::clearTables( )

src/popsift/gauss_filter.h

+4-21
Original file line numberDiff line numberDiff line change
@@ -61,25 +61,11 @@ struct GaussInfo
6161
*/
6262
GaussTable<GAUSS_LEVELS> inc;
6363

64-
/* Compute the 1D Gauss tables for all levels of octave 0.
65-
* For octave 0, all of these tables derive from the input
66-
* image.
64+
/* This is the 1D Gauss table for filtering the input image.
65+
* The input image is downscaled and blurred with sigma or by
66+
* blurring the input image with 2*sigma and downscaling afterwards.
6767
*/
68-
GaussTable<GAUSS_LEVELS> abs_o0;
69-
70-
/* Compute the 1D Gauss tables for all levels of octaves 1 and up.
71-
* Level 0 is empty, since it is created by other means.
72-
* All other levels blur from level 0, not considering any
73-
* initial blur.
74-
*/
75-
GaussTable<GAUSS_LEVELS> abs_oN;
76-
77-
/* In theory, level 0 of octave 2 contains the same information
78-
* whether it is constructed by downscaling and blurring the
79-
* input image with sigma or by blurring the input image with 2*sigma
80-
* and downscaling afterwards.
81-
*/
82-
GaussTable<MAX_OCTAVES> dd;
68+
GaussTable<1> dd;
8369

8470
__host__
8571
void clearTables( );
@@ -99,9 +85,6 @@ struct GaussInfo
9985

10086
__host__
10187
static int vlFeatRelativeSpan( float sigma );
102-
103-
__host__
104-
static int openCVSpan( float sigma );
10588
};
10689

10790
extern __device__ __constant__ GaussInfo d_gauss;

0 commit comments

Comments
 (0)