1 #ifndef TAG_RANSAC_ESTIMATORS_H
2 #define TAG_RANSAC_ESTIMATORS_H
9 #include <TooN/helpers.h>
10 #include <TooN/Cholesky.h>
14 #include <TooN/SymEigen.h>
24 namespace essential_matrix {
26 template <
class M>
inline int getValidPair(
const TooN::Matrix<3>& R1,
const TooN::Matrix<3>& R2,
const TooN::Vector<2>& e,
double z1,
const M& m)
29 TooN::Vector<3> ha = TooN::unproject(
first_point(m));
30 TooN::Vector<3> inf1 = R1*ha;
31 TooN::Vector<3> inf2 = R2*ha;
34 TooN::Vector<2> pinf1 = project(inf1);
35 TooN::Vector<2> pinf2 = project(inf2);
36 if (zp1*dm*(pinf1 - e) >= 0) {
39 return z1 <= 0 ? 0 : 1;
45 return z1 <= 0 ? 2 : 3;
50 template <
int N,
class Accessor>
double determinant(
const TooN::FixedMatrix<N,N,Accessor>& M)
54 for (
int i=0; i<N; i++)
55 det *= lu.get_lu()[i][i];
69 struct EssentialMatrix {
71 static const int hypothesis_size = 8;
74 template <
class It>
bool estimate(It begin, It end) {
75 TooN::Matrix<9> M = TooN::zeros<9,9>();
76 for (It it=begin; it!= end; ++it) {
79 const double factor = 1.0/
noise(*it);
80 const double m[9] = {b[0]*a[0], b[0]*a[1], b[1]*a[0], b[1]*a[1], b[0], b[1], a[0], a[1], 1};
81 for (
int j=0; j<9; j++) {
82 for (
int k=j; k<9; k++) {
83 M[j][k] += m[j]*m[k] * factor;
87 for (
int j=0; j<9;j++)
88 for (
int k=j; k<9; k++)
90 TooN::Matrix<4> M11 = M.template slice<0,0,4,4>();
91 TooN::Matrix<4,5> M12 = M.template slice<0,4,4,5>();
92 TooN::Matrix<5> M22 = M.template slice<4,4,5,5>();
93 TooN::Cholesky<5> chol(M22);
94 if (chol.get_rank() < 5) {
95 if (chol.get_rank() < 3)
100 TooN::SO3::coerce(R);
103 E[2][0] = E[2][1] = E[2][2] = 0;
106 TooN::Matrix<5,4> K = chol.inverse_times(M12.T());
107 TooN::Matrix<4> Q = M11 - M12*K;
108 TooN::SymEigen<4> eigen(Q);
109 TooN::Vector<4> e1 = eigen.get_evectors()[0];
110 TooN::Vector<5> e2 = -(K * e1);
117 E[2] = e2.template slice<2,3>();
119 TooN::SVD<3> svdE(E);
120 const TooN::Vector<3> temp = (TooN::make_Vector, 1, 1, 0);
121 E = svdE.get_U()*TooN::diagmult(temp,svdE.get_VT());
125 template <
class Match>
inline bool isInlier(
const Match& m,
double r)
const {
126 TooN::Vector<3> line = E.template slice<0,0,3,2>()*
first_point(m) + E.T()[2];
127 double dot = line.template slice<0,2>() *
second_point(m) + line[2];
128 return (dot*dot <= (line[0]*line[0] + line[1]*line[1]) * r*r *
noise(m));
131 template <
class Match>
inline double score(
const Match& m)
const {
132 TooN::Vector<3> line = E.template slice<0,0,3,2>()*
first_point(m) + E.T()[2];
133 double dot = line.template slice<0,2>() *
second_point(m) + line[2];
134 return dot*dot / (line[0]*line[0] + line[1]*line[1]);
143 template <
class It> std::vector<std::pair<size_t, TooN::SE3> > decompose(It begin, It end, std::vector<int>& group)
145 static const double vals[9]={0,-1,0,1,0,0,0,0,1};
146 static const TooN::Matrix<3> Rz(vals);
148 const size_t N = std::distance(begin,end);
149 assert(group.size() >= N);
151 TooN::SVD<3> svdE(E);
152 TooN::Matrix<3> R1 = svdE.get_U()*Rz.T()*svdE.get_VT();
153 TooN::Matrix<3> R2 = svdE.get_U()*Rz*svdE.get_VT();
154 if (essential_matrix::determinant(R1) < 0) {
158 TooN::Vector<3> t1 = svdE.get_U().T()[2];
159 TooN::Vector<3> t2 = -t1;
160 TooN::Vector<2> epipole = project(t1);
161 std::vector<std::pair<size_t, TooN::SE3> > result(4,std::make_pair(0,TooN::SE3()));
163 for (It it = begin; it!=end; ++it, ++i) {
164 int index = getValidPair(R1, R2, epipole, t1[2], *it);
165 result[index].first++;
168 result[0].second.get_rotation() = result[1].second.get_rotation() = R1;
169 result[2].second.get_rotation() = result[3].second.get_rotation() = R2;
170 result[0].second.get_translation() = result[2].second.get_translation() = t1;
171 result[1].second.get_translation() = result[3].second.get_translation() = t2;
200 template <
class It>
void estimate(It begin, It end) {
204 template <
class M>
inline double score(
const M& m)
const {
205 TooN::Vector<3> a = TooN::unproject(
first_point(m));
207 const TooN::Vector<2> disp = TooN::project(
H * a) - b;
211 template <
class M>
inline bool isInlier(
const M& m,
double r)
const {
235 template <
class It>
void estimate(It begin, It end) {
236 TooN::WLS<3> wls_x, wls_y;
239 for (It it = begin; it!= end; ++it) {
242 const double weight = 1.0 /
noise(*it);
243 wls_x.add_mJ(b[0], TooN::unproject(a), weight);
244 wls_y.add_mJ(b[1], TooN::unproject(a), weight);
248 TooN::Vector<3> Atx = wls_x.get_mu();
249 TooN::Vector<3> Aty = wls_y.get_mu();
250 A[0] = Atx.template slice<0,2>();
251 A[1] = Aty.template slice<0,2>();
256 template <
class M>
inline double score(
const M& m)
const {
259 const TooN::Vector<2> disp =
A*a +
t - b;
263 template <
class M>
inline bool isInlier(
const M& m,
double r)
const {
284 template <
class It>
void estimate(It begin, It end) {
295 template <
class M>
inline double score(
const M& m)
const {
300 template <
class M>
inline bool isInlier(
const M& m,
double r)
const {
323 template <
class It>
void estimate(It begin, It end){
324 assert(std::distance(begin, end) >= 3);
325 if( std::distance(begin, end) == 3 ){
326 const TooN::Vector<3> d1 = *(begin+1) - *begin;
327 const TooN::Vector<3> d2 = *(begin+2) - *begin;
328 plane.template slice<0,3>() = d1 ^ d2;
329 TooN::normalize(
plane.template slice<0,3>());
330 plane[3] = -(*begin) *
plane.template slice<0,3>();
332 TooN::Matrix<> design(std::distance(begin, end), 4);
333 for(It p = begin; p != end; ++p)
334 design[p-begin] = TooN::unproject(*p);
335 TooN::SVD<> s(design);
336 plane = s.get_VT()[3];
337 const double d = sqrt(
plane.template slice<0,3>() *
plane.template slice<0,3>());
341 plane = TooN::makeVector( 0, 0, 0, 1);
346 template <
class M>
inline double score(
const M & m)
const {
347 const double d =
plane * TooN::unproject(m);
351 template <
class M>
inline bool isInlier(
const M& m,
double r)
const {