-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #815 from borglab/add/colmap-sift
Add Colmap SIFT Features
- Loading branch information
Showing
7 changed files
with
198 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
# Front-end configuration that leverages PyColmap for feature extraction and verfiication. | ||
|
||
SceneOptimizer: | ||
_target_: gtsfm.scene_optimizer.SceneOptimizer | ||
save_gtsfm_data: True | ||
save_two_view_correspondences_viz: False | ||
save_3d_viz: False | ||
pose_angular_error_thresh: 5 # degrees | ||
|
||
image_pairs_generator: | ||
_target_: gtsfm.retriever.image_pairs_generator.ImagePairsGenerator | ||
retriever: | ||
_target_: gtsfm.retriever.exhaustive_retriever.ExhaustiveRetriever | ||
|
||
correspondence_generator: | ||
_target_: gtsfm.frontend.correspondence_generator.det_desc_correspondence_generator.DetDescCorrespondenceGenerator | ||
|
||
detector_descriptor: | ||
_target_: gtsfm.frontend.cacher.detector_descriptor_cacher.DetectorDescriptorCacher | ||
detector_descriptor_obj: | ||
_target_: gtsfm.frontend.detector_descriptor.colmap_sift.ColmapSIFTDetectorDescriptor | ||
max_keypoints: 8192 | ||
|
||
matcher: | ||
_target_: gtsfm.frontend.cacher.matcher_cacher.MatcherCacher | ||
matcher_obj: | ||
_target_: gtsfm.frontend.matcher.twoway_matcher.TwoWayMatcher | ||
ratio_test_threshold: 0.8 | ||
|
||
two_view_estimator: | ||
_target_: gtsfm.two_view_estimator_cacher.TwoViewEstimatorCacher | ||
two_view_estimator_obj: | ||
_target_: gtsfm.two_view_estimator.TwoViewEstimator | ||
bundle_adjust_2view: True | ||
eval_threshold_px: 4 # in px | ||
ba_reproj_error_thresholds: [0.5] | ||
bundle_adjust_2view_maxiters: 100 | ||
|
||
verifier: | ||
_target_: gtsfm.frontend.verifier.loransac.LoRansac | ||
use_intrinsics_in_verification: True | ||
estimation_threshold_px: 4 # for H/E/F estimators | ||
|
||
triangulation_options: | ||
_target_: gtsfm.data_association.point3d_initializer.TriangulationOptions | ||
mode: | ||
_target_: gtsfm.data_association.point3d_initializer.TriangulationSamplingMode | ||
value: NO_RANSAC | ||
|
||
inlier_support_processor: | ||
_target_: gtsfm.two_view_estimator.InlierSupportProcessor | ||
min_num_inliers_est_model: 15 | ||
min_inlier_ratio_est_model: 0.1 | ||
|
||
multiview_optimizer: | ||
_target_: gtsfm.multi_view_optimizer.MultiViewOptimizer | ||
|
||
# comment out to not run | ||
view_graph_estimator: | ||
_target_: gtsfm.view_graph_estimator.cycle_consistent_rotation_estimator.CycleConsistentRotationViewGraphEstimator | ||
edge_error_aggregation_criterion: MIN_EDGE_ERROR | ||
|
||
rot_avg_module: | ||
_target_: gtsfm.averaging.rotation.shonan.ShonanRotationAveraging | ||
weight_by_inliers: True | ||
|
||
trans_avg_module: | ||
_target_: gtsfm.averaging.translation.averaging_1dsfm.TranslationAveraging1DSFM | ||
robust_measurement_noise: True | ||
projection_sampling_method: SAMPLE_INPUT_MEASUREMENTS | ||
reject_outliers: True | ||
|
||
data_association_module: | ||
_target_: gtsfm.data_association.data_assoc.DataAssociation | ||
min_track_len: 3 | ||
triangulation_options: | ||
_target_: gtsfm.data_association.point3d_initializer.TriangulationOptions | ||
reproj_error_threshold: 10 | ||
mode: | ||
_target_: gtsfm.data_association.point3d_initializer.TriangulationSamplingMode | ||
value: RANSAC_SAMPLE_UNIFORM | ||
max_num_hypotheses: 100 | ||
save_track_patches_viz: False | ||
|
||
bundle_adjustment_module: | ||
_target_: gtsfm.bundle.bundle_adjustment.BundleAdjustmentOptimizer | ||
reproj_error_thresholds: [10, 5, 3] # for (multistage) post-optimization filtering | ||
robust_measurement_noise: True | ||
shared_calib: False | ||
cam_pose3_prior_noise_sigma: 0.1 | ||
calibration_prior_noise_sigma: 1e-5 | ||
measurement_noise_sigma: 1.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
"""SIFT Detector-Descriptor implementation. | ||
The detector was proposed in 'Distinctive Image Features from Scale-Invariant Keypoints' and is implemented by wrapping | ||
over OpenCV's API. | ||
References: | ||
- https://www.cs.ubc.ca/~lowe/papers/ijcv04.pdf | ||
- https://docs.opencv.org/3.4.2/d5/d3c/classcv_1_1xfeatures2d_1_1SIFT.html | ||
Authors: Ayush Baid | ||
""" | ||
from typing import Tuple | ||
|
||
import numpy as np | ||
import pycolmap | ||
|
||
import gtsfm.utils.images as image_utils | ||
from gtsfm.common.image import Image | ||
from gtsfm.common.keypoints import Keypoints | ||
from gtsfm.frontend.detector_descriptor.detector_descriptor_base import DetectorDescriptorBase | ||
|
||
|
||
class ColmapSIFTDetectorDescriptor(DetectorDescriptorBase): | ||
"""SIFT detector-descriptor using Colmap's implementation.""" | ||
|
||
def detect_and_describe(self, image: Image) -> Tuple[Keypoints, np.ndarray]: | ||
"""Perform feature detection as well as their description. | ||
Refer to detect() in DetectorBase and describe() in DescriptorBase for details about the output format. | ||
Args: | ||
image: the input image. | ||
Returns: | ||
Detected keypoints, with length N <= max_keypoints. | ||
Corr. descriptors, of shape (N, D) where D is the dimension of each descriptor. | ||
""" | ||
|
||
# Convert to grayscale. | ||
gray_image = image_utils.rgb_to_gray_cv(image) | ||
|
||
# Create pycolmap object every time as the object is not pickle-able. | ||
# Note: cannot use SiftGPU as wheels are not built with CUDA support. | ||
options = pycolmap.SiftExtractionOptions(max_num_features=self.max_keypoints) | ||
sift_obj = pycolmap.Sift(options) | ||
|
||
# Extract features. | ||
features, descriptors = sift_obj.extract(gray_image.value_array.astype(np.float32)) | ||
|
||
# Convert to GTSFM's keypoints. | ||
# Note: Columns of features is x-coordinate, y-coordinate, scale, and orientation, respectively. | ||
keypoints = Keypoints(coordinates=features[..., :2], scales=features[:, 2]) | ||
|
||
return keypoints, descriptors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
"""Tests for SIFT detector descriptor | ||
Authors: Ayush Baid | ||
""" | ||
import unittest | ||
|
||
import tests.frontend.detector_descriptor.test_detector_descriptor_base as test_detector_descriptor_base | ||
from gtsfm.frontend.detector.detector_from_joint_detector_descriptor import DetectorFromDetectorDescriptor | ||
from gtsfm.frontend.detector_descriptor.colmap_sift import ColmapSIFTDetectorDescriptor | ||
|
||
|
||
class TestColmapSIFTDetectorDescriptor(test_detector_descriptor_base.TestDetectorDescriptorBase): | ||
"""Main test class for detector-description combination base class in frontend. | ||
All unit test functions defined in TestDetectorDescriptorBase are run automatically. | ||
""" | ||
|
||
def setUp(self): | ||
"""Setup the attributes for the tests.""" | ||
super().setUp() | ||
# Note: pycolmap does not guarantee that the number of keypoints will not exceed the specified maximum, as there | ||
# can be ties in terms of the response scores. E.g., if the 5000th keypoint and the 5001st keypoint have the | ||
# same response, pycolmap will return 5001 keypoints. Setting the number of maximum keypoints lower reduces the | ||
# risk of this happening. | ||
self.detector_descriptor = ColmapSIFTDetectorDescriptor(max_keypoints=2000) | ||
|
||
# explicitly set the detector | ||
self.detector = DetectorFromDetectorDescriptor(self.detector_descriptor) | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |
31 changes: 0 additions & 31 deletions
31
tests/frontend/detector_descriptor/test_colmap_sift_detector_descriptor.py
This file was deleted.
Oops, something went wrong.