【OpenCV-Python】教程:5-3 光流

news2024/11/23 3:35:38

OpenCV Python Optical Flow (光流)

【目标】

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

【理论】

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

在这里插入图片描述

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

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

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

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

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

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

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

f x u + f y v + f t = 0 f_xu+f_yv+f_t=0 fxu+fyv+ft=0

其中:

f x = ∂ f ∂ x f y = ∂ f ∂ y u = d x d t , v = d y d t f_x = \frac{\partial f}{\partial x} f_y = \frac{\partial f}{\partial y} \\ u = \frac{dx}{dt}, v = \frac{dy}{dt} fx=xffy=yfu=dtdx,v=dtdy

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

  • Lucas-Kanade 方法

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

[ u v ] = [ ∑ f x i 2 ∑ f x i f y i ∑ f x i f y i ∑ f y i 2 ] − 1 [ − ∑ f x i f t i − ∑ f y i f t i ] \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]=[fxi2fxifyifxifyifyi2]1[fxiftifyifti]

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

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

【代码】

在这里插入图片描述

import numpy as np
import cv2

videoname = "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) & 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)
cv2.destroyAllWindows()

  • Dense Optical Flow(稠密光流)

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

在这里插入图片描述

import numpy as np
import cv2

cap = 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!')
        break
    next = 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/2
    hsv[..., 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) & 0xff
    if k == 27:
        break
    elif 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

