Update parameters of cap_resolution().

Add parameter `gsd_scaling` instead of using `gsd_error_estimate` in an unintuitive way.
pull/1333/head
Magnus Linderoth 2021-08-23 16:14:55 +02:00
rodzic c97d8b6b47
commit dc1ba2966d
3 zmienionych plików z 25 dodań i 18 usunięć

Wyświetl plik

@ -5,6 +5,7 @@ import math
from repoze.lru import lru_cache
from opendm import log
def rounded_gsd(reconstruction_json, default_value=None, ndigits=0, ignore_gsd=False):
"""
:param reconstruction_json path to OpenSfM's reconstruction.json
@ -61,12 +62,15 @@ def image_scale_factor(target_resolution, reconstruction_json, gsd_error_estimat
return 1
def cap_resolution(resolution, reconstruction_json, gsd_error_estimate = 0.1, ignore_gsd=False, ignore_resolution=False, has_gcp=False):
def cap_resolution(resolution, reconstruction_json, gsd_error_estimate = 0.1, gsd_scaling = 1.0, ignore_gsd=False,
ignore_resolution=False, has_gcp=False):
"""
:param resolution resolution in cm / pixel
:param reconstruction_json path to OpenSfM's reconstruction.json
:param gsd_error_estimate percentage of estimated error in the GSD calculation to set an upper bound on resolution.
:param gsd_scaling scaling of estimated GSD.
:param ignore_gsd when set to True, forces the function to just return resolution.
:param ignore_resolution when set to True, forces the function to return a value based on GSD.
:return The max value between resolution and the GSD computed from the reconstruction.
If a GSD cannot be computed, or ignore_gsd is set to True, it just returns resolution. Units are in cm / pixel.
"""
@ -76,14 +80,16 @@ def cap_resolution(resolution, reconstruction_json, gsd_error_estimate = 0.1, ig
gsd = opensfm_reconstruction_average_gsd(reconstruction_json, use_all_shots=has_gcp or ignore_resolution)
if gsd is not None:
gsd = gsd * (1 - gsd_error_estimate)
gsd = gsd * (1 - gsd_error_estimate) * gsd_scaling
if gsd > resolution or ignore_resolution:
log.ODM_WARNING('Maximum resolution set to GSD - {}% ({} cm / pixel, requested resolution was {} cm / pixel)'.format(gsd_error_estimate * 100, round(gsd, 2), round(resolution, 2)))
log.ODM_WARNING('Maximum resolution set to {} * (GSD - {}%) '
'({:.2f} cm / pixel, requested resolution was {:.2f} cm / pixel)'
.format(gsd_scaling, gsd_error_estimate * 100, gsd, resolution))
return gsd
else:
return resolution
else:
log.ODM_WARNING('Cannot calculate GSD, using requested resolution of {}'.format(round(resolution, 2)))
log.ODM_WARNING('Cannot calculate GSD, using requested resolution of {:.2f}'.format(resolution))
return resolution
@ -134,6 +140,7 @@ def opensfm_reconstruction_average_gsd(reconstruction_json, use_all_shots=False)
return None
def calculate_gsd(sensor_width, flight_height, focal_length, image_width):
"""
:param sensor_width in millimeters
@ -154,6 +161,7 @@ def calculate_gsd(sensor_width, flight_height, focal_length, image_width):
else:
return None
def calculate_gsd_from_focal_ratio(focal_ratio, flight_height, image_width):
"""
:param focal_ratio focal length (mm) / sensor_width (mm)

Wyświetl plik

@ -13,6 +13,7 @@ from opendm import pseudogeo
from opendm.tiles.tiler import generate_dem_tiles
from opendm.cogeo import convert_to_cogeo
class ODMDEMStage(types.ODM_Stage):
def process(self, args, outputs):
tree = outputs['tree']
@ -28,11 +29,15 @@ class ODMDEMStage(types.ODM_Stage):
ignore_resolution = True
pseudo_georeference = True
# It is probably not reasonable to have accurate DEMs a the same resolution as the source photos, so reduce it
# by a factor!
gsd_scaling = 2.0
resolution = gsd.cap_resolution(args.dem_resolution, tree.opensfm_reconstruction,
gsd_error_estimate=-1,
ignore_gsd=args.ignore_gsd,
ignore_resolution=ignore_resolution,
has_gcp=reconstruction.has_gcp())
gsd_scaling=gsd_scaling,
ignore_gsd=args.ignore_gsd,
ignore_resolution=ignore_resolution,
has_gcp=reconstruction.has_gcp())
log.ODM_INFO('Classify: ' + str(args.pc_classify))
log.ODM_INFO('Create DSM: ' + str(args.dsm))

Wyświetl plik

@ -13,6 +13,7 @@ from opendm.utils import double_quote
from opendm import pseudogeo
from opendm.multispectral import get_primary_band_name
class ODMOrthoPhotoStage(types.ODM_Stage):
def process(self, args, outputs):
tree = outputs['tree']
@ -23,18 +24,11 @@ class ODMOrthoPhotoStage(types.ODM_Stage):
system.mkdir_p(tree.odm_orthophoto)
if not io.file_exists(tree.odm_orthophoto_tif) or self.rerun():
gsd_error_estimate = 0.1
ignore_resolution = False
if not reconstruction.is_georeferenced():
# Match DEMs
gsd_error_estimate = -3
ignore_resolution = True
resolution = 1.0 / (gsd.cap_resolution(args.orthophoto_resolution, tree.opensfm_reconstruction,
gsd_error_estimate=gsd_error_estimate,
ignore_gsd=args.ignore_gsd,
ignore_resolution=ignore_resolution,
has_gcp=reconstruction.has_gcp()) / 100.0)
ignore_gsd=args.ignore_gsd,
ignore_resolution=not reconstruction.is_georeferenced(),
has_gcp=reconstruction.has_gcp()) / 100.0)
# odm_orthophoto definitions
kwargs = {