Yolov8项目实践——基于yolov8与OpenCV实现目标物体运动热力图

概述

在数据驱动和定位的世界中,对数据进行解释、可视化和决策的能力变得日益重要。这表明,使用正确的工具和技术可能是项目成功的关键。在计算机视觉领域,存在许多技术来解释从视频(包括录像、流媒体或实时视频)中获取的数据,特别是在评估需要分析交通强度或某些对象(如人、车辆、动物等)行为的区域时,热力图是一个极其有效的选择。

物体运动热力图可以展示物体在一段时间内的运动轨迹和活动强度。这种图表通常通过颜色的变化来表示不同区域的运动热度,颜色的深浅代表了物体在该区域的运动频率或者速度的快慢。在物理学和计算机视觉领域,热力图可以用于分析和理解物体的运动模式,例如人流监控、交通流量分析或者运动员的运动轨迹分析。

在传统的计算机视觉图像处理,使用OpenCV库背景减除法来识别和追踪视频中的移动物体,然后将这些信息累积起来,形成热力图。可以有效地突出显示物体运动的高频区域,帮助研究者或分析师更好地理解物体的运动模式,但传统的计算机视觉图像处理在一些场景变化比较的情况下,性能并不理想。

在多目标跟踪(MOT)领域,Tracking-by-detection它可以依赖于目标检测器来识别视频中的每个目标,然后使用跟踪算法来关联检测结果,形成目标的连续轨迹。这种方法的关键在于如何有效地关联来自不同帧的检测框,以便为每个目标创建准确且连贯的轨迹。

Yolov8集成了BYTE方法,BYTE是一种创新的数据关联方法,它旨在提高多目标跟踪的准确性和连贯性。BYTE方法通过利用检测框和跟踪轨迹之间的相似性,可以在保留高置信度检测结果的同时,从低置信度检测结果中去除背景噪声,并挖掘出真正的物体。这对于处理遮挡、模糊等困难样本特别有效,因为这些情况下的目标检测往往更加具有挑战性。

BYTE能够降低漏检率并提高轨迹的连贯性。可以轻松地应用于多种现有的state-of-the-art MOT方法中,并且能够提升这些方法的IDF1指标,这表明了其强大的通用性和有效性。

基于BYTE方法,提出的跟踪方法ByteTrack进一步展示了其在MOT任务中的潜力。ByteTrack在保持高运行速度(30 FPS)的同时,在MOT17基准测试上取得了显著的性能提升,包括80.3的MOTA(Multiple Object Tracking Accuracy)、77.3的IDF1和63.1的HOTA(High Order Track Accuracy)。这些结果表明,ByteTrack在处理多目标跟踪任务时,不仅能够准确地关联检测框,还能够有效地处理目标间的交互和复杂场景,从而实现高精度的轨迹跟踪。

实现效果:

基于yolov8与OpenCV实现目标物体运动热力图

基于Yolov8的运动热力图

1.环境安装

conda create -n yolov8 python=3.8
activate ylolv8
pip install ultralytics

2.下载模型

可以从官网上下载需要的模型,官网提供了几种不同尺寸的模型:
在这里插入图片描述

3.项目实践步骤

这里以一段航拍视频为例,视频是用俯视的一个三叉路口,目标是创建一个热力图来展示这三条路汽车流量密集热力图。实现步骤如下:

目标检测:首先,需要对视频进行分析,识别出视频中的车辆以及它们在每帧中的位置

轨迹跟踪:通过多目标跟踪BYTE方法,关联视频中连续帧中检测到的车辆,形成每个车辆的轨迹。

数据关联:利用检测框和跟踪轨迹之间的相似性,去除背景噪声,挖掘出真正的车辆,降低漏检并提高轨迹的连贯性。

热力图生成:将检测到的车辆位置信息汇总,并使用热力图库来生成热力图。热力图通过颜色的深浅来表示车辆密度的高低。

4.代码实践

导入需要的库

from collections import defaultdict
import cv2
import numpy as np
from ultralytics import YOLO

调用Yolo目标检测的模型,

model = YOLO('yolov8s.pt')

读取视频

videopath = 'video.mp4'
cap = cv2.VideoCapture(videopath)

现在创建一个空字典来存储跟踪位置(‘track_history’)和一个字典来存储每个对象的最后推断位置(‘last_positions’)。

track_history = defaultdict(lambda: [])
last_positions = {}

在计算机视觉和视频分析中,涉及点跟踪或对象运动的场景时,需要计算两个点之间的欧几里得距离。欧几里得距离是两点之间的直线距离,可以通过勾股定理来计算。在二维空间中,如果两点的坐标分别是 p 1 ( x 1 , y 1 ) p1(x_1, y_1) p1(x1,y1) p 2 ( x 2 , y 2 ) p2(x_2, y_2) p2(x2,y2),那么它们之间的欧几里得距离 d d d可以通过以下公式计算:

