【进阶OpenCV】 (10)--光流估计--->描绘运动物体轨迹

news2024/10/17 17:29:06

文章目录

  • 光流估计
    • 一、基本原理
    • 二、计算步骤
    • 三、实现步骤
      • 1. 处理第一帧
      • 2. 寻找特征点
      • 3. 创建全零掩膜
      • 4. 流光估计函数介绍
      • 5. 主循环处理视频的每一帧
        • 5.1 流光估计
        • 5.2 绘制轨迹
        • 5.3 生成最终图像
        • 5.4 更新旧灰度图和旧特征点
      • 6. 释放资源
  • 总结

光流估计

光流估计是计算机视觉中的一种重要技术,它通过计算图像中像素点在连续帧之间的运动向量来估计物体的运动情况。传统光流算法和基于深度学习的光流算法都有各自的优势和应用领域。随着计算机视觉技术的不断发展,光流估计将在更多领域发挥重要作用。

本篇我们来介绍,如何通过光流估计来描绘移动物体的运动情况

一、基本原理

  1. 亮度恒定假设:在相邻两帧图像中,同一物体上的像素点在时间上的变化主要由其在图像平面上的运动引起,而不受光照条件的影响。即,同一点随着时间的变化,其亮度不发生变化。
  2. 小运动假设:随着时间的变化,不会引起位置的剧烈变化,只有小运动情况下才能用前后帧之间单位位置变化引起的灰度变化去近似灰度对位置的偏导数。
  3. 空间一致性:一个场景上临近的点投影到图像上也是临近点,且临近点速度一致。

二、计算步骤

光流估计的计算过程主要分为两个步骤:特征提取和光流计算。

  1. 特征提取:在图像中选择合适的像素点作为特征点。一般选择具有较大亮度梯度的像素点(如边缘、角点等)作为特征点,因为这些点在图像中更容易被识别和跟踪。
  2. 光流计算:通过比较相邻两帧图像中特征点的亮度变化,计算出这些点的运动速度和方向。在实际计算中,通常会使用一些优化算法来提高计算精度和效率。常用的优化算法包括Lucas-Kanade算法、Horn-Schunck算法和金字塔光流算法等

三、实现步骤

由上所述,我们的实现过程需要找到特征点,然后找到亮度变换的点,从而找到移动物体,描绘其轨迹。

步骤

1.读取视频,得到第一帧的特征点 -----> 2. 创建全零掩膜,用于在其上面绘制轨迹 -----> 3. 主循环,计算下一帧的特征点 ----> 4. 将连续帧之间的特征点连线绘制在掩膜上

1. 处理第一帧

将第一帧转换为灰度图,便于接下来进行特征检测。

cap = cv2.VideoCapture('test.avi')
# 读取视频第一帧
ret,old_frame = cap.read()
# 将第一帧转换为灰度图像
old_gray = cv2.cvtColor(old_frame,cv2.COLOR_BGR2GRAY)

2. 寻找特征点

使用cv2.goodFeaturesToTrack()函数,在图像中检测“好”的特征点,这些特征点通常是在图像中容易识别和跟踪的点,如角点、边缘等。

cv2.goodFeaturesToTrack(image,maxCorners=100,qualityLevel=0.01,minDistance=10)

参数:

-- image:输入的灰度图像。注意,这个函数需要灰度图像作为输入,因此如果输入是彩色图像,需要先转换为灰度图像。
-- maxCorners:要返回的最大角点数量。如果检测到的角点数量超过这个值,则只返回响应值最强的 maxCorners 个角点。
-- qualityLevel:接受检测到的角点的最低质量水平参数。该参数表示最低可接受的角点质量,以最强角点的质量为基准,低于此值的角点会被		拒绝。通常设置为 0.010.1 之间的值。
-- minDistance:角点之间的最小欧氏距离。在检测过程中,如果两个角点之间的距离小于这个值,则较弱的角点会被拒绝。这有助于避免检测到		的角点过于集中。
  • 返回值是一个形状为 (-1, 1, 2) 的 NumPy 数组,其中 -1 表示行数(根据检测到的角点数量动态确定),1表示每个角点是一个单独的“批次”,2 表示每个角点的 (x, y) 坐标
