kopia lustrzana https://github.com/OpenDroneMap/ODM
Shared texturing labeling between multispectral bands
rodzic
8ac4780760
commit
375be07124
|
@ -0,0 +1,41 @@
|
||||||
|
import os
|
||||||
|
from opendm import log
|
||||||
|
|
||||||
|
def replace_nvm_images(src_nvm_file, img_map, dst_nvm_file):
|
||||||
|
"""
|
||||||
|
Create a new NVM file from an existing NVM file
|
||||||
|
replacing the image references based on img_map
|
||||||
|
where img_map is a dict { "old_image" --> "new_image" } (filename only).
|
||||||
|
The function does not write the points information (they are discarded)
|
||||||
|
"""
|
||||||
|
|
||||||
|
with open(src_nvm_file) as f:
|
||||||
|
lines = list(map(str.strip, f.read().split("\n")))
|
||||||
|
|
||||||
|
# Quick check
|
||||||
|
if len(lines) < 3 or lines[0] != "NVM_V3" or lines[1].strip() != "":
|
||||||
|
raise Exception("%s does not seem to be a valid NVM file" % src_nvm_file)
|
||||||
|
|
||||||
|
num_images = int(lines[2])
|
||||||
|
entries = []
|
||||||
|
|
||||||
|
for l in lines[3:3+num_images]:
|
||||||
|
image_path, *p = l.split(" ")
|
||||||
|
|
||||||
|
dir_name = os.path.dirname(image_path)
|
||||||
|
file_name = os.path.basename(image_path)
|
||||||
|
|
||||||
|
new_filename = img_map.get(file_name)
|
||||||
|
if new_filename is not None:
|
||||||
|
entries.append("%s %s" % (os.path.join(dir_name, new_filename), " ".join(p)))
|
||||||
|
else:
|
||||||
|
log.ODM_WARNING("Cannot find %s in image map for %s" % (file_name, dst_nvm_file))
|
||||||
|
|
||||||
|
if num_images != len(entries):
|
||||||
|
raise Exception("Cannot write %s, not all band images have been matched" % dst_nvm_file)
|
||||||
|
|
||||||
|
with open(dst_nvm_file, "w") as f:
|
||||||
|
f.write("NVM_V3\n\n%s\n" % len(entries))
|
||||||
|
f.write("\n".join(entries))
|
||||||
|
f.write("\n\n0\n0\n\n0")
|
||||||
|
|
|
@ -25,7 +25,8 @@ class ODMMvsTexStage(types.ODM_Stage):
|
||||||
'out_dir': os.path.join(tree.odm_texturing, subdir),
|
'out_dir': os.path.join(tree.odm_texturing, subdir),
|
||||||
'model': tree.odm_mesh,
|
'model': tree.odm_mesh,
|
||||||
'nadir': False,
|
'nadir': False,
|
||||||
'nvm_file': nvm_file
|
'nvm_file': nvm_file,
|
||||||
|
'labeling_file': os.path.join(tree.odm_texturing, "odm_textured_model_labeling.vec") if subdir else None
|
||||||
}]
|
}]
|
||||||
|
|
||||||
if not args.use_3dmesh:
|
if not args.use_3dmesh:
|
||||||
|
@ -33,7 +34,8 @@ class ODMMvsTexStage(types.ODM_Stage):
|
||||||
'out_dir': os.path.join(tree.odm_25dtexturing, subdir),
|
'out_dir': os.path.join(tree.odm_25dtexturing, subdir),
|
||||||
'model': tree.odm_25dmesh,
|
'model': tree.odm_25dmesh,
|
||||||
'nadir': True,
|
'nadir': True,
|
||||||
'nvm_file': nvm_file
|
'nvm_file': nvm_file,
|
||||||
|
'labeling_file': os.path.join(tree.odm_25dtexturing, "odm_textured_model_labeling.vec") if subdir else None
|
||||||
}]
|
}]
|
||||||
|
|
||||||
if reconstruction.multi_camera:
|
if reconstruction.multi_camera:
|
||||||
|
@ -81,7 +83,9 @@ class ODMMvsTexStage(types.ODM_Stage):
|
||||||
'skipLocalSeamLeveling': skipLocalSeamLeveling,
|
'skipLocalSeamLeveling': skipLocalSeamLeveling,
|
||||||
'toneMapping': self.params.get('tone_mapping'),
|
'toneMapping': self.params.get('tone_mapping'),
|
||||||
'nadirMode': nadir,
|
'nadirMode': nadir,
|
||||||
'nvm_file': r['nvm_file']
|
'nvm_file': r['nvm_file'],
|
||||||
|
'intermediate': '--no_intermediate_results' if (r['labeling_file'] or not reconstruction.multi_camera) else '',
|
||||||
|
'labelingFile': '-L "%s"' % r['labeling_file'] if r['labeling_file'] else ''
|
||||||
}
|
}
|
||||||
|
|
||||||
mvs_tmp_dir = os.path.join(r['out_dir'], 'tmp')
|
mvs_tmp_dir = os.path.join(r['out_dir'], 'tmp')
|
||||||
|
@ -95,10 +99,11 @@ class ODMMvsTexStage(types.ODM_Stage):
|
||||||
system.run('{bin} {nvm_file} {model} {out_dir} '
|
system.run('{bin} {nvm_file} {model} {out_dir} '
|
||||||
'-d {dataTerm} -o {outlierRemovalType} '
|
'-d {dataTerm} -o {outlierRemovalType} '
|
||||||
'-t {toneMapping} '
|
'-t {toneMapping} '
|
||||||
'--no_intermediate_results '
|
'{intermediate} '
|
||||||
'{skipGlobalSeamLeveling} '
|
'{skipGlobalSeamLeveling} '
|
||||||
'{skipLocalSeamLeveling} '
|
'{skipLocalSeamLeveling} '
|
||||||
'{nadirMode}'.format(**kwargs))
|
'{nadirMode} '
|
||||||
|
'{labelingFile} '.format(**kwargs))
|
||||||
|
|
||||||
progress += progress_per_run
|
progress += progress_per_run
|
||||||
self.update_progress(progress)
|
self.update_progress(progress)
|
||||||
|
|
|
@ -29,12 +29,6 @@ class ODMOpenMVSStage(types.ODM_Stage):
|
||||||
# export reconstruction from opensfm
|
# export reconstruction from opensfm
|
||||||
octx = OSFMContext(tree.opensfm)
|
octx = OSFMContext(tree.opensfm)
|
||||||
cmd = 'export_openmvs'
|
cmd = 'export_openmvs'
|
||||||
if reconstruction.multi_camera:
|
|
||||||
# Export only the primary band
|
|
||||||
primary_band = get_primary_band_name(reconstruction.multi_camera, args.primary_band)
|
|
||||||
|
|
||||||
image_list = os.path.join(tree.opensfm, "image_list_%s.txt" % primary_band.lower())
|
|
||||||
cmd += ' --image_list "%s"' % image_list
|
|
||||||
octx.run(cmd)
|
octx.run(cmd)
|
||||||
|
|
||||||
self.update_progress(10)
|
self.update_progress(10)
|
||||||
|
|
|
@ -13,6 +13,7 @@ from opendm import types
|
||||||
from opendm.utils import get_depthmap_resolution
|
from opendm.utils import get_depthmap_resolution
|
||||||
from opendm.osfm import OSFMContext
|
from opendm.osfm import OSFMContext
|
||||||
from opendm import multispectral
|
from opendm import multispectral
|
||||||
|
from opendm import nvm
|
||||||
|
|
||||||
class ODMOpenSfMStage(types.ODM_Stage):
|
class ODMOpenSfMStage(types.ODM_Stage):
|
||||||
def process(self, args, outputs):
|
def process(self, args, outputs):
|
||||||
|
@ -127,27 +128,10 @@ class ODMOpenSfMStage(types.ODM_Stage):
|
||||||
self.update_progress(80)
|
self.update_progress(80)
|
||||||
|
|
||||||
if reconstruction.multi_camera:
|
if reconstruction.multi_camera:
|
||||||
# Dump band image lists
|
|
||||||
log.ODM_INFO("Multiple bands found")
|
|
||||||
for band in reconstruction.multi_camera:
|
|
||||||
log.ODM_INFO("Exporting %s band" % band['name'])
|
|
||||||
image_list_file = octx.path("image_list_%s.txt" % band['name'].lower())
|
|
||||||
|
|
||||||
if not io.file_exists(image_list_file) or self.rerun():
|
|
||||||
with open(image_list_file, "w") as f:
|
|
||||||
f.write("\n".join([p.filename for p in band['photos']]))
|
|
||||||
log.ODM_INFO("Wrote %s" % image_list_file)
|
|
||||||
else:
|
|
||||||
log.ODM_WARNING("Found a valid image list in %s for %s band" % (image_list_file, band['name']))
|
|
||||||
|
|
||||||
nvm_file = octx.path("undistorted", "reconstruction_%s.nvm" % band['name'].lower())
|
|
||||||
if not io.file_exists(nvm_file) or self.rerun():
|
|
||||||
octx.run('export_visualsfm --points --image_list "%s"' % image_list_file)
|
|
||||||
os.rename(tree.opensfm_reconstruction_nvm, nvm_file)
|
|
||||||
else:
|
|
||||||
log.ODM_WARNING("Found a valid NVM file in %s for %s band" % (nvm_file, band['name']))
|
|
||||||
|
|
||||||
octx.restore_reconstruction_backup()
|
octx.restore_reconstruction_backup()
|
||||||
|
|
||||||
|
# Undistort primary band and write undistorted
|
||||||
|
# reconstruction.json, tracks.csv
|
||||||
octx.convert_and_undistort(self.rerun(), undistort_callback, runId='primary')
|
octx.convert_and_undistort(self.rerun(), undistort_callback, runId='primary')
|
||||||
|
|
||||||
if not io.file_exists(tree.opensfm_reconstruction_nvm) or self.rerun():
|
if not io.file_exists(tree.opensfm_reconstruction_nvm) or self.rerun():
|
||||||
|
@ -155,6 +139,29 @@ class ODMOpenSfMStage(types.ODM_Stage):
|
||||||
else:
|
else:
|
||||||
log.ODM_WARNING('Found a valid OpenSfM NVM reconstruction file in: %s' %
|
log.ODM_WARNING('Found a valid OpenSfM NVM reconstruction file in: %s' %
|
||||||
tree.opensfm_reconstruction_nvm)
|
tree.opensfm_reconstruction_nvm)
|
||||||
|
|
||||||
|
if reconstruction.multi_camera:
|
||||||
|
log.ODM_INFO("Multiple bands found")
|
||||||
|
|
||||||
|
# Write NVM files for the various bands
|
||||||
|
for band in reconstruction.multi_camera:
|
||||||
|
nvm_file = octx.path("undistorted", "reconstruction_%s.nvm" % band['name'].lower())
|
||||||
|
|
||||||
|
img_map = {}
|
||||||
|
for fname in p2s:
|
||||||
|
|
||||||
|
# Primary band maps to itself
|
||||||
|
if band['name'] == primary_band_name:
|
||||||
|
img_map[fname + '.tif'] = fname + '.tif'
|
||||||
|
else:
|
||||||
|
band_filename = next((p.filename for p in p2s[fname] if p.band_name == band['name']), None)
|
||||||
|
|
||||||
|
if band_filename is not None:
|
||||||
|
img_map[fname + '.tif'] = band_filename + '.tif'
|
||||||
|
else:
|
||||||
|
log.ODM_WARNING("Cannot find %s band equivalent for %s" % (band, fname))
|
||||||
|
|
||||||
|
nvm.replace_nvm_images(tree.opensfm_reconstruction_nvm, img_map, nvm_file)
|
||||||
|
|
||||||
self.update_progress(85)
|
self.update_progress(85)
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue