David J. Barnes

567 W 18th Street
Chicago, Il 60616 U.S.A.
+1 (312) 351-52849
Hello@DavidJBarnes.com
David J Barnes | Software Engineer Welcome
Current Projects
Publicly Available Software
Research Interests
Tutorials and Code Examples
Professional Experience
Charity & Volunteer Work
On Robotics and Mechatronics

Tutorials and Code Examples


Back to all Tutorials and Code Examples

Creating a Kalman Filter in C++ with OpenCV

Using a Kalman filter is a powerful way to track objects in motion. The below code was written in C++ and was tested and developed in CodeBlocks using OpenCV 1.1pre. The filter is used to predict the real position of an object being tracked. A dynamic model is developed using historical measurements. These measurements are then used to maximize the probability of the target.

Download the .cpp file.

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cv.h"
#include "highgui.h"

using namespace std;

int main()
{
    // Initialize Kalman filter object, window, number generator, etc
	cvNamedWindow( "Kalman", 1 );
	CvRandState rng;
	cvRandInit( &rng, 0, 1, -1, CV_RAND_UNI );
	
	IplImage* img = cvCreateImage( cvSize(500,500), 8, 3 );
	CvKalman* kalman = cvCreateKalman( 2, 1, 0 );

	// State is phi, delta_phi - angle and angular velocity
	// Initialize with random guess
	CvMat* x_k = cvCreateMat( 2, 1, CV_32FC1 );
	cvRandSetRange( &rng, 0, 0.1, 0 );
	rng.disttype = CV_RAND_NORMAL;
	cvRand( &rng, x_k );

	// Process noise
	CvMat* w_k = cvCreateMat( 2, 1, CV_32FC1 );

	// Measurements, only one parameter for angle
	CvMat* z_k = cvCreateMat( 1, 1, CV_32FC1 );
	cvZero( z_k );

	// Transition matrix F describes model parameters at and k and k+1
	const float F[] = { 1, 1, 0, 1 };
	memcpy( kalman->transition_matrix->data.fl, F, sizeof(F));

	// Initialize other Kalman parameters
	cvSetIdentity( kalman->measurement_matrix, cvRealScalar(1) );
	cvSetIdentity( kalman->process_noise_cov, cvRealScalar(1e-5) );
	cvSetIdentity( kalman->measurement_noise_cov, cvRealScalar(1e-1) );
	cvSetIdentity( kalman->error_cov_post, cvRealScalar(1) );

	// Choose random initial state
	cvRand( &rng, kalman->state_post );

	// Make colors
	CvScalar yellow = CV_RGB(255,255,0);
	CvScalar white = CV_RGB(255,255,255);
	CvScalar red = CV_RGB(255,0,0);

	while( 1 ){
		// Predict point position
		const CvMat* y_k = cvKalmanPredict( kalman, 0 );

		// Generate Measurement (z_k)
		cvRandSetRange( &rng, 0, sqrt( kalman->measurement_noise_cov->data.fl[0] ), 0 );
		cvRand( &rng, z_k );
		cvMatMulAdd( kalman->measurement_matrix, x_k, z_k, z_k );

		// Plot Points
		cvZero( img );


		// Yellow is observed state
		//cvCircle( img,
		//	cvPoint( cvRound(img->width/2 + img->width/3*cos(z_k->data.fl[0])),
		//	cvRound( img->height/2 - img->width/3*sin(z_k->data.fl[0])) ),
		//	4, yellow );


		// White is the predicted state via the filter
		cvCircle( img,
			cvPoint( cvRound(img->width/2 + img->width/3*cos(y_k->data.fl[0])),
			cvRound( img->height/2 - img->width/3*sin(y_k->data.fl[0])) ), 4, white, 2 );

		// Red is the real state
		cvCircle( img,
			cvPoint( cvRound(img->width/2 + img->width/3*cos(x_k->data.fl[0])),
			cvRound( img->height/2 - img->width/3*sin(x_k->data.fl[0])) ),
			4, red );
		cvShowImage( "Kalman", img );

		// Adjust Kalman filter state
		cvKalmanCorrect( kalman, z_k );

		// Apply the transition matrix F and apply "process noise" w_k
		cvRandSetRange( &rng, 0, sqrt( kalman->process_noise_cov->data.fl[0] ), 0 );
		cvRand( &rng, w_k );
		cvMatMulAdd( kalman->transition_matrix, x_k, w_k, x_k );

		// Exit on esc key
		if( cvWaitKey( 100 ) == 27 )
			break;
	}

	return 0;
}

----