diff --git a/CMakeLists.txt b/CMakeLists.txt index 920e4c312..87534d7e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,6 +109,9 @@ if(OpenMVS_USE_OPENGL) endif() if(OpenMVS_USE_CUDA) + if(POLICY CMP0146) + cmake_policy(SET CMP0146 NEW) + endif() FIND_PACKAGE(CUDA) if(CUDA_FOUND) ENABLE_LANGUAGE(CUDA) diff --git a/apps/DensifyPointCloud/DensifyPointCloud.cpp b/apps/DensifyPointCloud/DensifyPointCloud.cpp index f314c7736..757debefe 100644 --- a/apps/DensifyPointCloud/DensifyPointCloud.cpp +++ b/apps/DensifyPointCloud/DensifyPointCloud.cpp @@ -160,12 +160,12 @@ bool Application::Initialize(size_t argc, LPCTSTR* argv) ("postprocess-dmaps", boost::program_options::value(&nOptimize)->default_value(7), "flags used to filter the depth-maps after estimation (0 - disabled, 1 - remove-speckles, 2 - fill-gaps, 4 - adjust-filter)") ("filter-point-cloud", boost::program_options::value(&OPT::thFilterPointCloud)->default_value(0), "filter dense point-cloud based on visibility (0 - disabled)") ("export-number-views", boost::program_options::value(&OPT::nExportNumViews)->default_value(0), "export points with >= number of views (0 - disabled, <0 - save MVS project too)") - ("roi-border", boost::program_options::value(&OPT::fBorderROI)->default_value(0), "add a border to the region-of-interest when cropping the scene (0 - disabled, >0 - percentage, <0 - absolute)") - ("estimate-roi", boost::program_options::value(&OPT::nEstimateROI)->default_value(2), "estimate and set region-of-interest (0 - disabled, 1 - enabled, 2 - adaptive)") - ("crop-to-roi", boost::program_options::value(&OPT::bCrop2ROI)->default_value(true), "crop scene using the region-of-interest") - ("remove-dmaps", boost::program_options::value(&bRemoveDmaps)->default_value(false), "remove depth-maps after fusion") + ("roi-border", boost::program_options::value(&OPT::fBorderROI)->default_value(0), "add a border to the region-of-interest when cropping the scene (0 - disabled, >0 - percentage, <0 - absolute)") + ("estimate-roi", boost::program_options::value(&OPT::nEstimateROI)->default_value(2), "estimate and set region-of-interest (0 - disabled, 1 - enabled, 2 - adaptive)") + ("crop-to-roi", boost::program_options::value(&OPT::bCrop2ROI)->default_value(true), "crop scene using the region-of-interest") + ("remove-dmaps", boost::program_options::value(&bRemoveDmaps)->default_value(false), "remove depth-maps after fusion") ("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)") - ; + ; // hidden options, allowed both on command line and // in config file, but will not be shown to the user diff --git a/apps/InterfaceCOLMAP/InterfaceCOLMAP.cpp b/apps/InterfaceCOLMAP/InterfaceCOLMAP.cpp index 571c5d1e7..d9ff4489c 100644 --- a/apps/InterfaceCOLMAP/InterfaceCOLMAP.cpp +++ b/apps/InterfaceCOLMAP/InterfaceCOLMAP.cpp @@ -294,6 +294,7 @@ struct Camera { in >> ID >> model >> width >> height; if (in.fail()) return false; + ASSERT(ID > 0); --ID; if (model != _T("PINHOLE")) return false; @@ -313,10 +314,12 @@ struct Camera { numCameras = ReadBinaryLittleEndian(&stream); } - ID = ReadBinaryLittleEndian(&stream)-1; + ID = ReadBinaryLittleEndian(&stream); model = mapCameraModel[ReadBinaryLittleEndian(&stream)]; width = (uint32_t)ReadBinaryLittleEndian(&stream); height = (uint32_t)ReadBinaryLittleEndian(&stream); + ASSERT(ID > 0); + --ID; if (model != _T("PINHOLE")) return false; params.resize(4); @@ -398,6 +401,7 @@ struct Image { >> idCamera >> name; if (in.fail()) return false; + ASSERT(ID > 0 && idCamera > 0); --ID; --idCamera; Util::ensureValidPath(name); if (!NextLine(stream, in, false)) @@ -408,6 +412,7 @@ struct Image { in >> proj.p(0) >> proj.p(1) >> (int&)proj.idPoint; if (in.fail()) break; + ASSERT(proj.idPoint > 0); --proj.idPoint; projs.emplace_back(proj); } @@ -425,7 +430,7 @@ struct Image { numRegImages = ReadBinaryLittleEndian(&stream); } - ID = ReadBinaryLittleEndian(&stream)-1; + ID = ReadBinaryLittleEndian(&stream); q.w() = ReadBinaryLittleEndian(&stream); q.x() = ReadBinaryLittleEndian(&stream); q.y() = ReadBinaryLittleEndian(&stream); @@ -433,7 +438,9 @@ struct Image { t(0) = ReadBinaryLittleEndian(&stream); t(1) = ReadBinaryLittleEndian(&stream); t(2) = ReadBinaryLittleEndian(&stream); - idCamera = ReadBinaryLittleEndian(&stream)-1; + idCamera = ReadBinaryLittleEndian(&stream); + ASSERT(ID > 0 && idCamera > 0); + --ID; --idCamera; name = ""; while (true) { @@ -451,7 +458,9 @@ struct Image { Proj proj; proj.p(0) = (float)ReadBinaryLittleEndian(&stream); proj.p(1) = (float)ReadBinaryLittleEndian(&stream); - proj.idPoint = (uint32_t)ReadBinaryLittleEndian(&stream)-1; + proj.idPoint = (uint32_t)ReadBinaryLittleEndian(&stream); + ASSERT(proj.idPoint > 0); + --proj.idPoint; projs.emplace_back(proj); } return true; @@ -549,6 +558,7 @@ struct Point { c.z = CLAMP(r,0,255); if (in.fail()) return false; + ASSERT(ID > 0); --ID; tracks.clear(); while (true) { @@ -556,6 +566,7 @@ struct Point { in >> track.idImage >> track.idProj; if (in.fail()) break; + ASSERT(track.idImage > 0 && track.idProj > 0); --track.idImage; --track.idProj; tracks.emplace_back(track); } @@ -574,7 +585,7 @@ struct Point { } int r,g,b; - ID = (uint32_t)ReadBinaryLittleEndian(&stream)-1; + ID = (uint32_t)ReadBinaryLittleEndian(&stream); p.x = (float)ReadBinaryLittleEndian(&stream); p.y = (float)ReadBinaryLittleEndian(&stream); p.z = (float)ReadBinaryLittleEndian(&stream); @@ -585,15 +596,19 @@ struct Point { c.x = CLAMP(b,0,255); c.y = CLAMP(g,0,255); c.z = CLAMP(r,0,255); - + ASSERT(ID > 0); + --ID; + const size_t trackLength = ReadBinaryLittleEndian(&stream); tracks.clear(); for (size_t j = 0; j < trackLength; ++j) { Track track; - track.idImage = ReadBinaryLittleEndian(&stream)-1; - track.idProj = ReadBinaryLittleEndian(&stream)-1; + track.idImage = ReadBinaryLittleEndian(&stream); + track.idProj = ReadBinaryLittleEndian(&stream); + ASSERT(track.idImage > 0 && track.idProj > 0); + --track.idImage; --track.idProj; tracks.emplace_back(track); - } + } return !tracks.empty(); } diff --git a/libs/Common/Config.h b/libs/Common/Config.h index ead657f57..d5f7dddec 100644 --- a/libs/Common/Config.h +++ b/libs/Common/Config.h @@ -92,11 +92,11 @@ /*----------------------------------------------------------------*/ #ifdef _USRDLL #ifdef Common_EXPORTS - #define GENERAL_API EXPORT_API - #define GENERAL_TPL + #define GENERAL_API EXPORT_API + #define GENERAL_TPL #else - #define GENERAL_API IMPORT_API - #define GENERAL_TPL extern + #define GENERAL_API IMPORT_API + #define GENERAL_TPL extern #endif #else #define GENERAL_API diff --git a/libs/MVS/Camera.cpp b/libs/MVS/Camera.cpp index 17e049e4a..00bbdb791 100644 --- a/libs/MVS/Camera.cpp +++ b/libs/MVS/Camera.cpp @@ -73,6 +73,10 @@ Camera& Camera::operator= (const CameraIntern& camera) C = camera.C; return *this; } +Camera Camera::GetScaled(REAL s) const +{ + return Camera(GetScaledK(s), R, C); +} /*----------------------------------------------------------------*/ diff --git a/libs/MVS/Camera.h b/libs/MVS/Camera.h index 8c49c35a1..edb9b00d4 100644 --- a/libs/MVS/Camera.h +++ b/libs/MVS/Camera.h @@ -272,6 +272,8 @@ class MVS_API Camera : public CameraIntern Camera& operator= (const CameraIntern& camera); + Camera GetScaled(REAL s) const; // return a scaled camera + void ComposeP_RC(); // compose P from R and C only void ComposeP(); // compose P from K, R and C void DecomposeP_RC(); // decompose P in R and C, keep K unchanged diff --git a/libs/MVS/DepthMap.cpp b/libs/MVS/DepthMap.cpp index d2178b622..72df265ef 100644 --- a/libs/MVS/DepthMap.cpp +++ b/libs/MVS/DepthMap.cpp @@ -299,7 +299,7 @@ unsigned DepthData::DecRef() // - pMask: optional output mask; if defined, the mask is returned in this image instead of the BitMatrix bool DepthEstimator::ImportIgnoreMask(const Image& image0, const Image8U::Size& size, uint16_t nIgnoreMaskLabel, BitMatrix& bmask, Image8U* pMask) { - ASSERT(image0.IsValid() && !image0.image.empty()); + ASSERT(image0.IsValid()); const String maskFileName(image0.maskName.empty() ? Util::getFileFullName(image0.name)+".mask.png" : image0.maskName); Image16U mask; if (!mask.Load(maskFileName)) { diff --git a/libs/MVS/Image.h b/libs/MVS/Image.h index 6e8c46952..7b57bb5d4 100644 --- a/libs/MVS/Image.h +++ b/libs/MVS/Image.h @@ -64,7 +64,7 @@ class MVS_API Image Camera camera; // view's pose uint32_t width, height; // image size Image8U3 image; // image color pixels - ViewScoreArr neighbors; // scored neighbor images + ViewScoreArr neighbors; // scored neighbor images (image indices ordered by score) float scale; // image scale relative to the original size float avgDepth; // average depth of the points seen by this camera diff --git a/libs/MVS/Scene.cpp b/libs/MVS/Scene.cpp index 3cc319dc5..5364549b7 100644 --- a/libs/MVS/Scene.cpp +++ b/libs/MVS/Scene.cpp @@ -448,7 +448,7 @@ bool Scene::LoadViewNeighbors(const String& fileName) FOREACH(i, imageData.neighbors) { const IIndex nID(String::FromString(argv[i+1], NO_ID)); ASSERT(nID != NO_ID); - imageData.neighbors[i] = ViewScore{nID, 0, 1.f, FD2R(15.f), 0.5f, 3.f}; + imageData.neighbors[i] = ViewScore{nID, 0, 1.f, FD2R(15.f), 0.5f, 2.f+(argc-i)*0.5f}; } } diff --git a/libs/MVS/SceneDensify.cpp b/libs/MVS/SceneDensify.cpp index 0c36a2c4a..cc13747ac 100644 --- a/libs/MVS/SceneDensify.cpp +++ b/libs/MVS/SceneDensify.cpp @@ -285,7 +285,8 @@ bool DepthMapsData::SelectViews(DepthData& depthData) const float fMinScale(0.2f), fMaxScale(3.2f); const float fMinAngle(FD2R(OPTDENSE::fMinAngle)); const float fMaxAngle(FD2R(OPTDENSE::fMaxAngle)); - if (!Scene::FilterNeighborViews(depthData.neighbors, fMinArea, fMinScale, fMaxScale, fMinAngle, fMaxAngle, OPTDENSE::nMaxViews)) { + const unsigned nMaxViews(MAXF(OPTDENSE::nMaxViews, OPTDENSE::nNumViews)); + if (!Scene::FilterNeighborViews(depthData.neighbors, fMinArea, fMinScale, fMaxScale, fMinAngle, fMaxAngle, nMaxViews)) { DEBUG_EXTRA("error: reference image %3u has no good images in view", idxImage); return false; } @@ -332,8 +333,7 @@ bool DepthMapsData::InitViews(DepthData& depthData, IIndex idxNeighbor, IIndex n } else { // initialize all neighbor views too (global reconstruction is used) const float fMinScore(MAXF(depthData.neighbors.First().score*OPTDENSE::fViewMinScoreRatio, OPTDENSE::fViewMinScore)); - FOREACH(idx, depthData.neighbors) { - const ViewScore& neighbor = depthData.neighbors[idx]; + for (const ViewScore& neighbor: depthData.neighbors) { if ((numNeighbors && depthData.images.GetSize() > numNeighbors) || (neighbor.score < fMinScore)) break; diff --git a/scripts/python/MvgMvsPipeline.py b/scripts/python/MvgMvsPipeline.py index 1ef4e1a2a..870b62be9 100644 --- a/scripts/python/MvgMvsPipeline.py +++ b/scripts/python/MvgMvsPipeline.py @@ -256,7 +256,7 @@ def __init__(self): ["mapper", "--database_path", "%matches_dir%"+FOLDER_DELIM+"database.db", "--image_path", "%input_dir%", "--output_path", "%reconstruction_dir%"]], ["Model Aligner", # 15 COLMAP_BIN, - ["model_aligner", "--input_path", "%reconstruction_dir%"+FOLDER_DELIM+"0", "--database_path", "%matches_dir%"+FOLDER_DELIM+"database.db", "--output_path", "%reconstruction_dir%"+FOLDER_DELIM+"0", "--ref_is_gps=1", "--robust_alignment_max_error=2.0", "--alignment_type=enu", "--transform_path", "%reconstruction_dir%"+FOLDER_DELIM+"transform.txt"]], + ["model_aligner", "--input_path", "%reconstruction_dir%"+FOLDER_DELIM+"0", "--database_path", "%matches_dir%"+FOLDER_DELIM+"database.db", "--output_path", "%reconstruction_dir%"+FOLDER_DELIM+"0", "--ref_is_gps=1", "--alignment_max_error=2.0", "--alignment_type=enu", "--transform_path", "%reconstruction_dir%"+FOLDER_DELIM+"transform.txt"]], ["Image Undistorter", # 16 COLMAP_BIN, ["image_undistorter", "--image_path", "%input_dir%", "--input_path", "%reconstruction_dir%"+FOLDER_DELIM+"0", "--output_path", "%reconstruction_dir%"+FOLDER_DELIM+"dense", "--output_type", "COLMAP"]],