惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Attack and Defense Labs
Attack and Defense Labs
O
OpenAI News
AI
AI
Cloudbric
Cloudbric
Security Archives - TechRepublic
Security Archives - TechRepublic
H
Heimdal Security Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Recent Commits to openclaw:main
Recent Commits to openclaw:main
T
Threat Research - Cisco Blogs
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
腾讯CDC
S
SegmentFault 最新的问题
宝玉的分享
宝玉的分享
Cyberwarzone
Cyberwarzone
博客园 - 【当耐特】
TaoSecurity Blog
TaoSecurity Blog
The Cloudflare Blog
V
Visual Studio Blog
Forbes - Security
Forbes - Security
Apple Machine Learning Research
Apple Machine Learning Research
Spread Privacy
Spread Privacy
L
LINUX DO - 最新话题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
K
Kaspersky official blog
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
The Last Watchdog
The Last Watchdog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园_首页
Cisco Talos Blog
Cisco Talos Blog
Security Latest
Security Latest
量子位
W
WeLiveSecurity
V
V2EX
L
Lohrmann on Cybersecurity
S
Security @ Cisco Blogs
小众软件
小众软件
The Hacker News
The Hacker News
阮一峰的网络日志
阮一峰的网络日志
H
Hacker News: Front Page
博客园 - 聂微东
T
Troy Hunt's Blog
S
Schneier on Security
有赞技术团队
有赞技术团队
爱范儿
爱范儿
博客园 - 三生石上(FineUI控件)
Webroot Blog
Webroot Blog
P
Privacy International News Feed
Jina AI
Jina AI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com

Posts on Changkun's Blog

Why High-Output Systems Are Often the First to Stop Growing Dark Forest Theory: A Formal Derivation Agents (or Humans) in Goal-Directed and Goalless Environments: On Pipelines, Priors, and the Rhythm Between Exploration and Exploitation At the Boundary of Self-Reference: From Stable Structures in Artificial Intelligence to the Self as a Recursive Model in an Open Dissipative System 2023 Reading List 2022 Reading List 2021 Reading List Are PSS/USS and RSS Actually the Same Thing? Performance Differences from Page Faults vs. Prefetching 2020 Year-End Review Migration with Zero Downtime 2020 Reading List The All in Go Stack Pointers Might Not Be Ideal for Parameters Eliminating A Source of Measurement Errors in Benchmarks Setup Wordpress in 10 Minutes 我为什么不再写博客了? 2019 年终总结 2018-2019 读书清单 Ten years of blogging Rethinking the Reflections on Communications and Trusts 2018 年终总结 Go source code study is open source Go source study: unsafe Pattern Go source study: sync.Pool Go runtime programming A Million WebSocket and Go Designing Asynchronous RESTful APIs 分布式杂谈01:CAP 理论的误解 Issues of Human-Bot Interaction 压缩法与深度网络的泛化性 Go in 1 Hour UMSLT04: The Past and Present of SGD UMSLT03: A Gentle Start of Learning Theory UMSLT02: A Breif History of Neural Networks UMSLT01: A Breif History of Regularization 不笑不足以为道 论文笔记:Generalization in Deep Learning 2017 年终总结 2017 读书清单 深度学习的泛化理论简介 删除 GitHub 上已经提交的敏感信息 硕士生涯的第一年就这样告一段落了 人肉计算(10): 系统参与激励 人肉计算(9): 陷阱的解法 别聊,一聊你就暴露 人肉计算(8): 人肉计算与数据科学中的陷阱 人肉计算(7): 社会行为分析 Hexo + GitHub + Travis CI + VPS 自动部署 人肉计算(6): 预测市场 人肉计算(5): 信用风险评级模型 读书与回报 瞎扯: 对现代企业理论与当下IT企业的商业模式和信息产业链的规律性的思考 人肉计算(4): 输入数据聚合与PageRank 又一次打整了一下博客 人肉计算(3): 输入数据聚合与链路预测 人肉计算(2): 意图博弈 GWAPs 人肉计算(1): 众包与群众智慧 对后辈同学在计算机专业上的答疑与解惑 在德国的医疗及住院体验 这可能不是一个技术博客了 实验楼楼赛第3期-Python-题解 迅速更换了 DISQUS Electron 深度实践总结 良好的编码体验的三个方面 2016 年终总结 2016 读书清单 最近在着手写的文章 微信小程序文档极致总结 谈谈过去三个月在实验楼的实习经历 Built a Desktop Client for My Blog Guacamole 源码分析与 VNC 中 RFB 协议的坑 《高速上手 C++11/14》正式发布 Docker 极速入门教程02 - 镜像与容器管理 Docker 极速入门教程01 - 基本概念和操作 阶段性沉默 ELK+Redis 最佳实践 终于全面启用了 HTTPS 苹果开源了LZFSE无损压缩 Hash 碰撞的一种思路 记一次完整的 Kaldi-TIMIT 示例运行 Kaldi 上的 TIMIT 例子 Kaldi 安装与部署 从科研写作谈起 Swift API 设计指南 有趣的人类 所以其实论文并没有什么鬼用 Githug 通关记录及指南 小结一下这学期的收获 2015 读书清单 2015 年终总结 负能量爆表 转眼就快两个月了 博客迁移记录 大三总结 这个世界,终究不会是我们的。 Linux 内核分析 之六:Linux 内核创建进程的过程 小说「泽缘」 Linux 内核分析 之五:system_call中断处理过程的简要分析 大创项目的标题真是每年都在考验同学们的想象力啊
Kalman滤波器数学原理与应用
Changkun Ou · 2013-08-29 · via Posts on Changkun's Blog

