《OpenCV》——光流估计

news/2025/2/27 9:44:19

什么是光流估计?

在这里插入图片描述

光流估计的前提?

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

基本假设

  • 亮度恒定假设:目标像素点的亮度在相邻帧之间保持不变。这是光流计算的基础假设,基于此可以建立数学方程来求解光流。
  • 时间连续或运动平滑假设:相邻帧之间的时间间隔足够小,使得像素点的运动是连续的,不会发生突变;或者说相邻像素点的运动情况是相似的,具有平滑性。

经典算法

  • Lucas-Kanade 光流算法:该算法基于局部平滑假设,通过在一个小的窗口内对多个像素点进行约束,求解光流方程。它是一种基于梯度的方法,计算效率较高,常用于实时性要求较高的应用中。
  • Horn-Schunck 光流算法:是一种全局的光流估计算法,在亮度恒定和光滑性约束的基础上,通过最小化一个能量函数来求解光流。它考虑了整幅图像的信息,能够得到较为平滑的光流场,但计算量相对较大。
  • 基于深度学习的光流估计算法:近年来,随着深度学习的发展,基于卷积神经网络(CNN)的光流估计算法取得了很好的效果。例如 FlowNet、PWC-Net 等,这些算法通过大量的训练数据学习图像之间的运动模式,能够处理复杂的场景和运动情况,并且在精度和速度上都有了很大的提升。

实例

对视频中的人物走动轨迹进行光流追踪处理。
实现了基于 Lucas - Kanade 算法的稀疏光流估计,用于处理视频中的运动跟踪。

  • 导入必要的库
import numpy as np
import cv2

导入numpy库用于数值计算,cv2是 OpenCV 库,用于计算机视觉任务

  • 打开视频文件并初始化颜色
cap = cv2.VideoCapture('test.avi')
color = np.random.randint(0, 255, (100, 3))

cv2.VideoCapture(‘test.avi’):打开名为test.avi的视频文件。
np.random.randint(0, 255, (100, 3)):生成 100 个随机的 RGB 颜色,用于后续绘制光流轨迹。

  • 读取第一帧并转换为灰度图
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)

cap.read():读取视频的第一帧,ret是一个布尔值,表示是否成功读取帧,old_frame是读取的帧图像。
cv2.cvtColor():将彩色图像转换为灰度图像,因为光流估计通常在灰度图像上进行。

  • 检测特征点
feature_params = dict(maxCorners=100,
                      qualityLevel=0.3,
                      minDistance=7)
p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)

cv2.goodFeaturesToTrack():使用 Shi - Tomasi 角点检测算法检测图像中的特征点。

feature_params是一个字典,包含了角点检测的参数:

  • maxCorners:最多检测的角点数量。
  • qualityLevel:角点质量的阈值,只有质量高于该阈值的角点才会被保留。
  • minDistance:相邻角点之间的最小距离。
  • 初始化掩码图像
mask = np.zeros_like(old_frame)

创建一个与第一帧图像大小相同的全零掩码图像,用于绘制光流轨迹。

  • 设置 Lucas - Kanade 光流算法的参数
lk_params = dict(winSize=(15, 15),
                 maxLevel=2)

winSize:搜索窗口的大小,用于在计算光流时对每个像素点周围的区域进行分析。
maxLevel:金字塔的最大层数,用于处理大位移的光流。

  • 循环处理视频帧
while True:
    ret, frame = cap.read()
    if not ret:
        break
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
    good_new = p1[st == 1]
    good_old = p0[st == 1]

cap.read():读取视频的下一帧。
cv2.calcOpticalFlowPyrLK():使用金字塔 Lucas - Kanade 算法计算光流。

  • old_gray:前一帧的灰度图像。
  • frame_gray:当前帧的灰度图像。
  • p0:前一帧检测到的特征点。
  • p1:当前帧中对应的特征点位置。
  • st:状态数组,用于表示每个特征点是否被成功跟踪,st == 1表示成功跟踪。
  • err:每个特征点的跟踪误差。
  • 绘制光流轨迹
    for i, (new, old) in enumerate(zip(good_new, good_old)):
        a, b = new.ravel()
        c, d = old.ravel()
        a, b, c, d = int(a), int(b), int(c), int(d)
        mask = cv2.line(mask, (a, b), (c, d), color[i].tolist(), 2)
    img = cv2.add(frame, mask)

