【SLAM】光流 - LK光流 - 金字塔分层LK光流

news2024/10/5 18:29:40

在SLAM的视觉里程计中,比较常用的就是特征点法直接法。而直接法中,光流则是其中的重点内容,比如LSD-SLAM中就使用到了光流的方法。本文将会就光流的理论原理、公式推导进行详细的剖析,以帮助读者深刻地理解。


光流算法

光流是关于视域中的物体运动检测中的概念,它用来描述相对于观察者的运动所造成的观测目标、表面或边缘。

简单来讲,光流描述了场景中物体运动在视觉中的变化。光流的概念,由Gibson在1950年提出,其通过相邻帧之间像素点的对应关系计算像素点的瞬时速度,从而描述物体信息

为了应用光流计算物体运动法,相邻帧需要满足两个假设:

  • 灰度不变:两个间隔帧之间描述相同目标的像素点的灰度需要保持恒定
  • 运动较小:两个间隔帧之间描述相同目标的像素点并没有发生剧烈变化

假设图像上一个像素点 ( x , y ) (x, y) (x,y),它在时刻 t t t的亮度为 I ( x , y , t ) I(x, y, t) I(x,y,t),用 u ( x , y ) u(x, y) u(x,y) v ( x , y ) v(x, y) v(x,y)表示该点光流在水平和垂直方向上的速度分量:

u = d x d t u=\frac{\mathrm{d} x}{\mathrm{d} t} u=dtdx

u = d y d t u=\frac{\mathrm{d} y}{\mathrm{d} t} u=dtdy

在经过时间间隔 d t dt dt之后,该点的对应点的亮度变为 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 + 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 + d x , y + d y , t + d t ) ≈ I ( x , y , t ) + ∂ I ∂ x d x + ∂ I ∂ y d y + ∂ I ∂ t d t I(x+dx, y+dy, t+dt) \approx I(x, y, t) + \frac{\partial I}{\partial x} dx + \frac{\partial I}{\partial y} dy + \frac{\partial I}{\partial t} dt I(x+dx,y+dy,t+dt)I(x,y,t)+xIdx+yIdy+tIdt

根据上面两个式子,可以得到:

∂ I ∂ x d x + ∂ I ∂ y d y + ∂ I ∂ t d t = 0 \frac{\partial I}{\partial x} dx + \frac{\partial I}{\partial y} dy + \frac{\partial I}{\partial t} dt = 0 xIdx+yIdy+tIdt=0

d t dt dt足够小,趋向于0时:

∂ I ∂ x d x d t + ∂ I ∂ y d y d t + ∂ I ∂ t = 0 \frac{\partial I}{\partial x} \frac{dx}{dt} + \frac{\partial I}{\partial y} \frac{dy}{dt} + \frac{\partial I}{\partial t} = 0 xIdtdx+yIdtdy+tI=0

− ∂ I ∂ t = ∂ I ∂ x d x d t + ∂ I ∂ y d y d t = ∂ I ∂ x u + ∂ I ∂ y v -\frac{\partial I}{\partial t} = \frac{\partial I}{\partial x} \frac{dx}{dt} + \frac{\partial I}{\partial y} \frac{dy}{dt} = \frac{\partial I}{\partial x} u + \frac{\partial I}{\partial y} v tI=xIdtdx+yIdtdy=xIu+yIv

− I t = I x d x d t + I y d y d t = I x u + I y v -I_{t} = I_{x} \frac{dx}{dt} + I_{y} \frac{dy}{dt} = I_{x} u + I_{y} v It=Ixdtdx+Iydtdy=Ixu+Iyv

− I t = [ I x I y ] [ u v ] -I_{t} = \begin{bmatrix} I_{x} & I_{y} \end{bmatrix} \begin{bmatrix} u \\ v \end{bmatrix} It=[IxIy][uv]

其中, I x I_{x} Ix I y I_{y} Iy为图像在 ( x , y ) (x, y) (x,y)处的梯度, I t I_{t} It为图像在 ( x , y ) (x, y) (x,y)处关于时间 t t t的导数 I t ≈ I ( x , y , t ) − I ( x , y , t − 1 ) I_{t} \approx I(x, y, t) - I(x, y, t-1) ItI(x,y,t)I(x,y,t1)

这就是基本的光流约束方程。

不过对于某一个像素点而言,存在两个未知量 ( u , v ) (u, v) (u,v),但只有一个方程是无法求解的。

先小结一下光流的两个假设:

  1. 灰度不变:图像场景中的目标的像素在帧间运动时灰度保持不变。用于得到光流法基本方程;
  2. 运动较小:保证灰度可以对位置求偏导(换句话说,小运动情况下我们才能用前后顿之间单位位置变化引起的灰度变化去近似灰度对位置的偏导数),这也是光流法不可或缺的假定。

LK光流

LK光流在基本的光流算法基础上增加了一个假设:

  • 邻域相同:每个像素点的局部邻域内的所有像素点的光流保持一致

LK光流证法一

由于基本的光流约束方程中,一个方程两个未知量没法求解。LK光流算法考虑到了像素点的邻域,将问题转变成了计算某些点集的光流,联立多个方程,从而解决了这个问题。

假设在邻域 R R R n n n个像素点,光流保持一致,可以得到:

− I t k = [ I x k I y k ] [ u v ] , k ∈ R -I_{tk} = \begin{bmatrix} I_{xk} & I_{yk} \end{bmatrix} \begin{bmatrix} u \\ v \end{bmatrix},k\in R Itk=[IxkIyk][uv],kR

即:

