Skip to content

Commit ce03889

Browse files
authored
v2.3.0 (#1090)
- store all stages in Interface MVS format by default - store dense point-cloud as PLY, including all point-views information, etc - add max-texture-size and multi-texture support to mesh texturing stage - speedup/improve fix non-manifold mesh algorithm - unify library/application initialization/destroying - add python support for reading DMAP and Interface MVS file formats - account for different pixel center conventions when importing/exporting COLMAP which uses pixel center at (0.5,0.5) instead of (0, 0) as OpenMVS - add interface to MVSNet, Nerfstudio and RTMV scene formats - improve interface to Polycam scene format - speedup PLY load/save - speedup/improve ray-triangle intersection - add support for UV coordinates agnostic about orientation - add support for storing neighbor views information in Interface MVS format - add support for C++20 - various other fixes
1 parent 42b8816 commit ce03889

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+4083
-3324
lines changed

CMakeLists.txt

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ SET(OpenMVS_BUILD_TOOLS ON CACHE BOOL "Build example applications")
1919
SET(OpenMVS_USE_OPENMP ON CACHE BOOL "Enable OpenMP library")
2020
SET(OpenMVS_USE_OPENGL ON CACHE BOOL "Enable OpenGL library")
2121
SET(OpenMVS_USE_BREAKPAD ON CACHE BOOL "Enable BreakPad library")
22-
SET(OpenMVS_USE_PYTHON OFF CACHE BOOL "Enable Python library bindings")
22+
SET(OpenMVS_USE_PYTHON ON CACHE BOOL "Enable Python library bindings")
2323
SET(OpenMVS_USE_CERES OFF CACHE BOOL "Enable CERES optimization library")
2424
SET(OpenMVS_USE_CUDA ON CACHE BOOL "Enable CUDA library")
25-
SET(OpenMVS_USE_FAST_FLOAT2INT ON CACHE BOOL "Use an optimized code to convert real numbers to int")
25+
SET(OpenMVS_USE_FAST_FLOAT2INT OFF CACHE BOOL "Use an optimized code to convert real numbers to int")
2626
SET(OpenMVS_USE_FAST_INVSQRT OFF CACHE BOOL "Use an optimized code to compute the inverse square root (slower in fact on modern compilers)")
27-
SET(OpenMVS_USE_FAST_CBRT ON CACHE BOOL "Use an optimized code to compute the cubic root")
27+
SET(OpenMVS_USE_FAST_CBRT OFF CACHE BOOL "Use an optimized code to compute the cubic root")
2828
SET(OpenMVS_USE_SSE ON CACHE BOOL "Enable SSE optimizations")
2929
SET(OpenMVS_MAX_CUDA_COMPATIBILITY OFF CACHE BOOL "Build for maximum CUDA device compatibility")
3030
SET(OpenMVS_ENABLE_TESTS ON CACHE BOOL "Enable test code")
@@ -52,10 +52,15 @@ ENDIF()
5252
PROJECT(OpenMVS)
5353

5454
SET(OpenMVS_MAJOR_VERSION 2)
55-
SET(OpenMVS_MINOR_VERSION 2)
55+
SET(OpenMVS_MINOR_VERSION 3)
5656
SET(OpenMVS_PATCH_VERSION 0)
5757
SET(OpenMVS_VERSION ${OpenMVS_MAJOR_VERSION}.${OpenMVS_MINOR_VERSION}.${OpenMVS_PATCH_VERSION})
5858

59+
# Disable SSE on unsuported platforms
60+
IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm|ARM|aarch64|AARCH64)")
61+
SET(OpenMVS_USE_SSE OFF)
62+
ENDIF()
63+
5964
# Define helper functions and macros.
6065
INCLUDE(build/Utils.cmake)
6166