"""-----寻找特征点-----"""
# 定义特征点检测参数
feature_params = dict(maxCorners = 100,# 最大角点数量
                      qualityLevel = 0.3,# 角点质量的阈值
                      minDistance = 7)# 最小距离,用于分散角点
p0 = cv2.goodFeaturesToTrack(old_gray,mask=None,**feature_params)# **:关键字参数解包,用于将字典解包为关键字参数

3. 创建全零掩膜

创建一个与当前帧大小相同的全零掩膜,用于绘制轨迹,随机生成颜色,用于后续绘制不同轨迹。

"""-----创建一个与当前帧大小相同的全零掩膜,用于绘制轨迹-----"""
mask = np.zeros_like(old_frame)
# 随机生成颜色,用于绘制轨迹
color = np.random.randint(0,255,(100,3))

4. 流光估计函数介绍

cv2.calcOpticalFlowPyrLK()是 OpenCV 中用于计算稀疏光流的函数,具体实现的是 Lucas-Kanade 方法的金字塔版本。这个函数通过比较两帧图像(通常是连续的视频帧)之间的特征点位置,来估计这些特征点的运动

p1, st, err = cv2.calcOpticalFlowPyrLK(prevImg, nextImg, prevPts, nextPts=None, winSize=(15,15), maxLevel=0)

参数:

-- prevImg:前一帧图像,通常是灰度图。
-- nextImg:当前帧图像,也是灰度图。
-- prevPts:前一帧图像中的特征点坐标,通常是二维点集。
-- nextPts:输出参数,用于存储计算得到的当前帧中的特征点坐标。如果传入 None,则函数会分配一个新的数组来存储结果。
-- winSize:搜索窗口的大小,用于在每个金字塔层级上搜索特征点的对应点。
-- maxLevel:金字塔的最大层级数。0 表示只使用原始图像,不使用金字塔。

返回值:

-- p1:当前帧中特征点的坐标,形状为 (-1, 1, 2) 的 NumPy 数组,其中 -1 表示行数(根据输入特征点的数量动态确定),1 表示每个特	征点是一个单独的“批次”,2 表示每个特征点的 (x, y) 坐标。
-- st:状态数组,表示每个特征点是否成功跟踪到。值为 1 表示成功,0 表示失败。
-- err:每个特征点的误差数组,表示光流估计的误差大小。误差越小,表示估计越准确。

5. 主循环处理视频的每一帧

5.1 流光估计

通过连续的两帧图像,使用流光估计找到跟踪成功的点

while (True):
    # 读取下一帧
    ret,frame = cap.read()
    # 检查是否成功读取到帧
    if not ret:
        break
    # 将当前帧转换为灰度图像
    frame_gray = cv2.cvtColor(frame,cv2.COLOR_RGB2GRAY)

    # cv2.calcOpticalFlowPyrLK()这个函数通过比较两帧图像(通常是连续的视频帧)之间的特征点位置,来估计这些特征点的运动。
    p1,st,err = cv2.calcOpticalFlowPyrLK(old_gray,frame_gray,p0,None,**lk_params)

    # 选好的点(状态为1的点)
    good_new = p1[st == 1]
    good_old = p0[st == 1]
5.2 绘制轨迹

使用cv2.line()函数,在掩膜图片上将每一帧跟踪的点连线

for i,(new,old) in enumerate(zip(good_new,good_old)):
    a, b = new.ravel() # 获取新点坐标 或者[a,b] = new
    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)
    cv2.imshow('mask',mask)

在这里插入图片描述

5.3 生成最终图像

将掩膜添加到当前帧上,生成最终图像:

img = cv2.add(frame,mask)
# 显示结果图像
cv2.imshow('frame',img)

在这里插入图片描述

5.4 更新旧灰度图和旧特征点

因为,每次进行光流估计跟踪特征点,都是连续的两帧,所以上一帧的图像old_gray要不停的更新,每次结束之后更新为当前帧,用于下一次计算:

# 等待150ms,检测是否按下Esc健
k = cv2.waitKey(150) & 0xff # 按下Esc健,退出循环
if k == 27:
    break
