forked from edrosten/TooN
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathirls.h
163 lines (134 loc) · 5.91 KB
/
irls.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
// -*- c++ -*-
// Copyright (C) 2005,2009 Tom Drummond ([email protected])
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions
//are met:
//1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
//THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
//AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
//LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
#ifndef __IRLS_H
#define __IRLS_H
#include <TooN/wls.h>
#include <cassert>
#include <cmath>
namespace TooN {
/// Robust reweighting (type I) for IRLS.
/// A reweighting class with \f$w(x)=\frac{1}{\sigma + |x|}\f$.
/// This structure can be passed as the second template argument in IRLS.
/// @ingroup gEquations
template<typename Precision>
struct RobustI {
void set_sd(Precision x){ sd_inlier = x;} ///<Set the noise standard deviation.
double sd_inlier; ///< The inlier standard deviation, \f$\sigma\f$.
inline Precision reweight(Precision x) {return 1/(sd_inlier+fabs(x));} ///< Returns \f$w(x)\f$.
inline Precision true_scale(Precision x) {return reweight(x) - fabs(x)*reweight(x)*reweight(x);} ///< Returns \f$w(x) + xw'(x)\f$.
inline Precision objective(Precision x) {return fabs(x) + sd_inlier*::log(sd_inlier*reweight(x));} ///< Returns \f$\int xw(x)dx\f$.
};
/// Robust reweighting (type II) for IRLS.
/// A reweighting class with \f$w(x)=\frac{1}{\sigma + x^2}\f$.
/// This structure can be passed as the second template argument in IRLS.
/// @ingroup gEquations
template<typename Precision>
struct RobustII {
void set_sd(Precision x){ sd_inlier = x*x;} ///<Set the noise standard deviation.
Precision sd_inlier; ///< The inlier standard deviation squared, \f$\sigma\f$.
inline Precision reweight(Precision d){return 1/(sd_inlier+d*d);} ///< Returns \f$w(x)\f$.
inline Precision true_scale(Precision d){return d - 2*d*reweight(d);} ///< Returns \f$w(x) + xw'(x)\f$.
inline Precision objective(Precision d){return 0.5 * ::log(1 + d*d/sd_inlier);} ///< Returns \f$\int xw(x)dx\f$.
};
/// A reweighting class representing no reweighting in IRLS.
/// \f$w(x)=1\f$
/// This structure can be passed as the second template argument in IRLS.
/// @ingroup gEquations
template<typename Precision>
struct ILinear {
void set_sd(Precision){} ///<Set the noise standard deviation (does nothing).
inline Precision reweight(Precision d){return 1;} ///< Returns \f$w(x)\f$.
inline Precision true_scale(Precision d){return 1;} ///< Returns \f$w(x) + xw'(x)\f$.
inline Precision objective(Precision d){return d*d;} ///< Returns \f$\int xw(x)dx\f$.
};
///A reweighting class where the objective function tends to a
///fixed value, rather than infinity. Note that this is not therefore
///a proper distribution since its integral is not finite. It is considerably
///more efficient than RobustI and II, since log() is not used.
/// @ingroup gEquations
template<typename Precision>
struct RobustIII {
void set_sd(Precision x){ sd_inlier = x*x;} ///<Set the noise standard deviation.
Precision sd_inlier; ///< Inlier standard deviation squared.
/// Returns \f$w(x)\f$.
Precision reweight(Precision x) const
{
double d = (1 + x*x/sd_inlier);
return 1/(d*d);
}
///< Returns \f$\int xw(x)dx\f$.
Precision objective(Precision x) const
{
return x*x / (2*(1 + x*x/sd_inlier));
}
};
/// Performs iterative reweighted least squares.
/// @param Size the size
/// @param Reweight The reweighting functor. This structure must provide reweight(),
/// true-scale() and objective() methods. Existing examples are Robust I, Robust II and ILinear.
/// @ingroup gEquations
template <int Size, typename Precision, template <typename Precision> class Reweight>
class IRLS
: public Reweight<Precision>,
public WLS<Size,Precision>
{
public:
IRLS(int size=Size):
WLS<Size,Precision>(size),
my_true_C_inv(Zeros(size))
{
my_residual=0;
}
template<int Size2, typename Precision2, typename Base2>
inline void add_mJ(Precision m, const Vector<Size2,Precision2,Base2>& J) {
SizeMismatch<Size,Size2>::test(my_true_C_inv.num_rows(), J.size());
Precision scale = Reweight<Precision>::reweight(m);
Precision ts = Reweight<Precision>::true_scale(m);
my_residual += Reweight<Precision>::objective(m);
WLS<Size>::add_mJ(m,J,scale);
Vector<Size,Precision> scaledm(m*ts);
my_true_C_inv += scaledm.as_col() * scaledm.as_row();
}
void operator += (const IRLS& meas){
WLS<Size>::operator+=(meas);
my_true_C_inv += meas.my_true_C_inv;
}
Matrix<Size,Size,Precision>& get_true_C_inv() {return my_true_C_inv;}
const Matrix<Size,Size,Precision>& get_true_C_inv()const {return my_true_C_inv;}
Precision get_residual() {return my_residual;}
void clear(){
WLS<Size,Precision>::clear();
my_residual=0;
my_true_C_inv = Zeros;
}
private:
Precision my_residual;
Matrix<Size,Size,Precision> my_true_C_inv;
// comment out to allow bitwise copying
IRLS( IRLS& copyof );
int operator = ( IRLS& copyof );
};
}
#endif