diff --git a/.travis.yml b/.travis.yml index 178768661c..af13b26bf4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -104,7 +104,7 @@ script: fi cd $GT_TEST_SOURCE git checkout 1828a5076ccca86fd523c92a768f1d518dfdbb91 # checkout a specific commit to ensure repeatability - python EvaluationLauncher.py -s "$ALICEVISION_BUILD/$BUILD_SYSTEM-$BUILD_PROCESSOR" -i Benchmarking_Camera_Calibration_2008/ -o ${GT_TEST_OUTPUT} -r ${GT_TEST_RESULTS} --limit 3 + python EvaluationLauncher.py -s "$ALICEVISION_BUILD/$BUILD_SYSTEM-$BUILD_PROCESSOR" -i Benchmarking_Camera_Calibration_2008/ -o ${GT_TEST_OUTPUT} -r ${GT_TEST_RESULTS} -v --limit 3 cat ${GT_TEST_RESULTS} # Return to root and remove GT huge files to avoid cache problems cd $TRAVIS_BUILD_DIR diff --git a/src/aliceVision/camera/CMakeLists.txt b/src/aliceVision/camera/CMakeLists.txt index fea1330213..f82ac9c5df 100644 --- a/src/aliceVision/camera/CMakeLists.txt +++ b/src/aliceVision/camera/CMakeLists.txt @@ -1,24 +1,23 @@ # Headers set(camera_files_headers - camera.hpp - cameraCommon.hpp - cameraUndistortImage.hpp - IntrinsicBase.hpp - IntrinsicInitMode.hpp - Pinhole.hpp - PinholeBrown.hpp - PinholeFisheye.hpp - PinholeFisheye1.hpp - PinholeRadial.hpp + camera.hpp + cameraCommon.hpp + cameraUndistortImage.hpp + IntrinsicBase.hpp + IntrinsicInitMode.hpp + Pinhole.hpp + PinholeBrown.hpp + PinholeFisheye.hpp + PinholeFisheye1.hpp + PinholeRadial.hpp ) alicevision_add_interface(aliceVision_camera SOURCES ${camera_files_headers} LINKS + aliceVision_numeric aliceVision_geometry - aliceVision_multiview aliceVision_image - aliceVision_numeric aliceVision_stl aliceVision_system ) diff --git a/src/aliceVision/camera/Pinhole.hpp b/src/aliceVision/camera/Pinhole.hpp index ae0ad38997..79b681d95e 100644 --- a/src/aliceVision/camera/Pinhole.hpp +++ b/src/aliceVision/camera/Pinhole.hpp @@ -8,10 +8,10 @@ #pragma once #include +#include +#include #include #include -#include -#include #include #include diff --git a/src/aliceVision/geometry/frustumIntersection_test.cpp b/src/aliceVision/geometry/frustumIntersection_test.cpp index 903fd129a4..3c0c0e387b 100644 --- a/src/aliceVision/geometry/frustumIntersection_test.cpp +++ b/src/aliceVision/geometry/frustumIntersection_test.cpp @@ -9,7 +9,7 @@ #include "aliceVision/geometry/Frustum.hpp" #include "aliceVision/multiview/NViewDataSet.hpp" -#include "aliceVision/multiview/projection.hpp" +#include "aliceVision/numeric/projection.hpp" #include diff --git a/src/aliceVision/geometry/rigidTransformation3D.cpp b/src/aliceVision/geometry/rigidTransformation3D.cpp index 1c99a0c6f7..f96e260321 100644 --- a/src/aliceVision/geometry/rigidTransformation3D.cpp +++ b/src/aliceVision/geometry/rigidTransformation3D.cpp @@ -147,7 +147,7 @@ bool ACRansac_FindRTS(const Mat& x1, const KernelT kernel = KernelT(x1, x2); - multiview::MatrixModel RTS; + robustEstimation::MatrixModel RTS; // robust estimation of the Projection matrix and its precision const std::pair ACRansacOut = robustEstimation::ACRANSAC(kernel, vec_inliers, numIterations, &RTS, dPrecision); diff --git a/src/aliceVision/geometry/rigidTransformation3D.hpp b/src/aliceVision/geometry/rigidTransformation3D.hpp index 4671d05a98..9661c334bc 100644 --- a/src/aliceVision/geometry/rigidTransformation3D.hpp +++ b/src/aliceVision/geometry/rigidTransformation3D.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include namespace aliceVision { namespace geometry { @@ -150,7 +150,7 @@ void Refine_RTS(const Mat &x1, /** * @brief the Solver to use for ACRansac */ -class RTSSolver : public multiview::ISolver> +class RTSSolver : public robustEstimation::ISolver> { public: @@ -173,18 +173,18 @@ class RTSSolver : public multiview::ISolver> } // solve the RTS problem - inline void solve(const Mat& pts1, const Mat& pts2, std::vector>& models) const + inline void solve(const Mat& pts1, const Mat& pts2, std::vector>& models) const { - models.push_back( multiview::MatrixModel(Eigen::umeyama(pts1, pts2, true)) ); + models.push_back( robustEstimation::MatrixModel(Eigen::umeyama(pts1, pts2, true)) ); } - void solve(const Mat& x1, const Mat& x2, std::vector>& models, const std::vector& weights) const override + void solve(const Mat& x1, const Mat& x2, std::vector>& models, const std::vector& weights) const override { throw std::logic_error("RTSSolver does not support problem solving with weights."); } // compute the residual of the transformation - inline double error(const multiview::MatrixModel& RTS, const Vec3& pt1, const Vec3& pt2) + inline double error(const robustEstimation::MatrixModel& RTS, const Vec3& pt1, const Vec3& pt2) { const Mat4& matrixRTS = RTS.getMatrix(); const Mat3& RS = matrixRTS.topLeftCorner<3, 3>(); @@ -200,7 +200,7 @@ class RTSSolver : public multiview::ISolver> struct RTSSquaredResidualError { // return the squared error - inline double error(const multiview::MatrixModel& RTS, const Vec3& pt1, const Vec3& pt2) const + inline double error(const robustEstimation::MatrixModel& RTS, const Vec3& pt1, const Vec3& pt2) const { const Mat4& matrixRTS = RTS.getMatrix(); const Mat3& RS = matrixRTS.topLeftCorner<3, 3>(); @@ -212,7 +212,7 @@ struct RTSSquaredResidualError /** * @brief The kernel to use for ACRansac */ -template > +template > class ACKernelAdaptor_PointsRegistrationSRT { public: diff --git a/src/aliceVision/geometry/rigidTransformation3D_test.cpp b/src/aliceVision/geometry/rigidTransformation3D_test.cpp index e1796a3389..ff4c384711 100644 --- a/src/aliceVision/geometry/rigidTransformation3D_test.cpp +++ b/src/aliceVision/geometry/rigidTransformation3D_test.cpp @@ -166,7 +166,7 @@ BOOST_AUTO_TEST_CASE(SRT_precision_ACRANSAC_noNoise) Mat4 RTS; composeRTS(Sc, tc, Rc, RTS); - multiview::MatrixModel modelRTS(RTS); + robustEstimation::MatrixModel modelRTS(RTS); geometry::RTSSquaredResidualError errorEstimator; for(std::size_t i = 0; i < nbPoints; ++i) @@ -237,7 +237,7 @@ BOOST_AUTO_TEST_CASE(SRT_precision_ACRANSAC_noiseByShuffling) Mat4 RTS; composeRTS(Sc, tc, Rc, RTS); - multiview::MatrixModel modelRTS(RTS); + robustEstimation::MatrixModel modelRTS(RTS); geometry::RTSSquaredResidualError errorEstimator; // check the residuals for the inliers diff --git a/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_resection_robust_test.cpp b/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_resection_robust_test.cpp index d53dca3aa5..32d8061a7c 100644 --- a/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_resection_robust_test.cpp +++ b/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_resection_robust_test.cpp @@ -10,7 +10,7 @@ #include "aliceVision/linearProgramming/lInfinityCV/resection_kernel.hpp" #include "aliceVision/robustEstimation/maxConsensus.hpp" #include "aliceVision/robustEstimation/ScoreEvaluator.hpp" -#include "aliceVision/multiview/projection.hpp" +#include "aliceVision/numeric/projection.hpp" #include #include @@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(Resection_L_Infinity_Robust_OutlierFree) { KernelType kernel(pt2D, pt3D); ScoreEvaluator scorer(2*Square(0.6)); - multiview::Mat34Model P = maxConsensus(kernel, scorer, nullptr, 128); + robustEstimation::Mat34Model P = maxConsensus(kernel, scorer, nullptr, 128); // Check that Projection matrix is near to the GT : Mat34 GT_ProjectionMatrix = d.P(nResectionCameraIndex).array() @@ -98,7 +98,7 @@ BOOST_AUTO_TEST_CASE(Resection_L_Infinity_Robust_OneOutlier) const Mat & pt3D = d2._X; KernelType kernel(pt2D, pt3D); ScoreEvaluator scorer(Square(0.1)); //Highly intolerant for the test - multiview::Mat34Model P = maxConsensus(kernel, scorer, nullptr, 128); + robustEstimation::Mat34Model P = maxConsensus(kernel, scorer, nullptr, 128); // Check that Projection matrix is near to the GT : Mat34 GT_ProjectionMatrix = d.P(nResectionCameraIndex).array() diff --git a/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_resection_test.cpp b/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_resection_test.cpp index d755302f07..1cdee34439 100644 --- a/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_resection_test.cpp +++ b/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_resection_test.cpp @@ -9,7 +9,7 @@ #include #include "aliceVision/multiview/NViewDataSet.hpp" -#include "aliceVision/multiview/projection.hpp" +#include "aliceVision/numeric/projection.hpp" #include #include "aliceVision/linearProgramming/ISolver.hpp" diff --git a/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_tijsAndXis_outlier_test.cpp b/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_tijsAndXis_outlier_test.cpp index 9bb3ea1b45..3e55260337 100644 --- a/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_tijsAndXis_outlier_test.cpp +++ b/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_tijsAndXis_outlier_test.cpp @@ -10,7 +10,7 @@ #include "aliceVision/numeric/numeric.hpp" #include -#include "aliceVision/multiview/projection.hpp" +#include "aliceVision/numeric/projection.hpp" #include "aliceVision/linearProgramming/ISolver.hpp" #include "aliceVision/linearProgramming/OSIXSolver.hpp" diff --git a/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_tijsAndXis_test.cpp b/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_tijsAndXis_test.cpp index c629ab70a0..2213ff7ded 100644 --- a/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_tijsAndXis_test.cpp +++ b/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_tijsAndXis_test.cpp @@ -8,7 +8,7 @@ #include "aliceVision/multiview/NViewDataSet.hpp" #include "aliceVision/numeric/numeric.hpp" #include -#include "aliceVision/multiview/projection.hpp" +#include "aliceVision/numeric/projection.hpp" #include "aliceVision/linearProgramming/ISolver.hpp" #include "aliceVision/linearProgramming/OSIXSolver.hpp" #if ALICEVISION_IS_DEFINED(ALICEVISION_HAVE_MOSEK) diff --git a/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_triangulation_test.cpp b/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_triangulation_test.cpp index d69d61d1ce..a7ae0ed3e7 100644 --- a/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_triangulation_test.cpp +++ b/src/aliceVision/linearProgramming/lInfinityCV/lInftyCV_triangulation_test.cpp @@ -12,7 +12,7 @@ #include "aliceVision/numeric/numeric.hpp" #include -#include "aliceVision/multiview/projection.hpp" +#include "aliceVision/numeric/projection.hpp" #include "aliceVision/linearProgramming/ISolver.hpp" #include "aliceVision/linearProgramming/OSIXSolver.hpp" diff --git a/src/aliceVision/linearProgramming/lInfinityCV/resection_kernel.cpp b/src/aliceVision/linearProgramming/lInfinityCV/resection_kernel.cpp index 72a731b6ce..9c3ff48321 100644 --- a/src/aliceVision/linearProgramming/lInfinityCV/resection_kernel.cpp +++ b/src/aliceVision/linearProgramming/lInfinityCV/resection_kernel.cpp @@ -28,7 +28,7 @@ void translate(const Mat3X & X, const Vec3 & vecTranslation, } } -void l1SixPointResectionSolver::solve(const Mat &pt2D, const Mat &pt3d, std::vector& Ps) const +void l1SixPointResectionSolver::solve(const Mat &pt2D, const Mat &pt3d, std::vector& Ps) const { assert(2 == pt2D.rows()); assert(3 == pt3d.rows()); diff --git a/src/aliceVision/linearProgramming/lInfinityCV/resection_kernel.hpp b/src/aliceVision/linearProgramming/lInfinityCV/resection_kernel.hpp index 8ffed2c1ee..dd67f40245 100644 --- a/src/aliceVision/linearProgramming/lInfinityCV/resection_kernel.hpp +++ b/src/aliceVision/linearProgramming/lInfinityCV/resection_kernel.hpp @@ -7,8 +7,8 @@ #pragma once -#include -#include +#include +#include #include #include @@ -24,7 +24,7 @@ namespace kernel { * Rely on L1 Resection algorithm. * Work from 6 to N points. */ -struct l1SixPointResectionSolver : public multiview::ISolver +struct l1SixPointResectionSolver : public robustEstimation::ISolver { /** * @brief Return the minimum number of required samples @@ -48,7 +48,7 @@ struct l1SixPointResectionSolver : public multiview::ISolver& P) const; + void solve(const Mat& pt2D, const Mat& pt3D, std::vector& P) const; /** * @brief Solve the problem. @@ -57,7 +57,7 @@ struct l1SixPointResectionSolver : public multiview::ISolver& models, const std::vector& weights) const override + void solve(const Mat& x1, const Mat& x2, std::vector& models, const std::vector& weights) const override { throw std::logic_error("l1SixPointResectionSolver does not support problem solving with weights."); } @@ -67,7 +67,7 @@ struct l1SixPointResectionSolver : public multiview::ISolver l1PoseResectionKernel; +typedef robustEstimation::FittingKernel l1PoseResectionKernel; } // namespace kernel } // namespace lInfinityCV diff --git a/src/aliceVision/linearProgramming/lInfinityCV/triplet_tijsAndXis_kernel.hpp b/src/aliceVision/linearProgramming/lInfinityCV/triplet_tijsAndXis_kernel.hpp index 9808575650..edc9e5656f 100644 --- a/src/aliceVision/linearProgramming/lInfinityCV/triplet_tijsAndXis_kernel.hpp +++ b/src/aliceVision/linearProgramming/lInfinityCV/triplet_tijsAndXis_kernel.hpp @@ -10,8 +10,8 @@ #include "aliceVision/numeric/numeric.hpp" #include "aliceVision/config.hpp" -#include "aliceVision/multiview/projection.hpp" -#include "aliceVision/multiview/conditioning.hpp" +#include "aliceVision/numeric/projection.hpp" +#include "aliceVision/robustEstimation/conditioning.hpp" #include "aliceVision/multiview/triangulation/Triangulation.hpp" // Linear programming solver(s) diff --git a/src/aliceVision/localization/VoctreeLocalizer.cpp b/src/aliceVision/localization/VoctreeLocalizer.cpp index a0fdd855b7..59e7361d87 100644 --- a/src/aliceVision/localization/VoctreeLocalizer.cpp +++ b/src/aliceVision/localization/VoctreeLocalizer.cpp @@ -1135,9 +1135,9 @@ bool VoctreeLocalizer::robustMatching(matching::RegionsDatabaseMatcherPerDesc & // So we ignore the previous matches and recompute all matches. out_featureMatches.clear(); - multiview::Mat3Model model(geometricFilter.m_F); + robustEstimation::Mat3Model model(geometricFilter.m_F); - robustEstimation::guidedMatching( + robustEstimation::guidedMatching( model, queryIntrinsicsBase, // camera::IntrinsicBase of the matched image matchers.getDatabaseRegionsPerDesc(), // feature::Regions diff --git a/src/aliceVision/localization/rigResection.cpp b/src/aliceVision/localization/rigResection.cpp index c286711dcf..f64cdd5590 100644 --- a/src/aliceVision/localization/rigResection.cpp +++ b/src/aliceVision/localization/rigResection.cpp @@ -6,7 +6,6 @@ #include "rigResection.hpp" #include -#include #include #if ALICEVISION_IS_DEFINED(ALICEVISION_HAVE_OPENGV) diff --git a/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_E_AC.hpp b/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_E_AC.hpp index 0f6238ee31..2129d1481d 100644 --- a/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_E_AC.hpp +++ b/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_E_AC.hpp @@ -10,12 +10,12 @@ #include #include #include -#include -#include -#include #include -#include #include +#include +#include +#include +#include #include #include @@ -46,9 +46,6 @@ struct GeometricFilterMatrix_E_AC : public GeometricFilterMatrix const matching::MatchesPerDescType& putativeMatchesPerType, matching::MatchesPerDescType& out_geometricInliersPerType) { - using namespace aliceVision; - using namespace aliceVision::robustEstimation; - out_geometricInliersPerType.clear(); // get back corresponding view index @@ -79,10 +76,10 @@ struct GeometricFilterMatrix_E_AC : public GeometricFilterMatrix fillMatricesWithUndistortFeaturesMatches(pairIndex, putativeMatchesPerType, sfmData, regionsPerView, descTypes, xI, xJ); // define the AContrario adapted Essential matrix solver - typedef RelativePoseKernel_K< + typedef multiview::RelativePoseKernel_K< multiview::relativePose::Essential5PSolver, multiview::relativePose::FundamentalEpipolarDistanceError, - multiview::Mat3Model> + robustEstimation::Mat3Model> KernelT; const camera::Pinhole* ptrPinholeI = (const camera::Pinhole*)(camI); @@ -95,8 +92,8 @@ struct GeometricFilterMatrix_E_AC : public GeometricFilterMatrix const double upperBoundPrecision = Square(m_dPrecision); std::vector inliers; - multiview::Mat3Model model; - const std::pair ACRansacOut = ACRANSAC(kernel, inliers, m_stIteration, &model, upperBoundPrecision); + robustEstimation::Mat3Model model; + const std::pair ACRansacOut = robustEstimation::ACRANSAC(kernel, inliers, m_stIteration, &model, upperBoundPrecision); m_E = model.getMatrix(); if (inliers.empty()) @@ -157,9 +154,9 @@ struct GeometricFilterMatrix_E_AC : public GeometricFilterMatrix Mat3 F; fundamentalFromEssential(m_E, ptrPinholeI->K(), ptrPinholeJ->K(), &F); - multiview::Mat3Model model(F); + robustEstimation::Mat3Model model(F); // multiview::relativePose::FundamentalSymmetricEpipolarDistanceError - robustEstimation::guidedMatching( + robustEstimation::guidedMatching( model, camI, regionsPerView.getAllRegions(I), camJ, regionsPerView.getAllRegions(J), diff --git a/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_F_AC.hpp b/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_F_AC.hpp index 7848170c81..45a4dae3fa 100644 --- a/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_F_AC.hpp +++ b/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_F_AC.hpp @@ -10,18 +10,19 @@ #include #include #include -#include -#include -#include -#include -#include #include -#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -54,9 +55,6 @@ struct GeometricFilterMatrix_F_AC : public GeometricFilterMatrix const matching::MatchesPerDescType& putativeMatchesPerType, matching::MatchesPerDescType& out_geometricInliersPerType) { - using namespace aliceVision; - using namespace aliceVision::robustEstimation; - out_geometricInliersPerType.clear(); // get back corresponding view index @@ -94,9 +92,6 @@ struct GeometricFilterMatrix_F_AC : public GeometricFilterMatrix const matching::MatchesPerDescType& putativeMatchesPerType, matching::MatchesPerDescType& out_geometricInliersPerType) { - using namespace aliceVision; - using namespace aliceVision::robustEstimation; - out_geometricInliersPerType.clear(); const std::vector descTypes = getCommonDescTypes(regionI, regionJ); @@ -115,17 +110,17 @@ struct GeometricFilterMatrix_F_AC : public GeometricFilterMatrix switch(m_estimator) { - case ERobustEstimator::ACRANSAC: + case robustEstimation::ERobustEstimator::ACRANSAC: { if(m_estimateDistortion) { estimationPair = geometricEstimation_Mat_ACRANSAC(xI, xJ, imageSizeI, imageSizeJ, inliers); } else - estimationPair = geometricEstimation_Mat_ACRANSAC(xI, xJ, imageSizeI, imageSizeJ, inliers); + estimationPair = geometricEstimation_Mat_ACRANSAC(xI, xJ, imageSizeI, imageSizeJ, inliers); } break; - case ERobustEstimator::LORANSAC: + case robustEstimation::ERobustEstimator::LORANSAC: { if(m_estimateDistortion) throw std::invalid_argument("[GeometricFilterMatrix_F_AC::geometricEstimation] Using fundamental matrix and f10 solver with LO_RANSAC is not yet implemented"); @@ -170,13 +165,10 @@ struct GeometricFilterMatrix_F_AC : public GeometricFilterMatrix const std::pair& imageSizeJ, // size of the first image std::vector& out_inliers) { - using namespace aliceVision; - using namespace aliceVision::robustEstimation; - out_inliers.clear(); // define the AContrario adapted Fundamental matrix solver - typedef RelativePoseKernel< + typedef multiview::RelativePoseKernel< SolverT_, multiview::relativePose::FundamentalEpipolarDistanceError, //multiview::relativePose::FundamentalSymmetricEpipolarDistanceError, @@ -191,7 +183,7 @@ struct GeometricFilterMatrix_F_AC : public GeometricFilterMatrix const double upperBoundPrecision = Square(m_dPrecision); ModelT_ model; - const std::pair ACRansacOut = ACRANSAC(kernel, out_inliers, m_stIteration, &model, upperBoundPrecision); + const std::pair ACRansacOut = robustEstimation::ACRANSAC(kernel, out_inliers, m_stIteration, &model, upperBoundPrecision); m_F = model.getMatrix(); if(out_inliers.empty()) @@ -219,20 +211,17 @@ struct GeometricFilterMatrix_F_AC : public GeometricFilterMatrix const std::pair& imageSizeJ, // size of the first image std::vector& out_inliers) { - using namespace aliceVision; - using namespace aliceVision::robustEstimation; - out_inliers.clear(); // just a safeguard if(m_dPrecision == std::numeric_limits::infinity()) throw std::invalid_argument("[GeometricFilterMatrix_F_AC_AC::geometricEstimation] the threshold of the LORANSAC is set to infinity!"); - typedef RelativePoseKernel< + typedef multiview::RelativePoseKernel< SolverT_, multiview::relativePose::FundamentalSymmetricEpipolarDistanceError, multiview::UnnormalizerT, - multiview::Mat3Model, + robustEstimation::Mat3Model, SolverLsT_> KernelT; @@ -241,9 +230,9 @@ struct GeometricFilterMatrix_F_AC : public GeometricFilterMatrix //@fixme scorer should be using the pixel error, not the squared version, refactoring needed const double normalizedThreshold = Square(m_dPrecision * kernel.normalizer2()(0, 0)); - ScoreEvaluator scorer(normalizedThreshold); + robustEstimation::ScoreEvaluator scorer(normalizedThreshold); - multiview::Mat3Model model = LO_RANSAC(kernel, scorer, &out_inliers); + robustEstimation::Mat3Model model = robustEstimation::LO_RANSAC(kernel, scorer, &out_inliers); m_F = model.getMatrix(); if(out_inliers.empty()) @@ -284,10 +273,10 @@ struct GeometricFilterMatrix_F_AC : public GeometricFilterMatrix const camera::IntrinsicBase* camJ = sfmData->getIntrinsics().count(viewJ.getIntrinsicId()) ? sfmData->getIntrinsics().at(viewJ.getIntrinsicId()).get() : nullptr; - multiview::Mat3Model model(m_F); + robustEstimation::Mat3Model model(m_F); // check the features correspondences that agree in the geometric and photometric domain - robustEstimation::guidedMatching( + robustEstimation::guidedMatching( model, camI, // camera::IntrinsicBase regionsPerView.getAllRegions(I), // feature::Regions diff --git a/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_H_AC.hpp b/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_H_AC.hpp index 1e4178362d..fe9698cee1 100644 --- a/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_H_AC.hpp +++ b/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_H_AC.hpp @@ -10,11 +10,12 @@ #include #include #include -#include -#include -#include #include #include +#include +#include +#include +#include #include #include @@ -43,9 +44,6 @@ struct GeometricFilterMatrix_H_AC : public GeometricFilterMatrix const matching::MatchesPerDescType& putativeMatchesPerType, matching::MatchesPerDescType& out_geometricInliersPerType) { - using namespace aliceVision; - using namespace aliceVision::robustEstimation; - out_geometricInliersPerType.clear(); // get back corresponding view index @@ -65,11 +63,11 @@ struct GeometricFilterMatrix_H_AC : public GeometricFilterMatrix fillMatricesWithUndistortFeaturesMatches(pairIndex, putativeMatchesPerType, sfmData, regionsPerView, descTypes, xI, xJ); // define the AContrario adapted Homography matrix solver - typedef RelativePoseKernel< + typedef multiview::RelativePoseKernel< multiview::relativePose::Homography4PSolver, multiview::relativePose::HomographyAsymmetricError, multiview::UnnormalizerI, - multiview::Mat3Model> + robustEstimation::Mat3Model> KernelT; const KernelT kernel(xI, viewI.getWidth(), viewI.getHeight(), @@ -79,8 +77,8 @@ struct GeometricFilterMatrix_H_AC : public GeometricFilterMatrix const double upperBoundPrecision = Square(m_dPrecision); std::vector inliers; - multiview::Mat3Model model; - const std::pair ACRansacOut = ACRANSAC(kernel, inliers, m_stIteration, &model, upperBoundPrecision); + robustEstimation::Mat3Model model; + const std::pair ACRansacOut = robustEstimation::ACRANSAC(kernel, inliers, m_stIteration, &model, upperBoundPrecision); m_H = model.getMatrix(); if (inliers.empty()) @@ -188,7 +186,7 @@ struct GeometricFilterMatrix_H_AC : public GeometricFilterMatrix const camera::IntrinsicBase* camJ = sfmData->getIntrinsics().count(viewJ.getIntrinsicId()) ? sfmData->getIntrinsics().at(viewJ.getIntrinsicId()).get() : nullptr; - multiview::Mat3Model model(m_H); + robustEstimation::Mat3Model model(m_H); if(dDistanceRatio < 0) { @@ -207,7 +205,7 @@ struct GeometricFilterMatrix_H_AC : public GeometricFilterMatrix createMatricesWithUndistortFeatures(camI, pointsFeaturesI, xI); createMatricesWithUndistortFeatures(camJ, pointsFeaturesJ, xJ); - robustEstimation::guidedMatching(model, xI, xJ, Square(m_dPrecision_robust), localMatches); + robustEstimation::guidedMatching(model, xI, xJ, Square(m_dPrecision_robust), localMatches); // remove matches that have the same (X,Y) coordinates matching::IndMatchDecorator matchDeduplicator(localMatches, pointsFeaturesI, pointsFeaturesJ); @@ -218,7 +216,7 @@ struct GeometricFilterMatrix_H_AC : public GeometricFilterMatrix else { // filtering based on region positions and regions descriptors - robustEstimation::guidedMatching(model, + robustEstimation::guidedMatching(model, camI, regionsPerView.getAllRegions(I), camJ, regionsPerView.getAllRegions(J), Square(m_dPrecision_robust), Square(dDistanceRatio), diff --git a/src/aliceVision/multiview/AngularRadianErrorKernel.hpp b/src/aliceVision/multiview/AngularRadianErrorKernel.hpp new file mode 100644 index 0000000000..a9e951e595 --- /dev/null +++ b/src/aliceVision/multiview/AngularRadianErrorKernel.hpp @@ -0,0 +1,71 @@ +// This file is part of the AliceVision project. +// Copyright (c) 2019 AliceVision contributors. +// This Source Code Form is subject to the terms of the Mozilla Public License, +// v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include +#include +#include +#include +#include + +/** + * @brief Collection of kernel. + * @ref [1] "Robust and accurate calibration of camera networks". PhD. Pierre MOULON + * + * - AngularRadianErrorKernel: essential matrix estimation between spherical camera + * + * Mainly it add correct data normalization and define the function required + * by the generic ACRANSAC / LORANSAC routine. + */ + +namespace aliceVision { +namespace multiview { + +/** + * @brief Two view Kernel adapter for the A contrario (AC) model estimator. + * Specialization to handle radian angular residual error. + */ +template +class AngularRadianErrorKernel + : public robustEstimation::RansacKernel> +{ +public: + + using KernelBase = robustEstimation::RansacKernel>; + + AngularRadianErrorKernel(const Mat& x1, const Mat& x2) + : KernelBase(x1, x2) + , _logalpha0(log10(1.0 / 2.0)) + { + assert(3 == x1.rows()); + assert(x1.rows() == x2.rows()); + assert(x1.cols() == x2.cols()); + } + + inline double error(std::size_t sample, const ModelT_& model) const override + { + return Square(KernelBase::error(sample, model)); + } + + void unnormalize(ModelT_& model) const override + { + // do nothing, no normalization in the angular case + } + + double logalpha0() const override {return _logalpha0; } + double multError() const override {return 1./4.;} + Mat3 normalizer1() const override {return Mat3::Identity();} + Mat3 normalizer2() const override {return Mat3::Identity();} + double unormalizeError(double val) const override {return sqrt(val);} + +protected: + /// Alpha0 is used to make the error adaptive to the image size + double _logalpha0; +}; + +} // namespace multiview +} // namespace aliceVision diff --git a/src/aliceVision/multiview/CMakeLists.txt b/src/aliceVision/multiview/CMakeLists.txt index 2504b6b8e2..f31b468213 100644 --- a/src/aliceVision/multiview/CMakeLists.txt +++ b/src/aliceVision/multiview/CMakeLists.txt @@ -1,11 +1,13 @@ # Headers set(multiview_files_headers affineSolver.hpp - conditioning.hpp essential.hpp + epipolarEquation.hpp knownRotationTranslationKernel.hpp - projection.hpp - ISolver.hpp + Unnormalizer.hpp + AngularRadianErrorKernel.hpp + RelativePoseKernel.hpp + ResectionKernel.hpp relativePose/Essential5PSolver.hpp relativePose/Essential8PSolver.hpp relativePose/EssentialKernel.hpp @@ -17,6 +19,7 @@ set(multiview_files_headers relativePose/Homography4PSolver.hpp relativePose/HomographyError.hpp relativePose/HomographyKernel.hpp + relativePose/ISolverErrorRelativePose.hpp resection/EPnPSolver.hpp resection/EPnPKernel.hpp resection/P3PSolver.hpp @@ -25,6 +28,7 @@ set(multiview_files_headers resection/ProjectionDistanceError.hpp resection/Resection6PSolver.hpp resection/ResectionKernel.hpp + resection/ISolverErrorResection.hpp rotationAveraging/common.hpp rotationAveraging/rotationAveraging.hpp rotationAveraging/l1.hpp @@ -34,15 +38,13 @@ set(multiview_files_headers triangulation/Triangulation.hpp triangulation/triangulationDLT.hpp triangulation/NViewsTriangulationLORansac.hpp - TwoViewKernel.hpp ) # Sources set(multiview_files_sources affineSolver.cpp - conditioning.cpp essential.cpp - projection.cpp + Unnormalizer.cpp relativePose/Essential5PSolver.cpp relativePose/Essential8PSolver.cpp relativePose/Fundamental7PSolver.cpp diff --git a/src/aliceVision/multiview/NViewDataSet.cpp b/src/aliceVision/multiview/NViewDataSet.cpp index dd21636d1e..a399310289 100644 --- a/src/aliceVision/multiview/NViewDataSet.cpp +++ b/src/aliceVision/multiview/NViewDataSet.cpp @@ -8,7 +8,7 @@ #include "NViewDataSet.hpp" #include -#include +#include #include #include diff --git a/src/aliceVision/multiview/RelativePoseKernel.hpp b/src/aliceVision/multiview/RelativePoseKernel.hpp new file mode 100644 index 0000000000..4e59d9a686 --- /dev/null +++ b/src/aliceVision/multiview/RelativePoseKernel.hpp @@ -0,0 +1,187 @@ +// This file is part of the AliceVision project. +// Copyright (c) 2019 AliceVision contributors. +// This Source Code Form is subject to the terms of the Mozilla Public License, +// v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include +#include +#include +#include +#include + +/** + * @brief Collection of kernel. + * @ref [1] "Robust and accurate calibration of camera networks". PhD. Pierre MOULON + * + * - RelativePoseKernel: relative pose two view estimation (affine, homography, fundamental) with unkwon intrinsic + * - RelativePoseKernel_K: relative pose two view estimation for essential matrix with known intrinsics + * + * Mainly it add correct data normalization and define the function required + * by the generic ACRANSAC / LORANSAC routine. + */ + +namespace aliceVision { +namespace multiview { + +/** + * @brief Two view Kernel adapter for the A contrario (AC) model estimator. + * With unknown intrinsic. + * + * @note Handle data normalization and compute the corresponding logalpha 0 + * that depends of the error model (point to line, or point to point) + * + * @note This kernel adapter is working for affine, homography, fundamental matrix + * estimation. + */ +template> +class RelativePoseKernel + : public robustEstimation::RansacKernel +{ +public: + + using KernelBase = robustEstimation::RansacKernel; + + RelativePoseKernel(const Mat& x1, int w1, int h1, + const Mat& x2, int w2, int h2, + bool pointToLine = true) + : _x1(x1.rows(), x1.cols()) + , _x2(x2.rows(), x2.cols()) + , KernelBase(_x1, _x2) + , _logalpha0(0.0) + , _N1(3, 3) + , _N2(3, 3) + , _pointToLine(pointToLine) + { + assert(2 == x1.rows()); + assert(x1.rows() == x2.rows()); + assert(x1.cols() == x2.cols()); + + robustEstimation::normalizePointsFromImageSize(x1, &_x1, &_N1, w1, h1); + robustEstimation::normalizePointsFromImageSize(x2, &_x2, &_N2, w2, h2); + + // logAlpha0 is used to make error data scale invariant + if(pointToLine) + { + // Ratio of containing diagonal image rectangle over image area + const double D = sqrt(w2 * (double) w2 + h2 * (double) h2); // diameter + const double A = w2 * (double) h2; // area + _logalpha0 = log10(2.0 * D / A / _N2(0, 0)); + } + else + { + // ratio of area : unit circle over image area + _logalpha0 = log10(M_PI / (w2 * (double) h2) / (_N2(0, 0) * _N2(0, 0))); + } + } + + void unnormalize(ModelT_& model) const override + { + // Unnormalize model from the computed conditioning. + Mat3 H = model.getMatrix(); + UnnormalizerT_::unnormalize(_N1, _N2, &H); + model.setMatrix(H); + } + + double logalpha0() const override {return _logalpha0; } + double multError() const override {return (_pointToLine)? 0.5 : 1.0;} + Mat3 normalizer1() const override {return _N1;} + Mat3 normalizer2() const override {return _N2;} + double unormalizeError(double val) const override {return sqrt(val) / _N2(0,0);} + +protected: + /// Normalized input data + Mat _x1, _x2; + /// Matrix used to normalize data + Mat3 _N1, _N2; + /// Alpha0 is used to make the error adaptive to the image size + double _logalpha0; + /// Store if error model is pointToLine or point to point + bool _pointToLine; +}; + +/** + * @brief Two view Kernel adapter for the A contrario (AC) model estimator. + * With known intrinsic. + * + * @note Handle data normalization and compute the corresponding logalpha 0 + * that depends of the error model (point to line, or point to point) + * + * @note This kernel adapter is working only for essential matrix + * estimation. + */ +template> +class RelativePoseKernel_K + : public robustEstimation::RansacKernel +{ +public: + + using KernelBase = robustEstimation::RansacKernel; + + RelativePoseKernel_K(const Mat& x1, int w1, int h1, + const Mat& x2, int w2, int h2, + const Mat3& K1, const Mat3& K2) + : KernelBase(x1, x2) + , _N1(Mat3::Identity()) + , _N2(Mat3::Identity()) + , _logalpha0(0.0) + , _K1(K1) + , _K2(K2) + { + assert(2 == x1.rows()); + assert(x1.rows() == x2.rows()); + assert(x1.cols() == x2.cols()); + + robustEstimation::applyTransformationToPoints(x1, _K1.inverse(), &_x1k); + robustEstimation::applyTransformationToPoints(x2, _K2.inverse(), &_x2k); + + // point to line probability (line is the epipolar line) + const double D = sqrt(w2 * static_cast(w2) + h2 * static_cast(h2)); // diameter + const double A = w2 * static_cast(h2); // area + _logalpha0 = log10(2.0 * D / A * .5); + } + + void fit(const std::vector& samples, std::vector& models) const override + { + const Mat x1 = ExtractColumns(_x1k, samples); + const Mat x2 = ExtractColumns(_x2k, samples); + + KernelBase::KernelBase::_kernelSolver.solve(x1, x2, models); + } + + double error(std::size_t sample, const ModelT_& model) const override + { + Mat3 F; + fundamentalFromEssential(model.getMatrix(), _K1, _K2, &F); + const ModelT_ modelF(F); + return _errorEstimator.error(modelF, KernelBase::_x1.col(sample), KernelBase::_x2.col(sample)); + } + + void unnormalize(ModelT_& model) const override + { + // do nothing, no normalization in this case + } + + double logalpha0() const override {return _logalpha0; } + double multError() const override {return 0.5;} // point to line error + Mat3 normalizer1() const override {return _N1;} + Mat3 normalizer2() const override {return _N2;} + double unormalizeError(double val) const override { return val; } + +private: + + Mat _x1k, _x2k; + /// Matrix used to normalize data + Mat3 _N1, _N2; + /// Alpha0 is used to make the error adaptive to the image size + double _logalpha0; + /// Intrinsics camera parameter + Mat3 _K1, _K2; + /// solver error estimation + const ErrorT_ _errorEstimator; +}; + +} // namespace multiview +} // namespace aliceVision diff --git a/src/aliceVision/multiview/ResectionKernel.hpp b/src/aliceVision/multiview/ResectionKernel.hpp new file mode 100644 index 0000000000..f40a3089ea --- /dev/null +++ b/src/aliceVision/multiview/ResectionKernel.hpp @@ -0,0 +1,148 @@ +// This file is part of the AliceVision project. +// Copyright (c) 2019 AliceVision contributors. +// This Source Code Form is subject to the terms of the Mozilla Public License, +// v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include +#include +#include +#include +#include + +/** + * @brief Collection of kernel. + * @ref [1] "Robust and accurate calibration of camera networks". PhD. Pierre MOULON + * + * - ResectionKernel: pose / resection estimation with unknown intrinsic + * - ResectionKernel_K: pose / resection estimation with known intrinsic + * + * Mainly it add correct data normalization and define the function required + * by the generic ACRANSAC / LORANSAC routine. + */ + +namespace aliceVision { +namespace multiview { + +/** + * @brief Pose/Resection Kernel with unknown intrinsic for the A contrario (AC) model estimator. + */ +template> +class ResectionKernel + : public robustEstimation::RansacKernel +{ +public: + + using KernelBase = robustEstimation::RansacKernel; + + /** + * @brief ResectionKernel constructor with unknown intrinsic + * @param[in] x2d 2d points in the first image. One per column. + * @param[in] x3d 3d points in the second image. One per column. + * @param[in] K intrinsic camera parameter + */ + ResectionKernel(const Mat& x2d, const Mat& x3d, int w, int h) + : _x2d(x2d.rows(), x2d.cols()) + , KernelBase(_x2d, x3d) + , _logalpha0(log10(M_PI)) + , _N1(3, 3) + { + assert(2 == x2d.rows()); + assert(3 == x3d.rows()); + assert(x2d.cols() == x3d.cols()); + + robustEstimation::normalizePointsFromImageSize(x2d, &_x2d, &_N1, w, h); + } + + void unnormalize(ModelT_& model) const override + { + // unnormalize model from the computed conditioning. + Mat34 P = model.getMatrix(); + UnnormalizerT_::unnormalize(_N1, Mat3::Identity(), &P); + model.setMatrix(P); + } + + double logalpha0() const override {return _logalpha0; } + double multError() const override {return 1.0;} // point to point error + Mat3 normalizer1() const override {return Mat3::Identity();} + Mat3 normalizer2() const override {return _N1;} + double unormalizeError(double val) const override {return sqrt(val) / _N1(0,0);} + +protected: + /// Normalized input data + Mat _x2d; + /// Matrix used to normalize data + Mat3 _N1; + /// Alpha0 is used to make the error adaptive to the image size + double _logalpha0; +}; + + +/** + * @brief The kernel for the resection with known intrinsics (PnP) to be used with + * the ACRANSAC / LORANSAC framework. + * + * @tparam SolverT The minimal solver able to find a solution from a minimum set of points, usually any PnP solver. + * @tparam ErrorT The functor computing the error for each data sample with respect to the estimated model, usually a reprojection error functor. + * @tparam UnnormalizerT The functor used to normalize the data before the estimation of the model, usually a functor that normalize the point in camera + * coordinates (ie multiply by the inverse of the calibration matrix). + * @tparam SolverLsT = SolverT The least square solver that is used to find a solution from any set of data larger than the minimum required, + * usually the 6 point algorithm which solves the resection problem by means of LS. + * @tparam ModelT = Mat34Model The type of the model to estimate, the projection matrix. + */ +template> +class ResectionKernel_K + : public robustEstimation::RansacKernel +{ +public: + + using KernelBase = robustEstimation::RansacKernel; + + /** + * @brief ResectionKernel constructor with known intrinsic + * @param[in] x2d 2d points in the first image. One per column. + * @param[in] x3d 3d points in the second image. One per column. + * @param[in] K intrinsic camera parameter + */ + ResectionKernel_K(const Mat& x2d, const Mat& x3d, const Mat3& K) + : _x2d(x2d.rows(), x2d.cols()) + , KernelBase(_x2d, x3d) + , _logalpha0(log10(M_PI)) + , _N1(K.inverse()) + , _K(K) + { + assert(2 == x2d.rows()); + assert(3 == x3d.rows()); + assert(x2d.cols() == x3d.cols()); + + // normalize points by inverse K + robustEstimation::applyTransformationToPoints(x2d, _N1, &_x2d); + } + + void unnormalize(ModelT_& model) const override + { + // unnormalize model from the computed conditioning. + model.setMatrix(_K * model.getMatrix()); + } + + double logalpha0() const override {return _logalpha0; } + double multError() const override {return 1.0;} // point to point error + Mat3 normalizer1() const override {return Mat3::Identity();} + Mat3 normalizer2() const override {return _N1;} + double unormalizeError(double val) const override {return sqrt(val) / _N1(0,0);} + +protected: + /// Normalized input data + Mat _x2d; + /// Matrix used to normalize data + Mat3 _N1; + /// Alpha0 is used to make the error adaptive to the image size + double _logalpha0; + /// intrinsic camera parameter + Mat3 _K; +}; + +} // namespace multiview +} // namespace aliceVision diff --git a/src/aliceVision/multiview/Unnormalizer.cpp b/src/aliceVision/multiview/Unnormalizer.cpp new file mode 100644 index 0000000000..30135227b2 --- /dev/null +++ b/src/aliceVision/multiview/Unnormalizer.cpp @@ -0,0 +1,32 @@ +// This file is part of the AliceVision project. +// Copyright (c) 2016 AliceVision contributors. +// Copyright (c) 2012 openMVG contributors. +// Copyright (c) 2010 libmv contributors. +// This Source Code Form is subject to the terms of the Mozilla Public License, +// v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +#include "Unnormalizer.hpp" + +namespace aliceVision { +namespace multiview { + +// Denormalize the results. See HZ page 109. +void UnnormalizerT::unnormalize(const Mat3 &T1, const Mat3 &T2, Mat3 *H) +{ + *H = T2.transpose() * (*H) * T1; +} + +// Denormalize the results. See HZ page 109. +void UnnormalizerI::unnormalize(const Mat3 &T1, const Mat3 &T2, Mat3 *H) +{ + *H = T2.inverse() * (*H) * T1; +} + +void UnnormalizerResection::unnormalize(const Mat &T, const Mat &U, Mat34 *P) +{ + *P = T.inverse() * (*P); +} + +} // namespace multiview +} // namespace aliceVision diff --git a/src/aliceVision/multiview/Unnormalizer.hpp b/src/aliceVision/multiview/Unnormalizer.hpp new file mode 100644 index 0000000000..c9f988b6c2 --- /dev/null +++ b/src/aliceVision/multiview/Unnormalizer.hpp @@ -0,0 +1,49 @@ +// This file is part of the AliceVision project. +// Copyright (c) 2016 AliceVision contributors. +// Copyright (c) 2012 openMVG contributors. +// Copyright (c) 2010 libmv contributors. +// This Source Code Form is subject to the terms of the Mozilla Public License, +// v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include + +namespace aliceVision { +namespace multiview { + +/** + * @brief Unnormalize using Inverse + */ +struct UnnormalizerI +{ + /** + * @brief Denormalize the results. + * @see HZ page 109. + */ + static void unnormalize(const Mat3& T1, const Mat3& T2, Mat3* H); +}; + +/** + * @brief Unnormalize using Transpose + */ +struct UnnormalizerT +{ + /** + * @brief Denormalize the results. + * @see HZ page 109. + */ + static void unnormalize(const Mat3& T1, const Mat3& T2, Mat3* H); +}; + +/** + * @brief Unnormalize for resection + */ +struct UnnormalizerResection +{ + static void unnormalize(const Mat& T, const Mat& U, Mat34* P); +}; + +} //namespace multiview +} //namespace aliceVision diff --git a/src/aliceVision/multiview/epipolarEquation.hpp b/src/aliceVision/multiview/epipolarEquation.hpp new file mode 100644 index 0000000000..6ed4d9c995 --- /dev/null +++ b/src/aliceVision/multiview/epipolarEquation.hpp @@ -0,0 +1,67 @@ +// This file is part of the AliceVision project. +// Copyright (c) 2016 AliceVision contributors. +// Copyright (c) 2012 openMVG contributors. +// Copyright (c) 2010 libmv contributors. +// This Source Code Form is subject to the terms of the Mozilla Public License, +// v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +#include + +#include + +namespace aliceVision { +namespace multiview { + +/** + * @brief Build a 9 x n matrix from point matches, where each row is equivalent to the + * equation x'T*F*x = 0 for a single correspondence pair (x', x). The domain of + * the matrix is a 9 element vector corresponding to F. In other words, set up + * the linear system + * + * Af = 0, + * + * where f is the F matrix as a 9-vector rather than a 3x3 matrix (row + * major). If the points are well conditioned and there are 8 or more, then + * the nullspace should be rank one. If the nullspace is two dimensional, + * then the rank 2 constraint must be enforced to identify the appropriate F + * matrix. + * + * @note that this does not resize the matrix A; it is expected to have the + * appropriate size already. + */ +template +inline void encodeEpipolarEquation(const TMatX& x1, const TMatX& x2, TMatA* A, const std::vector *weights = nullptr) +{ + assert(x1.cols()==x2.cols()); + + if(weights != nullptr) + { + assert(x1.cols()==weights->size()); + } + + for(typename TMatX::Index i = 0; i < x1.cols(); ++i) + { + const Vec2 xx1 = x1.col(i); + const Vec2 xx2 = x2.col(i); + + A->row(i) << + xx2(0) * xx1(0), // 0 represents x coords, + xx2(0) * xx1(1), // 1 represents y coords. + xx2(0), + xx2(1) * xx1(0), + xx2(1) * xx1(1), + xx2(1), + xx1(0), + xx1(1), + 1.0; + + if(weights != nullptr) + A->row(i) *= (*weights)[i]; + } +} + +} // namespace multiview +} // namespace aliceVision diff --git a/src/aliceVision/multiview/essential.cpp b/src/aliceVision/multiview/essential.cpp index 0b34bc1aad..b574253ecc 100644 --- a/src/aliceVision/multiview/essential.cpp +++ b/src/aliceVision/multiview/essential.cpp @@ -7,7 +7,7 @@ // You can obtain one at https://mozilla.org/MPL/2.0/. #include -#include +#include #include #include diff --git a/src/aliceVision/multiview/knownRotationTranslationKernel.hpp b/src/aliceVision/multiview/knownRotationTranslationKernel.hpp index 8db023806c..52155c28ff 100644 --- a/src/aliceVision/multiview/knownRotationTranslationKernel.hpp +++ b/src/aliceVision/multiview/knownRotationTranslationKernel.hpp @@ -8,7 +8,7 @@ #pragma once #include -#include +#include namespace aliceVision { namespace multiview { @@ -50,7 +50,7 @@ struct TwoPointTranslationSolver * @param R * @param models t */ - void solve(const Mat& xA, const Mat& xB, const Mat3& R, std::vector>& models) const + void solve(const Mat& xA, const Mat& xB, const Mat3& R, std::vector>& models) const { const Mat3 Rt = R.transpose(); @@ -77,7 +77,7 @@ struct TwoPointTranslationSolver /** * @brief Generic Solver to find the translation from a known Rotation. */ -template> +template> class TranslationFromKnowRotationKernel { public: @@ -143,7 +143,7 @@ class TranslationFromKnowRotationKernel Mat34 poseA, poseB; P_from_KRt(Mat3::Identity(), Mat3::Identity(), Vec3::Zero(), &poseA); P_from_KRt(Mat3::Identity(), _R, model.getMatrix(), &poseB); - const Mat3Model F(F_from_P(poseA, poseB)); + const robustEstimation::Mat3Model F(F_from_P(poseA, poseB)); return _errorEstimator.error(F, _x1.col(sample), _x2.col(sample)); } diff --git a/src/aliceVision/multiview/knownRotationTranslationKernel_test.cpp b/src/aliceVision/multiview/knownRotationTranslationKernel_test.cpp index 1523875ae3..ba6b382508 100644 --- a/src/aliceVision/multiview/knownRotationTranslationKernel_test.cpp +++ b/src/aliceVision/multiview/knownRotationTranslationKernel_test.cpp @@ -43,7 +43,7 @@ BOOST_AUTO_TEST_CASE(TranslationFromKnowRotationKernel_Multiview) std::size_t samples_[2]={0,1}; std::vector samples(samples_, samples_ + 2); - std::vector> vec_t; + std::vector> vec_t; kernel.fit(samples, vec_t); BOOST_CHECK_EQUAL(1, vec_t.size()); diff --git a/src/aliceVision/multiview/relativePose/Essential5PSolver.cpp b/src/aliceVision/multiview/relativePose/Essential5PSolver.cpp index b0ae68a903..a0f9a94dd1 100644 --- a/src/aliceVision/multiview/relativePose/Essential5PSolver.cpp +++ b/src/aliceVision/multiview/relativePose/Essential5PSolver.cpp @@ -7,6 +7,7 @@ // You can obtain one at https://mozilla.org/MPL/2.0/. #include "Essential5PSolver.hpp" +#include namespace aliceVision { namespace multiview { @@ -157,7 +158,7 @@ Mat fivePointsPolynomialConstraints(const Mat& EBasis) return M; } -void Essential5PSolver::solve(const Mat& x1, const Mat& x2, std::vector& models) const +void Essential5PSolver::solve(const Mat& x1, const Mat& x2, std::vector& models) const { assert(2 == x1.rows()); assert(5 <= x1.cols()); diff --git a/src/aliceVision/multiview/relativePose/Essential5PSolver.hpp b/src/aliceVision/multiview/relativePose/Essential5PSolver.hpp index bde0eb86e7..050e9bcb6a 100644 --- a/src/aliceVision/multiview/relativePose/Essential5PSolver.hpp +++ b/src/aliceVision/multiview/relativePose/Essential5PSolver.hpp @@ -8,13 +8,13 @@ #pragma once -#include +#include namespace aliceVision { namespace multiview { namespace relativePose { -class Essential5PSolver : public ISolver +class Essential5PSolver : public robustEstimation::ISolver { public: @@ -42,7 +42,7 @@ class Essential5PSolver : public ISolver * @param[in] x2 Corresponding points in the second image. One per column. * @param[out] models A list of at most 10 candidate essential matrix solutions. */ - void solve(const Mat& x1, const Mat& x2, std::vector& models) const override; + void solve(const Mat& x1, const Mat& x2, std::vector& models) const override; /** * @brief Solve the problem. @@ -51,7 +51,7 @@ class Essential5PSolver : public ISolver * @param[out] models A vector into which the computed models are stored. * @param[in] weights. */ - void solve(const Mat& x1, const Mat& x2, std::vector& models, const std::vector& weights) const override + void solve(const Mat& x1, const Mat& x2, std::vector& models, const std::vector& weights) const override { throw std::logic_error("Essential5PSolver does not support problem solving with weights."); } diff --git a/src/aliceVision/multiview/relativePose/Essential8PSolver.cpp b/src/aliceVision/multiview/relativePose/Essential8PSolver.cpp index f091c7bac1..3f0e3de4cf 100644 --- a/src/aliceVision/multiview/relativePose/Essential8PSolver.cpp +++ b/src/aliceVision/multiview/relativePose/Essential8PSolver.cpp @@ -7,12 +7,13 @@ // You can obtain one at https://mozilla.org/MPL/2.0/. #include "Essential8PSolver.hpp" +#include namespace aliceVision { namespace multiview { namespace relativePose { -void Essential8PSolver::solve(const Mat& x1, const Mat& x2, std::vector& models) const +void Essential8PSolver::solve(const Mat& x1, const Mat& x2, std::vector& models) const { assert(2 == x1.rows()); assert(8 <= x1.cols()); diff --git a/src/aliceVision/multiview/relativePose/Essential8PSolver.hpp b/src/aliceVision/multiview/relativePose/Essential8PSolver.hpp index 70af24d01f..e817846d52 100644 --- a/src/aliceVision/multiview/relativePose/Essential8PSolver.hpp +++ b/src/aliceVision/multiview/relativePose/Essential8PSolver.hpp @@ -8,13 +8,13 @@ #pragma once -#include +#include namespace aliceVision { namespace multiview { namespace relativePose { -class Essential8PSolver : public ISolver +class Essential8PSolver : public robustEstimation::ISolver { public: @@ -45,7 +45,7 @@ class Essential8PSolver : public ISolver * @param[in] x2 Corresponding points in the second image. One per column. * @param[out] models A list of at most 10 candidate essential matrix solutions. */ - void solve(const Mat& x1, const Mat& x2, std::vector& models) const override; + void solve(const Mat& x1, const Mat& x2, std::vector& models) const override; /** * @brief Solve the problem. @@ -54,7 +54,7 @@ class Essential8PSolver : public ISolver * @param[out] models A vector into which the computed models are stored. * @param[in] weights. */ - void solve(const Mat& x1, const Mat& x2, std::vector& models, const std::vector& weights) const override + void solve(const Mat& x1, const Mat& x2, std::vector& models, const std::vector& weights) const override { throw std::logic_error("Essential8PSolver does not support problem solving with weights."); } diff --git a/src/aliceVision/multiview/relativePose/EssentialKernel.hpp b/src/aliceVision/multiview/relativePose/EssentialKernel.hpp index f4a3886b3f..70580dfb4d 100644 --- a/src/aliceVision/multiview/relativePose/EssentialKernel.hpp +++ b/src/aliceVision/multiview/relativePose/EssentialKernel.hpp @@ -8,11 +8,13 @@ #pragma once -#include -#include +#include +#include #include #include #include +#include +#include namespace aliceVision { namespace multiview { @@ -24,15 +26,15 @@ namespace relativePose { * @todo Error must be overwrite in order to compute F from E and K's. * Fitting must normalize image values to camera values. */ -template -class EssentialKernel : public TwoViewKernel +template +class EssentialKernel : public robustEstimation::FittingKernel { public: - using KernelBase = TwoViewKernel; + using KernelBase = robustEstimation::FittingKernel; EssentialKernel(const Mat& x1, const Mat& x2, const Mat3& K1, const Mat3& K2) - : TwoViewKernel(x1,x2) + : robustEstimation::FittingKernel(x1,x2) , _K1(K1) , _K2(K2) {} @@ -54,8 +56,8 @@ class EssentialKernel : public TwoViewKernel Mat x1_normalized; Mat x2_normalized; - applyTransformationToPoints(x1, K1Inverse, &x1_normalized); - applyTransformationToPoints(x2, K2Inverse, &x2_normalized); + robustEstimation::applyTransformationToPoints(x1, K1Inverse, &x1_normalized); + robustEstimation::applyTransformationToPoints(x2, K2Inverse, &x2_normalized); KernelBase::_kernelSolver.solve(x1_normalized, x2_normalized, models); } @@ -64,7 +66,7 @@ class EssentialKernel : public TwoViewKernel { Mat3 F; fundamentalFromEssential(model.getMatrix(), _K1, _K2, &F); - Mat3Model modelF(F); + robustEstimation::Mat3Model modelF(F); return KernelBase::_errorEstimator.error(modelF, KernelBase::_x1.col(sample), KernelBase::_x2.col(sample)); } @@ -77,12 +79,12 @@ class EssentialKernel : public TwoViewKernel /** * @brief Solver kernel for the 8pt Essential Matrix Estimation */ -typedef EssentialKernel Essential8PKernel; +typedef EssentialKernel Essential8PKernel; /** * @brief Solver kernel for the 5pt Essential Matrix Estimation */ -typedef EssentialKernel Essential5PKernel; +typedef EssentialKernel Essential5PKernel; } // namespace relativePose diff --git a/src/aliceVision/multiview/relativePose/Fundamental10PSolver.hpp b/src/aliceVision/multiview/relativePose/Fundamental10PSolver.hpp index 65d75fb7b6..037c3ec43b 100644 --- a/src/aliceVision/multiview/relativePose/Fundamental10PSolver.hpp +++ b/src/aliceVision/multiview/relativePose/Fundamental10PSolver.hpp @@ -7,22 +7,22 @@ #pragma once -#include +#include namespace aliceVision { namespace multiview { namespace relativePose { -struct Fundamental10PModel : public Mat3Model +struct Fundamental10PModel : public robustEstimation::Mat3Model { using Mat21 = Eigen::Matrix; Fundamental10PModel() - : Mat3Model() + : robustEstimation::Mat3Model() {} Fundamental10PModel(const Mat3& F, const Mat21& L) - : Mat3Model(F) , _L(L) + : robustEstimation::Mat3Model(F) , _L(L) {} inline const Mat21& getRadialDistortion() const @@ -34,7 +34,7 @@ struct Fundamental10PModel : public Mat3Model Mat21 _L; }; -class Fundamental10PSolver : public ISolver +class Fundamental10PSolver : public robustEstimation::ISolver { public: diff --git a/src/aliceVision/multiview/relativePose/Fundamental7PSolver.cpp b/src/aliceVision/multiview/relativePose/Fundamental7PSolver.cpp index 3d471ae726..00ac85ef8b 100644 --- a/src/aliceVision/multiview/relativePose/Fundamental7PSolver.cpp +++ b/src/aliceVision/multiview/relativePose/Fundamental7PSolver.cpp @@ -8,12 +8,13 @@ #include "Fundamental7PSolver.hpp" #include +#include namespace aliceVision { namespace multiview { namespace relativePose { -void Fundamental7PSolver::solve(const Mat& x1, const Mat& x2, std::vector& models) const +void Fundamental7PSolver::solve(const Mat& x1, const Mat& x2, std::vector& models) const { assert(2 == x1.rows()); assert(7 <= x1.cols()); diff --git a/src/aliceVision/multiview/relativePose/Fundamental7PSolver.hpp b/src/aliceVision/multiview/relativePose/Fundamental7PSolver.hpp index 458f220d0a..e8f4e6a393 100644 --- a/src/aliceVision/multiview/relativePose/Fundamental7PSolver.hpp +++ b/src/aliceVision/multiview/relativePose/Fundamental7PSolver.hpp @@ -8,13 +8,13 @@ #pragma once -#include +#include namespace aliceVision { namespace multiview { namespace relativePose { -class Fundamental7PSolver : public ISolver +class Fundamental7PSolver : public robustEstimation::ISolver { public: @@ -50,7 +50,7 @@ class Fundamental7PSolver : public ISolver * @param[in] x2 Corresponding points in the second image. One per column. * @param[out] models A list of at most 10 candidate essential matrix solutions. */ - void solve(const Mat& x1, const Mat& x2, std::vector& models) const override; + void solve(const Mat& x1, const Mat& x2, std::vector& models) const override; /** * @brief Solve the problem. @@ -59,7 +59,7 @@ class Fundamental7PSolver : public ISolver * @param[out] models A vector into which the computed models are stored. * @param[in] weights. */ - void solve(const Mat& x1, const Mat& x2, std::vector& models, const std::vector& weights) const override + void solve(const Mat& x1, const Mat& x2, std::vector& models, const std::vector& weights) const override { throw std::logic_error("Fundamental7PSolver does not support problem solving with weights."); } diff --git a/src/aliceVision/multiview/relativePose/Fundamental8PSolver.cpp b/src/aliceVision/multiview/relativePose/Fundamental8PSolver.cpp index d44a8ad619..51e9e4af98 100644 --- a/src/aliceVision/multiview/relativePose/Fundamental8PSolver.cpp +++ b/src/aliceVision/multiview/relativePose/Fundamental8PSolver.cpp @@ -7,12 +7,13 @@ // You can obtain one at https://mozilla.org/MPL/2.0/. #include "Fundamental8PSolver.hpp" +#include namespace aliceVision { namespace multiview { namespace relativePose { -void solveProblem(const Mat& x1, const Mat& x2, std::vector& models, const std::vector* weights = nullptr) +void solveProblem(const Mat& x1, const Mat& x2, std::vector& models, const std::vector* weights = nullptr) { assert(2 == x1.rows()); assert(8 <= x1.cols()); @@ -53,12 +54,12 @@ void solveProblem(const Mat& x1, const Mat& x2, std::vector& models, models.emplace_back(F); } -void Fundamental8PSolver::solve(const Mat& x1, const Mat& x2, std::vector& models) const +void Fundamental8PSolver::solve(const Mat& x1, const Mat& x2, std::vector& models) const { solveProblem(x1, x2, models); } -void Fundamental8PSolver::solve(const Mat& x1, const Mat& x2, std::vector& models, const std::vector& weights) const +void Fundamental8PSolver::solve(const Mat& x1, const Mat& x2, std::vector& models, const std::vector& weights) const { solveProblem(x1, x2, models, &weights); } diff --git a/src/aliceVision/multiview/relativePose/Fundamental8PSolver.hpp b/src/aliceVision/multiview/relativePose/Fundamental8PSolver.hpp index 112c9e0e4c..6fcb6f4bad 100644 --- a/src/aliceVision/multiview/relativePose/Fundamental8PSolver.hpp +++ b/src/aliceVision/multiview/relativePose/Fundamental8PSolver.hpp @@ -8,13 +8,13 @@ #pragma once -#include +#include namespace aliceVision { namespace multiview { namespace relativePose { -class Fundamental8PSolver : public ISolver +class Fundamental8PSolver : public robustEstimation::ISolver { public: @@ -42,7 +42,7 @@ class Fundamental8PSolver : public ISolver * @param[in] x2 Corresponding points in the second image. One per column. * @param[out] models A list of at most 10 candidate essential matrix solutions. */ - void solve(const Mat& x1, const Mat& x2, std::vector& models) const override; + void solve(const Mat& x1, const Mat& x2, std::vector& models) const override; /** * @brief Solve the problem. @@ -51,7 +51,7 @@ class Fundamental8PSolver : public ISolver * @param[out] models A vector into which the computed models are stored. * @param[in] weights. */ - void solve(const Mat& x1, const Mat& x2, std::vector& models, const std::vector& weights) const override; + void solve(const Mat& x1, const Mat& x2, std::vector& models, const std::vector& weights) const override; }; } // namespace relativePose diff --git a/src/aliceVision/multiview/relativePose/FundamentalError.hpp b/src/aliceVision/multiview/relativePose/FundamentalError.hpp index 0c0162bcff..f9056a25ec 100644 --- a/src/aliceVision/multiview/relativePose/FundamentalError.hpp +++ b/src/aliceVision/multiview/relativePose/FundamentalError.hpp @@ -8,7 +8,8 @@ #pragma once -#include +#include +#include namespace aliceVision { namespace multiview { @@ -17,9 +18,9 @@ namespace relativePose { /** * @brief Compute FundamentalSampsonError related to the Fundamental matrix and 2 correspondences */ -struct FundamentalSampsonError : public ISolverErrorRelativePose +struct FundamentalSampsonError : public ISolverErrorRelativePose { - inline double error(const Mat3Model& F, const Vec2& x1, const Vec2& x2) const override + inline double error(const robustEstimation::Mat3Model& F, const Vec2& x1, const Vec2& x2) const override { const Vec3 x(x1(0), x1(1), 1.0); const Vec3 y(x2(0), x2(1), 1.0); @@ -32,9 +33,9 @@ struct FundamentalSampsonError : public ISolverErrorRelativePose } }; -struct FundamentalSymmetricEpipolarDistanceError: public ISolverErrorRelativePose +struct FundamentalSymmetricEpipolarDistanceError: public ISolverErrorRelativePose { - inline double error(const Mat3Model& F, const Vec2& x1, const Vec2& x2) const override + inline double error(const robustEstimation::Mat3Model& F, const Vec2& x1, const Vec2& x2) const override { const Vec3 x(x1(0), x1(1), 1.0); const Vec3 y(x2(0), x2(1), 1.0); @@ -48,9 +49,9 @@ struct FundamentalSymmetricEpipolarDistanceError: public ISolverErrorRelativePos } }; -struct FundamentalEpipolarDistanceError : public ISolverErrorRelativePose +struct FundamentalEpipolarDistanceError : public ISolverErrorRelativePose { - inline double error(const Mat3Model& F, const Vec2& x1, const Vec2& x2) const override + inline double error(const robustEstimation::Mat3Model& F, const Vec2& x1, const Vec2& x2) const override { // transfer error in image 2 // @see page 287 equation (11.9) of HZ. diff --git a/src/aliceVision/multiview/relativePose/FundamentalKernel.hpp b/src/aliceVision/multiview/relativePose/FundamentalKernel.hpp index fef7449c67..920a23dfca 100644 --- a/src/aliceVision/multiview/relativePose/FundamentalKernel.hpp +++ b/src/aliceVision/multiview/relativePose/FundamentalKernel.hpp @@ -8,10 +8,11 @@ #pragma once -#include +#include #include #include #include +#include namespace aliceVision { namespace multiview { @@ -20,24 +21,24 @@ namespace relativePose { /** * @brief Kernel solver for the 8pt Fundamental Matrix Estimation */ -typedef TwoViewKernel Fundamental7PKernel; +typedef robustEstimation::FittingKernel Fundamental7PKernel; /** * @brief Kernel solver for the 8pt Fundamental Matrix Estimation */ -typedef TwoViewKernel Fundamental8PKernel; +typedef robustEstimation::FittingKernel Fundamental8PKernel; /** * @brief Normalized 7pt kernel * @see conditioning from HZ (Algo 11.1) pag 282 */ -typedef NormalizedTwoViewKernel NormalizedFundamental7PKernel; +typedef robustEstimation::NormalizedFittingKernel NormalizedFundamental7PKernel; /** * @brief Normalized 8pt kernel * @see conditioning from HZ (Algo 11.1) pag 282 */ -typedef NormalizedTwoViewKernel NormalizedFundamental8PKernel; +typedef robustEstimation::NormalizedFittingKernel NormalizedFundamental8PKernel; } // namespace relativePose } // namespace multiview diff --git a/src/aliceVision/multiview/relativePose/Homography4PSolver.cpp b/src/aliceVision/multiview/relativePose/Homography4PSolver.cpp index 808daccb46..ae7838e83f 100644 --- a/src/aliceVision/multiview/relativePose/Homography4PSolver.cpp +++ b/src/aliceVision/multiview/relativePose/Homography4PSolver.cpp @@ -41,7 +41,7 @@ void buildActionMatrix(Matrix& L, const Mat& x1, const Mat& x2) } } -void Homography4PSolver::solve(const Mat& x1, const Mat& x2, std::vector& models) const +void Homography4PSolver::solve(const Mat& x1, const Mat& x2, std::vector& models) const { assert(2 == x1.rows()); assert(4 <= x1.cols()); diff --git a/src/aliceVision/multiview/relativePose/Homography4PSolver.hpp b/src/aliceVision/multiview/relativePose/Homography4PSolver.hpp index 94c54ca584..85511a4841 100644 --- a/src/aliceVision/multiview/relativePose/Homography4PSolver.hpp +++ b/src/aliceVision/multiview/relativePose/Homography4PSolver.hpp @@ -8,13 +8,13 @@ #pragma once -#include +#include namespace aliceVision { namespace multiview { namespace relativePose { -class Homography4PSolver : public ISolver +class Homography4PSolver : public robustEstimation::ISolver { public: @@ -46,7 +46,7 @@ class Homography4PSolver : public ISolver * * The estimated homography should approximately hold the condition y = H x. */ - void solve(const Mat& x, const Mat& y, std::vector& models) const override; + void solve(const Mat& x, const Mat& y, std::vector& models) const override; /** * @brief Solve the problem. @@ -55,7 +55,7 @@ class Homography4PSolver : public ISolver * @param[out] models A vector into which the computed models are stored. * @param[in] weights. */ - void solve(const Mat& x1, const Mat& x2, std::vector& models, const std::vector& weights) const override + void solve(const Mat& x1, const Mat& x2, std::vector& models, const std::vector& weights) const override { throw std::logic_error("Homography4PSolver does not support problem solving with weights."); } diff --git a/src/aliceVision/multiview/relativePose/HomographyError.hpp b/src/aliceVision/multiview/relativePose/HomographyError.hpp index 83197ad585..20cce0144c 100644 --- a/src/aliceVision/multiview/relativePose/HomographyError.hpp +++ b/src/aliceVision/multiview/relativePose/HomographyError.hpp @@ -8,9 +8,9 @@ #pragma once - -#include -#include +#include +#include +#include namespace aliceVision { namespace multiview { @@ -20,9 +20,9 @@ namespace relativePose { * @brief The HomographyAsymmetricError struct * @note Should be distributed as Chi-squared with k = 2. */ -struct HomographyAsymmetricError : ISolverErrorRelativePose +struct HomographyAsymmetricError : ISolverErrorRelativePose { - inline double error(const Mat3Model& H, const Vec2& x1, const Vec2& x2) const + inline double error(const robustEstimation::Mat3Model& H, const Vec2& x1, const Vec2& x2) const { Vec3 x2h_est = H.getMatrix() * euclideanToHomogeneous(x1); Vec2 x2_est = x2h_est.head<2>() / x2h_est[2]; diff --git a/src/aliceVision/multiview/relativePose/HomographyKernel.hpp b/src/aliceVision/multiview/relativePose/HomographyKernel.hpp index 6f5de5ace9..9a44abfb94 100644 --- a/src/aliceVision/multiview/relativePose/HomographyKernel.hpp +++ b/src/aliceVision/multiview/relativePose/HomographyKernel.hpp @@ -8,9 +8,10 @@ #pragma once -#include +#include #include #include +#include namespace aliceVision { namespace multiview { @@ -19,12 +20,12 @@ namespace relativePose { /** * @brief Kernel that works on original data point */ -typedef TwoViewKernel Homography4PKernel; +typedef robustEstimation::FittingKernel Homography4PKernel; /** * @brief By default use the normalized version for increased robustness. */ -typedef NormalizedTwoViewKernel NormalizedHomography4PKernel; +typedef robustEstimation::NormalizedFittingKernel NormalizedHomography4PKernel; } // namespace relativePose } // namespace multiview diff --git a/src/aliceVision/multiview/relativePose/ISolverErrorRelativePose.hpp b/src/aliceVision/multiview/relativePose/ISolverErrorRelativePose.hpp new file mode 100644 index 0000000000..9fdbc2de96 --- /dev/null +++ b/src/aliceVision/multiview/relativePose/ISolverErrorRelativePose.hpp @@ -0,0 +1,24 @@ +// This file is part of the AliceVision project. +// Copyright (c) 2019 AliceVision contributors. +// This Source Code Form is subject to the terms of the Mozilla Public License, +// v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +namespace aliceVision { +namespace multiview { +namespace relativePose { + +/** + * @brief Relative pose solver error interface. + */ +template +struct ISolverErrorRelativePose +{ + virtual double error(const ModelT& model, const Vec2& x1, const Vec2& x2) const = 0; +}; + +} // namespace relativePose +} // namespace multiview +} // namespace aliceVision diff --git a/src/aliceVision/multiview/relativePose/essential5PSolver_test.cpp b/src/aliceVision/multiview/relativePose/essential5PSolver_test.cpp index 92e1f5bdb5..6d7788a0ee 100644 --- a/src/aliceVision/multiview/relativePose/essential5PSolver_test.cpp +++ b/src/aliceVision/multiview/relativePose/essential5PSolver_test.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include @@ -158,7 +158,7 @@ BOOST_AUTO_TEST_CASE(FivePointsRelativePose_Random) { TestData d = SomeTestData(); - std::vector Es; + std::vector Es; std::vector Rs; std::vector ts; @@ -213,7 +213,7 @@ BOOST_AUTO_TEST_CASE(FivePointsRelativePose_test_data_sets) // Compute pose [R|t] from 0 to [1;..;iNviews] for(int i=1; i Es; // Essential. + std::vector Es; // Essential. std::vector Rs; // Rotation matrix. std::vector ts; // Translation matrix. diff --git a/src/aliceVision/multiview/relativePose/essentialKernel_test.cpp b/src/aliceVision/multiview/relativePose/essentialKernel_test.cpp index 34c482f2aa..37b1cd25bb 100644 --- a/src/aliceVision/multiview/relativePose/essentialKernel_test.cpp +++ b/src/aliceVision/multiview/relativePose/essentialKernel_test.cpp @@ -6,7 +6,7 @@ // v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. -#include +#include #include #include #include @@ -37,7 +37,7 @@ BOOST_AUTO_TEST_CASE(Essential8PSolver_IdFocal) for(int i=0; i Es; // essential, + std::vector Es; // essential, std::vector Rs; // rotation matrix. std::vector ts; // translation matrix. @@ -99,7 +99,7 @@ BOOST_AUTO_TEST_CASE(Essential8PKernel_EightPointsRelativePose) for(int i=0; i Es; // Essential + std::vector Es; // Essential std::vector Rs; // Rotation matrix. std::vector ts; // Translation matrix. @@ -176,7 +176,7 @@ BOOST_AUTO_TEST_CASE(Essential5PKernel_KernelError) for (std::size_t i = 0; i < x1.cols(); ++i) { samples.push_back(i); } - std::vector Es; + std::vector Es; kernel.fit(samples, Es); bOk &= (!Es.empty()); @@ -201,7 +201,7 @@ BOOST_AUTO_TEST_CASE(Essential5PKernel_FivePointsRelativePose) std::size_t found = 0; for(int i=1; i Es; // Essential + std::vector Es; // Essential std::vector Rs; // Rotation matrix. std::vector ts; // Translation matrix. diff --git a/src/aliceVision/multiview/relativePose/fundamentalKernel_test.cpp b/src/aliceVision/multiview/relativePose/fundamentalKernel_test.cpp index 6c18f3086b..cd636a0b7b 100644 --- a/src/aliceVision/multiview/relativePose/fundamentalKernel_test.cpp +++ b/src/aliceVision/multiview/relativePose/fundamentalKernel_test.cpp @@ -6,7 +6,8 @@ // v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. -#include +#include +#include #include #define BOOST_TEST_MODULE fundamentalKernelSolver @@ -75,7 +76,7 @@ bool expectKernelProperties(const Mat& x1, const Mat& x2, Mat3* F_expected = nul for(std::size_t i = 0; i < x1.cols(); ++i) samples.push_back(i); - std::vector Fs; + std::vector Fs; kernel.fit(samples, Fs); bOk &= (!Fs.empty()); diff --git a/src/aliceVision/multiview/relativePose/homographyKernel_test.cpp b/src/aliceVision/multiview/relativePose/homographyKernel_test.cpp index c10480d4d4..fbe6faaa86 100644 --- a/src/aliceVision/multiview/relativePose/homographyKernel_test.cpp +++ b/src/aliceVision/multiview/relativePose/homographyKernel_test.cpp @@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(NormalizedHomography4PKernel_Fitting) std::vector samples(samples_,samples_+5); for(std::size_t j = 4; samples.size() < x.cols(); samples.push_back(j++)) { - std::vector Hs; + std::vector Hs; kernel.fit(samples, Hs); BOOST_CHECK_EQUAL(1, Hs.size()); @@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE(Homography4PKernel_Fitting) for(std::size_t j = 4; samples.size() < x.cols(); samples.push_back(j++)) { - std::vector Hs; + std::vector Hs; kernel.fit(samples, Hs); BOOST_CHECK_EQUAL(1, Hs.size()); diff --git a/src/aliceVision/multiview/resection/EPnPKernel.hpp b/src/aliceVision/multiview/resection/EPnPKernel.hpp index 316a690459..b93e383381 100644 --- a/src/aliceVision/multiview/resection/EPnPKernel.hpp +++ b/src/aliceVision/multiview/resection/EPnPKernel.hpp @@ -9,8 +9,8 @@ #include #include -#include -#include +#include +#include namespace aliceVision { namespace multiview { @@ -20,11 +20,11 @@ namespace resection { * @brief Euclidean (EPnP) resection kernel * @note Have K intrinsic helps */ -class EPnPKernel : public TwoViewKernel +class EPnPKernel : public robustEstimation::FittingKernel { public: - using KernelBase = TwoViewKernel; + using KernelBase = robustEstimation::FittingKernel; EPnPKernel(const Mat2X& x2d, const Mat3X& x3d) : KernelBase(x2d, x3d) @@ -44,7 +44,7 @@ class EPnPKernel : public TwoViewKernel& samples, std::vector& models) const override + void fit(const std::vector& samples, std::vector& models) const override { Mat2X x = ExtractColumns(x_camera_, samples); Mat3X X = ExtractColumns(X_, samples); diff --git a/src/aliceVision/multiview/resection/EPnPSolver.cpp b/src/aliceVision/multiview/resection/EPnPSolver.cpp index 38866b3a1d..5fb651027e 100644 --- a/src/aliceVision/multiview/resection/EPnPSolver.cpp +++ b/src/aliceVision/multiview/resection/EPnPSolver.cpp @@ -6,7 +6,7 @@ // You can obtain one at https://mozilla.org/MPL/2.0/. #include "EPnPSolver.hpp" -#include +#include namespace aliceVision { namespace multiview { @@ -457,7 +457,7 @@ bool EPnPSolver::resection(const Mat2X& x2d, const Mat3X& x3d, Mat3* R, Vec3* t) return false; } -void EPnPSolver::solve(const Mat& x2d, const Mat& x3d, std::vector& models) const +void EPnPSolver::solve(const Mat& x2d, const Mat& x3d, std::vector& models) const { Mat3 R; Vec3 t; diff --git a/src/aliceVision/multiview/resection/EPnPSolver.hpp b/src/aliceVision/multiview/resection/EPnPSolver.hpp index 196372ba4c..7ea30e62c6 100644 --- a/src/aliceVision/multiview/resection/EPnPSolver.hpp +++ b/src/aliceVision/multiview/resection/EPnPSolver.hpp @@ -7,13 +7,13 @@ #pragma once -#include +#include namespace aliceVision { namespace multiview { namespace resection { -class EPnPSolver : public ISolver +class EPnPSolver : public robustEstimation::ISolver { public: @@ -42,7 +42,7 @@ class EPnPSolver : public ISolver * @param[in] x3d Corresponding 3d points in the second image. One per column. * @param[out] models A list of solutions. */ - void solve(const Mat& x2d, const Mat& x3d, std::vector& models) const override; + void solve(const Mat& x2d, const Mat& x3d, std::vector& models) const override; /** * @brief Solve the problem. @@ -52,7 +52,7 @@ class EPnPSolver : public ISolver * @param[out] models A vector into which the computed models are stored. * @param[in] weights. */ - void solve(const Mat& x2d, const Mat& x3d, std::vector& models, const std::vector& weights) const override + void solve(const Mat& x2d, const Mat& x3d, std::vector& models, const std::vector& weights) const override { throw std::logic_error("EPnPSolver does not support problem solving with weights."); } diff --git a/src/aliceVision/multiview/resection/ISolverErrorResection.hpp b/src/aliceVision/multiview/resection/ISolverErrorResection.hpp new file mode 100644 index 0000000000..d887b05fd6 --- /dev/null +++ b/src/aliceVision/multiview/resection/ISolverErrorResection.hpp @@ -0,0 +1,24 @@ +// This file is part of the AliceVision project. +// Copyright (c) 2019 AliceVision contributors. +// This Source Code Form is subject to the terms of the Mozilla Public License, +// v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +#pragma once + +namespace aliceVision { +namespace multiview { +namespace resection { + +/** + * @brief Resection solver error interface. + */ +template +struct ISolverErrorResection +{ + virtual double error(const ModelT& model, const Vec2& x2d, const Vec3& x3d) const = 0; +}; + +} // namespace resection +} // namespace multiview +} // namespace aliceVision diff --git a/src/aliceVision/multiview/resection/P3PSolver.cpp b/src/aliceVision/multiview/resection/P3PSolver.cpp index b00ecbbeea..6c478810cc 100644 --- a/src/aliceVision/multiview/resection/P3PSolver.cpp +++ b/src/aliceVision/multiview/resection/P3PSolver.cpp @@ -7,7 +7,7 @@ // You can obtain one at https://mozilla.org/MPL/2.0/. #include "P3PSolver.hpp" -#include +#include namespace aliceVision { namespace multiview { @@ -253,7 +253,7 @@ bool computeP3PPoses(const Mat3& featureVectors, const Mat3& worldPoints, Mat& s return true; } -void P3PSolver::solve(const Mat& x2d, const Mat& x3d, std::vector& models) const +void P3PSolver::solve(const Mat& x2d, const Mat& x3d, std::vector& models) const { assert(2 == x2d.rows()); assert(3 == x3d.rows()); diff --git a/src/aliceVision/multiview/resection/P3PSolver.hpp b/src/aliceVision/multiview/resection/P3PSolver.hpp index afd3ec4724..bd9b58d81f 100644 --- a/src/aliceVision/multiview/resection/P3PSolver.hpp +++ b/src/aliceVision/multiview/resection/P3PSolver.hpp @@ -8,7 +8,7 @@ #pragma once -#include +#include namespace aliceVision { namespace multiview { @@ -16,7 +16,7 @@ namespace resection { typedef Eigen::Matrix Vec5; -class P3PSolver : public ISolver +class P3PSolver : public robustEstimation::ISolver { public: @@ -45,7 +45,7 @@ class P3PSolver : public ISolver * @param[in] x3d Corresponding 3d points in the second image. One per column. * @param[out] models A list of at most 4 candidate solutions. */ - void solve(const Mat& x2d, const Mat& x3d, std::vector& models) const override; + void solve(const Mat& x2d, const Mat& x3d, std::vector& models) const override; /** * @brief Solve the problem. @@ -55,7 +55,7 @@ class P3PSolver : public ISolver * @param[out] models A vector into which the computed models are stored. * @param[in] weights. */ - void solve(const Mat& x2d, const Mat& x3d, std::vector& models, const std::vector& weights) const override + void solve(const Mat& x2d, const Mat& x3d, std::vector& models, const std::vector& weights) const override { throw std::logic_error("P3PSolver does not support problem solving with weights."); } diff --git a/src/aliceVision/multiview/resection/P4PfSolver.cpp b/src/aliceVision/multiview/resection/P4PfSolver.cpp index e1abba2acc..8494142fb8 100644 --- a/src/aliceVision/multiview/resection/P4PfSolver.cpp +++ b/src/aliceVision/multiview/resection/P4PfSolver.cpp @@ -5,7 +5,7 @@ // You can obtain one at https://mozilla.org/MPL/2.0/. #include "P4PfSolver.hpp" -#include +#include #include #include diff --git a/src/aliceVision/multiview/resection/P4PfSolver.hpp b/src/aliceVision/multiview/resection/P4PfSolver.hpp index 1ceaeec4d9..38b94091c4 100644 --- a/src/aliceVision/multiview/resection/P4PfSolver.hpp +++ b/src/aliceVision/multiview/resection/P4PfSolver.hpp @@ -6,8 +6,9 @@ #pragma once -#include -#include +#include +#include +#include namespace aliceVision { namespace multiview { @@ -68,7 +69,7 @@ struct P4PfError : public ISolverErrorResection * Bujnak, M., Kukelova, Z., and Pajdla T. * CVPR 2008 */ -class P4PfSolver : public ISolver +class P4PfSolver : public robustEstimation::ISolver { public: diff --git a/src/aliceVision/multiview/resection/P5PfrSolver.cpp b/src/aliceVision/multiview/resection/P5PfrSolver.cpp index 0bac08017e..4298757db1 100644 --- a/src/aliceVision/multiview/resection/P5PfrSolver.cpp +++ b/src/aliceVision/multiview/resection/P5PfrSolver.cpp @@ -5,7 +5,7 @@ // You can obtain one at https://mozilla.org/MPL/2.0/. #include "P5PfrSolver.hpp" -#include +#include #include #include diff --git a/src/aliceVision/multiview/resection/P5PfrSolver.hpp b/src/aliceVision/multiview/resection/P5PfrSolver.hpp index 4860264ea9..6d5d19eb96 100644 --- a/src/aliceVision/multiview/resection/P5PfrSolver.hpp +++ b/src/aliceVision/multiview/resection/P5PfrSolver.hpp @@ -6,7 +6,8 @@ #pragma once -#include +#include +#include namespace aliceVision { namespace multiview { @@ -102,7 +103,7 @@ struct P5PfrError : public ISolverErrorResection * ICCV 2013 */ template -class P5PfrSolver : public ISolver +class P5PfrSolver : public robustEstimation::ISolver { public: diff --git a/src/aliceVision/multiview/resection/ProjectionDistanceError.hpp b/src/aliceVision/multiview/resection/ProjectionDistanceError.hpp index b2d1335618..80d975e353 100644 --- a/src/aliceVision/multiview/resection/ProjectionDistanceError.hpp +++ b/src/aliceVision/multiview/resection/ProjectionDistanceError.hpp @@ -7,8 +7,10 @@ #pragma once -#include -#include +#include +#include +#include + namespace aliceVision { namespace multiview { @@ -18,9 +20,9 @@ namespace resection { * @brief Compute the residual of the projection distance * (pt2D, project(P,pt3D)) */ -struct ProjectionDistanceError : public ISolverErrorResection +struct ProjectionDistanceError : public ISolverErrorResection { - inline double error(const Mat34Model& P, const Vec2& p2d, const Vec3& p3d) const override + inline double error(const robustEstimation::Mat34Model& P, const Vec2& p2d, const Vec3& p3d) const override { return (project(P.getMatrix(), p3d) - p2d).norm(); } @@ -30,9 +32,9 @@ struct ProjectionDistanceError : public ISolverErrorResection * @brief Compute the residual of the projection distance * (pt2D, project(P,pt3D)) */ -struct ProjectionDistanceSquaredError : public ISolverErrorResection +struct ProjectionDistanceSquaredError : public ISolverErrorResection { - inline double error(const Mat34Model& P, const Vec2& p2d, const Vec3& p3d) const override + inline double error(const robustEstimation::Mat34Model& P, const Vec2& p2d, const Vec3& p3d) const override { return (project(P.getMatrix(), p3d) - p2d).squaredNorm(); } diff --git a/src/aliceVision/multiview/resection/Resection6PSolver.cpp b/src/aliceVision/multiview/resection/Resection6PSolver.cpp index 477ee27a04..b3c1f331b0 100644 --- a/src/aliceVision/multiview/resection/Resection6PSolver.cpp +++ b/src/aliceVision/multiview/resection/Resection6PSolver.cpp @@ -6,7 +6,7 @@ // You can obtain one at https://mozilla.org/MPL/2.0/. #include "Resection6PSolver.hpp" -#include +#include namespace aliceVision { namespace multiview { @@ -74,7 +74,7 @@ void BuildActionMatrix(Matrix& A, const Mat& pt2D, const Mat& XPoints) A.row(i).normalize(); } -void solveProblem(const Mat& x2d, const Mat& x3d, std::vector& models, bool bcheck) +void solveProblem(const Mat& x2d, const Mat& x3d, std::vector& models, bool bcheck) { assert(2 == x2d.rows()); assert(3 == x3d.rows()); @@ -148,12 +148,12 @@ void solveProblem(const Mat& x2d, const Mat& x3d, std::vector& model } } -void Resection6PSolver::solve(const Mat& x2d, const Mat& x3d, std::vector& models) const +void Resection6PSolver::solve(const Mat& x2d, const Mat& x3d, std::vector& models) const { solveProblem(x2d, x3d, models, true); } -void Resection6PSolver::solve(const Mat& x2d, const Mat& x3d, std::vector& models, const std::vector& weights) const +void Resection6PSolver::solve(const Mat& x2d, const Mat& x3d, std::vector& models, const std::vector& weights) const { solveProblem(x2d, x3d, models, true); // TODO : no weights implementation } diff --git a/src/aliceVision/multiview/resection/Resection6PSolver.hpp b/src/aliceVision/multiview/resection/Resection6PSolver.hpp index f01ef8fe21..4a6dfeec14 100644 --- a/src/aliceVision/multiview/resection/Resection6PSolver.hpp +++ b/src/aliceVision/multiview/resection/Resection6PSolver.hpp @@ -7,13 +7,13 @@ #pragma once -#include +#include namespace aliceVision { namespace multiview { namespace resection { -class Resection6PSolver : public ISolver +class Resection6PSolver : public robustEstimation::ISolver { public: @@ -48,7 +48,7 @@ class Resection6PSolver : public ISolver * @param[in] x3d Corresponding 3d points in the second image. One per column. * @param[out] models A list of solutions. */ - void solve(const Mat& x2d, const Mat& x3d, std::vector& models) const override; + void solve(const Mat& x2d, const Mat& x3d, std::vector& models) const override; /** * @brief Solve the problem. @@ -58,7 +58,7 @@ class Resection6PSolver : public ISolver * @param[out] models A vector into which the computed models are stored. * @param[in] weights. */ - void solve(const Mat& x2d, const Mat& x3d, std::vector& models, const std::vector& weights) const override; + void solve(const Mat& x2d, const Mat& x3d, std::vector& models, const std::vector& weights) const override; }; } // namespace resection diff --git a/src/aliceVision/multiview/resection/ResectionKernel.hpp b/src/aliceVision/multiview/resection/ResectionKernel.hpp index 0f2fa83d6e..2651b55433 100644 --- a/src/aliceVision/multiview/resection/ResectionKernel.hpp +++ b/src/aliceVision/multiview/resection/ResectionKernel.hpp @@ -7,7 +7,7 @@ #pragma once -#include +#include #include #include @@ -18,15 +18,15 @@ namespace resection { /** * @brief Generic solver for resection algorithm using linear least squares. */ -template -class ResectionKernel : public TwoViewKernel +template +class ResectionKernel : public robustEstimation::FittingKernel { public: - using KernelBase = TwoViewKernel; + using KernelBase = robustEstimation::FittingKernel; ResectionKernel(const Mat& x2d, const Mat& x3d) - : TwoViewKernel(x2d, x3d) + : robustEstimation::FittingKernel(x2d, x3d) {} void fit(const std::vector& samples, std::vector& models) const override @@ -46,7 +46,7 @@ class ResectionKernel : public TwoViewKernel /** * @brief Usable solver for the 6pt Resection estimation */ -typedef TwoViewKernel Resection6PKernel; +typedef robustEstimation::FittingKernel Resection6PKernel; } // namespace resection } // namespace multiview diff --git a/src/aliceVision/multiview/resection/resectionKernel_test.cpp b/src/aliceVision/multiview/resection/resectionKernel_test.cpp index 8e8ca3d52b..72698a9043 100644 --- a/src/aliceVision/multiview/resection/resectionKernel_test.cpp +++ b/src/aliceVision/multiview/resection/resectionKernel_test.cpp @@ -38,7 +38,7 @@ BOOST_AUTO_TEST_CASE(Resection_Kernel_Multiview) std::size_t samples_[6]={0,1,2,3,4,5}; std::vector samples(samples_,samples_+6); - std::vector Ps; + std::vector Ps; kernel.fit(samples, Ps); @@ -74,7 +74,7 @@ BOOST_AUTO_TEST_CASE(P3P_Kneip_CVPR11_Multiview) std::size_t samples_[3]={0,1,2}; std::vector samples(samples_, samples_+3); - std::vector Ps; + std::vector Ps; kernel.fit(samples, Ps); bool bFound = false; @@ -192,7 +192,7 @@ BOOST_AUTO_TEST_CASE(EuclideanResection_Points6AllRandomInput) { std::size_t samples_[6]={0,1,2,3,4,5}; std::vector samples(samples_, samples_+6); - std::vector Ps; + std::vector Ps; kernel.fit(samples, Ps); BOOST_CHECK_EQUAL(1, Ps.size()); diff --git a/src/aliceVision/multiview/resection/resectionLORansac_test.cpp b/src/aliceVision/multiview/resection/resectionLORansac_test.cpp index e7bd960d83..4fc913f862 100644 --- a/src/aliceVision/multiview/resection/resectionLORansac_test.cpp +++ b/src/aliceVision/multiview/resection/resectionLORansac_test.cpp @@ -4,14 +4,15 @@ // v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. +#include #include -#include +#include #include #include -#include #include #include -#include +#include +#include #include #include #include @@ -176,23 +177,23 @@ BOOST_AUTO_TEST_CASE(P3P_Ransac_noisyFromImagePoints) typedef multiview::resection::P3PSolver SolverType; typedef multiview::resection::Resection6PSolver SolverLSType; - typedef aliceVision::robustEstimation::ResectionKernel_K KernelType; + typedef aliceVision::multiview::ResectionKernel_K KernelType; // this is just to simplify and use image plane coordinates instead of camera // (pixel) coordinates Mat pts2Dnorm; - multiview::applyTransformationToPoints(pts2D, Kgt.inverse(), &pts2Dnorm); + robustEstimation::applyTransformationToPoints(pts2D, Kgt.inverse(), &pts2Dnorm); KernelType kernel(pts2Dnorm, pts3D, Mat3::Identity()); std::vector inliers; const double threshold = 2*gaussianNoiseLevel; const double normalizedThreshold = Square(threshold / FOCAL); robustEstimation::ScoreEvaluator scorer(normalizedThreshold); - multiview::Mat34Model model = robustEstimation::LO_RANSAC(kernel, scorer, &inliers); + robustEstimation::Mat34Model model = robustEstimation::LO_RANSAC(kernel, scorer, &inliers); Mat34 Pest = model.getMatrix(); const std::size_t numInliersFound = inliers.size(); const std::size_t numInliersExpected = nbPoints-vec_outliers.size(); diff --git a/src/aliceVision/multiview/triangulation/NViewsTriangulationLORansac.hpp b/src/aliceVision/multiview/triangulation/NViewsTriangulationLORansac.hpp index d004c9bc38..05fdf99a8d 100644 --- a/src/aliceVision/multiview/triangulation/NViewsTriangulationLORansac.hpp +++ b/src/aliceVision/multiview/triangulation/NViewsTriangulationLORansac.hpp @@ -9,10 +9,12 @@ #pragma once #include -#include -#include +#include #include -#include +#include +#include +#include +#include #include #include @@ -36,7 +38,7 @@ namespace multiview { * a solution from any set of data larger than the minimum required, usually a * DLT algorithm. */ -template , typename SolverLsT_ = UndefinedSolver> +template , typename SolverLsT_ = robustEstimation::UndefinedSolver> class NViewsTriangulationLORansac : public robustEstimation::IRansacKernel { @@ -218,7 +220,7 @@ class NViewsTriangulationLORansac /** * @brief Functor used to compute the reprojection error as the pixel error. */ -template> +template> struct ReprojectionError { /** @@ -238,7 +240,7 @@ struct ReprojectionError /** * @brief Functor used to compute the error as the angular error. */ -template> +template> struct AngularError { /** @@ -262,7 +264,7 @@ struct AngularError // ReprojectionError, // UnnormalizerT, // TriangulateNViewsSolver> LORansacTriangulationKernel; -template>> -using LORansacTriangulationKernel = NViewsTriangulationLORansac, TriangulateNViewsSolver>; +template>> +using LORansacTriangulationKernel = NViewsTriangulationLORansac, TriangulateNViewsSolver>; } // namespace multiview } // namespace aliceVision diff --git a/src/aliceVision/multiview/triangulation/Triangulation.cpp b/src/aliceVision/multiview/triangulation/Triangulation.cpp index 750ea44d25..a332e2d35a 100644 --- a/src/aliceVision/multiview/triangulation/Triangulation.cpp +++ b/src/aliceVision/multiview/triangulation/Triangulation.cpp @@ -8,7 +8,7 @@ #include "Triangulation.hpp" #include "NViewsTriangulationLORansac.hpp" -#include +#include #include #include @@ -66,7 +66,7 @@ void TriangulateNViewLORANSAC(const Mat2X& x, using TriangulationKernel = multiview::LORansacTriangulationKernel<>; TriangulationKernel kernel(x, Ps); robustEstimation::ScoreEvaluator scorer(thresholdError); - multiview::MatrixModel model; + robustEstimation::MatrixModel model; model = robustEstimation::LO_RANSAC(kernel, scorer, inliersIndex); *X = model.getMatrix(); } @@ -145,19 +145,19 @@ Vec3 Triangulation::compute(int iter) const return X; } -void TriangulateNViewsSolver::solve(const Mat2X& x, const std::vector& Ps, std::vector> &X) const +void TriangulateNViewsSolver::solve(const Mat2X& x, const std::vector& Ps, std::vector> &X) const { Vec4 pt3d; TriangulateNViewAlgebraic(x, Ps, &pt3d); - X.push_back(MatrixModel(pt3d)); + X.push_back(robustEstimation::MatrixModel(pt3d)); assert(X.size() == 1); } -void TriangulateNViewsSolver::solve(const Mat2X& x, const std::vector& Ps, std::vector> &X, const std::vector &weights) const +void TriangulateNViewsSolver::solve(const Mat2X& x, const std::vector& Ps, std::vector> &X, const std::vector &weights) const { Vec4 pt3d; TriangulateNViewAlgebraic(x, Ps, &pt3d, &weights); - X.push_back(MatrixModel(pt3d)); + X.push_back(robustEstimation::MatrixModel(pt3d)); assert(X.size() == 1); } diff --git a/src/aliceVision/multiview/triangulation/Triangulation.hpp b/src/aliceVision/multiview/triangulation/Triangulation.hpp index 5c35e4276d..0b976cc51f 100644 --- a/src/aliceVision/multiview/triangulation/Triangulation.hpp +++ b/src/aliceVision/multiview/triangulation/Triangulation.hpp @@ -9,7 +9,7 @@ #pragma once #include -#include +#include #include @@ -127,9 +127,9 @@ struct TriangulateNViewsSolver return 1; } - void solve(const Mat2X& x, const std::vector& Ps, std::vector>& X) const; + void solve(const Mat2X& x, const std::vector& Ps, std::vector>& X) const; - void solve(const Mat2X& x, const std::vector& Ps, std::vector>& X, const std::vector& weights) const; + void solve(const Mat2X& x, const std::vector& Ps, std::vector>& X, const std::vector& weights) const; }; diff --git a/src/aliceVision/multiview/triangulation/triangulationDLT.cpp b/src/aliceVision/multiview/triangulation/triangulationDLT.cpp index 8f307a5012..a7ad1d72c8 100644 --- a/src/aliceVision/multiview/triangulation/triangulationDLT.cpp +++ b/src/aliceVision/multiview/triangulation/triangulationDLT.cpp @@ -6,7 +6,7 @@ // v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. -#include +#include #include namespace aliceVision { diff --git a/src/aliceVision/multiview/triangulation/triangulationDLT_test.cpp b/src/aliceVision/multiview/triangulation/triangulationDLT_test.cpp index 59f1bd8d85..a2e911fc62 100644 --- a/src/aliceVision/multiview/triangulation/triangulationDLT_test.cpp +++ b/src/aliceVision/multiview/triangulation/triangulationDLT_test.cpp @@ -6,7 +6,7 @@ // v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. -#include +#include #include #include diff --git a/src/aliceVision/mvsUtils/MultiViewParams.cpp b/src/aliceVision/mvsUtils/MultiViewParams.cpp index 4d73179c1f..f0b96eb9d5 100644 --- a/src/aliceVision/mvsUtils/MultiViewParams.cpp +++ b/src/aliceVision/mvsUtils/MultiViewParams.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/aliceVision/numeric/CMakeLists.txt b/src/aliceVision/numeric/CMakeLists.txt index 2b83c4f93e..66289bab2c 100644 --- a/src/aliceVision/numeric/CMakeLists.txt +++ b/src/aliceVision/numeric/CMakeLists.txt @@ -1,11 +1,13 @@ # Headers set(numeric_files_headers numeric.hpp + projection.hpp ) # Sources set(numeric_files_sources numeric.cpp + projection.cpp ) alicevision_add_library(aliceVision_numeric diff --git a/src/aliceVision/multiview/projection.cpp b/src/aliceVision/numeric/projection.cpp similarity index 99% rename from src/aliceVision/multiview/projection.cpp rename to src/aliceVision/numeric/projection.cpp index 029aa6cf47..30fd2bc4c7 100644 --- a/src/aliceVision/multiview/projection.cpp +++ b/src/aliceVision/numeric/projection.cpp @@ -6,7 +6,7 @@ // v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. -#include +#include "projection.hpp" #include diff --git a/src/aliceVision/multiview/projection.hpp b/src/aliceVision/numeric/projection.hpp similarity index 100% rename from src/aliceVision/multiview/projection.hpp rename to src/aliceVision/numeric/projection.hpp diff --git a/src/aliceVision/robustEstimation/CMakeLists.txt b/src/aliceVision/robustEstimation/CMakeLists.txt index 87cc243d7f..8c2386a9f9 100644 --- a/src/aliceVision/robustEstimation/CMakeLists.txt +++ b/src/aliceVision/robustEstimation/CMakeLists.txt @@ -1,25 +1,33 @@ # Headers set(robustEstimation_files_headers + conditioning.hpp + estimators.hpp + LineKernel.hpp + lineTestGenerator.hpp + FittingKernel.hpp + ISolver.hpp IRansacKernel.hpp - RansacKernel.hpp Ransac.hpp + RansacKernel.hpp ACRansac.hpp LORansac.hpp ransacTools.hpp randSampling.hpp - LineKernel.hpp - lineTestGenerator.hpp leastMedianOfSquares.hpp guidedMatching.hpp ScoreEvaluator.hpp supportEstimation.hpp maxConsensus.hpp - estimators.hpp ) -alicevision_add_interface(aliceVision_robustEstimation - SOURCES ${robustEstimation_files_headers} - LINKS +# Sources +set(robustEstimation_files_sources + conditioning.cpp +) + +alicevision_add_library(aliceVision_robustEstimation + SOURCES ${robustEstimation_files_headers} ${robustEstimation_files_sources} + PUBLIC_LINKS aliceVision_camera aliceVision_feature aliceVision_matching diff --git a/src/aliceVision/multiview/TwoViewKernel.hpp b/src/aliceVision/robustEstimation/FittingKernel.hpp similarity index 91% rename from src/aliceVision/multiview/TwoViewKernel.hpp rename to src/aliceVision/robustEstimation/FittingKernel.hpp index 1974c73f4e..0edc5092bc 100644 --- a/src/aliceVision/multiview/TwoViewKernel.hpp +++ b/src/aliceVision/robustEstimation/FittingKernel.hpp @@ -9,14 +9,14 @@ #pragma once #include -#include -#include +#include +#include #include #include namespace aliceVision { -namespace multiview { +namespace robustEstimation { /** * @brief This is one example (targeted at solvers that operate on correspondences @@ -45,7 +45,7 @@ namespace multiview { * should append new solutions to the end. */ template -class TwoViewKernel +class FittingKernel { public: @@ -53,7 +53,7 @@ class TwoViewKernel using ErrorT = ErrorT_; using ModelT = ModelT_; - TwoViewKernel(const Mat& x1, const Mat& x2) + FittingKernel(const Mat& x1, const Mat& x2) : _x1(x1) , _x2(x2) {} @@ -122,9 +122,9 @@ class TwoViewKernel protected: - /// left corresponding point + /// left corresponding data const Mat& _x1; - /// right corresponding point + /// right corresponding data const Mat& _x2; /// two view solver const SolverT _kernelSolver = SolverT(); @@ -133,13 +133,13 @@ class TwoViewKernel }; template -class NormalizedTwoViewKernel : public TwoViewKernel +class NormalizedFittingKernel : public FittingKernel { public: - using KernelBase = TwoViewKernel; + using KernelBase = FittingKernel; - NormalizedTwoViewKernel(const Mat& x1, const Mat& x2) + NormalizedFittingKernel(const Mat& x1, const Mat& x2) : KernelBase(x1, x2) {} @@ -175,5 +175,5 @@ class NormalizedTwoViewKernel : public TwoViewKernel } }; -} // namespace multiview +} // namespace robustEstimation } // namespace aliceVision diff --git a/src/aliceVision/multiview/ISolver.hpp b/src/aliceVision/robustEstimation/ISolver.hpp similarity index 62% rename from src/aliceVision/multiview/ISolver.hpp rename to src/aliceVision/robustEstimation/ISolver.hpp index b942445d9b..c6bee9bc60 100644 --- a/src/aliceVision/multiview/ISolver.hpp +++ b/src/aliceVision/robustEstimation/ISolver.hpp @@ -8,8 +8,10 @@ #include +#include + namespace aliceVision { -namespace multiview { +namespace robustEstimation { /** * @brief Generic solver interface. @@ -49,7 +51,6 @@ class ISolver virtual void solve(const Mat& x1, const Mat& x2, std::vector& models, const std::vector& weights) const = 0; }; - /** * @brief An Undefined Solver */ @@ -81,7 +82,6 @@ class UndefinedSolver : public ISolver } }; - /** * @brief Generic matrix solver model. */ @@ -124,71 +124,6 @@ typedef MatrixModel Mat3Model; */ typedef MatrixModel Mat34Model; -/** - * @brief Relative pose solver error interface. - */ -template -struct ISolverErrorRelativePose -{ - virtual double error(const ModelT& model, const Vec2& x1, const Vec2& x2) const = 0; -}; - -/** - * @brief Resection solver error interface. - */ -template -struct ISolverErrorResection -{ - virtual double error(const ModelT& model, const Vec2& x2d, const Vec3& x3d) const = 0; -}; - -/** - * @brief Build a 9 x n matrix from point matches, where each row is equivalent to the - * equation x'T*F*x = 0 for a single correspondence pair (x', x). The domain of - * the matrix is a 9 element vector corresponding to F. In other words, set up - * the linear system - * - * Af = 0, - * - * where f is the F matrix as a 9-vector rather than a 3x3 matrix (row - * major). If the points are well conditioned and there are 8 or more, then - * the nullspace should be rank one. If the nullspace is two dimensional, - * then the rank 2 constraint must be enforced to identify the appropriate F - * matrix. - * - * @note that this does not resize the matrix A; it is expected to have the - * appropriate size already. - */ -template -inline void encodeEpipolarEquation(const TMatX& x1, const TMatX& x2, TMatA* A, const std::vector *weights = nullptr) -{ - assert(x1.cols()==x2.cols()); - - if(weights != nullptr) - { - assert(x1.cols()==weights->size()); - } - - for(typename TMatX::Index i = 0; i < x1.cols(); ++i) - { - const Vec2 xx1 = x1.col(i); - const Vec2 xx2 = x2.col(i); - - A->row(i) << - xx2(0) * xx1(0), // 0 represents x coords, - xx2(0) * xx1(1), // 1 represents y coords. - xx2(0), - xx2(1) * xx1(0), - xx2(1) * xx1(1), - xx2(1), - xx1(0), - xx1(1), - 1.0; - - if(weights != nullptr) - A->row(i) *= (*weights)[i]; - } -} -} // namespace multiview +} // namespace robustEstimation } // namespace aliceVision diff --git a/src/aliceVision/robustEstimation/LineKernel.hpp b/src/aliceVision/robustEstimation/LineKernel.hpp index f07e3acb21..768716afdf 100644 --- a/src/aliceVision/robustEstimation/LineKernel.hpp +++ b/src/aliceVision/robustEstimation/LineKernel.hpp @@ -9,7 +9,7 @@ #pragma once #include -#include +#include #include namespace aliceVision { @@ -28,11 +28,11 @@ inline double pointToLineError(const Vec2& lineEq, const Vec2& xs) /** * @brief Embed the basic solver to fit from sampled point set */ -class LineKernel : public IRansacKernel> +class LineKernel : public IRansacKernel> { public: - using ModelT = multiview::MatrixModel; + using ModelT = robustEstimation::MatrixModel; LineKernel(const Mat2X& xs) : _xs(xs) diff --git a/src/aliceVision/robustEstimation/RansacKernel.hpp b/src/aliceVision/robustEstimation/RansacKernel.hpp index 38f331ccf0..55b9f6d7d6 100644 --- a/src/aliceVision/robustEstimation/RansacKernel.hpp +++ b/src/aliceVision/robustEstimation/RansacKernel.hpp @@ -8,27 +8,13 @@ #include #include -#include -#include -#include +#include +#include #include - -/** - * @brief Collection of kernel. - * @ref [1] "Robust and accurate calibration of camera networks". PhD. Pierre MOULON - * - * - RelativePoseKernel: relative pose two view estimation (affine, homography, fundamental) with unkwon intrinsic - * - RelativePoseKernel_K: relative pose two view estimation for essential matrix with known intrinsics - * - ResectionKernel: pose / resection estimation with unknown intrinsic - * - ResectionKernel_K: pose / resection estimation with known intrinsic - * - AngularRadianErrorKernel: essential matrix estimation between spherical camera - * - * Mainly it add correct data normalization and define the function required - * by the generic ACRANSAC / LORANSAC routine. - */ +#include namespace aliceVision { -namespace robustEstimation{ +namespace robustEstimation { /** * @brief A virtual kernel used for the ACRANSAC / LORANSAC framework. @@ -42,14 +28,14 @@ namespace robustEstimation{ * @note Handle data normalization and compute the corresponding logalpha 0 * that depends of the error model (point to line, or point to point) */ -template > +template > class RansacKernel - : public IRansacKernel - , public multiview::TwoViewKernel + : public robustEstimation::IRansacKernel + , public robustEstimation::FittingKernel { public: - using KernelBase = multiview::TwoViewKernel; + using KernelBase = robustEstimation::FittingKernel; RansacKernel(const Mat& x1, const Mat& x2) : KernelBase(x1, x2) @@ -166,323 +152,5 @@ class RansacKernel const SolverLsT_ _solverLs = SolverLsT_(); }; - -/** - * @brief Two view Kernel adapter for the A contrario (AC) model estimator. - * With unknown intrinsic. - * - * @note Handle data normalization and compute the corresponding logalpha 0 - * that depends of the error model (point to line, or point to point) - * - * @note This kernel adapter is working for affine, homography, fundamental matrix - * estimation. - */ -template> -class RelativePoseKernel - : public RansacKernel -{ -public: - - using KernelBase = RansacKernel; - - RelativePoseKernel(const Mat& x1, int w1, int h1, - const Mat& x2, int w2, int h2, - bool pointToLine = true) - : _x1(x1.rows(), x1.cols()) - , _x2(x2.rows(), x2.cols()) - , KernelBase(_x1, _x2) - , _logalpha0(0.0) - , _N1(3, 3) - , _N2(3, 3) - , _pointToLine(pointToLine) - { - assert(2 == x1.rows()); - assert(x1.rows() == x2.rows()); - assert(x1.cols() == x2.cols()); - - multiview::normalizePointsFromImageSize(x1, &_x1, &_N1, w1, h1); - multiview::normalizePointsFromImageSize(x2, &_x2, &_N2, w2, h2); - - // logAlpha0 is used to make error data scale invariant - if(pointToLine) - { - // Ratio of containing diagonal image rectangle over image area - const double D = sqrt(w2 * (double) w2 + h2 * (double) h2); // diameter - const double A = w2 * (double) h2; // area - _logalpha0 = log10(2.0 * D / A / _N2(0, 0)); - } - else - { - // ratio of area : unit circle over image area - _logalpha0 = log10(M_PI / (w2 * (double) h2) / (_N2(0, 0) * _N2(0, 0))); - } - } - - void unnormalize(ModelT_& model) const override - { - // Unnormalize model from the computed conditioning. - Mat3 H = model.getMatrix(); - UnnormalizerT_::unnormalize(_N1, _N2, &H); - model.setMatrix(H); - } - - double logalpha0() const override {return _logalpha0; } - double multError() const override {return (_pointToLine)? 0.5 : 1.0;} - Mat3 normalizer1() const override {return _N1;} - Mat3 normalizer2() const override {return _N2;} - double unormalizeError(double val) const override {return sqrt(val) / _N2(0,0);} - -protected: - /// Normalized input data - Mat _x1, _x2; - /// Matrix used to normalize data - Mat3 _N1, _N2; - /// Alpha0 is used to make the error adaptive to the image size - double _logalpha0; - /// Store if error model is pointToLine or point to point - bool _pointToLine; -}; - -/** - * @brief Two view Kernel adapter for the A contrario (AC) model estimator. - * With known intrinsic. - * - * @note Handle data normalization and compute the corresponding logalpha 0 - * that depends of the error model (point to line, or point to point) - * - * @note This kernel adapter is working only for essential matrix - * estimation. - */ -template> -class RelativePoseKernel_K - : public RansacKernel -{ -public: - - using KernelBase = RansacKernel; - - RelativePoseKernel_K(const Mat& x1, int w1, int h1, - const Mat& x2, int w2, int h2, - const Mat3& K1, const Mat3& K2) - : KernelBase(x1, x2) - , _N1(Mat3::Identity()) - , _N2(Mat3::Identity()) - , _logalpha0(0.0) - , _K1(K1) - , _K2(K2) - { - assert(2 == x1.rows()); - assert(x1.rows() == x2.rows()); - assert(x1.cols() == x2.cols()); - - multiview::applyTransformationToPoints(x1, _K1.inverse(), &_x1k); - multiview::applyTransformationToPoints(x2, _K2.inverse(), &_x2k); - - // point to line probability (line is the epipolar line) - const double D = sqrt(w2 * static_cast(w2) + h2 * static_cast(h2)); // diameter - const double A = w2 * static_cast(h2); // area - _logalpha0 = log10(2.0 * D / A * .5); - } - - void fit(const std::vector& samples, std::vector& models) const override - { - const Mat x1 = ExtractColumns(_x1k, samples); - const Mat x2 = ExtractColumns(_x2k, samples); - - KernelBase::KernelBase::_kernelSolver.solve(x1, x2, models); - } - - double error(std::size_t sample, const ModelT_& model) const override - { - Mat3 F; - fundamentalFromEssential(model.getMatrix(), _K1, _K2, &F); - const ModelT_ modelF(F); - return _errorEstimator.error(modelF, KernelBase::_x1.col(sample), KernelBase::_x2.col(sample)); - } - - void unnormalize(ModelT_& model) const override - { - // do nothing, no normalization in this case - } - - double logalpha0() const override {return _logalpha0; } - double multError() const override {return 0.5;} // point to line error - Mat3 normalizer1() const override {return _N1;} - Mat3 normalizer2() const override {return _N2;} - double unormalizeError(double val) const override { return val; } - -private: - - Mat _x1k, _x2k; - /// Matrix used to normalize data - Mat3 _N1, _N2; - /// Alpha0 is used to make the error adaptive to the image size - double _logalpha0; - /// Intrinsics camera parameter - Mat3 _K1, _K2; - /// solver error estimation - const ErrorT_ _errorEstimator; -}; - -/** - * @brief Pose/Resection Kernel with unknown intrinsic for the A contrario (AC) model estimator. - */ -template> -class ResectionKernel - : public RansacKernel -{ -public: - - using KernelBase = RansacKernel; - - /** - * @brief ResectionKernel constructor with unknown intrinsic - * @param[in] x2d 2d points in the first image. One per column. - * @param[in] x3d 3d points in the second image. One per column. - * @param[in] K intrinsic camera parameter - */ - ResectionKernel(const Mat& x2d, const Mat& x3d, int w, int h) - : _x2d(x2d.rows(), x2d.cols()) - , KernelBase(_x2d, x3d) - , _logalpha0(log10(M_PI)) - , _N1(3, 3) - { - assert(2 == x2d.rows()); - assert(3 == x3d.rows()); - assert(x2d.cols() == x3d.cols()); - - multiview::normalizePointsFromImageSize(x2d, &_x2d, &_N1, w, h); - } - - void unnormalize(ModelT_& model) const override - { - // unnormalize model from the computed conditioning. - Mat34 P = model.getMatrix(); - UnnormalizerT_::unnormalize(_N1, Mat3::Identity(), &P); - model.setMatrix(P); - } - - double logalpha0() const override {return _logalpha0; } - double multError() const override {return 1.0;} // point to point error - Mat3 normalizer1() const override {return Mat3::Identity();} - Mat3 normalizer2() const override {return _N1;} - double unormalizeError(double val) const override {return sqrt(val) / _N1(0,0);} - -protected: - /// Normalized input data - Mat _x2d; - /// Matrix used to normalize data - Mat3 _N1; - /// Alpha0 is used to make the error adaptive to the image size - double _logalpha0; -}; - - -/** - * @brief The kernel for the resection with known intrinsics (PnP) to be used with - * the ACRANSAC / LORANSAC framework. - * - * @tparam SolverT The minimal solver able to find a solution from a minimum set of points, usually any PnP solver. - * @tparam ErrorT The functor computing the error for each data sample with respect to the estimated model, usually a reprojection error functor. - * @tparam UnnormalizerT The functor used to normalize the data before the estimation of the model, usually a functor that normalize the point in camera - * coordinates (ie multiply by the inverse of the calibration matrix). - * @tparam SolverLsT = SolverT The least square solver that is used to find a solution from any set of data larger than the minimum required, - * usually the 6 point algorithm which solves the resection problem by means of LS. - * @tparam ModelT = Mat34Model The type of the model to estimate, the projection matrix. - */ -template> -class ResectionKernel_K - : public RansacKernel -{ -public: - - using KernelBase = RansacKernel; - - /** - * @brief ResectionKernel constructor with known intrinsic - * @param[in] x2d 2d points in the first image. One per column. - * @param[in] x3d 3d points in the second image. One per column. - * @param[in] K intrinsic camera parameter - */ - ResectionKernel_K(const Mat& x2d, const Mat& x3d, const Mat3& K) - : _x2d(x2d.rows(), x2d.cols()) - , KernelBase(_x2d, x3d) - , _logalpha0(log10(M_PI)) - , _N1(K.inverse()) - , _K(K) - { - assert(2 == x2d.rows()); - assert(3 == x3d.rows()); - assert(x2d.cols() == x3d.cols()); - - // normalize points by inverse K - multiview::applyTransformationToPoints(x2d, _N1, &_x2d); - } - - void unnormalize(ModelT_& model) const override - { - // unnormalize model from the computed conditioning. - model.setMatrix(_K * model.getMatrix()); - } - - double logalpha0() const override {return _logalpha0; } - double multError() const override {return 1.0;} // point to point error - Mat3 normalizer1() const override {return Mat3::Identity();} - Mat3 normalizer2() const override {return _N1;} - double unormalizeError(double val) const override {return sqrt(val) / _N1(0,0);} - -protected: - /// Normalized input data - Mat _x2d; - /// Matrix used to normalize data - Mat3 _N1; - /// Alpha0 is used to make the error adaptive to the image size - double _logalpha0; - /// intrinsic camera parameter - Mat3 _K; -}; - -/** - * @brief Two view Kernel adapter for the A contrario (AC) model estimator. - * Specialization to handle radian angular residual error. - */ -template -class AngularRadianErrorKernel - : public RansacKernel> -{ -public: - - using KernelBase = RansacKernel>; - - AngularRadianErrorKernel(const Mat& x1, const Mat& x2) - : KernelBase(x1, x2) - , _logalpha0(log10(1.0 / 2.0)) - { - assert(3 == x1.rows()); - assert(x1.rows() == x2.rows()); - assert(x1.cols() == x2.cols()); - } - - inline double error(std::size_t sample, const ModelT_& model) const override - { - return Square(KernelBase::error(sample, model)); - } - - void unnormalize(ModelT_& model) const override - { - // do nothing, no normalization in the angular case - } - - double logalpha0() const override {return _logalpha0; } - double multError() const override {return 1./4.;} - Mat3 normalizer1() const override {return Mat3::Identity();} - Mat3 normalizer2() const override {return Mat3::Identity();} - double unormalizeError(double val) const override {return sqrt(val);} - -protected: - /// Alpha0 is used to make the error adaptive to the image size - double _logalpha0; -}; - } // namespace robustEstimation } // namespace aliceVision diff --git a/src/aliceVision/robustEstimation/acRansac_test.cpp b/src/aliceVision/robustEstimation/acRansac_test.cpp index 8f081e3294..c1f8f66b74 100644 --- a/src/aliceVision/robustEstimation/acRansac_test.cpp +++ b/src/aliceVision/robustEstimation/acRansac_test.cpp @@ -40,7 +40,7 @@ BOOST_AUTO_TEST_CASE(RansacLineFitter_OutlierFree) // check the best model that fit the most of the data in a robust framework (ACRANSAC). std::vector inliers; - multiview::MatrixModel model; + robustEstimation::MatrixModel model; ACRANSAC(lineKernel, inliers, 300, &model); BOOST_CHECK_SMALL(2.0 - model.getMatrix()[1], 1e-9); @@ -79,7 +79,7 @@ BOOST_AUTO_TEST_CASE(RansacLineFitter_OneOutlier) // Check the best model that fit the most of the data // in a robust framework (ACRANSAC). std::vector inliers; - multiview::MatrixModel model; + robustEstimation::MatrixModel model; ACRANSAC(lineKernel, inliers, 300, &model); @@ -147,7 +147,7 @@ BOOST_AUTO_TEST_CASE(RansacLineFitter_RealisticCase) // Check the best model that fit the most of the data // in a robust framework (ACRANSAC). std::vector inliers; - multiview::MatrixModel model; + robustEstimation::MatrixModel model; ACRANSAC(lineKernel, inliers, 300, &model); @@ -247,7 +247,7 @@ BOOST_AUTO_TEST_CASE(RansacLineFitter_ACRANSACSimu) std::vector vec_inliersGT; generateLine(numPoints, outlierRatio, gaussianNoiseLevel, GTModel, gen, points, vec_inliersGT); // robust line estimation - multiview::MatrixModel model; + robustEstimation::MatrixModel model; // The base estimator LineKernel lineKernel(points, W, H); diff --git a/src/aliceVision/multiview/conditioning.cpp b/src/aliceVision/robustEstimation/conditioning.cpp similarity index 85% rename from src/aliceVision/multiview/conditioning.cpp rename to src/aliceVision/robustEstimation/conditioning.cpp index 0d4431c2fe..e15981ca56 100644 --- a/src/aliceVision/multiview/conditioning.cpp +++ b/src/aliceVision/robustEstimation/conditioning.cpp @@ -9,7 +9,7 @@ #include "conditioning.hpp" namespace aliceVision { -namespace multiview { +namespace robustEstimation { // HZ 4.4.4 pag.109 void preconditionerFromPoints(const Mat &points, Mat3 *T) { @@ -73,15 +73,5 @@ void normalizePoints(const Mat &points, applyTransformationToPoints(points, *T, normalized_points); } -// Denormalize the results. See HZ page 109. -void UnnormalizerT::unnormalize(const Mat3 &T1, const Mat3 &T2, Mat3 *H) { - *H = T2.transpose() * (*H) * T1; -} - -// Denormalize the results. See HZ page 109. -void UnnormalizerI::unnormalize(const Mat3 &T1, const Mat3 &T2, Mat3 *H) { - *H = T2.inverse() * (*H) * T1; -} - -} // namespace multiview -} //namespace aliceVision +} // namespace robustEstimation +} // namespace aliceVision diff --git a/src/aliceVision/multiview/conditioning.hpp b/src/aliceVision/robustEstimation/conditioning.hpp similarity index 69% rename from src/aliceVision/multiview/conditioning.hpp rename to src/aliceVision/robustEstimation/conditioning.hpp index 50c0a6fe68..053da3ccd8 100644 --- a/src/aliceVision/multiview/conditioning.hpp +++ b/src/aliceVision/robustEstimation/conditioning.hpp @@ -10,9 +10,6 @@ #include -namespace aliceVision { -namespace multiview { - /** * @brief Implementation of normalized coordinates. * Normalization improve accuracy of results and provide benefits @@ -20,6 +17,9 @@ namespace multiview { * The implementation follows @see Algorithm 4.2 from HZ page 109. */ +namespace aliceVision { +namespace robustEstimation { + /** * @brief Point conditioning */ @@ -45,41 +45,5 @@ void preconditionerFromImageSize(int width, int height, Mat3 *T); */ void normalizePointsFromImageSize(const Mat& points, Mat* normalized_points, Mat3* T, int width, int height); -/** - * @brief Unnormalize using Inverse - */ -struct UnnormalizerI -{ - /** - * @brief Denormalize the results. - * @see HZ page 109. - */ - static void unnormalize(const Mat3 &T1, const Mat3 &T2, Mat3 *H); -}; - -/** - * @brief Unnormalize using Transpose - */ -struct UnnormalizerT -{ - /** - * @brief Denormalize the results. - * @see HZ page 109. - */ - static void unnormalize(const Mat3 &T1, const Mat3 &T2, Mat3 *H); -}; - -/** - * @brief Unnormalize for resection - */ -struct UnnormalizerResection -{ - - static void unnormalize(const Mat &T, const Mat &U, Mat34 *P) - { - *P = T.inverse() * (*P); - } -}; - -} //namespace multiview +} //namespace robustEstimation } //namespace aliceVision diff --git a/src/aliceVision/sfm/pipeline/RelativePoseInfo.cpp b/src/aliceVision/sfm/pipeline/RelativePoseInfo.cpp index a50ff55884..02ca8a8721 100644 --- a/src/aliceVision/sfm/pipeline/RelativePoseInfo.cpp +++ b/src/aliceVision/sfm/pipeline/RelativePoseInfo.cpp @@ -6,14 +6,14 @@ // You can obtain one at https://mozilla.org/MPL/2.0/. #include "RelativePoseInfo.hpp" -#include -#include -#include -#include -#include +#include #include -#include #include +#include +#include +#include +#include +#include namespace aliceVision { namespace sfm { @@ -86,13 +86,13 @@ bool robustRelativePose(const Mat3& K1, const Mat3& K2, using SolverT = multiview::relativePose::Essential5PSolver; // define the kernel - using KernelT = robustEstimation::RelativePoseKernel_K; + using KernelT = multiview::RelativePoseKernel_K; KernelT kernel(x1, size_ima1.first, size_ima1.second, x2, size_ima2.first, size_ima2.second, K1, K2); - multiview::Mat3Model model; + robustEstimation::Mat3Model model; // robustly estimation of the Essential matrix and its precision const std::pair acRansacOut = robustEstimation::ACRANSAC(kernel, diff --git a/src/aliceVision/sfm/pipeline/global/GlobalSfMTranslationAveragingSolver.cpp b/src/aliceVision/sfm/pipeline/global/GlobalSfMTranslationAveragingSolver.cpp index 6e71a0698e..94e4db97ad 100644 --- a/src/aliceVision/sfm/pipeline/global/GlobalSfMTranslationAveragingSolver.cpp +++ b/src/aliceVision/sfm/pipeline/global/GlobalSfMTranslationAveragingSolver.cpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/aliceVision/sfm/pipeline/global/TranslationTripletKernelACRansac.hpp b/src/aliceVision/sfm/pipeline/global/TranslationTripletKernelACRansac.hpp index aa99253042..a70ecb3edb 100644 --- a/src/aliceVision/sfm/pipeline/global/TranslationTripletKernelACRansac.hpp +++ b/src/aliceVision/sfm/pipeline/global/TranslationTripletKernelACRansac.hpp @@ -8,7 +8,7 @@ #pragma once #include -#include +#include #include #include #include @@ -44,9 +44,9 @@ class TranslationTripletKernelACRansac , _Kinv(K.inverse()) { // Normalize points by inverse(K) - multiview::applyTransformationToPoints(_x1, _Kinv, &_x1n); - multiview::applyTransformationToPoints(_x2, _Kinv, &_x2n); - multiview::applyTransformationToPoints(_x3, _Kinv, &_x3n); + robustEstimation::applyTransformationToPoints(_x1, _Kinv, &_x1n); + robustEstimation::applyTransformationToPoints(_x2, _Kinv, &_x2n); + robustEstimation::applyTransformationToPoints(_x3, _Kinv, &_x3n); _vecKR[0] = _Kinv * _vecKR[0]; _vecKR[1] = _Kinv * _vecKR[1]; diff --git a/src/aliceVision/sfm/pipeline/localization/SfMLocalizer.cpp b/src/aliceVision/sfm/pipeline/localization/SfMLocalizer.cpp index c0a1eb4aa1..ecbc34055a 100644 --- a/src/aliceVision/sfm/pipeline/localization/SfMLocalizer.cpp +++ b/src/aliceVision/sfm/pipeline/localization/SfMLocalizer.cpp @@ -8,15 +8,16 @@ #include "SfMLocalizer.hpp" #include #include -#include -#include -#include -#include #include #include -#include #include #include +#include +#include +#include +#include +#include +#include namespace aliceVision { namespace sfm { @@ -45,14 +46,14 @@ bool SfMLocalizer::Localize(const Pair& imageSize, { // classic resection (try to compute the entire P matrix) using SolverT = multiview::resection::Resection6PSolver; - using KernelT = robustEstimation::ResectionKernel; + using KernelT = multiview::ResectionKernel; const KernelT kernel(resectionData.pt2D, resectionData.pt3D, imageSize.first, imageSize.second); minimumSamples = kernel.getMinimumNbRequiredSamples(); // robust estimation of the Projection matrix and its precision - multiview::Mat34Model model; + robustEstimation::Mat34Model model; const std::pair ACRansacOut = robustEstimation::ACRANSAC(kernel, resectionData.vec_inliers, resectionData.max_iteration, &model, precision); P = model.getMatrix(); // update the upper bound precision of the model found by AC-RANSAC @@ -79,7 +80,7 @@ bool SfMLocalizer::Localize(const Pair& imageSize, { // since K calibration matrix is known, compute only [R|t] using SolverT = multiview::resection::P3PSolver; - using KernelT = robustEstimation::ResectionKernel_K; + using KernelT = multiview::ResectionKernel_K; // otherwise we just pass the input points const KernelT kernel = KernelT(hasDistortion ? pt2Dundistorted : resectionData.pt2D, resectionData.pt3D, pinholeCam->K()); @@ -87,7 +88,7 @@ bool SfMLocalizer::Localize(const Pair& imageSize, minimumSamples = kernel.getMinimumNbRequiredSamples(); // robust estimation of the Projection matrix and its precision - multiview::Mat34Model model; + robustEstimation::Mat34Model model; const std::pair ACRansacOut = robustEstimation::ACRANSAC(kernel, resectionData.vec_inliers, resectionData.max_iteration, &model, precision); P = model.getMatrix(); @@ -114,7 +115,7 @@ bool SfMLocalizer::Localize(const Pair& imageSize, using SolverLsT = multiview::resection::Resection6PSolver; // use the six point algorithm as Least square solution to refine the model - using KernelT = robustEstimation::ResectionKernel_K; + using KernelT = multiview::ResectionKernel_K; // otherwise we just pass the input points const KernelT kernel = KernelT(hasDistortion ? pt2Dundistorted : resectionData.pt2D, resectionData.pt3D, pinholeCam->K()); @@ -128,7 +129,7 @@ bool SfMLocalizer::Localize(const Pair& imageSize, const double threshold = resectionData.error_max * resectionData.error_max * (kernel.normalizer2()(0, 0) * kernel.normalizer2()(0, 0)); robustEstimation::ScoreEvaluator scorer(threshold); - const multiview::Mat34Model model = robustEstimation::LO_RANSAC(kernel, scorer, &resectionData.vec_inliers); + const robustEstimation::Mat34Model model = robustEstimation::LO_RANSAC(kernel, scorer, &resectionData.vec_inliers); P = model.getMatrix(); break; diff --git a/src/aliceVision/sfmDataIO/sfmDataIO_test.cpp b/src/aliceVision/sfmDataIO/sfmDataIO_test.cpp index 48e5503182..39832d0e7b 100644 --- a/src/aliceVision/sfmDataIO/sfmDataIO_test.cpp +++ b/src/aliceVision/sfmDataIO/sfmDataIO_test.cpp @@ -6,7 +6,8 @@ // You can obtain one at https://mozilla.org/MPL/2.0/. #include -#include +#include +#include #include diff --git a/src/samples/accv12Demo/main_openCVFitting.cpp b/src/samples/accv12Demo/main_openCVFitting.cpp index 550a7b8849..93ae73e5ab 100644 --- a/src/samples/accv12Demo/main_openCVFitting.cpp +++ b/src/samples/accv12Demo/main_openCVFitting.cpp @@ -7,7 +7,7 @@ #include "aliceVision/numeric/numeric.hpp" #include "aliceVision/multiview/homographyKernelSolver.hpp" -#include "aliceVision/multiview/conditioning.hpp" +#include "aliceVision/robustEstimation/conditioning.hpp" #include "aliceVision/robustEstimation/maxConsensus.hpp" #include "aliceVision/robustEstimation/ScoreEvaluator.hpp" #include "aliceVision/robustEstimation/ACRansac.hpp" diff --git a/src/samples/featuresRepeatability/main_repeatabilityDataset.cpp b/src/samples/featuresRepeatability/main_repeatabilityDataset.cpp index cf9aa61be7..64782da766 100644 --- a/src/samples/featuresRepeatability/main_repeatabilityDataset.cpp +++ b/src/samples/featuresRepeatability/main_repeatabilityDataset.cpp @@ -366,8 +366,8 @@ int main(int argc, char **argv) PointsToMat(pointsFeaturesI, xI); IndMatches matches_0I; - robustEstimation::guidedMatching( - multiview::Mat3Model(dataset.H(i).transpose()), x0, xI, Square(m_dPrecision_robust), matches_0I); + robustEstimation::guidedMatching( + robustEstimation::Mat3Model(dataset.H(i).transpose()), x0, xI, Square(m_dPrecision_robust), matches_0I); std::cout << "Feature repeatablity Results" << "\n" << "*******************************" << "\n" @@ -403,8 +403,8 @@ int main(int argc, char **argv) PointsToMat(putativesMatches, pointsFeatures0, pointsFeaturesI, x0, xI); IndMatches matches_0I; - robustEstimation::guidedMatching( - multiview::Mat3Model(dataset.H(i).transpose()), x0, xI, Square(m_dPrecision_robust), matches_0I); + robustEstimation::guidedMatching( + robustEstimation::Mat3Model(dataset.H(i).transpose()), x0, xI, Square(m_dPrecision_robust), matches_0I); std::cout << "Feature matching repeatability Results" << "\n" << "*******************************" << "\n" diff --git a/src/samples/kvldFilter/main_kvldFilter.cpp b/src/samples/kvldFilter/main_kvldFilter.cpp index be477874e8..05800a4497 100644 --- a/src/samples/kvldFilter/main_kvldFilter.cpp +++ b/src/samples/kvldFilter/main_kvldFilter.cpp @@ -10,11 +10,10 @@ #include #include #include -#include +#include #include #include #include -#include #include diff --git a/src/samples/robustEssentialSpherical/main_robustEssentialSpherical.cpp b/src/samples/robustEssentialSpherical/main_robustEssentialSpherical.cpp index 217fe7a5b8..c272bbb3a4 100644 --- a/src/samples/robustEssentialSpherical/main_robustEssentialSpherical.cpp +++ b/src/samples/robustEssentialSpherical/main_robustEssentialSpherical.cpp @@ -11,8 +11,8 @@ #include "aliceVision/matching/RegionsMatcher.hpp" #include "aliceVision/multiview/essential.hpp" #include "aliceVision/robustEstimation/ACRansac.hpp" -#include "aliceVision/multiview/conditioning.hpp" -#include "aliceVision/robustEstimation/RansacKernel.hpp" +#include "aliceVision/robustEstimation/conditioning.hpp" +#include "aliceVision/multiview/AngularRadianErrorKernel.hpp" #include "sphericalCam.hpp" @@ -153,16 +153,16 @@ int main() { typedef aliceVision::spherical_cam::EssentialKernel_spherical Kernel; // Define the AContrario angular error adaptor - typedef aliceVision::robustEstimation::AngularRadianErrorKernel< + typedef aliceVision::multiview::AngularRadianErrorKernel< aliceVision::spherical_cam::EightPointRelativePoseSolver, aliceVision::spherical_cam::AngularError, - multiview::Mat3Model> + robustEstimation::Mat3Model> KernelType; KernelType kernel(xL_spherical, xR_spherical); // Robust estimation of the Essential matrix and it's precision - multiview::Mat3Model E; + robustEstimation::Mat3Model E; const double precision = std::numeric_limits::infinity(); const std::pair ACRansacOut = ACRANSAC(kernel, vec_inliers, 1024, &E, precision); const double & threshold = ACRansacOut.first; @@ -181,7 +181,7 @@ int main() { // Accumulator to find the best solution std::vector f(4, 0); - std::vector Es; // Essential, + std::vector Es; // Essential, std::vector Rs; // Rotation matrix. std::vector ts; // Translation matrix. diff --git a/src/samples/robustEssentialSpherical/sphericalCam.hpp b/src/samples/robustEssentialSpherical/sphericalCam.hpp index 8d4543d721..8fbf2427ae 100644 --- a/src/samples/robustEssentialSpherical/sphericalCam.hpp +++ b/src/samples/robustEssentialSpherical/sphericalCam.hpp @@ -8,9 +8,9 @@ #pragma once #include -#include -#include -#include +#include +#include +#include // [1] "Robust and accurate calibration of camera networks". PhD. // Authors: Pierre MOULON @@ -51,11 +51,11 @@ using namespace std; * See page 294 in HZ Result 11.1. * */ -class EightPointRelativePoseSolver : public multiview::ISolver +class EightPointRelativePoseSolver : public robustEstimation::ISolver { public: - using ModelT = multiview::Mat3Model; + using ModelT = robustEstimation::Mat3Model; /** * @brief Return the minimum number of required samples @@ -127,7 +127,7 @@ class EightPointRelativePoseSolver : public multiview::ISolver + : public robustEstimation::FittingKernel { public: - using ModelT = multiview::Mat3Model; - using KernelBase = multiview::TwoViewKernel; + using ModelT = robustEstimation::Mat3Model; + using KernelBase = robustEstimation::FittingKernel; EssentialKernel_spherical(const Mat& x1, const Mat& x2) : KernelBase(x1, x2) diff --git a/src/samples/robustFundamental/main_robustFundamental.cpp b/src/samples/robustFundamental/main_robustFundamental.cpp index e0189fd7b0..f8dc77844d 100644 --- a/src/samples/robustFundamental/main_robustFundamental.cpp +++ b/src/samples/robustFundamental/main_robustFundamental.cpp @@ -10,9 +10,9 @@ #include "aliceVision/feature/sift/ImageDescriber_SIFT.hpp" #include "aliceVision/matching/RegionsMatcher.hpp" #include "aliceVision/multiview/relativePose/FundamentalKernel.hpp" -#include "aliceVision/multiview/conditioning.hpp" +#include "aliceVision/robustEstimation/conditioning.hpp" #include "aliceVision/robustEstimation/ACRansac.hpp" -#include "aliceVision/robustEstimation/RansacKernel.hpp" +#include "aliceVision/multiview/RelativePoseKernel.hpp" #include "dependencies/vectorGraphics/svgDrawer.hpp" @@ -172,11 +172,11 @@ int main(int argc, char **argv) //-- Fundamental robust estimation std::vector vec_inliers; - typedef RelativePoseKernel< + typedef multiview::RelativePoseKernel< multiview::relativePose::Fundamental7PSolver, multiview::relativePose::FundamentalSymmetricEpipolarDistanceError, multiview::UnnormalizerT, - multiview::Mat3Model> + robustEstimation::Mat3Model> KernelType; KernelType kernel( @@ -184,7 +184,7 @@ int main(int argc, char **argv) xR, imageR.Width(), imageR.Height(), true); // configure as point to line error model. - multiview::Mat3Model F; + robustEstimation::Mat3Model F; const std::pair ACRansacOut = ACRANSAC(kernel, vec_inliers, 1024, &F, Square(4.0)); // Upper bound of authorized threshold diff --git a/src/samples/robustFundamentalGuided/main_robustFundamentalGuided.cpp b/src/samples/robustFundamentalGuided/main_robustFundamentalGuided.cpp index f3dab779cb..3c16ce63d0 100644 --- a/src/samples/robustFundamentalGuided/main_robustFundamentalGuided.cpp +++ b/src/samples/robustFundamentalGuided/main_robustFundamentalGuided.cpp @@ -10,9 +10,9 @@ #include #include #include -#include +#include #include -#include +#include #include #include @@ -128,11 +128,11 @@ int main() { //-- Fundamental robust estimation std::vector vec_inliers; - typedef RelativePoseKernel< + typedef multiview::RelativePoseKernel< multiview::relativePose::Fundamental7PSolver, multiview::relativePose::FundamentalSymmetricEpipolarDistanceError, multiview::UnnormalizerT, - multiview::Mat3Model> + robustEstimation::Mat3Model> KernelType; KernelType kernel( @@ -140,7 +140,7 @@ int main() { xR, imageR.Width(), imageR.Height(), true); // configure as point to line error model. - multiview::Mat3Model F; + robustEstimation::Mat3Model F; const std::pair ACRansacOut = ACRANSAC(kernel, vec_inliers, 1024, &F, Square(4.0)); // Upper bound of authorized threshold const double & thresholdF = ACRansacOut.first; @@ -199,14 +199,14 @@ int main() { //a. by considering only the geometric error - robustEstimation::guidedMatching( + robustEstimation::guidedMatching( F, xL, xR, Square(thresholdF), vec_corresponding_indexes[0]); std::cout << "\nGuided Fundamental matching (geometric error) found " << vec_corresponding_indexes[0].size() << " correspondences." << std::endl; // b. by considering geometric error and descriptor distance ratio - robustEstimation::guidedMatching( + robustEstimation::guidedMatching( F, NULL, *regions_perImage.at(0), // Null since no Intrinsic is defined NULL, *regions_perImage.at(1), // Null since no Intrinsic is defined diff --git a/src/samples/robustHomography/main_robustHomography.cpp b/src/samples/robustHomography/main_robustHomography.cpp index f1135190ef..8d66948f8e 100644 --- a/src/samples/robustHomography/main_robustHomography.cpp +++ b/src/samples/robustHomography/main_robustHomography.cpp @@ -12,9 +12,10 @@ #include "aliceVision/matching/RegionsMatcher.hpp" #include "aliceVision/multiview/relativePose/Homography4PSolver.hpp" #include "aliceVision/multiview/relativePose/HomographyError.hpp" -#include "aliceVision/multiview/conditioning.hpp" +#include "aliceVision/multiview/Unnormalizer.hpp" +#include "aliceVision/robustEstimation/conditioning.hpp" #include "aliceVision/robustEstimation/ACRansac.hpp" -#include "aliceVision/robustEstimation/RansacKernel.hpp" +#include "aliceVision/multiview/RelativePoseKernel.hpp" #include "dependencies/vectorGraphics/svgDrawer.hpp" @@ -128,11 +129,11 @@ int main() { //-- Homography robust estimation std::vector vec_inliers; - typedef RelativePoseKernel< + typedef multiview::RelativePoseKernel< multiview::relativePose::Homography4PSolver, multiview::relativePose::HomographyAsymmetricError, multiview::UnnormalizerI, - multiview::Mat3Model> + robustEstimation::Mat3Model> KernelType; KernelType kernel( @@ -140,7 +141,7 @@ int main() { xR, imageR.Width(), imageR.Height(), false); // configure as point to point error model. - multiview::Mat3Model H; + robustEstimation::Mat3Model H; const std::pair ACRansacOut = ACRANSAC(kernel, vec_inliers, 1024, &H, std::numeric_limits::infinity()); const double & thresholdH = ACRansacOut.first; @@ -168,7 +169,7 @@ int main() { svgStream.drawCircle(L.x(), L.y(), LL.scale(), svgStyle().stroke("yellow", 2.0)); svgStream.drawCircle(R.x()+imageL.Width(), R.y(), RR.scale(),svgStyle().stroke("yellow", 2.0)); // residual computation - vec_residuals[i] = std::sqrt(KernelType::ErrorT( ).error(H, LL.coords().cast(), RR.coords().cast())); + vec_residuals[i] = std::sqrt(KernelType::ErrorT().error(H, LL.coords().cast(), RR.coords().cast())); } string out_filename = "04_ACRansacHomography.svg"; ofstream svgFile( out_filename.c_str() ); diff --git a/src/samples/robustHomographyGuided/main_robustHomographyGuided.cpp b/src/samples/robustHomographyGuided/main_robustHomographyGuided.cpp index 29176c5b37..037c7acb18 100644 --- a/src/samples/robustHomographyGuided/main_robustHomographyGuided.cpp +++ b/src/samples/robustHomographyGuided/main_robustHomographyGuided.cpp @@ -10,9 +10,9 @@ #include "aliceVision/feature/sift/ImageDescriber_SIFT.hpp" #include "aliceVision/matching/RegionsMatcher.hpp" #include "aliceVision/multiview/relativePose/HomographyKernel.hpp" -#include "aliceVision/multiview/conditioning.hpp" +#include "aliceVision/robustEstimation/conditioning.hpp" #include "aliceVision/robustEstimation/ACRansac.hpp" -#include "aliceVision/robustEstimation/RansacKernel.hpp" +#include "aliceVision/multiview/RelativePoseKernel.hpp" #include "aliceVision/robustEstimation/guidedMatching.hpp" #include "dependencies/vectorGraphics/svgDrawer.hpp" @@ -127,11 +127,11 @@ int main() { //-- Homography robust estimation std::vector vec_inliers; - typedef RelativePoseKernel< + typedef multiview::RelativePoseKernel< multiview::relativePose::Homography4PSolver, multiview::relativePose::HomographyAsymmetricError, multiview::UnnormalizerI, - multiview::Mat3Model> + robustEstimation::Mat3Model> KernelType; KernelType kernel( @@ -139,7 +139,7 @@ int main() { xR, imageR.Width(), imageR.Height(), false); // configure as point to point error model. - multiview::Mat3Model H; + robustEstimation::Mat3Model H; const std::pair ACRansacOut = ACRANSAC(kernel, vec_inliers, 1024, &H, std::numeric_limits::infinity()); const double & thresholdH = ACRansacOut.first; @@ -198,14 +198,14 @@ int main() { //a. by considering only the geometric error - robustEstimation::guidedMatching( + robustEstimation::guidedMatching( H, xL, xR, Square(thresholdH), vec_corresponding_indexes[0]); std::cout << "\nGuided homography matching (geometric error) found " << vec_corresponding_indexes[0].size() << " correspondences." << std::endl; // b. by considering geometric error and descriptor distance ratio - robustEstimation::guidedMatching( + robustEstimation::guidedMatching( H, NULL, *regions_perImage.at(0), // Null since no Intrinsic is defined NULL, *regions_perImage.at(1), // Null since no Intrinsic is defined diff --git a/src/software/utils/main_qualityEvaluation.cpp b/src/software/utils/main_qualityEvaluation.cpp index d23e224628..9af1d385b9 100644 --- a/src/software/utils/main_qualityEvaluation.cpp +++ b/src/software/utils/main_qualityEvaluation.cpp @@ -7,7 +7,6 @@ #include #include -#include #include #include #include