关于光流法全面的介绍和OpenCV代码,请参考:zou\text{x}y09的专栏
\text{x}y09/article/details/8683859
本文和后续文章仅对光流法的原理进行补充。上述参考文章里面已经介绍的内容不会重复。

OpenCV中calcOpticalFlowFarneback

cv::calcOpticalFlowFarneback(prevgray, 
                gray,
                flow, 
                0.5, //double pyrScale金字塔参数:0.5为经典参数,每一层是下一层尺度的一半;                 
                3, // int levels金字塔的层数
                15, //int winsize窗口大小
                3, // int iterations,迭代次数
                5, //int polyN
                1.2, //double polySigma
                0);  // int flags  可以组合使用OPTFLOW_USE_INITIAL_FLOW  OPTFLOW_FARNEBACK_GAUSSIAN

用Gunnar Farneback 的算法计算稠密光流(即图像上所有像素点的光流都计算出来)。它的相关论文是:”Two-Frame Motion Estimation Based on PolynomialE\text{x}pansion”。

下面对原论文计算位移(即运动)的原理进行解读。
仅仅用相邻两帧图像来估计物体的运动,即估计物体的位移,位移场。
多项式展开指的是:对每个像素的领域使用一个多项式来近似表达。这里仅仅对二项式展开感兴趣。对每一个像素,位置为x,利用二次多项式构造一个局部信号模型,


f(x)∼xTAx+bTx+c


其中

A 是对称矩阵,b 是一个向量, c 是一个标量。

这些系数使用加权的最小二乘法拟合领域中信号的值。

位移估计
理想的情形:
对于第一副图像,构建一个局部信号:

f1(x)=xTA1x+bT1x+c1


在经历一个全局的位移

d(不随空间变化,恒定方向和大小)后,在第二副图像上,我构建一个新的信号f2如下:



f2(x)=f1(x−d) =(x−d)TA1(x−d)+bT1(x−d)+c1 =xTAzx+(b2−2A1d)Tx+dTA1d−bT1d+c1 =xTA2x+bT2x+c2


因此有



A2=A1        (4)


b2=b1−2A1d        (5)


c2=dTA1d−bT1d+c1        (6)


最关键的是(5)式:

A1 是非奇异矩阵的情况下,容易得到:



d=−12A−11(b2−b1)        (8)


值得注意的是,在任何维度下,上式是成立的。


实际情形:


很显然,我们使用一个不随空间变化的位移d,使用单一个多项式拟合函数来研究两副图像的关系,是不切实际的。


定义第一副图像随空间变化的参数

A1(x),b1(x),c1(x) ,第二幅图像参数 A2(x),b2(x),c2(x)


A(x)=A1(x)+A2(x)2        (9)


Δb(x)=−12(b2(x)−b1(x))        (10)


最主要的约束是:



A(x)d(x)=Δb(x)           (11)


注:(9)式对应于(4),显然必只用第一副图像的

A1更合理。


       (10)和(11)一起对应于(5)式。

d(x) 说明我们已经用一个随空间位置发生变化的位移场来代替方程(3)中恒定大小和方向的全局位移d。

使用先验证信息
位移比较大的时候,第一个多项式信号中的x(位置),