📜  OpenCV – Gunnar-Farneback 光流

📅  最后修改于: 2022-05-13 01:54:25.813000             🧑  作者: Mango

OpenCV – Gunnar-Farneback 光流

在本文中,我们将了解 Gunnar FarneBack 技术的 Dense Optical Flow,它发表在 Gunnar Farneback 于 2003 年发表的名为“基于多项式展开的双帧运动估计”的研究论文中。
先决条件: OpenCV
光流:
光流被称为物体的视运动模式,即,它是在序列的每两个连续帧之间的物体的运动,它是由被捕获的物体或捕获它的相机的运动引起的。考虑一个强度为I (x, y, t)的物体,在时间dt之后,它移动到dxdy ,现在,新的强度将是I (x+dx, y+dy, t+dt)

我们假设两帧之间的像素强度是恒定的,即
I (x, y, t) = I (x+dx, y+dy, t+dt)
泰勒近似是在 RHS 一侧进行的,结果是,

除以δt ,我们得到光流方程,即

其中, u = dx/dtv = dy/dt
此外, dI/dx是沿水平轴的图像梯度, dI/dy是沿垂直轴的图像梯度,dI/dt 是沿时间的。
因为,我们只有一个方程可以找到两个未知数,所以我们使用不同的方法来求解,

  • 稀疏光流(Lucas Kanade 方法)
  • 密集光流(Gunnar Farneback 方法)

Gunnar Farneback 光流
在密集光流中,我们查看所有的点(不像 Lucas Kanade,它只对 Shi-Tomasi 算法检测到的角点起作用)并检测两帧之间的像素强度变化,从而在转换后生成具有高亮像素的图像转换为 hsv 格式以便清晰可见。
它根据流向量的数组计算光流的大小和方向,即(dx/dt, dy/dt) 。后来它通过色调可视化流动的角度(方向),通过 HSV 颜色表示的值可视化流动的距离(大小)。为了获得最佳可见性,HSV 的强度设置为 255。OpenCV 提供了一个函数cv2.calcOpticalFlowFarneback来查看成密集的光流。
句法:

cv2.calcOpticalFlowFarneback(prev, next, pyr_scale, levels, winsize, iterations, poly_n, poly_sigma, flags[, flow])

参数:

  • prev :第一张 8 位单通道格式的输入图像。
  • next :prev相同类型和相同大小的第二个输入图像。
  • pyr_scale :参数指定为每个图像构建金字塔的图像比例(比例 < 1)。经典金字塔一般为 0.5 级,每增加一层,前一层减半。
  • levels : levels=1表示,没有额外的层(只有初始图像)。它是包括第一张图像的金字塔层数。
  • winsize :它是平均窗口大小,大小越大,算法对噪声的鲁棒性越强,并提供快速运动检测,但会产生模糊的运动场。
  • 迭代次数:在每个金字塔级别执行的迭代次数。
  • poly_n :通常为 5 或 7,它是像素邻域的大小,用于查找像素之间的多项式展开。
  • poly_sigma :作为多项式展开的基础,导数平滑的高斯标准差。对于poly= 5 ,它可以是 1.1,对于poly = 7,它可以是 1.5。
  • flow :计算出的流图像,其大小与prev相似,类型为 CV_32FC2。
  • 标志:它可以是 -
    OPTFLOW_USE_INITIAL_FLOW 使用输入流作为初始近似值。
    OPTFLOW_FARNEBACK_GAUSSIAN 使用高斯winsize*winsize过滤器。

代码:

Python3
# Importing libraries
import cv2
import numpy as np
# Capturing the video file 0 for videocam else you can provide the url
capture = cv2.VideoCapture("video_file.avi")
 
# Reading the first frame
_, frame1 = capture.read()
# Convert to gray scale
prvs = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
# Create mask
hsv_mask = np.zeros_like(frame1)
# Make image saturation to a maximum value
hsv_mask[..., 1] = 255
 
# Till you scan the video
while(1):
     
    # Capture another frame and convert to gray scale
    _, frame2 = capture.read()
    next = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
 
    # Optical flow is now calculated
    flow = cv2.calcOpticalFlowFarneback(prvs, next, None, 0.5, 3, 15, 3, 5, 1.2, 0)
    # Compute magnite and angle of 2D vector
    mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])
    # Set image hue value according to the angle of optical flow
    hsv_mask[..., 0] = ang * 180 / np.pi / 2
    # Set value as per the normalized magnitude of optical flow
    hsv_mask[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
    # Convert to rgb
    rgb_representation = cv2.cvtColor(hsv_mask, cv2.COLOR_HSV2BGR)
 
    cv2.imshow('frame2', rgb_representation)
    kk = cv2.waitKey(20) & 0xff
    # Press 'e' to exit the video
    if kk == ord('e'):
        break
    # Press 's' to save the video
    elif kk == ord('s'):
        cv2.imwrite('Optical_image.png', frame2)
        cv2.imwrite('HSV_converted_image.png', rgb_representation)
    prvs = next
 
capture.release()
cv2.destroyAllWindows()


输入

输出:

  • https://docs.opencv.org/2.4/modules/video/doc/motion_analysis_and_object_tracking.html