ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于YOLOv8+ByteTrack的道路行人检测与逆行识别实现

基于YOLOv8+ByteTrack的道路行人检测与逆行识别实现 道路场景的行人检测与逆行行为识别本质上是一条“检测 → 跟踪 → 行为推断”的技术链路。检测器负责在视频帧里找到行人跟踪器负责把前后帧的同一个目标关联起来最后的行为判断模块根据轨迹方向或行走区域判定是否逆行。这个方向在智慧交通、园区安防、路口监控里有实际需求难点通常不在单帧检测而在跨帧关联和判断规则的可靠性。一个视频画面里同时出现几个逆行的行人如何持续锁定它们并且尽量少误报才是真正要解决的工程问题。这篇文章按实际工程落地的方式展开先梳理整体技术架构再对比行人检测模型与跟踪算法的选型随后给出基于 YOLOv8 ByteTrack 轨迹规则判定的可运行代码链路最后补充数据集准备、训练调优、TensorRT 部署、显存观察、API 接口和常见问题排查。无论你是做智慧交通方向的研究、准备完成毕业设计还是要把这类功能集成到现有监控平台都可以把本文作为一套起步参考。先说结论这一类研究项目并不依赖概念上的高深技巧核心价值在于把检测、跟踪、方向判断三个模块稳定地串起来。本文所有流程都尽量使用可复制的代码和命令显存占用、推理速度这类参数会受分辨率、模型版本和 GPU 型号影响建议以本机实际测试为准。1. 核心能力速览能力项说明研究方向道路场景行人检测、跨帧轨迹跟踪、逆行行为判定核心链路视频帧输入 → 行人检测 → 多目标跟踪 → 方向/区域规则判断 → 逆行标记与告警常用检测模型YOLOv5、YOLOv8、YOLOv9、RT-DETR、Faster R-CNN 等常用跟踪算法ByteTrack、BoT-SORT、DeepSORT逆行判定方式轨迹方向与场景标定方向夹角判断可叠加禁行区域规则推理框架PyTorch、ONNX Runtime、TensorRT推荐硬件支持 CUDA 的 NVIDIA GPU显存越大越稳CPU 可跑但实时性受限启动方式Python 命令行、HTTP API 服务接口能力可输出目标框、跟踪 ID、轨迹方向角、逆行标签批量处理支持单张图片、视频文件、批量文件夹任务输出内容检测框标注视频、CSV/JSON 结构化结果、逆行事件片段表格里的配置不是固定答案实际以你选择的模型训练权重和部署设备为准。下面从技术架构开始讲。2. 适用场景与使用边界2.1 典型应用场景道路场景行人检测与逆行行为识别常见落点包括市政单行道、步行街判断行人是否沿规定方向行走当检测到长时间逆行的目标时产生告警。园区与工厂通道限定行人只能在指定区域、指定方向通行对穿越或逆行行为做记录。路口与斑马线附近结合区域规则识别闯禁行方向、横穿等行为为交通管理提供结构化事件数据。逆向跑动的人群监控在大型活动、枢纽通道中识别异常移动方向辅助现场调度。这些场景的共同特点是安装位置固定、画面视野相对稳定、监控区域可标定。正因为如此逆行识别通常可以走“规则判定”路线而不是完全依赖行为分类网络。2.2 功能边界与限制规则法逆行识别高度依赖相机视角和场景标定。相机安装角度变化后参考方向向量必须重新画一次画面中人流量过大、遮挡严重时跟踪器容易出现 ID 切换造成轨迹断裂夜间、逆光、低分辨率画面对小目标行人检测也会明显下降。同时需要明确合规边界。凡是涉及行人监控的功能部署时必须确认已经获得合法授权并遵守当地关于公共区域视频监控、个人信息保护的法规。本文介绍的技术仅限用于合规的交通管理、园区安防和研究测试不得用于未经授权的个人轨迹采集。3. 行人检测与逆行识别的技术架构3.1 整体处理流程整个系统可以分为四个阶段视频输入与抽帧读取本地视频、RTSP 流或图片序列按固定帧率送入检测器。行人检测检测当前帧中的行人目标输出边界框、置信度、类别。多目标跟踪将前后帧的检测框关联起来赋予稳定 ID输出轨迹点序列。逆行行为推断基于每条轨迹的运动方向、所在区域判断目标是否逆行。这里最关键的设计判断是逆行识别不需要只靠单帧图像。单帧图像只能看到“人在这里”看不到“人从哪来、往哪去”因此必须依赖时序信息。实际工程实现中跟踪器的稳定性往往比检测器的单帧精度更重要。3.2 检测模型对比道路行人检测常用的模型可以分成三类模型特点适用场景YOLOv8 / YOLOv9 / YOLO11单阶段检测器训练与部署生态成熟导出 ONNX/TensorRT 方便实时监控、批量视频处理RT-DETR无锚框检测在部分 CPU 场景下速度也可接受结构相对简洁需要省显存或 CPU 部署的试验场景Faster R-CNN两阶段检测器理论精度上限高但推理速度较慢离线分析、精度优先的数据集研究从工程落地角度看YOLO 系列是最稳妥的起步选择。原因是文档多、工具链完整Ultralytics 自带数据集格式、训练脚本、导出脚本能直接和 ByteTrack、BoT-SORT 等跟踪库对接。3.3 跟踪算法对比跟踪算法核心思路适合场景ByteTrack对低置信度检测框也参与匹配简单高效拥挤行人场景ID 切换少BoT-SORT结合相机运动补偿和更强的轨迹关联相机轻微晃动、密集人群DeepSORT依赖行人重识别特征网络匹配需要长时身份保持的离线分析实时监控优先建议 ByteTrack 或 BoT-SORT。ByteTrack 对行人密集、遮挡频繁的场景更稳代码集成也简单。如果相机存在轻微震动或者目标经常被车辆、路灯遮挡BoT-SORT 的效果会更稳定一些。4. 环境准备与本地部署行人检测推理环境4.1 硬件与系统要求本项目不是纯理论模型需要跑推理建议准备操作系统Windows 10/11、Ubuntu 18.04 或 20.04、Debian 等 Linux 发行版均可。GPUNVIDIA 显卡优先建议显存不低于 6GB后续使用 TensorRT 加速时需要 NVIDIA GPU。设备 AC 电源要稳定尤其是长时间跑批量任务时避免供电波动导致驱动崩溃。CPU 推理可以运行但帧率会明显下降适合离线抽帧验证算法不适合多路实时处理。磁盘空间前置环境 10GB 以上比较稳妥模型权重文件和视频素材另算。CUDA 与 PyTorch 版本谨慎安装。先确认显卡驱动版本再装对应 CUDA。如果没有硬性版本要求PyTorch 2.x 搭配 CUDA 11.8 或 12.1 是当前社区使用较多的组合。具体版本请以 PyTorch 官方命令为准避免装错后反复排查驱动链接错误。4.2 Python 环境与依赖安装建议使用 conda 或 venv 创建独立环境避免和系统其它 Python 包冲突。# 创建虚拟环境 conda create -n traffic-cv python3.10 -y conda activate traffic-cv基础依赖如下安装时按需精简不要一次全装# 核心依赖 pip install torch torchvision pip install ultralytics pip install opencv-python pip install numpy pandas # 跟踪与可视化相关 pip install supervision # 如需提供 HTTP 接口 pip install fastapi uvicorn python-multipart在没有 GPU 的机器上可以把torch的安装命令替换为 CPU 版本但涉及 TensorRT 部署的章节将无法执行。建议首次搭建时先跑通 CPU 推理再上 GPU。5. YOLOv8 行人检测与 ByteTrack 跟踪实现5.1 视频帧读取与 YOLOv8 行人检测下面先写一个最基础的单帧检测代码目标是把画面里的人找出来并画框。import cv2 from ultralytics import YOLO # COCO 数据集中 person 类别的 id 是 0 PERSON_CLASS_ID 0 model YOLO(yolov8n.pt) frame cv2.imread(street_frame.jpg) results model.predict(frame, conf0.4, verboseFalse) for box in results[0].boxes: cls_id int(box.cls[0]) if cls_id ! PERSON_CLASS_ID: continue x1, y1, x2, y2 map(int, box.xyxy[0]) conf float(box.conf[0]) cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(frame, fperson {conf:.2f}, (x1, y1 - 6), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.imwrite(detect_result.jpg, frame)这个步骤先把检测器跑通再接入跟踪器。实际监控中不会每帧都加载权重模型初始化放在程序启动阶段后续只调用推理接口。5.2 使用 ByteTrack 获取稳定 ID街道场景的行人经常互相遮挡、拥挤前行。单帧检测结果没有身份信息前后帧的人是谁必须靠跟踪算法回答。ByteTrack 是非常轻量的选择这里用 supervision 库内置封装的实现来演示链路接口名称以实际安装版本为准。import cv2 import supervision as sv from ultralytics import YOLO PERSON_CLASS_ID 0 model YOLO(yolov8n.pt) tracker sv.ByteTrack(minimum_matching_threshold0.5) # 以视频文件为输入 VIDEO_PATH road_clip.mp4 cap cv2.VideoCapture(VIDEO_PATH) frame_id 0 while True: ret, frame cap.read() if not ret: break frame_id 1 # 1. 检测 results model.predict(frame, conf0.4, verboseFalse) # 2. 转换为 supervision 标准格式并过滤行人 detections sv.Detections.from_ultralytics(results[0]) detections detections[detections.class_id PERSON_CLASS_ID] # 3. 跟踪 tracked tracker.update_with_detections(detections) # 4. 输出每个目标的 ID 与 bbox for tid, bbox, confidence in zip(tracked.tracker_id, tracked.xyxy, tracked.confidence): x1, y1, x2, y2 map(int, bbox) print(frame_id, tid, round(float(confidence), 2), [x1, y1, x2, y2]) cap.release()这段链路即使不接逆行判断也已经是一个完整的“行人检测 多目标跟踪”基础服务。下一步要解决的是拿到 ID 之后怎么判断这个人是不是在逆行。5.3 轨迹点管理逆行判断需要历史轨迹不能只依赖当前帧。建议为每个跟踪 ID 维护一个固定长度的轨迹队列保存最近 N 帧的中心点坐标。这样既能计算运动方向也能在遮挡造成短暂丢帧后继续判断。from collections import deque TRACK_BUFFER_LEN 10 track_point_buffers {} def buffer_center(track_id, cx, cy): if track_id not in track_point_buffers: track_point_buffers[track_id] deque(maxlenTRACK_BUFFER_LEN) track_point_buffers[track_id].append((cx, cy))轨迹长度不建议无限扩张。长度过大时目标已经转弯很久方向判断会滞后长度过短时方向向量噪声太大。10 到 15 帧是一个比较实用的起步窗口。6. 逆行行为识别的判定算法设计与实现6.1 判定思路逆行识别最常见的做法是“参考方向 位移向量夹角判断”。建设流程如下在每一路固定相机画面中标定一个规则通行方向例如画面中行人正常从下往上走参考方向设为(0, -1)。对每个跟踪 ID由轨迹队列计算实际运动方向。计算实际运动方向与参考方向的夹角夹角越接近 180°说明目标越接近“朝反方向走”。为了抗抖动要求连续最小帧数内夹角都超过阈值才判定为逆行。阈值设置举例如果参考方向规定为“从上到下”即(0, 1)那么夹角超过 120° 可以视作明显逆行超过 150° 则几乎完全反向。实际操作中阈值建议通过一段标注视频调试避免过于灵敏。这里需要注意坐标习惯图像坐标系 y 轴向下画面中人的运动方向向量必须按实际像素坐标计算。不要直接把“路面方向”套进代码。6.2 逆行判断器实现下面给出一段可直接扩展的判断器模板。它维护每个跟踪 ID 的轨迹点周期性计算方向夹角并在连续超过阈值时返回逆行标记。from collections import deque import numpy as np class ReverseJudge: def __init__(self, ref_dir(0, 1), angle_threshold120, min_frames5, buffer_len10): # ref_dir 必须是画面中“规定通行方向”的像素向量 self.ref_dir np.asarray(ref_dir, dtypenp.float32) self.angle_threshold angle_threshold self.min_frames min_frames self.buffer_len buffer_len self.track_points {} self.track_angles {} def update(self, track_id, cx, cy): if track_id not in self.track_points: self.track_points[track_id] deque(maxlenself.buffer_len) self.track_angles[track_id] deque(maxlenself.min_frames 1) self.track_points[track_id].append((cx, cy)) direction self._moving_direction(track_id) if direction is not None: angle self._angle_to_ref(direction) self.track_angles[track_id].append(angle) def _moving_direction(self, track_id): pts self.track_points[track_id] if len(pts) 2: return None first np.asarray(pts[0], dtypenp.float32) last np.asarray(pts[-1], dtypenp.float32) direction last - first norm np.linalg.norm(direction) if norm 1e-4: return None return direction / norm def _angle_to_ref(self, direction): cos np.dot(direction, self.ref_dir) / ( np.linalg.norm(self.ref_dir) 1e-6 ) cos float(np.clip(cos, -1.0, 1.0)) return np.degrees(np.arccos(cos)) def is_reverse(self, track_id): angles self.track_angles[track_id] if len(angles) self.min_frames: return False over_threshold [ a for a in angles if a is not None and a self.angle_threshold ] return len(over_threshold) self.min_frames - 1 def reset(self, track_id): self.track_points.pop(track_id, None) self.track_angles.pop(track_id, None)调用逻辑如下在跟踪循环中取得每个 track_id 的 bbox 中心点后传入update每隔一定帧数调用is_reverse返回True就产生逆行事件。跟踪丢失或目标离开画面后调用reset(track_id)清理缓存。6.3 区域规则叠加方向夹角规则适合“单方向道路”但很多路口同时存在多个通行方向。这时候可以在画面中定义多个多边形区域每个区域配置独立的参考方向向量。例如区域 A 为左侧人行道参考方向为(-1, 0)。区域 B 为右侧非机动车道方向参考方向为(1, 0)。判断顺序调整为先根据 bbox 中心点判断目标落在哪个区域。取该区域的参考方向向量。再计算夹角判断是否逆行。区域可以用多边形顶点描述例如 OpenCV 的cv2.pointPolygonTest完成点与多边形的包含判断。区域规则的价值在于能规避画面内“双向通行都合法”的情况例如双向人行道只有进入禁行区的一端才算逆行。这种场景仅靠全局夹角就会大量误报。7. 行人检测数据集与模型训练调优7.1 公开数据集参考训练行人检测模型时可供参考的公开数据集包括 CityPersons、BDD100K、Waymo Open Dataset、UA-DETRAC、VisDrone 等。这些数据集在场景多样性、遮挡程度、天气条件下各有侧重。使用前务必确认数据集许可证部分数据集可能限制商用。COCO 数据集本身包含 person 类别YOLOv8 官方权重已经带有较强的行人检测能力。研究起步阶段可以直接用 COCO 预训练权重后续再用自建道路场景数据微调。7.2 自建数据与标注道路监控场景的特殊性在于“相机视角固定”。算法从 3 米高度俯拍和从 20 米高位俯拍看到的行人尺寸差异很大。直接使用公开数据集训练出的模型部署到自建相机上不一定效果最佳。自建数据集建议按以下流程从本地监控视频中均匀抽帧覆盖不同时段白天、夜间、黄昏、雨天。使用 LabelImg、X-AnyLabeling 或 Roboflow 标注行人 bbox。导出为 YOLO 格式的 txt 标注并划分 train/val。训练时重点检查小目标类别的漏检情况。如果目标是对道路场景的行人进行实时检测与逆行识别建议把“夜间、遮挡、逆光”三类样本单独建目录方便后续针对性增强。7.3 训练与调优要点# 使用 Ultralytics 训练 YOLOv8配置文件按自己数据集调整 yolo detect train modelyolov8n.pt datadataset.yaml epochs60 imgsz640 batch8训练时优先关注以下指标mAP0.5判断模型对简单场景的基本识别能力。mAP0.5:0.95判断 bbox 定位精度跟踪稳定性与之强相关。小目标召回率道路场景中远处行人可能只有几十像素最容易漏检。工程调优顺序建议是先解决漏检提高输入分辨率、增加小目标增强再解决误检检查负样本、降低低置信度报警最后解决跟踪 ID 切换换用更强的跟踪算法、调整匹配阈值。不要在 mAP 很低的时候直接调跟踪参数方向判断的误差往往是从检测误差传播过来的。8. 部署优化、显存监控与 API 接口8.1 观察显存与推理性能推理性能不能只看模型理论计算量。实际运行时显存占用与输入分辨率、batch 大小、跟踪器缓存数量强相关。建议用工具实时监控# 每 1 秒刷新一次显存状态 nvidia-smi -l 1批量处理视频时分辨率从 1280 降到 640速度往往能提升数倍显存占用也明显下降。对识别“是否逆行”这类行为任务把检测分辨率降到 640 通常已经够用方向夹角计算并不需要 2K 级别的画面细节。最终推理帧率与显存占用需要在实际设备和视频码率下测试不同机器差异很大。8.2 TensorRT 加速需要实时处理多路视频时PyTorch 的推理开销偏高。常见优化路径是把 YOLOv8 权重导出为 TensorRT engine。# 导出 TensorRT engine需要 NVIDIA GPU 与匹配的 TensorRT 环境 yolo export modelyolov8n.pt formatengine device0 halfTrue导出成功后加载yolov8n.engine即可获得比 ONNX Runtime 更高的推理吞吐。实际收益取决于显卡型号、输入分辨率与半精度支持建议在接口部署前做 A/B 对比。8.3 提供 HTTP API把检测与逆行判断封装成 HTTP 服务可以让前端页面、告警系统或第三方平台直接调用。这里以 FastAPI 为例给出通用框架。from fastapi import FastAPI, UploadFile, File import cv2 import numpy as np app FastAPI() reverse_judge ReverseJudge() # 复用上一节实现 app.post(/api/detect/reverse) async def detect_reverse(file: UploadFile File(...)): data await file.read() arr np.frombuffer(data, dtypenp.uint8) frame cv2.imdecode(arr, cv2.IMREAD_COLOR) # 假设 pipeline.detect_and_track 返回 [track_id, bbox, confidence, reverse] result pipeline.detect_and_track(frame) return { status: ok, frame_width: frame.shape[1], frame_height: frame.shape[0], tracks: result, }返回的 JSON 可以设计为{ status: ok, frame_width: 1920, frame_height: 1080, tracks: [ { track_id: 3, bbox: [120, 340, 180, 420], confidence: 0.86, angle: 165.4, reverse: true }, { track_id: 7, bbox: [700, 500, 760, 620], confidence: 0.72, angle: 18.0, reverse: false } ] }FastAPI 默认监听 8000 端口。如果端口被占用可以换端口启动uvicorn main:app --host 0.0.0.0 --port 8000注意HTTP 接口暴露到公网前必须加认证与访问控制。内部测试时可以绑定127.0.0.1避免未授权的访问。8.4 批量视频处理批量处理本地视频时可以写一个简单的目录遍历脚本# 批量处理 videos 目录下所有 mp4 文件 for video in ./videos/*.mp4; do name$(basename $video .mp4) python run_batch.py --source $video --output ./results/$name.csv done批量任务建议为每个视频记录独立日志输出包含帧号、track_id、目标框、方向夹角、是否逆行的 CSV 文件。如果视频长时间处理或者中途卡住日志能帮你在哪一帧定位问题。8.5 异步任务与失败重试检测服务用于真实业务时不建议把所有请求串行堵塞。更稳的设计是视频或图片上传后进入任务队列。后台 worker 异步处理。前端轮询或通过回调获取结果。单次任务失败时自动重试 1 到 2 次记录失败原因。接口服务和批量任务的分离逻辑保持一致接口负责接收请求后台负责跑模型推理避免视频流阻塞导致接口超时。9. 常见问题与排查方法问题现象可能原因排查方式解决方案检测漏检严重目标太小、遮挡多、分辨率低打印检测框数量并可视化失败帧提高输入分辨率、换更大模型、增加小目标增强行人检测误检多背景复杂、负样本不足统计误检框的类别置信度分布增加负样本图像、降低低置信度输出跟踪 ID 频繁切换行人密集、相互遮挡输出 ID 序列观察切换频率换 BoT-SORT、降低检测阈值、修改匹配窗口逆行误报参考方向标定错误可视化轨迹方向与参考方向向量重新在画面中标定参考方向或调大角度阈值逆行漏报轨迹过短、判断帧数过大检查min_frames参数减小min_frames或缩短轨迹缓冲长度显存不足分辨率过高、batch 过大观察nvidia-smi -l 1的显存峰值降低分辨率、batch 设为 1、导出 TensorRT启动后页面或服务打不开端口冲突或服务未启动检查终端日志与端口占用更换端口或重启服务CPU 推理速度太慢模型复杂度与设备能力不匹配测试单帧处理耗时降低 imgsz、换轻量模型、或部署到 GPU夜间效果差光照变化大、训练数据缺少夜间样本单独评估夜间视频采集夜间数据做增强或使用兼容夜间的输入策略批量任务中某个视频卡住视频流损坏或输入路径错误查看该视频的日志输出增加异常捕获与失败重试每次修改参数后建议只改一个变量。例如先调检测阈值确认漏检变化再调跟踪参数如果同时改多个很难定位性能波动来自哪里。10. 工程化落地最佳实践与下一步这一方向最值得尝试的不是把检测模型刷到很高的 mAP而是把“检测 跟踪 方向判定”的闭环完整搭建起来。先从单路固定相机拍一段 5 分钟视频开始把 YOLOv8 检测框、ByteTrack ID、轨迹方向夹角的可视化结果导出一段测试视频。只要这条链路稳定再叠加多相机标定、夜间模型、告警推送都相对容易。最先应该验证的功能有三项一是行人检测的漏检率是否可接受二是目标在画面中交叉行走时跟踪 ID 是否保持稳定三是逆行判断在正常行走和逆行样本之间的角度分布是否有明显分界。角度的区分度直接决定规则法是否可靠。输出角度直方图能直观看到正态行走方向和逆行方向是否分离如果重合严重说明参考方向标定或相机视角有问题不建议继续调大阈值掩盖问题。最容易踩的坑有两个。第一个是直接把 COCO 预训练权重部署到高空俯拍相机导致行人目标过小、漏检严重第二个是在没有跟踪稳定性的前提下强行调逆行阈值结果多数误报来自 ID 切换。建议先用一段场景接近的数据微调检测模型再集中精力优化跟踪与判定。后续扩展方向可以考虑在检测模块接入更适合小目标的高分辨率分支把规则夹角替换为短时行为分类网络让模型学习“正常走、逆行、停留、横穿”等等也可以把 TensorRT 加速后的单路服务扩展到多路视频流配合消息队列实现批量告警。对于研究性质的课题还可以把注意力集中在遮挡场景下的轨迹重建这对逆行识别的漏报率影响最大。建议先搭建一条最小验证链路视频输入 → 检测框 → 跟踪轨迹 → 逆行标签 → 结构化结果导出。这条链路跑通后再把模型、阈值和推理框架逐步替换成生产级方案整个过程会可控得多。
返回列表