matlab 高斯迭代代码_KLT目标跟踪学习与代码实现

fb753e75b90e90653fb0fcba114430db.png

一、 前言

本篇文章链接:https://zhuanlan.zhihu.com/p/91341439

近年来研究跟踪的方法很多,各种算法几乎层出不齐,主要可将其分为两类目标跟踪算法,一类是传统的目标跟踪算法,一类是基于深度学习的跟踪方法,而基于传统的目标跟踪算法比较经典的有粒子滤波(pf)、Mean Shift目标跟踪算法以及KLT的跟踪算法又或者叫做Lucas光流法,这些方法各有优缺点:

粒子滤波(pf):能够比较好的在全局搜索到最优解,但其求解速度相对较慢,由于其是基于颜色直方图的计算,对颜色相近的物体不太能够区别开来。

Mean Shift算法:很容易陷入局部最优,但其跟踪的速度很快。

基于以上两种算法各自的优缺点,常常有人将Mean Shift和pf做结合,恰好在很多方面能够达到互补的效果。

二、 KLT跟踪算法

Kanade-Lucas-Tomasi方法,在跟踪方面表现的也不错,尤其在实时计算速度上,用它来得到的,是很多点的轨迹“trajectory”,并且还有一些发生了漂移的点,所以,得到跟踪点之后要进行一些后期的处理,说到Kanade-Lucas-Tomasi方法,首先要追溯到Kanade-Lucas两人在上世纪80年代发表的paper:An Iterative Image Registration Technique with an Application to Stereo Vision,这里讲的是一种图像点定位的方法,即图像的局部匹配,将图像匹配问题,从传统的滑动窗口搜索方法变为一个求解偏移量d的过程,后来Jianbo Shi和Carlo Tomasi两人发表了一篇CVPR(94')的文章Good Features To Track,这篇文章,主要就是讲,在求解d的过程中,哪些情况下可以保证一定能够得到d的解,这些情况的点有什么特点(后来会发现,很多时候都是寻找的角点)。

1、具体实现:

(1)几个前提假设:很直观的讲,如果判断一个视频的相邻两帧I、J在某局部窗口w上是一样的,则在窗口w内有:

1)亮度恒定:是为了保证其等号成立不受亮度的影响。这里也可以是从t-1时刻到t时刻,如下所示:

da688b78a915e4ec819e2e0f46368f30.png

亮度恒等式,时刻亮度与t时刻亮度相等:

2)时间连续或者是运动是“小运动”:为了保证KLT能够找到点
3)空间一致,临近点有相似运动,保持相邻:在同一个窗口中,所有点的偏移量都相等。

假设对像素点来说,周围的像素点都保持相同的移动距离假设窗口大小为

,则对于25个窗口内的像素点来说,就会如下等式成立:

bbba1120cda0694fb71efcd6624503f5.png

得到下面的过约束等式:

831b7f40ec0d08401a45548635ea6077.png

即:

采用最小二乘法求解d:

5b96254fad47683a465d0d71498af8b8.png

这样我们就得到了KLT光流等式与该窗口的Hessian矩阵:

a3084162eaf10ed959636d76c988f621.png

0d68d6eb9b300bd27f5b65a9dd58ce14.png

2、具体推导过程:

在窗口中,所有

都往一个方向移动了
,从而得到
,即t时刻的
点在
时刻为
,所以寻求匹配的问题可化为对以下的式子寻求最小值,或者叫做最小化以下式子:

e15383aed277246a9e70b59e3447e4c5.png

用积分来表示上述式子,以上式子可等效为:

c660d96c977fb06761fa91097560c395.png

这个式子的含义,即找到两幅图像中,在W窗口中,I,J的差异,这里的w(x)表示权重函数,一般我们可以采用高斯函数进行加权。其中I以

为中心,J以
为中心,
为半径的一个矩形窗口间的差异,结合微积分的知识,函数
要取得最小值,这个极值点的导数一定为0,即:

ba1c62d81a4707e5bb6dfd8da188f086.png

的值为0,由泰勒性质展开:

