day20 - 绘制物体的运动轨迹

news2024/11/25 3:25:09

在我们平常做目标检测或者目标追踪时,经常要画出目标的轨迹图。绘制轨迹图的一种方法就是利用光流估计来进行绘制。

本期我们主要来介绍视频中光流估计的使用和效果,利用光流估计来绘制运动轨迹。

完成本期内容,你可以:

  • 掌握视频的读取与显示
  • 掌握光流估计的流程和原理
  • 掌握使用光流估计绘制运功轨迹的代码实现

若要运行案例代码,你需要有:

  • 操作系统:Ubuntu 16.04

  • 工具软件:PyCharm 2020.1.5, Anaconda3 2020.07

  • 硬件环境:无特殊要求

  • 核心库:python 3.6.13, opencv-python 3.4.2.16

点击下载源码


视频的读取与显示

(1) OpenCV中的函数 cv2.VideoCapture() 可以用来完成摄像头的初始化工作。其语法格式如下:

dst = cv2.VideoCapture(index)

说明

  • index:摄像头ID号
  • 默认值:-1,表示随机选取一个摄像头。
  • 如果有多个摄像头,使用数字0表示第一个摄像头、使用数字1表示第2个摄像头,以此类推。
  • 如果只有一个摄像头,既可以使用数字0作为ID,也可以使用数字-1作为ID。
  • 在某些平台上,使用参数-1,会使OpenCV弹出一个选择窗口,让用户手动选择希望使用的摄像头。
  • 该函数同样适用于处理视频文件。

(2) OpenCV中的函数 cv2.isOpened() 可以用来判断当前的摄像头是否初始化成功。其语法格式如下:

retval = cv2.VideoCapture.isOpened()

说明

  • 判断当前的摄像头是否初始化成功,并根据摄像头初始化成功与否,返回不同的逻辑值retval:
  • 如果成功,该函数返回逻辑值真(True);
  • 如果不成功,该函数返回逻辑值假(False)。
  • 当函数返回值为逻辑值假时,说明摄像头初始化失败。这时,可以使用函数cv2.VideoCapture.open()打开摄像头。

(3) OpenCV中的函数 cv2.VideoCapture.read()可以用来进行帧捕捉。其语法格式如下:

retval, image=cv2.VideoCapture.read()

说明

  • image:是帧捕获的返回值,如果没有帧被捕获,则该值为空。
  • retval:用来表示捕获结果是否成功的逻辑值。如果成功返回逻辑值真(True);不成功返回逻辑值假(False)。

(4) OpenCV中的函数 cv2.VideoCapture.release()可以用来进行释放摄像头。其语法格式如下:

None=cv2.VideoCapture.release()

说明

  • 在不需要摄像头时,需要关闭摄像头。
  • 例如,当前有cv2.VideoCapture类的对象cap,则将其释放的语句为:cap.release()

保存视频文件

**(1)**OpenCV中的函数 cv2.VideoWriter() 可以用来创建类对象。其语法格式如下:

<VideoWriter object> = cv2.VideoWriter( filename, fourcc, fps, frameSize)

参数说明

  • filename:保存视频的路径
  • fourcc:用4个字符表示的视频编码格式
  • fps:帧速率
  • frameSize:每一帧的大小

**(2)**OpenCV中的函数 cv2.VideoWriter.write()可以用来进行帧捕捉。其语法格式如下:

None=cv2.VideoWriter.write(image)

说明

  • image:要写入的视频帧
  • 通常情况下,要求彩色图像的格式为BGR模式。

**(3)**OpenCV中的函数 cv2.VideoCapture.release()可以用来进行释放摄像头。其语法格式如下:

None=cv2.VideoCapture.release()

说明

  • 在不需要VideoWriter类对象时,需要释放该对象。
  • 例如,当前有VideoWriter类的对象out,则将其释放的语句为:out.release()

光流估计

稀疏特征集光流

Opencv中使用cv2.calcOpticalFlowPyrLK()函数计算一个稀疏特征集的光流其语法格式如下:

nextPts,status,err = cv2.calcOpticalFlowPyrLK(prevImg,nextImg,prevPts,nextPts,[, status[, err[, winSize[, maxLevel[, criteria[, flags[, minEigThreshold]]]]]]])

