1 // This file is part of OpenMVG, an Open Multiple View Geometry C++ library.
2 
3 // Copyright (c) 2017 Pierre MOULON, Romain JANVIER.
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_EO_ROBUST_HPP
10 #define OPENMVG_MATCHING_IMAGE_COLLECTION_EO_ROBUST_HPP
11 
12 #include <limits>
13 #include <utility>
14 #include <vector>
15 
16 #include "openMVG/cameras/Camera_Pinhole.hpp"
17 #include "openMVG/matching/indMatch.hpp"
18 #include "openMVG/matching_image_collection/Geometric_Filter_utils.hpp"
19 #include "openMVG/multiview/solver_essential_kernel.hpp"
20 #include "openMVG/multiview/essential.hpp"
21 #include "openMVG/robust_estimation/robust_estimator_ACRansac.hpp"
22 #include "openMVG/robust_estimation/robust_estimator_ACRansacKernelAdaptator.hpp"
23 #include "openMVG/sfm/sfm_data.hpp"
24 #include "openMVG/types.hpp"
25 
26 namespace openMVG {
27 
28 namespace sfm {
29 struct Regions_Provider;
30 }
31 
32 namespace matching_image_collection {
33 
34 //-- A contrario essential matrix estimation template functor used for filter pair of putative correspondences
35 struct GeometricFilter_EOMatrix_RA
36 {
GeometricFilter_EOMatrix_RAopenMVG::matching_image_collection::GeometricFilter_EOMatrix_RA37     GeometricFilter_EOMatrix_RA
38     (
39       double dPrecision = std::numeric_limits<double>::infinity(),
40       uint32_t iteration = 1024
41     ):
42       m_dPrecision(dPrecision),
43       m_stIteration(iteration),
44       m_E(Mat3::Identity())
45     {
46     }
47 
48     /// Robust fitting according an Orthographic Epipolar Geometry criteria
49     template<typename Regions_or_Features_ProviderT>
Robust_estimationopenMVG::matching_image_collection::GeometricFilter_EOMatrix_RA50     bool Robust_estimation
51     (
52       const sfm::SfM_Data * sfm_data,
53       const std::shared_ptr<Regions_or_Features_ProviderT> & regions_provider,
54       const Pair pairIndex,
55       const matching::IndMatches & vec_PutativeMatches,
56       matching::IndMatches & geometric_inliers
57     )
58     {
59       geometric_inliers.clear();
60 
61       // Get back corresponding view index
62       const IndexT
63         iIndex = pairIndex.first,
64         jIndex = pairIndex.second;
65 
66       //--
67       // Reject pair with missing Intrinsic information
68       //--
69 
70       const sfm::View
71         * view_I = sfm_data->views.at(iIndex).get(),
72         * view_J = sfm_data->views.at(jIndex).get();
73 
74        // Check that valid cameras can be retrieved for the pair of views
75       const cameras::IntrinsicBase
76         * cam_I =
77           sfm_data->GetIntrinsics().count(view_I->id_intrinsic) ?
78             sfm_data->GetIntrinsics().at(view_I->id_intrinsic).get() : nullptr,
79         * cam_J =
80           sfm_data->GetIntrinsics().count(view_J->id_intrinsic) ?
81             sfm_data->GetIntrinsics().at(view_J->id_intrinsic).get() : nullptr;
82 
83       if (!cam_I || !cam_J)
84         return false;
85       if (!isPinhole(cam_I->getType()) || !isPinhole(cam_J->getType()))
86         return false;
87 
88       //--
89       // Get corresponding point regions arrays
90       //--
91 
92       Mat2X xI,xJ;
93       MatchesPairToMat(pairIndex, vec_PutativeMatches, sfm_data, regions_provider, xI, xJ);
94 
95       // Update precision if required (normalization from image to camera plane):
96       if (m_dPrecision != std::numeric_limits<double>::infinity())
97       {
98         m_dPrecision = (cam_I->imagePlane_toCameraPlaneError(Square(m_dPrecision)) +
99                         cam_J->imagePlane_toCameraPlaneError(Square(m_dPrecision))) / 2.;
100       }
101 
102       //--
103       // Robust estimation
104       //--
105 
106       // Define the Kernel
107       // --- using KernelType = essential::kernel::ThreePointKernel;
108       using KernelType =
109         robust::ACKernelAdaptorEssentialOrtho<
110           essential::kernel::ThreePointKernel,
111           essential::kernel::OrthographicSymmetricEpipolarDistanceError,
112           Mat3>;
113 
114       const KernelType kernel(
115         (*cam_I)(xI),
116         sfm_data->GetViews().at(iIndex)->ui_width,
117         sfm_data->GetViews().at(iIndex)->ui_height,
118         (*cam_J)(xJ),
119         sfm_data->GetViews().at(jIndex)->ui_width,
120         sfm_data->GetViews().at(jIndex)->ui_height
121       );
122 
123       // Robustly estimate the model with AC-RANSAC
124       std::vector<uint32_t> vec_inliers;
125 
126       const auto ACRansacOut = ACRANSAC(
127         kernel, vec_inliers, m_stIteration, &m_E, m_dPrecision);
128 
129       if (vec_inliers.size() > KernelType::MINIMUM_SAMPLES * 2.5)
130       {
131         // update geometric_inliers
132         geometric_inliers.reserve(vec_inliers.size());
133         for (const uint32_t & index : vec_inliers)
134         {
135           geometric_inliers.push_back( vec_PutativeMatches[index] );
136         }
137         return true;
138       }
139       else
140       {
141         vec_inliers.clear();
142         return false;
143       }
144     }
145 
Geometry_guided_matchingopenMVG::matching_image_collection::GeometricFilter_EOMatrix_RA146   bool Geometry_guided_matching
147   (
148     const sfm::SfM_Data * sfm_data,
149     const std::shared_ptr<sfm::Regions_Provider> & regions_provider,
150     const Pair pairIndex,
151     const double dDistanceRatio,
152     matching::IndMatches & matches
153   )
154   {
155     return false;
156   }
157 
158   uint32_t m_stIteration; // maximal number of iteration for robust estimation
159   double m_dPrecision;    // upper_bound precision used for robust estimation
160   //
161   //-- Stored data
162   Mat3 m_E;
163 };
164 
165 } //namespace matching_image_collection
166 } // namespace openMVG
167 
168 #endif //OPENMVG_MATCHING_IMAGE_COLLECTION_EO_ROBUST_HPP
169