计算机视觉——光流法
系列文章目录
本系列开篇文章,暂时没有目录啦~
文章目录
- 系列文章目录
- 前言
- 一、问题假设
- 二、方程推导
- 三、计算Ix,Iy,ItI_x,I_y,I_tIx,Iy,It
- 四、计算光流u,vu,vu,v
- 4.1 传统算法Lucas-Kanade算法
- 五、孔径问题
- 5.1 直观理解
- 5.2 数学角度
- 5.3 解决方法
- 总结
前言
光流(Optical Flow)是指图像中的物体在连续帧之间的相对运动。具体来说,光流法试图通过图像中的像素变化(通常是亮度变化)来推测场景中物体的运动方向和速度。
假设你有一个视频或连续的图像帧,光流法就是计算在连续的两帧图像之间,每个像素点的位移(即物体的运动)。如果你可以估计每个像素点的位移,那么你就可以获得整个图像的光流场。
主要参考了下述两篇文章,如有侵权,联系我我会删除此内容
经典光流算法Lucas-Kanade(有图助理解)
光流法(optical flow methods)
一、问题假设
假设一——亮度一致性假设:图像中某个像素点的亮度在连续的两帧图像之间不会发生太大变化,只有由于相对运动而产生的位移。即假设物体的亮度在两帧图像之间是恒定的。这个假设是基于图像的亮度变化主要由物体的运动引起的。
假设二——平滑性假设:图像中的运动变化是平滑的,即在局部区域内,相邻像素的运动是相似的。
二、方程推导
设t时刻(x,y)位置的像素亮度为I(x,y,t)I(x,y,t)I(x,y,t)
根据假设一,对于一个像素点(x,y)(x,y)(x,y),在时间ttt和t+Δtt+\Delta tt+Δt之间的亮度变化应满足:
I(x,y,t)=I(x+Δx,y+Δy,t+Δt)I(x,y,t)=I(x+\Delta x,y+\Delta y,t+\Delta t)I(x,y,t)=I(x+Δx,y+Δy,t+Δt)
其中:
- I(x,y,t)I(x,y,t)I(x,y,t)表示时刻ttt时,坐标(x,y)(x,y)(x,y)位置的亮度。
- Δx,Δy\Delta x,\Delta yΔx,Δy分别是该像素在水平和垂直方向上的位移。
- Δt\Delta tΔt是两个图像帧之间的时间差。
利用泰勒级数展开对右边进行近似,可以得到一个简化的表达式。泰勒展开的思想是,通过将一个函数在某一点附近的变化表示为该点函数值与其各阶导数的线性组合,来逼近这个函数在该点附近的值。
将I(x+Δx,y+Δy,t+Δt)I(x+\Delta x,y+\Delta y,t+\Delta t)I(x+Δx,y+Δy,t+Δt)近似为I(x+Δx,y+Δy,t+Δt)≈I(x,y,t)+∂I∂xΔx+∂I∂yΔy+∂I∂tΔtI(x+\Delta x,y+\Delta y,t+\Delta t) \approx I(x,y,t)+\frac{\partial I}{\partial x}\Delta x+\frac{\partial I}{\partial y}\Delta y+\frac{\partial I}{\partial t}\Delta tI(x+Δx,y+Δy,t+Δt)≈I(x,y,t)+∂x∂IΔx+∂y∂IΔy+∂t∂IΔt
这个公式使用了泰勒展开的前几项,其中:
- ∂I∂x\frac{\partial I}{\partial x}∂x∂I是图像I(x,y,t)I(x,y,t)I(x,y,t)在xxx方向的偏导数,表示图像亮度在水平(x)方向上的变化速率(即图像在xxx方向上的梯度);
- ∂I∂y\frac{\partial I}{\partial y}∂y∂I是图像I(x,y,t))I(x,y,t))I(x,y,t))在yyy方向的偏导数,表示图像亮度在垂直(y)方向上的变化速率(即图像在yyy方向上的梯度);
- ∂I∂t\frac{\partial I}{\partial t}∂t∂I是图像I(x,y,t)I(x,y,t)I(x,y,t)随时间ttt变化的偏导数,表示图像亮度在时间方向上的变化速率(即图像随时间变化的亮度变化)。
现在,我们将泰勒展开的结果代入亮度恒定假设中:
I(x,y,t)=I(x+Δx,y+Δy,t+Δt)=I(x,y,t)+IxΔx+IyΔy+ItΔtI(x,y,t)=I(x+\Delta x,y+\Delta y,t+\Delta t)=I(x,y,t)+I_x\Delta x+I_y\Delta y+I_t\Delta tI(x,y,t)=I(x+Δx,y+Δy,t+Δt)=I(x,y,t)+IxΔx+IyΔy+ItΔt
其中:
- Ix=∂I∂xI_x=\frac{\partial I}{\partial x}Ix=∂x∂I是图像在xxx方向的梯度;
- Iy=∂I∂yI_y=\frac{\partial I}{\partial y}Iy=∂y∂I是图像在yyy方向的梯度;
- It=∂I∂tI_t=\frac{\partial I}{\partial t}It=∂t∂I是图像在ttt方向的梯度。
由于左侧的两个I(x,y,t)I(x,y,t)I(x,y,t)相等,可以将它们抵消掉:
0=IxΔx+IyΔy+ItΔt0=I_x\Delta x+I_y\Delta y+I_t\Delta t0=IxΔx+IyΔy+ItΔt
接下来,假设Δx\Delta xΔx和Δy\Delta yΔy是该像素的位移(即物体运动导致该像素位置的变化),我们可以将Δx\Delta xΔx和Δy\Delta yΔy表示为光流的分量uuu和vvv,即:
Δx=uΔt\Delta x=u\Delta tΔx=uΔt
Δy=vΔt\Delta y=v\Delta tΔy=vΔt
其中:
- uuu是图像中像素在方向的运动速度(光流的水平分量);
- vvv是图像中像素在方向的运动速度(光流的垂直分量);
- Δt\Delta tΔt是两个时间帧之间的时间差。
将这些表达式代入之前的方程,我们得到:
0=IxuΔt+IyvΔt+ItΔt0=I_xu\Delta t+I_yv\Delta t+I_t\Delta t0=IxuΔt+IyvΔt+ItΔt
由于Δt\Delta tΔt是一个常数,且不等于零,我们可以把Δt\Delta tΔt消去,得到光流的核心方程:
Ixu+Iyv+It=0I_xu+I_yv+I_t=0Ixu+Iyv+It=0
这个方程描述了在每个像素点上,图像亮度变化与该点的运动(光流)之间的关系。它给出了光流uuu和vvv的关系:像素的运动(光流)与图像的梯度信息(在空间和时间上的变化)有关。
三、计算Ix,Iy,ItI_x,I_y,I_tIx,Iy,It
四、计算光流u,vu,vu,v
4.1 传统算法Lucas-Kanade算法
增加一个假设:假设在小窗口内,光流是恒定的。
算法的核心思想是通过在该窗口内对每个像素的光流方程进行加权最小二乘法拟合,从而估算出该窗口内所有像素的水平和垂直方向的光流(即uuu和vvv)。
Ixu+Iyv+It=0I_xu+I_yv+I_t=0Ixu+Iyv+It=0
我们将上述公式转为矩阵形式:
(Ix,Iy)(uv)=−It(I_x,I_y)\begin{pmatrix} u\\ v \end{pmatrix}=-I_t(Ix,Iy)(uv)=−It
所以,如果我们选择一个n×nn \times nn×n的窗口(包含n2n^2n2个像素),那么每个像素的光流满足相同的方程。对于这个窗口内的所有像素,我们可以构建以下方程组:
{Ix1u+Iy1v=−It1Ix2u+Iy2v=−It2⋮Ixnu+Iynv=−Itn\left\{\begin{matrix} I_{x1}u+I_{y1}v=-I_{t1}\\ I_{x2}u+I_{y2}v=-I_{t2}\\ \vdots \\ I_{xn}u+I_{yn}v=-I_{tn} \end{matrix}\right.⎩⎨⎧Ix1u+Iy1v=−It1Ix2u+Iy2v=−It2⋮Ixnu+Iynv=−Itn
将上述方程组转为矩阵形式:
[Ix1Iy1Ix2Iy2⋮⋮IxnIyn][uv]=−[It1It2⋮Itn]\begin{bmatrix} I_{x1} & I_{y1}\\ I_{x2} & I_{y2}\\ \vdots &\vdots \\ I_{xn} &I_{yn} \end{bmatrix}\begin{bmatrix} u\\ v \end{bmatrix}=-\begin{bmatrix} I_{t1}\\ I_{t2}\\ \vdots\\ I_{tn} \end{bmatrix}Ix1Ix2⋮IxnIy1Iy2⋮Iyn[uv]=−It1It2⋮Itn
令左边矩阵为AAA,中间矩阵为xxx,右边矩阵为bbb,上述公式转为:
Ax=bAx=bAx=b
利用最小二乘法的解法,我们可以得到uuu和vvv的解:
x=(ATA)−1ATbx=(A^TA)^{-1}A^{T}bx=(ATA)−1ATb
观察上述公式可以发现一个问题:ATAA^TAATA一定有逆吗?参看第五节。
五、孔径问题
5.1 直观理解
想象你透过一个小孔(比如一根吸管)去观察一条运动的直线。如果这条直线向右上方移动,你在小孔里看到的只是直线的一小段。由于你只能看到局部信息,你会发现:
- 直线沿着垂直于自身的方向移动时,亮度会明显变化;
- 但如果直线沿着平行于自身的方向移动时,局部的亮度看起来几乎不变。
结果就是:
你无法仅凭小孔里的这一小段直线判断运动的真实方向,只能感知到垂直于边缘的运动,而沿边缘方向的运动信息丢失。
这就是“孔径问题”的由来。
5.2 数学角度
光流基本方程是:
Ixu+Iyv+It=0I_xu+I_yv+I_t=0Ixu+Iyv+It=0
这是一个一元约束(一条方程),但我们有两个未知数(u,v)(u,v)(u,v)。
结果是:我们只能确定光流在图像梯度方向上的分量,而沿着等梯度方向的分量无法确定。
举个例子:
- 如果图像中某个区域是纯水平边缘(亮度只随 y 变化),则Ix=0,Iy≠0I_x=0,I_y \neq 0Ix=0,Iy=0
- 则方程变成Iyv+It=0I_yv+I_t=0Iyv+It=0。这时候我们只能解出vvv(垂直方向的运动),而uuu(水平方向的运动)完全不受约束。
- 这就是孔径问题:缺少运动方向的完整信息。
那么与ATAA^TAATA是否可逆有什么关系呢?
我们先考虑一下有哪些情况ATAA^TAATA不可逆:
- 像素的梯度信息缺失或重复:如果图像中的某个区域(或多个区域)的梯度信息是重复的或无效的,那么矩阵的列会变得线性相关。例如,如果在某个区域内图像亮度完全不变化(如纯白色区域),那么,这意味着我们无法从该像素中提取任何有用的运动信息,导致梯度矩阵的列是线性相关的。
- 没有足够的运动信息:在一些特定情况下,比如图像中存在单一的边缘(比如水平或垂直边缘),我们只能检测到沿边缘方向的运动,而无法感知到垂直于边缘方向的运动。这会导致方向的梯度相同或相互平行,进而使得矩阵变得奇异(不可逆)。
- 局部区域的梯度信息不足:如果选择的局部窗口区域太小,导致该区域内的图像梯度几乎没有变化,也可能导致的列线性相关。例如,如果选择一个只有一条直线的区域,那么该区域内的梯度信息就没有足够的多样性来推测所有方向的运动。
是不是有点眼熟,好像我们刚刚在直观理解里面提到过一些东西?没错,孔径问题是在一定程度上可以用ATAA^TAATA不可逆来解释的。那么ATAA^TAATA不可逆会出现什么情况呢?可能会出现多解,也就是不能准确估计运动方向。
5.3 解决方法
既然ATAA^TAATA不可逆会出现孔径问题,那么我们不用ATAA^TAATA不可逆的地方不就行了?
因此我们可以选择一些角点,这样保证ATAA^TAATA可逆,就可以保证光流估计运动方向的精度了。