Published at发布于:   |   PV/UV: /   |   Reading阅读: 3 min

前段时间做Tracking,了解到Kalman滤波,感觉很不错。wikipedia上内容有点多,整理过后发现只有五个核心公式。

原理

Kalman滤波器不断把协方差递归,估算出最优值,并且保留了上一时刻的协方差(Kalman增益),因此它的运行很快,可以随不同的时刻而改变他的值。 首先,我们要引入一个离散控制过程系统,该系统可以用一个线性随机微分方程来描述:

$$ \begin{equation} X(k)=AX(k-1)+BU(k)+W(k) \end{equation} $$

加上系统的测量值:

$$ \begin{equation} Z(k)=HX(k)+V(k) \end{equation} $$

上面式子中,$X(k)$是$k$时刻的系统状态,$U(k)$是$k$时刻对系统的控制量。$AB$是系统参数,对于多模型系统,他们为矩阵。$Z(k)$是$k$时刻的测量值,$H$是测量系统的参数,对于多测量系统,$H$为矩阵。

$W(k)$和$V(k)$分别表示过程和测量的噪声。他们被假设成高斯白噪声他们的协方差分别为$Q$,$R$(假设不随系统状态变化而变化)。 对于满足上面条件(线性随机微分系统,过程和测量都是高斯白噪声),Kalman滤波器是最优的信息处理器。下面则用其自身和自身的协方差来估计系统的最优化输出。 首先,要利用系统的过程模型,来预测下一状态的系统。假设现在的系统状态是k,根据系统的模型,可以基于系统上一状态而预测出现在状态:

$$ \begin{equation} X(k|k-1)=AX(k-1|k-1)+BU(k) \end{equation} $$

上式中,$X(k|k-1)$是利用上一状态预测的结果,$X(k-1|k-1)$是上一状态最优的结果,$U(k)$为现在状态的控制量,如果没有控制量,它可以为0。 至此,系统结果已经更新,但对于$X(k|k-1)$的协方差还未更新,用$Cov$表示协方差则:

$$ \begin{equation} Cov(k|k-1)=ACov(k-1|k-1)A^{T}+Q \end{equation} $$

上式中,$Cov(k|k-1)$是$X(k|k-1)$对应的协方差,$Cov(k-1|k-1)$是$X(k-1|k-1)$对应的协方差,$A^{T}$表示$A$的转置,$Q$是系统过程的协方差。上面两个式子为对系统的预测。 当有了现在状态的预测结果,我们再收集现在状态的预测值。结合预测值和测量值,我们可以得到现在状态$k$的最优化估计值$X(k|k)$:

$$ \begin{equation} X(k|k)=X(k|k-1)+K_{g}(k)(Z(k)-HX(k|k-1)) \end{equation} $$

其中,$K_{g}$为Kalman增益:

$$ \begin{equation} K_{g}=Cov(k|k-1)H^{T}(HCov(k|k-1)H^{T}+R(k))^{-1} \end{equation} $$

于此,已经得到了k状态下的最优估算值$X(k|k)$。但是为了要另Kalman滤波器不断的运行下去直到系统过程结束,我们还要更新k状态下$X(k|k)$的协方差:

$$ \begin{equation} Cov(k|k)=(E-K_{g}H)Cov(k|k-1) \end{equation} $$

其中,$E$为单位矩阵。当系统进入$k+1$状态时,$Cov(k|k)$就是第二个公式的,因此,可以自回归下去。

应用

