开发者社区> cleverzcc> 正文

Optical Flow介绍与代码实现

简介: Optical Flow介绍与代码实现 介绍 首先我们先来介绍一下Optical Flow是个什么东西, 在浏览器的搜索框框里面我们输入"Optical flow"可以看到维基百科的解释: 光流(Optical flow or optic flow)是关于视域中的物体运动检测中的概念。
+关注继续查看

Optical Flow介绍与代码实现

介绍

首先我们先来介绍一下Optical Flow是个什么东西, 在浏览器的搜索框框里面我们输入"Optical flow"可以看到维基百科的解释:

光流(Optical flow or optic flow)是关于视域中的物体运动检测中的概念。用来描述相对于观察者的运动所造成的观测目标、表面或边缘的运动。

Optical flow 是一个概念, 描述的是一个相对于观测者的运动,这个运动是观测造成的,就是说,我们眼睛的目光和物体保持相对静止就没有光流运动啦.
似乎是个物理上面的东西, 这个网址 "http://people.csail.mit.edu/celiu/motionAnnotation/whatismotion.html"提出了一个问题 ":

What is motion?"对两个观点进行了辩论:

  • 1, " motion is the physical movement of pixels, and therefore motion has to be measured in a physical way. "
  • 2, " motion is human percept--motion is what we perceive in our brain, something we can sense and communicate."

然后贴了下面这个图

img_4c4b384c09223e161f4d7ff9a4919098.gif
image

Fig1 http://www.ritsumei.ac.jp/~akitaoka/index-e.html

我们人类可以从上面的静态图中感受到运动! 由此联想到计算机视觉系统是如何做的?

If the ultimate goal of computer vision is to let the computer see what humans perceive, then it is certainly the right way to let humans teach computer how to see the world. Our human-assisted motion annotation serves exactly for this purpose. Indeed, we shall show you that (a) humans' annotations are very consistent, and (b) human's annotations are consistent with other ground-truth data.

很容易发现, 只有在我们的眼睛(准确的是目光)移动的时候,我们才能感受到运动,那么眼睛移动引起了什么变化喃, 貌似有亮度, (角度)视角,这样子我们岂不是就可以估计相对运动啦. 是的嘛, 光流就是来估计运动的的嘛,,(这么简单的原理,为什么我就没有提出来喃 233).

言归正传

光流的概念是Gibson在1950年首先提出来的。它是空间运动物体在观察成像平面上的像素运动的瞬时速度,是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系,从而计算出相邻帧之间物体的运动信息的一种方法。一般而言,光流是由于场景中前景目标本身的移动、相机的运动,或者两者的共同运动所产生的。

当人的眼睛观察运动物体时,物体的景象在人眼的视网膜上形成一系列连续变化的图像,这一系列连续变化的信息不断“流过”视网膜(即图像平面),好像一种光的“流”,故称之为光流(optical flow)。光流表达了图像的变化,由于它包含了目标运动的信息,因此可被观察者用来确定目标的运动情况。研究光流场的目的就是为了从图片序列中近似得到不能直接得到的运动场。运动场,其实就是物体在三维真实世界中的运动;光流场,是运动场在二维图像平面上(人的眼睛或者摄像头)的投影。那通俗的讲就是通过一个图片序列,把每张图像中每个像素的运动速度和运动方向找出来就是光流场。那怎么找呢?咱们直观理解肯定是:第t帧的时候A点的位置是(x1, y1),那么我们在第t+1帧的时候再找到A点,假如它的位置是(x2,y2),那么我们就可以确定A点的运动了:

(ux, vy) = (x2, y2) - (x1,y1)。

那怎么知道第t+1帧的时候A点的位置呢? 这就存在很多的光流计算方法了。
1981年,Horn和Schunck创造性地将二维速度场与灰度相联系,引入光流约束方程,得到光流计算的基本算法。人们基于不同的理论基础提出各种光流计算方法,算法性能各有不同。Barron等人对多种光流计算技术进行了总结,按照理论基础与数学方法的区别把它们分成四种:基于梯度的方法、基于匹配的方法、基于能量的方法、基于相位的方法。近年来神经动力学方法也颇受学者重视。

贴自 https://blog.csdn.net/zouxy09/article/details/8683859

光流的测量

img_1f3ddb8dcbc4813bdf811eebde27e0fd.png
光流的测算

贴自 https://zh.wikipedia.org/wiki/%E5%85%89%E6%B5%81%E6%B3%95

几种测定方法

这里列举几个OpenCv实现了的测定算法:

Lucas-Kanade方法是由Bruce D. Lucas和Takeo Kanade开发的一种广泛使用的光流估计差分方法.它假设流在所考虑的像素的局部邻域中基本恒定,并且通过最小二乘准则解出该邻域中的所有像素的基本光流方程.
openCV 的API是 calcOpticalFlowPyrLK.

https://en.wikipedia.org/wiki/Lucas%E2%80%93Kanade_method

点这个链接,不错的理论解释(中文)http://image.sciencenet.cn/olddata/kexue.com.cn/upload/blog/file/2010/9/2010929122517964628.pdf

  • The Gunnar-Farneback optical flow

用Gunnar Farneback 的算法计算稠密光流(即图像上所有像素点的光流都计算出来)。它的相关论文是:"Two-Frame Motion Estimation Based on PolynomialExpansion"
opencv 的API 是 calcOpticalFlowFarneback.

