kopia lustrzana https://github.com/OpenDroneMap/ODM
Local submodel reconstruction, alignment
rodzic
277b60c22d
commit
3087af2775
|
@ -2,6 +2,7 @@
|
|||
OpenSfM related utils
|
||||
"""
|
||||
|
||||
import os
|
||||
from opendm import io
|
||||
from opendm import log
|
||||
from opendm import system
|
||||
|
@ -13,7 +14,7 @@ def run(command, opensfm_project_path):
|
|||
|
||||
|
||||
def export_bundler(opensfm_project_path, destination_bundle_file, rerun=False):
|
||||
if not io.file_exists(destination_bundle_file) or self.rerun():
|
||||
if not io.file_exists(destination_bundle_file) or rerun:
|
||||
# convert back to bundler's format
|
||||
system.run('%s/bin/export_bundler %s' %
|
||||
(context.opensfm_path, opensfm_project_path))
|
||||
|
@ -21,6 +22,31 @@ def export_bundler(opensfm_project_path, destination_bundle_file, rerun=False):
|
|||
log.ODM_WARNING('Found a valid Bundler file in: %s' % destination_bundle_file)
|
||||
|
||||
|
||||
def reconstruct(opensfm_project_path, rerun=False):
|
||||
tracks_file = os.path.join(opensfm_project_path, 'tracks.csv')
|
||||
reconstruction_file = os.path.join(opensfm_project_path, 'reconstruction.json')
|
||||
|
||||
if not io.file_exists(tracks_file) or rerun:
|
||||
run('create_tracks', opensfm_project_path)
|
||||
else:
|
||||
log.ODM_WARNING('Found a valid OpenSfM tracks file in: %s' % tracks_file)
|
||||
|
||||
if not io.file_exists(reconstruction_file) or rerun:
|
||||
run('reconstruct', opensfm_project_path)
|
||||
else:
|
||||
log.ODM_WARNING('Found a valid OpenSfM reconstruction file in: %s' % reconstruction_file)
|
||||
|
||||
# Check that a reconstruction file has been created
|
||||
if not io.file_exists(reconstruction_file):
|
||||
log.ODM_ERROR("The program could not process this dataset using the current settings. "
|
||||
"Check that the images have enough overlap, "
|
||||
"that there are enough recognizable features "
|
||||
"and that the images are in focus. "
|
||||
"You could also try to increase the --min-num-features parameter."
|
||||
"The program will now exit.")
|
||||
raise Exception("Reconstruction could not be generated")
|
||||
|
||||
|
||||
def setup(args, images_path, opensfm_path, photos, gcp_path=None, append_config = []):
|
||||
"""
|
||||
Setup a OpenSfM project
|
||||
|
@ -82,7 +108,7 @@ def setup(args, images_path, opensfm_path, photos, gcp_path=None, append_config
|
|||
with open(config_filename, 'w') as fout:
|
||||
fout.write("\n".join(config))
|
||||
|
||||
def run_feature_matching(opensfm_project_path, rerun=False):
|
||||
def feature_matching(opensfm_project_path, rerun=False):
|
||||
matched_done_file = io.join_paths(opensfm_project_path, 'matching_done.txt')
|
||||
if not io.file_exists(matched_done_file) or rerun:
|
||||
run('extract_metadata', opensfm_project_path)
|
||||
|
|
|
@ -373,11 +373,9 @@ class ODM_Stage:
|
|||
"""
|
||||
Does this stage need to be rerun?
|
||||
"""
|
||||
return (self.args.rerun is not None and
|
||||
self.args.rerun == self.name) or \
|
||||
return (self.args.rerun is not None and self.args.rerun == self.name) or \
|
||||
(self.args.rerun_all) or \
|
||||
(self.args.rerun_from is not None and
|
||||
self.name in self.args.rerun_from)
|
||||
(self.args.rerun_from is not None and self.name in self.args.rerun_from)
|
||||
|
||||
def run(self, outputs = {}):
|
||||
start_time = system.now_raw()
|
||||
|
|
|
@ -28,34 +28,15 @@ class ODMOpenSfMStage(types.ODM_Stage):
|
|||
output_file = tree.opensfm_reconstruction
|
||||
|
||||
# check if reconstruction was done before
|
||||
# TODO: more granularity for each step (setup/featurematch/reconstruction/etc.)
|
||||
|
||||
if not io.file_exists(output_file) or self.rerun():
|
||||
|
||||
osfm.setup(args, tree.dataset_raw, tree.opensfm, photos, gcp_path=tree.odm_georeferencing_gcp)
|
||||
|
||||
osfm.run_feature_matching(tree.opensfm, self.rerun())
|
||||
|
||||
if not io.file_exists(tree.opensfm_tracks) or self.rerun():
|
||||
osfm.run('create_tracks', tree.opensfm)
|
||||
else:
|
||||
log.ODM_WARNING('Found a valid OpenSfM tracks file in: %s' %
|
||||
tree.opensfm_tracks)
|
||||
|
||||
if not io.file_exists(tree.opensfm_reconstruction) or self.rerun():
|
||||
osfm.run('reconstruct', tree.opensfm)
|
||||
else:
|
||||
log.ODM_WARNING('Found a valid OpenSfM reconstruction file in: %s' %
|
||||
tree.opensfm_reconstruction)
|
||||
|
||||
# Check that a reconstruction file has been created
|
||||
if not io.file_exists(tree.opensfm_reconstruction):
|
||||
log.ODM_ERROR("The program could not process this dataset using the current settings. "
|
||||
"Check that the images have enough overlap, "
|
||||
"that there are enough recognizable features "
|
||||
"and that the images are in focus. "
|
||||
"You could also try to increase the --min-num-features parameter."
|
||||
"The program will now exit.")
|
||||
sys.exit(1)
|
||||
osfm.feature_matching(tree.opensfm, self.rerun())
|
||||
|
||||
osfm.reconstruction(tree.opensfm, self.rerun())
|
||||
|
||||
# Always export VisualSFM's reconstruction and undistort images
|
||||
# as we'll use these for texturing (after GSD estimation and resizing)
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import os
|
||||
from opendm import log
|
||||
from opendm import osfm
|
||||
from opendm import types
|
||||
from opendm import io
|
||||
from opensfm.large import metadataset
|
||||
|
||||
class ODMSplitStage(types.ODM_Stage):
|
||||
def process(self, args, outputs):
|
||||
|
@ -23,7 +25,7 @@ class ODMSplitStage(types.ODM_Stage):
|
|||
|
||||
osfm.setup(args, tree.dataset_raw, tree.opensfm, photos, gcp_path=tree.odm_georeferencing_gcp, append_config=config)
|
||||
|
||||
osfm.run_feature_matching(tree.opensfm, self.rerun())
|
||||
osfm.feature_matching(tree.opensfm, self.rerun())
|
||||
|
||||
# Create submodels
|
||||
if not io.dir_exists(tree.submodels_path) or self.rerun():
|
||||
|
@ -35,7 +37,31 @@ class ODMSplitStage(types.ODM_Stage):
|
|||
else:
|
||||
log.ODM_WARNING("Submodels directory already exist at: %s" % tree.submodels_path)
|
||||
|
||||
# TODO: on a network workflow we probably stop here
|
||||
# and let NodeODM take over
|
||||
# exit(0)
|
||||
|
||||
# Find paths of all submodels
|
||||
mds = metadataset.MetaDataSet(tree.opensfm)
|
||||
submodel_paths = [os.path.abspath(p) for p in mds.get_submodel_paths()]
|
||||
|
||||
# Reconstruct each submodel
|
||||
log.ODM_INFO("Dataset has been split into %s submodels. Reconstructing each submodel..." % len(submodel_paths))
|
||||
|
||||
for sp in submodel_paths:
|
||||
log.ODM_INFO("Reconstructing %s" % sp)
|
||||
osfm.reconstruct(sp, self.rerun())
|
||||
|
||||
# Align
|
||||
log.ODM_INFO("Aligning submodels...")
|
||||
osfm.run('align_submodels', tree.opensfm)
|
||||
|
||||
# Dense reconstruction for each submodel
|
||||
# TODO
|
||||
|
||||
exit(1)
|
||||
else:
|
||||
log.ODM_INFO("Normal dataset, will process all at once.")
|
||||
|
||||
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue