opencv 卡尔曼滤波器例子,自己修改过

一、卡尔曼滤波器的理论解释

http://blog.csdn.net/lindazhou2005/article/details/1534234(推荐)

二、代码中一些随机数设置函数,在opencv中文网站上没有查到:

cvRandInit()

初始化CvRandState数据结构,可以选定随机分布的种类,并给定它种子,有两种情形

cvRandInit(CvRandState数据结构,随机上界,随机下界,均匀分布参数,64bits种子的数字)

cvRandInit(CvRandState数据结构,平均数,标准偏差,常态分布参数,64bits种子的数字)

cvRandSetRange()

修改CvRandState数据结构的参数内容,均匀分布的话可以每个信道的上下界常态分布可以修改每个通道的平均数,标准偏差.

cvRandSetRange(CvRandState数据结构,均匀分布上界,均匀分布下界,目标信道数据)

cvRandSetRange(CvRandState数据结构,常态分布平均数,常态分布标准偏差,目标信道数据)

cvRand()

将CvMat或IplImage数据结构随机化,用被设定过的CvRandState数据结构来随机.

cvRand(CvRandState数据结构,CvMat或IplImage数据结构)

cvbRand()

将一维数组随机化,可以设定随机的长度

cvbRand(RandState数据结构,Float型别数组名,随机的长度);

http://blog.csdn.net/jiangdf/article/details/4553520

#define cvMatMulAdd( src1, src2, src3, dst ) cvGEMM( src1, src2, 1, src3, 1, dst, 0 )

三、

1、情景说明:

假设有一个做圆周运动的点,就像一辆在赛道上行驶的汽车,汽车以恒定的速度行驶。使用kalman滤波器跟踪这个汽车。程序运行结果,红圈代表理想运动汽车,,黄圈代表kalman滤波器预测汽车的位置,白圈代表观测得到汽车的位置,蓝圈代表kalman滤波器获得汽车的位置(速度这一分量,可以观察图中圆的运动速度)。

2、代码:

#include <cv.h>
#include <highgui.h>
#include <stdio.h>
int main (int argc,int ** argv)
{
 // Initialize Kalman filter object, window, number generator, etc
 cvNamedWindow( "Kalman", 1 );//创建窗口,当为的时候,表示窗口大小自动设定
 CvRandState rng;
 //cvRandInit( &rng, 0, 1, -1, CV_RAND_UNI );/* CV_RAND_UNI 指定为均匀分布类型、随机数种子为-1 *///怎么接下来又改为高斯分布
 cvRandInit(&rng,0,0.1,-1,CV_RAND_NORMAL);//自己添加,原函数中先设为均匀分布再改回,觉得没有必要
 IplImage* img = cvCreateImage( cvSize(500,500), 8, 3 );
 CvKalman* kalman = cvCreateKalman( 2, 1, 0 );/*状态向量为2维,观测向量为1维,无激励输入维*/
 // State is phi, delta_phi - angle and angular velocity
 // Initialize with random guess
 CvMat* x_k = cvCreateMat( 2, 1, CV_32FC1 );/*创建行列、元素类型为CV_32FC1,元素为位单通道浮点类型矩阵。*/
 //cvRandSetRange( &rng, 0, 0.1, 0 );/*设置随机数范围,随机数服从正态分布,均值为,均方差为.1,通道个数为*/
 //rng.disttype = CV_RAND_NORMAL;
 //cvRand( &rng, x_k ); /*随机填充数组*/
 x_k->data.fl[0]=0.;//设起始角度为0;//自己修改过的例子中x_k为汽车沿圆周运动的参数,去掉了噪声,在后面与kalman
//滤波器校正后的运动参数对比
 x_k->data.fl[1]=0.05f;//设角速度为1,弧度值
 // 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 }; /*状态转移矩阵*///F 矩阵实际上应该是2*2的矩阵[1,1;0,1]
 memcpy( kalman->transition_matrix->data.fl, F, sizeof(F));
 /*初始化转移矩阵,行列,具体见CvKalman* kalman = cvCreateKalman( 2, 1, 0 );*/
 // Initialize other Kalman parameters
 cvSetIdentity( kalman->measurement_matrix, cvRealScalar(1) );/*观测矩阵*///观测矩阵也是1*2 [1,0],因为只能测得汽车的位置
 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 );//此时的z_k并非测量值,只是为观测噪声,其实为理解方便应该设一的独立的变量
  cvMatMulAdd( kalman->measurement_matrix, x_k, z_k, z_k );//z_k为测量值
  // Update 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 );//
  // Plot Points
  cvZero( img );/*创建图像*/
  // Yellow is observed state 黄色是观测值
  //cvCircle(IntPtr, Point, Int32, MCvScalar, Int32, LINE_TYPE, Int32)
  //对应于下列其中,shift为数据精度
  //cvCircle(img, center, radius, color, thickness, lineType, shift)
  //绘制或填充一个给定圆心和半径的圆
  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 );
  CvScalar bule=cvScalar(255,0,0,0);
  cvCircle( img,
   cvPoint( cvRound(img->width/2 + img->width/3*cos(kalman->state_post->data.fl[0])),
   cvRound( img->height/2 - img->width/3*sin(kalman->state_post->data.fl[0])) ),
   4, bule ,2);
  // 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, NULL, x_k );//
  CvFont font;
  cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX,0.5f,0.5f,0,1,8);
  cvPutText(img,"Yellow:observe",cvPoint(0,20),&font,cvScalar(0,0,255));
  cvPutText(img,"While:predict",cvPoint(0,40),&font,cvScalar(0,0,255));
  cvPutText(img,"Red:real",cvPoint(0,60),&font,cvScalar(0,0,255));
  cvPutText(img,"Press Esc to Exit...",cvPoint(0,80),&font,cvScalar(255,255,255));
  cvShowImage( "Kalman", img );
  // Exit on esc key
  if(cvWaitKey(100) == 27)
   break;
 }
 cvReleaseImage(&img);/*释放图像*/
 cvReleaseKalman(&kalman);/*释放kalman滤波对象*/
 cvDestroyAllWindows();/*释放所有窗口*/
}

