opencv-python视频分析与目标跟踪

news2024/12/22 12:52:37

目录

光流

目标跟踪


一、光流

使用OpenCV光流分析,跟踪蚂蚁的轨迹:

代码实现: 

import numpy as np
import cv2

if __name__ == '__main__':
    cap = cv2.VideoCapture('ant.mp4')

    # ShiTomasi 角点检测参数
    feature_params = dict(
        maxCorners=100,
        qualityLevel=0.5,
        minDistance=30,
        blockSize=10
    )

    # Lucas Kanada 光流检测参数
    lk_params = dict(
        winSize=(15, 15),
        maxLevel=2,
        criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)
    )

    # 获取第一帧并发现角点
    ret, last_current_frame = cap.read()
    last_gray = cv2.cvtColor(last_current_frame, cv2.COLOR_BGR2GRAY)

    p0 = cv2.goodFeaturesToTrack(last_gray, mask=None, **feature_params)
    mask = np.zeros_like(last_current_frame)

    color = np.random.randint(0, 255, (100, 3))
    while (1):
        ret, current_frame = cap.read()

        if not ret:
            break

        current_gray = cv2.cvtColor(current_frame, cv2.COLOR_BGR2GRAY)

        # TODO(You): 请在此编写光流跟踪和绘制代码
        p1, st, err = cv2.calcOpticalFlowPyrLK(
        last_gray, current_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()
            a, b = int(a), int(b)
            c, d = int(c), int(d)
            mask = cv2.line(mask, (a, b), (c, d), color[i].tolist(), 2)
            current_frame = cv2.circle(
                current_frame, (a, b), 5, color[i].tolist(), -1)

        current_img = cv2.add(current_frame, mask)
        cv2.imshow('current_img', current_img)

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

        last_gray = current_gray.copy()
        p0 = good_new.reshape(-1, 1, 2)

    cv2.destroyAllWindows()
    cap.release()

二、目标跟踪

在视频分析(或视频结构化)应用开发中,多目标跟踪是非常重要的一个环节。它能有效弥补上一个目标检测环节中算法的不足,如检测算法输出坐标不稳定、漏检等。与此同时,跟踪算法输出的目标轨迹(track-id)对于应用下阶段的行为分析环节也有着至关重要的作用。下面是常见视频分析类应用系统结构:

 

目标检测算法输出单帧检测结果,目标跟踪算法负责将前后2帧中的目标关联起来、给予唯一标识track-id。假设t帧中检测到了M个目标,t+1帧中检测到了N个目标,跟踪算法本质上是M->N的匹配关联过程。

 

 

匹配过程中,目标可以分为以下三大类:

  1. matched_tracks,t帧目标出现,t+1帧该目标仍然出现,算法匹配上。
  2. unmatched_tracks,t帧目标出现,t+1帧该目标消失,算法未匹配上。
  3. unmatched_detections,t帧目标不存在,t+1帧该目标出现,新增检测目标。

其中,对于2和3来说,跟踪算法需要考虑:

t帧目标出现,t+1帧目标其实仍然存在,但是检测算法出现短暂漏检,误认为其消失。此时的解决方案是: 某帧未被匹配到的tracks不要立即清除,而是做若干帧的缓存,等待若干帧后检测算法恢复检测
t帧目标不存在,t+1帧该目标仍然不存在,但是检测算法出现短暂误检,误认为其出现。此时的解决方案是:新增的检测目标不要立即生效,而是做若干帧的缓存,等检测算法连续检测超过若干帧、并且都能匹配关联上后再生效

之所以要考虑以上2点,主要原因是对于连续视频帧而言,大部分检测算法基本无法做到100%连续、稳定检测,出现短暂的误检、漏检非常正常。

代码实现如下:

# 定义跟踪算法类
class Tracker(object):
  # 初始化参数
  def __init__(self, max_age=1, min_hits=3, iou_threshold=0.3):
    self.max_age = max_age
    self.min_hits = min_hits
    self.iou_threshold = iou_threshold
    self.trackers = []
    self.frame_count = 0

  # 跟踪函数,每帧检测结果返回后,调用一次update
  def update(self, dets=np.empty((0, 5))):
    self.frame_count += 1
    
    trks = np.zeros((len(self.trackers), 5))
    to_del = []
    ret = []
    for t, trk in enumerate(trks):
      pos = self.trackers[t].predict()[0]
      trk[:] = [pos[0], pos[1], pos[2], pos[3], 0]
      if np.any(np.isnan(pos)):
        to_del.append(t)
    
    trks = np.ma.compress_rows(np.ma.masked_invalid(trks))

    for t in reversed(to_del):
      self.trackers.pop(t)
    
    # 匹配关联
    matched, unmatched_dets, unmatched_trks = associate_detections_to_trackers(dets, trks, self.iou_threshold)

    # 后处理逻辑
    # TO-DO your code...
    # 更新matched_tracks
    for m in matched:
      self.trackers[m[1]].update(dets[m[0], :])

    # 初始化unmatched_detections,假设是当前帧新出现的检测目标
    for i in unmatched_dets:
        trk = KalmanBoxTracker(dets[i,:])
        self.trackers.append(trk)

    i = len(self.trackers)
    for trk in reversed(self.trackers):
        d = trk.get_state()[0]

        # 输出满足条件的tracks
        if (trk.time_since_update <= self.max_age) and (trk.hit_streak >= self.min_hits or self.frame_count <= self.min_hits):
          ret.append(np.concatenate((d,[trk.id+1])).reshape(1,-1))
        
        i -= 1
        # 移除超过self.max_age次的漏检目标
        if(trk.time_since_update > self.max_age):
          self.trackers.pop(i)

    # 返回跟踪结果 [[left, top, right, bottom, track-id]...]
    if(len(ret) > 0):
      return np.concatenate(ret)
    return np.empty((0, 5))

代码相关说明:

  1. self.max_age代表跟踪算法允许出现的最大漏检帧数
  2. self.min_hints代表跟踪算法要求的最低连续匹配帧数
  3. self.trackers代表跟踪算法维持的目标集合(已生成track-id)
  4. update(self, dets)代表跟踪函数,其中参数dets代表t+1帧中目标检测结果list[[left, top, right, bottom, score]...],即t+1帧中待匹配的detections
  5. associate_detections_to_trackers(...) 代表IOU+卡尔曼滤波匹配算法,返回上面提到的matched_tracksunmatched_tracksunmatched_detections三个值
  6. time_since_update代表目标当前漏检帧数
  7. hit_streak代表目标当前连续匹配帧数

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

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

相关文章

ConcurrentHashMap底层实现原理

ConcurrentHashMap底层实现原理 ConcurrentHashMap的整体架构ConcurrentHashMap的基本功能ConcurrentHashMap在性能方面的优化 ConcurrentHashMap的整体架构 1.8中的存储结构&#xff1a; 它是由数组、单向链表、红黑树组成的。 当们去初始化一个ConcurrentHashMap实例的时候…

【工具】FFmpeg|超大视频本地有损压缩,500MB变5MB(支持 Windows、Linux、macOS)

参考&#xff1a; 如何将一分钟长的1080p视频压缩至5MB以内&#xff1f;-知乎-滔滔清风近期HEVC扩展备用安装方法-B站-悲剧天下 总共三个步骤&#xff0c;安装FFmpeg、运行指令、打开视频。 亲测 500MB 变 5MB。 1 安装FFmpeg 对于不需要看教程可以自行完成安装的同学们&…

哪款手持洗地机更好用?好用的手持洗地机分享

家居卫生清洁对于每个家庭来说都是必不可少的事情&#xff0c;尤其是地面清洁更是需要重视。传统的清洁方法需要频繁更换工具才能完成吸、拖、吸的清洁步骤&#xff0c;而这个过程费时费力且效果并不尽如人意。然而&#xff0c;洗地机的出现完美地解决了这一问题&#xff0c;将…

【C++进阶之路】初始C++语法(下)

文章目录 一.引用1.基本概念2.使用场景函数参数函数返回值 3.优点4.指针与引用的区别 二.内联函数引入1.默认设置2.建议3.声明与定义&#xff08;不同文件&#xff09;add.cppadd.htest.cpp 三.auto1.必须有初始值2.只能确定一个类型3.auto可以为类型的一部分4.函数参数和自定义…

Ubuntu20.04部署YOLOv5

目录 前言一、环境配置1 显卡驱动安装1.1 卸载显卡驱动1.2 准备工作1.3 驱动安装1.4 验证 2 CUDA安装2.1 准备工作2.2 CUDA下载2.3 CUDA安装2.4 配置环境变量2.5 验证2.6 小结 3 cuDNN安装3.1 cuDNN下载3.2 cuDNN安装3.3 小结 4 TensorRT安装4.1 TensorRT下载4.2 TensorRT安装4…

UOS-----本地YUM源配置

1. cd /etc/apt/sources.list.d/ 将文件中的两个list配置文件内容注释掉&#xff0c;并保存 2. cd /etc/apt/ vi sources.list 将配置文件内容注释 3. cd /etc/apt/sources.list.d/ vi local.list (创建一个新的list文件&#xff0c;作为本地yum配置文件) 添…

电脑怎么压缩图片大小,4个通用方法分享

电脑怎么压缩图片大小&#xff1f;我相信这个问题很多小伙伴都遇到过的。我们压缩图片大小的主要原因是为了优化网站、应用程序或移动设备的性能。大尺寸的图片文件需要更多的存储空间和带宽&#xff0c;这将导致网页加载速度变慢&#xff0c;浪费用户时间并影响用户体验。此外…

香港科技大学有什么好的专业?

香港科技大学创办于1991年10月&#xff0c;是一所坐落于香港清水湾半岛的公立研究型大学。大学设有4个学院&#xff1a;工学院、理学院、人文社会科学学院和工商管理学院&#xff0c;还设有2个研究院&#xff1a;香港科技大学公共政策和行政研究生院和香港科技大学霍英东研究院…

nginx 配置代理ip访问https的域名配置

目录 问题背景 解决方式 正向代理&#xff1a; 反向代理&#xff1a; 通俗点儿一句话&#xff0c;正向与反向的区别&#xff1a; 问题背景 在某些单位或机构内部&#xff0c;访问互联网接口需要通过指定的服务器去访问&#xff0c;那我们就需要通过代理 ip 和 端口去访问外…

云计算基础——虚拟化

虚拟化技术简介 虚拟化是一个广义的术语&#xff0c;在计算机方面通常是指计算元件在虚拟的基础上而不是真实的基础上运行 虚拟化是一种经过验证的软件技术&#xff0c;它正迅速改变着IT的面貌&#xff0c;并从根本上改变着人们的计算方式 虚拟化是一个抽象层&#xff0c;它…

【C++学习】类和对象--运算符重载

运算符重载概念&#xff1a;对已有运算符重新定义&#xff0c;赋予其另一种功能&#xff0c;以适应不同的数据类型。 作用&#xff1a;实现两个自定义数据类型相加的运算。 目录 加号运算符重载 1.成员函数重载 2.全局函数重载 左移运算符重载<< 递增运算符重载 赋值…

java堆排序

堆排序是最基本的排序算法&#xff0c;简单来说就是把一堆数据&#xff08;数组&#xff09;分成两个相等的部分&#xff0c;其中一个部分作为数组的开头&#xff0c;另一个部分作为数组的结尾。之后在对这两个相等的部分进行比较&#xff0c;如果在比较之后发现这个数组中有一…

读懂什么是RDMA

一.什么是RDMA 1.RDMA主要体现 2.如何理解RDMA和TCP技术的区别&#xff1f; 3.使用RDMA的好处包括&#xff1a; 二.什么是RoCE&#xff1f; 1. RDMA协议包含: Infiniband&#xff08;IB&#xff09; 2. 为什么RoCE是目前主流的RDMA协议&#xff1f; …

GhostNet

文章目录 相关文章一、轻量化网络结构1. 分组卷积2. 深度可分离卷积 二、GhostNet1. 动机2. Ghost Module 相关文章 https://blog.csdn.net/search_129_hr/article/details/130280697 https://blog.csdn.net/c2250645962/article/details/104601305 一、轻量化网络结构 目的…

信息收集(一)域名信息收集

前言 信息收集也叫做资产收集。信息收集是渗透测试的前期主要工作&#xff0c;是非常重要的环节&#xff0c;收集足够多的信息才能方便接下来的测试&#xff0c;信息收集主要是收集网站的域名信息、子域名信息、目标网站信息、目标网站真实IP、敏感/目录文件、开放端口和中间件…

052:cesium加载网格地图

第052个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中加载grid地图。一个 ImageryProvider,它在每个具有可控背景和发光的图块上绘制线框网格。 可能对自定义渲染效果或调试地形很有用。 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 …

redis 教程 6(Redis 的Pipeline , Lua)

Redis 的Pipeline, Lua PipelinePipeline简介为什么需要PipelinePipeline 性能测试与原生批量命令对比 LuaLua 与事物Lua 的用法Redis 如何管理Lua脚本 Pipeline Pipeline简介 Pipeline&#xff08;流水线&#xff09; 能够将一组redis命令进行组装&#xff0c; 通过一次RTT&…

fmriprep2

一. sub-subXXX文件夹 sub-subXXX.html 二. sub-subXXX文件夹 sub-sub097 / anat / figures / func / log / anat / anat文件夹内文件比较多&#xff0c;文件命名规则遵守BIDS要求( https://bids-specification.readthedocs.io/en/stable/05-derivatives/01-introduction.ht…

【国内chatgpt使用方法合集】

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

2023_4_23_VS下Release怎么打断点进行debug

&#x1f37f;*★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★* &#x1f37f; &#x1f4a5;&#x1f4a5;&#x1f4a5;欢迎来到&#x1f91e;汤姆&#x1f91e;的csdn博文&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f49f;&#x1f49f;喜欢的朋友可以关注一下&#xf…