d = ( x 2 − x 1 ) 2 + ( y 2 − y 1 ) 2 d = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2} d=(x2x1)2+(y2y1)2

在Python中,你可以很容易地实现这个计算,以下是一个简单的函数示例:

def calculate_distance(p1, p2):return np.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)

这个函数euclidean_distance接受两个点作为输入,每个点由其在二维空间中的(x, y)坐标定义。函数计算并返回这两个点之间的直线距离。

在视频分析中,你可能需要比较连续视频帧中的对象位置,以确定它们是否为同一个对象,或者评估对象的运动速度。通过计算连续帧中对象位置的欧几里得距离,可以对对象的运动进行量化分析。如果距离很小,这可能表明对象几乎没有移动;如果距离较大,这可能表明对象在两帧之间有显著的移动。这种方法有助于过滤掉静止的对象(如停放的车辆),只关注移动的对象。

首先,使用numpy库初始化一个热力图,该图是一个三维矩阵,其所有元素初始值都为零。这个矩阵具有三个“层”,分别对应RGB颜色通道。

import numpy as np# 初始化热力图,尺寸与视频帧的高和宽相匹配,具有三个颜色通道
heatmap = np.zeros((int(cap.get(4)), int(cap.get(3)), 3), dtype=np.float32)

接下来,进入一个while循环,该循环将持续运行,直到视频处理完毕。

while cap.isOpened():success, frame = cap.read()if not success:break  # 如果无法读取帧,则退出循环

对于成功读取的每一帧,我们利用YOLO模型进行对象检测和跟踪。这里使用了跟踪和持久性算法,这对于处理视频帧序列非常有效。由于本例专注于车辆交通记录,我们只定义了两类对象。

if success:# 利用YOLO模型对帧进行对象检测和跟踪results = model.track(frame, persist=True, classes=2)

对于每一次有效的检测,更新热力图,记录对象的边界框坐标。

# 假设results['boxes']和results['track_ids']包含了检测结果的边界框和跟踪ID
for box, track_id in zip(results['boxes'], results['track_ids']):x_center, y_center, width, height = boxcurrent_position = (float(x_center), float(y_center))

使用calculate_distance函数来检查对象是否在移动,并根据移动的距离更新热力图。

last_position = last_positions.get(track_id)
if last_position and calculate_distance(last_position, current_position) > 5:# 如果对象移动的距离超过最小值,则在热力图上进行记录heatmap[top_left_y:bottom_right_y, top_left_x:bottom_right_x] += 1# 更新对象的最后位置记录last_positions[track_id] = current_position

为了提升视觉效果,对热力图应用高斯模糊滤镜。

# 对热力图应用高斯模糊,以增强视觉效果
heatmap_blurred = cv2.GaussianBlur(heatmap, (15, 15), 0)

随后,对热力图进行归一化处理,并应用颜色映射,以便在原始视频帧上进行叠加。

# 归一化热力图并应用颜色映射,以便在视频帧上叠加
heatmap_norm = cv2.normalize(heatmap_blurred, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)
heatmap_color = cv2.applyColorMap(heatmap_norm, cv2.COLORMAP_JET)

最后,在while循环中,添加了一个退出键的检查,以便用户可以通过按键退出程序。视频处理完成后,释放视频捕获对象,并关闭所有OpenCV创建的窗口。

# 添加退出键检查,允许用户通过按键退出程序
if cv2.waitKey(1) & 0xFF == ord("q"):break# 视频处理完成后,释放资源并关闭窗口
cap.release()
cv2.destroyAllWindows()

通过上述步骤,能够创建一个动态的热力图,它不仅能够检测和跟踪视频中的对象,还能直观地展示对象的移动情况。

整体代码实现如下:

from collections import defaultdict
import cv2
import numpy as np
from ultralytics import YOLOdef calculate_distance(p1, p2):return np.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)def create_history(input_video,output_video,model_path):model = YOLO(model_path)cap = cv2.VideoCapture(input_video)track_history = defaultdict(lambda: [])last_positions = {}heatmap = np.zeros((int(cap.get(4)), int(cap.get(3)), 3), dtype=np.float32)fps = int(cap.get(5))videoWriter = Nonewhile cap.isOpened():success, frame = cap.read()if not success:breakresults = model.track(frame, persist=True, classes=2)boxes = results[0].boxes.xywh.cpu()track_ids = results[0].boxes.id.int().cpu().tolist()for box, track_id in zip(boxes, track_ids):x_center, y_center, width, height = boxcurrent_position = (float(x_center), float(y_center))top_left_x = int(x_center - width / 2)top_left_y = int(y_center - height / 2)bottom_right_x = int(x_center + width / 2)bottom_right_y = int(y_center + height / 2)top_left_x = max(0, top_left_x)top_left_y = max(0, top_left_y)bottom_right_x = min(heatmap.shape[1], bottom_right_x)bottom_right_y = min(heatmap.shape[0], bottom_right_y)track = track_history[track_id]track.append(current_position)if len(track) > 1200:track.pop(0)last_position = last_positions.get(track_id)if last_position and calculate_distance(last_position, current_position) > 5:heatmap[top_left_y:bottom_right_y, top_left_x:bottom_right_x] += 1last_positions[track_id] = current_positionheatmap_blurred = cv2.GaussianBlur(heatmap, (15, 15), 0)heatmap_norm = cv2.normalize(heatmap_blurred, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)heatmap_color = cv2.applyColorMap(heatmap_norm, cv2.COLORMAP_JET)alpha = 0.7cv_dst = cv2.addWeighted(frame, 1 - alpha, heatmap_color, alpha, 0)cv_resize = cv2.resize(cv_dst,(640,360))if videoWriter is None:fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')videoWriter = cv2.VideoWriter(output_video, fourcc, fps, (cv_resize.shape[1], cv_resize.shape[0]))videoWriter.write(cv_resize)cv2.imshow("Traffic Heatmap",cv_resize)if cv2.waitKey(1) & 0xFF == ord("q"):breakcap.release()cv2.destroyAllWindows()if __name__ == '__main__':model_path = "yolov8s.pt"create_history('11.mp4','21.mp4',model_path)

实现效果:
在这里插入图片描述

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

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

相关文章

SpringMVC核心流程解析

SpringMVC核心流程解析 DispatcherServlet的继承关系请求流程分析获取HandlerChain(ControllrtMethod拦截器)获取HandlerAdapter handlerMappings的初始化过程 DispatcherServlet的继承关系 DispatcherServlet本质是一个servlet,既然是servlet,一个请求…

[Algorithm][滑动窗口][水果成篮][最大连续的一个数 Ⅲ][将x减到0的最小操作数]详细讲解

目录 1.水果成篮1.题目链接2.算法原理讲解3.代码讲解 2.找到字符串中所有字母异位词1.题目链接2.算法原理讲解3.代码实现 3.串联所有单词的字串1.题目链接2.算法原理讲解3.代码实现 3.最小覆盖字串1.题目链接2.算法原理讲解 1.水果成篮 1.题目链接 水果成篮 2.算法原理讲解 …

Java集合进阶——数据结构

1.栈 模型: 栈模型和一个杯子差不多,一端开口,一端封闭,开口的那端叫栈顶,封闭的那端叫栈底,如图所示 介绍: 元素进入栈中叫进栈/压栈,元素出来叫出栈,元素进栈后会先来…

Appian发布最新版本:通过AI流程自动化推动业务发展

Appian公司于2024年4月16日在弗吉尼亚州麦克莱恩宣布推出Appian平台的最新版本。此版本引入了Process HQ,这是一个集流程挖掘和企业AI于一体的系统,结合了Appian的数据平台。Process HQ为企业运营提供前所未有的可见性,支持数据驱动的决策和流…

CERLAB无人机自主框架: 2-动态目标检测与跟踪