cv2.line():在掩码图像上绘制从旧特征点到新特征点的线段。
cv2.add():将掩码图像与当前帧图像叠加,得到带有光流轨迹的图像。

  • 显示结果并更新帧信息
 cv2.imshow('mask', mask)
    cv2.imshow('frame', img)
    k = cv2.waitKey(150)
    if k == 27:
        break
    old_gray = frame_gray.copy()
    p0 = good_new.reshape(-1, 1, 2)

cv2.imshow():显示掩码图像和带有光流轨迹的图像。
cv2.waitKey(150):等待 150 毫秒,按下按键则返回按键的 ASCII 码。
k == 27:如果按下 ESC 键(ASCII 码为 27),则退出循环。
更新前一帧的灰度图像和特征点信息,以便下一帧的光流计算。

  • 释放资源
cv2.destroyAllWindows()
cap.release()

cv2.destroyAllWindows():关闭所有打开的窗口。
cap.release():释放视频捕获对象。
这段代码通过 Lucas - Kanade 算法实现了视频中特征点的光流估计,并将光流轨迹绘制在视频帧上。它可以帮助我们观察视频中物体的运动情况。

  • 结果:
    在这里插入图片描述

http://www.niftyadmin.cn/n/5869901.html

相关文章

2025面试Go真题第一场

前几天参加了一场面试,GoLang 后端工程师,他们直接给了我 10 道题,我留了一个截图。 在看答案之前,你可以先简单做一下,下面我会对每个题目做一个说明。 文章目录 1、golang map 是否并发安全?2、协程泄漏的原因可能是…

Linux 文字转语音包 eSpeak 的使用方法详解

一、安装 eSpeak 1. 更新软件包列表 在终端中运行以下命令,确保系统中的软件包列表是最新的: sudo apt-get update2. 安装 eSpeak 运行以下命令安装 eSpeak: sudo apt-get install espeak3. 验证安装 安装完成后,可以通过以…

Neo4j使用neo4j-admin导入csv数据方法

在neo4j desktop里创建project,创建dbms,创建database。 将csv文件放入如下import路径中,然后就可以使用相对路径来使用csv了。 在neo4j desktop中打开Terminal 键入导入数据语句: neo4j-admin database import full --nodes&qu…

对 flask 框架中的全局变量 request 探究

在 Python 的 Web 开发框架 flask 中有这样的四个全局变量,我们经常会使用它们来存取数据,在处理请求过程中它们是非常方便的,因为它们的实现方法是相同的,所以这里我们重点探究一下 request 的使用,其它的都是类似的。…

2024-2025 学年广东省职业院校技能大赛 “信息安全管理与评估”赛项 技能测试试卷(四)

2024-2025 学年广东省职业院校技能大赛 “信息安全管理与评估”赛项 技能测试试卷(四) 第一部分:网络平台搭建与设备安全防护任务书第二部分:网络安全事件响应、数字取证调查、应用程序安全任务书任务 1:应急响应&…

【Uniapp-Vue3】点击将内容复制到剪切板

具体使用方法在官网: uni-app官网https://uniapp.dcloud.net.cn/api/system/clipboard.html大致使用方法如下: // value是需要复制的值 function copyValue (value) { uni.setClipboardData({data: value,success: res>{// 复制成功逻辑},fail:err&…

Java基础关键_011_ String 类与正则表达式(二)

目 录 一、正则表达式 1.说明 2.应用 3. 相关方法 (1)replace(CharSequence target, CharSequence replacement) (2)replaceAll(String regex, CharSequence replacement) (3)split(String regex) &…

Go 1.24版本在性能方面有哪些提升?

Go 1.24版本在性能方面有多项显著提升,主要包括以下几点: 基于Swiss Tables的新内置map实现:这种实现方式通过压缩索引和更高效的查找机制,降低了内存使用量并提高了查询速度。根据测试,某些场景下性能提升接近50%[1][…