OpenCV Python Optical Flow (光流)

【目标】

  • 了解光流的概念和用 Lucas-Kanade 算法估计光流
  • 我们将使用cv2.calcOpticalFlowPyrLK()这样的函数来跟踪视频中的特征点。
  • 们将使用cv2.calcOpticalFlowFarneback()方法创建一个密集的光流场,可以用于前景检测。

【理论】

光流是由物体或相机的运动引起的图像物体在两个连续帧之间的表观运动模式。这是一个二维矢量场,其中每个矢量都是一个位移矢量,显示点从第一帧到第二帧的运动。

它显示了一个球在连续5帧中的移动,箭头表示位移矢量。光流有很多应用领域,如:

运动结果
视频压缩
视频稳定。。。

光流的工作原理有以下几个假设:

目标的像素亮度在连续帧中是恒定的。
相邻像素有相似的运动;

假设第一帧中有一个像素 I(x,y,t)I(x, y, t)I(x,y,t),这里增加了一个 时间维度 ttt, 下一帧中移动了 (dx,dy)(dx, dy)(dx,dy), 因为像素的亮度没有改变,所以

I(x,y,t)=I(x+dx,y+dy,t+dt)I(x, y, t) = I(x+dx, y+dy, t+dt) I(x,y,t)=I(x+dx,y+dy,t+dt)

对上式中的右边进行泰勒级数展开,去掉公约数并且除以 dtdtdt,得到下式

fxu+fyv+ft=0f_xu+f_yv+f_t=0 fx​u+fy​v+ft​=0

其中:

fx=∂f∂xfy=∂f∂yu=dxdt,v=dydtf_x = \frac{\partial f}{\partial x} f_y = \frac{\partial f}{\partial y} \\ u = \frac{dx}{dt}, v = \frac{dy}{dt} fx​=∂x∂f​fy​=∂y∂f​u=dtdx​,v=dtdy​

上面的方程为光流方程,fx,fyf_x,f_yfx​,fy​为图像的梯度,ftf_tft​为图像在时间上的梯度,但是 (u,v)(u,v)(u,v)是不知道的,一个方程不能求解两个未知参数,所以,有很多方法来求解该问题,例如其中的 Lucas-Kanade 方法。

  • Lucas-Kanade 方法

之前有一个假设,那就是相邻像素有相似的运动。Lucas-Kanade方法在点周围取 3∗33*33∗3块,所以,9个点的运动方向相同,可以求出9个点的 (fx,fy,ft)(f_x, f_y,f_t)(fx​,fy​,ft​),可以用最小二乘法得到较好的解。

[uv]=[∑fxi2∑fxifyi∑fxifyi∑fyi2]−1[−∑fxifti−∑fyifti]\begin{bmatrix} u\\v \end{bmatrix} = \begin{bmatrix} \sum f_{x_i}^2 & \sum f_{x_i}f_{y_i}\\ \sum f_{x_i}f_{y_i} & \sum f_{y_i}^2 \end{bmatrix}^{-1} \begin{bmatrix} -\sum f_{x_i}f_{t_i}\\ -\sum f_{y_i}f_{t_i} \end{bmatrix} [uv​]=[∑fxi​2​∑fxi​​fyi​​​∑fxi​​fyi​​∑fyi​2​​]−1[−∑fxi​​fti​​−∑fyi​​fti​​​]

用harris角点检测器来检查逆矩阵的相似性,表明角点确实是跟踪的比较好的点。

所以从用户的角度来看,想法很简单,我们给一些点来跟踪,我们得到了这些点的光流矢量,但还是有一些问题,例如大的运动就失效了,为了解决这个问题,我们使用金字塔,当金字塔在上升时,小的运动被移除了,大的运动变成了小的运动,所以通过运用 Lucas-Kanade, 我们得到了光流。

【代码】

import numpy as np
import cv2videoname = "assets/slow_traffic_small.mp4"
cap = cv2.VideoCapture(videoname)# ShiTomasi角点检测的参数
feature_params = dict(maxCorners=100,qualityLevel=0.3,minDistance=7,blockSize=7)
# lucas-kanade光流参数
lk_params = dict(winSize=(15, 15),maxLevel=2,criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))# 随机颜色
color = np.random.randint(0, 255, (100, 3))# 找到利于跟踪的角点
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 not ret:print('No frames grabbed!')break# 灰度化frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 计算光流p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)# 选择好的跟踪点if p1 is not None:good_new = p1[st == 1]good_old = p0[st == 1]# 画跟踪效果for i, (new, old) in enumerate(zip(good_new, good_old)):a, b = new.ravel()c, d = old.ravel()mask = cv2.line(mask, (int(a), int(b)),(int(c), int(d)), color[i].tolist(), 2)frame = cv2.circle(frame, (int(a), int(b)), 5, color[i].tolist(), -1)img = cv2.add(frame, mask)cv2.imshow('optical_flow', img)k = cv2.waitKey(30) & 0xffif k == 27:break# Now update the previous frame and previous pointsold_gray = frame_gray.copy()p0 = good_new.reshape(-1, 1, 2)
cv2.destroyAllWindows()
  • Dense Optical Flow(稠密光流)

