当前位置: 首页 > news >正文

PiscTrace基于YOLO追踪算法的物体速度检测系统详解

一、YOLO目标检测系统介绍

YOLO(You Only Look Once)是一种革命性的实时目标检测算法,其最新版本YOLOv8在精度和速度上都达到了业界领先水平。相比传统的两阶段检测器(RCNN系列),YOLO采用单阶段检测方式,将目标检测视为回归问题,直接在图像网格上预测边界框和类别概率。

YOLO的核心优势

  • 实时性能:处理速度可达30-60FPS

  • 端到端训练:单一卷积网络同时完成定位和分类

  • 多尺度预测:通过不同尺寸的特征图检测不同大小的物体

  • 丰富的预训练模型:支持从Nano到XLarge多种规模模型

在我们的速度检测系统中,YOLO负责提供准确的物体检测和初步的追踪ID分配,为后续速度计算奠定基础。

二、追踪算法原理

虽然代码中没有明确使用特定追踪算法(如DeepSORT、ByteTrack等),但YOLOv8内置了基于BoT-SORT的追踪功能。这类算法通常包含以下关键组件:

  1. 检测阶段:使用YOLO获取物体边界框

  2. 特征提取:为每个检测框提取外观特征

  3. 数据关联:使用匈牙利算法匹配当前检测与已有轨迹

  4. 轨迹管理:处理新物体出现、短暂消失等情况

追踪算法的核心是为同一物体在不同帧中保持相同的ID,这对速度计算的连续性至关重要。

三、系统架构与实现思路

1. 整体架构设计

系统工作流程:

  1. 输入视频帧

  2. YOLO进行物体检测与追踪

  3. 提取检测框和追踪ID

  4. 计算中心点位移

  5. 估算瞬时速度和平均速度

  6. 可视化结果显示

2. 关键问题解决思路

问题1:如何准确计算物体速度?

  • 解决方案:通过追踪ID关联连续帧中的同一物体,计算中心点位移

  • 像素到实际单位的转换:假设1像素=0.1厘米(实际应用需校准)

  • 速度计算:速度 = 位移 × 帧率

问题2:如何平滑速度数据?

  • 解决方案:采用滑动窗口平均法(30帧窗口)

  • 使用collections.deque实现高效的历史数据存储

问题3:如何有效可视化?

  • 为每个ID分配固定颜色

  • 大号字体显示关键信息

  • 中心点标记+位移/速度数据显示

四、核心代码解析

1. 位移与速度计算

def calculate_displacement_and_speed(self, current_pos, prev_pos):"""计算两帧之间的位移和瞬时速度"""if prev_pos is None:  # 第一帧无历史数据return 0.0, 0.0# 计算像素位移dx = current_pos[0] - prev_pos[0]dy = current_pos[1] - prev_pos[1]# 转换为厘米(假设1像素=0.1厘米)displacement = np.sqrt(dx**2 + dy**2) * 0.1# 计算瞬时速度(厘米/秒)speed = displacement * self.frame_ratereturn displacement, speed

2. 移动平均速度实现

def calculate_average_speed(self, track_id, current_speed):"""计算指定ID的30帧移动平均速度"""# 初始化历史记录队列if track_id not in self.speed_history:self.speed_history[track_id] = deque(maxlen=self.window_size)# 添加当前速度self.speed_history[track_id].append(current_speed)# 计算平均值return np.mean(self.speed_history[track_id]) if self.speed_history[track_id] else 0.0

3. 可视化渲染

def obj_exe(self, im0, results):"""主执行函数:处理帧并添加可视化元素"""# 提取检测结果self.extract_results(results)if self.track_ids:  # 仅处理有追踪ID的物体for box, cls, track_id in zip(self.boxes, self.clss, self.track_ids):# 计算中心点centroid = (int((box[0]+box[2])//2, int((box[1]+box[3])//2)# 获取或生成专属颜色color = self.track_colors.setdefault(track_id, self.generate_random_color())# 计算运动信息prev_pos = self.prev_positions.get(track_id)displacement, instant_speed = self.calculate_displacement_and_speed(centroid, prev_pos)avg_speed = self.calculate_average_speed(track_id, instant_speed)# 更新位置记录self.prev_positions[track_id] = centroid# 可视化渲染self._draw_visualization(centroid, color, cls, track_id, displacement, avg_speed)return self.im0

五、完整系统代码

