From e1a326f936a3badf504edf33c9d2825a698ed34c Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Mon, 15 Nov 2021 12:09:21 -0500 Subject: [PATCH] AKAZE features, BRUTEFORCE matcher logic, geo.txt fix --- opendm/config.py | 2 +- opendm/osfm.py | 32 +++++++++++++++++++++----------- opendm/remote.py | 4 ++++ opendm/types.py | 2 +- stages/dataset.py | 2 +- stages/splitmerge.py | 8 +++++++- 6 files changed, 35 insertions(+), 15 deletions(-) diff --git a/opendm/config.py b/opendm/config.py index f6d5d16d2..c1847cf23 100755 --- a/opendm/config.py +++ b/opendm/config.py @@ -151,7 +151,7 @@ def config(argv=None, parser=None): metavar='', action=StoreValue, default='flann', - choices=['bow', 'bruteforce'. 'flann'], + choices=['bow', 'bruteforce', 'flann'], help=('Matcher algorithm, Fast Library for Approximate Nearest Neighbors or Bag of Words. FLANN is slower, but more stable. BOW is faster, but can sometimes miss valid matches. BRUTEFORCE is very slow but robust.' 'Can be one of: %(choices)s. Default: ' '%(default)s')) diff --git a/opendm/osfm.py b/opendm/osfm.py index a5e3fe1fd..88b3fc63a 100644 --- a/opendm/osfm.py +++ b/opendm/osfm.py @@ -117,9 +117,6 @@ def setup(self, args, images_path, reconstruction, append_config = [], rerun=Fal except Exception as e: log.ODM_WARNING("Cannot set camera_models_overrides.json: %s" % str(e)) - use_bow = args.matcher_type == "bow" - feature_type = "SIFT" - # GPSDOP override if we have GPS accuracy information (such as RTK) if 'gps_accuracy_is_set' in args: log.ODM_INFO("Forcing GPS DOP to %s for all images" % args.gps_accuracy) @@ -208,20 +205,33 @@ def setup(self, args, images_path, reconstruction, append_config = [], rerun=Fal if args.camera_lens != 'auto': config.append("camera_projection_type: %s" % args.camera_lens.upper()) - if not has_gps: - log.ODM_INFO("No GPS information, using BOW matching") - use_bow = True - + matcher_type = args.matcher_type feature_type = args.feature_type.upper() - if use_bow: - config.append("matcher_type: WORDS") + osfm_matchers = { + "bow": "WORDS", + "flann": "FLANN", + "bruteforce": "BRUTEFORCE" + } - # Cannot use SIFT with BOW - if feature_type == "SIFT": + if not has_gps: + log.ODM_INFO("No GPS information, using BOW matching") + matcher_type = "bow" + + if matcher_type == "bow": + # Cannot use anything other than HAHOG with BOW + if feature_type != "HAHOG": log.ODM_WARNING("Using BOW matching, will use HAHOG feature type, not SIFT") feature_type = "HAHOG" + if feature_type == "AKAZE" or feature_type == "ORB": + # Cannot use anything other than BRUTEFORCE with AKAZE/ORB + if matcher_type != "bruteforce": + log.ODM_WARNING("Using BRUTEFORCE matching (needed since %s is selected)" % feature_type) + matcher_type = "bruteforce" + + config.append("matcher_type: %s" % osfm_matchers[matcher_type]) + # GPU acceleration? if has_gpus() and feature_type == "SIFT" and (not 'min_num_features_is_set' in args): log.ODM_INFO("Using GPU for extracting SIFT features") diff --git a/opendm/remote.py b/opendm/remote.py index 30a4daea4..1d45e3bb9 100644 --- a/opendm/remote.py +++ b/opendm/remote.py @@ -341,6 +341,10 @@ def execute_remote_task(self, done, seed_files = [], seed_touch_files = [], outp if os.path.exists(self.path("gcp_list.txt")): images.append(self.path("gcp_list.txt")) + # Add GEO (optional) + if os.path.exists(self.path("geo.txt")): + images.append(self.path("geo.txt")) + # Add seed file images.append(seed_file) diff --git a/opendm/types.py b/opendm/types.py index 72255728a..9401254d9 100644 --- a/opendm/types.py +++ b/opendm/types.py @@ -5,6 +5,7 @@ from opendm import get_image_size from opendm import location from opendm.gcp import GCPFile +from opendm.geo import GeoFile from pyproj import CRS import xmltodict as x2d from six import string_types @@ -25,7 +26,6 @@ def __init__(self, photos): self.photos = photos self.georef = None self.gcp = None - self.geo_file = None self.multi_camera = self.detect_multi_camera() def detect_multi_camera(self): diff --git a/stages/dataset.py b/stages/dataset.py index 2a69ab4f2..0006e3fa6 100644 --- a/stages/dataset.py +++ b/stages/dataset.py @@ -115,7 +115,7 @@ def find_mask(photo_path, masks): dataset_list.write(photos[-1].filename + '\n') # Check if a geo file is available - if tree.odm_geo_file is not None and os.path.exists(tree.odm_geo_file): + if tree.odm_geo_file is not None and os.path.isfile(tree.odm_geo_file): log.ODM_INFO("Found image geolocation file") gf = GeoFile(tree.odm_geo_file) updated = 0 diff --git a/stages/splitmerge.py b/stages/splitmerge.py index 72e8808fa..bb28c18cc 100644 --- a/stages/splitmerge.py +++ b/stages/splitmerge.py @@ -89,7 +89,13 @@ def process(self, args, outputs): io.copy(submodel_gcp_file, os.path.abspath(sp_octx.path("gcp_list.txt"))) else: log.ODM_INFO("No GCP will be copied for %s, not enough images in the submodel are referenced by the GCP" % sp_octx.name()) - + + # Copy GEO file if needed (one for each submodel project directory) + if tree.odm_geo_file is not None and os.path.isfile(tree.odm_geo_file): + geo_dst_path = os.path.abspath(sp_octx.path("..", "geo.txt")) + io.copy(tree.odm_geo_file, geo_dst_path) + log.ODM_INFO("Copied GEO file to %s" % geo_dst_path) + # Reconstruct each submodel log.ODM_INFO("Dataset has been split into %s submodels. Reconstructing each submodel..." % len(submodel_paths)) self.update_progress(25)