OpenCV Python 稠密光流 calcOpticalFlowFarneback 算法详解与实战
本文深入解析OpenCV中calcOpticalFlowFarneback函数,介绍Gunnar Farneback算法原理。详细列举pyr_scale、levels、winsize等关键参数的作用与取值建议,并提供基于摄像头实时处理的Python代码示例,展示如何计算并可视化密集光流场。
光流与稠密光流概述
光流描述了物体或相机运动导致图像中对象在连续两帧间的视在运动模式。光流算法通过计算时刻 t 和 t+Δt 拍摄的两帧图像中每个像素的运动位移来工作。这类方法属于差分法,基于图像信号的局部泰勒级数近似,即利用空间和时间坐标的偏导数进行计算。
与稀疏光流仅选取角点等特征点进行计算不同,稠密光流对图像进行逐像素匹配,计算所有点的偏移量以生成完整的光流场,进而用于图像配准。虽然其计算量显著高于稀疏光流,但通常能提供更优的处理效果。
核心函数为 calcOpticalFlowFarneback,用于实现上述功能。
def calcOpticalFlowFarneback(prev, next, flow, pyr_scale, levels, winsize, iterations, poly_n, poly_sigma, flags):
calcOpticalFlowFarneback 函数参数详解
该函数基于 Gunnar Farneback 算法来计算密集光流。
调用该函数时需配置以下关键参数:
prev:输入前一帧图像,要求为8位单通道图像。
next:输入后一帧图像,其大小和类型需与 prev 保持一致。
flow:输出计算得到的光流图像,大小与 prev 相同,数据类型为 CV_32FC2。
pyr_scale:指定构建图像金字塔的比例系数(需小于1)。例如 pyr_scale = 0.5 表示构建经典金字塔,即下一层图像尺寸比上一层小两倍。
levels:定义金字塔的层数,包含初始图像。若 levels = 1,则不创建额外层级,仅使用原始图像进行计算。
winsize:定义平均窗口的大小。较大的窗口值能增强算法对图像噪声的鲁棒性,并能检测更快的运动,但会导致生成的运动场更加模糊。
iterations:指定在每个金字塔层级上执行迭代算法的次数。该参数用于确定查找多项式展开时涉及的像素邻域范围。
poly_n:定义多项式展开的大小。较大的值意味着图像将被近似为更光滑的表面,从而产生更稳健的算法结果,但运动场也会更模糊。通常建议取值 poly_n = 5 或 7。
poly_sigma:用于平滑导数的标准高斯偏差,作为多项式展开的基础。当 poly_n = 5 时,可设置 poly_sigma = 1.1;当 poly_n = 7 时,可设置 poly_sigma = 1.5。
flags:操作标志,可选的计算方法包括:
OPTFLOW_USE_INITIAL_FLOW:使用输入的流场作为初始流近似值。
OPTFLOW_FARNEBACK_GAUSSIAN:使用大小为 winsize×winsize 的高斯滤波器替代默认的盒式滤波器进行光流估计。通常此选项能提供比盒式滤波器更精确的光流结果,但计算速度较慢;为实现相同的稳健性水平,通常需将高斯窗口的 winsize 设置为更大的值。
Python 代码实现示例
以下示例展示了如何在Python中应用该算法。
#!/usr/bin/python
# coding:utf8
import numpy as np
import cv2
step=10
if __name__ == '__main__':
cam = cv2.VideoCapture(0)
ret, prev = cam.read()
prevgray = cv2.cvtColor(prev, cv2.COLOR_BGR2GRAY)
while True:
ret, img = cam.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 使用Gunnar Farneback算法计算密集光流
flow = cv2.calcOpticalFlowFarneback(prevgray, gray, None, 0.5, 3, 15, 3, 5, 1.2, 0)
prevgray = gray
# 绘制线
h, w = gray.shape[:2]
y, x = np.mgrid[step / 2:h:step, step / 2:w:step].reshape(2, -1).astype(int)
fx, fy = flow[y, x].T
lines = np.vstack([x, y, x + fx, y + fy]).T.reshape(-1, 2, 2)
lines = np.int32(lines)
line = []
for l in lines:
if l[0][0]-l[1][0]>3 or l[0][1]-l[1][1]>3:
line.append(l)
cv2.polylines(img, line, 0, (0,255,255))
cv2.imshow('flow', img)
ch = cv2.waitKey(5)
if ch == 27:
break
cv2.destroyAllWindows()

以上关于OpenCV 3/Python中稠密光流 calcOpticalFlowFarneback 的详解内容分享完毕,希望能为读者提供参考。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













