光流(Optical Flow)原理及其算法示例

光流的概念最早是由Gibson在1950年提出的。它是空间移动物体在像素观察平面中移动的瞬时速度。是一种计算物体在相邻帧间运动信息的方法。

一般来说,光流(Optical Flow)是物体在三维空间中的运动在二维像平面上的投影。它是由物体和相机的相对速度产生的,反映了物体在极小时间内对应的图像像素的运动方向和速度。

Lucas–Kanade方法(KLT)是一种基于光流原理的特征点跟踪算法。本文首先介绍光流的原理,然后介绍了KLT及其相关的KLT变体算法。

光流约束方程

假设I(x,y,t)为时刻t像素点(x,y)的像素值(亮度),该像素点在两个图像帧之间移动了Δx,Δy,Δt。因此我们可以得出相同亮度的结论:

假设运动很小,我们可以从泰勒级数推导一阶泰勒展开式:

因此,

其中(dx/dt, dy/dt) = (u, v)为待解像素的光流。

(∂I/∂x,∂I/∂y) = (I_x, I_y)是像素灰度空间微分,t = I_x是像素坐标点的时间灰度微分。

整理成矩阵形式:

该公式表明,同一坐标位置上的时间灰度微分是空间灰度微分与该位置上相对于观测者的速度的乘积。假设空间一致性,对于周围的多个点,有:

这个方程组的方程多于未知数,因此通常是超定的。Lucas-Kanade方法通过最小二乘原理获得折衷解决方案:

这就是光流算法的孔径问题。为了找到光流,需要另一组方程,并附加约束条件。所有的光流方法都引入了估算实际流的附加条件。

局部差分法:Lucas-Kanade算法

为了使方程可求解,进行以下假设:

  • 亮度是恒定的,图像中对象的像素亮度在连续帧之间不会改变;
  • 短距离(短期)运动,相邻帧之间的时间足够短,并且物体运动很小;
  • 空间一致性,相邻像素具有相似的运动;

恒定亮度是指某些像素的跟踪不随时间变化:

公式表示被跟踪像素的灰度不随时间变化:

连续时间意味着相邻帧之间的运动很小。换句话说,运动的变化可以被认为是亮度相对于时间的导数。一维空间的示例:

其中,I_x是图像的偏导数,I_t是图像随时间的导数,v是所需速度。

与之前直接比较像素灰度值的方法不同,Lucas-Kanade算法比较像素周围的窗口像素以找到最相似的像素。假设光流在短时间τ内,前后两帧满足:

其中D为变形矩阵,d称为位移向量,D表示两像素窗口块移动后的变形量,因此,当窗口较小时,将更加难以估计。通常,D可用于测量两个像素窗口的相似度,即特征点是否漂移。对于光流跟踪,通常仅考虑平移模型:

为了通用性,我们使用仿射运动模型来推导Lucas-Kanade算法的原理。在像素窗口下,构造误差函数:

其中w(x)是权重函数,可以定义为高斯函数。分别对变量d和D进行微分:

其中

记住光流u = Dx + d,然后对运动后的像素点进行泰勒展开:

这里给出了平移运动模型的结果。设D = 0:

其中Z是2×2矩阵,e是2×1向量。这是一个线性方程优化问题。当Z是可逆的时,可以轻松地求解该方程。由于泰勒展开式是在推导过程中使用的,因此仅当像素位移较小时才成立。在实际操作中,通常每次将最后结果用于初始化和进一步解决时(在Newton-Raphson Fasion中),都需要迭代解决。

工作实例

在光流可以工作之前,我们必须给它提供一组关键点以在两个图像帧之间进行跟踪。

在下面的示例中,我们使用了Shi-Tomasi corner detector,该detector使用与Harris corner detector相同的过程来查找构成图像中“角点”的强度模式,只是它增加了一个额外的参数来帮助选择最突出的角点。

# parameters for ShiTomasi corner detectionfeature_params = dict( maxCorners = 10, qualityLevel = 0.2, minDistance = 5, blockSize = 5 )# convert all frames to grayscalegray_1 = cv2.cvtColor(frame_1, cv2.COLOR_RGB2GRAY)gray_2 = cv2.cvtColor(frame_2, cv2.COLOR_RGB2GRAY)gray_3 = cv2.cvtColor(frame_3, cv2.COLOR_RGB2GRAY)# Take first frame and find corner points in itpts_1 = cv2.goodFeaturesToTrack(gray_1, mask = None, **feature_params)# display the detected pointsplt.imshow(frame_1)for p in pts_1: # plot x and y detected points plt.plot(p[0][0], p[0][1], 'r.', markersize=15)# print out the x-y locations of the detected pointsprint(pts_1)

一旦我们在我们感兴趣的初始图像上检测到关键点,我们就可以计算这幅图像(帧1)和下一帧(帧2)之间的光流。它接收初始图像帧、下一幅图像帧和一组点,并返回下一帧中检测到的点和一个值,该值指示从一帧到下一帧的点之间的匹配程度。

这些参数还包括窗口大小和maxLevels,它们指示窗口的大小以及将使用pyramid缩放来缩放给定图像的级数。对匹配点进行迭代搜索,最后一个参数反映了这个匹配条件(如果使用不同的图像,您可能需要更改这些值,但是这些值应该适用于提供的示例)。Python示例代码如下

# parameters for lucas kanade optical flowlk_params = dict( winSize  = (5,5),                  maxLevel = 2,                  criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))# calculate optical flow between first and second framepts_2, match, err = cv2.calcOpticalFlowPyrLK(gray_1, gray_2, pts_1, None, **lk_params)# Select good matching points between the two image framesgood_new = pts_2[match==1]good_old = pts_1[match==1]