3、平台:opencv2.1 vs2008

4、实验结果:

5、分析

实验中有两个现象

一开始汽车的真实位置和卡尔曼滤波器得到的结果差别比较大。因为汽车一开始的位置为0,而给卡尔曼的滤波器设置的最初状态时一个高斯分布的随机值。但越到后来,汽车的真实位置和卡尔曼滤波器得到的结果差别变小;

蓝圈位置和白圈位置更接近,而黄圈和蓝圈的位置总是差别较大。因为过程协方差为1e-1,而观测协方差为1e-5(蓝色部分代码),所以卡尔曼滤波器得到的结果和观测结果更接近,即蓝圈位置和白圈位置更接近。如果改变过程协方差的大小会出现不同的结果。

opencv 卡尔曼滤波器例子,自己修改过

时间: 2024-10-25 07:28:50

opencv 卡尔曼滤波器例子,自己修改过的相关文章

对Kalman(卡尔曼)滤波器的理解

1.简介(Brief Introduction) 在学习卡尔曼滤波器之前,首先看看为什么叫"卡尔曼".跟其他著名的理论(例如傅立叶变换,泰勒级数等等)一样,卡尔曼也是一个人的名字,而跟他们不同的是,他是个现代人! 卡尔曼全名Rudolf Emil Kalman,匈牙利数学家,1930年出生于匈牙利首都布达佩斯.1953,1954年于麻省理工学院分别获得电机工程学士及硕士学位.1957年于哥伦比亚大学获得博士学位.我们现在要学习的卡尔曼滤波器,正是源于他的博士论文和1960年发表的论文&

卡尔曼滤波器 Kalman Filter (转载)

在学习卡尔曼滤波器之前,首先看看为什么叫“卡尔曼”.跟其他著名的理论(例如傅立叶变换,泰勒级数等等)一样,卡尔曼也是一个人的名字,而跟他们不同的是,他是个现代人! 卡 尔曼全名Rudolf Emil Kalman,匈牙利数学家,1930年出生于匈牙利首都布达佩斯.1953,1954年于麻省理工学院分别获得电机工程学士及硕士学位.1957年于哥 伦比亚大学获得博士学位.我们现在要学习的卡尔曼滤波器,正是源于他的博士论文和1960年发表的论文<A New Approach to Linear Fil

卡尔曼滤波器算法浅析及matlab实战

