学习参考:

卡尔曼滤波器的原理以及在matlab中的实现

Opencv实现Kalman滤波器

opencv中的KF源码分析

Opencv-kalman-filter-mouse-tracking

理解:

假设:一个小车距离左侧某一物体k时刻的真实位置状态

,而位置状态观测值为
,则小车的线性动态系统可表示为:

位置状态的系统预测值:

位置状态的观测值:

其中F为系统状态转移矩阵,B为控制输入矩阵,H为系统状态观测矩阵,

为系统预测过程中的噪声(其均值为0,协方差为Q),
为系统测量过程中的噪声(其均值为0,协防方差为R).

则卡拉曼滤波的思想就是利用Kalaman增益修正预测值

使其逼近真实值
来计算最优估计值

Kalaman步骤:

  1. 通过上一时刻的估计值预测当前状态的估计值

  2. 计算先验误差估计协方差矩阵
  3. 计算此时卡尔曼增益
  4. 更新估计值
  5. 计算后验误差估计协方差
  6. ,循环1-5。

Kalaman优点:

  • 时域滤波器,不需变换到频域设计
  • 一种递归估计,不需要记录历史观测值和估计值

Kalaman的实现:

  • kalaman.hpp
namespace cv{class CV_EXPORTS_W KalmanFilter
{public://缺省构造函数:无论构造函数是自动生成的还是用户定义的,它都是可以调用的构造函数,无需提供任何参数。CV_WRAP KalmanFilter();//完整构造函数CV_WRAP KalmanFilter(int dynamparams,int measureparamsint, int controlParams=0, int type=CV_32F);  //dynamparams:状态维度//measureparamsint:观测维度//controlParams:控制维度void init(int dynamParams, int measureParams, int controlParams=0, int type=CV_32F);//计算预测状态CV_WRAP const Mat& predict(const Mat& control=Mat());  //依据观测值更新预测状态 CV_WRAP const Mat& correct(const Mat& measurement);  Mat statePre;           //!< 预测状态 (x'(k)): x(k)=A*x(k-1)+B*u(k)  Mat statePost;          //!< 纠正状态 (x(k)): x(k)=x'(k)+K(k)*(z(k)-H*x'(k))  Mat transitionMatrix;   //!< 状态转换矩阵 (F)  Mat controlMatrix;      //!< 控制矩阵(B) (not used if there is no control)  Mat measurementMatrix;  //!< 观测矩阵(H)  Mat processNoiseCov;    //!< 处理过程噪声协方差矩阵 (Q)  Mat measurementNoiseCov;//!< 观测噪声协方差矩阵 (R)  Mat errorCovPre;        //!< 先验误差估计协方差矩阵 (P'(k)): P'(k)=A*P(k-1)*At + Q)*/  Mat gain;               //!< 卡尔曼增益矩阵 (K(k)): K(k)=P'(k)*Ht*inv(H*P'(k)*Ht+R)  Mat errorCovPost;       //!< 后验误差估计协方差矩阵 (P(k)): P(k)=(I-K(k)*H)*P'(k)  // temporary matrices  Mat temp1;  Mat temp2;  Mat temp3;  Mat temp4;  Mat temp5;
};
}

  • kalaman类的实现
namespace cv
{KalmanFilter::KalmanFilter() {}//dynamparams:状态维度//measureparamsint:观测维度//controlParams:控制维度
KalmanFilter::KalmanFilter(int dynamParams, int measureParams, int controlParams, int type)
{init(dynamParams, measureParams, controlParams, type);
}void KalmanFilter::init(int DP, int MP, int CP, int type)
{CV_Assert( DP > 0 && MP > 0 );CV_Assert( type == CV_32F || type == CV_64F );CP = std::max(CP, 0);statePre = Mat::zeros(DP, 1, type);//状态向量维度DP X 1statePost = Mat::zeros(DP, 1, type);transitionMatrix = Mat::eye(DP, DP, type);// 状态转移矩阵F的大小为DP X DPprocessNoiseCov = Mat::eye(DP, DP, type);// 处理过程噪声协方差矩阵Q的大小为DP X DPmeasurementMatrix = Mat::zeros(MP, DP, type);//观测矩阵H的大小为MP X DPmeasurementNoiseCov = Mat::eye(MP, MP, type);// 观测噪声协方差矩阵R大小为MP X MPerrorCovPre = Mat::zeros(DP, DP, type); // 先验误差估计协方差矩阵P'大小为DP X DPerrorCovPost = Mat::zeros(DP, DP, type);// 后验误差估计协方差矩阵P大小为DP X DPgain = Mat::zeros(DP, MP, type); // 卡尔曼增益矩阵if( CP > 0 )controlMatrix = Mat::zeros(DP, CP, type);// 控制矩阵BelsecontrolMatrix.release();temp1.create(DP, DP, type);temp2.create(MP, DP, type);temp3.create(MP, MP, type);temp4.create(MP, DP, type);temp5.create(MP, 1, type);
}const Mat& KalmanFilter::predict(const Mat& control)
{// 更新预测状态 e: x'(k) = F*x(k)statePre = transitionMatrix*statePost;//判断是否添加控制,是否添加控制矩阵影响更新的预测状态if( !control.empty() )// x'(k) = x'(k) + B*u(k)statePre += controlMatrix*control;// temp1 = F*P(k)temp1 = transitionMatrix*errorCovPost;// 更新先验误差估计协方差矩阵P'(k) = temp1*F_T + Q// gemm(a,b,n,c,m,ans,flags): ans = n*a*b+m*c// flags=GEMM_2_T:b transposesgemm(temp1, transitionMatrix, 1, processNoiseCov, 1, errorCovPre, GEMM_2_T);// handle the case when there will be measurement before the next predict.//a.copyTo(b):得到与a一样的b,两者可进行互不相关的操作。statePre.copyTo(statePost);errorCovPre.copyTo(errorCovPost);return statePre;
}const Mat& KalmanFilter::correct(const Mat& measurement)
{// K(k) = p'(k)*H_T*inv(H*p'(k)*H_T+R)// temp2 = F*P'(k)temp2 = measurementMatrix * errorCovPre;// temp3 = temp2*H_T + Rgemm(temp2, measurementMatrix, 1, measurementNoiseCov, 1, temp3, GEMM_2_T);//// solve(MA,MB,MX,CV_LU) 可以求AX=B for X 等价于X=A-1 *B// temp4 = inv(temp3)*temp2 = K(k)_Tsolve(temp3, temp2, temp4, DECOMP_SVD);// K(k)// 转置过来得到真正的Kgain = temp4.t();// temp5 = z(k) - H*x'(k)temp5 = measurement - measurementMatrix*statePre;// x(k) = x'(k) + K(k)*temp5statePost = statePre + gain*temp5;// P(k) = P'(k) - K(k)*temp2errorCovPost = errorCovPre - gain*temp2;return statePost;
}
}

  • demo.cpp
