Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,12 @@ Other optional libraries can enable specific features (check "CMake Options" for
* Alembic (data I/O)
* CCTag (feature extraction/matching and localization on CPU or GPU)
* Cuda >= 11.0 (feature extraction and depth map computation)
* Magma (required for UncertaintyTE)
* Magma
* Mosek >= 6 (linear programming)
* OpenCV >= 3.4.11 (feature extraction, calibration module, video IO), >= 4.5 for colorchecker (mcc)
* OpenMP (enable multi-threading)
* PCL (Point Cloud Library) >= 1.12.1 for the registration module
* PopSift (feature extraction on GPU)
* UncertaintyTE (Uncertainty computation)
* Lemon >= 1.3
* libe57format (support reading .e57 files)
* SWIG, Python 3 and NumPy 1.26 (Python binding for AliceVision modules)
Expand Down Expand Up @@ -222,11 +221,6 @@ At the end of the cmake process, a report shows for each library which version (
Enable GPU SIFT implementation.
`-DPopSift_DIR:PATH=/path/to/popsift/install/lib/cmake/PopSift` (where PopSiftConfig.cmake can be found)

* `ALICEVISION_USE_UNCERTAINTYTE` (default: `AUTO`)
Enable Uncertainty computation.
`-DUNCERTAINTYTE_DIR:PATH=/path/to/uncertaintyTE/install/` (where the `include` and `lib` folders can be found)
`-DMAGMA_ROOT:PATH=/path/to/magma/install/` (where the `include` and `lib` folders can be found)

* `ALICEVISION_USE_OPENCV` (default: `OFF`)
Build with OpenCV.
`-DOpenCV_DIR:PATH=/path/to/opencv/install/share/OpenCV/` (where OpenCVConfig.cmake can be found)
Expand Down
38 changes: 38 additions & 0 deletions meshroom/aliceVision/ComputeUncertainty.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
__version__ = "1.0"

from meshroom.core import desc
from meshroom.core.utils import VERBOSE_LEVEL


class ComputeUncertainty(desc.AVCommandLineNode):

commandLine = "aliceVision_computeUncertainty {allParams}"
size = desc.DynamicNodeSize("input")

category = "Utils"
documentation = """ Compute solution covariance """

inputs = [
desc.File(
name="input",
label="SfMData",
description="Input SfMData file.",
value="",
),
desc.ChoiceParam(
name="verboseLevel",
label="Verbose Level",
description="Verbosity level (fatal, error, warning, info, debug, trace).",
values=VERBOSE_LEVEL,
Comment thread
servantftransperfect marked this conversation as resolved.
value="info",
),
]

outputs = [
desc.File(
name="output",
label="SfMData",
description="Path to the output SfM file.",
value="{nodeCacheFolder}/sfmData.abc",
)
]
44 changes: 16 additions & 28 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ trilean_option(ALICEVISION_USE_CCTAG "Enable CCTAG markers" AUTO)
trilean_option(ALICEVISION_USE_APRILTAG "Enable AprilTag markers" AUTO)
trilean_option(ALICEVISION_USE_POPSIFT "Enable GPU SIFT implementation" AUTO)
trilean_option(ALICEVISION_USE_ALEMBIC "Enable Alembic I/O" AUTO)
trilean_option(ALICEVISION_USE_UNCERTAINTYTE "Enable Uncertainty computation" AUTO)
trilean_option(ALICEVISION_USE_ONNX "Enable ONNX Runtime" AUTO)
option(ALICEVISION_USE_ONNX_GPU "Use CUDA with ONNX Runtime" ON)
if(APPLE)
Expand Down Expand Up @@ -217,6 +216,7 @@ set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
include(OFA/OptimizeForArchitecture)
OptimizeForArchitecture()

set(ALICEVISION_HAVE_SSE 0 CACHE BOOL "SSE2 is available" FORCE)
if (USE_SSE2 OR TARGET_ARCHITECTURE STREQUAL "native")
if (MSVC AND NOT ${CMAKE_CL_64})
Expand Down Expand Up @@ -504,6 +504,7 @@ if (ALICEVISION_BUILD_SFM)
endif()
endif()


# ==============================================================================
# CoinUtils, Clp, Osi
# ==============================================================================
Expand Down Expand Up @@ -634,31 +635,6 @@ if (NOT ALICEVISION_USE_USD STREQUAL "OFF")
endif()
endif()

# ==============================================================================
# UncertaintyTE
# ==============================================================================
# - optional, only external and enabled only if ALICEVISION_USE_UNCERTAINTYTE is ON
# ==============================================================================
set(ALICEVISION_HAVE_UNCERTAINTYTE 0)

if (ALICEVISION_BUILD_SFM)
if (NOT ALICEVISION_USE_UNCERTAINTYTE STREQUAL "OFF")
find_package(UncertaintyTE)

if (UNCERTAINTYTE_FOUND)
set(ALICEVISION_HAVE_UNCERTAINTYTE 1)
message(STATUS "UncertaintyTE found.")
elseif (ALICEVISION_USE_UNCERTAINTYTE STREQUAL "ON")
message(SEND_ERROR "Failed to find UncertaintyTE.")
endif()
endif()

if (ALICEVISION_HAVE_UNCERTAINTYTE)
include_directories(${UNCERTAINTYTE_INCLUDE_DIR})
link_directories(${UNCERTAINTYTE_LIBRARY_DIR})
endif()
endif()

# ==============================================================================
# ZLIB
# ==============================================================================
Expand Down Expand Up @@ -864,6 +840,20 @@ if (ALICEVISION_BUILD_SFM)
endif()
endif()

# ==============================================================================
# Magma
# ==============================================================================
if (ALICEVISION_BUILD_SFM)
if (ALICEVISION_HAVE_CUDA)
find_package(magma CONFIG REQUIRED)

if (TARGET magma::magma)
set(MAGMA_LIBRARIES magma::magma)
else()
message(FATAL_ERROR "MAGMA can not be found")
endif()
endif()
endif()

# ==============================================================================
# Include directories
Expand All @@ -883,7 +873,6 @@ set(ALICEVISION_INCLUDE_DIRS
${LEMON_INCLUDE_DIRS}
${EIGEN3_INCLUDE_DIRS}
${CERES_INCLUDE_DIRS}
${UNCERTAINTYTE_INCLUDE_DIRS}
${MAGMA_INCLUDE_DIRS}
${FLANN_INCLUDE_DIRS}
${LP_INCLUDE_DIRS}
Expand Down Expand Up @@ -985,7 +974,6 @@ message("** Build LIDAR part: " ${ALICEVISION_BUILD_LIDAR})
message("** Build AliceVision tests: " ${ALICEVISION_BUILD_TESTS})
message("** Build AliceVision documentation: " ${ALICEVISION_HAVE_DOC})
message("** Build AliceVision+OpenCV samples programs: " ${ALICEVISION_HAVE_OPENCV})
message("** Build UncertaintyTE: " ${ALICEVISION_HAVE_UNCERTAINTYTE})
message("** Build MeshSDFilter: " ${ALICEVISION_HAVE_MESHSDFILTER})
message("** Build Alembic exporter: " ${ALICEVISION_HAVE_ALEMBIC})
message("** Build SWIG Python binding: " ${ALICEVISION_BUILD_SWIG_BINDING})
Expand Down
3 changes: 3 additions & 0 deletions src/aliceVision/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ if (ALICEVISION_BUILD_SFM)
add_subdirectory(track)
add_subdirectory(voctree)
add_subdirectory(calibration)
if (ALICEVISION_HAVE_CUDA)
add_subdirectory(uncertainty)
endif()
if (ALICEVISION_HAVE_OPENCV)
add_subdirectory(imageMasking)
add_subdirectory(keyframe)
Expand Down
2 changes: 2 additions & 0 deletions src/aliceVision/sfm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ set(sfm_files_headers
utils/poseNoise.hpp
utils/preprocess.hpp
utils/syntheticScene.hpp
utils/gauge.hpp
LocalBundleAdjustmentGraph.hpp
FrustumFilter.hpp
filters.hpp
Expand Down Expand Up @@ -96,6 +97,7 @@ set(sfm_files_sources
utils/poseNoise.cpp
utils/preprocess.cpp
utils/syntheticScene.cpp
utils/gauge.cpp
LocalBundleAdjustmentGraph.cpp
FrustumFilter.cpp
generateReport.cpp
Expand Down
42 changes: 30 additions & 12 deletions src/aliceVision/sfm/bundle/BundleAdjustmentCeres.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,6 @@ void BundleAdjustmentCeres::addExtrinsicsToProblem(const sfmData::SfMData& sfmDa
double* poseBlockPtr = poseBlock.data();
problem.AddParameterBlock(poseBlockPtr, 6);

// add pose parameter to the all parameters blocks pointers list
_allParametersBlocks.push_back(poseBlockPtr);

// keep the camera extrinsics constants
if (cameraPose.isLocked() || isConstant || (!refineTranslation && !refineRotation))
{
Expand Down Expand Up @@ -392,9 +389,6 @@ void BundleAdjustmentCeres::addIntrinsicsToProblem(const sfmData::SfMData& sfmDa
double* intrinsicBlockPtr = intrinsicBlock.data();
problem.AddParameterBlock(intrinsicBlockPtr, intrinsicBlock.size());

// add intrinsic parameter to the all parameters blocks pointers list
_allParametersBlocks.push_back(intrinsicBlockPtr);

// keep the camera intrinsic constant
if (intrinsicPtr->isLocked() || !refineIntrinsics || intrinsicPtr->getState() == EEstimatorParameterState::CONSTANT)
{
Expand Down Expand Up @@ -580,9 +574,6 @@ void BundleAdjustmentCeres::addLandmarksToProblem(const sfmData::SfMData& sfmDat

double* fakeDistortionBlockPtr = &_fakeDistortionBlock;

// add landmark parameter to the all parameters blocks pointers list
_allParametersBlocks.push_back(landmarkBlockPtr);

// iterate over 2D observation associated to the 3D landmark
for (const auto& [viewId, observation] : landmark.getObservations())
{
Expand Down Expand Up @@ -1083,7 +1074,6 @@ void BundleAdjustmentCeres::resetProblem()
{
_statistics = Statistics();

_allParametersBlocks.clear();
_posesBlocks.clear();
_intrinsicsBlocks.clear();
_landmarksBlocks.clear();
Expand Down Expand Up @@ -1220,21 +1210,49 @@ void BundleAdjustmentCeres::updateFromSolution(sfmData::SfMData& sfmData, ERefin
}
}

void BundleAdjustmentCeres::createJacobian(const sfmData::SfMData& sfmData, ERefineOptions refineOptions, ceres::CRSMatrix& jacobian)
void BundleAdjustmentCeres::createJacobian(const sfmData::SfMData& sfmData, ceres::CRSMatrix& jacobian, std::map<IndexT, size_t> & poseToPosition, std::map<IndexT, size_t> & landmarkToPosition)
{
std::vector<ceres::ResidualBlockId> landmarksBlockIds;
std::vector<ceres::ResidualBlockId> temporalConstraintBlockIds;

BundleAdjustment::ERefineOptions refineOptions = BundleAdjustment::REFINE_ROTATION | BundleAdjustment::REFINE_TRANSLATION | BundleAdjustment::REFINE_STRUCTURE;

// create problem
ceres::Problem::Options problemOptions;
problemOptions.loss_function_ownership = ceres::DO_NOT_TAKE_OWNERSHIP;
ceres::Problem problem(problemOptions);
createProblem(sfmData, refineOptions, problem, landmarksBlockIds, temporalConstraintBlockIds);


std::vector<double*> allParametersBlocks;
for (auto & [id, ptr] : _posesBlocks)
{
if (problem.IsParameterBlockConstant(ptr.data()))
{
continue;
}

poseToPosition[id] = allParametersBlocks.size();
allParametersBlocks.push_back(ptr.data());
}

for (auto & [id, ptr] : _landmarksBlocks)
{
if (problem.IsParameterBlockConstant(ptr.data()))
{
continue;
}

landmarkToPosition[id] = allParametersBlocks.size();
allParametersBlocks.push_back(ptr.data());
}



// configure Jacobian engine
double cost = 0.0;
ceres::Problem::EvaluateOptions evalOpt;
evalOpt.parameter_blocks = _allParametersBlocks;
evalOpt.parameter_blocks = allParametersBlocks;
evalOpt.num_threads = 8;
evalOpt.apply_loss_function = true;

Expand Down
11 changes: 4 additions & 7 deletions src/aliceVision/sfm/bundle/BundleAdjustmentCeres.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,16 @@
BundleAdjustmentCeres(const CeresOptions& options = CeresOptions(), int minNbImagesToRefineOpticalCenter = 3)
: _ceresOptions(options),
_minNbImagesToRefineOpticalCenter(minNbImagesToRefineOpticalCenter)
{}

Check failure on line 121 in src/aliceVision/sfm/bundle/BundleAdjustmentCeres.hpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

2 uninitialized fields at the end of the constructor call

See more on https://sonarcloud.io/project/issues?id=alicevision_AliceVision&issues=AZ34OY2MKrubnQCUZIBn&open=AZ34OY2MKrubnQCUZIBn&pullRequest=2121

/**
* @brief Create a jacobian CRSMatrix
* @param[in] sfmData The input SfMData contains all the information about the reconstruction
* @param[in] refineOptions The chosen refine flag
* @param[out] jacobian The jacobian CSRMatrix
* @param[out] poseToPosition a map which gives the parameter block index of a pose Id in the jacobian
* @param[out] landmarkToPosition a map which gives the parameter block index of a landmark Id in the jacobian
*/
void createJacobian(const sfmData::SfMData& sfmData, ERefineOptions refineOptions, ceres::CRSMatrix& jacobian);
void createJacobian(const sfmData::SfMData& sfmData, ceres::CRSMatrix& jacobian, std::map<IndexT, size_t> & poseToPosition, std::map<IndexT, size_t> & landmarkToPosition);

/**
* @brief Perform a Bundle Adjustment on the SfM scene with refinement of the requested parameters
Expand Down Expand Up @@ -258,13 +259,9 @@

// data wrappers for refinement

/// all parameters blocks pointers
std::vector<double*> _allParametersBlocks;
/// poses blocks wrapper
/// block: ceres angleAxis(3) + translation(3)
std::map<IndexT, std::array<double, 6>> _posesBlocks; // TODO : maybe we can use boost::flat_map instead of std::map ?
/// intrinsics blocks wrapper
/// block: intrinsics params
std::map<IndexT, std::array<double, 6>> _posesBlocks;
std::map<IndexT, std::vector<double>> _intrinsicsBlocks;
std::map<IndexT, std::vector<double>> _distortionsBlocks;
std::map<IndexT, std::shared_ptr<camera::IntrinsicBase>> _intrinsicObjects;
Expand Down
43 changes: 43 additions & 0 deletions src/aliceVision/sfm/sfmStatistics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,5 +428,48 @@ void computeObservationsLengthsPerView(const sfmData::SfMData& sfmData,
}
}

void computeResidualsMedianPerView(const sfmData::SfMData& sfmData, const std::set<IndexT>& specificViews, std::map<IndexT, double> & medianPerView)
{
std::set<IndexT> validViews = sfmData.getValidViews();

// Update valid views by intersecting with specificViews
if (!specificViews.empty())
{
std::set<IndexT> filteredValidViews;
std::set_intersection(validViews.begin(), validViews.end(), specificViews.begin(), specificViews.end(), std::inserter(filteredValidViews, filteredValidViews.begin()));
validViews = std::move(filteredValidViews);
}


std::unordered_map<IndexT, std::vector<double>> residualsPerView;
for (const auto & [_, landmark] : sfmData.getLandmarks())
{
const aliceVision::sfmData::Observations& observations = landmark.getObservations();
for (const auto & [idView, observation] : observations)
{
if (validViews.count(idView) == 0)
{
continue;
}

const sfmData::View& view = sfmData.getView(idView);
const aliceVision::geometry::Pose3 pose = sfmData.getPose(view).getTransform();
const aliceVision::camera::IntrinsicBase & intrinsic = sfmData.getIntrinsic(view.getIntrinsicId());
const Vec2 residual = intrinsic.residual(pose, landmark.getX().homogeneous(), observation.getCoordinates());

residualsPerView[idView].push_back(residual.norm());
}
}

for (auto & [idView, vec]: residualsPerView)
{
const auto medianIt2 = vec.begin() + vec.size() / 2;
std::nth_element(vec.begin(), medianIt2, vec.end());
const double med2 = *medianIt2;

ALICEVISION_LOG_ERROR(med2);
}
}

} // namespace sfm
} // namespace aliceVision
4 changes: 4 additions & 0 deletions src/aliceVision/sfm/sfmStatistics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,5 +119,9 @@ void computeObservationsLengthsPerView(const sfmData::SfMData& sfmData,
std::vector<double>& nbResidualsPerViewFirstQuartile,
std::vector<double>& nbResidualsPerViewThirdQuartile);

void computeResidualsMedianPerView(const sfmData::SfMData& sfmData,
const std::set<IndexT>& specificViews,
std::map<IndexT, double> & medianPerView);

} // namespace sfm
} // namespace aliceVision
Loading
Loading