VSLAM前端:金字塔光流跟踪算法
一、光流
像素点在二维图像中的运动被定义为光流,其在相邻帧图像中存在有位移运动,即存在像素的光流。我们的目的是计算出光流,计算要满足几个前提假设:1.灰度不变性:同一个像素的灰度值在各个图像中是固定不变的;2. 相邻帧之前像素的位移不能太大;3.运动像素周围的像素具有同样的运动规律。
假设图中像素点的位移向量为
,即光流,设第一帧中像素的二维坐标为
,下一帧像素的位置可以表示为
,前两帧图像分别用
和
表示。我们假设邻域内像素具有相同的运动规律,我们建立以光流为优化变量的误差函数:
其中
和
表示整数,一般取2,3,4,5,6,7。
二、图像金字塔
上图为4层图像金字塔,从下往上进行图像的下采样即可,这里不多解释,读者可自行了解。
三、基于金字塔的Lucas-Kanade算法
算法的基本思路为:首先在金字塔的最高层计算光流大小,将它作为下一层金字塔光流的初始值,以此类推计算第0层的光流大小,作为最终的光流结果。
我们将第一小节的误差函数改写为金字塔第
层的损失函数:
其中
为猜测光流,表示金字塔第
层迭代的光流初始值,
为剩余光流,表示金子塔第
层迭代的光流误差。
3.1 剩余光流
的计算
我们使用上式对
求导:
然后将图像
在
处进行一阶泰勒展开可得:
其中
表示图片
对
坐标求导。对于领域内的像素我们定义:
其中
由图像梯度求出,即:
我们将上述公式全部带入泰勒展开式,并且两边同时取转置,可得:
我们化简公式:
则可以得到:
当取得极小值时,导数为0,则
,至此我们得到经典的Lucas-Kanade光流公式,但其建立在像素位移很小的前提下。我们现在讨论的是金字塔光流,其对光流法进行了改进,进行多次迭代,我们改写公式:
当
小于阈值后,迭代终止,迭代公式为:
,以上就是每层金字塔剩余光流的计算过程。
3.2 猜测光流
的计算
最高层
,每层金字塔图像猜测光流公式为:
。
最终光流
。
四、原始论文算法流程
原始论文的算法流程更加简洁明了,推荐大家看下面流程:
五、opencv接口函数
void calcOpticalFlowPyrLK(
InputArray prevImg, InputArray nextImg, InputArray prevPts, InputOutputArray nextPts,
OutputArray status, OutputArray err,
Size winSize=Size(21,21), int maxLevel=3,
TermCriteria criteria=TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01),
int flags=0, double minEigThreshold=1e-4)
prevImg:第一帧金字塔图像;
nextImg:第二帧金字塔图像;
prevPts:第一帧的像素坐标;
nextPts:需要找到的第二帧像素坐标;
status:状态变量;
err:错误矢量输出;
winSize:每层金字塔的搜索窗口大小;
maxLevel:金字塔最大层级;
criteria:迭代终止条件;
flags:OPTFLOW_USE_INITIAL_FLOW与OPTFLOW_LK_GET_MIN_EIGENVALS使用的标志位;
minEigThreshold:最小特征值阈值;