From c6613910b30099e090eec82dec3d341bd329d9be Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Thu, 12 Nov 2020 10:23:02 -0500 Subject: [PATCH 1/3] Updated mvs-texturing, added --pc-quality flag, removed --texturing-nadir-weight --- SuperBuild/cmake/External-MvsTexturing.cmake | 2 +- VERSION | 2 +- opendm/config.py | 22 +++++++++---------- opendm/osfm.py | 15 +++++++------ opendm/photo.py | 9 ++++++++ opendm/utils.py | 23 ++++++++++++++++++++ stages/openmvs.py | 9 +++++--- stages/run_opensfm.py | 3 ++- 8 files changed, 60 insertions(+), 25 deletions(-) create mode 100644 opendm/utils.py diff --git a/SuperBuild/cmake/External-MvsTexturing.cmake b/SuperBuild/cmake/External-MvsTexturing.cmake index fff13360..d49b2096 100644 --- a/SuperBuild/cmake/External-MvsTexturing.cmake +++ b/SuperBuild/cmake/External-MvsTexturing.cmake @@ -9,7 +9,7 @@ ExternalProject_Add(${_proj_name} #--Download step-------------- DOWNLOAD_DIR ${SB_DOWNLOAD_DIR}/${_proj_name} GIT_REPOSITORY https://github.com/OpenDroneMap/mvs-texturing - GIT_TAG 200 + GIT_TAG 221 #--Update/Patch step---------- UPDATE_COMMAND "" #--Configure step------------- diff --git a/VERSION b/VERSION index ccbccc3d..c043eea7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2.0 +2.2.1 diff --git a/opendm/config.py b/opendm/config.py index ece64784..85b8adc6 100755 --- a/opendm/config.py +++ b/opendm/config.py @@ -235,7 +235,7 @@ def config(argv=None, parser=None): action=StoreValue, type=float, default=640, - help=('Controls the density of the point cloud by setting the resolution of the depthmap images. Higher values take longer to compute ' + help=('Legacy option (use --pc-quality instead). Controls the density of the point cloud by setting the resolution of the depthmap images. Higher values take longer to compute ' 'but produce denser point clouds. ' 'Default: %(default)s')) @@ -357,6 +357,15 @@ def config(argv=None, parser=None): 'Use 0 to disable cropping. ' 'Default: %(default)s')) + parser.add_argument('--pc-quality', + metavar='', + action=StoreValue, + default='medium', + choices=['ultra', 'high', 'medium', 'low'], + help=('Set point cloud quality. Higher quality generates better, denser point clouds, but requires more memory and takes longer. Each step up in quality increases processing time roughly by a factor of 4x.' + 'Can be one of: %(choices)s. Default: ' + '%(default)s')) + parser.add_argument('--pc-classify', action=StoreTrue, nargs=0, @@ -446,17 +455,6 @@ def config(argv=None, parser=None): help=('Data term: [area, gmi]. Default: ' '%(default)s')) - parser.add_argument('--texturing-nadir-weight', - metavar='', - action=StoreValue, - default=16, - type=int, - help=('Affects orthophotos only. ' - 'Higher values result in sharper corners, but can affect color distribution and blurriness. ' - 'Use lower values for planar areas and higher values for urban areas. ' - 'The default value works well for most scenarios. Default: ' - '%(default)s')) - parser.add_argument('--texturing-outlier-removal-type', metavar='', action=StoreValue, diff --git a/opendm/osfm.py b/opendm/osfm.py index d49574ab..ead01c3e 100644 --- a/opendm/osfm.py +++ b/opendm/osfm.py @@ -9,6 +9,8 @@ from opendm import log from opendm import system from opendm import context from opendm import camera +from opendm.utils import get_depthmap_resolution +from opendm.photo import find_largest_photo_dim from opensfm.large import metadataset from opensfm.large import tools from opensfm.actions import undistort @@ -145,6 +147,7 @@ class OSFMContext: # Compute feature_process_size feature_process_size = 2048 # default + if 'resize_to_is_set' in args: # Legacy log.ODM_WARNING("Legacy option --resize-to (this might be removed in a future version). Use --feature-quality instead.") @@ -157,12 +160,8 @@ class OSFMContext: 'low': 0.125, 'lowest': 0.0675, } - # Find largest photo dimension - max_dim = 0 - for p in photos: - if p.width is None: - continue - max_dim = max(max_dim, max(p.width, p.height)) + + max_dim = find_largest_photo_dim(photos) if max_dim > 0: log.ODM_INFO("Maximum photo dimensions: %spx" % str(max_dim)) @@ -170,6 +169,8 @@ class OSFMContext: else: log.ODM_WARNING("Cannot compute max image dimensions, going with defaults") + depthmap_resolution = get_depthmap_resolution(args, photos) + # create config file for OpenSfM config = [ "use_exif_size: no", @@ -180,7 +181,7 @@ class OSFMContext: "matching_gps_neighbors: %s" % matcher_neighbors, "matching_gps_distance: %s" % args.matcher_distance, "depthmap_method: %s" % args.opensfm_depthmap_method, - "depthmap_resolution: %s" % args.depthmap_resolution, + "depthmap_resolution: %s" % depthmap_resolution, "depthmap_min_patch_sd: %s" % args.opensfm_depthmap_min_patch_sd, "depthmap_min_consistent_views: %s" % args.opensfm_depthmap_min_consistent_views, "optimize_camera_parameters: %s" % ('no' if args.use_fixed_camera_params or args.cameras else 'yes'), diff --git a/opendm/photo.py b/opendm/photo.py index fc355869..cd99bb4f 100644 --- a/opendm/photo.py +++ b/opendm/photo.py @@ -15,6 +15,15 @@ import xmltodict as x2d from opendm import get_image_size from xml.parsers.expat import ExpatError +def find_largest_photo_dim(photos): + max_dim = 0 + for p in photos: + if p.width is None: + continue + max_dim = max(max_dim, max(p.width, p.height)) + + return max_dim + class ODM_Photo: """ODMPhoto - a class for ODMPhotos""" diff --git a/opendm/utils.py b/opendm/utils.py new file mode 100644 index 00000000..42cc2c6d --- /dev/null +++ b/opendm/utils.py @@ -0,0 +1,23 @@ +from opendm import log +from opendm.photo import find_largest_photo_dim + +def get_depthmap_resolution(args, photos): + if 'depthmap_resolution_is_set' in args: + # Legacy + log.ODM_WARNING("Legacy option --depthmap-resolution (this might be removed in a future version). Use --pc-quality instead.") + return int(args.depthmap_resolution) + else: + max_dim = find_largest_photo_dim(photos) + + pc_quality_scale = { + 'ultra': 0.5, + 'high': 0.25, + 'medium': 0.125, + 'low': 0.0675 + } + + if max_dim > 0: + return int(max_dim * pc_quality_scale[args.pc_quality]) + else: + log.ODM_WARNING("Cannot compute max image dimensions, going with default depthmap_resolution of 640") + return 640 # Sensible default diff --git a/stages/openmvs.py b/stages/openmvs.py index 961a86c7..35a9a9c8 100644 --- a/stages/openmvs.py +++ b/stages/openmvs.py @@ -6,6 +6,7 @@ from opendm import system from opendm import context from opendm import point_cloud from opendm import types +from opendm.utils import get_depthmap_resolution from opendm.osfm import OSFMContext class ODMOpenMVSStage(types.ODM_Stage): @@ -39,15 +40,17 @@ class ODMOpenMVSStage(types.ODM_Stage): depthmaps_dir = os.path.join(tree.openmvs, "depthmaps") if not io.dir_exists(depthmaps_dir): os.mkdir(depthmaps_dir) + + depthmap_resolution = get_depthmap_resolution(args, photos) - if outputs["undist_image_max_size"] <= args.depthmap_resolution: + if outputs["undist_image_max_size"] <= depthmap_resolution: resolution_level = 0 else: - resolution_level = math.floor(math.log(outputs['undist_image_max_size'] / float(args.depthmap_resolution)) / math.log(2)) + resolution_level = math.floor(math.log(outputs['undist_image_max_size'] / float(depthmap_resolution)) / math.log(2)) config = [ " --resolution-level %s" % int(resolution_level), - "--min-resolution %s" % int(args.depthmap_resolution), + "--min-resolution %s" % depthmap_resolution, "--max-resolution %s" % int(outputs['undist_image_max_size']), "--max-threads %s" % args.max_concurrency, '-w "%s"' % depthmaps_dir, diff --git a/stages/run_opensfm.py b/stages/run_opensfm.py index a5bf34c1..fee9e3d9 100644 --- a/stages/run_opensfm.py +++ b/stages/run_opensfm.py @@ -10,6 +10,7 @@ from opendm import context from opendm import gsd from opendm import point_cloud from opendm import types +from opendm.utils import get_depthmap_resolution from opendm.osfm import OSFMContext from opendm import multispectral @@ -60,7 +61,7 @@ class ODMOpenSfMStage(types.ODM_Stage): # since the undistorted images are used for MVS outputs['undist_image_max_size'] = max( gsd.image_max_size(photos, args.orthophoto_resolution, tree.opensfm_reconstruction, ignore_gsd=args.ignore_gsd, has_gcp=reconstruction.has_gcp()), - args.depthmap_resolution + get_depthmap_resolution(args, photos) ) if not io.file_exists(updated_config_flag_file) or self.rerun(): From 489ab390a4345c47622065a232145ec32c32e847 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Thu, 12 Nov 2020 10:32:07 -0500 Subject: [PATCH 2/3] Remove CPP from codeql --- .github/workflows/codeql-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 3883ce6b..d4f6eef1 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -29,7 +29,7 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'cpp', 'python' ] + language: [ 'python' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] # Learn more... # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection From 6aef1de9359f82c48c505c6deed1b10e844a108b Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Thu, 12 Nov 2020 19:38:13 -0500 Subject: [PATCH 3/3] Fix mvstex bug referencing old config parameter --- stages/mvstex.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/stages/mvstex.py b/stages/mvstex.py index eff92899..bcf7ea6c 100644 --- a/stages/mvstex.py +++ b/stages/mvstex.py @@ -91,7 +91,6 @@ class ODMMvsTexStage(types.ODM_Stage): 'keepUnseenFaces': keepUnseenFaces, 'toneMapping': self.params.get('tone_mapping'), 'nadirMode': nadir, - 'nadirWeight': 2 ** args.texturing_nadir_weight - 1, 'nvm_file': r['nvm_file'] } @@ -111,8 +110,7 @@ class ODMMvsTexStage(types.ODM_Stage): '{skipLocalSeamLeveling} ' '{skipHoleFilling} ' '{keepUnseenFaces} ' - '{nadirMode} ' - '-n {nadirWeight}'.format(**kwargs)) + '{nadirMode}'.format(**kwargs)) if args.optimize_disk_space: cleanup_files = [