[ I x 1 I y 1 I x 2 I y 2 . . . . . . I x n I y n ] [ u v ] = [ − I t 1 − I t 2 . . . − I t n ] \begin{bmatrix} I_{x1} & I_{y1} \\ I_{x2} & I_{y2} \\ ... & ... \\ I_{xn} & I_{yn} \end{bmatrix} \begin{bmatrix} u \\ v \end{bmatrix} = \begin{bmatrix} -I_{t1} \\ -I_{t2} \\ ... \\ -I_{tn} \end{bmatrix} Ix1Ix2...IxnIy1Iy2...Iyn [uv]= It1It2...Itn

为了简单起见,记作:

A [ u v ] = b A\begin{bmatrix} u \\ v \end{bmatrix} = b A[uv]=b

这是一个超正定方程,一种解法就是计算其最小二乘解。即,当 A T A A^{T}A ATA可逆时:

[ u v ] = ( A T A ) − 1 A T b \begin{bmatrix} u \\ v \end{bmatrix} = (A^{T}A)^{-1}A^{T}b [uv]=(ATA)1ATb

带入:

[ u v ] = [ ∑ i = 1 n I x i 2 ∑ i = 1 n I x i I y i ∑ i = 1 n I x i I y i ∑ i = 1 n I y i 2 ] − 1 [ − ∑ i = 1 n I x i I t − ∑ i = 1 n I y i I t ] \begin{bmatrix} u \\ v \end{bmatrix} = \begin{bmatrix} \sum_{i=1}^{n} I_{xi}^{2} & \sum_{i=1}^{n} I_{xi}I_{yi} \\ \sum_{i=1}^{n} I_{xi}I_{yi} & \sum_{i=1}^{n} I_{yi}^{2} \end{bmatrix} ^{-1}\begin{bmatrix} -\sum_{i=1}^{n}I_{xi}I_{t} \\ -\sum_{i=1}^{n}I_{yi}I_{t} \end{bmatrix} [uv]=[i=1nIxi2i=1nIxiIyii=1nIxiIyii=1nIyi2]1[i=1nIxiIti=1nIyiIt]

一般来说,在图像中沿两个方向都有像素变化的区域(例如角点),其对应的 A T A A^{T}A ATA是可逆的;相反的,在灰度变化很小的区域,一般对应的 A T A A^{T}A ATA是不可逆的

这限制了LK光流法的使用范围,这也是被称为稀疏光流法的主要原因。

LK光流证法二

假设相邻的两幅图像 I I I J J J,对于 I I I中像素点 u = [ u x u y ] T u=\begin{bmatrix} u_{x} & u_{y} \end{bmatrix}^{T} u=[uxuy]T,需要在图像 J J J中找到像素点 v = u + d = [ u x + d x u y + d y ] T v=u+d=\begin{bmatrix} u_{x}+d_{x} & u_{y}+d_{y} \end{bmatrix}^{T} v=u+d=[ux+dxuy+dy]T,使其最为相似(灰度值差別最小)。我们把 d = [ d x d y ] T d=\begin{bmatrix} d_{x} & d_{y} \end{bmatrix}^{T} d=[dxdy]T称为在 u u u处的光流。

当然为了求解,需要引入一个具有相同光流的邻域,其大小使用 w x w_{x} wx w y w_{y} wy两个参数表示。则求解 d d d转换为使下述目标函数取最小值的优化问题:

ε ( d ) = ε ( d x , d y ) = ∑ x = u x − w x u x + w x ∑ y = u y − w y u y + w y ( I ( x , y ) − J ( x + d x , y + d y ) ) 2 \varepsilon (d)=\varepsilon (d_{x}, d_{y})=\sum_{x=u_{x}-w_{x}}^{u_{x}+w_{x}}\sum_{y=u_{y}-w_{y}}^{u_{y}+w_{y}}(I(x, y)-J(x+d_{x}, y+d_{y}))^{2} ε(d)=ε(dx,dy)=x=uxwxux+wxy=uywyuy+wy(I(x,y)J(x+dx,y+dy))2

在最优解处导数为0,则得到:

∂ ε ( d ) ∂ d = − 2 ∑ x = u x − w x u x + w x ∑ y = u y − w y u y + w y ( I ( x , y ) − J ( x + d x , y + d y ) ) [ ∂ J ∂ x ∂ J ∂ y ] \frac{\partial \varepsilon (d)}{\partial d}=-2\sum_{x=u_{x}-w_{x}}^{u_{x}+w_{x}}\sum_{y=u_{y}-w_{y}}^{u_{y}+w_{y}}(I(x, y)-J(x+d_{x}, y+d_{y}))\begin{bmatrix} \frac{\partial J}{\partial x} & \frac{\partial J}{\partial y} \end{bmatrix} dε(d)=2x=uxwxux+wxy=uywyuy+wy(I(x,y)J(x+dx,y+dy))[xJyJ]

使用一阶泰勒展开,得到:

∂ ε ( d ) ∂ d ≈ − 2 ∑ x = u x − w x u x + w x ∑ y = u y − w y u y + w y ( I ( x , y ) − J ( x , y ) − [ ∂ J ∂ x ∂ J ∂ y ] [ d x d y ] ) [ ∂ J ∂ x ∂ J ∂ y ] \frac{\partial \varepsilon (d)}{\partial d} \approx -2\sum_{x=u_{x}-w_{x}}^{u_{x}+w_{x}}\sum_{y=u_{y}-w_{y}}^{u_{y}+w_{y}}(I(x, y)-J(x, y)-\begin{bmatrix} \frac{\partial J}{\partial x} & \frac{\partial J}{\partial y} \end{bmatrix} \begin{bmatrix} d_{x} \\ d_{y} \end{bmatrix})\begin{bmatrix} \frac{\partial J}{\partial x} & \frac{\partial J}{\partial y} \end{bmatrix} dε(d)2x=uxwxux+wxy=uywyuy+wy(I(x,y)J(x,y)[xJyJ][dxdy])[xJyJ]

