-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathMEstimator.h
202 lines (158 loc) · 5.59 KB
/
MEstimator.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
// -*- c++ -*-
// Copyright 2008 Isis Innovation Limited
// MEstimator.h
//
// Defines various MEstimators which can be used by the Tracker and
// the Bundle adjuster. Not that some of the inputs are square
// quantities!
#ifndef __MESTIMATOR_H
#define __MESTIMATOR_H
#include <vector>
#include <algorithm>
#include <cassert>
struct Tukey
{
inline static double FindSigmaSquared(std::vector<double> &vdErrorSquared);
inline static double SquareRootWeight(double dErrorSquared, double dSigmaSquared);
inline static double Weight(double dErrorSquared, double dSigmaSquared);
inline static double ObjectiveScore(double dErrorSquared, double dSigmaSquared);
};
struct Cauchy
{
inline static double FindSigmaSquared(std::vector<double> &vdErrorSquared);
inline static double SquareRootWeight(double dErrorSquared, double dSigmaSquared);
inline static double Weight(double dErrorSquared, double dSigmaSquared);
inline static double ObjectiveScore(double dErrorSquared, double dSigmaSquared);
};
struct Huber
{
inline static double FindSigmaSquared(std::vector<double> &vdErrorSquared);
inline static double SquareRootWeight(double dErrorSquared, double dSigmaSquared);
inline static double Weight(double dErrorSquared, double dSigmaSquared);
inline static double ObjectiveScore(double dErrorSquared, double dSigmaSquared);
};
struct LeastSquares
{
inline static double FindSigmaSquared(std::vector<double> &vdErrorSquared);
inline static double SquareRootWeight(double dErrorSquared, double dSigmaSquared);
inline static double Weight(double dErrorSquared, double dSigmaSquared);
inline static double ObjectiveScore(double dErrorSquared, double dSigmaSquared);
};
inline double Tukey::Weight(double dErrorSquared, double dSigmaSquared)
{
double dSqrt = SquareRootWeight(dErrorSquared, dSigmaSquared);
return dSqrt * dSqrt;
}
inline double Tukey::SquareRootWeight(double dErrorSquared, double dSigmaSquared)
{
if(dErrorSquared > dSigmaSquared)
return 0.0;
else
return 1.0 - (dErrorSquared / dSigmaSquared);
}
inline double Tukey::ObjectiveScore(double dErrorSquared, const double dSigmaSquared)
{
// NB All returned are scaled because
// I'm not multiplying by sigmasquared/6.0
if(dErrorSquared > dSigmaSquared)
return 1.0;
double d = 1.0 - dErrorSquared / dSigmaSquared;
return (1.0 - d*d*d);
}
inline double Tukey::FindSigmaSquared(std::vector<double> &vdErrorSquared)
{
double dSigmaSquared;
assert(vdErrorSquared.size() > 0);
std::sort(vdErrorSquared.begin(), vdErrorSquared.end());
double dMedianSquared = vdErrorSquared[vdErrorSquared.size() / 2];
double dSigma = 1.4826 * (1 + 5.0 / (vdErrorSquared.size() * 2 - 6)) * sqrt(dMedianSquared);
dSigma = 4.6851 * dSigma;
dSigmaSquared = dSigma * dSigma;
return dSigmaSquared;
}
inline double Cauchy::Weight(double dErrorSquared, double dSigmaSquared)
{
return 1.0 / (1.0 + dErrorSquared / dSigmaSquared);
}
inline double Cauchy::SquareRootWeight(double dErrorSquared, double dSigmaSquared)
{
return sqrt(Weight(dErrorSquared, dSigmaSquared));
}
inline double Cauchy::ObjectiveScore(double dErrorSquared, const double dSigmaSquared)
{
return log(1.0 + dErrorSquared / dSigmaSquared);
}
inline double Cauchy::FindSigmaSquared(std::vector<double> &vdErrorSquared)
{
double dSigmaSquared;
assert(vdErrorSquared.size() > 0);
std::sort(vdErrorSquared.begin(), vdErrorSquared.end());
double dMedianSquared = vdErrorSquared[vdErrorSquared.size() / 2];
double dSigma = 1.4826 * (1 + 5.0 / (vdErrorSquared.size() * 2 - 6)) * sqrt(dMedianSquared);
dSigma = 4.6851 * dSigma;
dSigmaSquared = dSigma * dSigma;
return dSigmaSquared;
}
///////////////////////////////////////
///////////////////////////////////////
///////////////////////////////////////
///////////////////////////////////////
inline double Huber::Weight(double dErrorSquared, double dSigmaSquared)
{
if(dErrorSquared < dSigmaSquared)
return 1;
else
return sqrt(dSigmaSquared / dErrorSquared);
}
inline double Huber::SquareRootWeight(double dErrorSquared, double dSigmaSquared)
{
return sqrt(Weight(dErrorSquared, dSigmaSquared));
}
inline double Huber::ObjectiveScore(double dErrorSquared, const double dSigmaSquared)
{
if(dErrorSquared< dSigmaSquared)
return 0.5 * dErrorSquared;
else
{
double dSigma = sqrt(dSigmaSquared);
double dError = sqrt(dErrorSquared);
return dSigma * ( dError - 0.5 * dSigma);
}
}
inline double Huber::FindSigmaSquared(std::vector<double> &vdErrorSquared)
{
double dSigmaSquared;
assert(vdErrorSquared.size() > 0);
std::sort(vdErrorSquared.begin(), vdErrorSquared.end());
double dMedianSquared = vdErrorSquared[vdErrorSquared.size() / 2];
double dSigma = 1.4826 * (1 + 5.0 / (vdErrorSquared.size() * 2 - 6)) * sqrt(dMedianSquared);
dSigma = 1.345 * dSigma;
dSigmaSquared = dSigma * dSigma;
return dSigmaSquared;
}
///////////////////////////////////////
///////////////////////////////////////
///////////////////////////////////////
///////////////////////////////////////
inline double LeastSquares::Weight(double dErrorSquared, double dSigmaSquared)
{
return 1.0;
}
inline double LeastSquares::SquareRootWeight(double dErrorSquared, double dSigmaSquared)
{
return 1.0;
}
inline double LeastSquares::ObjectiveScore(double dErrorSquared, const double dSigmaSquared)
{
return dErrorSquared;
}
inline double LeastSquares::FindSigmaSquared(std::vector<double> &vdErrorSquared)
{
if(vdErrorSquared.size() == 0)
return 0.0;
double dSum = 0.0;
for(unsigned int i=0; i<vdErrorSquared.size(); i++)
dSum+=vdErrorSquared[i];
return dSum / vdErrorSquared.size();
}
#endif