关于光流法全面的介绍和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(位置),