348217aed61444151af86e2bfeb6f19b.png

可以得到:

2f12df6ef637c1ce8fa2319c8d2c7f58.png

于是,问题转化为:

907f43521861d1029b4ceab00e71701b.png

其中:

02fe9757952e98c55ff8fb77a398a4d9.png

从而,问题即为:

9b7206d81ec0e01c70bdb42623c3a615.png

可将上面的等式看作为:

这里,Z为一个2x2的矩阵e为一个2x1的向量,

3c24d80278d551a47da1028d1afa4ed4.png

为了要使得d能够得到解,则Z需要满足

的矩阵可逆,其中
为Z的转置,而在一般情况下,恰好角点有这样的特点,由此我们可以进一步对KLT算法理解,KLT算法就是在给定的图像上遍历寻找出特征点,也就是角点,常用Harris角点,然后与被给定的目标模板,即跟踪目标的特征点对准之后计算增量平移的一个迭代计算,来实现跟踪,也可以认为是,图像配准之后计算仿射变换参数实现目标迭代跟踪。

3、KLT特征跟踪的主要步骤:

1) 用诸如Harris角点的特征检测器在初始帧中寻找一系列特征点;

2) 基于各特征点的局部模板,通过采用平移或仿射运动模型的Lucas-Kanade运动估计,寻找各特征点的帧间对应矢量。

3) 对于各特征点,在各帧中判断其跟踪的好坏。有些特征可以移除(比如去除掉那些被遮挡的或者无法准确跟踪的),可以周期性(如每隔5帧)加入一些新的特征。

三、 基于Opencv代码实现

代码参考:http://cecas.clemson.edu/~stb/klt/

对于下面两幅图像img0.pgm和img1.pgm:

62912f3ccedc1c6d2e318644eaa80652.png

40c1f37a100ae84c5ff4faf20add7516.png

检测Harris角点得到:

4672e4f9ea7a10166fe724157ecd36c3.png

KLT跟踪计算得到:

fd8f8db08b05ee99ba0937e915ae386a.png

7c5a5bb1e157166e55ef5d505810f81e.png

上面分别选取了100个特征点,计算了其所在的位置,最后有55个特征点成功被追踪到。

四、 基于Matlab的人脸检测与KLT特征跟踪

1、基于Matlab的官方自带的人脸检测的代码实列:

主要参考代码:https://ww2.mathworks.cn/help/vision/examples/face-detection-and-tracking-using-the-klt-algorithm.html

4ef9b26ef01cf36846133b35fb11b558.png

然后在框内进行特征点提取。

ba12be395d0e8267535b20949e63a117.png

KLT跟踪:

b68b0e0c9069643e5cec9551eb7547a0.png

baf34d64cda8317962a7ea98c176e9ed.png

b445e64ca5826297b8405443da74cc3e.png

49659a5a5d976b3e0e2bc4216542ba0e.png

最后由于我的动作太快,导致了后面的跟踪失败,可见这里体现了前面提到的KLT的假设2:时间连续或者是“小动作”,KLT跟踪局限性还是很大。

2、具体原理步骤实现的代码:

有大神已经在github上上传了相关的代码:https://github.com/yjadaa/KLT,具体实现原理步骤可以参考论文 《good features to track》,效果图附上:

3e808be5f156413526a93d8378edf6c5.png

7746f71c3a5cbf6f48af48c0ce0ea008.png

我在基于此上的代码基础上做了修改,通过框选指定矩形内检测最大角点响应点,对该角点进行跟踪,代码我已经上传到github上,

有需要的可自行下载:https://github.com/hli151/Object-Tracking,代码文件描述如下:

bd3c83db21f4ce651b6a027ec6598765.png

9341ff3fe533336fa083da4a390e7d9d.png

代码运行结果如下:

03445fcb83cc58707abcf25c590129a0.png
框选指定矩形区域

8d950083cdb2213e632628d99c32a7ed.png
绘制款选范围内检测出来的角点

0a16def17fc47be010d353a81e4826e0.png
对最大角点响应进行跟踪

7057295e89780457a50603f3ad0684e2.png