其中, I ( x , y ) − J ( x , y ) I(x, y)-J(x, y) I(x,y)J(x,y)是像素点 ( x , y ) (x, y) (x,y)关于时间的图像导数,记作 δ I \delta I δI [ ∂ J ∂ x ∂ J ∂ y ] \begin{bmatrix} \frac{\partial J}{\partial x} & \frac{\partial J}{\partial y} \end{bmatrix} [xJyJ]是图像 J J J在像素点 ( x , y ) (x, y) (x,y)处的梯度,将其近似为 [ ∂ I ∂ x ∂ I ∂ y ] \begin{bmatrix} \frac{\partial I}{\partial x} & \frac{\partial I}{\partial y} \end{bmatrix} [xIyI],并记 ∇ I = [ ∂ I ∂ x ∂ I ∂ y ] T \nabla I=\begin{bmatrix} \frac{\partial I}{\partial x} & \frac{\partial I}{\partial y} \end{bmatrix}^{T} I=[xIyI]T

1 2 ∂ ε ( d ) ∂ d ≈ ∑ x = u x − w x u x + w x ∑ y = u y − w y u y + w y ( ∇ I T d − δ I ) ∇ I T \frac{1}{2}\frac{\partial \varepsilon (d)}{\partial d} \approx \sum_{x=u_{x}-w_{x}}^{u_{x}+w_{x}}\sum_{y=u_{y}-w_{y}}^{u_{y}+w_{y}}(\nabla I^{T}d-\delta I)\nabla I^{T} 21dε(d)x=uxwxux+wxy=uywyuy+wy(ITdδI)IT

需要注意, ∇ I T d − δ I \nabla I^{T}d-\delta I ITdδI为标量,所以:

1 2 [ ∂ ε ( d ) ∂ d ] T ≈ ∑ x = u x − w x u x + w x ∑ y = u y − w y u y + w y ( ∇ I T d − δ I ) ∇ I \frac{1}{2}\begin{bmatrix}\frac{\partial \varepsilon (d)}{\partial d}\end{bmatrix}^{T} \approx \sum_{x=u_{x}-w_{x}}^{u_{x}+w_{x}}\sum_{y=u_{y}-w_{y}}^{u_{y}+w_{y}}(\nabla I^{T}d-\delta I)\nabla I 21[dε(d)]Tx=uxwxux+wxy=uywyuy+wy(ITdδI)I

1 2 [ ∂ ε ( d ) ∂ d ] T ≈ ∑ x = u x − w x u x + w x ∑ y = u y − w y u y + w y [ I x 2 I x I y I x I y I y 2 ] d − ∑ x = u x − w x u x + w x ∑ y = u y − w y u y + w y [ δ I ⋅ I x δ I ⋅ I y ] \frac{1}{2}\begin{bmatrix}\frac{\partial \varepsilon (d)}{\partial d}\end{bmatrix}^{T} \approx \sum_{x=u_{x}-w_{x}}^{u_{x}+w_{x}}\sum_{y=u_{y}-w_{y}}^{u_{y}+w_{y}}\begin{bmatrix} I_{x}^{2} & I_{x}I_{y} \\ I_{x}I_{y} & I_{y}^{2} \end{bmatrix}d-\sum_{x=u_{x}-w_{x}}^{u_{x}+w_{x}}\sum_{y=u_{y}-w_{y}}^{u_{y}+w_{y}}\begin{bmatrix} \delta I \cdot I_{x} \\ \delta I \cdot I_{y} \end{bmatrix} 21[dε(d)]Tx=uxwxux+wxy=uywyuy+wy[Ix2IxIyIxIyIy2]dx=uxwxux+wxy=uywyuy+wy[δIIxδIIy]

记:

G = ∑ x = u x − w x u x + w x ∑ y = u y − w y u y + w y [ I x 2 I x I y I x I y I y 2 ] G=\sum_{x=u_{x}-w_{x}}^{u_{x}+w_{x}}\sum_{y=u_{y}-w_{y}}^{u_{y}+w_{y}}\begin{bmatrix} I_{x}^{2} & I_{x}I_{y} \\ I_{x}I_{y} & I_{y}^{2} \end{bmatrix} G=x=uxwxux+wxy=uywyuy+wy[Ix2IxIyIxIyIy2]

b = ∑ x = u x − w x u x + w x ∑ y = u y − w y u y + w y [ δ I ⋅ I x δ I ⋅ I y ] b=\sum_{x=u_{x}-w_{x}}^{u_{x}+w_{x}}\sum_{y=u_{y}-w_{y}}^{u_{y}+w_{y}}\begin{bmatrix} \delta I \cdot I_{x} \\ \delta I \cdot I_{y} \end{bmatrix} b=x=uxwxux+wxy=uywyuy+wy[δIIxδIIy]

则:

d = G − 1 b d=G^{-1}b d=G1b

两种证法

仔细观察两种证法的结果,可以看出最终得到的结果是一样的。现在梳理一下光流计算中,需要用到的值:

  • I x I_{x} Ix I y I_{y} Iy:图像在 ( x , y ) (x, y) (x,y)处的梯度;

  • δ I \delta I δI I t I_{t} It:图像在 ( x , y ) (x,y) (x,y)处对时间的变化。