前言:更多更新文章详见我的个人博客主页【MGodmonkeyの世界】 描述:欢迎来到CERLAB无人机自主框架,这是一个用于自主无人飞行器 (UAV) 的多功能模块化框架。该框架包括不同的组件 (模拟器,感知,映射,规划和…

Hadoop——Yarn 调度器和调度算法

Yarn 调度器和调度算法 YARN调度器(Scheduler)是负责将集群资源分配给不同应用程序的组件。它根据应用程序的资源需求和优先级,以及集群的资源供给情况,决定如何分配资源。YARN提供了多种调度器实现,每种调度器都有不…

如何通过MSTSC连接Ubuntu的远程桌面?

正文共:666 字 12 图,预估阅读时间:1 分钟 前面我们介绍了如何通过VNC连接Ubuntu 18.04的远程桌面(Ubuntu 18.04开启远程桌面连接),非常简单。但是有小伙伴咨询如何使用微软的远程桌面连接MSTSC&#xff08…

Go栈内存管理源码解读

基本介绍 栈内存一般是由Go编译器自动分配和释放,其中存储着函数的入参和局部变量,这些参数和变量随着函数调用而创建,当调用结束后也会随之被回收。通常开发者不需要关注内存是分配在堆上还是栈上,这部分由编译器在编译阶段通过…

Android Studio学习笔记——广播机制Broadcast

Android Studio学习笔记——广播机制 5.1 广播机制简介5.2 接收系统广播5.2.1 动态注册监听网络变化5.2.2 静态注册实现开机启动 5.3 发送自定义广播5.3.1 发送标准广播5.3.2 发送有序广播 5.4 使用本地广播5.5 广播的最佳实践——强制下线功能 5.1 广播机制简介 安卓每个应用…

spring boot后端开发基础

spring boot后端开发基础 Spring Boot一、开发步骤二、Web分析三、跨域问题四、HTTP协议五、Web服务器六、响应前端请求七、springboot常用注解创建一个简单的RESTful API服务层和数据访问层配置类和Bean定义响应体和路径变量 Spring Boot 一、开发步骤 创建项目 添加依赖 项…

k8s部署Eureka集群

部署有状态负载 镜像配置: 环境变量如下: AUTHENTICATE_ENABLEtrue JAVA_OPTS-Dauth.userName账号 -Dauth.password密码 MY_POD_NAMEmetadata.name BOOL_REGISTERtrue BOOL_FETCHtrue APPLICATION_NAME负载名称 EUREKA_INSTANCE_HOSTNAME${MY_POD_NA…

webpack源码分析——enhanced-resolve库之getType、normalize、join和cachedJoin函数

一、PathType 路径类型 const PathType Object.freeze({Empty: 0, // 空Normal: 1, // 默认值Relative: 2, // 相对路径AbsoluteWin: 3, // win 下的绝对路径AbsolutePosix: 4, // posix 下的绝对路径Internal: 5 // enhanced-resolve 内部自定义的一种类型,具体是…

小程序AI智能名片S2B2C商城系统:做内容、造IP、玩社群打造私域流量的新营销秘籍

在数字化浪潮汹涌的新时代,小程序AI智能名片S2B2C商城系统正以其独特的魅力,引领着营销领域的新变革。这套系统不仅将人工智能与小程序技术完美结合,更通过创新的S2B2C模式,为企业打开了一扇通往成功的大门。 面对激烈的市场竞争&…

SQL注入作业

目录 一、万能密码和二阶注入测试 1.万能密码 2.二阶注入测试 二、联合查询注入测试 1.判断注入点 2.判断当前查询语句的列数 3.查询数据库基本信息 4.查询数据库中的数据 三、报错注入 1. 报错注入函数EXTRATVALUE 2.UPDATEXML 四、盲注测试 1.布尔盲注 判断数据…

Linux搭建Discuz论坛

搭建一个论坛 —接上篇博客 改名/etc/httpd/conf.d/vhosts.conf 》/etc/httpd/conf.d/vhosts.conf.bak [rootlocalhost conf.d]# mv /etc/httpd/conf.d/vhosts.conf /etc/httpd/conf.d/vhosts.conf.bak此时的vhosts.conf是一个新创建的文件,之前的vhosts.conf已经…

使用 Godot 游戏引擎为 Apple 的 visionOS 创建游戏和应用的平台

借助GodotVision ,您可以使用Godot 游戏引擎为 Apple VisionOS创建游戏和应用程序。 保卫牛城堡,一款使用 GodotVision 制作的 VisionOS 游戏 GodotVision 运行一个控制本机RealityKit 视图的无头 Godot实例。粗略地说:Godot 是后端,

毅速3D打印随形透气钢:革新传统,引领未来

透气钢,这种多孔金属材料,既融合了金属材料的坚固性,又具备了透气材料的通透性。尤其在注塑模具的制造中,透气钢的作用不可忽视。通过镶嵌透气钢,能够有效解决因困气产生的注塑问题,使成型加工更为完善&…

机器学习鸢尾花使用csv

操作流程 下载鸢尾花数据集导入需要的包读取数据并查看数据大小和长度划分训练集和测试集使用模型评估算法 下载鸢尾花数据集 链接:https://pan.baidu.com/s/1RzZyXsaiJB3e611itF466Q?pwdj484 提取码:j484 --来自百度网盘超级会员V1的分享导入需要…

矩阵混乱度(熵值)代码计算

1、先回顾下熵值的数据公式: 2、jax.numpy代码 注意的点:熵值计算的输入的必须是归一化的正值 import jax.numpy as jnp import jax def _entroy(probs):log_probs jnp.log2(jnp.maximum(1.0e-30, probs))mean_sum_plogp jnp.mean(- jnp.sum(log_pro…

vscode+vue开发常用插件整理

前言: vscode新机开发常用插件整理 1、chinese 简体中文配置 2、file-jump 别名跳转,可以把引入的组件,通过ctrl地址名 跳转组件内部 3、Vue Peek:vue项目中的一些配置,安装后,能实现 ctrl组件名 跳转…