LK光流估计

光流的概念是Gibson在1950年首先提出来的。它是空间运动物体在观察成像平面上的像素运动的瞬时速度,是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系,从而计算出相邻帧之间物体的运动信息的一种方法。

一般而言,光流是由于场景中前景目标本身的移动、相机的运动,或者两者的共同运动所产生的。

假设条件

  1. 亮度恒定,就是同一点随着时间的变化,其亮度不会发生改变。这是基本光流法的假定(所有光流法变种都必须满足),用于得到光流法基本方程;

  2. 小运动,这个也必须满足,就是时间的变化不会引起位置的剧烈变化,这样灰度才能对位置求偏导(换句话说,小运动情况下我们才能用前后帧之间单位位置变化引起的灰度变化去近似灰度对位置的偏导数),这也是光流法不可或缺的假定;

  3. 空间一致,一个场景上邻近的点投影到图像上也是邻近点,且邻近点速度一致。这是Lucas-Kanade光流法特有的假定,因为光流法基本方程约束只有一个,而要求x,y方向的速度,有两个未知变量。我们假定特征点邻域内做相似运动,就可以连立n多个方程求取x,y方向的速度(n为特征点邻域总点数,包括该特征点)

光流约束方程

由亮度恒定假设,得到如下等式 \[ I(x,y,t)=I(x+\Delta x,y+\Delta y,t+\Delta t) \] 泰勒展开得到 \[ f_xu+f_yv+f_t=0 \] 其中\(f_x=\frac{\partial I}{\partial x},f_y=\frac{\partial I}{\partial y},f_t=\frac{\partial I}{\partial t},u=\Delta x,v=\Delta y,\Delta t=1\)

一个方程但是有两个未知数u,v,显然是求不出来解的

L-K光流估计方法

由于空间一致假设,可以使用一个3*3的窗口,那就有9个像素点,就会对应9个光流方程,得到一组光流估计方程。考虑邻域内像素可以取不同权值,得到一个最优化问题 \[ \min||w(A\mathbf u-b)||_2 \]

用矩阵表示如下

\[ \begin{bmatrix} w_{1} & 0 & 0\\ 0 & \ddots & 0\\ 0 & 0 & w_{9}\\ \end{bmatrix} \begin{bmatrix} f_{x1} & f_{y1}\\ \vdots & \vdots\\ f_{x9} & f_{y9}\\ \end{bmatrix} \begin{bmatrix} u\\ v \end{bmatrix}= \begin{bmatrix} w_{1} & 0 & 0\\ 0 & \ddots & 0 \\ 0 & 0 & w_{9}\\ \end{bmatrix} \begin{bmatrix} f_{t1}\\ \vdots\\ f_{t9}\\ \end{bmatrix} \]

最小二乘法约束为 \[ E(u,v)=\sum_{i=1}^9w_i^2(f_xu+f_yv+f_t)^2 \]

最小二乘解\(\mathbf u=(A^TW^2A)^{-1}A^TW^2b\)

可信度判断

矩阵求逆是否能实现 \[ A^TA= \begin{bmatrix} \sum f_x^2 & \sum f_xf_y\\ \sum f_xf_y & \sum f_y^2 \end{bmatrix} =\sum \begin{bmatrix} f_x \\ f_y\\ \end{bmatrix} \begin{bmatrix} f_x & f_y\\ \end{bmatrix}= \sum \nabla f(\nabla f)^T \] 我们在计算光流的时候,我们要求图像对应位置灰度变化充分(具有充分特征),假如位置灰度变化平缓,那么沿x和y方向的偏倒就可能为0,那么上述式子不可求逆,也就无法计算光流。

通过特征值判断是否计算可信 在数学上我们要判断矩阵是否可逆,我们可以通过计算特征值来判断。如果两个特征值远大于0,那么矩阵求逆是可靠的。假如有一个特征值接近于0的话,那么矩阵求逆是不可靠的。

金字塔LK方法

为了解决物体移动大位移的情况,需要下采样到一个比较小的图像,使得满足小运动条件

20220521205335

  1. 在l层建立光流约束方程 \[ I^l(\mathbf u,t)=I^l(\mathbf u+d^l,t+1) \]

  2. 根据LK方法可以算出位移\(d^l\) 20220521205417

  3. 设采样率为2,则l-1层光流约束方程为 \[ I^{l-1}(\mathbf u,t)=I^{l-1}(\mathbf u+2d^l+d^{l-1},t+1) \]

  4. 泰勒展开如下 \[ f^{l-1}(\mathbf u+2d^l)d^{l-1}=I^{l-1}(\mathbf u,t)-I^{l-1}(\mathbf u+2d^l,t+1) \]

  5. 可以算出位移\(d^{l-1}\)

  6. 最终算出原图像位移

opencv函数

CV_EXPORTS_W void goodFeaturesToTrack( InputArray image, OutputArray corners,
int maxCorners, double qualityLevel, double minDistance,
InputArray mask = noArray(), int blockSize = 3,
bool useHarrisDetector = false, double k = 0.04 );
CV_EXPORTS_W 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,输出状态向量;如果相应点光流被发现,向量的每个元素被设置为1,否则,被置为0。