kopia lustrzana https://github.com/OpenDroneMap/ODM
OpenCV 3 update, removed bundler export, GSD optimization adjustments
Former-commit-id: 0ff220e47f
pull/1161/head
rodzic
12467dc225
commit
16b410df4b
|
@ -7,8 +7,7 @@ ExternalProject_Add(${_proj_name}
|
||||||
STAMP_DIR ${_SB_BINARY_DIR}/stamp
|
STAMP_DIR ${_SB_BINARY_DIR}/stamp
|
||||||
#--Download step--------------
|
#--Download step--------------
|
||||||
DOWNLOAD_DIR ${SB_DOWNLOAD_DIR}
|
DOWNLOAD_DIR ${SB_DOWNLOAD_DIR}
|
||||||
URL https://github.com/Itseez/opencv/archive/2.4.11.zip
|
URL https://github.com/opencv/opencv/archive/3.4.6.zip
|
||||||
URL_MD5 b517e83489c709eee1d8be76b16976a7
|
|
||||||
#--Update/Patch step----------
|
#--Update/Patch step----------
|
||||||
UPDATE_COMMAND ""
|
UPDATE_COMMAND ""
|
||||||
#--Configure step-------------
|
#--Configure step-------------
|
||||||
|
|
|
@ -70,9 +70,9 @@ def config():
|
||||||
metavar='<integer>',
|
metavar='<integer>',
|
||||||
default=2048,
|
default=2048,
|
||||||
type=int,
|
type=int,
|
||||||
help='Resizes images by the largest side for feature extraction. '
|
help='Resizes images by the largest side for feature extraction purposes only. '
|
||||||
'Set to -1 to disable. This does not affect the final orthophoto '
|
'Set to -1 to disable. This does not affect the final orthophoto '
|
||||||
' resolution quality. Default: %(default)s')
|
' resolution quality and will not resize the original images. Default: %(default)s')
|
||||||
|
|
||||||
parser.add_argument('--end-with', '-e',
|
parser.add_argument('--end-with', '-e',
|
||||||
metavar='<string>',
|
metavar='<string>',
|
||||||
|
@ -153,11 +153,11 @@ def config():
|
||||||
parser.add_argument('--camera-model',
|
parser.add_argument('--camera-model',
|
||||||
metavar='<string>',
|
metavar='<string>',
|
||||||
default='auto',
|
default='auto',
|
||||||
choices=['auto', 'perspective', 'brown', 'fisheye'],
|
choices=['auto', 'perspective', 'brown', 'fisheye', 'spherical'],
|
||||||
help=('Set a camera projection type. Manually setting a value '
|
help=('Set a camera projection type. Manually setting a value '
|
||||||
'can help improve geometric undistortion. By default the application '
|
'can help improve geometric undistortion. By default the application '
|
||||||
'tries to determine a projection type from the images metadata. Can be '
|
'tries to determine a projection type from the images metadata. Can be '
|
||||||
'set to one of: [auto, perspective, brown, fisheye]. Default: '
|
'set to one of: [auto, perspective, brown, fisheye, spherical]. Default: '
|
||||||
'%(default)s'))
|
'%(default)s'))
|
||||||
|
|
||||||
parser.add_argument('--max-concurrency',
|
parser.add_argument('--max-concurrency',
|
||||||
|
|
|
@ -23,7 +23,7 @@ class OSFMContext:
|
||||||
def export_bundler(self, destination_bundle_file, rerun=False):
|
def export_bundler(self, destination_bundle_file, rerun=False):
|
||||||
if not io.file_exists(destination_bundle_file) or rerun:
|
if not io.file_exists(destination_bundle_file) or rerun:
|
||||||
# convert back to bundler's format
|
# convert back to bundler's format
|
||||||
system.run('%s/bin/export_bundler "%s"' %
|
system.run('%s/bin/export_bundler --undistorted "%s"' %
|
||||||
(context.opensfm_path, self.opensfm_project_path))
|
(context.opensfm_path, self.opensfm_project_path))
|
||||||
else:
|
else:
|
||||||
log.ODM_WARNING('Found a valid Bundler file in: %s' % destination_bundle_file)
|
log.ODM_WARNING('Found a valid Bundler file in: %s' % destination_bundle_file)
|
||||||
|
@ -122,7 +122,6 @@ class OSFMContext:
|
||||||
if not has_gps:
|
if not has_gps:
|
||||||
log.ODM_INFO("No GPS information, using BOW matching")
|
log.ODM_INFO("No GPS information, using BOW matching")
|
||||||
config.append("matcher_type: WORDS")
|
config.append("matcher_type: WORDS")
|
||||||
config.append("matching_bow_neighbors: %s" % args.matcher_neighbors)
|
|
||||||
|
|
||||||
if has_alt:
|
if has_alt:
|
||||||
log.ODM_INFO("Altitude data detected, enabling it for GPS alignment")
|
log.ODM_INFO("Altitude data detected, enabling it for GPS alignment")
|
||||||
|
@ -234,30 +233,6 @@ class OSFMContext:
|
||||||
else:
|
else:
|
||||||
log.ODM_WARNING("Tried to update configuration, but %s does not exist." % cfg_file)
|
log.ODM_WARNING("Tried to update configuration, but %s does not exist." % cfg_file)
|
||||||
|
|
||||||
def save_absolute_image_list_to(self, file):
|
|
||||||
"""
|
|
||||||
Writes a copy of the image_list.txt file and makes sure that all paths
|
|
||||||
written in it are absolute paths and not relative paths.
|
|
||||||
"""
|
|
||||||
image_list_file = self.path("image_list.txt")
|
|
||||||
|
|
||||||
if io.file_exists(image_list_file):
|
|
||||||
with open(image_list_file, 'r') as f:
|
|
||||||
content = f.read()
|
|
||||||
|
|
||||||
lines = []
|
|
||||||
for line in map(str.strip, content.split('\n')):
|
|
||||||
if line and not line.startswith("/"):
|
|
||||||
line = os.path.abspath(os.path.join(self.opensfm_project_path, line))
|
|
||||||
lines.append(line)
|
|
||||||
|
|
||||||
with open(file, 'w') as f:
|
|
||||||
f.write("\n".join(lines))
|
|
||||||
|
|
||||||
log.ODM_INFO("Wrote %s with absolute paths" % file)
|
|
||||||
else:
|
|
||||||
log.ODM_WARNING("No %s found, cannot create %s" % (image_list_file, file))
|
|
||||||
|
|
||||||
def name(self):
|
def name(self):
|
||||||
return os.path.basename(os.path.abspath(self.path("..")))
|
return os.path.basename(os.path.abspath(self.path("..")))
|
||||||
|
|
||||||
|
|
|
@ -259,9 +259,6 @@ class ODM_Tree(object):
|
||||||
|
|
||||||
# mve
|
# mve
|
||||||
self.mve_model = io.join_paths(self.mve, 'mve_dense_point_cloud.ply')
|
self.mve_model = io.join_paths(self.mve, 'mve_dense_point_cloud.ply')
|
||||||
self.mve_path = io.join_paths(self.opensfm, 'mve')
|
|
||||||
self.mve_image_list = io.join_paths(self.mve_path, 'list.txt')
|
|
||||||
self.mve_bundle = io.join_paths(self.mve_path, 'bundle/bundle.out')
|
|
||||||
self.mve_views = io.join_paths(self.mve, 'views')
|
self.mve_views = io.join_paths(self.mve, 'views')
|
||||||
|
|
||||||
# filter points
|
# filter points
|
||||||
|
|
|
@ -21,19 +21,6 @@ class ODMMveStage(types.ODM_Stage):
|
||||||
|
|
||||||
# check if reconstruction was done before
|
# check if reconstruction was done before
|
||||||
if not io.file_exists(tree.mve_model) or self.rerun():
|
if not io.file_exists(tree.mve_model) or self.rerun():
|
||||||
# cleanup if a rerun
|
|
||||||
if io.dir_exists(tree.mve_path) and self.rerun():
|
|
||||||
shutil.rmtree(tree.mve_path)
|
|
||||||
|
|
||||||
# make bundle directory
|
|
||||||
if not io.file_exists(tree.mve_bundle):
|
|
||||||
system.mkdir_p(tree.mve_path)
|
|
||||||
system.mkdir_p(io.join_paths(tree.mve_path, 'bundle'))
|
|
||||||
|
|
||||||
octx = OSFMContext(tree.opensfm)
|
|
||||||
octx.save_absolute_image_list_to(tree.mve_image_list)
|
|
||||||
io.copy(tree.opensfm_bundle, tree.mve_bundle)
|
|
||||||
|
|
||||||
# mve makescene wants the output directory
|
# mve makescene wants the output directory
|
||||||
# to not exists before executing it (otherwise it
|
# to not exists before executing it (otherwise it
|
||||||
# will prompt the user for confirmation)
|
# will prompt the user for confirmation)
|
||||||
|
@ -42,22 +29,16 @@ class ODMMveStage(types.ODM_Stage):
|
||||||
|
|
||||||
# run mve makescene
|
# run mve makescene
|
||||||
if not io.dir_exists(tree.mve_views):
|
if not io.dir_exists(tree.mve_views):
|
||||||
system.run('%s "%s" "%s"' % (context.makescene_path, tree.mve_path, tree.mve), env_vars={'OMP_NUM_THREADS': args.max_concurrency})
|
system.run('%s "%s" "%s"' % (context.makescene_path, tree.opensfm_reconstruction_nvm, tree.mve), env_vars={'OMP_NUM_THREADS': args.max_concurrency})
|
||||||
|
|
||||||
self.update_progress(10)
|
self.update_progress(10)
|
||||||
|
|
||||||
# Compute mve output scale based on depthmap_resolution
|
# Compute mve output scale based on depthmap_resolution
|
||||||
max_width = 0
|
|
||||||
max_height = 0
|
|
||||||
for photo in photos:
|
|
||||||
max_width = max(photo.width, max_width)
|
|
||||||
max_height = max(photo.height, max_height)
|
|
||||||
|
|
||||||
max_pixels = args.depthmap_resolution * args.depthmap_resolution
|
max_pixels = args.depthmap_resolution * args.depthmap_resolution
|
||||||
if max_width * max_height <= max_pixels:
|
if outputs['undist_image_max_size'] * outputs['undist_image_max_size'] <= max_pixels:
|
||||||
mve_output_scale = 0
|
mve_output_scale = 0
|
||||||
else:
|
else:
|
||||||
ratio = float(max_width * max_height) / float(max_pixels)
|
ratio = float(outputs['undist_image_max_size'] * outputs['undist_image_max_size']) / float(max_pixels)
|
||||||
mve_output_scale = int(math.ceil(math.log(ratio) / math.log(4.0)))
|
mve_output_scale = int(math.ceil(math.log(ratio) / math.log(4.0)))
|
||||||
|
|
||||||
dmrecon_config = [
|
dmrecon_config = [
|
||||||
|
|
|
@ -44,11 +44,19 @@ class ODMOpenSfMStage(types.ODM_Stage):
|
||||||
output_file = tree.opensfm_reconstruction
|
output_file = tree.opensfm_reconstruction
|
||||||
|
|
||||||
updated_config_flag_file = octx.path('updated_config.txt')
|
updated_config_flag_file = octx.path('updated_config.txt')
|
||||||
|
|
||||||
|
# Make sure it's capped by the depthmap-resolution arg,
|
||||||
|
# since the undistorted images are used for MVS
|
||||||
|
outputs['undist_image_max_size'] = max(
|
||||||
|
gsd.image_max_size(photos, args.orthophoto_resolution, tree.opensfm_reconstruction, ignore_gsd=args.ignore_gsd),
|
||||||
|
args.depthmap_resolution
|
||||||
|
)
|
||||||
|
|
||||||
if not io.file_exists(updated_config_flag_file) or self.rerun():
|
if not io.file_exists(updated_config_flag_file) or self.rerun():
|
||||||
octx.update_config({'undistorted_image_max_size': gsd.image_max_size(photos, args.orthophoto_resolution, tree.opensfm_reconstruction, ignore_gsd=args.ignore_gsd)})
|
octx.update_config({'undistorted_image_max_size': outputs['undist_image_max_size']})
|
||||||
octx.touch(updated_config_flag_file)
|
octx.touch(updated_config_flag_file)
|
||||||
|
|
||||||
# These will be used for texturing
|
# These will be used for texturing / MVS
|
||||||
undistorted_images_path = octx.path("undistorted")
|
undistorted_images_path = octx.path("undistorted")
|
||||||
|
|
||||||
if not io.dir_exists(undistorted_images_path) or self.rerun():
|
if not io.dir_exists(undistorted_images_path) or self.rerun():
|
||||||
|
@ -59,7 +67,7 @@ class ODMOpenSfMStage(types.ODM_Stage):
|
||||||
self.update_progress(80)
|
self.update_progress(80)
|
||||||
|
|
||||||
if not io.file_exists(tree.opensfm_reconstruction_nvm) or self.rerun():
|
if not io.file_exists(tree.opensfm_reconstruction_nvm) or self.rerun():
|
||||||
octx.run('export_visualsfm --undistorted')
|
octx.run('export_visualsfm --undistorted --points')
|
||||||
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)
|
||||||
|
|
Ładowanie…
Reference in New Issue