参数说明

  • prevImg: 上一帧图片;
  • nextImg:当前帧图片;
  • prevPts:上一帧找到的特征点向量;
  • nextPts:与返回值中的nextPtrs相同;
  • status:与返回的status相同;
  • err:与返回的err相同;
  • winSize:在计算局部连续运动的窗口尺寸(在图像金字塔中),default=Size(21, 21);
  • maxLevel:图像金字塔层数,0表示不使用金字塔, default=3;
  • criteria:寻找光流迭代终止的条件;
  • flags:有两个宏,表示两种计算方法,分别是OPTFLOW_USE_INITIAL_FLOW表示使用估计值作为寻找到的初始光流,OPTFLOW_LK_GET_MIN_EIGENVALS表示使用最小特征值作为误差测量,default=0;
  • minEigThreshold:该算法计算光流方程的2×2规范化矩阵的最小特征值,除以窗口中的像素数; 如果此值小于minEigThreshold,则会过滤掉相应的功能并且不会处理该光流,因此它允许删除坏点并获得性能提升, default=1e-4.
  • nextPtrs:输出一个二维点的向量,这个向量可以是用来作为光流算法的输入特征点,也是光流算法在当前帧找到特征点的新位置(浮点数);
  • status:标志,在当前帧当中发现的特征点标志status==1,否则为0;
  • err:向量中的每个特征对应的错误率.

稠密光流法

Opencv的函数cv2.calcOpticalFlowFarneback寻找稠密光流。其语法格式如下:

flow=cv.calcOpticalFlowFarneback(prev,next, flow,pyr_scale, levels, winsize,iterations, poly_n, poly_sigma, flags)

参数说明

  • prev:前一帧图片
  • next:下一帧图片,格式与prev相同
  • flow:与返回值相同,得到一个CV_32FC2格式的光流图
  • pyr_scale:构建图像金字塔尺度
  • levels:图像金字塔层数
  • winsize:窗口尺寸,值越大探测高速运动的物体越容易,但是越模糊,同时对噪声的容错性越强
  • iterations:对每层金字塔的迭代次数
  • poly_n:每个像素中找到多项式展开的邻域像素的大小。n越大越光滑,也越稳定
  • poly_sigma:高斯标准差,用来平滑倒数,n越大,sigma应该适当增加
  • flags:光流的方式,有OPTFLOW_USE_INITIAL_FLOW 和OPTFLOW_FARNEBACK_GAUSSIAN 两种
  • flow:一个两通道的光流向量,实际上是每个点的像素的位移值

光流估计的流程

光流估计的流程通常包含以下步骤:

  • 定义角点检测参数
  • 定义光流估计参数
  • 定义轨迹颜色
  • 灰度处理
  • 角点检测
  • 创建掩膜
  • 进入循环
    • 读取每一帧图像并转换为灰度图
    • 光流估计
    • 匹配后上升维度
    • 绘制轨迹
    • 显示
    • 更新

具体步骤

使用高通滤波提取图像边缘。

步骤一:创建项目工具

创建项目名为绘制物体的运动轨迹,项目根目录下新建code文件夹储存代码,新建dataset文件夹储存数据,项目结构如下:

绘制物体的运动轨迹                        # 项目名称
├── code                               # 储存代码文件
├── dataset                            # 储存数据文件

注:如项目结构已存在,无需再创建。

步骤二:读取视频

  1. 导入所需模块:OpenCV、NumPy ;
  2. 读取dataset文件夹下的dog.mp4 视频;

代码实现

import numpy as np
import cv2 as cv
# 读取视频
cap = cv.VideoCapture('../dataset/dog.mp4')

步骤三:定义角点参数

代码实现

# 设置ShiTomasi 角点检测的参数
feature_params = dict( maxCorners = 100,
                       qualityLevel = 0.3,
                       minDistance = 7,
                       blockSize = 7 )

步骤四:定义光流估计的参数

代码实现

# 设置lucas kanade 光流的参数
lk_params = dict( winSize  = (15,15),
                  maxLevel = 2,
                  criteria = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 0.03))
# 创建一些随机颜色
color = np.random.randint(0,255,(100,3))

步骤五:角点检测、创建掩码图像

  1. 读取第一帧并转换为灰度图像
  2. 检测图像中的角点
  3. 创建掩码图像