#include "opencv2/video/tracking.hpp"
#include <iostream>
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
void on_mouse(int e, int x, int y, int d, void *ptr)
{Point*p = (Point*)ptr;p->x = x;p->y = y;
}int main()
{// 初始化int stateSize = 4;  // [x, y, v_x, v_y]int measSize = 2;   // [z_x, z_y] int contrSize = 0;  // no control inputunsigned int F_type = CV_32F;//or CV_64FKalmanFilter KF(stateSize, measSize, contrSize, F_type);Mat state(stateSize, 1, F_type);  // [x, y, v_x, v_y] Mat meas(measSize, 1, F_type);    // [z_x, z_y] setIdentity(KF.transitionMatrix);setIdentity(KF.measurementMatrix);setIdentity(KF.processNoiseCov, Scalar::all(1e-4));setIdentity(KF.measurementNoiseCov, Scalar::all(1e-1));setIdentity(KF.errorCovPost, Scalar::all(.1));Mat display_image(600, 800, CV_8UC3);namedWindow("Mouse Kalman");char ch = 0;double ticks = 0;Point mousePos;vector<Point> mousev, kalmanv;while (ch != 'q' && ch != 'Q'){//预测state = KF.predict(); Point predictPt(state.at<float>(0), state.at<float>(1));// 鼠标观测setMouseCallback("Mouse Kalman", on_mouse, &mousePos);meas.at<float>(0) = mousePos.x;meas.at<float>(1) = mousePos.y;// >更新Mat estimated = KF.correct(meas);Point statePt(estimated.at<float>(0), estimated.at<float>(1));Point measPt(meas.at<float>(0), meas.at<float>(1));char mousep[20];sprintf(mousep, "(%0.2f,%0.2f)", meas.at<float>(0), meas.at<float>(1));putText(display_image, "mouse point:",Point(0,10), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 2,false );putText(display_image, mousep, Point(120,10), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 2,false);char prept[20];sprintf(prept, "(%0.2f,%0.2f)", state.at<float>(0), state.at<float>(1));putText(display_image, "pre point:",Point(0,50), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 2,false );putText(display_image, prept,Point(120,50), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 2,false );imshow("Mouse Kalman", display_image);display_image = Scalar::all(0);//push_back 将新元素移动拷贝到vector里mousev.push_back(measPt);kalmanv.push_back(statePt);//以点坐标画园circle(display_image,statePt,5,(255,0,0),1);circle(display_image,measPt,5,(0,0,255),1);//画出运动轨迹for (int i = 0; i < mousev.size() - 1; i++)line(display_image, mousev[i], mousev[i + 1], Scalar(0, 0, 255), 1);for (int i = 0; i < kalmanv.size() - 1; i++)line(display_image, kalmanv[i], kalmanv[i + 1], Scalar(255, 0, 0), 1);ch = cv::waitKey(10);}
}

