Skip to content

Commit

Permalink
Merge pull request #1201 from pierotofy/221
Browse files Browse the repository at this point in the history
Improved orthophotos, added --pc-quality flag
  • Loading branch information
pierotofy committed Nov 15, 2020
2 parents f90960c + 6aef1de commit 786833d
Show file tree
Hide file tree
Showing 10 changed files with 62 additions and 29 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion SuperBuild/cmake/External-MvsTexturing.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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-------------
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.2.0
2.2.1
22 changes: 10 additions & 12 deletions opendm/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'))

Expand Down Expand Up @@ -357,6 +357,15 @@ def config(argv=None, parser=None):
'Use 0 to disable cropping. '
'Default: %(default)s'))

parser.add_argument('--pc-quality',
metavar='<string>',
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,
Expand Down Expand Up @@ -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='<integer: 0 <= x <= 32>',
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='<string>',
action=StoreValue,
Expand Down
15 changes: 8 additions & 7 deletions opendm/osfm.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
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
Expand Down Expand Up @@ -145,6 +147,7 @@ def setup(self, args, images_path, photos, reconstruction, append_config = [], r

# 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.")
Expand All @@ -157,19 +160,17 @@ def setup(self, args, images_path, photos, reconstruction, append_config = [], r
'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))
feature_process_size = int(max_dim * feature_quality_scale[args.feature_quality])
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",
Expand All @@ -180,7 +181,7 @@ def setup(self, args, images_path, photos, reconstruction, append_config = [], r
"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'),
Expand Down
9 changes: 9 additions & 0 deletions opendm/photo.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@
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"""

Expand Down
23 changes: 23 additions & 0 deletions opendm/utils.py
Original file line number Diff line number Diff line change
@@ -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
4 changes: 1 addition & 3 deletions stages/mvstex.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ def add_run(nvm_file, primary=True, band=None):
'keepUnseenFaces': keepUnseenFaces,
'toneMapping': self.params.get('tone_mapping'),
'nadirMode': nadir,
'nadirWeight': 2 ** args.texturing_nadir_weight - 1,
'nvm_file': r['nvm_file']
}

Expand All @@ -111,8 +110,7 @@ def add_run(nvm_file, primary=True, band=None):
'{skipLocalSeamLeveling} '
'{skipHoleFilling} '
'{keepUnseenFaces} '
'{nadirMode} '
'-n {nadirWeight}'.format(**kwargs))
'{nadirMode}'.format(**kwargs))

if args.optimize_disk_space:
cleanup_files = [
Expand Down
9 changes: 6 additions & 3 deletions stages/openmvs.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
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):
Expand Down Expand Up @@ -39,15 +40,17 @@ def process(self, args, outputs):
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,
Expand Down
3 changes: 2 additions & 1 deletion stages/run_opensfm.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
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

Expand Down Expand Up @@ -60,7 +61,7 @@ def process(self, args, outputs):
# 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():
Expand Down

0 comments on commit 786833d

Please sign in to comment.