由于本身KLT算法就是很耗时的,所以运行过程中会比较慢,但是能够看到自己修改的代码能有结果也很开森啦,但是到后面不知道出于什么原因,跟踪就不准确,导致跟踪失败,我猜测是不是KLT算法的三个前提假设不满足了呢?或者是有尺度变化导致?(因为KLT算法对目标的跟踪是不具备尺度不变性的),总之,这个算法还是很有局限性的,有待改善!

五、基于QT的代码实现:

也有大神已经在github上上传了相关的代码:https://github.com/search?q=KLT+QT,具体实现的效果图附上:

c27b2cadda874d7b326cb77ebfaa42f4.png

7e443d93a4a4580ff23ac7659b600115.png

由效果图我们不难看出,物体的运动速度越慢,所画出来的运动场的矢量对应幅度越短,物体的运动速度越快,所画出来的运动场的矢量对应幅度越长。

主要参考:

1、具体推导过程。https://www.cnblogs.com/moondark/archive/2012/05/12/2497391.html

2、这篇博客很不错哦。

lowkeyway:(三十八)稀疏光流----KLT​zhuanlan.zhihu.com
43d4dce720755aa0bb42c844d826d72f.png

五、结束语。

作者人丑勿喷,小菜鸟一枚,欢迎指点,谢谢大家!!!

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用Matlab实现高斯金字塔和KLT(光流跟踪)的代码示例: ```matlab % 创建高斯金字塔 function pyramid = createGaussianPyramid(image, levels) pyramid = cell(1, levels); pyramid{1} = image; for i = 2:levels pyramid{i} = impyramid(pyramid{i-1}, 'reduce'); end end % 计算图像梯度 function [Ix, Iy] = computeGradient(image) kernel = [-1, 0, 1]; Ix = conv2(image, kernel, 'same'); Iy = conv2(image, kernel', 'same'); end % 计算光流 function [u, v] = computeOpticalFlow(prevImage, currImage, windowSize, maxIterations, epsilon) [Ix, Iy] = computeGradient(prevImage); u = zeros(size(prevImage)); v = zeros(size(prevImage)); for i = 1:maxIterations % 在每个像素位置计算误差 error = currImage - warpImage(prevImage, u, v); % 计算误差的梯度 [Itx, Ity] = computeGradient(error); % 构建矩阵A和向量b A = zeros(2, 2); b = zeros(2, 1); for x = 1:size(prevImage, 2) for y = 1:size(prevImage, 1) A(1, 1) = A(1, 1) + Ix(y, x)^2; A(1, 2) = A(1, 2) + Ix(y, x) * Iy(y, x); A(2, 1) = A(2, 1) + Ix(y, x) * Iy(y, x); A(2, 2) = A(2, 2) + Iy(y, x)^2; b(1) = b(1) + Itx(y, x) * Ix(y, x); b(2) = b(2) + Ity(y, x) * Iy(y, x); end end % 解线性方程组 delta = pinv(A) * b; % 更新光流 u = u + delta(1); v = v + delta(2); % 检查是否收敛 if norm(delta) < epsilon break; end end end % 对图像进行仿射变换 function warpedImage = warpImage(image, u, v) [X, Y] = meshgrid(1:size(image, 2), 1:size(image, 1)); Xp = X + u; Yp = Y + v; warpedImage = interp2(X, Y, image, Xp, Yp); end % 示例代码 prevImage = imread('prev_image.jpg'); currImage = imread('curr_image.jpg'); windowSize = 15; maxIterations = 100; epsilon = 0.01; pyramid = createGaussianPyramid(prevImage, 3); [u, v] = computeOpticalFlow(pyramid{1}, currImage, windowSize, maxIterations, epsilon); % 显示光流结果 [X, Y] = meshgrid(1:size(prevImage, 2), 1:size(prevImage, 1)); quiver(X, Y, u, v); ``` 请注意,这只是一个简单的示例代码,实际应用可能需要进行更多的优化和改进。此外,你需要将`prev_image.jpg`和`curr_image.jpg`替换为你自己的图像文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值