opencv对光流法的实现(python3)

@TOC


一、光流法的数学原理

参考 https://blog.csdn.net/qq_41368247/article/details/82562165

二、准备

  1. opencv安装
  2. ffmpeg安装(不安装的话读取视频会报错)并配置环境

三、opencv实现光流法(python3)

1. 实现流程

基于python语言,会用到matplotlib(但不是必须的,可以删除对应语句)
首先获取视频或者摄像头的第一帧图像。用goodFeaturesToTrack函数获取初始化的角点,然后开始无限循环获取视频图像帧,将新图像和上一帧图像放入calcOpticalFlowPyrLK函数当中,从而获取新图像的光流
calcOpticalFlowPyrLK的官方文档:https://docs.opencv.org/4.4.0/dc/d6b/group__video__track.html#ga473e4b886d0bcc6b65831eb88ed93323

2. 代码

基于python3语言的实现

代码如下:

import numpy as np
import cv2
import matplotlib.pyplot as plt #直接用cv2中的imshow也可以画图,这里用plt绘图方便显示

#------------------------------------------------------------读取视频-----------------------------------------------------
path = "./video003.mp4"
cap = cv2.VideoCapture(path)
print("Is this video captured correctly? :",cap.isOpened()) #返回True表示视频读取成功

#---------------------------------------------------------计算视频总帧数---------------------------------------------------
frame_count = 0
all_frames = []
while(True):
    ret, frame = cap.read()
    if ret is False: #逐帧读取到最后一帧的下一帧时,ret=false
        break
    all_frames.append(frame)
    frame_count = frame_count + 1
print("The total number of frames:",frame_count)

#----------------------------------------------------------计算视频fps---------------------------------------------------
(major_ver, minor_ver, subminor_ver) = (cv2.__version__).split('.') #返回cv2的版本,根据不同版本查阅fps的命令不同。我的版本是4.4.0
if int(major_ver) < 3:
    fps = cap.get(cv2.cv.CV_CAP_PROP_FPS)
    print("Frames per second: {0}".format(fps))
else:
    fps = cap.get(cv2.CAP_PROP_FPS)
    print("Frames per second: {0}".format(fps))

#-------------------------------------------------------设置角点检测及光流法的参数-------------------------------------------
feature_params = dict(maxCorners = 100, qualityLevel = 0.3, minDistance = 7, blockSize = 7)# ShiTomasi 角点检测参数
lk_params = dict( winSize  = (15,15),maxLevel = 2,criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))# lucas kanade光流法参数
color = np.random.randint(0,255,(100,3))# 创建随机颜色

#-------------------------------------------------------获取第一帧的灰度图像及其角点-----------------------------------------
cap = cv2.VideoCapture(path) #这里必要要重新捕获视频,否则.read()不能正确获取第一帧
ret, old_frame = cap.read() #获取第一帧
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY) #找到原始灰度图
plt.figure("old_gray")
plt.imshow(old_gray)
plt.title('old_gray')
plt.show()
#cv2.imshow("old_gray",old_gray) #用cv2中的模块画图
#cv2.waitKey()
p0 = cv2.goodFeaturesToTrack(old_gray, mask = None, **feature_params) #获取第一帧图像old_frame的灰度图像old_gray中的角点p0

#-----------------------------------------------------对每帧图像计算光流并绘制光流轨迹-----------------------------------------
mask = np.zeros_like(old_frame) #创建一个蒙版用来画轨迹,i.e.和每帧图像大小相同的全0张量
while(1):
    ret,frame = cap.read()
    try:
        frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    except:
        print("This video has been processed.")
        break

    # 计算每帧的光流
    p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)

    # 选取好的跟踪点
    good_new = p1[st==1]
    good_old = p0[st==1]

    # 画出轨迹
    for i,(new,old) in enumerate(zip(good_new,good_old)):
        a,b = new.ravel()
        c,d = old.ravel()
        mask = cv2.line(mask, (int(a),int(b)),(int(c),int(d)), color[i].tolist(), 2) #添加了该帧光流的轨迹图
        frame = cv2.circle(frame,(int(a),int(b)),5,color[i].tolist(),-1)
    img = cv2.add(frame,mask) #将该图和轨迹图合并
    cv2.imshow('frame',img)

    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break

    # 更新上一帧的图像和追踪点
    old_gray = frame_gray.copy()
    p0 = good_new.reshape(-1,1,2)

cv2.destroyAllWindows()
cap.release()

3.输出结果

光流法结果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 17
    点赞
  • 117
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
好的,您想了解关于稀疏光流Python OpenCV 中的应用和使用方法是吗?那么我可以简单地为您介绍一下。 稀疏光流是一种计算图像中像素运动的方法,它可以通过检测两个连续帧之间的像素强度变化来计算像素的运动向量。Python OpenCV提供了实现稀疏光流的函数 cv2.calcOpticalFlowPyrLK()。 以下是一个简单的示例代码,演示了如何使用稀疏光流来计算两个连续帧之间的像素运动: ``` import cv2 # 读取两个连续帧 frame1 = cv2.imread('frame1.jpg') frame2 = cv2.imread('frame2.jpg') # 转换为灰度图像 gray1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY) gray2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY) # 设置参数 lk_params = dict(winSize=(15, 15), maxLevel=2, criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)) # 获取关键点 p0 = cv2.goodFeaturesToTrack(gray1, mask=None, maxCorners=100, qualityLevel=0.3, minDistance=7) # 计算光流 p1, st, err = cv2.calcOpticalFlowPyrLK(gray1, gray2, p0, None, **lk_params) # 选择好的点 good_new = p1[st == 1] good_old = p0[st == 1] # 绘制运动向量 for i, (new, old) in enumerate(zip(good_new, good_old)): a, b = new.ravel() c, d = old.ravel() frame1 = cv2.circle(frame1, (a, b), 5, (0, 255, 0), -1) frame1 = cv2.line(frame1, (a, b), (c, d), (255, 0, 0), 2) # 显示结果 cv2.imshow('frame', frame1) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在上述示例代码中,我们首先读取了两个连续帧,然后将它们转换为灰度图像。接下来,我们使用 cv2.goodFeaturesToTrack() 函数获取了第一帧中的关键点,并将这些关键点作为稀疏光流的输入。然后,我们使用 cv2.calcOpticalFlowPyrLK() 函数计算了两个连续帧之间的稀疏光流。最后,我们选择好的点,并使用 cv2.circle() 和 cv2.line() 函数绘制了运动向量。 希望这个简单的示例代码可以帮助您更好地理解稀疏光流Python OpenCV 中的应用和使用方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值