Opencv 实战(三)光流估计

光流估计是计算机视觉领域的一项重要任务,它用于分析图像序列中像素在时间上的移动情况。光流估计可以帮助我们理解运动物体的轨迹、检测视频中的动作、实现目标跟踪和视频稳定等应用。OpenCV提供了多种光流估计算法来满足不同场景的需求,其中最常用的是基于Lucas-Kanade光流法和Farneback光流法。

  1. Lucas-Kanade光流法:

Lucas-Kanade光流法是一种稀疏光流估计方法,它基于一个关键假设:在图像中相邻像素的运动具有一定的空间一致性,即局部邻域内的像素运动相似。该方法假设像素的灰度值在时间上的变化可以通过一个2D运动向量来描述。

基本步骤:

首先,选择感兴趣的关键点或特征点,这些特征点在相邻帧中能够稳定检测到。
对每个特征点,构建一个窗口(或局部邻域),在该窗口内寻找对应的特征点。在相邻帧中,特征点周围的像素灰度值在时间上的变化由一个2D运动向量表示。
使用最小二乘法来优化运动向量,使得在窗口内的像素灰度值的误差最小化。
重复以上过程,直到所有特征点的运动向量被估计。
2. Farneback光流法:

Farneback光流法是一种稠密光流估计方法,它能够计算图像中每个像素的运动向量。相对于Lucas-Kanade光流法,Farneback光流法具有更高的计算复杂度,但能够提供更丰富的光流信息。

基本步骤:

先计算两帧图像之间的稠密光流场,得到每个像素的粗略运动向量。
对稠密光流场进行优化和插值,以得到更精确的光流信息。
最终得到图像中每个像素的运动向量,这些向量描述了像素在时间上的位移情况。
总的来说,光流估计方法能够帮助我们捕捉图像序列中的运动信息,从而实现目标跟踪、动作检测和视频稳定等应用。在OpenCV中,您可以通过调用相关函数如cv.calcOpticalFlowPyrLK()(Lucas-Kanade法)和cv.calcOpticalFlowFarneback()(Farneback法)来进行光流估计操作。

import numpy as np
import cv2

cap = cv2.VideoCapture('test.avi')

# 角点检测所需参数
feature_params = dict( maxCorners = 100,
                       qualityLevel = 0.3,
                       minDistance = 7)

# lucas kanade参数
lk_params = dict( winSize  = (15,15),
                  maxLevel = 2)

# 随机颜色条
color = np.random.randint(0,255,(100,3))

# 拿到第一帧图像
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
# 返回所有检测特征点,需要输入图像,角点最大数量(效率),品质因子(特征值越大的越好,来筛选)
# 距离相当于这区间有比这个角点强的,就不要这个弱的了
p0 = cv2.goodFeaturesToTrack(old_gray, mask = None, **feature_params)

# 创建一个mask
mask = np.zeros_like(old_frame)

while(True):
    ret,frame = cap.read()
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 需要传入前一帧和当前图像以及前一帧检测到的角点
    p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)

    # st=1表示
    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, (a,b),(c,d), color[i].tolist(), 2)
        frame = cv2.circle(frame,(a,b),5,color[i].tolist(),-1)
    img = cv2.add(frame,mask)

    cv2.imshow('frame',img)
    k = cv2.waitKey(150) & 0xff
    if k == 27:
        break

    # 更新
    old_gray = frame_gray.copy()
    p0 = good_new.reshape(-1,1,2)

cv2.destroyAllWindows()
cap.release()

在这里插入图片描述
展示一下结果

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VisionX Lab

你的鼓励将是我更新的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值