import cv2
import numpy as np
import random
from collections import deque
from ultralytics.utils.plotting import Annotatorclass TrackingFlowVisualizer:"""物体运动追踪可视化类,用于计算并显示物体位移和速度(带30帧平均速度计算)"""def __init__(self, line_thickness=2, point_size=6):"""初始化追踪可视化器参数:line_thickness (int): 文字和圆圈的线宽point_size (int): 中心点的大小"""# 可视化参数self.tf = line_thickness * 3  # 增大线宽以适应大号文字self.point_size = point_size * 3  # 增大中心点尺寸self.frame_rate = 30  # 帧率用于速度计算 (1像素=0.1厘米)self.font_scale = 4.0  # 字体放大10倍(原为0.5)self.font = cv2.FONT_HERSHEY_SIMPLEX  # 字体类型self.window_size = 30  # 平均速度计算窗口大小(帧数)# 初始化变量self.im0 = None  # 当前帧图像self.imw = 0  # 图像宽度self.imh = 0  # 图像高度self.annotator = None  # 标注工具self.track_ids = None  # 追踪ID列表self.boxes = None  # 边界框坐标self.clss = None  # 类别ID列表self.names = None  # 类别名称字典# 存储每个track_id的颜色和位置历史self.track_colors = {}  # {track_id: (B,G,R)}self.prev_positions = {}  # {track_id: (x,y)}self.speed_history = {}  # {track_id: deque([speed1, speed2, ...])}def extract_results(self, results):"""从YOLO结果中提取追踪信息参数:results (list): YOLO返回的检测结果列表"""# 提取边界框坐标(左上角x1y1, 右下角x2y2)self.boxes = results[0].boxes.xyxy.cpu()# 提取物体类别IDself.clss = results[0].boxes.cls.cpu().tolist()# 提取追踪ID(如果有)if results[0].boxes.id is not None:self.track_ids = results[0].boxes.id.int().cpu().tolist()# 提取类别名称字典if hasattr(results[0], 'names'):self.names = results[0].namesdef generate_random_color(self):"""生成随机高饱和度颜色(BGR格式)返回:tuple: (B,G,R)颜色值"""hue = random.randint(0, 179)  # 随机色调(0-179)saturation = 255  # 最大饱和度brightness = 255  # 最大亮度# 生成HSV颜色并转换为BGRhsv = np.array([[[hue, saturation, brightness]]], dtype=np.uint8)bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)return tuple(bgr[0][0].tolist())def calculate_displacement_and_speed(self, current_pos, prev_pos):"""计算位移和速度参数:current_pos (tuple): 当前帧中心点(x,y)prev_pos (tuple): 上一帧中心点(x,y)返回:tuple: (位移(厘米), 速度(厘米/秒))"""if prev_pos is None:  # 如果是第一帧检测到该物体return 0.0, 0.0# 计算x和y方向的位移dx = current_pos[0] - prev_pos[0]dy = current_pos[1] - prev_pos[1]# 计算总位移(勾股定理)displacement = np.sqrt(dx ** 2 + dy ** 2)*0.1  # 单位:像素/厘米# 计算瞬时速度(位移×帧率)speed = displacement * self.frame_rate  # 单位:厘米/秒return displacement, speeddef calculate_average_speed(self, track_id, current_speed):"""计算30帧移动平均速度参数:track_id (int): 物体追踪IDcurrent_speed (float): 当前帧计算的瞬时速度返回:float: 30帧平均速度"""# 初始化该track_id的速度历史队列if track_id not in self.speed_history:self.speed_history[track_id] = deque(maxlen=self.window_size)# 添加当前速度到历史记录self.speed_history[track_id].append(current_speed)# 计算平均速度(当有足够历史数据时)if len(self.speed_history[track_id]) > 0:return np.mean(self.speed_history[track_id])else:return 0.0def obj_exe(self, im0, results):"""主执行函数:计算并可视化物体运动信息(带30帧平均速度)参数:im0 (ndarray): 输入图像帧results (list): YOLO检测结果返回:ndarray: 添加了可视化信息的图像帧"""self.im0 = im0self.imw, self.imh = im0.shape[1], im0.shape[0]  # 获取图像尺寸# 从结果中提取检测信息self.extract_results(results)# 初始化标注工具self.annotator = Annotator(self.im0, self.tf, None)if self.track_ids is not None:  # 如果有追踪IDfor box, cls, track_id in zip(self.boxes, self.clss, self.track_ids):# 计算当前帧物体中心点centroid = (int((box[0] + box[2]) // 2), int((box[1] + box[3]) // 2))# 为每个track_id分配固定颜色if track_id not in self.track_colors:self.track_colors[track_id] = self.generate_random_color()color = self.track_colors[track_id]# 获取上一帧位置并计算运动信息prev_pos = self.prev_positions.get(track_id, None)displacement, instant_speed = self.calculate_displacement_and_speed(centroid, prev_pos)# 计算30帧平均速度avg_speed = self.calculate_average_speed(track_id, instant_speed)# 更新位置信息self.prev_positions[track_id] = centroid# 绘制中心点(放大尺寸)cv2.circle(self.im0, centroid, self.point_size, color, -1)# 准备显示的位移和速度文本text_displacement = f"D: {displacement:.1f} cm"text_speed = f"S: {avg_speed:.1f} cm/s"  # 显示平均速度# 计算文本尺寸用于精确定位(text_width, _), _ = cv2.getTextSize(text_displacement, self.font, self.font_scale, self.tf)# 确定文本位置(中心点上方和下方)text_pos_displacement = (centroid[0] - text_width // 2, centroid[1] - self.point_size - 10)text_pos_speed = (centroid[0] - text_width // 2, centroid[1] + self.point_size + 50)# 绘制位移文本(大号字体)cv2.putText(self.im0, text_displacement, text_pos_displacement,self.font, self.font_scale, color, self.tf, cv2.LINE_AA)# 绘制平均速度文本(大号字体)cv2.putText(self.im0, text_speed, text_pos_speed,self.font, self.font_scale, color, self.tf, cv2.LINE_AA)# 绘制物体类别和ID信息id_text = f"{self.names[cls]} ID:{track_id}"(id_width, id_height), _ = cv2.getTextSize(id_text, self.font, self.font_scale, self.tf)cv2.putText(self.im0, id_text,(centroid[0] - id_width // 2, centroid[1] - self.point_size - id_height - 20),self.font, self.font_scale, color, self.tf, cv2.LINE_AA)return self.im0