p r e v ( y , x ) ∼ n e x t ( y + f l o w ( y , x ) [ 1 ] , x + f l o w ( 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.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/91266.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]Python计算机毕业设计高校心理咨询管理系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等…

Java+SSH实验室预约系统(含源码+论文+答辩PPT等)

该项目采用技术: 后台:SpringSpringmvcHibernate 前台JqueryMy97DatePickercssjs 使用了MySQLTomcat等相关技术 项目含有源码、文档、配套开发软件、软件安装教程、项目发布教程等 本系统的用户可以分为三种:管理员、教师、学生。以下针对三种…

协同共进 | 中睿天下入会工业信息安全产业发展联盟

近日,中睿天下加入“工业信息安全产业发展联盟”,成为新一批会员单位。 工业信息安全是网络安全、国家安全的重要组成部分,涉及工业领域各个环节,涵盖工业控制系统安全、工业互联网安全、工业数据安全等各领域,直接关系到经济发展…

u盘出现fat32如何恢复文件?告诉你两种好方法

u盘由于体积小、内存大等优势,在日常生活领域应用的很多,但是使用过程中,总会遇到这样或那样的问题,比如u盘显示fat32打开啥都没有了?或者u盘出现fat32而无法访问的情况,这时如果里面有重要的数据怎么办呢&…

Activiti 工作流引擎

一、什么是工作流? 工作流:指业务过程的部分或整体在计算机应用环境下的自动化。是对工作流程及其各操作步骤之间业务规则的抽象、概括描述。在计算机中,工作流属于计算机支持的协同工作(CSCW)的一部分,后者是普遍研究…

win7无损合并分区,win7合并磁盘分区

电脑的操作系统是win7的,如果磁盘分区太小或者说磁盘分区不合理,需要对磁盘分区重新分区,其中合并磁盘分区就是解决方法之一,那么,有没有关于win7无损合并分区的操作方法呢? 一、利用Windows自带的功能来合…

Matlab|基于BP神经网络进行电力系统短期负荷预测

目录 摘要 一、电力负荷数据导入 二、输入输出数据归一化 三、建立和训练BP神经网络 四、 使用测试数据进行负荷预测 五、Matlab代码实现 摘要 使用BP神经网络实现简单的电力负荷回归预测任务。主要的步骤为:导入数据、数据归一化、建立BP神经网络、训练BP神…

熹乐科技范维肖CC:基于开源 YoMo 框架构建“全球同服”的 Realtime Metaverse Application

前言 在「RTE2022 实时互联网大会」中,熹乐科技创始人 & CEO 范维肖CC 以《基于开源 YoMo 框架构建“全球同服”的 Realtime Metaverse Application》为题进行了主题演讲。 本文内容基于演讲内容进行整理,为方便阅读略有删改。 大家好,…

chatGPT的爆火,是计算机行业这次真的“饱和”了?

近日,chatGPT这一生成式AI爆火,这款号称神仙级别的自动语言生成式AI发布短短5天内,就吸引了100万用户,在官方描述中,chatGPT是一个“可以连续回答问题、承认自己的错误、挑战不正确的前提并拒绝不适当的要求”的对话模…

【GO】 K8s 管理系统项目[API部分--Deployment]

K8s 管理系统项目[API部分–Deployment] 1. 实现接口 service/dataselector.go package serviceimport ("sort""strings""time"appsv1 "k8s.io/api/apps/v1"corev1 "k8s.io/api/core/v1" )// dataselector 用于排序,过滤…

第11讲:vue脚手架集成ElementUI

一、创建vue路由项目并添加ElementUI支持 ElementUI官方网站:ElementUI组件 创建路由项目请参考:路由开发 使用如下命令集成ElementUI npm i element-ui -S在src/main.js文件中引用ElementUI import Vue from vue import App from ./App.vue import …

创建第一个QT程序demo

双击Qt Creator 9.0.0 (Community)图标,打开软件。该图标所处位置为(如果是默认安装到C盘下面的话):C:\Qt\Tools\QtCreator\bin\qtcreator.exe 或者从开始菜单栏启动(开始菜单栏的启动图标本质上也是一个快捷方式&…

记录windows上的VSCODE 远程到linux编译代码机器上的一些问题

设置windows SSH 到linux时免密码登录的方法: 将C:\Users\Administrator.ssh\id_rsa.pub中的公钥字符串复制,追加到linux ~/.ssh/authorized_keys文件中。 问题: rootlocalhost:~/.vscode-server/bin/6261075646f055b99068d3688932416f2346d…

[附源码]Node.js计算机毕业设计服装创意定制管理系统Express

项目运行 环境配置: Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术: Express框架 Node.js Vue 等等组成,B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境:最好是Nodejs最新版,我…

【Redis技术探索】「底层架构原理」探索分析服务数据同步持久化机制

📚背景介绍 ✒️ Redis数据恢复的介绍 通常情况下redis的数据全部存储在内存中,数据库一旦故障发生重启数据会全部丢失,持久化功能在于能够有效地避免因进程退出造成的数据丢失问题,在下次重启时利用之前持久化的文件即可实现数据…

【学习打卡】ZFNet深度学习图像分类算法

文章目录引言可以学到什么为什么叫ZFNetZFNet的网络结构简介方法:可视化反卷积反池化反激活反卷积训练细节大小裁剪层可视化特征可视化第 1 层第 2 层两边的对应关系更深的层第 3 层第 4 层第 5 层特征演化特征不变性实验简介图的分析模型改进:AlexNet局…

【愚公系列】2022年12月 Elasticsearch数据库-ELK添加中文分词器插件(三)

文章目录前言1.IK分词器2.pingying分词器一、ELK添加中文分词器插件1.IK分词器测试1.1 文件准备1.2 测试2.pingying分词器测试2.1 文件准备2.2 测试2.2.1 单个测试2.2.2 多个测试2.2.3 短语查询测试2.2.3.1 medcl2索引2.2.3.2 medcl3索引前言 分词器的作用是把一段文本中的词按…

Python学习基础笔记五十一——学校管理系统

完成一个作业: 1. 创建北京、上海 2 所学校 2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开 3. 课程包含,周期,价格 4. 班级关联课程、讲师 5. 创建学员时,选择学校,关联…

从零开始搭建CentOS7虚拟机系统、MySQL5.7和Redis3服务

CentOS7搭建MySQL和Redis服务 为什么不直接搭建高版本的呢? 因为有些公司的环境就是低版本的,这些低版本的环境也需要学会如何搭建。 准备工作 搭建一个CentOS7系统 第一步:先下载一个CentOS7的iso文件 点击直接下载:https:…

Odoo丨如何改造Odoo原生form表单使其更好看

文章目录前言一、原生表单实现方式二、问题发现与分析1.项目中遇到问题2.问题具体分析三、具体解决方法第一步:把Span变成输入框第二步:改写_renderFieldWidget前言 Odoo作为快速搭建系统的框架,我们在利用它便捷高效功能的同时,…