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算法,并提供了两个示例。在实际编程中,我们可以根据具体的需求选择合适的稠密光流算法和参数,以提高稠密光流的准确率和鲁棒性。