原创不易,转载请注明出处

【注】:本博客包含很多作者本人的直观理解和解释,不甚严谨,仅供参考。

基本概念

  • 光流:在图像视觉任务中,所谓“光流”就是光的流向,一个像素点在 t t t帧所在位置是 ( x 1 , y 1 ) (x_1,y_1) (x1​,y1​),在 t + 1 t+1 t+1时刻移动到 ( x 2 , y 2 ) (x_2,y_2) (x2​,y2​),那么就可以说 t t t时刻 ( x 1 , y 1 ) (x_1,y_1) (x1​,y1​)位置的光流为方向指向 ( x 2 , y 2 ) (x_2,y_2) (x2​,y2​),大小为两点之间模长的一个矢量,其实不难看出,也就是 t t t时刻 ( x 1 , y 1 ) (x_1,y_1) (x1​,y1​)像素的速度(既有方向也有大小)。当然了,像素实际上是不会移动的,所以光流实质上反应的是像素灰度的变化趋势。
  • 光流场:所谓"场"反应到纸面上就是对空间中没一点的运动/趋势的描述,所以光流场就是对整个空间光流变化的一个描述(或者说就是一个式子、函数)
    光流场
    图1. 光流场

光流法基本原理

假设条件

  • 亮度恒定不变:即同一目标在不同帧间运动时,其亮度不会发生改变。这是基本光流法的假定(所有光流法变种都必须满足),用于得到光流法基本方程
  • 时间连续或运动是“小运动”:即时间的变化不会引起目标位置的剧烈变化,相邻帧之间位移要比较小。同样也是光流法不可或缺的假定。

基本约束方程

假设在空间中, ( x , y ) (x,y) (x,y)位置的像素在 t t t时刻的光强是 I ( x , y , t ) I(x,y,t) I(x,y,t),过了 d t dt dt时间,这个光强向 x , y x,y x,y方向分别移动了 d x , d y dx,dy dx,dy,那么移动后的光强表示是 I ( x + d x , y + d y , t + d t ) I(x+dx,y+dy,t+dt) I(x+dx,y+dy,t+dt)。根据亮度恒定不变假设,有
I ( x , y , t ) = I ( x + d x , y + d y , t + d t ) I(x,y,t)=I(x+dx,y+dy,t+dt) I(x,y,t)=I(x+dx,y+dy,t+dt)
将右侧泰勒展开有
I ( x , y , t ) = I ( x , y , t ) + ∂ I ∂ x d x + ∂ I ∂ y d y + ∂ I ∂ t d t + ϵ I(x,y,t)=I(x,y,t)+\frac{\partial I}{\partial x}dx+\frac{\partial I}{\partial y}dy+\frac{\partial I}{\partial t}dt+\epsilon I(x,y,t)=I(x,y,t)+∂x∂I​dx+∂y∂I​dy+∂t∂I​dt+ϵ
(这个展开就是一阶泰勒展开的公式)
将 ϵ \epsilon ϵ忽略,两边消掉 I ( x , y , t ) I(x,y,t) I(x,y,t),并同除以 d t dt dt,就有
∂ I ∂ x d x d t + ∂ I ∂ y d y d t + ∂ I ∂ t d t d t = 0 \frac{\partial I}{\partial x}\frac{dx}{dt}+\frac{\partial I}{\partial y}\frac{dy}{dt}+\frac{\partial I}{\partial t}\frac{dt}{dt}=0 ∂x∂I​dtdx​+∂y∂I​dtdy​+∂t∂I​dtdt​=0
这里显然 d x d t , d y d t \frac{dx}{dt},\frac{dy}{dt} dtdx​,dtdy​是 x x x方向和 y y y方向上的速度。分别设为 u , v u,v u,v,并设 I x = d I d x , I y = d I d y , I t = d I d t I_x=\frac{dI}{dx},I_y=\frac{dI}{dy},I_t=\frac{dI}{dt} Ix​=dxdI​,Iy​=dydI​,It​=dtdI​,于是有
I x u + I y v + I t = 0 ,( 1 ) I_xu+I_yv+I_t=0, (1) Ix​u+Iy​v+It​=0,(1)
显然 I x , I y , I t I_x,I_y,I_t Ix​,Iy​,It​分别是亮度函数在 x , y , t x,y,t x,y,t方向上的梯度,也就是变化的剧烈程度。
实际上 I x , I y , I t I_x,I_y,I_t Ix​,Iy​,It​是已知的,可以用差分法求出,比如
I x = I ( x + d x , y , t ) − I ( x , y , t ) = I ( x + 1 , y , t ) − I ( x , y , t ) I_x=I(x+dx,y,t)-I(x,y,t)=I(x+1,y,t)-I(x,y,t) Ix​=I(x+dx,y,t)−I(x,y,t)=I(x+1,y,t)−I(x,y,t)
其中 I ( x + 1 , y , t ) I(x+1,y,t) I(x+1,y,t)实际上就是第 t t t帧图像在 ( x + 1 , y ) (x+1,y) (x+1,y)像素处的灰度值。

