转载自:http://blog.csdn.net/w12345_ww/article/details/44925403
这几天主要看了光流的有关内容,下面就关于光流的有关内容进行个简单的总结。
所谓的光流是一种运动模式,这种运动模式即是指一个物体、表面、边缘在一个视角下由一个观察者和背景之间形成的明显移动。在如下的图中给出了光流的直观解释。
这里的每个像素都与速度相关联,这样得到的即是稠密光流,在光流中主要分为稠密光流和稀疏光流,相对于稠密光流,稀疏光流的计算则需要在跟踪之前指定一组点,下面我主要介绍下比较流行的基于金字塔的Lucas-Kanade光流算法。
(1)LK算法
LK算法其实是基于三个假设进行的:
a.亮度恒定。图像场景中目标的像素在帧间运动时外观上保持不变,对于灰度图像,需要假设像素被逐帧跟踪时其亮度不发生变化。这样的假设,我们可以用下面的数学表达式来表达:
也即是亮度I对时间t的偏导数为0,即:
b.时间连续或者运动是“小运动”。图像的运动随时间的变化比较缓慢。实际应用中指的是时间变化相对于图像中运动的比例要足够小,这样目标在帧间的运动就比较小。
这条假设,就只能针对小运动,但实际上的运动往往是比较大的运动,这时我们就会将现在的LK算法加以改进,采用基于图像金字塔的LK算法,这在后面将进一步进行介绍。
针对这条假设,换句话说,可以将运动的变化看成是亮度对时间的导数,此时将f(x,t)用I(x(t),t)替换,应用偏微分的链式法则即可得到:
我们接着将从一维的情况过渡到二维的情况下去分析即得到:
c.空间一致性假设。一个场景中同一表面上邻近的点具有相似的运动,在图像平面上的投影也在邻近区域。
下面的这幅图,直观的给出了上述的三条假设。
但垂直光流由孔径问题产生,即用小孔或者小窗口去测量运动。这种情况下,我们通常只能观测到边缘而观测不到角点,而只靠边缘是不足以判断整个物体是如何运动的,如下图解释的那样:
单像素是不能解决整个运动的,要想解决这样的一个问题,需用到光流的最后一个假设。若一个局部区域的像素运动是一致的,则可以建立邻域像素的系统方程来求解中心像素的移动。这个约束方程有点复杂,如果感兴趣可以去查阅相关文献。
以上的LK算法只需要每个感兴趣点周围小窗口的局部信息,但是使用小窗口的LK算法存在着不足之处就是,较大的运动点将点移出这个小窗口,从而造成算法无法找到这些点。而金字塔的LK算法可以解决这样的问题,即从图像金字塔的最高层(细节最少)开始向金字塔的低层(丰富的细节)进行跟踪。
(2)图像金字塔的LK算法
在图像金字塔的最高层计算光流,用得到的运动估计结果作为下一层金字塔的起始点,重复这个过程直到达到金字塔的最底层。这样就将不满足运动假设的可能性降到最小从而实现对更快和更长的运动的跟踪,这个算法就叫做基于金字塔的LK算法。如图所示:
在OpenCV中主要有个基于图像金字塔的LK算法的函数cvCalcOpticalFlowPyrLK(),下面就简要介绍下这个函数的具体的参数的意义,并尝试给出完整的示例程序。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
应用上述函数的过程非常简单:
输入图像,在featuresA中列出需要跟踪的点,然后调用函数。函数返回后,检查status数组以确定哪些点被成功跟踪,再检查featuresB得到这些点新的位置。
下面给出基于图像金字塔的LK算法完整的示例程序:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
下面是这个程序运行的结果:
这个程序选择的是两帧不同的图像进行跟踪画出的光流,大家可以尝试着把OpenCV中的视频捕捉功能用起来,用摄像头捕捉两帧图像进行基于图像金字塔的LK算法。
最后如果想继续研究下LK算法的数学原理,可以参考以下这篇博客
http://www.cnblogs.com/gnuhpc/archive/2012/12/04/2802124.html