-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path03_random_const_estimate_offline_cvkf.cpp
138 lines (102 loc) · 3.81 KB
/
03_random_const_estimate_offline_cvkf.cpp
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
//
// Created by jin on 1/21/19.
//
#include <opencv2/opencv.hpp>
#include <time.h>
using namespace cv;
using namespace std;
int main()
{
//Greg Welch and Gary Bishop, "An Introduction to the Kalman Filter", 2006
//Estimating a Random Constant: Offline with KalmanFilter class in OpenCV
theRNG().state = time(NULL);
int t, count = 500;
double x = -0.37727; // truth value
///////////// Kalman Filter /////////////
double Q = 1e-5; //process variance
double R = 0.0001; //estimation of measurement variance
Scalar stddevR = Scalar::all(sqrt(R));
vector<float> measurement_k(count); //the noisy measurement, z_k
randn(measurement_k, Scalar::all(x), stddevR);
vector<float> state_k(count); // state, x_k
vector<float> postP(count); // the posteriori error covariance, P
KalmanFilter KF(1, 1, 0);
Mat measurement(1, 1, CV_32F);
setIdentity(KF.transitionMatrix); //A = 1
setIdentity(KF.measurementMatrix); // H = 1
setIdentity(KF.processNoiseCov, Scalar::all(Q));
setIdentity(KF.measurementNoiseCov, Scalar::all(R));
//initial guesses
setIdentity(KF.statePost, Scalar::all(0)); // x_k(0) = 0
setIdentity(KF.errorCovPost, Scalar::all(1)); // P_k(0) = 1
state_k[0] = KF.statePost.at<float>(0);
postP[0] = KF.errorCovPost.at<float>(0);
for (t = 1; t < count; t++)
{
Mat prediction = KF.predict(); // predict
measurement.at<float>(0) = measurement_k[t];
//state_k[t] = KF.statePost.at<float>(0);
//postP[t] = KF.errorCovPost.at<float>(0);
Mat estimate = KF.correct(measurement); //update
// state_k[t] = estimate.at<float>(0);
state_k[t] = KF.statePost.at<float>(0);
postP[t] = KF.errorCovPost.at<float>(0);
}
// drawing values
Mat dstImage(512, 512, CV_8UC3, Scalar::all(255));
Size size = dstImage.size();
namedWindow("dstImage");
double minVal, maxVal;
minMaxLoc(measurement_k, &minVal, &maxVal);
double scale = size.height / (maxVal - minVal);
cout << "measurement_k : ";
cout << " minVal= " << minVal;
cout << ", maxVal= " << maxVal << endl;
// drawing the truth value, x = -0.37727
Point pt1, pt2;
pt1.x = 0;
pt1.y = size.height - cvRound(scale * x - scale * minVal);
pt2.x = size.width;
pt2.y = size.height - cvRound(scale * x - scale * minVal);
line(dstImage, pt1, pt2, Scalar(255, 0, 0), 2);
//drawing the noisy measurements, measurement_k
int step = size.width / count;
for (t = 0; t < count; t++)
{
pt1.x = t * step;
pt1.y = size.height - cvRound(scale * measurement_k[t] - scale * minVal);
circle(dstImage, pt1, 3, Scalar(0, 255, 0), 2);
}
//drawing the filter estimate, state_k
pt1.x = 0;
pt1.y = size.height - cvRound(scale * state_k[0] - scale * minVal);
for (t = 1; t < count; t++)
{
pt2.x = t * step;
pt2.y = size.height - cvRound(scale * state_k[t] - scale * minVal);
line(dstImage, pt1, pt2, Scalar(0, 0, 255), 2);
pt1 = pt2;
}
imshow("dstImage", dstImage);
//drawing the error covariance, postP
Mat PImage(size.height, size.width, CV_8UC3, Scalar::all(255));
size = PImage.size();
namedWindow("PImage");
minMaxLoc(postP, &minVal, &maxVal);
scale = size.height / (maxVal - minVal);
cout << "error covariance, postP: ";
cout << " minVal = " << minVal;
cout << ", maxVal = " << maxVal << endl;
pt1.x = 0;
pt1.y = size.height - cvRound(scale * postP[0] - scale * minVal);
step = size.width / count;
for (t = 1; t < count; t++)
{
pt2.x = t * step;
pt2.y = size.height - cvRound(scale * postP[t] - scale * minVal);
line(PImage, pt1, pt2, Scalar(0, 0, 255), 2);
pt1 = pt2;
}
imshow("PImage", PImage);
waitKey(0);
}