迭代求解LK

有时候我们为了求得更加精确的 d d d,可以使用迭代求解的方式更新 d d d

使用 K ( K ≥ 1 ) K(K\ge 1) K(K1)代表迭代次数,对于第 k k k次迭代,前面的第 k − 1 k-1 k1次迭代用于提供初始值 d k − 1 = [ d x k − 1 d y k − 1 ] T d^{k-1}=\begin{bmatrix} d_{x}^{k-1} & d_{y}^{k-1}\end{bmatrix}^{T} dk1=[dxk1dyk1]T,这里把它作为图像 J J J移动的初始值,移动之后得到图像 J k J_{k} Jk,且 J k ( x , y ) = J ( x + d x k − 1 , y + d y k − 1 ) J_{k}(x,y)=J(x+d_{x}^{k-1},y+d_{y}^{k-1}) Jk(x,y)=J(x+dxk1,y+dyk1),之后的问题就是计算优化变量 η k = [ η x k η y k ] T \eta ^{k}=\begin{bmatrix} \eta_{x}^{k} & \eta_{y}^{k}\end{bmatrix}^{T} ηk=[ηxkηyk]T,使下面的目标函数最小:

ε k ( η k ) = ε ( η x k , η y k ) = ∑ x = u x − w x u x + w x ∑ y = u y − w y u y + w y ( I ( x , y ) − J k ( x + η x k , y + η y k ) ) 2 \varepsilon^{k} (\eta^{k})=\varepsilon (\eta_{x}^{k}, \eta_{y}^{k})=\sum_{x=u_{x}-w_{x}}^{u_{x}+w_{x}}\sum_{y=u_{y}-w_{y}}^{u_{y}+w_{y}}(I(x, y)-J_{k}(x+\eta_{x}^{k}, y+\eta_{y}^{k}))^{2} εk(ηk)=ε(ηxk,ηyk)=x=uxwxux+wxy=uywyuy+wy(I(x,y)Jk(x+ηxk,y+ηyk))2

根据上文的第二种证法的推导形式,最终可以整理为:

η k = G − 1 b k \eta^{k}=G^{-1}b_{k} ηk=G1bk

注意:这里的 G G G在迭代计算中保持不变,因此只需要计算一次 b k b_{k} bk每次需要重新计算,之后第 k k k次迭代的结果 d k = d k − 1 + η k d_{k}=d_{k-1}+\eta^{k} dk=dk1+ηk

当迭代次数达到设定次数,或者计算得到的 η k \eta^{k} ηk的大小小于设定阀值时,迭代计算结束


金字塔LK

这里重新把LK中的三条假设拿出来:

  1. 同一个空间点的像素灰度值,在各个图像中固定不变;
  2. 相邻帧间物体的运动足够小;
  3. 邻域具有相同的光流。

这三条假设都是强假设,但实际场景中尤其是第二条很难满足。但是对于我们一直在用的一阶泰勒展开,只有在变量变化很小的情况下才会成立。但如果帧间像素点的运动比较大时,泰勒展开就不能适用了。

原理

金字塔LK主要就是用来解决帧间变化较大的问题

举例来说,对于分辨率为 800 × 600 800\times 600 800×600的图像,若两帧间某个像素点的运动为 40 × 40 40\times 40 40×40,当把图像分辨率改为 400 × 300 400\times 300 400×300时,运动变为 20 × 20 20\times 20 20×20。以此类推,总能在图像像素降低到一定程度时,原本较大的像素间运动变得足够小,能够使用泰勒展开式进行计算。

把原始图像作为第 0 0 0层,宽高缩小 2 L 2^{L} 2L倍的图像作为第 L L L层,多层图像组织起来,就像是一个金字塔。

请添加图片描述

其中计算时需要注意一些小问题:

  1. 在图像降采样之前通常使用低通滤波器滤波,防止降采样后发生锯齿现象,其中就会碰到对于图像边界像素如何滤波的问题;
  2. 原始图像尺寸无法保证宽高严格满足整除 2 L 2^{L} 2L,因此降采样后新的图像的宽高如何确定,有不同的解决方法。可以对原始图像调整宽高满足整除 2 L 2^{L} 2L,或者用下面的公式确定新图像的宽高:

n x L ≤ n x L − 1 + 1 2 n_{x}^{L}\le \frac{n_{x}^{L-1}+1}{2} nxL2nxL1+1

n y L ≤ n y L − 1 + 1 2 n_{y}^{L}\le \frac{n_{y}^{L-1}+1}{2} nyL2nyL1+1

其中, n x L n_{x}^{L} nxL n y L n_{y}^{L} nyL分别代表第 L L L层图像的宽和高。

接下来,就是利用金字塔图像从最高的第 L L L层图像,开始向下迭代计算每层中对应像素点的位移。其实这部分操作和迭代求解LK部分的原理相同。

使用 I L I^{L} IL J L J^{L} JL代表图像 I I I J J J的第 L L L层金字塔图像,假设 u = [ u x u y ] T u=\begin{bmatrix}u_{x} & u_{y}\end{bmatrix}^{T} u=[uxuy]T为图像 I I I中需要跟踪的像素点坐标,则在 I L I^{L} IL中对应的坐标 u L = [ u x L u y L ] T = u / 2 L u^{L}=\begin{bmatrix}u_{x}^{L} & u_{y}^{L}\end{bmatrix}^{T}=u/2^{L} uL=[uxLuyL]T=u/2L

