kopia lustrzana https://github.com/OpenDroneMap/ODM
Started adding OpenMVS
rodzic
c100f03576
commit
e3cc8f1f9b
|
@ -27,7 +27,9 @@ RUN rm -rf \
|
||||||
/code/SuperBuild/src/opencv \
|
/code/SuperBuild/src/opencv \
|
||||||
/code/SuperBuild/src/opengv \
|
/code/SuperBuild/src/opengv \
|
||||||
/code/SuperBuild/src/pcl \
|
/code/SuperBuild/src/pcl \
|
||||||
/code/SuperBuild/src/pdal
|
/code/SuperBuild/src/pdal \
|
||||||
|
/code/SuperBuild/src/openmvs \
|
||||||
|
/code/SuperBuild/build/openmvs
|
||||||
|
|
||||||
# Entry point
|
# Entry point
|
||||||
ENTRYPOINT ["python3", "/code/run.py"]
|
ENTRYPOINT ["python3", "/code/run.py"]
|
|
@ -110,6 +110,7 @@ set(custom_libs OpenSfM
|
||||||
PDAL
|
PDAL
|
||||||
Entwine
|
Entwine
|
||||||
MvsTexturing
|
MvsTexturing
|
||||||
|
OpenMVS
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach(lib ${custom_libs})
|
foreach(lib ${custom_libs})
|
||||||
|
|
|
@ -92,6 +92,9 @@ install() {
|
||||||
libboost-date-time-dev \
|
libboost-date-time-dev \
|
||||||
libboost-thread-dev
|
libboost-thread-dev
|
||||||
|
|
||||||
|
echo "Installing OpenMVS Dependencies"
|
||||||
|
sudo apt-get install -y -qq --no-install-recommends libcgal-dev
|
||||||
|
|
||||||
pip install --ignore-installed -r requirements.txt
|
pip install --ignore-installed -r requirements.txt
|
||||||
|
|
||||||
if [ ! -z "$PORTABLE_INSTALL" ]; then
|
if [ ! -z "$PORTABLE_INSTALL" ]; then
|
||||||
|
|
|
@ -9,7 +9,7 @@ from pyodm import Node, exceptions
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
# parse arguments
|
# parse arguments
|
||||||
processopts = ['dataset', 'split', 'merge', 'opensfm', 'mve', 'odm_filterpoints',
|
processopts = ['dataset', 'split', 'merge', 'opensfm', 'openmvs', 'odm_filterpoints',
|
||||||
'odm_meshing', 'mvs_texturing', 'odm_georeferencing',
|
'odm_meshing', 'mvs_texturing', 'odm_georeferencing',
|
||||||
'odm_dem', 'odm_orthophoto', 'odm_report']
|
'odm_dem', 'odm_orthophoto', 'odm_report']
|
||||||
|
|
||||||
|
@ -275,16 +275,6 @@ def config(argv=None, parser=None):
|
||||||
help='Run local bundle adjustment for every image added to the reconstruction and a global '
|
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.')
|
||||||
|
|
||||||
parser.add_argument('--mve-confidence',
|
|
||||||
metavar='<float: 0 <= x <= 1>',
|
|
||||||
action=StoreValue,
|
|
||||||
type=float,
|
|
||||||
default=0.60,
|
|
||||||
help=('Discard points that have less than a certain confidence threshold. '
|
|
||||||
'This only affects dense reconstructions performed with MVE. '
|
|
||||||
'Higher values discard more points. '
|
|
||||||
'Default: %(default)s'))
|
|
||||||
|
|
||||||
parser.add_argument('--use-3dmesh',
|
parser.add_argument('--use-3dmesh',
|
||||||
action=StoreTrue,
|
action=StoreTrue,
|
||||||
nargs=0,
|
nargs=0,
|
||||||
|
|
|
@ -40,6 +40,9 @@ dem2points_path = os.path.join(superbuild_path, 'src', 'dem2points', 'dem2points
|
||||||
# define mvstex path
|
# define mvstex path
|
||||||
mvstex_path = os.path.join(superbuild_path, "install/bin/texrecon")
|
mvstex_path = os.path.join(superbuild_path, "install/bin/texrecon")
|
||||||
|
|
||||||
|
# openmvs paths
|
||||||
|
omvs_densify_path = os.path.join(superbuild_path, "install/bin/OpenMVS/DensifyPointCloud")
|
||||||
|
|
||||||
# define txt2las path
|
# define txt2las path
|
||||||
txt2las_path = os.path.join(superbuild_path, 'src/las-tools/bin')
|
txt2las_path = os.path.join(superbuild_path, 'src/las-tools/bin')
|
||||||
pdal_path = os.path.join(superbuild_path, 'build/pdal/bin')
|
pdal_path = os.path.join(superbuild_path, 'build/pdal/bin')
|
||||||
|
|
|
@ -12,8 +12,8 @@ def extract_path_from_file(file):
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
def join_paths(path1, path2):
|
def join_paths(*args):
|
||||||
return os.path.join(path1, path2)
|
return os.path.join(*args)
|
||||||
|
|
||||||
|
|
||||||
def file_exists(path_file):
|
def file_exists(path_file):
|
||||||
|
|
|
@ -214,6 +214,7 @@ class ODM_Tree(object):
|
||||||
self.dataset_raw = io.join_paths(self.root_path, 'images')
|
self.dataset_raw = io.join_paths(self.root_path, 'images')
|
||||||
self.opensfm = io.join_paths(self.root_path, 'opensfm')
|
self.opensfm = io.join_paths(self.root_path, 'opensfm')
|
||||||
self.mve = io.join_paths(self.root_path, 'mve')
|
self.mve = io.join_paths(self.root_path, 'mve')
|
||||||
|
self.openmvs = io.join_paths(self.opensfm, 'undistorted', 'openmvs')
|
||||||
self.odm_meshing = io.join_paths(self.root_path, 'odm_meshing')
|
self.odm_meshing = io.join_paths(self.root_path, 'odm_meshing')
|
||||||
self.odm_texturing = io.join_paths(self.root_path, 'odm_texturing')
|
self.odm_texturing = io.join_paths(self.root_path, 'odm_texturing')
|
||||||
self.odm_25dtexturing = io.join_paths(self.root_path, 'odm_texturing_25d')
|
self.odm_25dtexturing = io.join_paths(self.root_path, 'odm_texturing_25d')
|
||||||
|
@ -244,6 +245,9 @@ class ODM_Tree(object):
|
||||||
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_views = io.join_paths(self.mve, 'views')
|
self.mve_views = io.join_paths(self.mve, 'views')
|
||||||
|
|
||||||
|
# OpenMVS
|
||||||
|
self.openmvs_model = io.join_paths(self.openmvs, 'scene_dense.ply')
|
||||||
|
|
||||||
# filter points
|
# filter points
|
||||||
self.filtered_point_cloud = io.join_paths(self.odm_filterpoints, "point_cloud.ply")
|
self.filtered_point_cloud = io.join_paths(self.odm_filterpoints, "point_cloud.ply")
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,9 @@ RUN rm -rf \
|
||||||
/code/SuperBuild/src/opencv \
|
/code/SuperBuild/src/opencv \
|
||||||
/code/SuperBuild/src/opengv \
|
/code/SuperBuild/src/opengv \
|
||||||
/code/SuperBuild/src/pcl \
|
/code/SuperBuild/src/pcl \
|
||||||
/code/SuperBuild/src/pdal
|
/code/SuperBuild/src/pdal \
|
||||||
|
/code/SuperBuild/src/openmvs \
|
||||||
|
/code/SuperBuild/build/openmvs
|
||||||
|
|
||||||
# Entry point
|
# Entry point
|
||||||
ENTRYPOINT ["python3", "/code/run.py"]
|
ENTRYPOINT ["python3", "/code/run.py"]
|
||||||
|
|
|
@ -8,7 +8,7 @@ from opendm import log
|
||||||
|
|
||||||
from stages.dataset import ODMLoadDatasetStage
|
from stages.dataset import ODMLoadDatasetStage
|
||||||
from stages.run_opensfm import ODMOpenSfMStage
|
from stages.run_opensfm import ODMOpenSfMStage
|
||||||
from stages.mve import ODMMveStage
|
from stages.openmvs import ODMOpenMVSStage
|
||||||
from stages.odm_slam import ODMSlamStage
|
from stages.odm_slam import ODMSlamStage
|
||||||
from stages.odm_meshing import ODMeshingStage
|
from stages.odm_meshing import ODMeshingStage
|
||||||
from stages.mvstex import ODMMvsTexStage
|
from stages.mvstex import ODMMvsTexStage
|
||||||
|
@ -34,7 +34,7 @@ class ODMApp:
|
||||||
merge = ODMMergeStage('merge', args, progress=100.0)
|
merge = ODMMergeStage('merge', args, progress=100.0)
|
||||||
opensfm = ODMOpenSfMStage('opensfm', args, progress=25.0)
|
opensfm = ODMOpenSfMStage('opensfm', args, progress=25.0)
|
||||||
slam = ODMSlamStage('slam', args)
|
slam = ODMSlamStage('slam', args)
|
||||||
mve = ODMMveStage('mve', args, progress=50.0)
|
openmvs = ODMOpenMVSStage('openmvs', args, progress=50.0)
|
||||||
filterpoints = ODMFilterPoints('odm_filterpoints', args, progress=52.0)
|
filterpoints = ODMFilterPoints('odm_filterpoints', args, progress=52.0)
|
||||||
meshing = ODMeshingStage('odm_meshing', args, progress=60.0,
|
meshing = ODMeshingStage('odm_meshing', args, progress=60.0,
|
||||||
max_vertex=args.mesh_size,
|
max_vertex=args.mesh_size,
|
||||||
|
@ -71,8 +71,8 @@ class ODMApp:
|
||||||
if args.use_opensfm_dense or args.fast_orthophoto:
|
if args.use_opensfm_dense or args.fast_orthophoto:
|
||||||
opensfm.connect(filterpoints)
|
opensfm.connect(filterpoints)
|
||||||
else:
|
else:
|
||||||
opensfm.connect(mve) \
|
opensfm.connect(openmvs) \
|
||||||
.connect(filterpoints)
|
.connect(filterpoints)
|
||||||
|
|
||||||
filterpoints \
|
filterpoints \
|
||||||
.connect(meshing) \
|
.connect(meshing) \
|
||||||
|
@ -82,14 +82,5 @@ class ODMApp:
|
||||||
.connect(orthophoto) \
|
.connect(orthophoto) \
|
||||||
.connect(report)
|
.connect(report)
|
||||||
|
|
||||||
# # SLAM pipeline
|
|
||||||
# # TODO: this is broken and needs work
|
|
||||||
# log.ODM_WARNING("SLAM module is currently broken. We could use some help fixing this. If you know Python, get in touch at https://community.opendronemap.org.")
|
|
||||||
# self.first_stage = slam
|
|
||||||
|
|
||||||
# slam.connect(mve) \
|
|
||||||
# .connect(meshing) \
|
|
||||||
# .connect(texturing)
|
|
||||||
|
|
||||||
def execute(self):
|
def execute(self):
|
||||||
self.first_stage.run()
|
self.first_stage.run()
|
|
@ -21,7 +21,7 @@ class ODMFilterPoints(types.ODM_Stage):
|
||||||
elif args.use_opensfm_dense:
|
elif args.use_opensfm_dense:
|
||||||
inputPointCloud = tree.opensfm_model
|
inputPointCloud = tree.opensfm_model
|
||||||
else:
|
else:
|
||||||
inputPointCloud = tree.mve_model
|
inputPointCloud = tree.openmvs_model
|
||||||
|
|
||||||
point_cloud.filter(inputPointCloud, tree.filtered_point_cloud,
|
point_cloud.filter(inputPointCloud, tree.filtered_point_cloud,
|
||||||
standard_deviation=args.pc_filter,
|
standard_deviation=args.pc_filter,
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
import shutil, os, glob, math
|
||||||
|
|
||||||
|
from opendm import log
|
||||||
|
from opendm import io
|
||||||
|
from opendm import system
|
||||||
|
from opendm import context
|
||||||
|
from opendm import point_cloud
|
||||||
|
from opendm import types
|
||||||
|
from opendm.osfm import OSFMContext
|
||||||
|
|
||||||
|
class ODMOpenMVSStage(types.ODM_Stage):
|
||||||
|
def process(self, args, outputs):
|
||||||
|
# get inputs
|
||||||
|
tree = outputs['tree']
|
||||||
|
reconstruction = outputs['reconstruction']
|
||||||
|
photos = reconstruction.photos
|
||||||
|
|
||||||
|
if not photos:
|
||||||
|
log.ODM_ERROR('Not enough photos in photos array to start OpenMVS')
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# check if reconstruction was done before
|
||||||
|
if not io.file_exists(tree.openmvs_model) or self.rerun():
|
||||||
|
if io.dir_exists(tree.openmvs):
|
||||||
|
shutil.rmtree(tree.openmvs)
|
||||||
|
|
||||||
|
# export reconstruction from opensfm
|
||||||
|
octx = OSFMContext(tree.opensfm)
|
||||||
|
cmd = 'export_openmvs'
|
||||||
|
if reconstruction.multi_camera:
|
||||||
|
# Export only the primary band
|
||||||
|
primary = reconstruction.multi_camera[0]
|
||||||
|
image_list = os.path.join(tree.opensfm, "image_list_%s.txt" % primary['name'].lower())
|
||||||
|
cmd += ' --image_list "%s"' % image_list
|
||||||
|
octx.run(cmd)
|
||||||
|
|
||||||
|
self.update_progress(10)
|
||||||
|
|
||||||
|
depthmaps_dir = os.path.join(tree.openmvs, "depthmaps")
|
||||||
|
if not io.dir_exists(depthmaps_dir):
|
||||||
|
os.mkdir(depthmaps_dir)
|
||||||
|
|
||||||
|
resolution_level = int(float(outputs['undist_image_max_size']) / (2*args.depthmap_resolution))
|
||||||
|
|
||||||
|
config = [
|
||||||
|
" --resolution-level %s" % resolution_level,
|
||||||
|
"--min-resolution %s" % args.depthmap_resolution,
|
||||||
|
"--max-resolution %s" % outputs['undist_image_max_size'],
|
||||||
|
"--max-threads %s" % args.max_concurrency,
|
||||||
|
'-w "%s"' % depthmaps_dir,
|
||||||
|
"-v 0",
|
||||||
|
]
|
||||||
|
|
||||||
|
log.ODM_INFO("Running dense reconstruction. This might take a while.")
|
||||||
|
|
||||||
|
system.run('%s "%s" %s' % (context.omvs_densify_path,
|
||||||
|
os.path.join(tree.openmvs, 'scene.mvs'),
|
||||||
|
' '.join(config)))
|
||||||
|
|
||||||
|
self.update_progress(90)
|
||||||
|
|
||||||
|
if args.optimize_disk_space:
|
||||||
|
dense_scene = os.path.join(tree.openmvs, 'scene_dense.mvs')
|
||||||
|
if os.path.exists(dense_scene):
|
||||||
|
os.remove(dense_scene)
|
||||||
|
shutil.rmtree(depthmaps_dir)
|
||||||
|
else:
|
||||||
|
log.ODM_WARNING('Found a valid OpenMVS reconstruction file in: %s' %
|
||||||
|
tree.openmvs_model)
|
Ładowanie…
Reference in New Issue