camenduru's picture
ceres-solver and colmap
7b7496d
// Copyright (c) 2022, ETH Zurich and UNC Chapel Hill.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
#ifndef COLMAP_SRC_FEATURE_SIFT_H_
#define COLMAP_SRC_FEATURE_SIFT_H_
#include "estimators/two_view_geometry.h"
#include "feature/types.h"
#include "util/bitmap.h"
class SiftGPU;
class SiftMatchGPU;
namespace colmap {
struct SiftExtractionOptions {
// Number of threads for feature extraction.
int num_threads = -1;
// Whether to use the GPU for feature extraction.
bool use_gpu = true;
// Index of the GPU used for feature extraction. For multi-GPU extraction,
// you should separate multiple GPU indices by comma, e.g., "0,1,2,3".
std::string gpu_index = "-1";
// Maximum image size, otherwise image will be down-scaled.
int max_image_size = 3200;
// Maximum number of features to detect, keeping larger-scale features.
int max_num_features = 8192;
// First octave in the pyramid, i.e. -1 upsamples the image by one level.
int first_octave = -1;
// Number of octaves.
int num_octaves = 4;
// Number of levels per octave.
int octave_resolution = 3;
// Peak threshold for detection.
double peak_threshold = 0.02 / octave_resolution;
// Edge threshold for detection.
double edge_threshold = 10.0;
// Estimate affine shape of SIFT features in the form of oriented ellipses as
// opposed to original SIFT which estimates oriented disks.
bool estimate_affine_shape = false;
// Maximum number of orientations per keypoint if not estimate_affine_shape.
int max_num_orientations = 2;
// Fix the orientation to 0 for upright features.
bool upright = false;
// Whether to adapt the feature detection depending on the image darkness.
// Note that this feature is only available in the OpenGL SiftGPU version.
bool darkness_adaptivity = false;
// Domain-size pooling parameters. Domain-size pooling computes an average
// SIFT descriptor across multiple scales around the detected scale. This was
// proposed in "Domain-Size Pooling in Local Descriptors and Network
// Architectures", J. Dong and S. Soatto, CVPR 2015. This has been shown to
// outperform other SIFT variants and learned descriptors in "Comparative
// Evaluation of Hand-Crafted and Learned Local Features", Schönberger,
// Hardmeier, Sattler, Pollefeys, CVPR 2016.
bool domain_size_pooling = false;
double dsp_min_scale = 1.0 / 6.0;
double dsp_max_scale = 3.0;
int dsp_num_scales = 10;
enum class Normalization {
// L1-normalizes each descriptor followed by element-wise square rooting.
// This normalization is usually better than standard L2-normalization.
// See "Three things everyone should know to improve object retrieval",
// Relja Arandjelovic and Andrew Zisserman, CVPR 2012.
L1_ROOT,
// Each vector is L2-normalized.
L2,
};
Normalization normalization = Normalization::L1_ROOT;
bool Check() const;
};
struct SiftMatchingOptions {
// Number of threads for feature matching and geometric verification.
int num_threads = -1;
// Whether to use the GPU for feature matching.
bool use_gpu = true;
// Index of the GPU used for feature matching. For multi-GPU matching,
// you should separate multiple GPU indices by comma, e.g., "0,1,2,3".
std::string gpu_index = "-1";
// Maximum distance ratio between first and second best match.
double max_ratio = 0.8;
// Maximum distance to best match.
double max_distance = 0.7;
// Whether to enable cross checking in matching.
bool cross_check = true;
// Maximum number of matches.
int max_num_matches = 32768;
// Maximum epipolar error in pixels for geometric verification.
double max_error = 4.0;
// Confidence threshold for geometric verification.
double confidence = 0.999;
// Minimum/maximum number of RANSAC iterations. Note that this option
// overrules the min_inlier_ratio option.
int min_num_trials = 100;
int max_num_trials = 10000;
// A priori assumed minimum inlier ratio, which determines the maximum
// number of iterations.
double min_inlier_ratio = 0.25;
// Minimum number of inliers for an image pair to be considered as
// geometrically verified.
int min_num_inliers = 15;
// Whether to attempt to estimate multiple geometric models per image pair.
bool multiple_models = false;
// Whether to perform guided matching, if geometric verification succeeds.
bool guided_matching = false;
// Force Homography use for Two-view Geometry (can help for planar scenes)
bool planar_scene = false;
bool Check() const;
};
// Extract SIFT features for the given image on the CPU. Only extract
// descriptors if the given input is not NULL.
bool ExtractSiftFeaturesCPU(const SiftExtractionOptions& options,
const Bitmap& bitmap, FeatureKeypoints* keypoints,
FeatureDescriptors* descriptors);
bool ExtractCovariantSiftFeaturesCPU(const SiftExtractionOptions& options,
const Bitmap& bitmap,
FeatureKeypoints* keypoints,
FeatureDescriptors* descriptors);
// Create a SiftGPU feature extractor. The same SiftGPU instance can be used to
// extract features for multiple images. Note a OpenGL context must be made
// current in the thread of the caller. If the gpu_index is not -1, the CUDA
// version of SiftGPU is used, which produces slightly different results
// than the OpenGL implementation.
bool CreateSiftGPUExtractor(const SiftExtractionOptions& options,
SiftGPU* sift_gpu);
// Extract SIFT features for the given image on the GPU.
// SiftGPU must already be initialized using `CreateSiftGPU`.
bool ExtractSiftFeaturesGPU(const SiftExtractionOptions& options,
const Bitmap& bitmap, SiftGPU* sift_gpu,
FeatureKeypoints* keypoints,
FeatureDescriptors* descriptors);
// Load keypoints and descriptors from text file in the following format:
//
// LINE_0: NUM_FEATURES DIM
// LINE_1: X Y SCALE ORIENTATION D_1 D_2 D_3 ... D_DIM
// LINE_I: ...
// LINE_NUM_FEATURES: X Y SCALE ORIENTATION D_1 D_2 D_3 ... D_DIM
//
// where the first line specifies the number of features and the descriptor
// dimensionality followed by one line per feature: X, Y, SCALE, ORIENTATION are
// of type float and D_J represent the descriptor in the range [0, 255].
//
// For example:
//
// 2 4
// 0.32 0.12 1.23 1.0 1 2 3 4
// 0.32 0.12 1.23 1.0 1 2 3 4
//
void LoadSiftFeaturesFromTextFile(const std::string& path,
FeatureKeypoints* keypoints,
FeatureDescriptors* descriptors);
// Match the given SIFT features on the CPU.
void MatchSiftFeaturesCPUBruteForce(const SiftMatchingOptions& match_options,
const FeatureDescriptors& descriptors1,
const FeatureDescriptors& descriptors2,
FeatureMatches* matches);
void MatchSiftFeaturesCPUFLANN(const SiftMatchingOptions& match_options,
const FeatureDescriptors& descriptors1,
const FeatureDescriptors& descriptors2,
FeatureMatches* matches);
void MatchSiftFeaturesCPU(const SiftMatchingOptions& match_options,
const FeatureDescriptors& descriptors1,
const FeatureDescriptors& descriptors2,
FeatureMatches* matches);
void MatchGuidedSiftFeaturesCPU(const SiftMatchingOptions& match_options,
const FeatureKeypoints& keypoints1,
const FeatureKeypoints& keypoints2,
const FeatureDescriptors& descriptors1,
const FeatureDescriptors& descriptors2,
TwoViewGeometry* two_view_geometry);
// Create a SiftGPU feature matcher. Note that if CUDA is not available or the
// gpu_index is -1, the OpenGLContextManager must be created in the main thread
// of the Qt application before calling this function. The same SiftMatchGPU
// instance can be used to match features between multiple image pairs.
bool CreateSiftGPUMatcher(const SiftMatchingOptions& match_options,
SiftMatchGPU* sift_match_gpu);
// Match the given SIFT features on the GPU. If either of the descriptors is
// NULL, the keypoints/descriptors will not be uploaded and the previously
// uploaded descriptors will be reused for the matching.
void MatchSiftFeaturesGPU(const SiftMatchingOptions& match_options,
const FeatureDescriptors* descriptors1,
const FeatureDescriptors* descriptors2,
SiftMatchGPU* sift_match_gpu,
FeatureMatches* matches);
void MatchGuidedSiftFeaturesGPU(const SiftMatchingOptions& match_options,
const FeatureKeypoints* keypoints1,
const FeatureKeypoints* keypoints2,
const FeatureDescriptors* descriptors1,
const FeatureDescriptors* descriptors2,
SiftMatchGPU* sift_match_gpu,
TwoViewGeometry* two_view_geometry);
} // namespace colmap
#endif // COLMAP_SRC_FEATURE_SIFT_H_