ARTICLE DETAIL

资讯详情

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

基于YOLOv5的水域游泳者危险检测:数据集构建与训练避坑指南

基于YOLOv5的水域游泳者危险检测:数据集构建与训练避坑指南 简介这份资源是面向高校学生与深度学习初学者的水域游泳者危险检测识别系统完整项目包基于YOLOV5目标检测框架实现可直接用于期末大作业、课程设计或毕业设计参考。压缩包共1878个文件约235.38MB包含880张jpg与4张jpeg图像样本、811个txt标注文件、60个yaml配置、34张png图表、27个py源码脚本及11个pt权重文件另附sh脚本、Dockerfile与ipynb笔记覆盖数据、训练、推理与部署全流程。项目已获导师指导并通过取得96分高分代码完整下载即可运行。已有287人学习关注读者可从中获得完整的数据集与标注、YOLOV5模型训练与推理代码、配置文件与预训练权重以及可复现的实验记录便于快速理解水域危险检测任务的实现思路并在此基础上二次开发。1. 水域游泳者危险检测为什么通用 YOLOv5 模型直接拿来用会翻车夏天一到泳池、水库、河道边的监控画面里最怕出现的不是人多而是有人在水里姿势不对、长时间不动、或者突然下沉。基于 YOLOv5 的水域中游泳者危险检测识别系统本质上就是把这套目标检测框架搬到水域场景让模型从监控画面里框出「人」再结合位置、姿态、停留时间判断是否处于危险状态。它解决的是人工盯屏容易疲劳、漏看的问题适合做期末大作业、课程设计也适合安防方向想快速跑通一套可演示系统的同学。但这里有个反直觉的结论直接拿 COCO 预训练的 YOLOv5 权重去跑泳池画面mAP 往往掉得厉害。原因不复杂——通用数据集里「人」大多是站立、行走、上半身清晰而水域场景里人只露出头肩、水面反光、身体被水遮挡、俯视角度畸变模型看到的分布完全变了。所以这套系统的核心不是「调 YOLOv5」而是「让 YOLOv5 认识水里的人」。源码和数据集的价值就在于把这条从通用到专用的迁移路径固定下来让你不用从零标注就能复现。2. 数据集怎么组织从原始监控帧到 YOLOv5 可训练的标签2.1 水域危险检测的数据集该标什么、分几类先明确标注对象。水域场景里我一般把类别拆成两类或三类取决于你的演示粒度两类方案swimmer正常游泳者、danger危险状态如挣扎、下沉、长时间静止。三类方案swimmer、drowning溺水征兆、floating漂浮不动。对期末大作业来说两类足够跑通闭环三类更出彩但标注成本翻倍。标注时用矩形框不要用关键点因为 YOLOv5 是检测框架关键点需要换 head超出标题范围。数据集目录建议按下面结构放这是 YOLOv5 官方推荐的布局源码里一般也按这个读dataset/ ├── images/ │ ├── train/ # 训练集图片jpg/png │ ├── val/ # 验证集图片 │ └── test/ # 测试集图片可选 ├── labels/ │ ├── train/ # 与图片同名的 txt 标签 │ ├── val/ │ └── test/ └── data.yaml # 数据集配置文件图片和标签必须同名比如images/train/001.jpg对应labels/train/001.txt。标签格式是 YOLO 标准每行class_id x_center y_center width height全部归一化到 0~1。很多同学第一次跑报「找不到标签」九成是路径或同名没对上。2.2 data.yaml 的四个关键字段与常见写错点data.yaml是训练入口字段不多但错一个就训练不起来# dataset/data.yaml path: ../dataset # 数据集根目录相对或绝对都行 train: images/train # 相对 path 的训练图片目录 val: images/val # 相对 path 的验证图片目录 nc: 2 # 类别数必须和 names 长度一致 names: # 类别名顺序即 class_id 0: swimmer 1: danger逻辑说明path是基准目录train/val是相对它的子路径YOLOv5 会拼成完整路径去读图。nc和names必须严格对应names的键就是标签里的class_id。参数上最容易翻车的是nc写成 1 但标签里有1这个类训练时直接报 index 越界。提示如果数据集是从网上下的压缩包先检查标签里有没有class_id超出nc-1的情况用一行脚本统计一下最稳。import os from collections import Counter label_dir dataset/labels/train counter Counter() for f in os.listdir(label_dir): if f.endswith(.txt): with open(os.path.join(label_dir, f)) as fp: for line in fp: if line.strip(): counter[line.split()[0]] 1 print(counter) # 看各类别 id 分布确认没有越界这段脚本遍历训练标签统计每个class_id出现次数。如果打印出的键里有大于等于nc的值说明标签和配置不匹配必须先修标签再训练否则后面全是无用功。3. 用 YOLOv5 训练水域危险检测模型环境、命令与超参数3.1 环境配置conda 建环境到跑通 detect 的最小步骤环境这块血泪经验是别在 base 环境里装依赖冲突会让你怀疑人生。用 conda 单独建一个conda create -n yolo_water python3.9 -y conda activate yolo_water # 克隆 YOLOv5 官方仓库源码包里一般已含可跳过 git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt装完后先验证环境能不能跑推理别急着训练python detect.py --weights yolov5s.pt --source data/images/bus.jpg这条命令用官方预训练权重跑一张示例图能正常输出带框图片说明 PyTorch、CUDA如果装了和依赖都通了。如果这里就报错先解决环境问题训练阶段只会放大错误。参数说明--weights指定权重文件--source可以是单图、目录或视频。3.2 训练命令与 batch、imgsz、epochs 三个必调参数环境通了之后用迁移学习微调。水域数据集通常几千张从yolov5s.pt起步最稳python train.py \ --img 640 \ --batch 16 \ --epochs 100 \ --data dataset/data.yaml \ --weights yolov5s.pt \ --cfg models/yolov5s.yaml \ --name water_danger \ --cache逻辑说明--weights yolov5s.pt加载 COCO 预训练权重做迁移学习这是小数据集能收敛的关键--data指向你的data.yaml--name是这次训练的输出目录名结果会存到runs/train/water_danger/。参数逐个说--img 640输入分辨率。水域里人小可以试 640 或 768越大越吃显存但小目标召回更好。--batch 16批大小。显存不够就降到 8 或 4别硬撑OOM 会直接中断。--epochs 100训练轮数。小数据集 100~300 都常见看验证集 mAP 是否还在涨。--cache把图片缓存到内存加速读取数据集大时慎用会吃内存。训练过程中重点看runs/train/water_danger/results.csv里面记录了每轮的metrics/mAP_0.5。如果 20 轮后 mAP 还在 0.1 附近不动多半是标签或data.yaml有问题回去查第 2 章。3.3 从检测框到危险判断后处理逻辑怎么写YOLOv5 只给你框危险判断得自己加一层。常见做法是结合「位置 停留时间 框的宽高比」import time # 简化示意记录每个 track_id 在水面区域内的停留时长 danger_records {} def judge_danger(track_id, box, water_zone, fps25): x1, y1, x2, y2 box cx, cy (x1 x2) / 2, (y1 y2) / 2 # 判断中心点是否落在预设的水面危险区域内 in_zone water_zone[0] cx water_zone[2] and water_zone[1] cy water_zone[3] if not in_zone: danger_records.pop(track_id, None) return False rec danger_records.setdefault(track_id, {start: time.time(), still: 0}) # 框宽高比异常比如接近正方形且很小可能是下沉 w, h x2 - x1, y2 - y1 if h 0 and 0.8 w / h 1.2 and w 40: rec[still] 1 else: rec[still] 0 duration time.time() - rec[start] # 停留超过阈值或静止帧数过多判为危险 return duration 10 or rec[still] fps * 3逻辑说明water_zone是你根据摄像头画面手动框出的水面区域只有落在这个区域内的目标才参与危险判断避免岸上的人误报。duration是目标在区域内持续停留时间超过 10 秒触发still统计框接近正方形且很小的连续帧数模拟「下沉只剩头顶」的形态。参数上10秒和fps*3都要按你的场景调泳池和野水域差别很大。注意这套后处理是规则兜底不是模型输出。演示时能讲清楚「检测 规则」两层结构比单纯说模型准确率更有说服力。4. 避坑与排查训练水域危险检测模型时最容易踩的五个坑4.1 现象训练 loss 一直不降mAP 卡在 0.0x原因最常见是标签路径错或标签格式错。YOLOv5 找不到标签时不会报错而是当成背景训练loss 自然不降。其次是data.yaml里nc和实际类别数不一致。解决先跑第 2.2 节的统计脚本确认class_id范围再检查labels/train下 txt 是否和图片同名。可以用下面命令快速比对# 找出有图无标签的文件 for img in dataset/images/train/*.jpg; do labeldataset/labels/train/$(basename ${img%.jpg}).txt [ -f $label ] || echo 缺标签: $img done4.2 现象验证集 mAP 很高但实际视频里漏检严重原因训练集和验证集来自同一段视频或同一摄像头分布太像模型过拟合到那个视角。换一个角度或光线就崩。解决划分数据集时按摄像头或时间段切分别随机切。比如 A 摄像头画面全进训练B 摄像头画面进验证这样验证集 mAP 才反映真实泛化能力。4.3 现象显存 OOM训练中途崩原因--batch或--img设太大或者--cache把大图全塞内存。解决先把--batch降到 8再不行降到 4--img从 640 降到 512去掉--cache。用nvidia-smi看显存占用留 1~2GB 余量。4.4 现象水面反光被误检成游泳者原因训练集里反光样本少模型把高亮区域学成了目标特征。解决在数据增强里加--hsv_h 0.015 --hsv_s 0.7 --hsv_v 0.4让模型对亮度变化更鲁棒同时补一批含反光的负样本空标签图进训练集。4.5 现象推理速度慢视频卡顿原因用了大模型如yolov5x或输入分辨率过高边缘设备扛不住。解决换yolov5s或yolov5n--img降到 416导出 ONNX 或 TensorRT 加速。树莓派 5 上部署自己训练的 YOLOv5 模型时优先用yolov5n ONNX Runtime实测比原生 PyTorch 快不少。5. 进阶技巧用验证集曲线和混淆矩阵判断模型到底能不能用训练完不是看一个 mAP 就完事。我一般会打开runs/train/water_danger/下的几张图它们比数字更能说明问题。先看results.png重点看三条线train/box_loss、val/box_loss、metrics/mAP_0.5。如果训练 loss 一直降但验证 loss 开始抬头说明过拟合该早停或加数据增强。如果两条 loss 都平说明欠拟合加 epochs 或换更大模型。再看confusion_matrix.png。水域危险检测最怕的是把danger漏判成swimmer所以重点看danger那一行的召回。如果danger大量被分到background说明危险样本太少或特征不明显需要补样本或调类别权重。最后看val_batch0_pred.jpg这是验证集第一批的预测可视化。直接肉眼比对预测框和真实框能发现很多数字看不出的问题比如框偏大、框到水面反光、密集人群漏检。一个具体技巧导出模型时用--include onnx然后在推理脚本里固定--conf 0.4 --iou 0.5起步再根据误报漏报微调。conf 太低误报多太高漏检多水域场景我一般从 0.4 开始试。python export.py --weights runs/train/water_danger/weights/best.pt --include onnx导出后可以用 ONNX Runtime 加载脱离 YOLOv5 仓库跑推理方便集成到你的大作业系统里。参数上--include支持onnx、torchscript、engine等按部署环境选。我自己踩过最深的坑是第一次做这类系统时只看 mAP 就交作业结果答辩现场换了一段新视频模型几乎全漏。后来养成习惯训练完先拿一段完全没参与训练的视频跑一遍肉眼数漏检和误报再决定要不要返工。这个习惯比任何指标都靠谱。希望帮到你。本文还有配套的精品资源点击获取
返回列表