资讯动态

YOLOv8跌倒检测实战:数据集清洗、训练调参与摄像头部署

发布时间:2026/9/11 1:48:16 来源:尧图企业网站定制
简介这是一套基于YOLOv8的跌倒检测毕业设计完整项目面向计算机视觉方向学生与开发者旨在解决老年人监护、公共场所及家庭安全中的跌倒识别问题适用于课程设计与毕设参考。压缩包共1437个文件以1428张JPEG图像数据集为主辅以6个Python训练/推理脚本、1个ONNX模型、1个PT权重文件和1个Markdown说明文档整体约78.41MB目录结构统一便于按模块检索。已有91人学习适合快速上手与二次开发。资源涵盖数据准备、模型训练、评估与导出全流程JPEG数据集包含多种跌倒与非跌倒场景可直接运行源码查看检测效果配套的ONNX和PT权重文件方便部署验证Markdown文档梳理了实验思路有助于理解YOLOv8网络结构、训练策略与软件工程实践。学习者能从中掌握从数据集整理、模型训练到结果评估的完整链路对做毕业设计或深入目标检测算法均有较高参考价值。1. 从“yolov8训练跌倒检测”源码包到自己的模型先搞懂训练闭环跌倒检测如今是目标检测领域最常见的毕业设计题之一。YOLOv8 把训练入口收敛成一个命令数据集和源码包也容易找到看起来比检测加跟踪更可控但真正拿到压缩包后卡点反而在开头标签不干净、类别 id 对不上、训练参数含义不清楚于是 loss 不降或 mAP 很低。这篇按实际动手顺序来讲先把数据集和标注格式理清再配置 yolov8 环境跑通第一次训练之后用损失曲线和数据增强调训练最后把 best.pt 导出接到摄像头做连续帧跌倒判定。适合正在做毕设、课程设计或第一次用 yolov8 训练自己的数据集的读者。2. 跌倒检测数据集的目录结构、标注格式与清洗脚本2.1 先决定用 YOLO 格式还是 COCO 格式YOLOv8 的原生训练接口同时支持 YOLO 格式的 txt 标签和 COCO 格式的 json 标签但跌倒检测这种单类别场景我一般直接用 YOLO 格式。每一张 jpg/png 对应一个同名 txttxt 里每一行代表一个目标框内容依次是类别 id、归一化后的中心点 x、中心点 y、框宽 w、框高 h。类别 id 从 0 开始坐标全部除以图片宽高后落到 0 到 1 之间。对比项YOLO txt 格式COCO json 格式每个目标的行数每行 5 个数字每个 annotation 一个字典坐标方式中心点宽高归一化左上角宽高像素值修改难易文本编辑器可改需要解析 json 再改yolov8 支持程度原生、最快支持但要多转一次适合场景自定义数据集、快速验证已有 COCO 结构或要换 mmdetection不要迷信源码包里现成的标签。很多公开的跌倒检测数据集的框是半自动标注出来的常见问题包括框的中心点坐标越界、宽高写成像素值没归一化、类别 id 写了两个却在 data.yaml 里只声明一个类别。YOLO 格式的好处就在这里任何异常都能用脚本扫出来。2.2 按 images/labels 结构重建目录不管压缩包里原来的目录长什么样我会先把数据集统一成下面的结构datasets/fall/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yamlimages 下放原始图片labels 下放同名 txt。注意文件名要一一对应jpg 配 jpg 的同名 txt最好连扩展名也统一成 .jpg避免出现一张图片叫 a.jpg、标签叫 a.txt 却另一个叫 b.JPG 的情况。划分比例一般用 8:1:1或者 7:2:1训练集多给一些。一个小脚本就能完成划分import random import shutil from pathlib import Path src Path(raw_data) # 创建训练/验证/测试输出目录 img_train Path(datasets/fall/images/train) img_val Path(datasets/fall/images/val) img_test Path(datasets/fall/images/test) lab_train Path(datasets/fall/labels/train) lab_val Path(datasets/fall/labels/val) lab_test Path(datasets/fall/labels/test) for d in [img_train, img_val, img_test, lab_train, lab_val, lab_test]: d.mkdir(parentsTrue, exist_okTrue) images list(src.glob(*.jpg)) list(src.glob(*.png)) # 固定随机种子保证每次划分一致 random.seed(42) random.shuffle(images) n len(images) train_split images[:int(n * 0.8)] val_split images[int(n * 0.8):int(n * 0.9)] test_split images[int(n * 0.9):] def move_imgs(imgs, img_dst, lab_dst): for img in imgs: lab src / (img.stem .txt) # 跳过没有标签的图片 if not lab.exists(): print(fskip {img.name}, label not found) continue shutil.copy(img, img_dst / img.name) shutil.copy(lab, lab_dst / (img.stem .txt)) move_imgs(train_split, img_train, lab_train) move_imgs(val_split, img_val, lab_val) move_imgs(test_split, img_test, lab_test)这段脚本先打乱图片列表再按比例切出三个集合复制时要求每个图片必须存在同名 txt否则直接跳过并把缺失信息打印出来。random.seed(42) 保证每次运行结果一致方便复现实验。实际使用中如果发现某些图片对应的标签文件是空文件也就是这张图里没有跌倒目标建议直接删掉而不是保留空标签否则训练时容易把空图当成背景影响 early stopping 的判断。提示不要按文件夹硬切。先把所有数据混在一起再划分可以避免同一个视频序列的连续帧同时出现在 train 和 val指标会虚高。2.3 data.yaml 的写法与类别顺序的坑在 datasets/fall 里放一个 data.yaml这是 yolov8 训练时唯一需要手动维护的配置文件path: /home/user/datasets/fall train: images/train val: images/val test: images/test nc: 1 names: 0: fallpath 建议写绝对路径或者保证运行 yolo 命令时当前路径和 path 相对路径能对上。train/val/test 是相对于 path 的路径。nc 是类别数跌倒检测一般只有一个类别写 1。names 是类别名列表索引顺序必须和标签里的 class id 完全一致。这里有一个很容易踩的坑如果你后面想加一个stand类别把 names 改成 0: stand、1: fall那么之前所有标签里 class id 为 0 的框全会变成 stand而不是原来的 fall。所以训练开始前就把标签里的 class id 和 names 定死中途不要加类别顺序。检查标签的脚本我每次都会跑一遍from pathlib import Path label_root Path(datasets/fall/labels) # 检查标签行数与坐标范围 for split in [train, val, test]: for p in (label_root / split).glob(*.txt): for line in p.read_text().splitlines(): parts line.split() if len(parts) ! 5: print(f{p}: {line}) continue try: cls int(parts[0]) vals [float(x) for x in parts[1:]] if cls 1 or not all(0 x 1 for x in vals): print(f{p}: {line}) except (ValueError, IndexError): print(f{p}: bad line)这段脚本找出三类问题行内数字不是 5 个、类别 id 超出 names 范围、坐标不在 0 到 1 之间。在第一次训练前把数据清洗干净比之后反复调参更省时间。如果源码包里已经有清洗过的数据集这一步可以缩到只跑检查脚本确认一遍。3. 配置yolov8训练环境并跑通跌倒检测模型的最小命令3.1 安装 ultralytics 和 PyTorch拿到源码包后先别急着读 train.py。yolov8 训练的入口是 ultralytics 库源码包里的 train.py 一般只是对这个库的再封装。安装这一步决定后面所有实验能否顺利跑起来我通常这样建环境conda create -n yolov8 python3.10 -y conda activate yolov8 pip install ultralytics如果机器上有 NVIDIA 显卡继续装对应 CUDA 版本的 PyTorch。这里以 CUDA 11.8 为例pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118之后再安装其他缺失依赖。验证环境是否正常可以跑一个最简单的命令python -c from ultralytics import YOLO; m YOLO(yolov8n.pt); print(ok)这个命令会加载 yolov8n.pt 预训练权重。首次运行如果本地没有权重库会尝试从官方地址下载离线环境里可以手动下载对应 .pt 文件放到当前目录再把 model 参数指向本地路径。不要用手里的跌倒检测源码包里的 best.pt 当预训练权重继续跑因为它是别人在别人的数据集上训出来的和你的 data.yaml 类别定义未必一致直接用可能直接报 class mismatch。提示GTX 1660 Ti 这种 6GB 显存显卡训练自建跌倒检测数据集完全够用。真正影响能否跑起来的是 batch 和 imgsz不是模型结构本身。3.2 先选 YOLOv8n 还是 YOLOv8s模型结构里YOLOv8 把特征提取部分换成了 C2f 模块相比 C3 浅层信息保留得更多所以在同样尺寸下精度和速度都有优势。但选择哪个尺寸模型还是看你的显存和落地目标。看网络结构图时会发现 C2f 出现在 backbone 的多个 stage它决定了特征图能保留多少小目标信息跌倒检测里人不是特别小的目标n 和 s 的差距没有想象中大。模型体积感受显存压力建议yolov8n最小很低2GB 也能跑快速验证、CPU 推理、边缘设备yolov8s中等6GB 可跑 batch 16毕业设计主力选择yolov8m较大建议 8GB 以上追求精度、服务器推理yolov8l大需要 12GB 以上离线分析不推荐给跌倒检测对跌倒检测来说目标和摄像头的距离决定了框的大小。室内监控场景框一般不会特别小用 n 或 s 就能达到不错的召回率m 的收益有限。我一般先用 s 跑一版作为基准如果显存不够再退回 n。源码包里的 train.py 如果默认是 l 或 x记得回来看一下这一节再改。3.3 第一次训练的命令和参数解释在 datasets/fall 平级目录下执行下面的命令# 从预训练权重迁移学习训练 100 轮 yolo detect train \ datadatasets/fall/data.yaml \ modelyolov8s.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ projectruns/fall \ nameexp1逐项说明data 指向上一步写好的 data.yamlmodel 填预训练权重路径库会加载 COCO 上训练过的权重做迁移学习epochs 是训练轮数跌倒检测小数据集跑 100 轮已经足够更多轮数配合早停才有意义imgsz 是输入图片分辨率640 是默认值框很小或样本不清时可以用 800batch 是每批图片数显存不够时优先从 16 降到 8 或 4device0 表示使用第一张 GPU没有 GPU 时改成 devicecpu但训练速度会慢很多project 和 name 决定结果输出到 runs/fall/exp1可以每次实验换一个 name 对比。训练结束后runs/fall/exp1/weights/ 下会生成 best.pt 和 last.pt。best.pt 是在验证集上指标最好的权重last.pt 是最后一轮权重。部署和后续验证都用 best.pt。如果训练过程报错先看是不是 data.yaml 路径写错再看类别数是否一致。源码包里如果自带 train.py也可以用 python train.py 代替 yolo 命令但最终透传的参数和上面一致。直接在命令行改参数比改脚本再跑更便于留痕推荐优先用 yolo 命令。这样换数据集重新训练时只需要复制并修改命令不会误改源码包里的逻辑。4. 用损失曲线和数据增强控制跌倒检测训练过程4.1 训练结果目录和损失曲线怎么读ultralytics 会自动生成 results.csv 和 results.png。results.png 里包含 train/box_loss, train/cls_loss, train/dfl_loss 以及对应的 val 曲线。很多初学者只看 mAP忽略了 loss。如果 train loss 一直下降但 val loss 在第 20 轮开始反弹这就是典型的过拟合信号此时继续加 epochs 只会让结果更差。YOLOv8 的 yolo detect train 在每轮结束时都会验证一次所以 results.csv 里已包含全部数据。用脚本重新画损失函数曲线图方便把实验组叠在一起看import pandas as pd import matplotlib.pyplot as plt # 读取训练日志并绘制 box_loss 曲线 df pd.read_csv(runs/fall/exp1/results.csv) df.columns [c.strip() for c in df.columns] plt.figure(figsize(10, 5)) plt.plot(df[epoch], df[train/box_loss], labeltrain box) plt.plot(df[epoch], df[val/box_loss], labelval box) plt.xlabel(epoch) plt.ylabel(box loss) plt.legend() plt.grid(True) plt.savefig(loss_curve.png)这里读取 results.csv 后用 strip 去掉列名里的空格再画 train 和 val 的 box_loss。box_loss 反映预测框和真实框的回归误差跌倒检测里如果这个值不降多半是标注框本身不干净或者目标太小。cls_loss 反映分类置信度在单类别场景下通常很低如果 cls_loss 波动大检查是不是类别 id 写错。4.2 数据增强参数怎么调yolov8 默认开启的数据增强已经很激进mosaic、随机翻转、HSV 扰动都开着。跌倒检测有自己的特殊性视频帧里人通常是竖直的fliplr 水平翻转可以用但 degrees 旋转角度不建议调太大因为跌倒的人很少出现横躺在画面里的极端角度旋转 30 度以上反而增加误检。参数默认跌倒检测建议说明degrees0.00~5旋转角度范围translate0.10.1平移比例scale0.50.3~0.5缩放比例太小容易丢失远距离人fliplr0.50.5水平翻转mosaic1.01.0 或 0.8拼图增强最后 10 轮建议关闭hsv_h / s / v0.015 / 0.7 / 0.4默认室内光照变化不大可降低mosaic 是 yolov8 训练跌倒检测时最需要关注的一个参数。默认 1.0 开启在训练后期因为四张图拼在一起框会被裁剪或压缩导致小目标的样本分布被改变收敛位置会偏移。常见做法是训练最后 10 轮把 mosaic 关掉让模型在接近真实分布的数据上收敛。用命令行参数直接覆盖即可# 在原有训练基础上继续跑 10 轮并关掉 mosaic yolo detect train \ datadatasets/fall/data.yaml \ modelruns/fall/exp1/weights/last.pt \ epochs110 \ imgsz640 \ batch16 \ close_mosaic10close_mosaic10 表示最后 10 轮自动关闭 mosaic。注意这里 modellast.pt 是接着上一轮训练继续跑如果你只是想从头调数据增强model 应该传回 yolov8s.pt。4.3 显存不足、过拟合和训练崩溃的调整顺序显存不足时调参优先级依次是把 batch 降到 8、把 imgsz 降到 480、把模型从 s 换到 n。注意 imgsz 降到 480 会让训练时间缩短但精度可能受影响最好用同一个 val 集合比较。过拟合时不要先调增强先看训练集和验证集是否来自同一个分布。跌倒检测常见的数据问题是验证集里混入了训练视频序列的邻近帧导致 val loss 很低而真实场景很差。确认数据没问题后再加 weight_decay0.0005、dropout0.1 这些正则化参数。yolov8 支持直接传 weight_decaydropout 在分类头部分生效。如果训练中途 loss 变成 nan一般不是参数问题而是数据里存在异常值。先跑一遍数据集检查脚本看看有没有坐标超大或者长宽为 0 的框。如果检查脚本没输出就检查 data.yaml 里的类别数和标签里的最大 class id 是否一致类别数写少了也会导致 loss 异常。4.4 验证集指标和混淆矩阵训练完成后单独跑一次验证避免被 last.pt 干扰# 用 best.pt 在验证集上重新评估 yolo detect val \ modelruns/fall/exp1/weights/best.pt \ datadatasets/fall/data.yaml \ splitval这个命令会输出 mAP50、mAP50-95、precision、recall并在 runs/fall/exp1 下生成混淆矩阵图。跌倒检测项目里mAP50 比 mAP50-95 更贴近实际需求因为报警系统对框的精确度要求没那么高IoU 在 0.5 就足够。如果 recall 远低于 precision说明标注框偏大或漏检多优先去补数据如果 precision 低而 recall 高则调高 conf 阈值。5. 跌倒检测模型部署导出ONNX、摄像头实时检测与连续帧判定5.1 用 ONNX Export 把 best.pt 转成部署格式训练完成后第一件事是用验证集确认 best.pt然后导出 ONNX# 导出为动态尺寸 ONNX 模型 yolo export \ modelruns/fall/exp1/weights/best.pt \ formatonnx \ opset12 \ dynamicTruedynamicTrue 允许输入图片宽高不固定方便后面接视频流。如果目标是 RK3588 这类 NPU 边缘设备需要先导出 ONNX再转成对应 runtime 格式如果只是 PC 上部署ONNX Runtime 就够了。导出的 onnx 文件可以和 ultralytics 的 YOLO 类直接配合使用。5.2 摄像头实时检测与连续帧判定跌倒检测和普通目标检测不一样的地方在于跌倒是一个过程单帧出现 fall 类别未必是真的跌倒可能是蹲下、弯腰或者只是姿态变化。更稳的判据是连续 N 帧里都有 fall 且置信度超过阈值同时框的高度方向发生明显变化。实际项目里我用的是滑窗投票from ultralytics import YOLO import cv2 model YOLO(runs/fall/exp1/weights/best.pt) cap cv2.VideoCapture(0) fall_count 0 ALARM_FRAMES 3 while cap.isOpened(): ret, frame cap.read() if not ret: break result model(frame, conf0.4, imgsz640, verboseFalse)[0] is_fall False for box in result.boxes: if result.names[int(box.cls)] fall: x1, y1, x2, y2 map(int, box.xyxy[0]) h y2 - y1 # 置信度和框高双重过滤减少蹲下误报 if box.conf 0.6 and h frame.shape[0] * 0.3: is_fall True cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), 2) break fall_count fall_count 1 if is_fall else 0 if fall_count ALARM_FRAMES: cv2.putText(frame, FALL DETECTED, (20, 60), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 0, 255), 3) cv2.imshow(fall, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()这段代码用 YOLO 类加载 best.pt对摄像头每帧做推理。conf0.4 是置信度阈值调低会增加召回但误检也变多框高超过画面高度 30% 和置信度超过 0.6 两个条件一起过滤能去除大部分蹲下和部分遮挡的误报。fall_count 做连续帧计数连续 3 帧命中才会触发报警避免单帧闪烁带来的误报。你可以把 ALARM_FRAMES 改成 5或者加入框面积变化率来判断跌落后的姿态是否稳定。如果摄像头实时推理帧率不够优先做两件事把 imgsz 从 640 降到 416把模型从 s 换成 n。这两个改动对帧率影响最直接精度牺牲在可接受范围。对于已经导出的 ONNX也可以换用 onnxruntime 的 Session 来跑但 ultralytics 的 YOLO 类对刚完成的毕业设计项目来说最省事。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价