# 更新旧灰度图和旧特征点
old_gray = frame_gray.copy()
p0 = good_new.reshape(-1,1,2) # 重新整理特征点为适合下次计算的形状,(38,2) --> (

6. 释放资源

"""-----释放资源-----"""
cv2.destroyAllWindows()
cap.release()

总结

本篇介绍了,如何利用光流估计来绘制移动物体的轨迹。

注意!!:每两个连续帧之间计算完特征点并连线之后,都需要将上一帧的图像更新为当前帧,用于下次计算时称为它的上一帧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2212901.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

操作系统——磁盘管理

目录 前言基础实例1.1读取磁盘数据计算时间1.2磁盘调度算法1.3单双缓冲区1.4磁盘基础知识 前言 本文简述操作系统中有关磁盘的相关知识点,作为软件设计师考试资料复习 基础 磁盘管理是指对计算机中的磁盘进行有效地管理和使用的过程。磁盘管理包括以下方面&#…

软件测试工程师面试整理 —— 操作系统与网络基础!

在软件测试中,了解操作系统和网络基础知识对于有效地进行测试工作至关重要。无论是在配置测试环境、调试网络问题,还是在进行性能测试和安全测试时,这些知识都是不可或缺的。 1. 操作系统基础 操作系统(Operating System, OS&am…

【Redis】网络模型(day10)

在本篇文章中,主要是对五种网络模型进行一个简单的介绍,然后对Redis4.0和6.0的网络模型进行一个概述。 用户空间和内核空间 在Linux系统上,分为用户空间、内核空间和硬件设备。硬件设备主要包括CPU、内存、网卡等物体,内核应用去…

垃圾回收器和垃圾回收机制(简单介绍,用于回忆总结)

文章目录 垃圾回收机制1. 分代收集2. 标记复制3. 标记清除4. 标记压缩(整理) 垃圾回收器1. Serial / Serial Old2. Parallel Scavenge3. ParNew收集器4. CMS收集器5. G1收集器 参考链接 垃圾回收机制 1. 分代收集 分代收集(Generational Co…

吉时利KEITHLEY 2657A源表keithley2651A数字源表

Keithley 2657A 源表是一款高电压、高功率、低电流源测量单元 (SMU) 仪器,可提供前所未有的功率、精度、速度、灵活性和易用性,以提高研发、生产测试和可靠性环境中的生产力。 Keithley 2657A SourceMeter 仪器专门设计用于表征和测试高压电子器件和功率…

【隐私计算篇】一种批量匿踪查询友好算法PIRANA的原理分析

1. 背景分析 前段时间开展了批量匿踪查询算法迭代优化的工作,取得了一些进展。不得不说,甲方爸爸永远会提出非常有挑战性的目标,push你去想各种解决方案。在实际的算法研发落地上,我们会结合算法本身的机制改进以及工程优化这两方…

力扣hot100--二叉树

目录 二叉树 1. 94. 二叉树的中序遍历 2. 98. 验证二叉搜索树 3. 101. 对称二叉树 二叉树 1. 94. 二叉树的中序遍历 给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。 示例 1: 输入:root [1,null,2,3] 输出:[1,3,2]示…

[ComfyUI]最好用的图像提示词反推工具发布 2.0 版本啦!更好用了!

图像提示词反推工具我也介绍了好一些了,但是架不住技术一直在迭代啊!过一段时间就出一个新的,或者是升级版,所以我们的分享也不能停! 前段时间 joy_caption 蛮火的,不过后来也陆陆续续出了一些比较好用的反…

JMeter性能测试时,如何做CSV参数化

在现代软件开发中,性能测试是保证应用程序在高负载条件下稳定运行的重要环节。为了实现真实场景的测试,参数化技术应运而生。其中,CSV参数化是一种高效且灵活的方法,可以让测试人员通过外部数据文件驱动测试脚本,从而模…

U-Boot阶段系统全量更新固件包制作杂记

背景:有一个在 U-Boot 阶段做系统全量自更新的需求,要制作系统的全量固件包(U-Boot.img、kerlen.img、rootfs.img)。大体分为三个主要部分:U-Boot-shell 脚本编写、打包各镜像为一个固件包、固件包的加密和解密 一、U…

电采暖集控系统陕西高陵体育馆应用项目案例

电采暖集控系统是一种集监测、控制和管理于一体的智能管理系统,旨在提高采暖效率、降低能耗和运营成本,同时提升用户的舒适度。该系统利用先进的计算机控制技术和系统集成技术,实现对电热采暖设备的集中管理和远程操控。 陕西高陵体育馆 是…

四川方维嘉术科技有限公司简介

四川方维嘉术科技有限公司 公司简介 四川方维嘉术科技有限公司成立于2023年,注册资本100万元整,位于中国西南地区的中心位置,是一家专注于供应医疗设备、高值耗材并提供医疗方面解决方案的企业。 【主要代理产品】 湖南瑞康通 &#xff1…

Alberta Wells数据集:首个包含超过213,000个油气井的大规模高质量基准数据集,它们是温室气体和其他污染物的重要来源,助力环境监测与气候变化。

2024-10-11,由Mila – Quebec AI Institute和McGill University等机构创建了首个大规模油井检测数据集,这个数据集的意义在于提供了一个工具,能够通过卫星图像识别和定位全球数以百万计的废弃油气井,这对于减少温室气体排放和保护…

数据结构与算法:堆与优先队列的深入剖析

数据结构与算法:堆与优先队列的深入剖析 堆是一种特殊的树形数据结构,广泛应用于优先队列的实现以及各种高效的算法中,如排序和图算法。通过深入了解堆的结构、不同堆的实现方式,以及堆在实际系统中的应用,我们可以掌…

使用js和canvas实现简单的网页打砖块小游戏

玩法介绍 点击开始游戏后,使用键盘上的←→控制移动,小球会不停移动,板子触碰小球时会反弹,碰撞到砖块时会摧毁砖块,如果没有用板子接住小球就游戏失败 代码实现 代码比较简单,直接阅读注释即可&#x…

工作日志:elementplus上传图片问题

问题&#xff1a;打开弹窗&#xff0c;上传一张照片后&#xff0c;关闭再打开&#xff0c;之前上传的图片仍在列表里展示。 然后添加了几行代码&#xff0c;报错。 <el-upload list-type"picture-card":limit"1":on-success"handleAvatarSuccess&…

Spring Boot 之三大配置文件.properties、.yml、.yaml 及其优先级解析

Spring Boot 的强大之处在于其高度可配置性&#xff0c;允许开发者根据不同环境和需求定制应用程序的行为。而这一切的核心便是配置文件。Spring Boot 支持多种配置文件格式&#xff0c;其中最常用的三种是 .properties、.yml 和 .yaml。 1. .properties&#xff1a;传统方式 …

基于NXP LS1023+FPGA的嵌入式解决方案

基于 NXP公司的LS1043A高性能64位ARM四核处理器。 LS1043A处理器是NXP公司面向嵌入式网络推出的一款四核64位ARM处理器&#xff0c; 支持无风扇设计的灵活I/O封装&#xff0c; 提供超过10 Gbps的性能&#xff0c;是专为小规格网络和工业应用而设计的解决方案。全新23x23封装方式…

jquery实现点击菜单实现高德地图定位点与数据展示联动效果

&#x1f34a;jquery实现点击菜单实现高德地图定位点与数据展示联动效果 版本介绍&#xff1a; jQuery v3.7.1高德地图JS API 2.0 代码仓库 ⭐ Gitee&#xff1a;实现点击菜单实现高德地图定位点与数据展示联动效果 1.启动说明 &#x1f4d4; 推荐VS Code编辑器插件Live Ser…

java项目之信息化在线教学平台的设计与实现(源码+文档)

项目简介 信息化在线教学平台的设计与实现实现了以下功能&#xff1a; 信息化在线教学平台的设计与实现的主要使用者管理员功能有个人中心&#xff0c;学生信息管理&#xff0c;教师信息管理&#xff0c;教学信息管理&#xff0c;学生成绩管理&#xff0c;留言板管理&#xf…