Lucas-Kanade方法计算稀疏特征集的光流(在我们的例子中,使用Shi-Tomasi算法检测角)。OpenCV提供了另一种查找密集光流的算法。它计算帧中所有点的光流。它基于Gunnar Farneback的算法,Gunnar Farneback在2003年的“基于多项式展开的两帧运动估计”中解释了该算法。

import numpy as np
import cv2cap = cv2.VideoCapture(cv2.samples.findFile("assets/vtest.avi"))
ret, frame1 = cap.read()
prvs = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
hsv = np.zeros_like(frame1)
hsv[..., 1] = 255
while (1):ret, frame2 = cap.read()if not ret:print('No frames grabbed!')breaknext = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)flow = cv2.calcOpticalFlowFarneback(prvs, next, None, 0.5, 3, 15, 3, 5, 1.2, 0)mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])hsv[..., 0] = ang*180/np.pi/2hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)cv2.imshow('DenseOpticalFlow', bgr)cv2.imshow('src', frame2)k = cv2.waitKey(30) & 0xffif k == 27:breakelif k == ord('s'):cv2.imwrite('opticalfb.png', frame2)cv2.imwrite('opticalhsv.png', bgr)prvs = next
cv2.destroyAllWindows()

【接口】

  • calcOpticalFlowPyrLK
cv2.calcOpticalFlowPyrLK(    prevImg, nextImg, prevPts, nextPts[, status[, err[, winSize[, maxLevel[, criteria[, flags[, minEigThreshold]]]]]]]  ) -> nextPts, status, err

利用Lucas-Kanade方法和金字塔为稀疏特征点计算光流,

  • prevImg: 上一张 8位 图像,
  • nextImg: 第二张输入图像,尺寸和类型与上一张一样
  • prevPts: 2D points 的 vector,需要计算光流的点
  • nextPts: 输出的二维点集,在第二张图像中计算出来的特征点的位置;
  • status: 输出的状态,如果找到了对应的点,则为1,否则为0
  • err: 输出的误差,每一个元素就是对应点的误差,如果没有找到光流,则误差没有定义;
  • winSize: 搜索窗口
  • maxLevel: 0层为最大的金字塔层数,如果设置为0,则不用金字塔,如果设置为1,则使用两层。。。
  • criterial: 终止条件,可以设置最大次数或者最小误差;
  • flags: 操作标志: OPTFLOW_USE_INITIAL_FLOW & OPTFLOW_LK_GET_MIN_EIGENVALS
  • minEigThreshold: 最小特征值,如果特征值小于这个阈值,则对应的特征会被过滤掉,或者不处理,
  • goodFeaturesToTrack

【OpenCV-Python】教程:4-3 Shi-Tomasi 角点检测

  • calcOpticalFlowFarneback
cv2.calcOpticalFlowFarneback(    prev, next, flow, pyr_scale, levels, winsize, iterations, poly_n, poly_sigma, flags ) -> flow

利用Gunnar Farneback 算法计算稠密光流

  • prev: 第一张8位单通道图像
  • next: 第二张8位单通道图像
  • flow: 输出的光流,类型为 CV_32FC2,一个是方向,一个是梯度
  • pyr_scale: 金字塔缩放的长度,如果为0.5,则是经典的金字塔图像,即下一层是前一层的一半;
  • levels: 包含初始图像的层级, levels=1则没有创建额外的层,只使用原始的图像
  • winsize: 平均窗口尺寸,值越大,会增加算法的鲁棒性可以应对快速的运动
  • iterations: 迭代次数
  • poly_n: 每个像素的多项式展开,值越大,越平滑,一般设置为5或7
  • poly_sigma: 标准差,如果 poly_n 为5, 则为1.1, 如果 poly_n 为 7, 则设置为 1.5
  • flags: OPTFLOW_USE_INITIAL_FLOW, OPTFLOW_FARNEBACK_GAUSSIAN

prev(y,x)∼next(y+flow(y,x)[1],x+flow(y,x)[0])prev(y,x)∼next(y+flow(y,x)[1],x+flow(y,x)[0]) prev(y,x)∼next(y+flow(y,x)[1],x+flow(y,x)[0])

【参考】

  1. OpenCV: Optical Flow
  2. Object Tracking
  3. Jean-Yves Bouguet. Pyramidal implementation of the affine lucas kanade feature tracker description of the algorithm. Intel Corporation , 5, 2001.
  4. Gunnar Farnebäck. Two-frame motion estimation based on polynomial expansion. In Image Analysis , pages 363–370. Springer, 2003.