@@ -109,16 +114,15 @@ if(OpenMVS_USE_CUDA)
109114
ENABLE_LANGUAGE(CUDA)
110115
# CUDA-11.x can not be compiled using C++14 standard on Windows
111116
string(REGEX MATCH "^[0-9]+" CUDA_MAJOR ${CMAKE_CUDA_COMPILER_VERSION})
112-
if(${CUDA_MAJOR} GREATER 10 AND CMAKE_CXX_COMPILER MATCHES "MSVC" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "19.29")
113-
message("Working around windows build failure with visual studio. Visual studio 16.10 introduced a compiler bug with compilng CUDA code with C++14. Set the cuda standard to 17 as a workaround.")
114-
set(CMAKE_CUDA_STANDARD 17)
117+
if(${CUDA_MAJOR} GREATER 10)
118+
SET(CMAKE_CUDA_STANDARD 17)
115119
endif()
116120
EXECUTE_PROCESS(COMMAND "${CMAKE_CUDA_COMPILER}" --list-gpu-arch
117121
OUTPUT_VARIABLE LIST_GPU_ARCH
118122
ERROR_QUIET)
119123
if(NOT LIST_GPU_ARCH AND OpenMVS_MAX_CUDA_COMPATIBILITY)
120124
message(WARNING "Cannot compile for max CUDA compatibility, nvcc does not support --list-gpu-arch")
121-
set(OpenMVS_MAX_CUDA_COMPATIBILITY NO)
125+
SET(OpenMVS_MAX_CUDA_COMPATIBILITY OFF)
122126
endif()
123127
if(NOT OpenMVS_MAX_CUDA_COMPATIBILITY)
124128
if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES)
@@ -172,19 +176,21 @@ if(OpenMVS_USE_BREAKPAD)
172176
endif()
173177
endif()
174178

179+
SET(Boost_EXTRA_COMPONENTS "")
175180
if(OpenMVS_USE_PYTHON)
176-
FIND_PACKAGE(PythonLibs 3.0 REQUIRED)
177-
if(PythonLibs_FOUND)
178-
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIRS})
179-
LIST(APPEND OpenMVS_EXTRA_INCLUDES ${PYTHON_INCLUDE_DIRS})
180-
LIST(APPEND OpenMVS_EXTRA_LIBS ${PYTHON_LIBRARIES})
181-
MESSAGE(STATUS "Python ${PYTHON_VERSION} found (include: ${PYTHON_INCLUDE_DIRS})")
181+
FIND_PACKAGE(Python3 COMPONENTS Interpreter Development REQUIRED)
182+
if(Python3_FOUND)
183+
INCLUDE_DIRECTORIES(${Python3_INCLUDE_DIRS})
184+
LIST(APPEND OpenMVS_EXTRA_INCLUDES ${Python3_INCLUDE_DIRS})
185+
LIST(APPEND OpenMVS_EXTRA_LIBS ${Python3_LIBRARIES})
186+
LIST(APPEND Boost_EXTRA_COMPONENTS python${Python3_VERSION_MAJOR}${Python3_VERSION_MINOR})
187+
MESSAGE(STATUS "Python ${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR} found (include: ${Python3_INCLUDE_DIRS})")
182188
else()
183189
MESSAGE("-- Can't find Python. Continuing without it.")
184190
endif()
185191
endif()
186192

187-
FIND_PACKAGE(Boost REQUIRED COMPONENTS iostreams program_options system serialization OPTIONAL_COMPONENTS python3)
193+
FIND_PACKAGE(Boost REQUIRED COMPONENTS iostreams program_options system serialization OPTIONAL_COMPONENTS ${Boost_EXTRA_COMPONENTS})
188194
if(Boost_FOUND)
189195
LIST(APPEND OpenMVS_EXTRA_INCLUDES ${Boost_INCLUDE_DIRS})
190196
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
@@ -195,12 +201,12 @@ if(Boost_FOUND)
195201
LIST(APPEND Boost_LIBRARIES zstd)
196202
endif()
197203
SET(_USE_BOOST TRUE)
198-
if(Boost_python3_FOUND)
204+
if(OpenMVS_USE_PYTHON AND Boost_${Boost_EXTRA_COMPONENTS}_FOUND)
199205
SET(_USE_BOOST_PYTHON TRUE)
200206
endif()
201207
endif()
202208

203-
FIND_PACKAGE(Eigen3 REQUIRED)
209+
FIND_PACKAGE(Eigen3 3.4 REQUIRED)
204210
if(EIGEN3_FOUND)
205211
LIST(APPEND OpenMVS_EXTRA_INCLUDES ${EIGEN3_INCLUDE_DIR})
206212
INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIR})

