光流运动估计教程

概要

计算机视觉研究的进步通过利用诸如用于识别属于特定类别的对象的对象检测和用于像素级分类的语义分割等技术,彻底改变了机器感知环境的方式。然而,当涉及实时视频处理时,这些技术的大多数实现仅考虑同一帧(x,y)内对象的空间关系,而忽略时间方面(t)。这意味着每个帧都是独立评估的,与之前或未来的帧没有任何关联。但是,如果我们需要连续帧之间的关系怎么办?例如,如果我们想要跟踪车辆跨帧的运动以估计其当前速度并预测其在下一帧中的位置该怎么办?请添加图片描述
交通的稀疏光流(每个箭头都指向相应像素的预测流的方向)。

或者,如果我们需要连续帧之间的人体姿势关系信息来识别射箭、棒球和篮球等人类动作,该怎么办?

在这里插入图片描述
各种行动分类
在这里插入图片描述
使用光流对动作进行分类

在本教程中,我们将了解光流是什么,如何实现它的两个主要变体(稀疏和密集),并全面了解涉及深度学习的最新方法和有前途的未来方向。

什么是光流?

让我们从对光流的高层次理解开始。光流是对象在序列的连续帧之间的运动,由对象和相机之间的相对运动引起。光流问题可以表示为:
在这里插入图片描述
光流问题

在连续帧之间,我们可以将图像强度 (I) 表示为空间 (x,y) 和时间 (t) 的函数。换句话说,如果我们获取第一张图像 I(x,y,t) 并在 t 时间内将其像素移动 (dx,dy),我们将获得新图像 I(x+dx,y+dy,t+dt) )。

首先,我们假设物体的像素强度在连续帧之间是恒定的。

在这里插入图片描述

光流的恒定强度假设

其次,我们采用RHS的泰勒级数近似,并去除常用项。

泰勒级数:像素强度的近似值

第三,我们除以dt来推导出光流方程:

在这里插入图片描述
光流方程,其中 u=dx/dt 和 v=dy/dt

dI/dx、dI/dy 和 dI/dt 是沿横轴、纵轴和时间的图像梯度。因此,我们总结了光流问题,即求解 u(dx/dt) 和 v(dy/dt) 以确定随时间的运动。您可能会注意到,我们无法直接求解 u 和 v 的光流方程,因为两个未知变量只有一个方程。我们将实施一些方法,例如 Lucas-Kanade 方法来解决这个问题。

稀疏光流与密集光流

稀疏光流给出了帧内一些“有趣的特征”(例如描绘物体边缘或角落的几个像素)的流动向量,而密集光流,它给出了整个帧(所有像素)的流动向量——每个像素最多一个流动向量。正如您已经猜到的那样,密集光流具有更高的精度,但代价是速度慢/计算成本高。

在这里插入图片描述
左:稀疏光流 – 跟踪几个“特征”像素;右图:密集光流 – 估计图像中所有像素的流量。

实现稀疏光流

稀疏光流选择一组稀疏的像素特征(例如,有趣的特征,如边缘和角落)来跟踪其速度矢量(运动)。提取的特征在光流函数中从一帧传递到另一帧,以确保跟踪相同的点。稀疏光流有多种实现方式,包括 Lucas-Kanade 方法、Horn-Schunck 方法、Buxton-Buxton 方法等。我们将使用 Lucas-Kanade 方法与 OpenCV(一个开源的计算机视觉算法库)进行实现。

1. 设置环境

如果您尚未安装 OpenCV,请打开终端并运行:

pip install opencv-python

现在,克隆教程软件仓库:

git clone https://github.com/chuanenlin/optical-flow.git

接下来,使用文本编辑器打开 sparse-starter.py。我们将在这个 Python 文件中编写所有代码。

2.配置OpenCV读取视频并设置参数


import cv2 as cv
import numpy as np
 
# Parameters for Shi-Tomasi corner detection
feature_params = dict(maxCorners = 300, qualityLevel = 0.2, minDistance = 2, blockSize = 7)
# Parameters for Lucas-Kanade optical flow
lk_params = dict(winSize = (15,15), maxLevel = 2, criteria = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 0.03))
# The video feed is read in as a VideoCapture object
cap = cv.VideoCapture("shibuya.mp4")
# Variable for color to draw optical flow track
color = (0, 255, 0)
# ret = a boolean return value from getting the frame, first_frame = the first frame in the entire video sequence
ret, first_frame = cap.read()
 
while(cap.isOpened()):
    # ret = a boolean return value from getting the frame, frame = the current frame being projected in the video
    ret, frame = cap.read()
    # Frames are read by intervals of 10 milliseconds. The programs breaks out of the while loop when the user presses the 'q' key
    if cv.waitKey(10) & 0xFF == ord('q'):
        break
# The following frees up resources and closes all windows
cap.release()
cv.destroyAllWindows()

3. Grayscaling 3. 灰度化

import cv2 as cv
import numpy as np
 
# Parameters for Shi-Tomasi corner detection
# feature_params = dict(maxCorners = 300, qualityLevel = 0.2, minDistance = 2, blockSize = 7)
# Parameters for Lucas-Kanade optical flow
# lk_params = dict(winSize = (15,15), maxLevel = 2, criteria = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 0.03))
# The video feed is read in as a VideoCapture object
# cap = cv.VideoCapture("shibuya.mp4")
# Variable for color to draw optical flow track
# color = (0, 255, 0)
# ret = a boolean return value from getting the frame, first_frame = the first frame in the entire video sequence
# ret, first_frame = cap.read()
# Converts frame to grayscale because we only need the luminance channel for detecting edges - less computationally expensive
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

点PY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值