阿雪的学习记录|光流法基础

本文代码参考这篇博客,文献附后

目的

相机运动检测,是的,相机运动检测,这个斌斌就是逊啦!
一年前还对光流法的效果嗤之以鼻弃之不理,一年后终归是又回来了,一直觉得新的方法理论可实现就好,结果实验效果拉胯到地心,鲁棒性,如果说有一个形容词是用来表示鲁棒性很差很差的,那么那个形容词就是:my method

基本原理

简单来说就是特征点跟踪,问题在于这个特征点怎么识别,这一块好像和最基本的光流法没有关系,难点在于怎么死死跟住这个特征点,不丢失不滑移。
文献[1]中用的是一个18年提出的光流估计网络,发表在CVPR,他的选择依据是这么表述的:
“这是一个能够同时进行特征提取和光流计算的级联网络,且比传统方法能够在更大的感兴趣区域进行信息匹配。”
他直接拿来用了,关于这一点我也有看到另一个网络,知乎地址,这篇发表在ECCV,2020年提出,说是有着更小的模型尺寸和更快的运行速度,mark一下明天看好了

好了回到正题,题头提到的那篇代码的光流法是最最最基础的那种,运行速度慢的鸭皮,它不走GPU(我也不太懂为啥有的就走GPU有的就不走,我好菜我明天就去学),40秒的视频运行几遍才能成功,而且我的视频还没有什么物体之间的运动,只有相机动而且背景单一,光照情况也比较稳定,就成功了一次,还没跟够40秒就出错退出了,没什么鲁棒性,不过不影响学

1.基本光流概念

光流法跟踪就是要识别到光流,光流存在的条件
(1)相邻帧之间的亮度恒定;
(2)相邻帧的取帧时间连续,帧帧之间物体运动幅度小;
(3)保持空间一致性,这一点要求目标物体上的像素点要有相同的运动,那也就是说这个物体得是刚性的。

这光流法如果只满足这样的条件的话,都不用想,它都没什么应用场景吧,就算是要目标检测也需要目标自己内部不发生运动才能获得理想的检测结果……

那么如何去计算光流呢,是要在目标点(我想最初应该就是随机选取或者都取,这应该是加强算法要加强的点之一吧)周围取邻域,也就是集成窗口,确定它的大小,使得当前帧该窗口中所有像素点和下一帧该窗口中已经位移了的像素点差分取平方,当能得到最小差异时,该位移就是这两帧之间的光流。

那这个目标点咋选呢,还有这个集成窗口,我怎么知道两个窗口里哪两个像素点是对应的啊?这些问题就由下面这个函数实现。

2.图像金字塔

这calcOpticalFlowPyrLK()应该是这个方法的核心函数,使用文献[2]提出的金字塔迭代Lucas-Kanade方法计算稀疏特征集的光流。

