Horn–Schunck光流算法 — Horn–Schunck Method

Horn-Schunck光流算法通过引入全局平滑约束来做图像中的运动估计。Horn和Schunck设定图像中像素的运动速度和其临近像素的速度相似或相同,且光流场中的每处的速度变化是平滑的,不会突变【学习本文内容前,需要先了解光流的基础知识】。有两种方法来表示平滑约束(最小化以下式子):
( ∂ u ∂ x ) 2 + ( ∂ u ∂ y ) 2 和 ( ∂ v ∂ x ) 2 + ( ∂ v ∂ y ) 2 (\frac{\partial{u}}{\partial{x}})^2+(\frac{\partial{u}}{\partial{y}})^2 \hspace{0.5cm} 和 \hspace{0.5cm} (\frac{\partial{v}}{\partial{x}})^2+(\frac{\partial{v}}{\partial{y}})^2 (xu)2+(yu)2(xv)2+(yv)2

或者:
∇ 2 u = ∂ 2 u ∂ 2 x + ∂ 2 u ∂ 2 y 和 ∇ 2 v = ∂ 2 v ∂ 2 x + ∂ 2 v ∂ 2 y \nabla^2{u} = \frac{\partial^2{u}}{\partial^2{x}}+\frac{\partial^2{u}}{\partial^2{y}} \hspace{0.5cm} 和 \hspace{0.5cm} \nabla^2{v} = \frac{\partial^2{v}}{\partial^2{x}}+\frac{\partial^2{v}}{\partial^2{y}} 2u=2x2u+2y2u2v=2x2v+2y2v

对于 ∇ 2 u \nabla^2{u} 2u ∇ 2 v \nabla^2{v} 2v的计算,可以参考Horn和Schunck在1981年发表的论文 D e t e r m i n i n g   O p t i c a l   F l o w Determining\ Optical\ Flow Determining Optical Flow中的计算方法。如下:
∇ 2 u ≈   3 ( u ˉ i , j , k − u i , j , k ) 和 ∇ 2 v ≈   3 ( v ˉ i , j , k − v i , j , k ) \nabla^2{u} \approx \ _{3}(\bar{u}_{i,j,k} - u_{i,j,k}) \hspace{0.5cm} 和 \hspace{0.5cm} \nabla^2{v} \approx \ _{3}(\bar{v}_{i,j,k} - v_{i,j,k}) 2u 3(uˉi,j,kui,j,k)2v 3(vˉi,j,kvi,j,k)

其中,左下标 3 3 3表示像素的临近范围, u ˉ i , j , k \bar{u}_{i,j,k} uˉi,j,k v ˉ i , j , k \bar{v}_{i,j,k} vˉi,j,k定义如下:
u ˉ i , j , k = 1 6 { u i − 1 , j , k + u i , j + 1 , k + u i + 1 , j , k + u i , j − 1 , k } + 1 12 { u i − 1 , j − 1 , k + u i − 1 , j + 1 , k + u i + 1 , j + 1 , k + u i + 1 , j − 1 , k } , v ˉ i , j , k = 1 6 { v i − 1 , j , k + v i , j + 1 , k + v i + 1 , j , k + v i , j − 1 , k } + 1 12 { v i − 1 , j − 1 , k + v i − 1 , j + 1 , k + v i + 1 , j + 1 , k + v i + 1 , j − 1 , k } , \begin{aligned} \bar{u}_{i,j,k} = & \frac{1}{6}\{ u_{i-1,j,k} + u_{i,j+1,k} + u_{i+1,j,k} + u_{i,j-1,k}\} \\ & + \frac{1}{12}\{ u_{i-1,j-1,k} + u_{i-1,j+1,k} + u_{i+1,j+1,k} + u_{i+1,j-1,k}\}, \\ \bar{v}_{i,j,k} = & \frac{1}{6}\{ v_{i-1,j,k} + v_{i,j+1,k} + v_{i+1,j,k} + v_{i,j-1,k}\} \\ & + \frac{1}{12}\{ v_{i-1,j-1,k} + v_{i-1,j+1,k} + v_{i+1,j+1,k} + v_{i+1,j-1,k}\}, \\ \end{aligned} uˉi,j,k=vˉi,j,k=61{ui1,j,k+ui,j+1,k+ui+1,j,k+ui,j1,k}+121{ui1,j1,k+ui1,j+1,k+ui+1,j+1,k+ui+1,j1,k},61{vi1,j,k+vi,j+1,k+vi+1,j,k+vi,j1,k}+121{vi1,j1,k+vi1,j+1,k+vi+1,j+1,k+vi+1,j1,k},

如图:
在这里插入图片描述

至此,Horn-Schunck光流算法已经建立了两个约束条件,可以完成对光流中的 u u u v v v的计算。
ξ b = u I x + v I y + I t ξ c 2 = ∇ 2 u + ∇ 2 v \begin{aligned} & \xi_{b} = uI_{x} + vI_{y} + I_{t} \\ & \xi_{c}^{2} = \nabla^2{u} + \nabla^2{v} \end{aligned} ξb=uIx+vIy+Itξc2=2u+2v