论文地址: http://www.diva-portal.org/smash/get/diva2:273847/FULLTEXT01.pdf

  • block matching method

依赖于块匹配方法,OpenCv的API 是: CalcOpticalFlowBM.

  • Horn–Schunck method
    用Horn-Schunck 的算法计算稠密光流。OpenCv的API是 CalcOpticalFlowHS.
  • SimpleFlow

项目网站(源代码)http://graphics.berkeley.edu/papers/Tao-SAN-2012-05/

OpenCv的API是 calcOpticalFlowSF.

代码演示

对于代码,这里只演示计算量更少,更加适用于SLAM系统的Lucas–Kanade method. 我们首先需要使用 cv2.goodFeaturesToTrack()来寻找角点,然后在使用Lucas–Kanade method进行运动跟踪。

python
#!/usr/bin/python

import numpy as np
import cv2

# opencv-3.1.0/samples/data/768x576.avi
cap = cv2.VideoCapture('768x576.avi')

# params for ShiTomasi corner detection
feature_params = dict( maxCorners = 100,
                       qualityLevel = 0.3,
                       minDistance = 7,
                       blockSize = 7 )

# Parameters for lucas kanade optical flow
lk_params = dict( winSize  = (15,15),
                  maxLevel = 2,
                  criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))

# Create some random colors
color = np.random.randint(0,255,(100,3))

# Take first frame and find corners in it
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
p0 = cv2.goodFeaturesToTrack(old_gray, mask = None, **feature_params)

# Create a mask image for drawing purposes
mask = np.zeros_like(old_frame)

while(1):
    ret,frame = cap.read()
    if ret is True:
        print ret
        frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        # calculate optical flow
        p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)

        # Select good points
        good_new = p1[st==1]
        good_old = p0[st==1]

        # draw the tracks
        for i,(new,old) in enumerate(zip(good_new,good_old)):
            a,b = new.ravel()
            c,d = old.ravel()
            mask = cv2.line(mask, (a,b),(c,d), color[i].tolist(), 2)
            frame = cv2.circle(frame,(a,b),5,color[i].tolist(),-1)
        img = cv2.add(frame,mask)

        cv2.imshow('frame',img)
        k = cv2.waitKey(30) & 0xff
        if k == 27:
            break

        # Now update the previous frame and previous points
        old_gray = frame_gray.copy()
        p0 = good_new.reshape(-1,1,2)
    else:
        break

cv2.destroyAllWindows()
cap.release()

效果图

img_128a9144da04f7c5c72e3de7273ad067.png
效果图

这个理论由于基于一个很强的亮度不变的假设,因此具有较大的局限性,只能用于估计很小的运动。

参考文献

Application of local optical flow methods to high-velocity free-surface flows:
Validation and application to stepped chutes :http://staff.civil.uq.edu.au/h.chanson/reprints/Zhang_Chanson_etfs_2018.pdf (介绍了主流的几种光流算法)

https://blog.csdn.net/zouxy09/article/details/8683859(光流Optical Flow介绍与OpenCV实现)

http://image.sciencenet.cn/olddata/kexue.com.cn/upload/blog/file/2010/9/2010929122517964628.pdf (Lucas–Kanade method的中文理论推导)

http://vision.middlebury.edu/flow/floweval-ijcv2011.pdf (同一)

最后的最后

不足之处,敬请斧正; 若你觉得文章还不错,请关注微信公众号“SLAM 技术交流”继续支持我们,笔芯:D。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
纯js实现下载功能【附上js代码】
纯js实现下载功能【附上js代码】
14 0
一句代码实现批量数据绑定“.NET技术”[下篇]
  《上篇》主要介绍如何通过DataBinder实现批量的数据绑定,以及如何解决常见的数据绑定问题,比如数据的格式化。接下来,我们主要来谈谈DataBinder的设计,看看它是如何做到将作为数据源实体的属性值绑定到界面对应的控件上的。
623 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
18988 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
25226 0
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
20690 0
原生js代码实现秒表效果
jQuery用的多了,逐渐忘记了原生js如何书写代码。今天看到一个面试题,利用原生js写一个计算鼠标移入某个区域所停留的时长,移出暂停,再次移入累加。 于是想到了,利用原生js实现一个秒表效果。做之前也搜索了一些秒表效果,是利用setTimeout()实现的。本文是利用setInterval()定时器实现的。 html代码如下: <div> <span id
2012 0
js模拟点击事件实现代码
js模拟点击事件实现代码 类型:转载 时间:2012-11-06  在实际的应用开发中,我们会常常用到JS的模事件,比如说点击事件,举个简单的例子,点击表单外的“提交”按钮来提交表单。
1404 0
一句“.NET技术”代码实现批量数据绑定[下篇]
  《上篇》主要介绍如何通过DataBinder实现批量的数据绑定,以及如何解决常见的数据绑定问题,比如数据的格式化。接下来,我们主要来谈谈DataBinder的设计,看看它是如何做到将作为数据源实体的属性值绑定到界面对应的控件上的。
625 0
Wiondows 查询卷设备信息代码实现
NTSTATUS DPQueryVolumeInformation( PDEVICE_OBJECT DevObj, LARGE_INTEGER * TotalSize, DWORD * ClusterSize, DWO...
756 0
+关注
cleverzcc
机器人控制,SLAM技术,欣赏者。
18
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载