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

掌握YOLOv8:从视频目标检测到划定区域统计计数的实用指南

文章目录

    • 1. 引言
    • 2. YOLOv8基础回顾
      • 2.1 YOLOv8的核心改进
      • 2.2 YOLOv8的基本使用
    • 3. 视频划定区域目标统计计数实现
      • 3.1 总体思路
      • 3.2 详细实现代码
      • 3.3 代码解析
    • 4. 进阶改进方向
      • 4.1 多区域计数
      • 4.2 方向敏感计数
      • 4.3 性能优化技巧
    • 5. 实际应用案例
      • 5.1 交通流量统计
      • 5.2 商场入口人流统计
    • 6. 总结与展望

1. 引言

目标检测是计算机视觉领域的重要任务之一,而YOLO(You Only Look Once)系列算法因其速度和精度的平衡而广受欢迎。YOLOv8作为该系列的最新版本,在性能和易用性上都有了显著提升。本文将介绍如何利用YOLOv8进行视频中划定区域的目标统计计数,这是一个在实际应用中非常有用的功能,如交通流量统计、商场人流量监测等。

2. YOLOv8基础回顾

2.1 YOLOv8的核心改进

YOLOv8在以下几个方面进行了重要改进:

  1. 更高效的网络架构:采用了新的骨干网络和特征金字塔结构
  2. 改进的损失函数:使用了更合理的分类和回归损失组合
  3. 增强的训练策略:包括更好的数据增强和优化器设置
  4. 简化的API:提供了更友好的用户接口

2.2 YOLOv8的基本使用

from ultralytics import YOLO# 加载预训练模型
model = YOLO('yolov8n.pt')  # 可以替换为yolov8s/m/l/x.pt# 进行目标检测
results = model('image.jpg')# 显示结果
results[0].show()

3. 视频划定区域目标统计计数实现

3.1 总体思路

实现视频划定区域目标统计计数的基本流程:

  1. 加载YOLOv8模型
  2. 读取视频流
  3. 定义感兴趣区域(ROI)
  4. 对每一帧进行目标检测
  5. 统计进入/离开ROI的目标数量
  6. 可视化结果并输出统计信息

3.2 详细实现代码