图像金字塔,顾名思义,就是将图片逐级缩放,给它摞起来,像个金字塔一样,那这个金字塔迭代呢就是对每一层图片估计一个光流向量 g g g,在每层的估计时都会产生一个光流漂移向量 d d d(就是实际向量-光流向量 g g g
由于图片是逐级缩放的,缩放比例相等,假设层层之间图片都缩小一半,比如我猜第一层(原始尺寸的图片)的参数是 ( g 1 , d 1 ) (g1,d1) (g1,d1),那么理想情况下我第二层的参数就应该是 0.5 ∗ ( g 1 , d 1 ) 0.5*(g1,d1) 0.5(g1,d1),最顶层的偏移量就应该是很小一个系数 n ∗ ( g 1 , d 1 ) n*(g1,d1) n(g1,d1),我们记为 ( g n , d n ) (gn,dn) (gn,dn)
但最顶层的图片已经是个点了,实际的参数是 ( 0 , 0 ) (0,0) (0,0),那此时,就可以得到实际参数和预测参数之间的不同, ( g n , d n ) (gn,dn) (gn,dn),还记得 g g g d d d的意义吗,那到最后一层的时候这两个参数都成了漂移量,所以最后它的漂移量d就是: d = g n + d n d=gn+dn d=gn+dn

金字塔看懂了吧,那我咋计算某层的 ( g , d ) (g,d) (g,d)呢?蛤,就是不断迭代
每一层都可以计算出 ( g , d ) (g,d) (g,d),每两层都可以算出较高一层的实际漂移量 d d d,这里的实际漂移量就是说我这层估计出来个 ( g 2 , d 2 ) (g2,d2) (g2,d2),这层的底下一层也估计出来个 ( g 1 , d 1 ) (g1,d1) (g1,d1),如果底下那层估计得可准了的话,这个等式就应该成立:
( g 1 , d 1 ) = 2 ∗ ( g 2 , d 2 ) (g1,d1)=2*(g2,d2) (g1,d1)=2(g2,d2)
但肯定不成立呀,怎么会那么简单!所以2层相对一1层就有一个实际漂移量了,这个实际漂移量的表示:
d 2 ′ = 2 ∗ g 2 − g 1 + d 2 − d 1 d2'=2*g2-g1+d2-d1 d2=2g2g1+d2d1
(编辑下标多是一件美逝啊不了不了)
那我已知金字塔顶端的是 ( 0 , 0 ) (0,0) (0,0)了,迭代就是力求最后一层的 ( g n , d n ) (gn,dn) (gn,dn)绝对值最小呗

好了迭代我懂了,那第一层的 ( g 1 , d 1 ) (g1,d1) (g1,d1)咋算啊!我总不能就随机选取吧,嗯,这里就是特征选择了

3.特征点选取

我不造为啥这个特征点选取要放在文献的最后讲,就很怪,明明……明明我觉得这个辣么重要!可能Jean先生提出的金字塔才是他的创新点,雀食,但对我来讲这个金字塔很好很奈斯但特征点怎么选才是最难的,就好比我之前用的那个方法,理论上很好很奈斯但是图像分割效果不好的话后面就都是虾扯蛋QAQ

如何选择这个特征点呢,和肉眼观察一样,我们对具有特征的地方记忆犹新,就好比你在乘坐火车的时候,眼睛会不由自主地一次次追随路边的某棵快速划过的树,而很难做到看着外面动着的场景目不斜视(反正我不行,除非我假装自己什么都不看),那这棵树在第一秒出现在视野里的时候就有了区别于别的树的特征,比如它比较高大,反正你记住它了,它在最后一片叶子离开这扇窗之前它都是那个模样,高大这个特征就是你找到的最明显的特征,Jean先生说这种特征就是“easy to track”

所以特征点提取就像轮廓检测一样,找到梯度最大的像素点,都给它找出来,再算算这些像素点的邻域点的梯度,保留最大的那个,我觉得这一步应该会减少挺多无效特征点的,这样特征点就找好了

就没了他就说到这了!然后就启用他的光流不匹配向量,也就是该点在x和y两方向上前后两像素的平均值,和该点与我所预测的光流向量g、漂移量d之和,之间的差值的积分,用这个不匹配向量除以梯度矩阵,算出当前像素和前一个像素之间的光流差,如此迭代,直到遍历所有像素,或者这个光流差小于设定好的阈值,就结束迭代,迭代到最后,这个光流差就成了这层图片上,这帧和前一帧之间的漂移量d,g的计算方法也是迭代,迭代就完事了。(我还以为要讲啥呢……这就是特征点选取吗这块公式看得我都睡着了)

为啥我觉得这个方法它……这么……就好像我拿了100串钥匙,首先我知道我要开一字锁孔,这个特征好明显我就先把一字钥匙选出来,然后一个一个试,而且我拿的这些钥匙还不一定有一把能打开这个锁,我得记录每次开锁的感觉,嗯,这把感觉好像就差一点,那把好像插进去就拧不动了,最后万一我找到一把能开锁我就不再尝试,如果就是找不到,保留感觉好像稍微改改就能开锁的钥匙,并记录这个“稍微改改“的程度,以后有这种感觉了就都停止尝试,甭管后面有没有真能开锁的钥匙。

所以说,这个方法,是不是就是Brute-Force蛮力匹配,甭管我这个目标在下一帧还在不在了,我都要一个一个试一次,那我猜,感觉RANSAC方法会好一点吧,好歹是可以舍弃一些野点,这篇RANSAC基本原理有讲,可以看看,顺着找了找特征匹配的方法,参考这篇opencv-python 详解图像特征(四)之特征匹配,里面有介绍很多更为快速且效果更好的方法,其中讲到了单应性匹配……唉,也是我曾弃之不理的办法,不过这个方法我当时弃了是不太会用,其实针对相机旋转运动来讲单应性匹配应该是最好的方法。

好了不行了困死我了今天就到这里吧晚安玛卡巴卡

参考文献

[1]刘思博,房立金.单目相机轨迹的真实尺度恢复[J].中国图象图形学报,2022,27(02):486-499.
[2]Pyramidal Implementation of the Lucas Kanade Feature Tracker Description of the algorithm
(点击就送pdf,关键是我咋找不到现成的标准引用啊)

每天学一点点,就能少菜一点点,加油( •̀ ω •́ )y

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值