diff --git a/opendm/config.py b/opendm/config.py index ec22ea69..60921204 100644 --- a/opendm/config.py +++ b/opendm/config.py @@ -33,6 +33,10 @@ parser.add_argument('--rerun', '-r', choices=processopts, help=('Can be one of:' + ' | '.join(processopts))) +parser.add_argument('--video', + metavar='', + help='Path to the video file to process') + parser.add_argument('--force-focal', metavar='', type=float, diff --git a/scripts/odm_app.py b/scripts/odm_app.py index 19236eb6..a9795215 100644 --- a/scripts/odm_app.py +++ b/scripts/odm_app.py @@ -7,6 +7,7 @@ from opendm import config from dataset import ODMLoadDatasetCell from resize import ODMResizeCell from opensfm import ODMOpenSfMCell +from odm_slam import ODMSlamCell from pmvs import ODMPmvsCell from cmvs import ODMCmvsCell from odm_meshing import ODMeshingCell @@ -40,6 +41,7 @@ class ODMApp(ecto.BlackBox): processes=context.num_cores, matching_gps_neighbors=p.args['matcher_neighbors'], matching_gps_distance=p.args['matcher_distance']), + 'slam': ODMSlamCell(), 'cmvs': ODMCmvsCell(max_images=p.args['cmvs_maxImages']), 'pmvs': ODMPmvsCell(level=p.args['pmvs_level'], csize=p.args['pmvs_csize'], @@ -68,6 +70,8 @@ class ODMApp(ecto.BlackBox): self.tree = ecto.Constant(value=tree) def connections(self, _p): + run_slam = _p.args.get('video') is not None + # define initial task initial_task = _p.args['start_with'] initial_task_id = config.processopts.index(initial_task) @@ -75,23 +79,33 @@ class ODMApp(ecto.BlackBox): ## define the connections like you would for the plasm connections = [] - ## load the dataset - connections = [ self.tree[:] >> self.dataset['tree'] ] + if run_slam: + # run slam cell + connections += [ self.tree[:] >> self.slam['tree'], + self.args[:] >> self.slam['args'] ] - # run resize cell - connections += [ self.tree[:] >> self.resize['tree'], - self.args[:] >> self.resize['args'], - self.dataset['photos'] >> self.resize['photos'] ] + # run cmvs + connections += [ self.tree[:] >> self.cmvs['tree'], + self.args[:] >> self.cmvs['args'], + self.slam['reconstruction'] >> self.cmvs['reconstruction'] ] + else: + # load the dataset + connections = [ self.tree[:] >> self.dataset['tree'] ] - # run opensfm with images from load dataset - connections += [ self.tree[:] >> self.opensfm['tree'], - self.args[:] >> self.opensfm['args'], - self.resize['photos'] >> self.opensfm['photos'] ] - - # run cmvs - connections += [ self.tree[:] >> self.cmvs['tree'], - self.args[:] >> self.cmvs['args'], - self.opensfm['reconstruction'] >> self.cmvs['reconstruction'] ] + # run resize cell + connections += [ self.tree[:] >> self.resize['tree'], + self.args[:] >> self.resize['args'], + self.dataset['photos'] >> self.resize['photos'] ] + + # run opensfm with images from load dataset + connections += [ self.tree[:] >> self.opensfm['tree'], + self.args[:] >> self.opensfm['args'], + self.resize['photos'] >> self.opensfm['photos'] ] + + # run cmvs + connections += [ self.tree[:] >> self.cmvs['tree'], + self.args[:] >> self.cmvs['args'], + self.opensfm['reconstruction'] >> self.cmvs['reconstruction'] ] # run pmvs connections += [ self.tree[:] >> self.pmvs['tree'], @@ -108,15 +122,16 @@ class ODMApp(ecto.BlackBox): self.args[:] >> self.texturing['args'], self.meshing['reconstruction'] >> self.texturing['reconstruction'] ] - # create odm georeference - connections += [ self.tree[:] >> self.georeferencing['tree'], - self.args[:] >> self.georeferencing['args'], - self.dataset['photos'] >> self.georeferencing['photos'], - self.texturing['reconstruction'] >> self.georeferencing['reconstruction'] ] + if not run_slam: + # create odm georeference + connections += [ self.tree[:] >> self.georeferencing['tree'], + self.args[:] >> self.georeferencing['args'], + self.dataset['photos'] >> self.georeferencing['photos'], + self.texturing['reconstruction'] >> self.georeferencing['reconstruction'] ] - ## create odm orthophoto - connections += [ self.tree[:] >> self.orthophoto['tree'], - self.args[:] >> self.orthophoto['args'], - self.georeferencing['reconstruction'] >> self.orthophoto['reconstruction'] ] + ## create odm orthophoto + connections += [ self.tree[:] >> self.orthophoto['tree'], + self.args[:] >> self.orthophoto['args'], + self.georeferencing['reconstruction'] >> self.orthophoto['reconstruction'] ] return connections diff --git a/scripts/odm_slam.py b/scripts/odm_slam.py new file mode 100644 index 00000000..5116ad5d --- /dev/null +++ b/scripts/odm_slam.py @@ -0,0 +1,44 @@ +import os + +import ecto + +from opendm import log +from opendm import system +from opendm import context + + +class ODMSlamCell(ecto.Cell): + def declare_params(self, params): + pass + + def declare_io(self, params, inputs, outputs): + inputs.declare("tree", "Struct with paths", []) + inputs.declare("args", "The application arguments.", {}) + outputs.declare("reconstruction", "list of ODMReconstructions", []) + + def process(self, inputs, outputs): + + log.ODM_INFO('Running OMD Slam Cell') + + # get inputs + tree = self.inputs.tree + args = self.inputs.args + video = os.path.join(tree.root_path, args['video']) + + if not video: + log.ODM_ERROR('No video provided') + return ecto.QUIT + + # create working directories + system.mkdir_p(tree.opensfm) + system.mkdir_p(tree.pmvs) + + # run meshing binary + system.run( + '{}/odm_slam ' + 'SuperBuild/src/orb_slam2/Vocabulary/ORBvoc.txt ' + 'SuperBuild/src/orb_slam2/Examples/Monocular/TUM1.yaml ' + '{}'.format(context.odm_modules_path, video)) + + log.ODM_INFO('Running OMD Slam Cell - Finished') + return ecto.OK if args['end_with'] != 'opensfm' else ecto.QUIT