-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathLSFit.hpp
88 lines (72 loc) · 1.72 KB
/
LSFit.hpp
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
#include "opencv2/opencv.hpp"
using namespace cv;
namespace LS {
enum CurveDegree {
CURVE_DEG_CONST = 1,
CURVE_DEG_LIN,
CURVE_DEG_QUAD,
CURVE_DEG_CUBIC,
CURVE_DEG_QUART,
CURVE_DEG_QUINT
};
template<int D, typename X, typename Y>
class LSFit
{
public:
LSFit(bool w = false)
: weighted(w),
coef(D, 1, DataType<Y>::type)
{
}
void solve_ls() {
size_t n = ys.size();
int dim = n < D ? n : D;
if (n < D || coef.rows < dim)
coef.resize(dim, 0);
Mat x(n, dim, DataType<Y>::type);
Mat y(ys, weighted); // need a copy of data when using weights
x.col(0) = Scalar(1);
if (dim > 1)
Mat(xs, weighted).convertTo(x.col(1), DataType<Y>::type);
for (int d = 2; d < dim; ++d)
pow(x.col(1), d, x.col(d));
if (weighted) {
for (int i = 1; i < n; ++i) {
x.row(i) *= i * 0.25;
y.row(i) *= i * 0.25;
}
}
solve(x, y, coef, DECOMP_QR); // alternatively DECOMP_SVD
}
size_t size() {
return ys.size();
}
Y at(size_t i) {
return ys[i];
}
void push_back(X x, Y y, bool solve = true) {
xs.push_back(x);
ys.push_back(y);
if (solve)
solve_ls();
}
void clear() {
xs.clear();
ys.clear();
}
const Y interpolate(const X& x) const {
Y sum(0);
for (size_t d = 0; d < coef.rows; ++d)
sum += coef.at<Y>(d, 0) * pow(x, d);
return sum;
}
const Y operator[](const X& x) const {
return interpolate(x);
}
private:
bool weighted;
vector<X> xs;
vector<Y> ys;
Mat coef;
};
}