diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index a8a441d8..00000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -project(OpenDroneMap C CXX) - -# TODO(edgar): add option in order to point to CMAKE_PREFIX_PATH -# if we want to build SuperBuild in an external directory. -# It is assumed that SuperBuild have been compiled. - -# Set third party libs location -set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/SuperBuild/install") - -# move binaries to the same bin directory -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) - -option(ODM_BUILD_SLAM "Build SLAM module" OFF) - -# Add ODM sub-modules -add_subdirectory(modules) diff --git a/SuperBuild/cmake/External-MvsTexturing.cmake b/SuperBuild/cmake/External-MvsTexturing.cmake index 5797bc40..2e916d9e 100644 --- a/SuperBuild/cmake/External-MvsTexturing.cmake +++ b/SuperBuild/cmake/External-MvsTexturing.cmake @@ -9,7 +9,7 @@ ExternalProject_Add(${_proj_name} #--Download step-------------- DOWNLOAD_DIR ${SB_DOWNLOAD_DIR}/${_proj_name} GIT_REPOSITORY https://github.com/OpenDroneMap/mvs-texturing - GIT_TAG 264 + GIT_TAG 267 #--Update/Patch step---------- UPDATE_COMMAND "" #--Configure step------------- diff --git a/SuperBuild/cmake/External-OpenMVS.cmake b/SuperBuild/cmake/External-OpenMVS.cmake index 70dd1138..ea0095d2 100644 --- a/SuperBuild/cmake/External-OpenMVS.cmake +++ b/SuperBuild/cmake/External-OpenMVS.cmake @@ -35,6 +35,15 @@ if(UNIX) endif() endif() +if(WIN32) + # On Windows systems without NVIDIA GPUs, OpenMVS will not launch + # unless a CUDA DLL is available; we download a dummy DLL + # generated with https://github.com/ykhwong/dummy-dll-generator that is + # loaded UNLESS the real CUDA DLL is available, since it will + # be loaded before our dummy DLL. + file(DOWNLOAD "https://github.com/OpenDroneMap/windows-deps/releases/download/2.5.0/nvcuda_dummy.dll" "${SB_INSTALL_DIR}/bin/nvcuda.dll") +endif() + ExternalProject_Add(${_proj_name} DEPENDS ceres opencv vcg eigen34 PREFIX ${_SB_BINARY_DIR} diff --git a/opendm/gpu.py b/opendm/gpu.py index 3de5e3d8..53f7d1a9 100644 --- a/opendm/gpu.py +++ b/opendm/gpu.py @@ -1,4 +1,5 @@ import os +import sys from opendm import log from repoze.lru import lru_cache @@ -24,3 +25,20 @@ def has_gpus(): return len(platforms) > 0 except Exception as e: return False + +@lru_cache(maxsize=None) +def windows_no_cuda(): + """ + Check if CUDA lib is available on Windows + Returns true if OS is windows and CUDA is not found. + """ + if sys.platform == 'win32': + nvcuda_path = os.path.join(os.environ.get('SYSTEMROOT'), 'system32', 'nvcuda.dll') + if os.path.isfile(nvcuda_path): + return False + else: + log.ODM_INFO("No CUDA drivers detected, using CPU") + return True + else: + return False + diff --git a/opendm/mesh.py b/opendm/mesh.py index 44bcb576..332c93a1 100644 --- a/opendm/mesh.py +++ b/opendm/mesh.py @@ -127,7 +127,7 @@ def dem_to_mesh_gridded(inGeotiff, outMesh, maxVertexCount, verbose=False, maxCo system.run('"{reconstructmesh}" -i "{infile}" ' '-o "{outfile}" ' '--remove-spikes 0 --remove-spurious 0 --smooth 0 ' - '--target-face-num {max_faces} '.format(**cleanupArgs)) + '--target-face-num {max_faces} -v 0'.format(**cleanupArgs)) # Delete intermediate results os.remove(outMeshDirty) @@ -163,7 +163,6 @@ def screened_poisson_reconstruction(inPointCloud, outMesh, depth = 8, samples = 'samples': samples, 'pointWeight': pointWeight, 'threads': int(threads), - 'memory': int(concurrency.get_max_memory_mb(4, 0.8) // 1024), 'verbose': '--verbose' if verbose else '' } @@ -175,7 +174,6 @@ def screened_poisson_reconstruction(inPointCloud, outMesh, depth = 8, samples = '--pointWeight {pointWeight} ' '--samplesPerNode {samples} ' '--threads {threads} ' - '--maxMemory {memory} ' '--bType 2 ' '--linearFit ' '{verbose}'.format(**poissonReconArgs)) @@ -207,7 +205,7 @@ def screened_poisson_reconstruction(inPointCloud, outMesh, depth = 8, samples = system.run('"{reconstructmesh}" -i "{infile}" ' '-o "{outfile}" ' '--remove-spikes 0 --remove-spurious 20 --smooth 0 ' - '--target-face-num {max_faces} '.format(**cleanupArgs)) + '--target-face-num {max_faces} -v 0'.format(**cleanupArgs)) # Delete intermediate results os.remove(outMeshDirty) diff --git a/stages/mvstex.py b/stages/mvstex.py index 7d981d6a..fe90332d 100644 --- a/stages/mvstex.py +++ b/stages/mvstex.py @@ -6,12 +6,20 @@ from opendm import system from opendm import context from opendm import types from opendm.multispectral import get_primary_band_name +from opendm.photo import find_largest_photo_dim class ODMMvsTexStage(types.ODM_Stage): def process(self, args, outputs): tree = outputs['tree'] reconstruction = outputs['reconstruction'] + max_dim = find_largest_photo_dim(reconstruction.photos) + max_texture_size = 8 * 1024 # default + + if max_dim > 8000: + log.ODM_INFO("Large input images (%s pixels), increasing maximum texture size." % max_dim) + max_texture_size *= 3 + class nonloc: runs = [] @@ -92,6 +100,7 @@ class ODMMvsTexStage(types.ODM_Stage): 'keepUnseenFaces': keepUnseenFaces, 'toneMapping': self.params.get('tone_mapping'), 'nadirMode': nadir, + 'maxTextureSize': '--max_texture_size=%s' % max_texture_size, '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 '' @@ -113,7 +122,8 @@ class ODMMvsTexStage(types.ODM_Stage): '{skipLocalSeamLeveling} ' '{keepUnseenFaces} ' '{nadirMode} ' - '{labelingFile} '.format(**kwargs)) + '{labelingFile} ' + '{maxTextureSize} '.format(**kwargs)) # Backward compatibility: copy odm_textured_model_geo.mtl to odm_textured_model.mtl # for certain older WebODM clients which expect a odm_textured_model.mtl diff --git a/stages/openmvs.py b/stages/openmvs.py index 6dfef8ef..bf338d11 100644 --- a/stages/openmvs.py +++ b/stages/openmvs.py @@ -6,7 +6,7 @@ from opendm import system from opendm import context from opendm import point_cloud from opendm import types -from opendm.gpu import gpu_disabled_by_user +from opendm.gpu import gpu_disabled_by_user, windows_no_cuda from opendm.utils import get_depthmap_resolution from opendm.osfm import OSFMContext from opendm.multispectral import get_primary_band_name @@ -71,8 +71,10 @@ class ODMOpenMVSStage(types.ODM_Stage): "-v 0" ] - if gpu_disabled_by_user(): - config.append("--cuda-device -1") + gpu_config = [] + + if gpu_disabled_by_user() or windows_no_cuda(): + gpu_config.append("--cuda-device -1") if args.pc_tile: config.append("--fusion-mode 1") @@ -82,7 +84,7 @@ class ODMOpenMVSStage(types.ODM_Stage): system.run('%s "%s" %s' % (context.omvs_densify_path, openmvs_scene_file, - ' '.join(config))) + ' '.join(config + gpu_config))) self.update_progress(85) files_to_remove = [] @@ -98,7 +100,7 @@ class ODMOpenMVSStage(types.ODM_Stage): ] system.run('%s "%s" %s' % (context.omvs_densify_path, openmvs_scene_file, - ' '.join(config))) + ' '.join(config + gpu_config))) scene_files = glob.glob(os.path.join(tree.openmvs, "scene_[0-9][0-9][0-9][0-9].mvs")) if len(scene_files) == 0: @@ -130,10 +132,10 @@ class ODMOpenMVSStage(types.ODM_Stage): ] try: - system.run('%s "%s" %s' % (context.omvs_densify_path, sf, ' '.join(config))) + system.run('%s "%s" %s' % (context.omvs_densify_path, sf, ' '.join(config + gpu_config))) # Filter - system.run('%s "%s" --filter-point-cloud -1 -v 0' % (context.omvs_densify_path, scene_dense_mvs)) + system.run('%s "%s" --filter-point-cloud -1 -v 0 %s' % (context.omvs_densify_path, scene_dense_mvs, ' '.join(gpu_config))) except: log.ODM_WARNING("Sub-scene %s could not be reconstructed, skipping..." % sf) @@ -162,7 +164,7 @@ class ODMOpenMVSStage(types.ODM_Stage): '-i "%s"' % scene_dense, "-v 0" ] - system.run('%s %s' % (context.omvs_densify_path, ' '.join(config))) + system.run('%s %s' % (context.omvs_densify_path, ' '.join(config + gpu_config))) else: raise system.ExitException("Cannot find scene_dense.mvs, dense reconstruction probably failed. Exiting...")