YOLOv8训练跌倒检测模型全流程指南:从数据集到部署
简介这套基于YOLOv8的跌倒检测完整毕业设计资源面向计算机视觉方向学生及需要快速落地目标检测项目的开发者。资源包含带标注的跌倒/非跌倒图像数据集、完整训练与评估源码、预训练模型文件及说明文档能够帮助使用者从数据准备到模型部署全流程复现跌倒检测方案适用于老年人监护、室内安防等场景。压缩包共1437个文件其中1428张jpg图像构成训练与验证数据6个py脚本覆盖数据加载、模型训练与推理流程另含1个pt权重、1个onnx导出模型及1个md说明文档整体大小78.41MB结构清晰便于按需检索。目前已有93人浏览学习。通过该资源可掌握YOLOv8的数据集组织方式、训练参数配置、模型评估与导出方法还能参考其工程代码风格完成毕业设计文档与模块划分是一份兼顾算法理解与工程实践的宝贵资料。1. 跌倒检测模型为什么值得自己训练YOLOv8 不是拿来即用的黑匣子老人跌倒检测这几年从论文走向了社区和养老院可真正落地时你会发现拿通用目标检测模型直接去识别“倒地的人”根本不行。人体姿态、卧姿、遮挡、轮椅、地毯花纹这些干扰会把误报率抬到没法用的程度。而基于 YOLOv8 训练一个自己的跌倒检测模型好处是能完全控制数据来源、标注口径和部署形态最后产出一个几百 MB 的 .pt 权重转成 ONNX 或 rknn 就能塞进边缘盒子。这篇笔记适合手里已经有一批图片、想从零跑通训练闭环的开发者也适合做毕设选题的同学照着复现。我按“数据集怎么做 → 环境怎么搭 → 训练怎么调 → 踩了哪些坑 → 部署前怎么验”的顺序把一套能出结果的路径完整讲清楚。2. 训练跌倒检测前的数据集准备标注格式、类别平衡与划分策略2.1 跌倒检测数据集应该长什么样从图片收集到统一成 YOLO 格式自己训练的第一步不是装环境而是把数据集整理成 YOLOv8 直接能读的格式。YOLOv8 训练自己的数据集要求图片和标注文件同目录或分目录存放标注文件是 .txt每行一个目标格式为class x_center y_center width height四个坐标值都是相对图片宽高的归一化小数。跌倒检测一般只做单类目标类别名就叫fall但如果你想把“站立”“行走”“跌倒”都识别出来那就定义三个类。常见做法是用 LabelImg 或 Labelme 标注。LabelImg 输出的是 PASCAL VOC 的 XMLLabelme 输出的是 JSON。我先说 LabelImg 这种更省事的路径标注完拿到 XML 后写个脚本把 XML 转成 YOLO 格式。下面这段脚本是我常用的转换逻辑放在数据集根目录下执行import xml.etree.ElementTree as ET import os from pathlib import Path def convert_xml_to_yolo(xml_path, out_dir, classes): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) out_lines [] for obj in root.findall(object): cls obj.find(name).text if cls not in classes: continue box obj.find(bndbox) xmin int(box.find(xmin).text) ymin int(box.find(ymin).text) xmax int(box.find(xmax).text) ymax int(box.find(ymax).text) x_center ((xmin xmax) / 2) / img_w y_center ((ymin ymax) / 2) / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h out_lines.append(f{classes.index(cls)} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) txt_path Path(out_dir) / (Path(xml_path).stem .txt) txt_path.write_text(\n.join(out_lines), encodingutf-8) classes [fall] # 按你标注时的类别顺序写 xml_dir annotations out_dir labels os.makedirs(out_dir, exist_okTrue) for xml_file in Path(xml_dir).glob(*.xml): convert_xml_to_yolo(str(xml_file), out_dir, classes)逻辑说明脚本先读 XML 里的图片宽高和每个目标的左上、右下坐标再换算成归一化的中心点坐标和宽高。需要注意classes列表的顺序必须和训练时的data.yaml保持一致否则类别会错位。参数说明里最容易被忽略的就是坐标系YOLO 格式不接受像素绝对坐标归一化时把 xmin、ymax 除以宽高即可不要乘回去。2.2 跌倒样本太少怎么办数据增强与负样本策略跌倒检测的训练集难点在于正样本稀缺网上公开的跌倒数据集要么数量少、要么场景单一。我的做法是三类数据混着来第一类是公开的跌倒检测图片集数量不够就做增强第二类是从视频里抽帧把连续跌倒动作每隔 2 到 3 帧截一张能凑出上千张第三类是负样本也就是大量正常坐、蹲、躺、弯腰捡东西的图片这些能让模型学会区分“跌倒”和“主动躺下”。增强不能无脑用 YOLOv8 自带的 mosaic因为 mosaic 会把多张图拼一起跌倒目标在拼接后可能被切掉一半。我一般只开轻微的水平翻转、缩放和亮度变化。另外非常关键的一点是类别不平衡跌倒样本数和其他干扰样本数最好控制在 1:1 到 1:3 之间太少模型会学不到跌倒特征太多误报飙升。你可以在data.yaml里直接写训练集和验证集路径然后跑通一次训练看看 loss 曲线的走势这点后面会展开。2.3 制作 VOC 与 YOLO 的目录对照images、labels 与 data.yaml 的最小约定YOLOv8 的data.yaml不需要像老版本那样建 JPEGImages、Annotations 一堆目录最小约定是这样path: ./ train: images/train val: images/val names: 0: fallpath是数据集根目录的相对或绝对路径train和val指向存放图片的目录。注意 YOLOv8 会默认在同级目录下找labels目录所以如果你的图片在images/train标注文件必须放在labels/train图片和标注的文件名要一致否则训练时会警告 “WARNING no labels found”。这个目录结构是我踩过最多坑的地方——很多人把标注文件跟图片混在一起训练直接跑不起来。有一个验证命令我建议在训练前一定先执行python -c from ultralytics import YOLO; YOLO(yolov8n.pt).val(datadata.yaml, splitval, imgsz640)逻辑说明这行命令不是为了真的验证精度而是让 Ultralytics 加载你的数据集配置如果目录结构或标注文件有问题它会在报错信息里指出具体缺了什么。参数splitval指定用验证集做评估imgsz640是推理时缩放尺寸。如果数据集正常输出里会出现all这一行的 mAP 指标如果输出里有0 labels之类的提示说明标注对不上回去检查目录结构。3. Ubuntu 20.04 搭建 YOLOv8 环境并跑通跌倒检测训练从 CPU 到 GPU 的选择3.1 环境搭建的最小步骤conda 创建环境与安装 ultralytics对于 Ubuntu 20.04搭建 YOLOv8 环境最好别直接用系统 Python我通常用 conda 隔离。下面是最小安装命令conda create -n fall python3.8 -y conda activate fall pip install ultralytics逻辑说明ultralytics这个包已经包含了 YOLO 模型定义、训练器和推理接口不需要再单独装 darknet 或 mmdetection。Python 3.8 在 Ubuntu 20.04 下兼容性最好torch 和 torchvision 都能找到对应 wheel。如果你只是 CPU 版本那么到这里其实已经能跑了只是速度慢你希望用 GPU 加速就继续装pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118注意这个命令假设你的机器是 NVIDIA 显卡且驱动已装好。参数说明里有个细节cu118对应 CUDA 11.8如果你的显卡较新建议装cu121或更新版本。装完可以用python -c import torch; print(torch.cuda.is_available())验证。必须说清楚CPU 版本不是不能用只是训练一个小数据集几百张图同样 100 轮要跑两三个小时GPU 可能十分钟就完事。3.2 用 GPU 训练跌倒检测模型命令行参数逐项拆解环境装好后训练命令并不复杂但参数含义必须吃透。我一般这样启动训练yolo detect train modelyolov8n.pt datadata.yaml epochs120 imgsz640 batch16 device0 patience20逻辑说明modelyolov8n.pt是预训练权重n是 nano 版本参数量最小适合跌倒检测这种相对简单的单类任务。epochs120是训练轮数imgsz640是输入图片尺寸batch16是批大小device0指定第一张 GPUpatience20是早停耐心值如果连续 20 轮验证集指标没提升就自动停止。参数说明里最容易翻车的是batch和显存的关系。跌倒检测图片通常 1080p 分辨率缩放到 640 后单张占用约 6GB 显存batch16 时需要如果你的显卡只有 8GB建议改成batch8。epochs不是越多越好跌倒检测数据集小120 轮足够再加就容易过拟合表现为训练 loss 降了、验证 mAP 反而掉。3.3 画损失函数曲线图训练日志里的 box_loss、cls_loss 与 dfl_lossYOLOv8 训练过程中的输出日志包含box_loss边界框回归损失、cls_loss分类损失、dfl_loss分布焦点损失还有验证集上的对应指标。训练结束后Ultralytics 会在runs/detect/train目录下生成results.png这张图天然就是损失函数曲线图。不过很多人想自己画更细的曲线用训练日志里的 CSV 是更好的方式。打开runs/detect/train/results.csv里面每一行对应一轮列有epoch, train/box_loss, train/cls_loss, train/dfl_loss, metrics/precision, metrics/recall, metrics/mAP50(B), val/box_loss等。用 pandas 直接读取并画图import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/detect/train/results.csv) fig, ax plt.subplots(1, 2, figsize(12, 4)) ax[0].plot(df[epoch], df[train/cls_loss], labeltrain_cls) ax[0].plot(df[epoch], df[val/cls_loss], labelval_cls) ax[0].set_title(Classification Loss) ax[0].legend() ax[1].plot(df[epoch], df[train/box_loss], labeltrain_box) ax[1].plot(df[epoch], df[val/box_loss], labelval_box) ax[1].set_title(Box Loss) ax[1].legend() plt.tight_layout() plt.savefig(loss_curve.png)逻辑说明这个脚本把原版results.csv里的两列连续画出来方便观察训练是否收敛。关键看两个点训练 loss 持续下降而验证 loss 上升说明过拟合验证 loss 在 60 轮后进入平台期说明模型差不多到头了。参数说明里train/cls_loss和val/cls_loss列名前半部分是分组后半部分是指标不同版本列名可能带(B)或(M)后缀画图前先打印df.columns确认。4. 把 YOLOv8 跌倒检测模型的精度提上去锚框、预训练权重与数据清洗三个关键点4.1 用 yolov8s 还是 yolov8n单类检测任务的选型逻辑YOLOv8 提供 n/s/m/l/x 五个尺寸跌倒检测这种单类任务不需要追求极致精度因为类间差异很大——人倒在地上和站着走路的视觉特征足够明显。我通常先拿yolov8n跑通流程确认数据集没问题后再切yolov8s做最终训练。yolov8s的参数量大约是 nano 的三倍但推理速度在边缘设备上还能接受。如果你的部署平台是 RK3588 这类 NPUnano 版本往往更友好因为量化后的精度损失更小。选型时要看你的数据规模。500 张图用yolov8s很容易过拟合1000 张以上才建议从 s 起步。m/l 版本对跌倒检测来说收益很小还拖慢训练速度不建议新手一上来就尝试。4.2 训练参数再调优从 data.yaml 到默认超参数的改动清单Ultralytics 默认的超参面向 COCO 这种多类别通用场景跌倒检测需要改几个值。第一个是lr0默认 0.01小数据集建议降到 0.005否则前期震荡太剧烈。第二个是mosaic老版本默认 1.0新版本在augment模型参数里控制跌倒检测建议设成 0.5 或 0.0。第三个是close_mosaic数据不足时不要用它的默认 10可以设成 5。修改超参有两种方式命令行直接传参例如lr00.005 mosaic0.5或者改模型配置文件。我更推荐命令行传参因为每轮实验的参数都留在训练日志里方便对比。下面是我针对跌倒检测调过的一版参考命令yolo detect train modelyolov8n.pt datadata.yaml epochs120 imgsz640 batch16 lr00.005 mosaic0.5 close_mosaic5 patience30逻辑说明mosaic0.5表示每批样本中 50% 使用马赛克增强剩下一半保持原始图。参数说明里close_mosaic是最后 5 轮关闭马赛克这样能让模型适应正常宽高比的目标。如果你不设置这两个参数模型会把跌倒的人拼成奇怪形状验证时遇到完整人体反而检测不到。4.3 识别率低先别调参先检查标注框是否贴合人体训练出来的模型 recall 低最常见的原因是标注框太紧或太松。跌倒检测里人倒地后身体呈对角线标注框如果只包住上半身模型学到的特征就不完整。我的经验是标注框要包含整个人体轮廓哪怕把边缘留出 5% 的余量也不要切掉四肢。你可以用可视化工具把标注框画在图片上检查代码非常简单import cv2 from pathlib import Path img cv2.imread(images/train/001.jpg) h, w img.shape[:2] label_path Path(labels/train/001.txt) for line in label_path.read_text().strip().splitlines(): cls, xc, yc, bw, bh map(float, line.split()) x1 int((xc - bw / 2) * w) y1 int((yc - bh / 2) * h) x2 int((xc bw / 2) * w) y2 int((yc bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imwrite(check_001.jpg, img)逻辑说明这个脚本把 YOLO 格式的标注框还原成像素坐标画在图上用于抽检标注质量。参数说明里xc, yc是中心点坐标bw, bh是宽高比例换算回像素时必须要乘以图片宽高很多人写脚本时忘记这一步画的框全部偏到左上角。抽检 20 张如果超过 5 张框没贴合就回去重新标注这比调任何参数都管用。5. YOLOv8 跌倒检测训练高频踩坑环境、数据与显存问题的排查记录5.1 训练时提示 CUDA out of memory但换小 batch 还是崩现象yolo detect train启动后没跑几步就报CUDA out of memory把 batch 改成 2 仍然崩溃。原因是 YOLOv8 默认开启缓存图片到显存cacheTrue小数据集整图缓存会额外占用几个 GB。解决方法是关闭缓存并限制 worker 数yolo detect train modelyolov8n.pt datadata.yaml batch8 cacheFalse workers2这样cache参数设为False后每轮从磁盘读图虽然慢一点但显存占用骤降。如果还是崩检查你是不是同时开了多个进程或终端占用显存用nvidia-smi看一下。5.2 WARNING no labels found 循环提示但标注文件明明存在现象训练日志里不断出现WARNING no labels found in labels/train打开目录发现.txt文件都在。原因是文件名不一致图片是001.jpg标注是001.txt看起来没问题但如果标注文件是从 XML 转换时带了额外后缀比如001.xml.txt就会匹配不上。另外检查data.yaml最后是否有空行或隐藏字符我遇到过一次从 Windows 复制过来的data.yaml里路径带\r导致读取失败。解决方法是统一重命名标注文件再执行一遍我前面给过的验证命令。5.3 模型训练完检测不到跌倒但训练时 mAP 很高现象验证集 mAP0.5 到 0.95看起来不错拿到现场视频里一测跌倒的人完全检测不到。这通常不是模型问题而是数据分布偏差——训练集里的跌倒图片多为正面视角、光线均匀现场是俯拍或侧视模型没见过。解决方法是补充多视角数据尤其要加俯视 45 度角、夜间红外、昏暗走廊场景。如果现场只有枪机固定视角最好单独收集该视角的 100 张跌倒图做微调而不是指望通用权重泛化。5.4 跌倒检测把坐下、蹲下也报成跌倒现象误报集中在老人弯腰系鞋带、坐在矮凳上起身这几类动作。原因在于“跌倒”和“低位姿态”在单帧图像上真的很难区分——人躺在地上和蹲下时检测框的宽高比都大于 1。解决思路有两个第一个训练时加入大量干扰负样本明确标注为normal让模型学习区分第二个在推理端加后处理逻辑用连续帧的位移和速度判断只有目标在短时间内从站立高度变为倒地高度才算跌倒。后处理不是 YOLOv8 自带能力需要自己写几行规则或接入跟踪器。5.5 CPU 训练慢得无法忍受但只有 CPU 可用现象Ubuntu 20.04 上搭好 CPU 版本环境训练 120 轮耗时 8 小时。解决方法是降低输入尺寸和轮数imgsz416epochs60配合workers0。另外可以先用modelyolov8n.pt冻结前 10 层做迁移学习。如果做毕设只需要一个能跑的模型CPU 训练小数据集完全可行不必为了加速去租 GPU。我建议你先跑通几轮epochs5确认数据加载、损失计算正常后再挂机跑完整训练。6. 训练完成后的验证与部署前检查用验证集指标和实际视频把模型逼到极限6.1 用混淆矩阵和 PR 曲线判断模型是否值得用Ultralytics 训练结束后会在runs/detect/train下生成confusion_matrix.png和PR_curve.png。打开混淆矩阵重点关注fall类的假正例和假负例。如果假正例集中出现在背景或normal类说明负样本不够如果假负例多说明姿态多样性不足。PR 曲线的曲线下面积如果大于 0.9模型基本可用0.8 左右就得考虑回炉。没有这两张图也能通过输出日志里的metrics/precision(B)和metrics/recall(B)判断但图能告诉你到底是哪一类出错。6.2 视频推理测试的固定脚本检测置信度与帧率的作用不要只拿图片测跌倒检测最终面对的是视频流。一个用于验证的视频推理脚本要能控制置信度、显示帧率并统计连续检测结果。下面是我常用的测试脚本import cv2 from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) cap cv2.VideoCapture(test_fall.mp4) conf 0.35 while cap.isOpened(): ret, frame cap.read() if not ret: break results model(frame, confconf, imgsz640, verboseFalse)[0] annotated results.plot() fps cap.get(cv2.CAP_PROP_FPS) cv2.putText(annotated, f{fps:.1f} FPS, (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) cv2.imshow(fall test, annotated) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()逻辑说明这个脚本用model(frame, confconf)对每一帧做推理conf0.35是置信度阈值。results.plot()把检测框画到原图上。参数说明里conf的取值直接决定误报率——跌倒检测建议先跑一遍统计 mAP50 对应的置信度阈值通常 0.25 到 0.5 之间选择。现场误报严重时调高到 0.6但如果召回率明显下降就退回 0.4 并靠后处理过滤。6.3 导出 ONNX 与 RKNN 时的精度验证技巧训练完的.pt文件不能直接部署到大多数嵌入式设备转 ONNX 是标准动作。用 YOLOv8 自带导出命令转换yolo export modelruns/detect/train/weights/best.pt formatonnx imgsz640转换后一定要对比 PyTorch 模型和 ONNX 的推理结果是否一致用同样的图片分别跑model.predict和onnxruntime推理比较检测框坐标和置信度差异。差异超过 2% 通常是因为你用了动态尺寸导出建议固定imgsz640。如果是 RK3588 这类 NPUONNX 还要转成 RKNN转换过程里量化校准集最好从训练集里随机抽 100 张不要用验证集否则精度会被高估。我自己的习惯是最终验收模型时不只看 mAP而是拿一段 5 分钟的真实监控视频里面包含 3 次跌倒和 5 次弯腰、蹲下动作然后数模型框出多少次。只要这个测试通过项目才算真正落地。这些验证步骤做下来你才会知道 YOLOv8 跌倒检测模型原来比想象中更需要场景适配而不是训练完就万事大吉。希望这些经验帮到你至少让你少走我当初走过的弯路。本文还有配套的精品资源点击获取