卡尔曼滤波matlab_卡尔曼滤波(kalaman Filter)相关推荐

  1. 卡尔曼滤波-建立卡尔曼滤波直觉

    卡尔曼滤波-建立卡尔曼滤波直觉 概述 预测算法的必要性 数学知识 均值和期望值 方差和标准差 拓展一下(有偏估计和无偏估计) 高斯分布(正态分布) 随机变量 估计.准确度和精度 小结 α−β−γ 滤波 ...

  2. 卡尔曼滤波matlab_汽车毫米波雷达距离测量中的一种扩展卡尔曼滤波实现

    本文详细描述了卡尔曼滤波器在汽车毫米波距离测量应用中的工作原理,详细介绍了卡尔曼的工作原理,实际测量中的噪声来源,并在搭建好模型后运用MATLAB分析验证了模型的有效性. 毫米波雷达对待测目标进行间隔 ...

  3. 滤波算法_标准卡尔曼滤波(SKF, Standard Kalman filter)_①基础铺垫

    学习卡尔曼滤波不能一蹴而就,特别是对于基础薄弱者而言,需要一步一步来,在推导kalman滤波算法之前,需要学习一些基础知识作为铺垫. 1.递归算法 卡尔曼滤波,它本质上是一种最优的递归的数字处理算法. ...

  4. 【笔记】自适应卡尔曼滤波 Adaptive Extended Kalman Filter

    0 阅读文章 <Adaptive Adjustment of Noise Covariance in Kalman Filter for Dynamic State Estimation> ...

  5. 4.卡尔曼滤波之卡尔曼滤波的基本方程

    目录 一.卡尔曼滤波的基本方程 二.基本方程的使用要点 初值的选取 估值均方误差真阵的等价形式的选用 一步转移矩阵的计算 三.小结 一.卡尔曼滤波的基本方程 经过前面三篇文章的铺垫,我们可以开始说说卡 ...

  6. python多目标跟踪卡尔曼滤波_卡尔曼滤波+单目标追踪+python-opencv

    向面试官一句话解释卡尔曼滤波: 用上一次的最优状态估计和最优估计误差去计算这一次的先验状态估计和先验误差估计: 用1得到的本次先验误差估计和测量噪声,得到卡尔曼增益: 用1,2步骤得到所有先验误差估计 ...

  7. 【卡尔曼滤波】卡尔曼滤波在雷达目标跟踪中的应用仿真matlab源码

    1 模型 [摘要]目标跟踪问题的应用背景是雷达数据处理,即雷达在搜索到目标并记录目标的位置数据,对测量到的目标位置数据(称为点迹)进行处理,自动形成航迹,并对目标在下一时刻的位置进行预测.本文简要讨论 ...

  8. 【卡尔曼滤波】卡尔曼滤波简单实例

    文章目录 Part.I 问题&解决方案 Chap.I 解决方案 Chap.II 建模与分析 Part.II 简单实现 参考&引用 [1] 严老师捷联惯导课程视频:https://www ...

  9. java 二维卡尔曼滤波_卡尔曼滤波 – Kalman Filtering

    1.    什么是卡尔曼滤波器 (What is the Kalman Filter?) 在学习卡尔曼滤波器之前,首先看看为什么叫"卡尔曼".跟其他著名的理论(例如傅立叶变换,泰勒 ...

最新文章

  1. CentOS 6.2 yum安装配置lnmp服务器(Nginx+PHP+MySQL)
  2. Zookeeper (一)集群简单搭建
  3. 人类血液中首次发现微塑料颗粒,饮料瓶塑料袋化妆品都是来源
  4. mal是什么类型对应的java类型是什么,【Java】mysql的 int 类型,刨析返回类型为BigDicemal 类型的奇怪现象...
  5. HDU 6136 Death Podracing (堆)
  6. 中小型研发团队架构实践:集中式日志ELK
  7. linux 禁止账户远程登录
  8. 使用Hadoop自带的例子pi计算圆周率
  9. phpcmsV9 表单向导(案例一)应用示例
  10. 转换图片保持画质_图片格式怎么相互转换,如何转换jpg、 bmp、png格式
  11. 在Linux上使用logwatch分析监控日志文件
  12. java中String stringBuffer StringBuider
  13. Static 单例模式
  14. 算法:回溯十八 Factor Combinations 因子组合(3种解法)
  15. JAVA 二叉树面试题
  16. cad怎么查找未闭合_CAD应该怎么测量图形?未封闭、不规则的图形要这样测量
  17. LeetCode 707
  18. python量化交易策略实例_Python进阶量化交易:听说有个回测框架叫backtrader
  19. CSPS Oct目标
  20. 2,2,2,2-((ethene-1,1,2,2-tetrakis(benzene-4,1-diyl))tetrakis-(oxy)tetraacetic acid 2,2,2,2-四(乙烯基-苯氧

热门文章

  1. ArrayList遍历的同时删除
  2. Java IO最详解
  3. Python爬虫实战六之抓取爱问知识人问题并保存至数据库
  4. 如何设计一门语言(十一)——删减语言的功能
  5. 跟vczh看实例学编译原理——一:Tinymoe的设计哲学
  6. 人工智能:第八章 自动规划
  7. eclipse导出jar包
  8. 【OpenCV3】图像通道分离与合并——cv::split()与cv::merge()详解
  9. Windows 8 应用开发 - 应用栏
  10. CTO下午茶: 没有安全,一切创新都是套路