百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

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

toyiye 2024-07-05 01:26 13 浏览 0 评论

光流的概念最早是由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 detection
feature_params = dict( maxCorners = 10,
                       qualityLevel = 0.2,
                       minDistance = 5,
                       blockSize = 5 )


# convert all frames to grayscale
gray_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 it
pts_1 = cv2.goodFeaturesToTrack(gray_1, mask = None, **feature_params)

# display the detected points
plt.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 points
print(pts_1)

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

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

# parameters for lucas kanade optical flow
lk_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 frame
pts_2, match, err = cv2.calcOpticalFlowPyrLK(gray_1, gray_2, pts_1, None, **lk_params)

# Select good matching points between the two image frames
good_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 frame
mask = 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 together

composite_im = np.copy(frame_2)
composite_im[mask!=0] = [0]

plt.imshow(composite_im)

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码