Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[testing] Compare various descriptors #115

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Support for Cuda CC 7 cards (RTX 2080) [PR](https://github.com/alicevision/popsift/pull/67)
- Support for Boost 1.70 [PR](https://github.com/alicevision/popsift/pull/65)
- Support for device selection and multiple GPUs [PR](https://github.com/alicevision/popsift/pull/121)
- Test: adding descriptor comparator [PR](https://github.com/alicevision/popsift/pull/115)

### Fixed
- CMake: fixes to allow building on Windows using vcpkg [PR](https://github.com/alicevision/popsift/pull/92)
Expand Down
5 changes: 5 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ CUDA_ADD_LIBRARY(popsift
popsift/s_desc_grid.cu popsift/s_desc_grid.h
popsift/s_desc_igrid.cu popsift/s_desc_igrid.h
popsift/s_desc_notile.cu popsift/s_desc_notile.h
popsift/s_desc_vlfeat.cu popsift/s_desc_vlfeat.h
popsift/s_desc_norm_rs.h
popsift/s_desc_norm_l2.h
popsift/s_desc_normalize.h
Expand Down Expand Up @@ -149,3 +150,7 @@ if(PopSift_BUILD_EXAMPLES)
add_subdirectory(application)
endif()

if(PopSift_USE_TEST_CMD)
add_subdirectory(compareSiftFiles)
endif()

47 changes: 30 additions & 17 deletions src/application/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ using namespace std;
static bool print_dev_info = false;
static bool print_time_info = false;
static bool write_as_uchar = false;
static bool write_with_ori = false;
static bool dont_write = false;
static bool pgmread_loading = false;
static bool float_mode = false;
Expand All @@ -62,15 +63,30 @@ static void parseargs(int argc, char** argv, popsift::Config& config, string& in
options_description parameters("Parameters");
{
parameters.add_options()
("octaves", value<int>(&config.octaves), "Number of octaves")
("levels", value<int>(&config.levels), "Number of levels per octave")
("sigma", value<float>()->notifier([&](float f) { config.setSigma(f); }), "Initial sigma value")

("threshold", value<float>()->notifier([&](float f) { config.setThreshold(f); }), "Contrast threshold")
("edge-threshold", value<float>()->notifier([&](float f) { config.setEdgeLimit(f); }), "On-edge threshold")
("edge-limit", value<float>()->notifier([&](float f) { config.setEdgeLimit(f); }), "On-edge threshold")
("downsampling", value<float>()->notifier([&](float f) { config.setDownsampling(f); }), "Downscale width and height of input by 2^N")
("initial-blur", value<float>()->notifier([&](float f) {config.setInitialBlur(f); }), "Assume initial blur, subtract when blurring first time");
("octaves",
value<int>(&config.octaves)->default_value(config.getOctaves()),
"Number of octaves")
("levels",
value<int>(&config.levels)->default_value(config.getLevels()),
"Number of levels per octave")
("sigma",
value<float>()->notifier([&](float f) { config.setSigma(f); })->default_value(config.getSigma()),
"Initial sigma value")
("threshold",
value<float>()->notifier([&](float f) { config.setThreshold(f); })->default_value(config.getThreshold()),
"Contrast threshold")
("edge-threshold",
value<float>()->notifier([&](float f) { config.setEdgeLimit(f); })->default_value(config.getEdgeLimit()),
"On-edge threshold")
("edge-limit",
value<float>()->notifier([&](float f) { config.setEdgeLimit(f); }),
"On-edge threshold")
("downsampling",
value<float>()->notifier([&](float f) { config.setDownsampling(f); })->default_value(config.getDownsampling()),
"Downscale width and height of input by 2^N")
("initial-blur",
value<float>()->notifier([&](float f) {config.setInitialBlur(f); })->default_value(config.getInitialBlur()),
"Assume initial blur, subtract when blurring first time");
}
options_description modes("Modes");
{
Expand All @@ -79,11 +95,8 @@ static void parseargs(int argc, char** argv, popsift::Config& config, string& in
popsift::Config::getGaussModeUsage() )
// "Choice of span (1-sided) for Gauss filters. Default is VLFeat-like computation depending on sigma. "
// "Options are: vlfeat, relative, relative-all, opencv, fixed9, fixed15"
("desc-mode", value<std::string>()->notifier([&](const std::string& s) { config.setDescMode(s); }),
"Choice of descriptor extraction modes:\n"
"loop, iloop, grid, igrid, notile\n"
"Default is loop\n"
"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.")
( "desc-mode", value<std::string>()->notifier([&](const std::string& s) { config.setDescMode(s); }),
popsift::Config::getDescModeUsage() )
("popsift-mode", bool_switch()->notifier([&](bool b) { if(b) config.setMode(popsift::Config::PopSift); }),
"During the initial upscale, shift pixels by 1. In extrema refinement, steps up to 0.6, do not reject points when reaching max iterations, "
"first contrast threshold is .8 * peak thresh. Shift feature coords octave 0 back to original pos.")
Expand All @@ -104,7 +117,7 @@ static void parseargs(int argc, char** argv, popsift::Config& config, string& in
( "norm-mode", value<std::string>()->notifier([&](const std::string& s) { config.setNormMode(s); }),
popsift::Config::getNormModeUsage() )
( "root-sift", bool_switch()->notifier([&](bool b) { if(b) config.setNormMode(popsift::Config::RootSift); }),
popsift::Config::getNormModeUsage() )
"synonym to --norm-mode=RootSift" )
("filter-max-extrema", value<int>()->notifier([&](int f) {config.setFilterMaxExtrema(f); }), "Approximate max number of extrema.")
("filter-grid", value<int>()->notifier([&](int f) {config.setFilterGridSize(f); }), "Grid edge length for extrema filtering (ie. value 4 leads to a 4x4 grid)")
("filter-sort", value<std::string>()->notifier([&](const std::string& s) {config.setFilterSorting(s); }), "Sort extrema in each cell by scale, either random (default), up or down");
Expand All @@ -118,6 +131,7 @@ static void parseargs(int argc, char** argv, popsift::Config& config, string& in
("print-time-info", bool_switch(&print_time_info)->default_value(false), "A debug output printing image processing time after load()")
("write-as-uchar", bool_switch(&write_as_uchar)->default_value(false), "Output descriptors rounded to int.\n"
"Scaling to sensible ranges is not automatic, should be combined with --norm-multi=9 or similar")
("write-with-ori", bool_switch(&write_with_ori)->default_value(false), "Output points are written with sigma and orientation.\n")
("dont-write", bool_switch(&dont_write)->default_value(false), "Suppress descriptor output")
("pgmread-loading", bool_switch(&pgmread_loading)->default_value(false), "Use the old image loader instead of LibDevIL")
("float-mode", bool_switch(&float_mode)->default_value(false), "Upload image to GPU as float instead of byte")
Expand Down Expand Up @@ -254,7 +268,7 @@ void read_job( SiftJob* job, bool really_write )
nvtxRangePushA( "Writing features to disk" );

std::ofstream of( "output-features.txt" );
feature_list->print( of, write_as_uchar );
feature_list->print( of, write_as_uchar, write_with_ori );
}
delete feature_list;

Expand Down Expand Up @@ -327,4 +341,3 @@ int main(int argc, char **argv)

return EXIT_SUCCESS;
}

38 changes: 38 additions & 0 deletions src/compareSiftFiles/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
# I am top-level project, i.e. I am not being include by another project
cmake_minimum_required(VERSION 3.12)
project(PopSiftCompareDescriptors LANGUAGES CXX)

include(GNUInstallDirs)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
endif()

if(PopSift_BOOST_USE_STATIC_LIBS)
set(Boost_USE_STATIC_LIBS ON)
endif()
find_package(Boost 1.53.0 REQUIRED COMPONENTS filesystem program_options system)
if(WIN32)
add_definitions("-DBOOST_ALL_NO_LIB")
endif(WIN32)

#############################################################
# compareSiftFiles
#############################################################

add_executable(popsift-compareSiftFiles
compareSiftFiles.cpp
csf_feat.cpp csf_feat.h
csf_options.cpp csf_options.h)

target_include_directories(popsift-compareSiftFiles PUBLIC ${Boost_INCLUDE_DIRS})
target_link_libraries(popsift-compareSiftFiles PUBLIC ${Boost_LIBRARIES})

set_property(TARGET popsift-compareSiftFiles PROPERTY CXX_STANDARD 14)

#############################################################
# installation
#############################################################

install(TARGETS popsift-compareSiftFiles DESTINATION ${CMAKE_INSTALL_BINDIR})
131 changes: 131 additions & 0 deletions src/compareSiftFiles/compareSiftFiles.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <cstring>

#include <boost/program_options.hpp>

#include "csf_feat.h"
#include "csf_options.h"

using namespace std;

typedef vector<float> desc_t;

/** Read a file containing SIFT descriptors
*/
void readFile( vector<feat_t>& vec, const std::string& filename );

/** Write the average descriptor differences to file
* @param file The output file
* @param stats A 128-float vector containing the sum of differences
* @param sz The number of samples that have been collected in stats
*/
void writeSummary( ostream& file, const vector<float>& stats, int sz );

/** Open a new stream or return the default stream. The default stream is
* returned if the name is empty or opening the stream fails.
* @param name A string containing the name of the file to open or empty
* @param default_stream The default stream to return
*/
ostream* openOutputFile( const string& name, ostream* default_stream );

int main( int argc, char* argv[] )
{
Parameters param;

parseargs( argc, argv, param );

vector<feat_t> l_one;
vector<feat_t> l_two;

readFile( l_one, param.input[0] );
readFile( l_two, param.input[1] );

ostream* outfile = openOutputFile( param.outfile_name, &cout );
ostream* descfile = openOutputFile( param.descfile_name, nullptr );

int len = l_one.size();
int ct = 0;
float nextpercent = 10;

vector<float> desc_stats( 128, 0.0f );

ostream* print_dists = param.descfile_verbose ? descfile : 0;

for( auto l : l_one )
{
l.compareBestMatch( *outfile, print_dists, l_two, desc_stats, param.briefinfo );
ct++;
if( float(ct * 100) / len >= float(nextpercent) )
{
cerr << nextpercent << "% " << ct << endl;
nextpercent += 10;
}
}

if( descfile )
{
writeSummary( *descfile, desc_stats, l_one.size() );
}

if( ! param.outfile_name.empty() )
{
delete outfile;
}
}

void writeSummary( ostream& descfile, const vector<float>& desc_stats, int sz )
{
descfile << "========== Summary Stats ==========" << endl
<< "Average values:" << endl
<< setprecision(3);
for( int i=0; i<128; i++ )
{
if( i%32==0 ) descfile << "X=0 | ";
if( i%32==8 ) descfile << "X=1 | ";
if( i%32==16 ) descfile << "X=2 | ";
if( i%32==24 ) descfile << "X=3 | ";
float d = desc_stats[i] / sz;
descfile << setw(8) << d << " ";
if( i%8==7 ) descfile << endl;
}
descfile << endl;
}

void readFile( vector<feat_t>& vec, const std::string& filename )
{
ifstream infile( filename );

if( ! infile.good() )
{
cerr << "File " << filename << " is not open." << endl;
exit( -1 );
}

int lines_read = readFeats( vec, infile );
cerr << "Read " << lines_read << " lines from " << filename << endl;
}

ostream* openOutputFile( const string& outfile_name, ostream* default_stream )
{
ostream* outfile = default_stream;
if( outfile_name.empty() ) return outfile;

ostream* o = new ofstream( outfile_name );
if( o->good() )
{
outfile = o;
}
else
{
delete o;
}

return outfile;
}

Loading