代码实现

# 读取第一帧
ret, old_frame = cap.read()
old_gray = cv.cvtColor(old_frame, cv.COLOR_BGR2GRAY)
# 跟踪检测图像中的角点
p0 = cv.goodFeaturesToTrack(old_gray, mask = None, **feature_params)

# 为绘图目的创建掩码图像
mask = np.zeros_like(old_frame)

步骤六:光流估计并绘制

  1. 读取每一帧图像并转为灰度图
  2. 光流估计
  3. 匹配后上升维度
  4. 绘制轨迹
  5. 显示轨迹
  6. 更新上一帧和之前的点

代码实现

while(1):
    ret,frame = cap.read()
    if frame is None:
        break
    frame_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)

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

    # 选择好的点,st=1表示找到特征点
    if p1 is not None:
        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 = cv.line(mask, (int(a),int(b)),(int(c),int(d)), color[i].tolist(), 2)
        frame = cv.circle(frame,(int(a),int(b)),5,color[i].tolist(),-1)
    img = cv.add(frame,mask)

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

    # 现在更新上一帧和之前的点
    old_gray = frame_gray.copy()
    p0 = good_new.reshape(-1,1,2)
cv.destroyAllWindows()
cap.release()

请添加图片描述

实验效果

本期重点是使用稀疏光流进行图像运动轨迹的绘制,这对于目标检测或追踪有着重要的意义。

点击下载源码

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

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

相关文章

通过js来判断是否是横屏如果是就自刷新页面解决横屏之后只有屏幕一半宽度的问题

