1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/video/tracking.hpp" 2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/highgui/highgui.hpp" 3793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 4793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <stdio.h> 5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 6793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerusing namespace cv; 7793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic inline Point calcPoint(Point2f center, double R, double angle) 9793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 10793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return center + Point2f((float)cos(angle), (float)-sin(angle))*(float)R; 11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 12793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 13793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void help() 14793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 15793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler printf( "\nExample of c calls to OpenCV's Kalman filter.\n" 16793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler" Tracking of rotating point.\n" 17793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler" Rotation speed is constant.\n" 18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler" Both state and measurements vectors are 1D (a point angle),\n" 19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler" Measurement is the real point angle + gaussian noise.\n" 20793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler" The real and the estimated points are connected with yellow line segment,\n" 21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler" the real and the measured points are connected with red line segment.\n" 22793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler" (if Kalman filter works correctly,\n" 23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler" the yellow segment should be shorter than the red one).\n" 24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "\n" 25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler" Pressing any key (except ESC) will reset the tracking with a different speed.\n" 26793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler" Pressing ESC will stop the program.\n" 27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ); 28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 29793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerint main(int, char**) 31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 32793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler help(); 33793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Mat img(500, 500, CV_8UC3); 34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler KalmanFilter KF(2, 1, 0); 35793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Mat state(2, 1, CV_32F); /* (phi, delta_phi) */ 36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Mat processNoise(2, 1, CV_32F); 37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Mat measurement = Mat::zeros(1, 1, CV_32F); 38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler char code = (char)-1; 39793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for(;;) 41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 42793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler randn( state, Scalar::all(0), Scalar::all(0.1) ); 43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler KF.transitionMatrix = (Mat_<float>(2, 2) << 1, 1, 0, 1); 44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler setIdentity(KF.measurementMatrix); 46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler setIdentity(KF.processNoiseCov, Scalar::all(1e-5)); 47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler setIdentity(KF.measurementNoiseCov, Scalar::all(1e-1)); 48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler setIdentity(KF.errorCovPost, Scalar::all(1)); 49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler randn(KF.statePost, Scalar::all(0), Scalar::all(0.1)); 51793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 52793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for(;;) 53793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 54793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Point2f center(img.cols*0.5f, img.rows*0.5f); 55793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler float R = img.cols/3.f; 56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double stateAngle = state.at<float>(0); 57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Point statePt = calcPoint(center, R, stateAngle); 58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Mat prediction = KF.predict(); 60793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double predictAngle = prediction.at<float>(0); 61793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Point predictPt = calcPoint(center, R, predictAngle); 62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 63793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler randn( measurement, Scalar::all(0), Scalar::all(KF.measurementNoiseCov.at<float>(0))); 64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // generate measurement 66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler measurement += KF.measurementMatrix*state; 67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 68793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double measAngle = measurement.at<float>(0); 69793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Point measPt = calcPoint(center, R, measAngle); 70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // plot points 72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #define drawCross( center, color, d ) \ 73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler line( img, Point( center.x - d, center.y - d ), \ 74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Point( center.x + d, center.y + d ), color, 1, LINE_AA, 0); \ 75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler line( img, Point( center.x + d, center.y - d ), \ 76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Point( center.x - d, center.y + d ), color, 1, LINE_AA, 0 ) 77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler img = Scalar::all(0); 79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler drawCross( statePt, Scalar(255,255,255), 3 ); 80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler drawCross( measPt, Scalar(0,0,255), 3 ); 81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler drawCross( predictPt, Scalar(0,255,0), 3 ); 82793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler line( img, statePt, measPt, Scalar(0,0,255), 3, LINE_AA, 0 ); 83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler line( img, statePt, predictPt, Scalar(0,255,255), 3, LINE_AA, 0 ); 84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if(theRNG().uniform(0,4) != 0) 86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler KF.correct(measurement); 87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler randn( processNoise, Scalar(0), Scalar::all(sqrt(KF.processNoiseCov.at<float>(0, 0)))); 89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler state = KF.transitionMatrix*state + processNoise; 90793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 91793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler imshow( "Kalman", img ); 92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler code = (char)waitKey(100); 93793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( code > 0 ) 95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( code == 27 || code == 'q' || code == 'Q' ) 98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return 0; 102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 103