kalman 滤波 演示与opencv代码

在机器视觉中追踪时常会用到预测算法,kalman是你一定知道的。它可以用来预测各种状态,比如说位置,速度等。关于它的理论有很多很好的文献可以参考。opencv给出了kalman filter的一个实现,而且有范例,但估计不少人对它的使用并不清楚,因为我也是其中一个。本文的应用是对二维坐标进行预测和平滑

 

使用方法:

1、初始化

const int stateNum=4;//状态数,包括(x,y,dx,dy)坐标及速度(每次移动的距离)
const int measureNum=2;//观测量,能看到的是坐标值,当然也可以自己计算速度,但没必要
Kalman* kalman = cvCreateKalman( stateNum, measureNum, 0 );//state(x,y,detaX,detaY)


转移矩阵或者说增益矩阵的值好像有点莫名其妙

float A[stateNum][stateNum] ={//transition matrix
		1,0,1,0,
		0,1,0,1,
		0,0,1,0,
		0,0,0,1
	};

看下图就清楚了

kalman 滤波 演示与opencv代码_第1张图片

X1=X+dx,依次类推
所以这个矩阵还是很容易却确定的,可以根据自己的实际情况定制转移矩阵

同样的方法,三维坐标的转移矩阵可以如下

#include <cv.h>
#include <cxcore.h>
#include <highgui.h>

#include <cmath>
#include <vector>
#include <iostream>
using namespace std;

const int winHeight=600;
const int winWidth=800;


CvPoint mousePosition=cvPoint(winWidth>>1,winHeight>>1);

//mouse event callback
void mouseEvent(int event, int x, int y, int flags, void *param )
{
 if (event==CV_EVENT_MOUSEMOVE) {
  mousePosition=cvPoint(x,y);
 }
}

int main (void)
{
 //1.kalman filter setup
 const int stateNum=4;
 const int measureNum=2;
 CvKalman* kalman = cvCreateKalman( stateNum, measureNum, 0 );//state(x,y,detaX,detaY)
 CvMat* process_noise = cvCreateMat( stateNum, 1, CV_32FC1 );
 CvMat* measurement = cvCreateMat( measureNum, 1, CV_32FC1 );//measurement(x,y)
 CvRNG rng = cvRNG(-1);
 float A[stateNum][stateNum] ={//transition matrix
  1,0,1,0,
  0,1,0,1,
  0,0,1,0,
  0,0,0,1
 };

 memcpy( kalman->transition_matrix->data.fl,A,sizeof(A));
 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));
 //initialize post state of kalman filter at random
 cvRandArr(&rng,kalman->state_post,CV_RAND_UNI,cvRealScalar(0),cvRealScalar(winHeight>winWidth?winWidth:winHeight));

 CvFont font;
 cvInitFont(&font,CV_FONT_HERSHEY_SCRIPT_COMPLEX,1,1);

 cvNamedWindow("kalman");
 cvSetMouseCallback("kalman",mouseEvent);
 IplImage* img=cvCreateImage(cvSize(winWidth,winHeight),8,3);
 while (1){
  //2.kalman prediction
  const CvMat* prediction=cvKalmanPredict(kalman,0);
  CvPoint predict_pt=cvPoint((int)prediction->data.fl[0],(int)prediction->data.fl[1]);

  //3.update measurement
  measurement->data.fl[0]=(float)mousePosition.x;
  measurement->data.fl[1]=(float)mousePosition.y;

  //4.update
  cvKalmanCorrect( kalman, measurement );  

  //draw 
  cvSet(img,cvScalar(255,255,255,0));
  cvCircle(img,predict_pt,5,CV_RGB(0,255,0),3);//predicted point with green
  cvCircle(img,mousePosition,5,CV_RGB(255,0,0),3);//current position with red
  char buf[256];
  sprintf_s(buf,256,"predicted position:(%3d,%3d)",predict_pt.x,predict_pt.y);
  cvPutText(img,buf,cvPoint(10,30),&font,CV_RGB(0,0,0));
  sprintf_s(buf,256,"current position :(%3d,%3d)",mousePosition.x,mousePosition.y);
  cvPutText(img,buf,cvPoint(10,60),&font,CV_RGB(0,0,0));
  
  cvShowImage("kalman", img);
  int key=cvWaitKey(3);
  if (key==27){//esc   
   break;   
  }
 }      

 cvReleaseImage(&img);
 cvReleaseKalman(&kalman);
 return 0;
}

kalman filter 视频演示:

http://v.youku.com/v_show/id_XMjU4MzEyODky.html

 

demo snapshot:

kalman 滤波 演示与opencv代码_第2张图片



 

你可能感兴趣的:(kalman)