-
Notifications
You must be signed in to change notification settings - Fork 895
Expand file tree
/
Copy pathconfig.py
More file actions
429 lines (392 loc) · 18.8 KB
/
config.py
File metadata and controls
429 lines (392 loc) · 18.8 KB
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
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
# pyre-strict
from __future__ import annotations
import os
from dataclasses import asdict, dataclass
from typing import Any, Dict, IO, Union
import yaml
@dataclass
class OpenSfMConfig:
##################################
# Params for metadata
##################################
use_exif_size: bool = True
# Treat images from unknown camera models as coming from different cameras
unknown_camera_models_are_different: bool = False
default_focal_prior: float = 0.85
##################################
# Params for features
##################################
# Feature type (AKAZE, SURF, SIFT, HAHOG, ORB)
feature_type: str = "HAHOG"
# If true, apply square root mapping to features
feature_root: bool = True
# If fewer frames are detected, sift_peak_threshold/surf_hessian_threshold is reduced.
feature_min_frames: int = 4000
# Same as above but for panorama images
feature_min_frames_panorama: int = 16000
# Resize the image if its size is larger than specified. Set to -1 for original size
feature_process_size: int = 2048
# Same as above but for panorama images
feature_process_size_panorama: int = 4096
feature_use_adaptive_suppression: bool = False
# Bake segmentation info (class and instance) in the feature data. Thus it is done once for all at extraction time.
features_bake_segmentation: bool = False
# Maximum amount of memory to use for feature extraction (in MB). See default in features_processing.py.
mem_ceiling: int | None = None
# Ratio of the memory ceiling to use for feature extraction. See default in features_processing.py.
mem_ratio: float | None = None
##################################
# Params for SIFT
##################################
# Smaller value -> more features
sift_peak_threshold: float = 0.1
# See OpenCV doc
sift_edge_threshold: int = 10
# See OpenCV doc
sift_nfeatures: int = 0
# See OpenCV doc
sift_octave_layers: int = 3
# See OpenCV doc
sift_sigma: float = 1.6
##################################
# Params for SURF
##################################
# Smaller value -> more features
surf_hessian_threshold: float = 3000
# See OpenCV doc
surf_n_octaves: int = 4
# See OpenCV doc
surf_n_octavelayers: int = 2
# See OpenCV doc
surf_upright: int = 0
##################################
# Params for AKAZE (See details in lib/src/third_party/akaze/AKAZEConfig.h)
##################################
# Maximum octave evolution of the image 2^sigma (coarsest scale sigma units)
akaze_omax: int = 4
# Detector response threshold to accept point
akaze_dthreshold: float = 0.001
# Feature type
akaze_descriptor: str = "MSURF"
# Size of the descriptor in bits. 0->Full size
akaze_descriptor_size: int = 0
# Number of feature channels (1,2,3)
akaze_descriptor_channels: int = 3
akaze_kcontrast_percentile: float = 0.7
akaze_use_isotropic_diffusion: bool = False
##################################
# Params for HAHOG
##################################
hahog_peak_threshold: float = 0.00001
hahog_edge_threshold: float = 10
hahog_normalize_to_uchar: bool = True
##################################
# Params for general matching
##################################
# Ratio test for matches
lowes_ratio: float = 0.8
# FLANN, BRUTEFORCE, or WORDS
matcher_type: str = "FLANN"
# Match symmetrically or one-way
symmetric_matching: bool = True
##################################
# Params for FLANN matching
##################################
# Algorithm type (KMEANS, KDTREE)
flann_algorithm: str = "KMEANS"
# See OpenCV doc
flann_branching: int = 8
# See OpenCV doc
flann_iterations: int = 10
# See OpenCV doc
flann_tree: int = 8
# Smaller -> Faster (but might lose good matches)
flann_checks: int = 20
##################################
# Params for BoW matching
##################################
bow_file: str = "bow_hahog_root_uchar_10000.npz"
# Number of words to explore per feature.
bow_words_to_match: int = 50
# Number of matching features to check.
bow_num_checks: int = 20
# Matcher type to assign words to features
bow_matcher_type: str = "FLANN"
##################################
# Params for VLAD matching
##################################
vlad_file: str = "bow_hahog_root_uchar_64.npz"
##################################
# Params for guided matching
##################################
# Number of randomized spanning-trees to samples over the tracks-graph
guided_spanning_trees: int = 5
# Random ratio higher bound edges are multiplied with
guided_spanning_trees_random: float = 0.5
# Threshold for epipolar distance for accepting a match in radians
guided_matching_threshold: float = 0.006
# Minimum track length for initial triangulation
guided_min_length_initial: int = 3
# Minimum track length for final triangulation
guided_min_length_final: int = 3
# Threshold of reprojection for extending a track within a new image (in radians)
guided_extend_threshold: float = 0.002
# Number of images considered as neighbors of another one
guided_extend_image_neighbors: int = 50
# Maximum number of reprojected neighbors (in the tracks-graph) to check when extending a track within a new image
guided_extend_feature_neighbors: int = 10
##################################
# Params for matching
##################################
# Maximum gps distance between two images for matching
matching_gps_distance: float = 150
# Number of images to match selected by GPS distance. Set to 0 to use no limit (or disable if matching_gps_distance is also 0)
matching_gps_neighbors: int = 0
# Number of images to match selected by time taken. Set to 0 to disable
matching_time_neighbors: int = 0
# Number of images to match selected by image name. Set to 0 to disable
matching_order_neighbors: int = 0
# Number of images to match selected by BoW distance. Set to 0 to disable
matching_bow_neighbors: int = 0
# Maximum GPS distance for preempting images before using selection by BoW distance. Set to 0 to disable
matching_bow_gps_distance: float = 0
# Number of images (selected by GPS distance) to preempt before using selection by BoW distance. Set to 0 to use no limit (or disable if matching_bow_gps_distance is also 0)
matching_bow_gps_neighbors: int = 0
# If True, BoW image selection will use N neighbors from the same camera + N neighbors from any different camera. If False, the selection will take the nearest neighbors from all cameras.
matching_bow_other_cameras: bool = False
# Number of images to match selected by VLAD distance. Set to 0 to disable
matching_vlad_neighbors: int = 0
# Maximum GPS distance for preempting images before using selection by VLAD distance. Set to 0 to disable
matching_vlad_gps_distance: float = 0
# Number of images (selected by GPS distance) to preempt before using selection by VLAD distance. Set to 0 to use no limit (or disable if matching_vlad_gps_distance is also 0)
matching_vlad_gps_neighbors: int = 0
# If True, VLAD image selection will use N neighbors from the same camera + N neighbors from any different camera. If False, the selection will take the nearest neighbors from all cameras.
matching_vlad_other_cameras: bool = False
# Number of rounds to run when running triangulation-based pair selection
matching_graph_rounds: int = 0
# If True, removes static matches using ad-hoc heuristics
matching_use_filters: bool = False
# Use segmentation information (if available) to improve matching
matching_use_segmentation: bool = False
##################################
# Params for geometric estimation
##################################
# Outlier threshold for fundamental matrix estimation as portion of image width
robust_matching_threshold: float = 0.004
# Outlier threshold for essential matrix estimation during matching in radians
robust_matching_calib_threshold: float = 0.004
# Minimum number of matches to accept matches between two images
robust_matching_min_match: int = 20
# Outlier threshold for essential matrix estimation during incremental reconstruction in radians
five_point_algo_threshold: float = 0.004
# Minimum number of inliers for considering a two view reconstruction valid
five_point_algo_min_inliers: int = 20
# Number of LM iterations to run when refining relative pose during matching
five_point_refine_match_iterations: int = 10
# Number of LM iterations to run when refining relative pose during reconstruction
five_point_refine_rec_iterations: int = 1000
# Check for Necker reversal ambiguities. Useful for long focal length with long distance capture (aerial manned)
five_point_reversal_check: bool = False
# Ratio of triangulated points non-reversed/reversed when checking for Necker reversal ambiguities
five_point_reversal_ratio: float = 0.95
# Outlier threshold for accepting a triangulated point in radians
triangulation_threshold: float = 0.006
# Minimum angle between views to accept a triangulated point
triangulation_min_ray_angle: float = 1.0
# Minimum depth to accept a triangulated point
triangulation_min_depth: float = 0.001
# Triangulation type : either considering all rays (FULL), or sing a RANSAC variant (ROBUST)
triangulation_type: str = "FULL"
# Number of LM iterations to run when refining a point
triangulation_refinement_iterations: int = 10
# Outlier threshold for resection in radians
resection_threshold: float = 0.004
# Minimum number of resection inliers to accept it
resection_min_inliers: int = 10
##################################
# Params for track creation
##################################
# Minimum number of features/images per track
min_track_length: int = 2
# Whether to use depth prior during BA
use_depth_prior: bool = False
# Depth prior default std deviation
depth_std_deviation_m_default: float = 1.0
# Whether depth is radial (distance to camera center) or Z value
depth_is_radial: bool = False
# Whether depth is stored as inverted depth
depth_is_inverted: bool = False
##################################
# Params for bundle adjustment
##################################
# Loss function for the ceres problem (see: http://ceres-solver.org/modeling.html#lossfunction)
loss_function: str = "SoftLOneLoss"
# Threshold on the squared residuals. Usually cost is quadratic for smaller residuals and sub-quadratic above.
loss_function_threshold: float = 1
# The standard deviation of the reprojection error
reprojection_error_sd: float = 0.004
# The standard deviation of the exif focal length in log-scale
exif_focal_sd: float = 0.01
# The standard deviation of aspect ratio, i.e. fu/fv, in log-scale
aspect_ratio_sd: float = 0.01
# The standard deviation of the principal point coordinates
principal_point_sd: float = 0.01
# The standard deviation of the first radial distortion parameter
radial_distortion_k1_sd: float = 0.01
# The standard deviation of the second radial distortion parameter
radial_distortion_k2_sd: float = 0.01
# The standard deviation of the third radial distortion parameter
radial_distortion_k3_sd: float = 0.01
# The standard deviation of the fourth radial distortion parameter
radial_distortion_k4_sd: float = 0.01
# The standard deviation of the first tangential distortion parameter
tangential_distortion_p1_sd: float = 0.01
# The standard deviation of the second tangential distortion parameter
tangential_distortion_p2_sd: float = 0.01
# The default horizontal standard deviation of the GCPs (in meters)
gcp_horizontal_sd: float = 0.01
# The default vertical standard deviation of the GCPs (in meters)
gcp_vertical_sd: float = 0.1
# Global weight for GCPs, expressed a ratio of the sum of (# projections) + (# shots) + (# relative motions)
gcp_global_weight: float = 0.1
# The standard deviation of the rig translation
rig_translation_sd: float = 0.1
# The standard deviation of the rig rotation
rig_rotation_sd: float = 0.1
# Type of threshold for filtering outlier : either fixed value (FIXED) or based on actual distribution (AUTO)
bundle_outlier_filtering_type: str = "FIXED"
# For AUTO filtering type, projections with larger reprojection than ratio-times-mean, are removed
bundle_outlier_auto_ratio: float = 3.0
# For FIXED filtering type, projections with larger reprojection error after bundle adjustment are removed
bundle_outlier_fixed_threshold: float = 0.006
# Optimize internal camera parameters during bundle
optimize_camera_parameters: bool = True
# Maximum optimizer iterations.
bundle_max_iterations: int = 100
# Ratio of (resection candidates / total tracks) of a given image so that it is culled at resection and resected later
resect_redundancy_threshold: float = 0.7
# Retriangulate all points from time to time
retriangulation: bool = True
# Retriangulate when the number of points grows by this ratio
retriangulation_ratio: float = 1.2
# Use analytic derivatives or auto-differentiated ones during bundle adjustment
bundle_analytic_derivatives: bool = True
# Bundle after adding 'bundle_interval' cameras
bundle_interval: int = 999999
# Bundle when the number of points grows by this ratio
bundle_new_points_ratio: float = 1.2
# Max image graph distance for images to be included in local bundle adjustment
local_bundle_radius: int = 3
# Minimum number of common points betwenn images to be considered neighbors
local_bundle_min_common_points: int = 20
# Max number of shots to optimize during local bundle adjustment
local_bundle_max_shots: int = 30
# Number of grid division for seleccting tracks in local bundle adjustment
local_bundle_grid: int = 8
# Number of grid division for selecting tracks in final bundle adjustment
final_bundle_grid: int = 32
# Remove uncertain and isolated points from the final point cloud
filter_final_point_cloud: bool = False
# Save reconstructions at every iteration
save_partial_reconstructions: bool = False
##################################
# Params for GPS/GCP alignment
##################################
# Use or ignore EXIF altitude tag
use_altitude_tag: bool = True
# orientation_prior or naive
align_method: str = "auto"
# horizontal, vertical or no_roll
align_orientation_prior: str = "horizontal"
# Enforce GPS position in bundle adjustment
bundle_use_gps: bool = True
# Enforce Ground Control Point position in bundle adjustment
bundle_use_gcp: bool = True
# Compensate GPS with a per-camera similarity transform
bundle_compensate_gps_bias: bool = False
# Thrershold for the reprojection error of GCPs to be considered outliers
gcp_reprojection_error_threshold: float = 0.05
##################################
# Params for rigs
##################################
# Number of rig instances to use when calibration rigs
rig_calibration_subset_size: int = 15
# Ratio of reconstructed images needed to consider a reconstruction for rig calibration
rig_calibration_completeness: float = 0.85
# Number of SfM tentatives to run until we get a satisfying reconstruction
rig_calibration_max_rounds: int = 10
##################################
# Params for image undistortion
##################################
# Format in which to save the undistorted images
undistorted_image_format: str = "jpg"
# Max width and height of the undistorted image
undistorted_image_max_size: int = 100000
##################################
# Params for depth estimation
##################################
# Raw depthmap computation algorithm (PATCH_MATCH, BRUTE_FORCE, PATCH_MATCH_SAMPLE)
depthmap_method: str = "PATCH_MATCH_SAMPLE"
# Resolution of the depth maps
depthmap_resolution: int = 640
# Number of neighboring views
depthmap_num_neighbors: int = 10
# Number of neighboring views used for each depthmaps
depthmap_num_matching_views: int = 6
# Minimum depth in meters. Set to 0 to auto-infer from the reconstruction.
depthmap_min_depth: float = 0
# Maximum depth in meters. Set to 0 to auto-infer from the reconstruction.
depthmap_max_depth: float = 0
# Number of PatchMatch iterations to run
depthmap_patchmatch_iterations: int = 3
# Size of the correlation patch
depthmap_patch_size: int = 7
# Patches with lower standard deviation are ignored
depthmap_min_patch_sd: float = 1.0
# Minimum correlation score to accept a depth value
depthmap_min_correlation_score: float = 0.1
# Threshold to measure depth closeness
depthmap_same_depth_threshold: float = 0.01
# Min number of views that should reconstruct a point for it to be valid
depthmap_min_consistent_views: int = 3
# Save debug files with partial reconstruction results
depthmap_save_debug_files: bool = False
##################################
# Params for multi-processing/threading
##################################
# Number of threads to use
processes: int = 1
# When processes > 1, number of threads used for reading images
read_processes: int = 4
##################################
# Params for submodel split and merge
##################################
# Average number of images per submodel
submodel_size: int = 80
# Radius of the overlapping region between submodels
submodel_overlap: float = 30.0
# Relative path to the submodels directory
submodels_relpath: str = "submodels"
# Template to generate the relative path to a submodel directory
submodel_relpath_template: str = "submodels/submodel_%04d"
# Template to generate the relative path to a submodel images directory
submodel_images_relpath_template: str = "submodels/submodel_%04d/images"
def default_config() -> Dict[str, Any]:
"""Return default configuration"""
return asdict(OpenSfMConfig())
def load_config(filepath: str) -> Dict[str, Any]:
"""DEPRECATED: = Load config from a config.yaml filepath"""
if not os.path.isfile(filepath):
return default_config()
with open(filepath) as fin:
return load_config_from_fileobject(fin)
def load_config_from_fileobject(
f: Union[IO[bytes], IO[str], bytes, str],
) -> Dict[str, Any]:
"""Load config from a config.yaml fileobject"""
config = default_config()
new_config = yaml.safe_load(f)
if new_config:
for k, v in new_config.items():
config[k] = v
return config