编写自己的目标跟踪算法

目标跟踪算法大致可以分为两类,一类是用前后两帧目标的相似程度来判断它们是否为同一个目标,另一类是预测目标的运动轨迹来判断下一帧同一目标的位置。

本文也编写一个目标跟踪算法,其原理是计算相邻两帧目标中心点的距离来判断它们是否为同一目标,即我们默认一个目标移动的范围不会超过某一阈值。该算法原理简单、易于实现,虽然比不上成熟的DeepSORT或ByteTrack,但在某些不是那么复杂的场合下,还是具有一定的准确性的。

下面我们就来介绍该算法及其代码。

设置ID:

from collections import defaultdict
import numpy as np
import mathid_history = defaultdict(lambda: [])
id_counter = 0
now_id = []def set_id(centerPt):return_id = 0flag_new_id = Truefor k, v in id_history.items():dist = math.hypot(v[-1][0]-centerPt[0], v[-1][1]-centerPt[1])if dist < 35:id_history[k].append((float(centerPt[0]), float(centerPt[1])))return_id = know_id.append(k)flag_new_id = Falseif len(id_history[k]) > 20:  id_history[k].pop(0)breakif flag_new_id is True:global id_counterid_history[id_counter].append((float(centerPt[0]), float(centerPt[1])))return_id = id_counternow_id.append(id_counter)id_counter +=1return return_id

字典变量id_history用于保存目标ID和该目标的中心点的坐标,字典的key为ID,value为该ID的坐标。在这里,我们除了为目标标注ID外,还实现了另一个功能:绘制了该目标的运动轨迹,所以这里的坐标不仅仅是当前帧的坐标,还包括以前同一目标的坐标。

id_counter为目标ID的编号。

我们除了为目标设置ID外,还需要删除那些不再出现的ID,因此我们还需要一个数组变量now_id,用于记录当前帧内的所有ID。

函数set_id的作用就是为当前目标设置ID,它的输入变量是被设置目标ID的中心点坐标centerPt,返回的是该目标的ID号return_id。变量flag_new_id用于标注当前目标是否在前一帧出现过,如果出现过,则赋予前一帧同一目标的ID,否则赋予新的ID。for循环遍历所有以前的目标ID,计算距离测度,当小于35时,我们就认为它们是用一个目标,并把它的坐标添加至该ID内,同时也把该ID添加至now_id内。由于我们只绘制一定长度的运动轨迹,所以需删除早期存储的该ID的多余坐标。if flag_new_id is True内用于为该目标赋予以前从未出现的新ID。

除了为目标设置ID外,还需要删除不再出现的ID,否则跟踪算法会不准确:

def del_id():[id_history.pop(k) for k in set(id_history.keys()) - set(now_id)] now_id.clear()

由于我们已经把当前帧内出现的ID保存在了now_id内,所以我们只需要把id_history内的ID与now_id比较,将now_id内没有出现的ID从id_history内剔除掉即可。

算法的核心部分就介绍完了,下面我们介绍一个附加功能,绘制目标运动轨迹:

def traj(img, trackid, thick=15, color=(70, 250, 116),):points = np.hstack(id_history[trackid]).astype(np.int32).reshape((-1, 2))leng = len(id_history[trackid])for i in range(leng-1):thickness = max(thick - i, 3)cv2.line(frame, points[-1*(i+1)], points[-1*(i+2)], color=color, thickness=thickness, lineType=cv2.LINE_AA)

函数traj实现了绘制ID为trackid的运动轨迹。轨迹坐标就保存在id_history的key为trackid的value内,这些坐标是按先后顺序保存的。为了使轨迹看起来更形象逼真,我们并没有使用cv2.polylines一次性的绘制,而是采用cv2.line两两坐标画线,而采用的线宽thickness是渐变的。

代码的其他部分就是目标检测器和绘制目标边框。与上一篇博文一样,我们仍然选择YOLOv8来检测目标,具体的注解就不再赘述,在这里只是附上代码:

import torch
from ultralytics import YOLO
import cv2model = YOLO("yolov8l.pt")
device = torch.device("cuda")
model.to(device)cap = cv2.VideoCapture('D:/track/british_highway_traffic.mp4')
fps = cap.get(cv2.CAP_PROP_FPS)
size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
fNUMS = cap.get(cv2.CAP_PROP_FRAME_COUNT)
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
videoWriter = cv2.VideoWriter("D:/track/track.mp4", fourcc, fps, size)def box_label(image, box, label='', color=(128, 128, 128), txt_color=(255, 255, 255)):p1, p2 = (int(box[0]), int(box[1])), (int(box[2]), int(box[3]))cv2.rectangle(image, p1, p2, color, thickness=2, lineType=cv2.LINE_AA)if label:w, h = cv2.getTextSize(label, 0, fontScale=2 / 3, thickness=1)[0]  outside = p1[1] - h >= 3p2 = p1[0] + w, p1[1] - h - 3 if outside else p1[1] + h + 3cv2.rectangle(image, p1, p2, color, -1, cv2.LINE_AA)cv2.putText(image,label, (p1[0], p1[1] - 2 if outside else p1[1] + h + 2),0,2 / 3,txt_color,thickness=1,lineType=cv2.LINE_AA)while(cap.isOpened()):ret, frame = cap.read()if not ret:breakresults = model(frame,device='cuda')[0]boxes = results.boxes.datafor box in boxes:x1, y1, x2, y2 = box[:4]x = (x1+x2)/2y = (y1+y2)/2track_id = set_id((x,y))   #为当前目标设置IDif box[-1] == 2:box_label(frame, box,  '#'+str(track_id)+' car', (89, 161, 197))traj(frame, track_id)   #为该目标绘制轨迹elif box[-1] == 7:box_label(frame, box,  '#'+str(track_id)+' truck', (67, 161, 255))traj(frame, track_id)elif box[-1] == 3:box_label(frame, box,  '#'+str(track_id)+' motorcycle', (186, 55, 2))traj(frame, track_id)elif box[-1] == 5:box_label(frame, box,  '#'+str(track_id)+' bus', (19, 222, 24))traj(frame, track_id)cv2.imshow('frame',frame)cv2.putText(frame, "https://blog.csdn.net/zhaocj", (25, 50),cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)videoWriter.write(frame)del_id()    #删除该帧内没有出现的IDif cv2.waitKey(1) & 0xFF == ord('q'):breakcap.release()
videoWriter.release()
cv2.destroyAllWindows()

上述代码的详细解释,还请移步上一篇博文。

下面展示该算法的效果:

track

该算法在目标被遮挡,甚至断帧的情况下,识别效果肯定不行,但在一般情况下,该算法也不失为一种简单有效的方法。

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

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

相关文章

Windows 构建 Acid Game Engine 的坑

下载 OpenAL 的话&#xff0c;配置环境变量到 OpenAL 1.1 SDK 就好了 我的 cmake 的 FindOpenAL 里面会添加 OpenAL 的库&#xff0c;所以我不知道为什么原仓库会把那个判断是否已经存在 OpenAL 库的语句注释掉……我就加回来了 Sources\CMakeLists.txt # OpenAL must be in…

cpolar内网穿透

1、下载地址 https://www.cpolar.com/ windows系统可以在cpolar官网下载最新的安装包&#xff0c;然后解压默认安装即可。 2、地址配置 创建隧道映射内网端口&#xff0c;双击安装的软件&#xff0c;即可进入浏览器配置界面 http://localhost:9200/#/dashboard cpolar安装…

go的学习路线

学习 Go 语言的路线可以分为以下几个步骤&#xff1a; 安装和设置 Go 环境&#xff1a;下载安装 Go 并设置环境变量&#xff0c;安装开发工具。 学习基础语法&#xff1a;了解 Go 的基本语法、数据类型、控制流程、函数等基础知识。 掌握标准库和常用工具&#xff1a;学习标准…

Vue中的生命周期钩子

生命周期钩子 :::warning 注意 所有生命周期钩子的 this 上下文将自动绑定至实例中&#xff0c;因此你可以利用 this 访问 props、data、computed 和 methods 等选项内的数据/函数。这意味着你不应该使用箭头函数来定义一个生命周期方法&#xff0c;因为箭头函数中没有 this&a…

实时车辆行人多目标检测与跟踪系统(含UI界面,Python代码)

算法架构&#xff1a; 目标检测&#xff1a;yolov5 目标跟踪&#xff1a;OCSort其中&#xff0c; Yolov5 带有详细的训练步骤&#xff0c;可以根据训练文档&#xff0c;训练自己的数据集&#xff0c;及其方便。 另外后续 目标检测会添加 yolov7 、yolox&#xff0c;目标跟踪会…

node_modules/XXX/index.js:XXX;XX ||= XXX?.[level];SyntaxError: Une

这个语法是 ECMAScript 2021的语法 还挺新的 对node版本要求会比较高 这里这个 icon || this.options.icon?.[level];意思就是 如果this.options.icon [level] 拿得到值 就等于它 否则 如果拿不到 icon 就等于自己 要解决这个问题 一个是你可以提高node版本 但我不建议 还是…

k8s---基本架构--节点

节点 Kubernetes 中添加节点到 API 服务器的两种主要方式&#xff1a; 节点上的 kubelet 自动向控制平面注册。您&#xff08;或其他人&#xff09;手动添加一个 Node 对象。 当您创建一个 Node 对象&#xff0c;或者节点上的 kubelet 自动注册时&#xff0c;控制平面会检查…

AlexNet——训练花数据集