卡尔曼滤波器是一种利用线性系统状态方程,通过系统输入输出观测数据,对系统状态进行最优估计的算法.而且由于观测包含系统的噪声和干扰的影响,所以最优估计也可看做是滤波过程. 卡尔曼滤波器的核心内容就是5条公式,计算简单快速,适合用于少量数据的预测和估计. 下面我们用一个例子来说明一下卡尔曼算法的应用. 假设我们想在有一辆小车,在 t 时刻其速度为 Vt ,位置坐标为 Pt,ut 表示 t 时刻的加速度,那么我们可以用Xt表示 t 时刻的状态,如下: 则我们可以得到,由t-1 时刻到 t 时刻,位置以

卡尔曼滤波器原理之基本思想续

在上一篇文章卡尔曼滤波器原理之基本思想中,我们分析并推导了基于卡尔曼一步预测的滤波器状态递推公式,接下来,我们将完成上一次的推导过程.首先,我们拿来上次的推导结果: \[\hat x(n + 1|{{\bf{Y}}_n}) = \sum\limits_{k = 1}^{n - 1} {E[x(n + 1){\alpha ^H}(k)]{{\bf{R}}^{ - 1}}(k)\alpha (k)}  + E[x(n + 1){\alpha ^H}(k)]{{\bf{R}}^{ - 1}}(k)\a

卡尔曼滤波器原理之基本思想

一.卡尔曼滤波器要解决的问题 首先说一下卡尔曼滤波器要解决的是哪一类问题,这类系统应该如何建模.这里说的是线性卡尔曼滤波器,顾名思意,那就是线性动态的离散系统.这类系统可以用如下两个方程来表示: \[\begin{array}{l} x(n + 1) = F(n + 1,n)x(n) + {v_1}(n) \\  y(n) = C(n)x(n) + {v_2}(n) \\  \end{array}\] 其中: x(n)表示系统的状态 F(n+1,n)为状态转移矩阵,表示状态随时间的变化规律.通俗

卡尔曼滤波器:用R语言中的KFAS建模时间序列

于时间序列预测,ARIMA等传统模型通常是一种流行的选择.虽然这些模型可以证明具有高度的准确性,但它们有一个主要缺点 - 它们通常不会解释“冲击”或时间序列的突然变化.让我们看看我们如何使用称为卡尔曼滤波器的模型来潜在地缓解这个问题. 时间序列  我们以货币市场为例.货币对可能会有整体上升趋势,然后在抛售期间大幅下跌.传统的时间序列模型不一定能够立即解决这个问题,并且在考虑到趋势的突然变化之前可能需要几个时期. 因此,我们希望使用一个确实能够解释这种冲击的时间序列模型.让我们来看一个称为卡尔曼滤

卡尔曼滤波器

卡尔曼的历史不讲了... 网上写卡尔曼滤波器的太多了...而且大(yi)多(mu)雷(yi)同(yang),所以,我也不知道谁是第一稿,谁是转载者,这里...我也是参考别人的博文.将卡尔曼滤波器用在了一个GPS的小程序里,最简单的一维模型... 首先,我们先要引入一个离散控制过程的系统.该系统可用一个线性随机微分方程(Linear Stochastic Difference equation)来描述: X(k)=A*X(k-1)+B*U(k)+W(k) 再加上系统的测量值: Z(k)=H*X(k

卡尔曼滤波器的简单推导

本文将简单推导卡尔曼滤波器的预测和更新公式.为了简单,使用标量(一维向量)而不是向量,并且假设系统没有输入. 系统状态的理论值如下: $x_k=\Phi_k x_{k-1}+w_k$ 但是由于过程噪声和观测噪声的存在,系统状态的真实值是不可知的.但我们仍可以根据以下思路,尽量跟踪真实值: 1) 状态转换系数是已知的,因此我们可以根据上一状态得到当前状态的先验估计: $\hat{x}_k^-=\Phi_k \hat{x}_{k-1}$ 2) 将对当前状态的先验估计$\hat{x}_k^-$变换到对

测试卡尔曼滤波器(Kalman Filter)

真实的温度测试数据,通过加热棒加热一盆水测得的真实数据,X轴是时间秒,Y轴是温度: 1)滤波前 2)滤波后(p=10, q=0.0001, r=0.05, kGain=0;) 2)滤波后(p=10, q=0.00001, r=1, kGain=0;),Y轴放大10倍并取整 .   相关C语言代码: #define LINE 1024 static float prevData=0; static float p=10, q=0.0001, r=0.05, kGain=0; float kalma