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