基于上两式,Horn和Schunck构建误差函数 ξ 2 \xi^2 ξ2,如下:
ξ 2 = ∫ ∫ ( α 2 ξ c 2 + ξ b 2 ) d x d y \xi^2 = \int\int (\alpha^{2}\xi_{c}^2 + \xi_{b}^2)dxdy ξ2=(α2ξc2+ξb2)dxdy

其中, α \alpha α值越大,光流越平滑。目标是计算误差函数 ξ 2 \xi^2 ξ2取得最小值时, u u u v v v的取值。通过变分法(博主还不懂变分法,以后慢慢学~~),误差函数 ξ 2 \xi^2 ξ2可变换为:
I x 2 u + I x I y v = α 2 ∇ 2 u − I x I t I x I y u + I y 2 v = α 2 ∇ 2 v − I y I t \begin{aligned} I_{x}^{2}u + I_{x}I_{y}v = \alpha^{2}\nabla^2{u} - I_{x}I_{t} \\ I_{x}I_{y}u + I_{y}^2v = \alpha^{2}\nabla^2{v} - I_{y}I_{t} \end{aligned} Ix2u+IxIyv=α22uIxItIxIyu+Iy2v=α22vIyIt

代入 ∇ 2 u = u ˉ i , j , k − u i , j , k \nabla^2{u} = \bar{u}_{i,j,k} - u_{i,j,k} 2u=uˉi,j,kui,j,k ∇ 2 v = u ˉ i , j , k − u i , j , k \nabla^2{v} = \bar{u}_{i,j,k} - u_{i,j,k} 2v=uˉi,j,kui,j,k,得:
( α 2 + I x 2 ) u + I x I y v = ( α 2 u ˉ − I x I t ) I x I y u + ( α 2 + I y 2 ) v = ( α 2 v ˉ − I y I t ) (\alpha^2 + I_{x}^{2})u + I_{x}I_{y}v = (\alpha^2\bar{u} - I_{x}I_{t}) \\ I_{x}I_{y}u + (\alpha^2 + I_{y}^{2})v = (\alpha^2\bar{v} - I_{y}I_{t}) (α2+Ix2)u+IxIyv=(α2uˉIxIt)IxIyu+(α2+Iy2)v=(α2vˉIyIt)

上式的矩阵形式为:
[ α 2 + I x 2 I x I y I x I y α 2 + I y 2 ] [ u v ] = [ α 2 u ˉ − I x I t α 2 v ˉ − I y I t ] \begin{bmatrix} \alpha^2 + I_{x}^{2} & I_{x}I_{y} \\ I_{x}I_{y} & \alpha^2 + I_{y}^{2} \end{bmatrix} \begin{bmatrix} u \\ v \end{bmatrix} = \begin{bmatrix} \alpha^2\bar{u} - I_{x}I_{t} \\ \alpha^2\bar{v} - I_{y}I_{t} \end{bmatrix} [α2+Ix2IxIyIxIyα2+Iy2][uv]=[α2uˉIxItα2vˉIyIt]

通过对上式进行行列式计算,得到 u u u v v v的表达式:
( α 2 + I x 2 + I y 2 ) u = ( α 2 + I y 2 ) u ˉ − I x I y v ˉ − I x I t ( α 2 + I x 2 + I y 2 ) v = − I x I y u ˉ + ( α 2 + I x 2 ) v ˉ − I y I t \begin{aligned} & (\alpha^2 + I_{x}^{2} + I_{y}^2)u = (\alpha^2 + I_{y}^2)\bar{u} - I_{x}I_{y}\bar{v} - I_{x}I_{t} \\ & (\alpha^2 + I_{x}^{2} + I_{y}^2)v = -I_{x}I_{y}\bar{u} + (\alpha^2 + I_{x}^2)\bar{v} - I_{y}I_{t} \end{aligned} (α2+Ix2+Iy2)u=(α2+Iy2)uˉIxIyvˉIxIt(α2+Ix2+Iy2)v=IxIyuˉ+(α2+Ix2)vˉIyIt

上式的另一种形式可以是:
( α 2 + I x 2 + I y 2 ) ( u − u ˉ ) = − I x [ I x u ˉ + I y v ˉ + I t ] ( α 2 + I x 2 + I y 2 ) ( v − v ˉ ) = − I y [ I x u ˉ + I y v ˉ + I t ] (\alpha^2 + I_{x}^{2} + I_{y}^2)(u - \bar{u}) = -I_{x}[I_{x}\bar{u} + I_{y}\bar{v} + I_{t}] \\ (\alpha^2 + I_{x}^{2} + I_{y}^2)(v - \bar{v}) = -I_{y}[I_{x}\bar{u} + I_{y}\bar{v} + I_{t}] (α2+Ix2+Iy2)(uuˉ)=Ix[Ixuˉ+Iyvˉ+It](α2+Ix2+Iy2)(vvˉ)=Iy[Ixuˉ+Iyvˉ+It]