那么所谓光流场,也就是公式(1)的解,因为对于每帧图像的每个位置 ( x , y ) (x,y) (x,y), I x , I y , I t I_x,I_y,I_t Ix​,Iy​,It​是已知值,只要解出公式(1)得到 u , v u,v u,v的值,就得到了这点像素的“速度矢量”,也就是光流。但是显然问题是只有一个等式却有两个未知变量,在现有条件下不可解,或者说有无数多解。那么各个光流法的本质就是在此基础上再加约束,使得(1)式可解,得到确定的 u , v u,v u,v值。

Lucas-Kanade(LK)光流法

对于公式(1)无穷多解的问题,LK法的核心思想是提出一个假设,即图像上的一个小窗口内,所有像素位置的光流都一样,即小窗口内的每个像素都有相同的 u , v u,v u,v。在此假设下会得到N个方程,2个未知数的超定方程组,没有精确解但是可以用最小二乘法求最优解。
假设窗口大小为 3 × 3 3\times3 3×3,就有
{ I x 1 u + I y 1 v = − I t 1 I x 2 u + I y 2 v = − I t 2 . . . I x 9 u + I y 9 v = − I t 9 \left\{ \begin{matrix} I_{x_1}u+I_{y_1}v=-I_{t_1} \\ I_{x_2}u+I_{y_2}v=-I_{t_2} \\ ...\\ I_{x_9}u+I_{y_9}v=-I_{t_9} \\ \end{matrix} \right. ⎩ ⎨ ⎧​Ix1​​u+Iy1​​v=−It1​​Ix2​​u+Iy2​​v=−It2​​...Ix9​​u+Iy9​​v=−It9​​​
矩阵形式
A [ u v ] = b A\begin{bmatrix} u\\ v \end{bmatrix}=b A[uv​]=b
其中
A = [ I x 1 I y 1 I x 2 I y 2 . . . . . . I x n I y n ] , b = [ − I t 1 − I t 2 . . . − I t n ] A=\begin{bmatrix} I_{x_1} & I_{y_1}\\ I_{x_2} & I_{y_2}\\ ... & ...\\ I_{x_n} & I_{y_n}\\ \end{bmatrix} ,b=\begin{bmatrix} -I_{t1} \\ -I_{t2} \\ ... \\ -I_{t_n} \end{bmatrix} A= ​Ix1​​Ix2​​...Ixn​​​Iy1​​Iy2​​...Iyn​​​ ​,b= ​−It1​−It2​...−Itn​​​ ​
那么需要的解就变成了找到 x x x使得 ∣ ∣ A x − b ∣ ∣ 2 ||Ax-b||^2 ∣∣Ax−b∣∣2最小。根据最小二乘法公式,解法公式为:
( A T A ) [ u v ] = A T b (A^TA)\begin{bmatrix}u\\v\end{bmatrix}=A^Tb (ATA)[uv​]=ATb
最终解为:
[ u v ] = ( A T A ) − 1 A T b \begin{bmatrix}u\\v\end{bmatrix}=(A^TA)^{-1}A^Tb [uv​]=(ATA)−1ATb
经计算有
A T A = [ ∑ I x 2 ∑ I x I y ∑ I x I y ∑ I y 2 ] , A T b = [ − ∑ I x I t − ∑ I y I t ] A^TA=\begin{bmatrix} \sum{I_x^2} & \sum{I_xI_y} \\ \sum{I_xI_y} & \sum{I_y^2} \end{bmatrix}, A^Tb=\begin{bmatrix} -\sum{I_xI_t} \\ -\sum{I_yI_t} \end{bmatrix} ATA=[∑Ix2​∑Ix​Iy​​∑Ix​Iy​∑Iy2​​],ATb=[−∑Ix​It​−∑Iy​It​​]
所以最终有
[ u v ] = [ ∑ I x 2 ∑ I x I y ∑ I x I y ∑ I y 2 ] − 1 [ − ∑ I x I t − ∑ I y I t ] \begin{bmatrix} u \\ v \end{bmatrix}= \begin{bmatrix} \sum{I_x^2} & \sum{I_xI_y} \\ \sum{I_xI_y} & \sum{I_y^2} \end{bmatrix}^{-1} \begin{bmatrix} -\sum{I_xI_t} \\ -\sum{I_yI_t} \end{bmatrix} [uv​]=[∑Ix2​∑Ix​Iy​​∑Ix​Iy​∑Iy2​​]−1[−∑Ix​It​−∑Iy​It​​]
矩阵的逆的计算方法可以搜相关教程。
因为这个方法里需要计算矩阵的逆,所以隐含条件是矩阵必须可逆,即 A T A A^TA ATA必须可逆,如果这个矩阵接近0,那么往往是不可逆的。当小窗口所在区域图像内容比如是白墙、蓝天,往往就不可计算。所以LK方法只对纹理丰富的点有效。

金字塔LK(Pyramid Lucas-Kanade)

LK方法里使用了一阶泰勒展开,这样就有一个前提是,这种方法只适用于位移、时间变动都很小的情况。如果图像内出现移动速度很快的目标,一帧图像可能就跨越几十个像素,那么用LK方法就不合适,对于这种大位移情况,可以用金字塔LK方法。
方法的核心思想:通过上采样不断把图像缩小,那么目标的位移也就不断减小,在足够小的图像尺度上使用LK方法,计算出 u , v u,v u,v,将此作为初始值再计算下一层的 u , v u,v u,v,以此类推最终算出原图的 u , v u,v u,v。
例如对于原始图像 I 0 I_0 I0​,做4次缩放,每次缩放尺度变为原本的 1 2 \frac{1}{2} 21​,得到 I 1 , I 2 , I 3 I_1, I_2, I_3 I1​,I2​,I3​,在 I 3 I_3 I3​上使用LK方法,计算出 I 3 I_3 I3​的光流 u 3 , v 3 u_3, v_3 u3​,v3​,然后计算 I 2 I_2 I2​上的初始值:
u u p 3 = 2 u 3 , v u p 3 = 2 v 3 u_{up_3}=2u_3,v_{up_3}=2v_3 uup3​​=2u3​,vup3​​=2v3​
假定 I 2 I_2 I2​上的光流 u 2 , v 2 u_2,v_2 u2​,v2​是在 I 3 I_3 I3​光流基础上做了微小调整,那么就有
( u 2 , v 2 ) = ( u u p 3 , v u p 3 ) + ( Δ u , Δ v ) ,( 2 ) (u_2,v_2)=(u_{up_3},v_{up_3})+(\Delta u, \Delta v),(2) (u2​,v2​)=(uup3​​,vup3​​)+(Δu,Δv),(2)
再在 I 2 I_2 I2​上使用LK方法:
I x 2 u 2 + I y 2 v 2 = − I t 2 I x 2 ( u u p 3 + Δ u ) + I y 2 ( v u p 3 + Δ v ) = − I t 2 I_{x_2}u_2+I_{y_2}v_2=-I_{t_2} \\ I_{x_2}(u_{up_3}+\Delta u)+I_{y_2}(v_{up_3}+\Delta v)=-I_{t_2} Ix2​​u2​+Iy2​​v2​=−It2​​Ix2​​(uup3​​+Δu)+Iy2​​(vup3​​+Δv)=−It2​​
整理有
I x 2 Δ u + I y 2 Δ v = − ( I t 2 + I x 2 u u p 3 + I y 3 v u p 3 ) I_{x_2}\Delta u + I_{y_2} \Delta v=-(I_{t_2}+I_{x_2}u_{up_3}+I_{y_3}v_{up_3}) Ix2​​Δu+Iy2​​Δv=−(It2​​+Ix2​​uup3​​+Iy3​​vup3​​)
设 δ I = ( I t 2 + I x 2 u u p 3 + I y 3 v u p 3 ) \delta I=(I_{t_2}+I_{x_2}u_{up_3}+I_{y_3}v_{up_3}) δI=(It2​​+Ix2​​uup3​​+Iy3​​vup3​​),就有
I x 2 Δ u + I y 2 Δ v = − δ I I_{x_2}\Delta u + I_{y_2} \Delta v=-\delta I Ix2​​Δu+Iy2​​Δv=−δI
那么后面就和普通LK推理方法一样,得到
[ Δ u Δ v ] = [ ∑ I x 2 2 ∑ I x 2 I y 2 ∑ I x 2 I y 2 ∑ I y 2 2 ] − 1 [ − ∑ I x 2 δ I − ∑ I y 2 δ I ] \begin{bmatrix} \Delta u \\ \Delta v \end{bmatrix}= \begin{bmatrix} \sum{I_{x_2}^2} & \sum{I_{x_2}I_{y_2}} \\ \sum{I_{x_2}I_{y_2}} & \sum{I_{y_2}^2} \end{bmatrix}^{-1} \begin{bmatrix} -\sum{I_{x_2}\delta I} \\ -\sum{I_{y_2}\delta I} \end{bmatrix} [ΔuΔv​]=[∑Ix2​2​∑Ix2​​Iy2​​​∑Ix2​​Iy2​​∑Iy2​2​​]−1[−∑Ix2​​δI−∑Iy2​​δI​]
得到 Δ u , Δ v \Delta u,\Delta v Δu,Δv后就可以用公式(2)计算 u 2 , v 2 u_2, v_2 u2​,v2​了,然后就可以继续计算 u u p 2 , v u p 2 u_{up_2},v_{up_2} uup2​​,vup2​​,然后继续向下传播,最终在 I 0 I_0 I0​上得到光流。

参考资料

计算机视觉–光流法(optical flow)简介

Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