Kalman滤波器作为一个很好的预测模型,可以根据现有情况来预测未来情况,在做Tracking中则变得很有用处。对于一个对象$S$的Tracking,$S$的pos在域中漂移,利用Tracking可以使得pos平滑稳定。 在OpenCV中提供了CvKalman结构,但是使用起来仍然需要建立模型,前几天我根据上述原理对整个过程进行了封装:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//
//  CvKalmanPoint.h
//  Renovation
//
//  Version History: 
//		Created by 欧 长坤 on 2013-08-17 
//
//  Description:
//		//2013-08-17
//		创建CvKalmanPoint对象并使用
//		cvKalmanPositionPrediction方法来返回Kalman滤波预测点。
//  
//  Copyright (c) 2013年 欧 长坤. All rights reserved.
//
//
#ifndef CVKALMANPOINT_H__
#define CVKALMANPOINT_H__

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

class CvKalmanPoint
{
public:

	// 参数
	int stateNum;
	int measureNum;

	// 屏幕分辨率
	int windowHeight;
	int windowWidth;

	CvKalman* kalman;
	CvMat* process_noise;
	CvMat* measurement;
	CvRNG rng;

	// 鼠标坐标
	CvPoint mousePosition;

	// 初始化
	CvKalmanPoint(void);
	~CvKalmanPoint(void);

	// 预测卡尔曼点
	CvPoint cvKalmanPositionPrediction(void);

};

#endif

下面则是构造函数和cvKalmanPositionPrediction方法的具体实现:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include "CvKalmanPoint.h"
#include <windows.h>
#include <winuser.h>

CvKalmanPoint::CvKalmanPoint(void)
{

	windowWidth  = GetSystemMetrics(SM_CXSCREEN);
	windowHeight = GetSystemMetrics(SM_CYSCREEN); 

	stateNum  	  = 4;		// 状态数,包括(x,y,dx,dy)坐标及速度(每次移动的距离)
	measureNum	  = 2;		// 实际量,能看到的是坐标值,当然也可以自己计算速度,但是没有必要。 
	kalman	 	  = cvCreateKalman( stateNum, measureNum, 0 );	// state(x,y,detaX,detaY)  
	process_noise = cvCreateMat( stateNum, 1, CV_32FC1 );
	measurement	  = cvCreateMat( measureNum, 1, CV_32FC1 );		// measurement(x,y) 
	rng			  = cvRNG(-1);	// 64位长整数种子,初始化rng

	/*
		// 变换矩阵
		┌ x'┐  ┌1 0 1 0┐┌ x┐
		│ y'│= │0 1 0 1││ y│
		│dx'│  │0 0 1 0││dx│
		└dy'┘  └0 0 0 1┘└dy┘
		==> x'  = x + dx
		==> y'  = y + dy
		==> dx' = dx
		==> dy' = dy
	*/
	// 4 == stateNum
	float transformMatrix[4][4] = {  
		1,0,1,0,  
		0,1,0,1,  
		0,0,1,0,  
		0,0,0,1  
	};

	memcpy( 
		kalman->transition_matrix->data.fl, 
		transformMatrix, 
		sizeof(transformMatrix) 
	);

	// 把数组中除了行数与列数相等以外的所有元素的值都设置为0,行数与列数相等的元素的值都设置为1
	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)
	);

	// 初始化后的随机态卡尔曼滤波 
	cvRandArr(
		&amp;rng,
		kalman->state_post,
		CV_RAND_UNI,
		cvRealScalar(0),
		cvRealScalar(windowHeight>windowWidth?windowWidth:windowHeight)
	);
}
CvKalmanPoint::~CvKalmanPoint(void)
{

}

CvPoint CvKalmanPoint::cvKalmanPositionPrediction(void)
{
	// 卡尔曼预测
    const CvMat* prediction = cvKalmanPredict(kalman,0);  
    CvPoint predict_pt=cvPoint((int)prediction->data.fl[0],(int)prediction->data.fl[1]);  

    // 测量校准  
    measurement->data.fl[0] = (float)mousePosition.x;  
    measurement->data.fl[1] = (float)mousePosition.y;  

    // 更新  
    cvKalmanCorrect(kalman, measurement);       

	//printf("预测位置:(%d,%d)\n",predict_pt.x,predict_pt.y);
	//printf("实际位置:(%d,%d)\n",mousePosition.x,mousePosition.y);

	return predict_pt;
}

使用方法:

1
2
3
4
5
6
CvPoint measure;
……
CvKalmanPoint kalman_point;
kalman_point.mousePosition.x = measure.x;
kalman_point.mousePosition.y = measure.y;
measure = kalman_point.cvKalmanPositionPrediction();