目录 一、网络结构 二、创新点分析 三、知识点 1. nn.ReLU(inplace) 2. os.getcwd与os.path.abspath 3. 使用torchvision下的datasets包 4. items()与dict()用法 5. json文件 6. tqdm 7. net.train()与net.val() 四、代码 AlexNet是由Alex Krizhevsky、Ilya S…

2023最全Java面试题及答案汇总

前言 面试前还是很有必要针对性的刷一些题&#xff0c;很多朋友的实战能力很强&#xff0c;但是理论比较薄弱&#xff0c;面试前不做准备是很吃亏的。这里整理了很多面试常考的一些面试题&#xff0c;希望能帮助到你面试前的复习并且找到一个好的工作&#xff0c;也节省你在网…

NLP技术如何为搜索引擎赋能

目录 1. NLP关键词提取与匹配在搜索引擎中的应用1. 关键词提取例子 2. 关键词匹配例子 Python实现 2. NLP语义搜索在搜索引擎中的应用1. 语义搜索的定义例子 2. 语义搜索的重要性例子 Python/PyTorch实现 3. NLP个性化搜索建议在搜索引擎中的应用1. 个性化搜索建议的定义例子 2…

Java:JSR 310日期时间体系LocalDateTime、OffsetDateTime、ZonedDateTime

JSR 310日期时间体系&#xff1a; LocalDateTime&#xff1a;本地日期时间OffsetDateTime&#xff1a;带偏移量的日期时间ZonedDateTime&#xff1a;带时区的日期时间 目录 构造计算格式化参考文章 日期时间包 import java.time.LocalDateTime; import java.time.OffsetDateT…

Stable Diffusion WebUI 使用

想要正常运行 Stable Diffusion WebUI 需要机器上有 Nvidia 显卡才行, 简单体验可以 RTX 3070 起步, 正常玩需要 RTX 3080 起步, 要训练模型就要 RTX 3090 起步。 修改配置 通常 Stable Diffusion WebUI 的配置信息写在 stable-diffusion-webui/webui-user.sh 文件中: $ cd …

Eclipse如何打开debug变量窗口

今天笔者在使用Eclipse调试的时候&#xff0c;发现没有变量&#xff08;Variables&#xff09;监视窗口&#xff0c;真是头痛得很&#xff0c;最后摸索出一套显示变量窗口的操作如下&#xff1a; 点击other&#xff0c;找到Variables并点击 最后调试代码&#xff0c;调试后如图…

机器学习(17)---支持向量机(SVM)

支持向量机 一、概述1.1 介绍1.2 工作原理1.3 三层理解 二、sklearn.svm.SVC2.1 查看数据集2.2 contour函数2.3 画决策边界&#xff1a;制作网格2.4 建模画图 三、非线性情况推广3.1 查看数据集3.2 线性画图3.3 为非线性数据增加维度并绘制3D图像 四、核函数 一、概述 1.1 介绍…

免杀对抗-Python-混淆算法+反序列化-打包生成器-Pyinstall

Python-MSF/CS生成shellcode-上线 cs上线 1.生成shellcode-c或者python 2.打开pycharm工具&#xff0c;创建一个py文件&#xff0c;将原生态执行代码复制进去 shellcode执行代码&#xff1a; import ctypesfrom django.contrib.gis import ptr#cs#shellcodebytearray(b"生…

Java skill - 服务同时开始https和http端口

Java skill - 服务同时开始https和http端口 添加ssl配置代码开启http端口讲解大坑 添加ssl配置 在配置文件中添加配置 server:# ssl证书配置ssl:# 双向证书配置# 证书文件路径key-store: /opt/ops/cert/xes.p12# 证书密码key-store-password: 123456# 证书类型key-store-type…

IMX6ULL移植篇-Linux内核源码目录分析一

一. Linux内核源码目录 之前文章对 Linux内核源码的文件做了大体的了解&#xff0c;如下&#xff1a; IMX6ULL移植篇-Linux内核源码文件表_凌肖战的博客-CSDN博客 本文具体说明 Linux内核源码的一些重要文件含义。 二. Linux内核源码中重要文件分析 1. arch 目录 这个目录…

用了 TCP 协议,就一定不会丢包吗?

表面上我是个技术博主。 但没想到今天成了个情感博主。 我是没想到有一天&#xff0c;我会通过技术知识&#xff0c;来挽救粉丝即将破碎的感情。 掏心窝子的说。这件事情多少是沾点功德无量了。 事情是这样的。 最近就有个读者加了我的绿皮聊天软件&#xff0c;女生&#xff0c…

01强化学习的数学原理:大纲

01强化学习学习路线大纲 前言强化学习脉络图章节介绍Chapter 1&#xff1a;Basic ConceptsChapter 2&#xff1a;Bellman EquationChapter 3&#xff1a;Bellman Optimality EquationChapter 4&#xff1a;Value Iteration / Policy IterationChapter 5&#xff1a;Monte Carlo…

华为OD机试 - 靠谱的车 - 逻辑分析(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#…