结语

本文详细介绍的基于YOLO的物体速度检测系统,结合了现代目标检测、多目标追踪和运动分析技术,构建了一个完整的解决方案。系统核心优势在于:

  • 实时性能优异

  • 实现相对简单

  • 扩展性强

  • 可视化直观

开发者可以根据具体应用场景调整参数和扩展功能,将其应用于各种需要物体运动分析的领域。随着计算机视觉技术的不断发展,这类系统的精度和实用性还将持续提高。

  对 PiscTrace or PiscCode感兴趣?更多精彩内容请移步官网看看~🔗 PiscTrace

http://www.dtcms.com/a/330556.html

相关文章:

  • 【软考中级网络工程师】知识点之入侵防御系统:筑牢网络安全防线
  • 【入门级-算法-2、入门算法:模拟法】
  • 解决“Win7共享文件夹其他电脑网络无法发现共享电脑名称”的问题
  • 融合服务器助力下的电视信息发布直播点播系统革新
  • 服务器装两个cpu
  • 1780. 判断一个数字是否可以表示成三的幂的和
  • MongoDB 从入门到生产:建模、索引、聚合、事务、分片与运维实战(含 Node.js/Python 示例)
  • 基于现代 C++ 的湍流直接数值模拟 (DNS) 并行算法优化与实现
  • 9.【C++进阶】继承
  • 河南萌新联赛2025第(五)场:信息工程大学”(补题)
  • QLab Pro for Mac —— 专业现场音频与多媒体控制软件
  • Boost库中Pool 基础内存池(boost::pool<>)的详细用法解析和实战应用
  • filezilla mac新版本MacOS-12.6.3会自动进入全屏模式BUG解决方法
  • 图论Day2学习心得
  • 支持pcm语音文件缓存顺序播放
  • springBoot+knife4j+openapi3依赖问题参考
  • 图灵测试:人工智能的“行为主义判据”与哲学争议
  • 计算机毕设大数据选题推荐 基于spark+Hadoop+python的贵州茅台股票数据分析系统【源码+文档+调试】
  • 浏览器环境下AES-GCM JavaScript 加解密程序
  • Vue Vant应用-数据懒加载
  • Docker + Cronicle + Traefik 搭建服务器计划任务工具
  • Vue3从入门到精通: 4.2 Vue Router路由守卫与权限控制深度解析
  • uni-app 小程序跳转小程序
  • rn入口文件setup.js解读
  • JS 解构赋值语法
  • 问题总结三
  • 最新去水印小程序系统 前端+后端全套源码 多套模版 免授权(源码下载)
  • 前端框架选择之争:jQuery与Vue在现代Web开发中的真实地位-优雅草卓伊凡
  • C# 中 ArrayList动态数组、List<T>列表与 Dictionary<T Key, T Value>字典的深度对比
  • Elasticsearch ABAC 配置:基于患者数据的动态访问控制