Better config help, cleanup

pull/1222/head
Piero Toffanin 2020-12-19 12:29:00 -05:00
rodzic 8e49d99939
commit 43d67019da
3 zmienionych plików z 121 dodań i 162 usunięć

Wyświetl plik

@ -76,15 +76,14 @@ def config(argv=None, parser=None):
parser.add_argument('--project-path',
metavar='<path>',
action=StoreValue,
help='Path to the project folder')
help='Path to the project folder. Your project folder should contain subfolders for each dataset. Each dataset should have an "images" folder.')
parser.add_argument('name',
metavar='<project name>',
action=StoreValue,
type=alphanumeric_string,
default='code',
nargs='?',
help='Name of Project (i.e subdirectory of projects folder)')
help='Name of dataset (i.e subfolder name within project folder). Default: %(default)s')
parser.add_argument('--resize-to',
metavar='<integer>',
@ -93,14 +92,14 @@ def config(argv=None, parser=None):
type=int,
help='Legacy option (use --feature-quality instead). Resizes images by the largest side for feature extraction purposes only. '
'Set to -1 to disable. This does not affect the final orthophoto '
'resolution quality and will not resize the original images. Default: %(default)s')
'resolution quality and will not resize the original images. Default: %(default)s')
parser.add_argument('--end-with', '-e',
metavar='<string>',
action=StoreValue,
default='odm_report',
choices=processopts,
help=('Can be one of:' + ' | '.join(processopts)))
help='End processing at this stage. Can be one of: %(choices)s. Default: %(default)s')
rerun = parser.add_mutually_exclusive_group()
@ -108,27 +107,19 @@ def config(argv=None, parser=None):
metavar='<string>',
action=StoreValue,
choices=processopts,
help=('Can be one of:' + ' | '.join(processopts)))
help=('Rerun this stage only and stop. Can be one of: %(choices)s. Default: %(default)s'))
rerun.add_argument('--rerun-all',
action=StoreTrue,
nargs=0,
default=False,
help='force rerun of all tasks')
help='Permanently delete all previous results and rerun the processing pipeline.')
rerun.add_argument('--rerun-from',
action=RerunFrom,
metavar='<string>',
choices=processopts,
help=('Can be one of:' + ' | '.join(processopts)))
# parser.add_argument('--video',
# metavar='<string>',
# help='Path to the video file to process')
# parser.add_argument('--slam-config',
# metavar='<string>',
# help='Path to config file for orb-slam')
help=('Rerun processing from this stage. Can be one of: %(choices)s. Default: %(default)s'))
parser.add_argument('--min-num-features',
metavar='<integer>',
@ -136,8 +127,9 @@ def config(argv=None, parser=None):
default=8000,
type=int,
help=('Minimum number of features to extract per image. '
'More features leads to better results but slower '
'execution. Default: %(default)s'))
'More features can be useful for finding more matches between images, '
'potentially allowing the reconstruction of areas with little overlap or insufficient features. '
'More features also slow down processing. Default: %(default)s'))
parser.add_argument('--feature-type',
metavar='<string>',
@ -174,10 +166,7 @@ def config(argv=None, parser=None):
help='Number of nearest images to pre-match based on GPS '
'exif data. Set to 0 to skip pre-matching. '
'Neighbors works together with Distance parameter, '
'set both to 0 to not use pre-matching. OpenSFM '
'uses both parameters at the same time, Bundler '
'uses only one which has value, prefering the '
'Neighbors parameter. Default: %(default)s')
'set both to 0 to not use pre-matching. Default: %(default)s')
parser.add_argument('--matcher-distance',
metavar='<integer>',
@ -193,7 +182,7 @@ def config(argv=None, parser=None):
action=StoreTrue,
nargs=0,
default=False,
help='Turn off camera parameter optimization during bundler')
help='Turn off camera parameter optimization during bundle adjustment. This can be sometimes useful for improving results that exhibit doming/bowling or when images are taken with a rolling shutter camera. Default: %(default)s')
parser.add_argument('--cameras',
default='',
@ -213,8 +202,7 @@ def config(argv=None, parser=None):
choices=['auto', 'perspective', 'brown', 'fisheye', 'spherical'],
help=('Set a camera projection type. Manually setting a value '
'can help improve geometric undistortion. By default the application '
'tries to determine a lens type from the images metadata. Can be '
'set to one of: %(choices)s. Default: '
'tries to determine a lens type from the images metadata. Can be one of: %(choices)s. Default: '
'%(default)s'))
parser.add_argument('--radiometric-calibration',
@ -227,7 +215,7 @@ def config(argv=None, parser=None):
'to obtain reflectance values (otherwise you will get digital number values). '
'[camera] applies black level, vignetting, row gradient gain/exposure compensation (if appropriate EXIF tags are found). '
'[camera+sun] is experimental, applies all the corrections of [camera], plus compensates for spectral radiance registered via a downwelling light sensor (DLS) taking in consideration the angle of the sun. '
'Can be set to one of: %(choices)s. Default: '
'Can be one of: %(choices)s. Default: '
'%(default)s'))
parser.add_argument('--max-concurrency',
@ -282,25 +270,25 @@ def config(argv=None, parser=None):
nargs=0,
default=False,
help='Run local bundle adjustment for every image added to the reconstruction and a global '
'adjustment every 100 images. Speeds up reconstruction for very large datasets.')
'adjustment every 100 images. Speeds up reconstruction for very large datasets. Default: %(default)s')
parser.add_argument('--use-3dmesh',
action=StoreTrue,
nargs=0,
default=False,
help='Use a full 3D mesh to compute the orthophoto instead of a 2.5D mesh. This option is a bit faster and provides similar results in planar areas.')
help='Use a full 3D mesh to compute the orthophoto instead of a 2.5D mesh. This option is a bit faster and provides similar results in planar areas. Default: %(default)s')
parser.add_argument('--skip-3dmodel',
action=StoreTrue,
nargs=0,
default=False,
help='Skip generation of a full 3D model. This can save time if you only need 2D results such as orthophotos and DEMs.')
help='Skip generation of a full 3D model. This can save time if you only need 2D results such as orthophotos and DEMs. Default: %(default)s')
parser.add_argument('--use-opensfm-dense',
action=StoreTrue,
nargs=0,
default=False,
help='Use opensfm to compute dense point cloud alternatively')
help='Use OpenSfM to compute the dense point cloud instead of OpenMVS. Default: %(default)s')
parser.add_argument('--ignore-gsd',
action=StoreTrue,
@ -309,7 +297,7 @@ def config(argv=None, parser=None):
help='Ignore Ground Sampling Distance (GSD). GSD '
'caps the maximum resolution of image outputs and '
'resizes images when necessary, resulting in faster processing and '
'lower memory usage. Since GSD is an estimate, sometimes ignoring it can result in slightly better image output quality.')
'lower memory usage. Since GSD is an estimate, sometimes ignoring it can result in slightly better image output quality. Default: %(default)s')
parser.add_argument('--mesh-size',
metavar='<positive integer>',
@ -322,39 +310,19 @@ def config(argv=None, parser=None):
parser.add_argument('--mesh-octree-depth',
metavar='<positive integer>',
action=StoreValue,
default=10,
default=11,
type=int,
help=('Oct-tree depth used in the mesh reconstruction, '
help=('Octree depth used in the mesh reconstruction, '
'increase to get more vertices, recommended '
'values are 8-12. Default: %(default)s'))
parser.add_argument('--mesh-samples',
metavar='<float >= 1.0>',
action=StoreValue,
default=1.0,
type=float,
help=('Number of points per octree node, recommended '
'and default value: %(default)s'))
parser.add_argument('--mesh-point-weight',
metavar='<positive float>',
action=StoreValue,
default=4,
type=float,
help=('This floating point value specifies the importance'
' that interpolation of the point samples is given in the '
'formulation of the screened Poisson equation. The results '
'of the original (unscreened) Poisson Reconstruction can '
'be obtained by setting this value to 0.'
'Default= %(default)s'))
parser.add_argument('--fast-orthophoto',
action=StoreTrue,
nargs=0,
default=False,
help='Skips dense reconstruction and 3D model generation. '
'It generates an orthophoto directly from the sparse reconstruction. '
'If you just need an orthophoto and do not need a full 3D model, turn on this option.')
'If you just need an orthophoto and do not need a full 3D model, turn on this option. Default: %(default)s')
parser.add_argument('--crop',
metavar='<positive float>',
@ -388,37 +356,35 @@ def config(argv=None, parser=None):
action=StoreTrue,
nargs=0,
default=False,
help='Export the georeferenced point cloud in CSV format. Default: %(default)s')
help='Export the georeferenced point cloud in CSV format. Default: %(default)s')
parser.add_argument('--pc-las',
action=StoreTrue,
nargs=0,
default=False,
help='Export the georeferenced point cloud in LAS format. Default: %(default)s')
help='Export the georeferenced point cloud in LAS format. Default: %(default)s')
parser.add_argument('--pc-ept',
action=StoreTrue,
nargs=0,
default=False,
help='Export the georeferenced point cloud in Entwine Point Tile (EPT) format. Default: %(default)s')
help='Export the georeferenced point cloud in Entwine Point Tile (EPT) format. Default: %(default)s')
parser.add_argument('--pc-filter',
metavar='<positive float>',
action=StoreValue,
type=float,
default=2.5,
help='Filters the point cloud by removing points that deviate more than N standard deviations from the local mean. Set to 0 to disable filtering.'
'\nDefault: '
'%(default)s')
help='Filters the point cloud by removing points that deviate more than N standard deviations from the local mean. Set to 0 to disable filtering. '
'Default: %(default)s')
parser.add_argument('--pc-sample',
metavar='<positive float>',
action=StoreValue,
type=float,
default=0,
help='Filters the point cloud by keeping only a single point around a radius N (in meters). This can be useful to limit the output resolution of the point cloud. Set to 0 to disable sampling.'
'\nDefault: '
'%(default)s')
help='Filters the point cloud by keeping only a single point around a radius N (in meters). This can be useful to limit the output resolution of the point cloud. Set to 0 to disable sampling. '
'Default: %(default)s')
parser.add_argument('--smrf-scalar',
metavar='<positive float>',
@ -426,8 +392,7 @@ def config(argv=None, parser=None):
type=float,
default=1.25,
help='Simple Morphological Filter elevation scalar parameter. '
'\nDefault: '
'%(default)s')
'Default: %(default)s')
parser.add_argument('--smrf-slope',
metavar='<positive float>',
@ -435,8 +400,7 @@ def config(argv=None, parser=None):
type=float,
default=0.15,
help='Simple Morphological Filter slope parameter (rise over run). '
'\nDefault: '
'%(default)s')
'Default: %(default)s')
parser.add_argument('--smrf-threshold',
metavar='<positive float>',
@ -444,8 +408,7 @@ def config(argv=None, parser=None):
type=float,
default=0.5,
help='Simple Morphological Filter elevation threshold parameter (meters). '
'\nDefault: '
'%(default)s')
'Default: %(default)s')
parser.add_argument('--smrf-window',
metavar='<positive float>',
@ -453,38 +416,33 @@ def config(argv=None, parser=None):
type=float,
default=18.0,
help='Simple Morphological Filter window radius parameter (meters). '
'\nDefault: '
'%(default)s')
'Default: %(default)s')
parser.add_argument('--texturing-data-term',
metavar='<string>',
action=StoreValue,
default='gmi',
choices=['gmi', 'area'],
help=('Data term: [area, gmi]. Default: '
'%(default)s'))
help=('When texturing the 3D mesh, for each triangle, choose to prioritize images with sharp features (gmi) or those that cover the largest area (area). Default: %(default)s'))
parser.add_argument('--texturing-outlier-removal-type',
metavar='<string>',
action=StoreValue,
default='gauss_clamping',
choices=['none', 'gauss_clamping', 'gauss_damping'],
help=('Type of photometric outlier removal method: '
'[none, gauss_damping, gauss_clamping]. Default: '
'%(default)s'))
help=('Type of photometric outlier removal method. Can be one of: %(choices)s. Default: %(default)s'))
parser.add_argument('--texturing-skip-global-seam-leveling',
action=StoreTrue,
nargs=0,
default=False,
help=('Skip global seam leveling. Useful for IR data.'
'Default: %(default)s'))
help=('Skip normalization of colors across all images. Useful when processing radiometric data. Default: %(default)s'))
parser.add_argument('--texturing-skip-local-seam-leveling',
action=StoreTrue,
nargs=0,
default=False,
help='Skip local seam blending. Default: %(default)s')
help='Skip the blending of colors near seams. Default: %(default)s')
parser.add_argument('--texturing-tone-mapping',
metavar='<string>',
@ -492,7 +450,7 @@ def config(argv=None, parser=None):
choices=['none', 'gamma'],
default='none',
help='Turn on gamma tone mapping or none for no tone '
'mapping. Choices are \'gamma\' or \'none\'. '
'mapping. Can be one of %(choices)s. '
'Default: %(default)s ')
parser.add_argument('--gcp',
@ -500,11 +458,12 @@ def config(argv=None, parser=None):
action=StoreValue,
default=None,
help=('Path to the file containing the ground control '
'points used for georeferencing. Default: '
'%(default)s. The file needs to '
'points used for georeferencing. '
'The file needs to '
'use the following format: \n'
'EPSG:<code> or <+proj definition>\n'
'geo_x geo_y geo_z im_x im_y image_name [gcp_name] [extra1] [extra2]'))
'geo_x geo_y geo_z im_x im_y image_name [gcp_name] [extra1] [extra2]\n'
'Default: %(default)s'))
parser.add_argument('--geo',
metavar='<path string>',
@ -512,33 +471,32 @@ def config(argv=None, parser=None):
default=None,
help=('Path to the image geolocation file containing the camera center coordinates used for georeferencing. '
'Note that omega/phi/kappa are currently not supported (you can set them to 0). '
'Default: '
'%(default)s. The file needs to '
'The file needs to '
'use the following format: \n'
'EPSG:<code> or <+proj definition>\n'
'image_name geo_x geo_y geo_z [omega (degrees)] [phi (degrees)] [kappa (degrees)] [horz accuracy (meters)] [vert accuracy (meters)]'
''))
'image_name geo_x geo_y geo_z [omega (degrees)] [phi (degrees)] [kappa (degrees)] [horz accuracy (meters)] [vert accuracy (meters)]\n'
'Default: %(default)s'))
parser.add_argument('--use-exif',
action=StoreTrue,
nargs=0,
default=False,
help=('Use this tag if you have a gcp_list.txt but '
'want to use the exif geotags instead'))
help=('Use this tag if you have a GCP File but '
'want to use the EXIF information for georeferencing instead. Default: %(default)s'))
parser.add_argument('--dtm',
action=StoreTrue,
nargs=0,
default=False,
help='Use this tag to build a DTM (Digital Terrain Model, ground only) using a simple '
'morphological filter. Check the --dem* and --smrf* parameters for finer tuning.')
'morphological filter. Check the --dem* and --smrf* parameters for finer tuning. Default: %(default)s')
parser.add_argument('--dsm',
action=StoreTrue,
nargs=0,
default=False,
help='Use this tag to build a DSM (Digital Surface Model, ground + objects) using a progressive '
'morphological filter. Check the --dem* parameters for finer tuning.')
'morphological filter. Check the --dem* parameters for finer tuning. Default: %(default)s')
parser.add_argument('--dem-gapfill-steps',
metavar='<positive integer>',
@ -549,7 +507,7 @@ def config(argv=None, parser=None):
'Starting with a radius equal to the output resolution, N different DEMs are generated with '
'progressively bigger radius using the inverse distance weighted (IDW) algorithm '
'and merged together. Remaining gaps are then merged using nearest neighbor interpolation. '
'\nDefault=%(default)s')
'Default: %(default)s')
parser.add_argument('--dem-resolution',
metavar='<float>',
@ -557,7 +515,7 @@ def config(argv=None, parser=None):
type=float,
default=5,
help='DSM/DTM resolution in cm / pixel. Note that this value is capped by a ground sampling distance (GSD) estimate. To remove the cap, check --ignore-gsd also.'
'\nDefault: %(default)s')
' Default: %(default)s')
parser.add_argument('--dem-decimation',
metavar='<positive integer>',
@ -565,8 +523,7 @@ def config(argv=None, parser=None):
default=1,
type=int,
help='Decimate the points before generating the DEM. 1 is no decimation (full quality). '
'100 decimates ~99%% of the points. Useful for speeding up '
'generation.\nDefault=%(default)s')
'100 decimates ~99%% of the points. Useful for speeding up generation of DEM results in very large datasets. Default: %(default)s')
parser.add_argument('--dem-euclidean-map',
action=StoreTrue,
@ -584,21 +541,21 @@ def config(argv=None, parser=None):
action=StoreValue,
default=5,
type=float,
help=('Orthophoto resolution in cm / pixel. Note that this value is capped by a ground sampling distance (GSD) estimate. To remove the cap, check --ignore-gsd also.\n'
help=('Orthophoto resolution in cm / pixel. Note that this value is capped by a ground sampling distance (GSD) estimate. To remove the cap, check --ignore-gsd also. '
'Default: %(default)s'))
parser.add_argument('--orthophoto-no-tiled',
action=StoreTrue,
nargs=0,
default=False,
help='Set this parameter if you want a stripped geoTIFF.\n'
help='Set this parameter if you want a striped GeoTIFF. '
'Default: %(default)s')
parser.add_argument('--orthophoto-png',
action=StoreTrue,
nargs=0,
default=False,
help='Set this parameter if you want to generate a PNG rendering of the orthophoto.\n'
help='Set this parameter if you want to generate a PNG rendering of the orthophoto. '
'Default: %(default)s')
parser.add_argument('--orthophoto-compression',
@ -607,7 +564,7 @@ def config(argv=None, parser=None):
type=str,
choices=['JPEG', 'LZW', 'PACKBITS', 'DEFLATE', 'LZMA', 'NONE'],
default='DEFLATE',
help='Set the compression to use for orthophotos. Options: %(choices)s.\nDefault: %(default)s')
help='Set the compression to use for orthophotos. Can be one of: %(choices)s. Default: %(default)s')
parser.add_argument('--orthophoto-cutline',
action=StoreTrue,
@ -631,28 +588,27 @@ def config(argv=None, parser=None):
action=StoreTrue,
nargs=0,
default=False,
help='Build orthophoto overviews using gdaladdo.')
help='Build orthophoto overviews for faster display in programs such as QGIS. Default: %(default)s')
parser.add_argument('--verbose', '-v',
action=StoreTrue,
nargs=0,
default=False,
help='Print additional messages to the console\n'
help='Print additional messages to the console. '
'Default: %(default)s')
parser.add_argument('--time',
action=StoreTrue,
nargs=0,
default=False,
help='Generates a benchmark file with runtime info\n'
help='Generates a benchmark file with runtime info. '
'Default: %(default)s')
parser.add_argument('--debug',
action=StoreTrue,
nargs=0,
default=False,
help='Print debug messages\n'
'Default: %(default)s')
help='Print debug messages. Default: %(default)s')
parser.add_argument('--version',
action='version',
@ -668,7 +624,7 @@ def config(argv=None, parser=None):
'splitting a large dataset into smaller '
'submodels, images are grouped into clusters. '
'This value regulates the number of images that '
'each cluster should have on average.')
'each cluster should have on average. Default: %(default)s')
parser.add_argument('--split-overlap',
type=float,
@ -679,13 +635,13 @@ def config(argv=None, parser=None):
'After grouping images into clusters, images '
'that are closer than this radius to a cluster '
'are added to the cluster. This is done to ensure '
'that neighboring submodels overlap.')
'that neighboring submodels overlap. Default: %(default)s')
parser.add_argument('--split-multitracks',
action=StoreTrue,
nargs=0,
default=False,
help='Split multi-track reconstructions.')
# parser.add_argument('--split-multitracks',
# action=StoreTrue,
# nargs=0,
# default=False,
# help='Split multi-track reconstructions.')
parser.add_argument('--sm-cluster',
metavar='<string>',

Wyświetl plik

@ -39,8 +39,8 @@ class ODMApp:
meshing = ODMeshingStage('odm_meshing', args, progress=60.0,
max_vertex=args.mesh_size,
oct_tree=args.mesh_octree_depth,
samples=args.mesh_samples,
point_weight=args.mesh_point_weight,
samples=1.0,
point_weight=4.0,
max_concurrency=args.max_concurrency,
verbose=args.verbose)
texturing = ODMMvsTexStage('mvs_texturing', args, progress=70.0,

Wyświetl plik

@ -104,67 +104,70 @@ class ODMSplitStage(types.ODM_Stage):
self.update_progress(50)
resplit_done_file = octx.path('resplit_done.txt')
if not io.file_exists(resplit_done_file) and bool(args.split_multitracks):
submodels = mds.get_submodel_paths()
i = 0
for s in submodels:
template = octx.path("../aligned_submodels/submodel_%04d")
with open(s+"/reconstruction.json", "r") as f:
j = json.load(f)
for k in range(0, len(j)):
v = j[k]
path = template % i
# TODO: this is currently not working and needs a champion to fix it
# https://community.opendronemap.org/t/filenotfound-error-cameras-json/6047/2
# resplit_done_file = octx.path('resplit_done.txt')
# if not io.file_exists(resplit_done_file) and bool(args.split_multitracks):
# submodels = mds.get_submodel_paths()
# i = 0
# for s in submodels:
# template = octx.path("../aligned_submodels/submodel_%04d")
# with open(s+"/reconstruction.json", "r") as f:
# j = json.load(f)
# for k in range(0, len(j)):
# v = j[k]
# path = template % i
#Create the submodel path up to opensfm
os.makedirs(path+"/opensfm")
os.makedirs(path+"/images")
# #Create the submodel path up to opensfm
# os.makedirs(path+"/opensfm")
# os.makedirs(path+"/images")
#symlinks for common data
images = os.listdir(octx.path("../images"))
for image in images:
os.symlink("../../../images/"+image, path+"/images/"+image)
os.symlink("../../../opensfm/exif", path+"/opensfm/exif")
os.symlink("../../../opensfm/features", path+"/opensfm/features")
os.symlink("../../../opensfm/matches", path+"/opensfm/matches")
os.symlink("../../../opensfm/reference_lla.json", path+"/opensfm/reference_lla.json")
os.symlink("../../../opensfm/camera_models.json", path+"/opensfm/camera_models.json")
# #symlinks for common data
# images = os.listdir(octx.path("../images"))
# for image in images:
# os.symlink("../../../images/"+image, path+"/images/"+image)
# os.symlink("../../../opensfm/exif", path+"/opensfm/exif")
# os.symlink("../../../opensfm/features", path+"/opensfm/features")
# os.symlink("../../../opensfm/matches", path+"/opensfm/matches")
# os.symlink("../../../opensfm/reference_lla.json", path+"/opensfm/reference_lla.json")
# os.symlink("../../../opensfm/camera_models.json", path+"/opensfm/camera_models.json")
shutil.copy(s+"/../cameras.json", path+"/cameras.json")
# shutil.copy(s+"/../cameras.json", path+"/cameras.json")
shutil.copy(s+"/../images.json", path+"/images.json")
# shutil.copy(s+"/../images.json", path+"/images.json")
with open(octx.path("config.yaml")) as f:
doc = yaml.safe_load(f)
# with open(octx.path("config.yaml")) as f:
# doc = yaml.safe_load(f)
dmcv = "depthmap_min_consistent_views"
if dmcv in doc:
if len(v["shots"]) < doc[dmcv]:
doc[dmcv] = len(v["shots"])
print("WARNING: Reduced "+dmcv+" to accommodate short track")
# dmcv = "depthmap_min_consistent_views"
# if dmcv in doc:
# if len(v["shots"]) < doc[dmcv]:
# doc[dmcv] = len(v["shots"])
# print("WARNING: Reduced "+dmcv+" to accommodate short track")
with open(path+"/opensfm/config.yaml", "w") as f:
yaml.dump(doc, f)
# with open(path+"/opensfm/config.yaml", "w") as f:
# yaml.dump(doc, f)
#We need the original tracks file for the visualsfm export, since
#there may still be point matches between the tracks
shutil.copy(s+"/tracks.csv", path+"/opensfm/tracks.csv")
# #We need the original tracks file for the visualsfm export, since
# #there may still be point matches between the tracks
# shutil.copy(s+"/tracks.csv", path+"/opensfm/tracks.csv")
#Create our new reconstruction file with only the relevant track
with open(path+"/opensfm/reconstruction.json", "w") as o:
json.dump([v], o)
# #Create our new reconstruction file with only the relevant track
# with open(path+"/opensfm/reconstruction.json", "w") as o:
# json.dump([v], o)
#Create image lists
with open(path+"/opensfm/image_list.txt", "w") as o:
o.writelines(list(map(lambda x: "../images/"+x+'\n', v["shots"].keys())))
with open(path+"/img_list.txt", "w") as o:
o.writelines(list(map(lambda x: x+'\n', v["shots"].keys())))
# #Create image lists
# with open(path+"/opensfm/image_list.txt", "w") as o:
# o.writelines(list(map(lambda x: "../images/"+x+'\n', v["shots"].keys())))
# with open(path+"/img_list.txt", "w") as o:
# o.writelines(list(map(lambda x: x+'\n', v["shots"].keys())))
i+=1
os.rename(octx.path("../submodels"), octx.path("../unaligned_submodels"))
os.rename(octx.path("../aligned_submodels"), octx.path("../submodels"))
octx.touch(resplit_done_file)
# i+=1
# os.rename(octx.path("../submodels"), octx.path("../unaligned_submodels"))
# os.rename(octx.path("../aligned_submodels"), octx.path("../submodels"))
# octx.touch(resplit_done_file)
mds = metadataset.MetaDataSet(tree.opensfm)
submodel_paths = [os.path.abspath(p) for p in mds.get_submodel_paths()]