opencv3/Python 稠密光流calcOpticalFlowFarneback详解

  • Post category:Python

opencv3/Python稠密光流calcOpticalFlowFarneback详解

稠密光流是计算机视觉中的一个重要问题,它可以用来估计图像中每个像素的运动。OpenCV提供了多种稠密光流算法,其中calcOpticalFlowneback是一种常用的算法。本攻略将详细讲解如何使用OpenCV3和Python实现calcOpticalFlowFarneback算法,并提供两个示例。

步骤一:导入库

在使用OpenCV3和Python实现calcOpticalFlowFarneback算法之前,我们需要先导入相关的库。下面是一个简单的示例:

import cv2
import numpy as np

在上面的代码中,我们导入了OpenCV和NumPy库。

步骤二:读取视频

在使用OpenCV3和Python实现calcOpticalFlowFarneback算法之前,我们需要先读取视频。下面是一个简单的示例:

# 读取视频
cap = cv2.VideoCapture('test.mp4')

# 获取第一帧
ret, frame1 = cap.read()

# 转换为灰度图像
prvs = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)

在上面的代码中,我们使用2.VideoCapture方法读取视频,然后使用cap.read方法获取第一帧图像。接着,我们使用cv2.cvtColor方法将图像转换为灰度图像。

步骤三:计算稠密光流

在读取视频之后,我们可以使用OpenCV3和Python计算稠光流。下面是一个简单的示例:

# 计算稠密光流
while(1):
    ret, frame2 = cap.read()
    if ret:
        next = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
        flow = cv2.calcOpticalFlowFarneback(prvs, next, None, 0.5, 3, 15, 3, 5, 1.2, 0)
        # 可视化稠密光流
        hsv = np.zeros_like(frame2)
        hsv[...,1] = 255
        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(hsv2.COLOR_HSV2BGR)
        cv2.imshow('frame2',bgr)
        k = cv2.waitKey(30) & 0xff
        if k == 27:
            break
        # 更新前一帧
       vs = next
    else:
        break

在上面的代码中,我们使用cv2.calcOpticalFlowFarneback方法计算稠密光流,并使用cv2.cartToPolar方法将光流向量转换为极坐标形式。接着,使用cv2.normalize方法将光流强度归一化到0-255之间,并使用cv2.cvtColor方法将图像从HSV颜色空间转换为BGR颜色空间。最后,我们使用cv2.imshow方法显示可视化的稠密光,并使用cv2.waitKey方法等待用户按下ESC键退出程序。

示例一:稠密光流跟踪运动目标

下面是一个稠密光流跟踪运动目标的示例:

import cv2
import numpy as np

# 读取视频
cap = cv2.VideoCapture('test.mp4')

# 获取第一帧
ret, frame1 = cap.read()

# 转为灰度图像
prvs = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)

# 定义ROI
r,h,c,w = 250,90,400,125
track_window = (c,r,w,h)

# 设置追踪器参数
term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRIA_COUNT, 10, 1 )

# 计算稠密光流
while(1):
    ret, frame2 = cap.read()
    if ret:
        next = cv2.cvtColor(frame2, cv2.COLOR_BGR2)
        flow = cv2.calcOpticalFlowFarneback(prvs, next, None, 0.5, 3, 15, 3, 5, 1.2, 0)
        # 可视化稠密光流
        hsv = np.zeros_like(frame2)
        hsv[...,1 = 255
        mag, ang = cv2.cartToPolar(flow[...,0], flow[...,1])
        hsv[...,0] = ang*180/np.pi/2
        hsv[...,2] = cv2.normalize(mag,None,,255,cv2.NORM_MINMAX)
        bgr = cv2.cvtColor(hsv,cv2.COLOR_HSV2BGR)
        cv2.imshow('frame2',bgr)
        # 追踪运动目标
        if c > 0 and r > 0 and w > 0 and h > 0:
            roi = bgr[r:r+h, c:c+w]
            hsv_roi =  cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
            mask = cv2.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
            roi_hist = cv2.calcHist([hsv_roi],[0],mask,[180],[0,180])
            cv2(roi_hist,roi_hist,0,255,cv2.NORM_MINMAX)
            dst = cv2.calcBackProject([hsv],[0],roi_hist,[0,180],1)
            ret, track_window = cv2.meanShift(dst, track_window, term_crit)
            x,y,w,h = track_window
            img2 = cv2.rectangle(bgr, (x,y), (x+w,y+h), 255,2)
            cv2.imshow('img2',img2)
        k = cv2.waitKey(30) & 0xff
        if k == 27:
            break
        # 更新前一帧
        prvs = next
    else:
        break

在上面的代码中,我们首先定义了一个ROI,然后使用cv2.inRange方法将ROI中的像素转换为二进制掩码。接着,我们使用cv2Hist方法计算ROI的颜色直方图,并使用cv2.normalize方法将直方图归一化到0-255之间。然后,使用cv2.calcBackProject方法计算反向投影图,并使用cv2.meanShift方法追踪运动目标。最后,我们使用cv2.rectangle方法在图像中绘制矩形框,以标记运动目标。

示例二:稠密光流估计相机运动

下面是一个使用稠密光流估计相机运动的示例:

import cv2
import numpy as np

# 读取视频
cap = cv2.VideoCapture('test.mp4')

# 获取第一帧
ret, frame1 = cap.read()

# 转换为灰度图像
prvs = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)

# 计算稠密光流
while(1):
    ret, frame2 = cap.read()
    if ret:
        next = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
        flow = cv2.calcOpticalFlowFarneback(prvs, next, None, 0.5, 3, 15, 3, 5, 1.2, 0)
        # 可视化稠密光
        hsv = np.zeros_like(frame2)
        hsv[...,1] = 255
        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('frame2',bgr)
        # 估计相机运动
        M =.zeros((2,3))
        M[0,0] = 1
        M[1,1] = 1
        M[0,2] = np.mean(flow[...,0])
        M[1,2] = np.mean(flow[...,1])
        frame2 cv2.warpAffine(frame2,M,(frame2.shape[1],frame2.shape[0]))
        cv2.imshow('frame2',frame2)
        k = cv2.waitKey(30) & 0xff
        if k == 27:
            break
        # 更新前一帧
        prvs = next
    else:
        break

在上面的代码中,我们使用np.mean方法计算光流向量的平均值,并使用cv2.warpAffine方法估计相机运动。最后,我们使用cv2.imshow方法显示估计的相机运动。

总结

本攻略详细讲解了如何使用OpenCV3和Python实现calcOpticalFlowFarneback算法,并提供了两个示例。在实际编程中,我们可以根据具体的需求选择合适的稠密光流算法和参数,以提高稠密光流的准确率和鲁棒性。