1 // This file is part of OpenMVG, an Open Multiple View Geometry C++ library. 2 3 // Copyright (c) 2012, 2013, 2015 Pierre MOULON. 4 5 // This Source Code Form is subject to the terms of the Mozilla Public 6 // License, v. 2.0. If a copy of the MPL was not distributed with this 7 // file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 9 #ifndef OPENMVG_MATCHING_IMAGE_COLLECTION_F_AC_ROBUST_HPP 10 #define OPENMVG_MATCHING_IMAGE_COLLECTION_F_AC_ROBUST_HPP 11 12 #include <limits> 13 #include <utility> 14 #include <vector> 15 16 #include "openMVG/matching/indMatch.hpp" 17 #include "openMVG/matching_image_collection/Geometric_Filter_utils.hpp" 18 #include "openMVG/multiview/essential.hpp" 19 #include "openMVG/multiview/solver_fundamental_kernel.hpp" 20 #include "openMVG/robust_estimation/guided_matching.hpp" 21 #include "openMVG/robust_estimation/robust_estimator_ACRansac.hpp" 22 #include "openMVG/robust_estimation/robust_estimator_ACRansacKernelAdaptator.hpp" 23 #include "openMVG/sfm/pipelines/sfm_regions_provider.hpp" 24 #include "openMVG/sfm/sfm_data.hpp" 25 26 namespace openMVG { namespace sfm { struct Regions_Provider; } 27 28 namespace matching_image_collection { 29 30 //-- A contrario fundamental matrix estimation template functor used for filter pair of putative correspondences 31 struct GeometricFilter_FMatrix_AC 32 { GeometricFilter_FMatrix_ACopenMVG::matching_image_collection::GeometricFilter_FMatrix_AC33 GeometricFilter_FMatrix_AC 34 ( 35 double dPrecision = std::numeric_limits<double>::infinity(), 36 uint32_t iteration = 1024 37 ): 38 m_dPrecision(dPrecision), 39 m_stIteration(iteration), 40 m_F(Mat3::Identity()), 41 m_dPrecision_robust(std::numeric_limits<double>::infinity()){} 42 43 /// Robust fitting of the FUNDAMENTAL matrix 44 template<typename Regions_or_Features_ProviderT> Robust_estimationopenMVG::matching_image_collection::GeometricFilter_FMatrix_AC45 bool Robust_estimation 46 ( 47 const sfm::SfM_Data * sfm_data, 48 const std::shared_ptr<Regions_or_Features_ProviderT> & regions_provider, 49 const Pair pairIndex, 50 const matching::IndMatches & vec_PutativeMatches, 51 matching::IndMatches & geometric_inliers) 52 { 53 using namespace openMVG; 54 using namespace openMVG::robust; 55 geometric_inliers.clear(); 56 57 // Get back corresponding view index 58 const IndexT iIndex = pairIndex.first; 59 const IndexT jIndex = pairIndex.second; 60 61 //-- 62 // Get corresponding point regions arrays 63 //-- 64 65 Mat2X xI,xJ; 66 MatchesPairToMat(pairIndex, vec_PutativeMatches, sfm_data, regions_provider, xI, xJ); 67 68 //-- 69 // Robust estimation 70 //-- 71 72 // Define the AContrario adapted Fundamental matrix solver 73 using KernelType = 74 ACKernelAdaptor< 75 openMVG::fundamental::kernel::SevenPointSolver, 76 openMVG::fundamental::kernel::EpipolarDistanceError, 77 //openMVG::fundamental::kernel::SymmetricEpipolarDistanceError, 78 UnnormalizerT, 79 Mat3>; 80 81 const KernelType kernel( 82 xI, sfm_data->GetViews().at(iIndex)->ui_width, sfm_data->GetViews().at(iIndex)->ui_height, 83 xJ, sfm_data->GetViews().at(jIndex)->ui_width, sfm_data->GetViews().at(jIndex)->ui_height, true); 84 85 // Robustly estimate the Fundamental matrix with A Contrario ransac 86 const double upper_bound_precision = Square(m_dPrecision); 87 std::vector<uint32_t> vec_inliers; 88 const std::pair<double,double> ACRansacOut = 89 ACRANSAC(kernel, vec_inliers, m_stIteration, &m_F, upper_bound_precision); 90 91 if (vec_inliers.size() > KernelType::MINIMUM_SAMPLES *2.5) 92 { 93 m_dPrecision_robust = ACRansacOut.first; 94 // update geometric_inliers 95 geometric_inliers.reserve(vec_inliers.size()); 96 for (const uint32_t & index : vec_inliers) 97 { 98 geometric_inliers.push_back( vec_PutativeMatches[index] ); 99 } 100 return true; 101 } 102 else 103 { 104 vec_inliers.clear(); 105 return false; 106 } 107 } 108 Geometry_guided_matchingopenMVG::matching_image_collection::GeometricFilter_FMatrix_AC109 bool Geometry_guided_matching 110 ( 111 const sfm::SfM_Data * sfm_data, 112 const std::shared_ptr<sfm::Regions_Provider> & regions_provider, 113 const Pair pairIndex, 114 const double dDistanceRatio, 115 matching::IndMatches & matches 116 ) 117 { 118 if (m_dPrecision_robust != std::numeric_limits<double>::infinity()) 119 { 120 // Get back corresponding view index 121 const IndexT iIndex = pairIndex.first; 122 const IndexT jIndex = pairIndex.second; 123 124 const sfm::View * view_I = sfm_data->views.at(iIndex).get(); 125 const sfm::View * view_J = sfm_data->views.at(jIndex).get(); 126 127 // Retrieve corresponding pair camera intrinsic if any 128 const cameras::IntrinsicBase * cam_I = 129 sfm_data->GetIntrinsics().count(view_I->id_intrinsic) ? 130 sfm_data->GetIntrinsics().at(view_I->id_intrinsic).get() : nullptr; 131 const cameras::IntrinsicBase * cam_J = 132 sfm_data->GetIntrinsics().count(view_J->id_intrinsic) ? 133 sfm_data->GetIntrinsics().at(view_J->id_intrinsic).get() : nullptr; 134 135 const std::shared_ptr<features::Regions> 136 regionsI = regions_provider->get(iIndex), 137 regionsJ = regions_provider->get(jIndex); 138 139 // Check the features correspondences that agree in the geometric and photometric domain 140 geometry_aware::GuidedMatching< 141 Mat3, 142 openMVG::fundamental::kernel::EpipolarDistanceError>( 143 //openMVG::fundamental::kernel::SymmetricEpipolarDistanceError>( 144 m_F, 145 cam_I, *regionsI, 146 cam_J, *regionsJ, 147 Square(m_dPrecision_robust), Square(dDistanceRatio), 148 matches); 149 } 150 return matches.size() != 0; 151 } 152 153 double m_dPrecision; // upper_bound precision used for robust estimation 154 uint32_t m_stIteration; // maximal number of iteration for robust estimation 155 // 156 //-- Stored data 157 Mat3 m_F; 158 double m_dPrecision_robust; 159 }; 160 161 } //namespace matching_image_collection 162 } // namespace openMVG 163 164 #endif // OPENMVG_MATCHING_IMAGE_COLLECTION_F_AC_ROBUST_HPP 165