00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00039 #include <stdio.h>
00040 #include <stdlib.h>
00041 #include <iostream>
00042
00043 #include <QDebug>
00044 #include <QVApplication>
00045 #include <QVDefaultGUI>
00046
00047 #include <QVNumericPlot>
00048 #include <QVVector>
00049 #include <QVMatrix>
00050
00051 #include <qvmath.h>
00052
00053 #ifndef DOXYGEN_IGNORE_THIS
00054
00055 #define MEASUREMENT_NOISE_COV 0.5
00056 #define PROCESS_NOISE_COV 0.1
00057
00058 class QVKalmanFilter
00059 {
00060 private:
00061 CvKalman* kalman;
00062
00063 public:
00064 QVKalmanFilter( const int dynamParams, const int measureParams, const QVMatrix &transitionMatrix,
00065 const double processNoiseCovariance, const double measurementNoiseCovariance):
00066 kalman(cvCreateKalman(dynamParams, measureParams, 0))
00067 {
00068 CvMat *transitionCvMatrix = transitionMatrix.toCvMat(CV_32F);
00069 cvCopy(transitionCvMatrix, kalman->transition_matrix);
00070
00071 cvReleaseMat(&transitionCvMatrix);
00072
00073 cvSetIdentity(kalman->process_noise_cov, cvRealScalar(processNoiseCovariance));
00074 cvSetIdentity(kalman->measurement_noise_cov, cvRealScalar(measurementNoiseCovariance));
00075 cvSetIdentity(kalman->measurement_matrix, cvRealScalar(1));
00076 cvSetIdentity(kalman->error_cov_post, cvRealScalar(1));
00077
00078 cvZero( kalman->state_post );
00079 }
00080
00081 const QVVector predict() const
00082 {
00083 return QVMatrix(cvKalmanPredict( kalman, 0 ));
00084 }
00085
00086 void correct(const QVVector &z)
00087 {
00088 CvMat* z_k = z.toColumnMatrix().toCvMat(CV_32F);
00089 cvKalmanCorrect( kalman, z_k );
00090 cvReleaseMat(&z_k);
00091 }
00092
00093 static const QVMatrix linearMotionTransitionMatrix(const int size = 1, const double step = 0.1)
00094 {
00095 QVMatrix transitionMatrix = QVMatrix::identity(2*size);
00096 for (int i = 0; i < size; i++)
00097 transitionMatrix(i,size+i) = step;
00098
00099 return transitionMatrix;
00100 }
00101 };
00102
00103
00104 class KalmanFilterBlock: public QVProcessingBlock
00105 {
00106 private:
00107 QVKalmanFilter kalmanFilter;
00108
00109 public:
00110 KalmanFilterBlock(const QString name): QVProcessingBlock(name),
00111 kalmanFilter(2, 1, QVKalmanFilter::linearMotionTransitionMatrix(), PROCESS_NOISE_COV, MEASUREMENT_NOISE_COV)
00112 {
00113 addProperty<double>("Kalman[sin(x) + noise]", outputFlag);
00114 addProperty<double>("sin(x)", outputFlag);
00115 addProperty<double>("sin(x) + noise", outputFlag);
00116
00117 addProperty<double>("Kalman error", outputFlag);
00118 addProperty<double>("Measurement error", outputFlag);
00119 }
00120
00121 void iterate()
00122 {
00123
00124 const double realState = 1 - cos((double) getIteration() / 512.0),
00125 measurementNoise = ((double)(rand()%2000)/1000.0 - 1.0) * sqrt(MEASUREMENT_NOISE_COV),
00126 processNoise = ((double)(rand()%2000)/1000.0 - 1.0) * sqrt(PROCESS_NOISE_COV);
00127
00128
00129 const QVVector y = kalmanFilter.predict();
00130 kalmanFilter.correct(QVVector(1, realState + processNoise + measurementNoise));
00131
00132
00133 setPropertyValue<double>("Kalman[sin(x) + noise]", y[0]);
00134 setPropertyValue<double>("sin(x)", realState + processNoise);
00135 setPropertyValue<double>("sin(x) + noise", realState + processNoise + measurementNoise);
00136 setPropertyValue<double>("Kalman error", ABS(realState - y[0]));
00137 setPropertyValue<double>("Measurement error", ABS(processNoise + measurementNoise));
00138 }
00139 };
00140
00141 #include <QVYUV4MPEG2WriterBlock>
00142 #include <QVNumericPlot>
00143
00144 int main(int argc, char *argv[])
00145 {
00146 QVApplication app(argc, argv,
00147 "Example program for QVision library. Applies Kalman filtering to an input function."
00148 );
00149
00150 KalmanFilterBlock kalmanFilterBlock("Corners Block");
00151
00152 QVDefaultGUI gui;
00153
00154 QVNumericPlot measurePlot("Obtained values");
00155 kalmanFilterBlock.linkProperty("Kalman[sin(x) + noise]", measurePlot);
00156 kalmanFilterBlock.linkProperty("sin(x)", measurePlot);
00157 kalmanFilterBlock.linkProperty("sin(x) + noise", measurePlot);
00158
00159 QVNumericPlot errorPlot("Estimation errors");
00160 kalmanFilterBlock.linkProperty("Kalman error", errorPlot);
00161 kalmanFilterBlock.linkProperty("Measurement error", errorPlot);
00162
00163 return app.exec();
00164
00165 }
00166
00167 #endif
00168