首先在最高层 L m L_{m} Lm层计算光流大小,把它作为第 L m − 1 L_{m}-1 Lm1层光流的初始值,再计算该层的光流大小;之后把得到的光流大小作为 L m − 2 L_{m}-2 Lm2层光流大小的初始值。以此类推,直至第 0 0 0层图像,得到光流的最终结果。

以第 L + 1 L+1 L+1层到第 L L L层之间的计算为例,详细说明下计算流程。

假设通过第 L + 1 L+1 L+1层计算得到第 L L L层光流大小的初始值为 g L = [ g x L g y L ] T g^{L}=\begin{bmatrix}g_{x}^{L} & g_{y}^{L}\end{bmatrix}^{T} gL=[gxLgyL]T,那么我们要做的就是求得 d L = [ d x L d y L ] d^{L}=\begin{bmatrix}d_{x}^{L} & d_{y}^{L}\end{bmatrix} dL=[dxLdyL],使
下面的优化函数最小:

ε k ( d k ) = ε ( d x k , d y k ) = ∑ x = u x − w x u x + w x ∑ y = u y − w y u y + w y ( I L ( x , y ) − J L ( x + g x k + d x k , y + g y k + d y k ) ) 2 \varepsilon^{k} (d^{k})=\varepsilon (d_{x}^{k}, d_{y}^{k})=\sum_{x=u_{x}-w_{x}}^{u_{x}+w_{x}}\sum_{y=u_{y}-w_{y}}^{u_{y}+w_{y}}(I^{L}(x, y)-J^{L}(x+g_{x}^{k}+d_{x}^{k}, y+g_{y}^{k}+d_{y}^{k}))^{2} εk(dk)=ε(dxk,dyk)=x=uxwxux+wxy=uywyuy+wy(IL(x,y)JL(x+gxk+dxk,y+gyk+dyk))2

由于 g L = [ g x L g y L ] T g^{L}=\begin{bmatrix}g_{x}^{L} & g_{y}^{L}\end{bmatrix}^{T} gL=[gxLgyL]T已经比较接近真实值了,所以这里我们很有底气地适用泰勒展开处理 J L ( x + g x k + d x k , y + g y k + d y k ) J^{L}(x+g_{x}^{k}+d_{x}^{k}, y+g_{y}^{k}+d_{y}^{k}) JL(x+gxk+dxk,y+gyk+dyk),后面的处理和常规LK类似,不再赘述。

计算得到 d L = [ d x L d y L ] d^{L}=\begin{bmatrix}d_{x}^{L} & d_{y}^{L}\end{bmatrix} dL=[dxLdyL]后,定义 g L − 1 = 2 ( g L + d L ) g^{L-1}=2(g^{L}+d^{L}) gL1=2(gL+dL)作为第 L − 1 L-1 L1层光流大小的初始值,重复上述计算过程逐层迭代计算即可。特别的,在最高层 L m L_{m} Lm处,定义 g L m = [ 0 0 ] T g^{L_{m}}=\begin{bmatrix}0 & 0\end{bmatrix}^{T} gLm=[00]T

通过观察我们可以发现,最终计算得到的光流 d = ∑ L = 0 L m 2 L d L d=\sum_{L=0}^{L_{m}}2^{L}d^{L} d=L=0Lm2LdL。这个公式表明虽然原始图像中像素位移比较大,但对于每层图像来说对应的 d L d^{L} dL都比较小,因此可以使用泰勒展开简化求解

这里的金字塔LK的流程就有点像:准确值=估计值+残差。估计值由上一层金字塔提供,残差在本层中适用迭代法求出最佳的残差。估计值的初始值为顶层金字塔光流 [ 0 0 ] T \begin{bmatrix}0 & 0\end{bmatrix}^{T} [00]T,残差在每层金字塔都会初始化为 [ 0 0 ] T \begin{bmatrix}0 & 0\end{bmatrix}^{T} [00]T

请添加图片描述

整体流程

现在把金字塔LK光流算法的整体流程使用伪代码梳理一遍。

目标:对于图像 I I I中的像素点 u u u,寻找在图像 J J J中灰度最相似的像素点。

Step1

为图像 I I I J J J分别建立金字塔表达 { I L } L = 0 , 1 , . . . , L m \{I^{L}\}_{L=0,1,...,L_{m}} {IL}L=0,1,...,Lm { J L } L = 0 , 1 , . . . , L m \{J^{L}\}_{L=0,1,...,L_{m}} {JL}L=0,1,...,Lm

Step2

初始化最高层光流初始值 g L m = [ 0 0 ] T g^{L_{m}}=\begin{bmatrix}0 & 0\end{bmatrix}^{T} gLm=[00]T