import cv2
import numpy as np
from collections import defaultdict
from ultralytics import YOLOclass VideoROICounter:def __init__(self, model_path, video_path, roi_points):"""初始化视频ROI计数器:param model_path: YOLOv8模型路径:param video_path: 视频文件路径:param roi_points: ROI多边形顶点坐标列表"""self.model = YOLO(model_path)self.cap = cv2.VideoCapture(video_path)self.roi_points = np.array(roi_points, np.int32)self.roi_mask = Noneself.track_history = defaultdict(list)self.in_count = 0self.out_count = 0self.prev_positions = {}# 获取视频基本信息self.width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))self.height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))self.fps = self.cap.get(cv2.CAP_PROP_FPS)# 初始化ROI maskself._init_roi_mask()def _init_roi_mask(self):"""初始化ROI掩码"""self.roi_mask = np.zeros((self.height, self.width), dtype=np.uint8)cv2.fillPoly(self.roi_mask, [self.roi_points], 255)def _is_inside_roi(self, point):"""判断点是否在ROI内"""return cv2.pointPolygonTest(self.roi_points, point, False) >= 0def _draw_roi(self, frame):"""在帧上绘制ROI"""cv2.polylines(frame, [self.roi_points], True, (0, 255, 0), 2)overlay = frame.copy()cv2.fillPoly(overlay, [self.roi_points], (0, 255, 0))frame = cv2.addWeighted(overlay, 0.1, frame, 0.9, 0)return framedef _update_counts(self, track_id, current_pos):"""更新计数"""if track_id in self.prev_positions:prev_pos = self.prev_positions[track_id]prev_inside = self._is_inside_roi(prev_pos)curr_inside = self._is_inside_roi(current_pos)if not prev_inside and curr_inside:self.in_count += 1elif prev_inside and not curr_inside:self.out_count += 1self.prev_positions[track_id] = current_posdef process_video(self, output_path=None, classes_of_interest=None):"""处理视频并统计ROI内的目标:param output_path: 输出视频路径,None则不保存:param classes_of_interest: 感兴趣的类别列表,None则统计所有类别"""if output_path:fourcc = cv2.VideoWriter_fourcc(*'mp4v')out = cv2.VideoWriter(output_path, fourcc, self.fps, (self.width, self.height))while self.cap.isOpened():ret, frame = self.cap.read()if not ret:break# 进行目标检测和跟踪results = self.model.track(frame, persist=True, classes=classes_of_interest)if results[0].boxes.id is not None:boxes = results[0].boxes.xywh.cpu()track_ids = results[0].boxes.id.int().cpu().tolist()clss = results[0].boxes.cls.cpu().tolist()for box, track_id, cls in zip(boxes, track_ids, clss):x, y, w, h = boxcenter = (int(x), int(y))# 更新轨迹历史track = self.track_history[track_id]track.append(center)if len(track) > 30:  # 保留最近的30个点track.pop(0)# 更新计数self._update_counts(track_id, center)# 绘制轨迹points = np.array(track, dtype=np.int32).reshape((-1, 1, 2))cv2.polylines(frame, [points], isClosed=False, color=(0, 255, 255), thickness=2)# 绘制ROI和计数信息frame = self._draw_roi(frame)cv2.putText(frame, f"In: {self.in_count}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)cv2.putText(frame, f"Out: {self.out_count}", (10, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)# 显示结果cv2.imshow("ROI Counting", frame)if output_path:out.write(frame)if cv2.waitKey(1) & 0xFF == ord('q'):breakself.cap.release()if output_path:out.release()cv2.destroyAllWindows()# 使用示例
if __name__ == "__main__":# 定义ROI多边形顶点(顺时针或逆时针顺序)roi_points = [(300, 200), (800, 200), (900, 600), (200, 600)]# 创建计数器实例counter = VideoROICounter(model_path="yolov8n.pt",video_path="input_video.mp4",roi_points=roi_points)# 处理视频(只统计人和车)counter.process_video(output_path="output_video.mp4",classes_of_interest=[0, 2]  # 0: person, 2: car in COCO dataset)

3.3 代码解析

  1. ROI定义:使用多边形顶点定义感兴趣区域,可以是不规则形状
  2. 目标跟踪:利用YOLOv8的跟踪功能保持目标ID一致性
  3. 进出判断:通过比较目标当前位置与前一帧位置判断进出ROI
  4. 轨迹可视化:绘制目标的运动轨迹便于分析
  5. 类别过滤:可以指定只统计特定类别的目标

4. 进阶改进方向

4.1 多区域计数

可以扩展代码实现多个独立ROI的计数:

class MultiROICounter(VideoROICounter):def __init__(self, model_path, video_path, roi_list):""":param roi_list: 多个ROI的列表,每个ROI是一个顶点坐标列表"""super().__init__(model_path, video_path, [])self.roi_list = [np.array(roi, np.int32) for roi in roi_list]self.roi_masks = [self._create_roi_mask(roi) for roi in self.roi_list]self.counters = [{'in': 0, 'out': 0} for _ in self.roi_list]def _create_roi_mask(self, roi_points):mask = np.zeros((self.height, self.width), dtype=np.uint8)cv2.fillPoly(mask, [roi_points], 255)return maskdef _is_inside_any_roi(self, point):for i, roi in enumerate(self.roi_list):if cv2.pointPolygonTest(roi, point, False) >= 0:return ireturn -1# 重写_update_counts方法实现多ROI计数# ...

4.2 方向敏感计数

改进计数逻辑,只统计特定方向移动的目标:

def _update_counts_with_direction(self, track_id, current_pos):if track_id in self.prev_positions:prev_pos = self.prev_positions[track_id]prev_inside = self._is_inside_roi(prev_pos)curr_inside = self._is_inside_roi(current_pos)# 计算移动方向(只关心y轴方向移动)direction = current_pos[1] - prev_pos[1]if not prev_inside and curr_inside and direction < 0:  # 向上移动进入self.in_count += 1elif prev_inside and not curr_inside and direction > 0:  # 向下移动离开self.out_count += 1

4.3 性能优化技巧

  1. ROI内检测:只在ROI区域内进行目标检测
  2. 帧采样:对高帧率视频进行适当采样
  3. 模型量化:使用量化后的模型提高推理速度
  4. 多线程处理:分离IO和计算任务

5. 实际应用案例

5.1 交通流量统计

在交通监控视频中,统计特定车道内的车辆数量:

# 定义车道ROI
lane_roi = [(300, 400), (500, 400), (550, 600), (250, 600)]counter = VideoROICounter(model_path="yolov8l.pt",  # 使用更大的模型提高车辆检测精度video_path="traffic.mp4",roi_points=lane_roi
)# 只统计车辆类(COCO数据集中2,3,5,7等是车辆类)
counter.process_video(classes_of_interest=[2, 3, 5, 7])

5.2 商场入口人流统计

统计商场入口进出人数:

# 定义门口区域ROI
entrance_roi = [(200, 300), (600, 300), (600, 500), (200, 500)]counter = VideoROICounter(model_path="yolov8s.pt",  # 对小尺寸人检测足够video_path="mall_entrance.mp4",roi_points=entrance_roi
)# 只统计人类(COCO class 0)
counter.process_video(classes_of_interest=[0])

6. 总结与展望

本文详细介绍了如何利用YOLOv8实现视频中划定区域的目标统计计数。通过合理的ROI定义和跟踪计数逻辑,我们可以构建出实用的视频分析系统。未来可以进一步探索:

  1. 结合深度信息实现更精确的3D空间计数
  2. 集成更复杂的行为分析算法
  3. 开发基于Web的交互式ROI定义工具
  4. 优化算法实现实时高清视频处理

YOLOv8的强大检测和跟踪能力为视频分析应用提供了坚实基础,结合特定业务逻辑可以开发出各种实用的智能视频分析系统。

在这里插入图片描述

相关文章:

  • 6.824 lab1
  • float、double 这类 浮点数 相比,DECIMAL 是另一种完全不同的数值类型
  • 动态表单 LiveCycle 与 AcroForms 对比
  • 东南亚用工合规困境破解:从文化冲突到数字化管理升级
  • 央国企人力资源数字化转型:全景路径与6类挑战解析
  • vite+vue3项目中,单个组件中使用 @use报错
  • 群晖NAS套件历史版本资源
  • 动态规划---股票问题
  • AiPy实战:10分钟用AI造了个音乐游戏!
  • Kinova机械臂在Atlas手术导航系统中的核心作用
  • 数论~~~
  • redis配置及优化
  • 兰亭妙微 | 医疗软件的界面设计能有多专业?
  • windows环境Google-sparsehash安装
  • 数据库设计的三大范式
  • 【PhysUnits】15.16 补充to_i32方法的类型级整数表示(basic.rs)
  • 【西门子杯工业嵌入式-1-基本环境与空白模板】
  • 如何排查MySQL是否走索引
  • 是否存在路径(FIFOBB算法)
  • 人工智能100问☞第41问:什么是边缘AI?
  • phton可以做网站吗/查排名官网
  • 本地的丹阳网站建设/今日热点新闻15条
  • 打开汽车之家网页版/关键词排名的排名优化
  • adobe 网站制作软件有哪些/谷歌竞价广告
  • 衢州网站建设专业的公司/郑州百度seo排名公司
  • 做网站好的公司/如何查看百度搜索指数