【OpenCV-Python】教程:5-3 光流相关推荐

  1. OpenCV Python教程(2、图像元素的访问、通道分离与合并)

    OpenCV Python教程之图像元素的访问.通道分离与合并 转载请详细注明原作者及出处,谢谢! 访问像素 像素的访问和访问numpy中ndarray的方法完全一样,灰度图为: [python] v ...

  2. OpenCV Python教程(3)(4)(5): 直方图的计算与显示 形态学处理 初级滤波内

    OpenCV Python教程(3.直方图的计算与显示) 本篇文章介绍如何用OpenCV Python来计算直方图,并简略介绍用NumPy和Matplotlib计算和绘制直方图 直方图的背景知识.用途 ...

  3. opencv python教程简书_OpenCV-Python系列二:常用的图像属性

    对于图像,我们经常需要知道关于图像的特殊属性,比如宽度,高度,面积,像素点数目等等,那么在opencv-python中,这些信息如何获取呢? 本文结构: 1.基本图像属性 2. 对于opencv中的特 ...

  4. opencv python教程-OpenCV4 Python 最新中文版官方教程来了(附下载)

    教程简介 OpenCV 是计算机视觉中经典的专用库,然而其中文版官方教程久久不来.近日,一款最新 OpenCV4.1 版本的完整中文版官方教程出炉,读者朋友可以更好的学习了解 OpenCV 相关细节. ...

  5. OpenCV Python教程(1、图像的载入、显示和保存)

    本文是OpenCV  2 Computer Vision Application Programming Cookbook读书笔记的第一篇.在笔记中将以Python语言改写每章的代码. PythonO ...

  6. opencv python教程简书_Python-OpenCV —— 基本操作一网打尽

    OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux.Windows.MacOS操作系统上.它轻量级而且高效--由一系列 C 函数和少量C++类构成,同时提供了Pyt ...

  7. 机器视觉 OpenCV—python目标跟踪(光流)

    文章目录 一.运动检测 1.1 检测思路 1.2 代码 二.运动方向预测 2.1 关键点(角点)追踪 goodFeaturesToTrack() 2.2 光流法 一.运动检测 1.1 检测思路 目标跟 ...

  8. OpenCV Python教程系列

    参考: OpenCV - sunny2038的专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/sunny2038/article/category/904451

  9. opencv python教程简书_OpenCV-Python教程:27.图像转换

    理论 傅里叶变换用来分析多种过滤器的频率特征.对于图片,2D离散傅里叶变换(DFT)用来找频率范围.一个快速算法叫快速傅里叶变换(FFT)用来计算DFT. 对于正弦信号,x(t) = Asin(2πf ...

  10. opencv python教程简书_OpenCV-Python教程:28.模板匹配

    理论 模板匹配是在一个大图里搜索和找模板图像位置的方法.OpenCV有个函数cv2.matchTemplate()来做这个.它吧模板图像在输入图像上滑动,对比模板和在模板图像下的输入图像块.它返回了一 ...

最新文章

  1. Java 内部类分析
  2. 360脱口秀:‘未来属于虚拟’开播啦!
  3. Linq to sql查询句法
  4. 检索数据_9_返回的字段在某个范围内的数据
  5. marlin 三角洲_三角洲湖泊和数据湖泊-入门
  6. spring学习(23):基础组件
  7. 4.1.3数据报与虚电路
  8. 灰度内测是什么意思?
  9. firefox flash插件_巧用firefox下载视频资源
  10. 中国好岳父?女婿亏掉公司半个亿 岳父3天还清!涉事公司回应了
  11. 来了!华为首款5G双模手机Mate 20 X (5G)发布:这个价格香吗?
  12. 第38周星期四电话会议忙碌的一天
  13. 保存位图位图保存时上下颠倒?
  14. 教你实现一个 iOS 重签名工具
  15. 【火炉炼AI】机器学习053-数据降维绝招-PCA和核PCA
  16. 解决macOS无法在线升级更新的问题
  17. ORACLE ORDER BY用法总结
  18. html打印页标题行,打印标题行的设置方法
  19. 【转】ubuntu下为APT设置代理
  20. EasyUI下拉列表中实现输入框不可手动输入

热门文章

  1. 智慧城市一卡通如何开通
  2. [附源码]计算机毕业设计JAVA领导干部听课评课管理系统
  3. 设置360浏览器的背景为护眼模式(浅豆绿色)
  4. python设置背景颜色为豆绿色_eclipse 设置豆沙绿保护色,保护眼睛
  5. 计算机基础教学质量分析报告,张丹菲信息技术质量分析报告1
  6. 这些行业已经开始用数据挖掘了,我们的前途光明
  7. Java导出excel文件
  8. 使用KCP 加速游戏消息,让全球玩家流畅联网
  9. 10月14日科技资讯|华为折叠屏手机月底或开卖;苹果计划 3 年内推出 5G 基带芯片;Node.js 12.12.0 发布 | 极客头条
  10. 多发性胆囊息肉有哪些危害?