f o r   L = L m ; L ≥ 0 ; L − − for\ L=L_{m};L\ge 0;L-- for L=Lm;L0;L

        计算图像 I L I^{L} IL中像素点 u u u对应的位置: u L = [ u x L u y L ] = u / 2 L u^{L}=\begin{bmatrix}u_{x}^{L} & u_{y}^{L}\end{bmatrix}=u/2^{L} uL=[uxLuyL]=u/2L

        计算图像 I L I^{L} IL x x x方向地梯度: I x L ( x , y ) = I L ( x + 1 , y ) − I L ( x − 1 , y ) 2 I_{x}^{L}(x,y)=\frac{I^{L}(x+1,y)-I^{L}(x-1,y)}{2} IxL(x,y)=2IL(x+1,y)IL(x1,y)

        计算图像 I L I^{L} IL y y y方向地梯度: I y L ( x , y ) = I L ( x , y + 1 ) − I L ( x , y − 1 ) 2 I_{y}^{L}(x,y)=\frac{I^{L}(x,y+1)-I^{L}(x,y-1)}{2} IyL(x,y)=2IL(x,y+1)IL(x,y1)

        计算空间矩阵 G = ∑ x = u x L − w x u x L + w x ∑ y = u y L − w y u y L + w y [ I x L 2 I x L I y L I x L I y L I y L 2 ] G=\sum_{x=u_{x}^{L}-w_{x}}^{u_{x}^{L}+w_{x}}\sum_{y=u_{y}^{L}-w_{y}}^{u_{y}^{L}+w_{y}}\begin{bmatrix} I_{x}^{L^{2}} & I_{x}^{L}I_{y}^{L} \\ I_{x}^{L}I_{y}^{L} & I_{y}^{L^{2}} \end{bmatrix} G=x=uxLwxuxL+wxy=uyLwyuyL+wy[IxL2IxLIyLIxLIyLIyL2]

        初始化迭代LK初始值: d 0 = [ 0 0 ] T d^{0}=\begin{bmatrix}0 & 0\end{bmatrix}^{T} d0=[00]T

         f o r   k = 1 ; k ≤ K ∣ ∣ f a b s f ( η ) < t h r e s h o l d ; k + + for\ k=1;k\le K||fabsf(\eta)<threshold;k++ for k=1;kK∣∣fabsf(η)<threshold;k++

                计算图像差异: δ I k ( x , y ) = I L ( x , y ) − J L ( x + g x L + d x k − 1 , y + g y L + d y k − 1 ) \delta I^{k}(x,y)=I^{L}(x,y)-J^{L}(x+g_{x}^{L}+d_{x}^{k-1}, y+g_{y}^{L}+d_{y}^{k-1}) δIk(x,y)=IL(x,y)JL(x+gxL+dxk1,y+gyL+dyk1)

                计算匹配差异向量: b k = ∑ x = u x L − w x u x L + w x ∑ y = u y L − w y u y L + w y [ δ I k ( x , y ) ⋅ I x ( x , y ) δ I k ( x , y ) ⋅ I y ( x , y ) ] b_{k}=\sum_{x=u_{x}^{L}-w_{x}}^{u_{x}^{L}+w_{x}}\sum_{y=u_{y}^{L}-w_{y}}^{u_{y}^{L}+w_{y}}\begin{bmatrix} \delta I^{k}(x,y) \cdot I_{x}(x,y) \\ \delta I^{k}(x,y) \cdot I_{y}(x,y) \end{bmatrix} bk=x=uxLwxuxL+wxy=uyLwyuyL+wy[δIk(x,y)Ix(x,y)δIk(x,y)Iy(x,y)]

                计算光流: η k = G − 1 b k \eta^{k}=G^{-1}b_{k} ηk=G1bk

                为下一次迭代提供初始值: d k = d k − 1 + η k d^{k}=d^{k-1}+\eta^{k} dk=dk1+ηk

         结束 k k k上的迭代

         得到第 L L L层图像上的光流优化值: d L = d k d^{L}=d^{k} dL=dk

         为第 L − 1 L-1 L1层光流提供光流初始值: g L − 1 = 2 ( g L + d L ) g^{L-1}=2(g^{L}+d^{L}) gL1=2(gL+dL)

结束 L L L上的迭代

最终计算得到光流 d = g 0 + d 0 d=g^{0}+d^{0} d=g0+d0

图像 J J J中对应坐标 v = u + d v=u+d v=u+d

补充

  1. 实际计算中得到的类似于 ( x + g x L + d x k − 1 , y + g y L + d y k − 1 ) (x+g_{x}^{L}+d_{x}^{k-1}, y+g_{y}^{L}+d_{y}^{k-1}) (x+gxL+dxk1,y+gyL+dyk1)往往不是整数点像素,所以其像素灰度值需要插值计算得到,一般可以用双线性插值计算;
  2. 在对图像进行类似于卷积操作时(求梯度、高斯滤波等),需要注意位于图像边界处像素点的处理,这里会发生像素越界,需要采用一些方法处理;
  3. 使用光流法计算匹配点时,当 v = u + d v=u+d v=u+d超出图像 J J J时,我们判定为匹配失败:不过即使 v = u + d v=u+d v=u+d位于图像 J J J中,也未必是正确的匹配点,毕竟光流法的前提假设过于理想。且该方法中未提供依据判断匹配是否成功,需要其他的方法来滤除该方法计算得到的误匹配,一种常用的方法是基于RANSAC计算两帧图像的变换矩阵。

应用:基于中值流的目标跟踪

TLD算法的跟踪模块借鉴了中值流算法,用于上一帧目标 b b bb bb到当前帧目标 b b bb bb的预测。

中值流算法的流程如下:

  1. 初始化第 t t t帧中的目标 b b bb bb b b bb bb内均匀取点用于跟踪。TLD的作者在目标 b b bb bb内均匀选取了100个像素点作为跟踪点;
  2. 利用LK光流法确定第 t t t帧与第 t + 1 t+1 t+1帧之间的光流情况。用预测到的第 t + 1 t+1 t+1帧中这些点的位置,反向利用LK光流法得到这些点的后向跟踪轨迹。这样,每个跟踪点都会在第一帧中由前向和后向得到两个位置,这两个位置的欧式距离就作为每个点的 F B e r r o r FBerror FBerror
  3. 计算每个跟踪点在两帧之间的匹配度(即计算 n c c ncc ncc的值);
  4. 利用所有的跟踪点预测 b b bb bb的变化有失妥当,因为有的跟踪点可能并不对 b b bb bb的变化起作用,甚至会影响 b b bb bb的预测。所以需要筛选得到一部分可靠的点。这也就是中值流算法的核心部分将这些跟踪点在相邻两顿之间的 F B e r r o r FBerror FBerror n c c ncc ncc值进行排序,得到中值,利用中值,得到同时小于 F B e r r o r FBerror FBerror中值与 n c c ncc ncc中值的特征点(分别过滤 50 % 50\% 50%跟踪点),这样保留不到 50 % 50\% 50%的点作为跟踪成功的点
  5. 利用剩下的这些点来预测上一顿的目标 b b bb bb在当前帧的位置和大小

