我在这里找到了LKT算法的Matlab实现,它基于亮度恒定方程。
该算法通过将图像与适当的2x2水平和垂直边缘梯度算子卷积来计算x和y方向上的图像梯度。
经典文献中的亮度恒定方程右手边有两个连续帧之间的差异。
然而,在上述链接所指的实现中,右侧是卷积的差异。
It_m = conv2(im1,[1,1;1,1]) + conv2(im2,[-1,-1;-1,-1]);
为什么不能简单地将It_m计算为:
it_m = im1 - im2;
正如您所提到的,理论上,光流计算只规定了逐像素的差异。然而,在实践中,所有的自然(非合成)图像都包含一定程度的噪声。另一方面,微分是某种高通滤波器,会对信号强调(高通)噪声比。因此,为了避免由噪声引起的伪影,通常在任何图像微分之前进行图像平滑(或低通滤波)(我们在边缘检测中也有这样的过程)。该代码正是这样做的,即在图像上应用移动平均滤波器以减少噪声影响。
It_m = conv2(im1,[1,1;1,1]) + conv2(im2,[-1,-1;-1,-1]);
(注释转换为答案。)
理论上,采用像素差异并没有错:
Im_t = im1-im2;
以计算时间导数。在计算时间导数时使用空间平滑器可以减轻噪声的影响。
此外,看看代码计算空间(x和y)导数的方式:
Ix_m = conv2(im1,[-1 1; -1 1], 'valid');
用类似的核和valid
选项计算时间导数确保矩阵It_x
、It_y
和Im_t
具有兼容的大小。
时间偏导数(沿t)与空间偏导数(沿着x和y)相连。
把你正在分析的视频序列想象成一个体积,时空体积。在任何给定点(x,y,t),如果你想估计偏导数,即估计该点的3D梯度,那么你将受益于具有相同内核支持的3个滤波器。
要了解更多关于为什么会这样的理论,请查阅主题导向滤波器,或者更好地查阅偏导数应该是什么的基本概念,以及它如何与方向导数相联系。
通常,2D梯度是首先估计的,然后人们倾向于认为时间导数其次独立于x和y分量。这可能并且经常会导致最终光流计算中的数值误差。处理这些误差的常见方法是进行正向和反向流量估计,并最终将结果组合起来。
考虑你所估计的梯度的一种方法是,它有一个3D的支撑区域。此类区域的最小尺寸应为2x2x2。
如果在第一个和第二个图像中都只使用2x2滤波器进行2D梯度,则通过对两个滤波器的结果进行平均来收集3D体积的相应FIR滤波器。
在2D中应该有相同的滤波器支持区域这一事实对大多数人来说都是清楚的:这就是为什么Sobel和Scharr算子看起来像他们这样
在我制作的这个Matlab工具箱中,你可以看到为光流精心设计的微分算子所得到的结果,部分原因是为了说明这一点。