apps/DensifyPointCloud/DensifyPointCloud.cpp

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ namespace {
4747

4848
namespace OPT {
4949
String strInputFileName;
50+
String strPointCloudFileName;
5051
String strOutputFileName;
5152
String strViewNeighborsFileName;
5253
String strOutputViewNeighborsFileName;
@@ -73,8 +74,17 @@ String strConfigFileName;
7374
boost::program_options::variables_map vm;
7475
} // namespace OPT
7576

77+
class Application {
78+
public:
79+
Application() {}
80+
~Application() { Finalize(); }
81+
82+
bool Initialize(size_t argc, LPCTSTR* argv);
83+
void Finalize();
84+
}; // Application
85+
7686
// initialize and parse the command line parameters
77-
bool Initialize(size_t argc, LPCTSTR* argv)
87+
bool Application::Initialize(size_t argc, LPCTSTR* argv)
7888
{
7989
// initialize log and console
8090
OPEN_LOG();
@@ -86,7 +96,7 @@ bool Initialize(size_t argc, LPCTSTR* argv)
8696
("help,h", "produce this help message")
8797
("working-folder,w", boost::program_options::value<std::string>(&WORKING_FOLDER), "working directory (default current directory)")
8898
("config-file,c", boost::program_options::value<std::string>(&OPT::strConfigFileName)->default_value(APPNAME _T(".cfg")), "file name containing program options")
89-
("archive-type", boost::program_options::value(&OPT::nArchiveType)->default_value(ARCHIVE_DEFAULT), "project archive type: 0-text, 1-binary, 2-compressed binary")
99+
("archive-type", boost::program_options::value(&OPT::nArchiveType)->default_value(ARCHIVE_MVS), "project archive type: -1-interface, 0-text, 1-binary, 2-compressed binary")
90100
("process-priority", boost::program_options::value(&OPT::nProcessPriority)->default_value(-1), "process priority (below normal by default)")
91101
("max-threads", boost::program_options::value(&OPT::nMaxThreads)->default_value(0), "maximum number of threads (0 for using all available cores)")
92102
#if TD_VERBOSE != TD_VERBOSE_OFF
@@ -127,6 +137,7 @@ bool Initialize(size_t argc, LPCTSTR* argv)
127137
boost::program_options::options_description config("Densify options");
128138
config.add_options()
129139
("input-file,i", boost::program_options::value<std::string>(&OPT::strInputFileName), "input filename containing camera poses and image list")
140+
("pointcloud-file,p", boost::program_options::value<std::string>(&OPT::strPointCloudFileName), "sparse point-cloud with views file name to densify (overwrite existing point-cloud)")
130141
("output-file,o", boost::program_options::value<std::string>(&OPT::strOutputFileName), "output filename for storing the dense point-cloud (optional)")
131142
("view-neighbors-file", boost::program_options::value<std::string>(&OPT::strViewNeighborsFileName), "input filename containing the list of views and their neighbors (optional)")
132143
("output-view-neighbors-file", boost::program_options::value<std::string>(&OPT::strOutputViewNeighborsFileName), "output filename containing the generated list of views and their neighbors")
@@ -153,7 +164,7 @@ bool Initialize(size_t argc, LPCTSTR* argv)
153164
("estimate-roi", boost::program_options::value(&OPT::nEstimateROI)->default_value(2), "estimate and set region-of-interest (0 - disabled, 1 - enabled, 2 - adaptive)")
154165
("crop-to-roi", boost::program_options::value(&OPT::bCrop2ROI)->default_value(true), "crop scene using the region-of-interest")
155166
("remove-dmaps", boost::program_options::value(&bRemoveDmaps)->default_value(false), "remove depth-maps after fusion")
156-
("tower-mode", boost::program_options::value(&OPT::nTowerMode)->default_value(3), "add a cylinder of points in the center of ROI; scene assume to be Z-up oriented (0 - disabled, 1 - replace, 2 - append, 3 - select neighbors, <0 - force tower mode)")
167+
("tower-mode", boost::program_options::value(&OPT::nTowerMode)->default_value(4), "add a cylinder of points in the center of ROI; scene assume to be Z-up oriented (0 - disabled, 1 - replace, 2 - append, 3 - select neighbors, 4 - select neighbors & append, <0 - force tower mode)")
157168
;
158169

159170
// hidden options, allowed both on command line and
@@ -211,6 +222,7 @@ bool Initialize(size_t argc, LPCTSTR* argv)
211222
return false;
212223

213224
// initialize optional options
225+
Util::ensureValidPath(OPT::strPointCloudFileName);
214226
Util::ensureValidPath(OPT::strOutputFileName);
215227
Util::ensureValidPath(OPT::strViewNeighborsFileName);
216228
Util::ensureValidPath(OPT::strOutputViewNeighborsFileName);
@@ -242,29 +254,14 @@ bool Initialize(size_t argc, LPCTSTR* argv)
242254
if (!bValidConfig && !OPT::strDenseConfigFileName.empty())
243255
OPTDENSE::oConfig.Save(OPT::strDenseConfigFileName);
244256

245-
// initialize global options
246-
Process::setCurrentProcessPriority((Process::Priority)OPT::nProcessPriority);
247-
#ifdef _USE_OPENMP
248-
if (OPT::nMaxThreads != 0)
249-
omp_set_num_threads(OPT::nMaxThreads);
250-
#endif
251-
252-
#ifdef _USE_BREAKPAD
253-
// start memory dumper
254-
MiniDumper::Create(APPNAME, WORKING_FOLDER);
255-
#endif
256-
257-
Util::Init();
257+
MVS::Initialize(APPNAME, OPT::nMaxThreads, OPT::nProcessPriority);
258258
return true;
259259
}
260260

261261
// finalize application instance
262-
void Finalize()
262+
void Application::Finalize()
263263
{
264-
#if TD_VERBOSE != TD_VERBOSE_OFF
265-
// print memory statistics
266-
Util::LogMemoryInfo();
267-
#endif
264+
MVS::Finalize();
268265

269266
CLOSE_LOGFILE();
270267
CLOSE_LOGCONSOLE();
@@ -280,7 +277,8 @@ int main(int argc, LPCTSTR* argv)
280277
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);// | _CRTDBG_CHECK_ALWAYS_DF);
281278
#endif
282279

283-
if (!Initialize(argc, argv))
280+
Application application;
281+
if (!application.Initialize(argc, argv))
284282
return EXIT_FAILURE;
285283

286284
Scene scene(OPT::nMaxThreads);
@@ -296,12 +294,16 @@ int main(int argc, LPCTSTR* argv)
296294
scene.mesh.SamplePoints(ROUND2INT<unsigned>(-OPT::fSampleMesh), pointcloud);
297295
VERBOSE("Sample mesh completed: %u points (%s)", pointcloud.GetSize(), TD_TIMER_GET_FMT().c_str());
298296
pointcloud.Save(MAKE_PATH_SAFE(Util::getFileFullName(OPT::strOutputFileName))+_T(".ply"));
299-
Finalize();
300297
return EXIT_SUCCESS;
301298
}
302299
// load and estimate a dense point-cloud
303-
if (!scene.Load(MAKE_PATH_SAFE(OPT::strInputFileName)))
300+
const Scene::SCENE_TYPE sceneType(scene.Load(MAKE_PATH_SAFE(OPT::strInputFileName)));
301+
if (sceneType == Scene::SCENE_NA)
302+
return EXIT_FAILURE;
303+
if (!OPT::strPointCloudFileName.empty() && !scene.pointcloud.Load(MAKE_PATH_SAFE(OPT::strPointCloudFileName))) {
304+
VERBOSE("error: cannot load point-cloud file");
304305
return EXIT_FAILURE;
306+
}
305307
if (!OPT::strMaskPath.empty()) {
306308
Util::ensureValidFolderPath(OPT::strMaskPath);
307309
for (Image& image : scene.images) {
@@ -322,7 +324,6 @@ int main(int argc, LPCTSTR* argv)
322324
return EXIT_FAILURE;
323325
fs >> scene.obb;
324326
scene.Save(MAKE_PATH_SAFE(Util::getFileFullName(OPT::strOutputFileName))+_T(".mvs"), (ARCHIVE_TYPE)OPT::nArchiveType);
325-
Finalize();
326327
return EXIT_SUCCESS;
327328
}
328329
if (!scene.IsBounded())
@@ -332,7 +333,6 @@ int main(int argc, LPCTSTR* argv)
332333
if (!fs)
333334
return EXIT_FAILURE;
334335
fs << scene.obb;
335-
Finalize();
336336
return EXIT_SUCCESS;
337337
}
338338
if (OPT::nTowerMode!=0)
@@ -355,15 +355,13 @@ int main(int argc, LPCTSTR* argv)
355355
if (!scene.ExportMeshToDepthMaps(MAKE_PATH_SAFE(OPT::strExportDepthMapsName)))
356356
return EXIT_FAILURE;
357357
VERBOSE("Mesh projection completed: %u depth-maps (%s)", scene.images.size(), TD_TIMER_GET_FMT().c_str());
358-
Finalize();
359358
return EXIT_SUCCESS;
360359
}
361360
if (OPT::fMaxSubsceneArea > 0) {
362361
// split the scene in sub-scenes by maximum sampling area
363362
Scene::ImagesChunkArr chunks;
364363
scene.Split(chunks, OPT::fMaxSubsceneArea);
365364
scene.ExportChunks(chunks, GET_PATH_FULL(OPT::strOutputFileName), (ARCHIVE_TYPE)OPT::nArchiveType);
366-
Finalize();
367365
return EXIT_SUCCESS;
368366
}
369367
if (OPT::thFilterPointCloud < 0) {
@@ -372,7 +370,6 @@ int main(int argc, LPCTSTR* argv)
372370
const String baseFileName(MAKE_PATH_SAFE(Util::getFileFullName(OPT::strOutputFileName))+_T("_filtered"));
373371
scene.Save(baseFileName+_T(".mvs"), (ARCHIVE_TYPE)OPT::nArchiveType);
374372
scene.pointcloud.Save(baseFileName+_T(".ply"));
375-
Finalize();
376373
return EXIT_SUCCESS;
377374
}
378375
if (OPT::nExportNumViews && scene.pointcloud.IsValid()) {
@@ -388,7 +385,6 @@ int main(int argc, LPCTSTR* argv)
388385
scene.Save(baseFileName+_T(".mvs"), (ARCHIVE_TYPE)OPT::nArchiveType);
389386
scene.pointcloud.Save(baseFileName+_T(".ply"));
390387
}
391-
Finalize();
392388
return EXIT_SUCCESS;
393389
}
394390
if (OPT::fEstimateScale > 0 && !scene.pointcloud.IsEmpty() && !scene.images.empty()) {
@@ -402,35 +398,36 @@ int main(int argc, LPCTSTR* argv)
402398
}
403399
const String baseFileName(MAKE_PATH_SAFE(Util::getFileFullName(OPT::strOutputFileName)));
404400
scene.pointcloud.SaveWithScale(baseFileName+_T("_scale.ply"), scene.images, OPT::fEstimateScale);
405-
Finalize();
406401
return EXIT_SUCCESS;
407402
}
408-
if ((ARCHIVE_TYPE)OPT::nArchiveType != ARCHIVE_MVS) {
403+
PointCloud sparsePointCloud;
404+
if ((ARCHIVE_TYPE)OPT::nArchiveType != ARCHIVE_MVS || sceneType == Scene::SCENE_INTERFACE) {
409405
#if TD_VERBOSE != TD_VERBOSE_OFF
410406
if (VERBOSITY_LEVEL > 1 && !scene.pointcloud.IsEmpty())
411407
scene.pointcloud.PrintStatistics(scene.images.data(), &scene.obb);
412408
#endif
409+
if ((ARCHIVE_TYPE)OPT::nArchiveType == ARCHIVE_MVS)
410+
sparsePointCloud = scene.pointcloud;
413411
TD_TIMER_START();
414412
if (!scene.DenseReconstruction(OPT::nFusionMode, OPT::bCrop2ROI, OPT::fBorderROI)) {
415413
if (ABS(OPT::nFusionMode) != 1)
416414
return EXIT_FAILURE;
417415
VERBOSE("Depth-maps estimated (%s)", TD_TIMER_GET_FMT().c_str());
418-
Finalize();
419416
return EXIT_SUCCESS;
420417
}
421418
VERBOSE("Densifying point-cloud completed: %u points (%s)", scene.pointcloud.GetSize(), TD_TIMER_GET_FMT().c_str());
422419
}
423420

424421
// save the final point-cloud
425422
const String baseFileName(MAKE_PATH_SAFE(Util::getFileFullName(OPT::strOutputFileName)));
426-
scene.Save(baseFileName+_T(".mvs"), (ARCHIVE_TYPE)OPT::nArchiveType);
427-
scene.pointcloud.Save(baseFileName+_T(".ply"));
423+
scene.pointcloud.Save(baseFileName+_T(".ply"), (ARCHIVE_TYPE)OPT::nArchiveType == ARCHIVE_MVS);
428424
#if TD_VERBOSE != TD_VERBOSE_OFF
429425
if (VERBOSITY_LEVEL > 2)
430426
scene.ExportCamerasMLP(baseFileName+_T(".mlp"), baseFileName+_T(".ply"));
431427
#endif
432-
433-
Finalize();
428+
if ((ARCHIVE_TYPE)OPT::nArchiveType == ARCHIVE_MVS)
429+
scene.pointcloud.Swap(sparsePointCloud);
430+
scene.Save(baseFileName+_T(".mvs"), (ARCHIVE_TYPE)OPT::nArchiveType);
434431
return EXIT_SUCCESS;
435432
}
436433
/*----------------------------------------------------------------*/

0 commit comments

Comments
 (0)