判断页面是横屏还是竖屏 window.addEventListener("load", rotate, false);window.addEventListener("onorientationchange" in window ? "orientationchange" : "resize", rotate, false);function rotate() {if (window.orientatio…

首个机器学习实时特征平台测试基准论文被 VLDB 2023 录取

国际顶级数据库学术会议 VLDB 2023 将于 2023 年 8 月份在加拿大温哥华举办。近日&#xff0c;由清华大学、新加坡国立大学、以及 OpenMLDB 社区联合完成的科研成果 - 业界第一个严谨的机器学习实时特征平台测试基准&#xff0c;被大会录取并且受邀在现场报告。论文题目为&…

Mybatis-动态SQL

1.什么是动态SQL? Mabits是一个Java持久化框架&#xff0c;它提供了动态SQL的功能。动态SQL是一种根据不同条件动态生成SQL语句的技术。在Mabits中&#xff0c;动态SQL通常是通过使用一组特殊的标签和代码块来实现的&#xff0c;这些标签和代码块可以根据条件包含或排…

性能测试——jmeter实时压测结果收集

这里写目录标题 前言一、压测监控平台组成二、性能监控平台部署 - InfluxDB三、性能监控平台部署 - JMeter四、性能监控平台部署 - Grafana五、性能监控平台部署 – 运行与结果展示 前言 测试报告 .vs. 压测监控 JMeter原生测试报告带来的“痛苦” • 不具备实时性 • 报告中的…

单体项目偶遇并发漏洞!短短一夜时间竟让老板蒸发197.83元

事先声明&#xff1a;以下故事基于真实事件而改编&#xff0c;如有雷同&#xff0c;纯属巧合~ 眼下这位正襟危坐的男子&#xff0c;名为小竹&#xff0c;他正是本次事件的主人公&#xff0c;也即将成为熊猫集团的被告&#xff0c;嗯&#xff1f;这究竟怎么一回事&#xff1f;欲…

通过白噪声的频谱处理产生任意光谱斜率(f^a)噪声(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

首站中科院!百度商业AI技术创新大赛开启巡回宣讲

近日&#xff0c;百度商业AI技术创新大赛正式启动&#xff0c;并于5月18日起开启高校巡回宣讲。 宣讲会首站落地中国科学院大学&#xff0c;中国科学院大学人工智能学院副院长、教授、博士生导师肖俊教授&#xff0c;百度商业研发主任架构师焦学武&#xff0c;百度商业资深工程…

springboot 集成 Swagger3(速通)

→ springboot 集成 Swagger2 ← 目录 1. 案例2. info 配置3. Docket 配置1. 开关配置2. 扫描路径3. 路径匹配4. 分组管理 4. 常用注解1. 说明2. 案例 1. 案例 这次直接使用 2.5.6 的 spring-boot 。 依赖&#xff1a; <parent><groupId>org.springframework.…

亏损?盈利?禾赛科技Q1财报背后的激光雷达赛道「现实」

随着禾赛科技在去年登陆美股&#xff0c;作为全球为数不多已经开始前装量产交付的激光雷达上市公司&#xff0c;财务数据的变化&#xff0c;也在一定程度上反映了行业的真实状况。 根据禾赛科技最新发布的今年一季度财报显示&#xff0c;公司季度净营收为4.3亿元&#xff08;人…

基于html+css的图展示91

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

电表及配电监控系统的智能化发展

安科瑞虞佳豪 在电力领域&#xff0c;AI渗透率近年来也持续提升。今年3月&#xff0c;国家能源局发布《关于加快推进能源数字化智能化发展的若干意见》&#xff0c;文件中针对电力、、油气等行业数字化智能化转型&#xff0c;明确了指导思想和基本原则&#xff0c;从加快行业转…

Unity之ShaderGraph数据类型

前言 ShaderGraph是Unity引擎中的一个可视化着色器编辑器&#xff0c;它允许开发者使用节点和连接线的方式来创建自定义的着色器。使用ShaderGraph&#xff0c;开发者可以通过简单的拽和连接节点来创建复杂的着色器效果&#xff0c;而无需编写任何代码。 为了更好的学习Shader…

chatgpt赋能python:PythonWOL:简化计算机远程唤醒的一种方法

Python WOL&#xff1a;简化计算机远程唤醒的一种方法 随着人们越来越频繁地远程连接和控制计算机&#xff0c;计算机的远程唤醒功能变得越来越重要。WOL&#xff0c;即“Wake on LAN”&#xff0c;是一种使用网络信号远程唤醒计算机的技术。 在许多情况下&#xff0c;使用WO…

打家劫舍问题 Python题解

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…

python 网络编程和http协议--网络编程,HTTP协议,Web服务器

一.网络编程 1.IP地址 给网络中的每一台设备进行编号. IPV4 IPV6 2.端口和端口号 端口的作用就是给运行的应用程序提供传输数据的通道。 端口号的作用是用来区分和管理不同端口的&#xff0c;通过端口号能找到唯一个的一个端口。 3.TCP协议 协议: 双方的约定. 网络传输协…

基于SpringBoot+微信小程序的点餐系统

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 小程序外卖扫码点餐为…

【MQTT】关于部署含有MQTT协议的程序pod到K8S中出现的问题

1、如何在go-zero整合MQTT协议 整合EMQX与eclipse/paho.mqtt.golang实现TLS&#xff08;ssl&#xff09;单向认证 订阅、发布、解压缩gzip、zlib数据报文 https://ctraplatform.blog.csdn.net/article/details/130525974 1.1 、通过钩子函数一直出现Lost问题排查 场景&#xff…

人类睡眠EEG分析:附代码实现的方法学入门

导读 近年来&#xff0c;人类睡眠脑电图(EEG)研究激增&#xff0c;采用了越来越复杂的分析策略将电生理活动与认知和疾病联系起来。然而&#xff0c;正确计算和解释当代睡眠EEG中使用的指标需要注意许多理论和实际的信号处理细节。本研究回顾了与频谱分析、蒙太奇选择、相位和…

VC GDI双缓冲绘图

VC GDI双缓冲绘图 VC GDI双缓冲绘图创建内存DC和内存图片&#xff0c;缺一不可最好是封装一下内存绘制绘制效果 关键是不闪烁PS 重绘机制 VC GDI双缓冲绘图 双缓冲绘图&#xff0c;知道这个知识点&#xff0c;每次用的时候还得踩一遍坑&#xff0c;真是服&#xff0c;总结记录…

BGP实验--联邦以及反射器

实验明细 实验拓扑实验要求实验内容 实验拓扑 实验要求 1.R2-R7每台路由器均存在一个环回接口用于建立邻居&#xff1b;同时还存在一个环回来代表连接用户的接口&#xff1b;最终这些连接用户的接口网络需要可以和R1/8的环回通讯 2.AS2网段地址为172.16.0.0/16&#xff0c;减少…