接下来,让我们显示最终的运动向量,Python示例代码如下

# create a mask image for drawing (u,v) vectors on top of the second framemask = np.zeros_like(frame_2)# draw the lines between the matching points (these lines indicate motion vectors)for i,(new,old) in enumerate(zip(good_new,good_old)): a,b = new.ravel() c,d = old.ravel() # draw points on the mask image mask = cv2.circle(mask,(a,b),5,(200),-1) # draw motion vector as lines on the mask image mask = cv2.line(mask, (a,b),(c,d), (200), 3) # add the line image and second frame togethercomposite_im = np.copy(frame_2)composite_im[mask!=0] = [0]plt.imshow(composite_im)
(0)

相关推荐

  • DeepFlow高效的光流匹配算法(上)

    分 享 本周主要介绍一篇基于传统光流法而改进的实现快速的稠密光流算法.该算法已经集成到OpenCV中,算法介绍网址:http://lear.inrialpes.fr/src/deepmatching/ ...

  • 【从零学习OpenCV 4】中值滤波

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<OpenCV 4开发详解>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • 【从零学习OpenCV 4】图像修复

    重磅干货,第一时间送达 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍<OpenCV 4开发详解>.为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通 ...

  • Python进阶——OpenCV之Core Operations

    文章目录 图像基本操作 访问并修改像素值 访问图像的属性 设置图像区域 图像分割与合并 画图像边框 图像的数学操作 图像叠加 图像融合 图像位操作 Python OpenCV代码检测与速度优化 时隔一 ...

  • 基于OpenCV Haar实战级联分类器的使用

    重磅干货,第一时间送达 近年来,对象检测引起了广泛的关注.从智能手机到交通监控,目标检测已遍及每个领域.时间和准确性是对象检测中的关键约束.目标检测算法的成功取决于其特征表示技术和学习算法,后者仅关注 ...

  • OpenCV实战(1)

    如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 最近 ...

  • 无需深度学习即可提取图像特征

    重磅干货,第一时间送达 一.简介 图像分类是数据科学中最热门的领域之一,在本文中,我们将分享一些将图像转换为特征向量的技术,可以在每个分类模型中使用. 二.定义 VATbox,作为n一个我们所暗示的, ...

  • 基于OpenCV实战:动态物体检测

    重磅干货,第一时间送达 最近,闭路电视安全系统运行着多种算法来确保安全,例如面部识别,物体检测,盗窃检测,火灾警报等.我们在运动检测的基础上实现了许多算法,因为在空闲帧上运行所有这些进程没有任何意义. ...

  • 使用OpenCV进行颜色分割

    重磅干货,第一时间送达 在滤波.变换.缩放等任务中,图像分割具有重要的意义.图像分割是将不同的对象划分为不同的部分,并将这些区域以明显的颜色或者记号标记出来.图像分割是使用轮廓.边界框等概念进行其他高 ...

  • R语言贝叶斯推断与MCMC:实现Metropolis-Hastings 采样算法示例

    原文链接:http://tecdat.cn/?p=21545 示例1:使用MCMC的指数分布采样 任何MCMC方案的目标都是从"目标"分布产生样本.在这种情况下,我们将使用平均值为 ...

  • CRC循环冗余校验的原理与算法及FPGA实现

    一.CRC基本原理 在串行数据流的最有效的检错方案是CRC(Cyclic Redundancy check)循环冗余检验,CRC循环冗余校验最根本的原理就是将原始数据除以某个固定的数,然后所得的余数就 ...

  • DL:深度学习(神经网络)的简介、基础知识(神经元/感知机、训练策略、预测原理)、算法分类、经典案例应用之详细攻略

    DL:深度学习(神经网络)的简介.基础知识(神经元/感知机.训练策略.预测原理).算法分类.经典案例应用之详细攻略 深度学习(神经网络)的简介 深度学习(Deep Learning, DL)或阶层学习 ...

  • 从传感器到算法原理,机器人、视觉避障都在这里了

    避障是指移动机器人在行走过程中,通过传感器感知到在其规划路线上存在静态或动态障碍物时,按照 一定的算法实时更新路径,绕过障碍物,最后达到目标点. 不管是要进行导航规划还是避障,感知周边环境信息是第一步 ...

  • 路由器原理及常用的路由协议、路由算法

    路由器原理及常用的路由协议、路由算法

  • R机器学习:分类算法之判别分析LDA,QDA的原理与实现

    判别分析的框框很大,今天给大家写写线性判别和二次判别,这两个是判别分析中最常见也是最基本的,希望能够给大家写明白. 首先给出判别分析的定义: Linear discriminant analysis ...

  • R机器学习:基于树的分类算法的原理及实现

    基于决策数的分类方法是一种非常直观的,非常好解释的,初中生都可以看得懂的分类算法,所以今天就给大家写写这个简单实用的分类算法. 决策树的基本流程就是通过一系列只能回答是否的问题将数据进行分类,这种方法 ...

  • 韩信点兵算法及其原理

    [问题]求最小非负整数N,使他在除以3,5,7以后所得余数分别是a,b,c. [韩信点兵法的口诀] 三人同行七十稀,五树梅花廿一枝,     七子团圆整半月,除百零五便得知. [韩信点兵法口诀的释义] ...

  • R机器学习:分类算法之logistics回归分类器的原理和实现

    一看到logistics回归分类器,第一反应这个不是统计上的logistics回归嘛,其实是一样的,之前也给大家写过logistics回归的做法,今天放在机器学习的框架下再写一次. logistic ...