File size: 11,175 Bytes
2b5a2b6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | // 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_
|