位置(位移估计):用保留的这些点的 ( x , y ) (x,y) (x,y)位移的中值作为目标 b b bb bb的位移

大小(尺度估计):计算上一帧中保留的这些点之间的欧氏距离 d 1 d1 d1,当前帧中保留的这些点之间的欧氏距离 d 2 d2 d2。并以此得到伸缩比的中值 s s s s = m e d i a n ( d 2 / d 1 ) s=median(d2/d1) s=median(d2/d1),这个伸缩比的中值作为目标 b b bb bb尺度伸缩值。


OpenCV接口

CV_EXPORTS_W void calcOpticalFlowPyrLK( InputArray prevImg, InputArray nextImg,
                           InputArray prevPts, CV_OUT InputOutputArray nextPts,
                           OutputArray status, OutputArray err,
                           Size winSize=Size(21,21), int maxLevel=3,
                           TermCriteria criteria=TermCriteria(
                            TermCriteria::COUNT+TermCriteria::EPS,
                            30, 0.01),
                           double derivLambda=0.5,
                           int flags=0,
                           double minEigThreshold=1e-4);

各个参数代表的含义如下:

  • prevImg
    你的标定图像的灰度图
  • nextImg
    你想搜寻的图像的灰度图
  • prevPts
    输入的标定图像的特征点(可以是其他特征点检测方法找到的点)
  • nextPts
    输出场景的特征点
  • status
    输出状态向量(无符号char),如果在当前图像中能够光流得到标定的特征点位置改变,则设置status的对应位置为1,否则设置为0
  • err
    输出错误向量;向量的每个元素被设为相应特征的一个错误,误差测量的类型可以在flags参数中设置;如果流不被发现然后错误未被定义(使用status(状态)参数找到此情形)。
  • winSize
    在每个金字塔水平搜寻窗口的尺寸
  • maxLevel
    金字塔的高度,初始为3层

相关阅读

  • Pyramidal Implementation of the Lucas Kanade Feature Tracker Description of the algorithm
  • 金字塔LK光流法数学原理学习笔记
  • 总结:光流–LK光流–基于金字塔分层的LK光流–中值流
  • 图像金字塔(高斯金字塔 与 拉普拉斯金字塔)
  • 多元函数的泰勒(Taylor)展开式
  • 光流金字塔calcOpticalFlowPyrLK进行特征点跟踪

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/928906.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

每日一练 | 华为认证真题练习Day103

1、网络设备发送的IPv6报文时&#xff0c;会首先将报文长度和NTU值进行对比&#xff0c;如果大于MTU值&#xff0c;则直接丢弃。 A. 对 B. 错 2、路由器接口输出信息如下&#xff0c;则此接口可以接收哪些组播地址的数据&#xff1f; &#xff08;多选&#xff09; A. FF02::…

中国储能行业研究报告,光伏和风电领域装机量迅速增长

随着科学技术的进步&#xff0c;储能工业对我们的生活产生了深远的影响。电池技术的突破使得手机使用寿命更长&#xff0c;家庭储能系统使得能源管理更加智能和高效。人们通过对于储能的需求进行不断发展增长&#xff0c;将目光投向更环保可持续的解决问题方案。这个行业的发展…

计算机丢失msvcp140.dll是什么意思,要怎么处理呢?

今天&#xff0c;我将和大家探讨一个关于计算机的问题——“计算机丢失msvcp140.dll是什么意思&#xff0c;要怎么处理呢&#xff1f;”这个问题可能会在很多使用计算机的朋友中遇到。希望通过今天的演讲&#xff0c;能够帮助大家解决这个困扰。 首先&#xff0c;我们来了解一…

DevOps中的持续测试优势和工具

持续测试 DevOps中的持续测试是一种软件测试类型&#xff0c;它涉及在软件开发生命周期的每个阶段测试软件。持续测试的目标是通过早期测试和经常测试来评估持续交付过程的每一步的软件质量。 DevOps中的持续测试流程涉及开发人员、DevOps、QA和操作系统等利益相关者。 持续…

CC++ 常用技巧

C 中的C C 是面向过程的是把整个大程序分为一个个的子函数&#xff1b;C 是面向对象的是把整个程序划分为一个个的类。C 是完全兼容C 的&#xff0c;C 是C 的子集&#xff0c;C 是C 的超集。C 又对C 做了很多补充和提升&#xff0c;因此使用C 会比使用纯C 更方便。混用C和C&am…

《软件开发的201个原则》阅读笔记 120-161条

目录 使用有效的测试完成度标准 原则122 达成有效的测试覆盖 原则123 不要在单元测试之前集成 原则 124 测量你的软件 原则125 分析错误的原因 对错不对人 原则127 好的管理比好的技术更重要 使用恰当的方法 原则 129 不要相信你读到的一切 原则130 理解客户的优先级 原…