由于一开始, u u u v v v的取值未知,因此 u ˉ \bar{u} uˉ v ˉ \bar{v} vˉ的取值也未知。无法直接通过上式计算 u u u v v v的取值。不过,我们可以采用迭代的方式来计算:
u n + 1 = u ˉ n − I x [ I x u ˉ n + I y v ˉ n + I t ] α 2 + I x 2 + I y 2 v n + 1 = v ˉ n − I y [ I x u ˉ n + I y v ˉ n + I t ] α 2 + I x 2 + I y 2 \begin{aligned} u^{n+1} = \bar{u}^{n} - \frac{I_{x}[I_{x}\bar{u}^{n} + I_{y}\bar{v}^{n} + I_{t}]}{\alpha^2 + I_{x}^{2} + I_{y}^2} \\ v^{n+1} = \bar{v}^{n} - \frac{I_{y}[I_{x}\bar{u}^{n} + I_{y}\bar{v}^{n} + I_{t}]}{\alpha^2 + I_{x}^{2} + I_{y}^2} \end{aligned} un+1=uˉnα2+Ix2+Iy2Ix[Ixuˉn+Iyvˉn+It]vn+1=vˉnα2+Ix2+Iy2Iy[Ixuˉn+Iyvˉn+It]

至此,Horn–Schunck光流算法原理已介绍完毕。

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是基于Lucas-Kanade光流算法、基于Kalman滤波的光流算法和基于Horn-Schunck光流算法的精确度比较的Matlab代码。 ```matlab % 读入两幅图像 I1 = imread('frame1.jpg'); I2 = imread('frame2.jpg'); % 转为灰度图像 I1 = rgb2gray(I1); I2 = rgb2gray(I2); % Lucas-Kanade光流算法 points1 = detectMinEigenFeatures(I1); [features1, points1] = extractFeatures(I1, points1); points2 = detectMinEigenFeatures(I2); [features2, points2] = extractFeatures(I2, points2); indexPairs = matchFeatures(features1, features2); matchedPoints1 = points1(indexPairs(:, 1), :); matchedPoints2 = points2(indexPairs(:, 2), :); [tform, inlierPoints1, inlierPoints2] = estimateGeometricTransform(matchedPoints1, matchedPoints2, 'affine'); outputView = imref2d(size(I1)); Ir = imwarp(I2, tform, 'OutputView', outputView); figure, imshowpair(I1, Ir, 'montage') % 基于Kalman滤波的光流算法 [motionVect, blkIdx] = motionEstARPS(I1, I2, 16); blkCnt = length(blkIdx); for i = 1:blkCnt h = blkIdx(i, 1); w = blkIdx(i, 2); motionVec = motionVect(h, w, :); x1 = (w - 1) * 16 + 1; y1 = (h - 1) * 16 + 1; x2 = x1 + motionVec(1); y2 = y1 + motionVec(2); line([x1 x2], [y1 y2], 'Color', 'r'); end % 基于Horn-Schunck光流算法 [Gx, Gy, Gt] = horn_schunck(I1, I2, 1); u = zeros(size(I1)); v = zeros(size(I1)); alpha = 1; for i = 1:10 uAvg = conv2(u, ones(3, 3), 'same') / 9; vAvg = conv2(v, ones(3, 3), 'same') / 9; du = ((Gx .* uAvg) + (Gy .* vAvg) + Gt) ./ (alpha^2 + Gx.^2 + Gy.^2); dv = ((Gx .* vAvg) + (Gy .* uAvg) + Gt) ./ (alpha^2 + Gx.^2 + Gy.^2); u = uAvg - Gx .* du; v = vAvg - Gy .* dv; end figure, imshow(I1) hold on [x, y] = meshgrid(1:16:size(I1,2), 1:16:size(I1,1)); quiver(x, y, u(1:16:end, 1:16:end), v(1:16:end, 1:16:end), 2, 'r'); % 计算精度 groundTruth = readFlowFile('groundtruth.flo'); flowLK = estimateFlowLK(I1, I2); flowKalman = motion2flow(motionVect); flowHS = flow2uv(u, v); errLK = flow_error(groundTruth, flowLK); errKalman = flow_error(groundTruth, flowKalman); errHS = flow_error(groundTruth, flowHS); fprintf('Lucas-Kanade光流算法平均误差:%f\n', mean(errLK)); fprintf('基于Kalman滤波的光流算法平均误差:%f\n', mean(errKalman)); fprintf('基于Horn-Schunck光流算法平均误差:%f\n', mean(errHS)); ``` 需要注意的是,这里的`motionEstARPS`、`horn_schunck`、`motion2flow`、`flow2uv`、`flow_error`和`readFlowFile`等函数并不是Matlab自带的函数,需要自己实现或者下载相应的代码库。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值