千人千面的分析?SpeedBI数据可视化工具也很擅长

SpeedBI数据可视化工具可以实现千人千面的分析&#xff0c;通过个性化的数据展示和交互式分析功能&#xff0c;让每个人都可以根据自己的需求和业务背景进行数据分析和可视化。 SpeedBI数据可视化工具支持多维自助分析&#xff0c;可以帮助用户深入探索和分析数据。以下是Spee…

超店有数最新报告!美国TikTok小店全新洗牌?搏一把的机会到了

据传&#xff0c;TikTok美国市场的半闭环模式将于8月底关闭&#xff0c;其将在美国全力发展全闭环。也就是说&#xff0c;想要继续在TikTok美区卖货&#xff0c;必须开通TikTok小店&#xff0c;官方不给放外链了。 如果消息属实&#xff0c;全闭环模式开启&#xff0c;美国Tik…

抖音电商,从消费者体验中做增量

夜晚总是最容易emo&#xff0c;也最容易冲动的时候。 王雪临睡前刷着抖音&#xff0c;看到一家化妆品品牌在直播&#xff0c;刚好最近她想买抗老精华&#xff0c;点进去听主播小姐姐介绍一番后下了单。第二天早上起来犹豫要不要退货&#xff0c;再货比三家时&#xff0c;手机收…

stm32之DHT11

今天&#xff0c;记录一下DHT11&#xff0c;涉及到了单总线协议&#xff0c;所以先花点时间谈论一下单总线协议&#xff08;DS18B20也是用的单总线&#xff09;。 单总线协议 单总线技术的通信协议 可能这时序图就是个例子&#xff0c;ds18b20的时序图与DHT11的时序图也是不一…

服务器中了mkp勒索病毒该怎么办?勒索病毒解密,数据恢复

mkp勒索病毒算的上是一种比较常见的勒索病毒类型了。它的感染数量上也常年排在前几名的位置。所以接下来就由云天数据恢复中心的技术工程师来对mkp勒索病毒做一个分析&#xff0c;以及中招以后应该怎么办。 一&#xff0c;中了mkp勒索病毒的表现 桌面以及多个文件夹当中都有一封…

mysql基础——认识索引

一、介绍 “索引”是为了能够更快地查询数据。比如一本书的目录&#xff0c;就是这本书的内容的索引&#xff0c;读者可以通过在目录中快速查找自己想要的内容&#xff0c;然后根据页码去找到具体的章节。 二、优缺点 优势&#xff1a;以快速检索&#xff0c;减少I/O次数&am…

TMP: 利用std::tuple完成运行期的if...else替换

code client code 参考链接&#xff1a; std::tuple std::tuple_size std::tuple_element

接口测试-快问快答你能做对几道【含答案】

1、做接口测试当请求参数多时tps下降明显&#xff0c;此接口根据参数从redis中获取数据&#xff0c;每个参数与redis交互一次&#xff0c;当一组参数是tps5133&#xff0c;五组参数是tps1169&#xff0c;多次交互影响了处理性能&#xff0c;请详细阐述如何改进增进效果的方案。…

AD(第二部分---绘制原理图库及编译检查)

设计电路-----器件选型----绘制原理图----->先有"BOOM"&#xff0c;后更改AD封装 10.元件的放置&#xff1a; 当有多个元件库&#xff0c;选择某一个时&#xff0c;需要点击右下角"Panels"&#xff0c;之后点击Components。如下图&#xff1a; 之后双击…

基于机器视觉的旋转编码器缺陷检测

基于机器视觉的旋转编码器缺陷检测 1 背景及意义 旋转编码器是用来测量转速并配合PWM技术可以实现快速调速的装置,基本上每一个伺服电机都有一个旋转编码器。旋转编码器的质量将直接影响到伺服电机的好坏,所以每一个旋转编码器出厂前都要经过严格的质检。 传统的检测方法是…

价值30K的硬核性能测试面试题

如何判断java应用程序内存泄漏&#xff1f; Java应用程序内存泄漏是指程序中的某些对象在不再需要时仍然占用内存&#xff0c;导致内存消耗不断增加并最终导致程序崩溃或性能下降。以下是一些判断Java应用程序内存泄漏的方法&#xff1a; 监控内存使用情况&#xff1a;使用Jav…

机器学习笔记 - 基于OpenMMLab在自定义数据集上训练RTMDet网络

一、什么是 RTMDet? RTMDet是一种高效的实时目标检测器,其自报告指标优于YOLO 系列。它在COCO上实现了52.8% 的 AP ,在 NVIDIA 3090 GPU 上实现了300+ FPS,使其成为当前号称最快、最准确的目标检测器之一。 RTMDet 与其他实时物体检测器的对比。 RTMDet 采用了一种…

云安全攻防(十三)之 使用minikube安装搭建 K8s 集群

使用minikube安装搭建 K8s 集群 Kubernetes 是一个可移植的、可扩展的开源平台&#xff0c;用于管理容器化的工作负载和服务&#xff0c;可促进声明式配置和自动化,一般来说K8s安装有三种方式&#xff0c;分别是Minikube装搭建 K8s 集群&#xff0c;特点是只有一个节点的集群&…

解锁时尚潮流,畅享短视频商城新体验

近年来&#xff0c;随着短视频媒体的兴起和时尚潮流的盛行&#xff0c;人们对于探索潮流趋势和购物方式的需求也不断增长。为满足用户的需求&#xff0c;越来越多的短视频商城应运而生。这些商城不仅为用户提供了一站式的购物平台&#xff0c;还提供了独特的时尚潮流推荐和体验…