
简介这份资源是面向深度学习入门与计算机视觉实践者的YOLOv5摔倒检测、跌倒识别完整项目包适合需要完成课程设计、毕业设计或安防场景算法验证的学生与开发者。包内共193个文件约40.29MB以jpg、jpeg图像样本和py源码为主辅以yaml、yml配置、pt权重、pyc缓存及Dockerfile、md说明等覆盖数据、训练配置与推理脚本下载后按文档配置环境即可运行。项目难度适中源码经过本地编译验证内容经助教审定能直接满足学习与使用需求。目前已有487人学习下载。读者可获得一套可复现的跌倒识别方案包括标注数据、模型配置、训练与检测代码以及OpenPose相关的jit模型文件便于快速跑通流程、理解YOLOv5在行为识别任务中的落地方式并在此基础上做二次开发与效果调优。1. 摔倒检测这件事为什么 YOLOv5 依然是性价比最高的起点如果你正在找yolov5 摔倒检测 跌倒识别项目源码全部数据大概率是三种人之一要交毕设的学生、要给养老院或工地做 Demo 的工程师、或者想拿一个完整数据集练手目标检测的转行者。这三种人的共同诉求其实很一致——要一套能跑起来、能复现、能改的完整方案而不是一篇讲注意力机制的论文。摔倒检测本质上是一个「人体姿态 时序判断」的问题但绝大多数落地项目最后都退化成了「目标检测 规则判断」。原因很现实姿态估计模型如 HRNet、MediaPipe在遮挡、侧躺、快速倒地这些场景下关键点抖动严重而 YOLOv5 直接检测person和fall两类框配合宽高比和框中心高度变化做二次判断鲁棒性反而更好部署也简单——树莓派 5 上跑量化后的 YOLOv5s 完全可行。这套方案适合谁适合想用最小成本跑通「数据集标注 → 训练 → 推理 → 报警逻辑」全链路的人。它不追求 SOTA 精度但能让你在两天内看到一个真实可用的跌倒识别 Demo。下面我按自己实际做过的顺序把选型、数据、训练、部署和踩坑一次讲清楚。2. 从标注到训练集摔倒数据集的构建与 YOLO 格式转换2.1 为什么摔倒检测的数据集比模型更决定成败先说一个血泪经验摔倒检测项目翻车90% 不是模型问题是数据问题。公开数据集里UR Fall Detection 只有几十段视频Le2i 场景单一真正能用的标注数据非常稀缺。所以「全部数据」这四个字在标题里出现说明这个项目的核心价值其实在数据集而不是那几百行训练代码。摔倒检测的数据有几个硬性要求缺一个模型就会学偏正负样本比例跌倒帧和正常行走帧的比例建议控制在 1:3 到 1:5。全是跌倒帧模型会把「弯腰捡东西」也判成跌倒。场景多样性至少覆盖室内地板、床边、卫生间、室外水泥地四类背景否则换个摄像头就废。姿态多样性前扑、后仰、侧倒、坐地滑倒都要有只标「躺在地上」的框模型学不会「正在倒」的中间状态。标注粒度建议只标person和fall两类。不要标standing、sitting那会让类别数膨胀且边界模糊。我一般会把数据组织成下面这个结构和 YOLOv5 官方要求完全对齐fall_dataset/ ├── images/ │ ├── train/ # 约 70% │ ├── val/ # 约 20% │ └── test/ # 约 10% ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yaml2.2 用脚本把 VOC/COCO 标注转成 YOLO txt很多现成数据集是 VOC 的 XML 格式YOLOv5 只认归一化的 txt。转换脚本我写过不下十遍下面这版是最稳的处理了边界框越界和空标注两个高频坑import os import xml.etree.ElementTree as ET from PIL import Image # 类别映射0person, 1fall CLASS_MAP {person: 0, fall: 1} def voc_to_yolo(xml_dir, img_dir, out_label_dir): os.makedirs(out_label_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, xml_file)) root tree.getroot() # 图片尺寸从实际图片读取不要信 XML 里的 size经常是错的 img_name root.find(filename).text img_path os.path.join(img_dir, img_name) w, h Image.open(img_path).size lines [] for obj in root.iter(object): cls_name obj.find(name).text.strip().lower() if cls_name not in CLASS_MAP: continue # 忽略未定义类别避免训练时报错 bbox obj.find(bndbox) x1 float(bbox.find(xmin).text) y1 float(bbox.find(ymin).text) x2 float(bbox.find(xmax).text) y2 float(bbox.find(ymax).text) # 裁剪到图像边界防止归一化后出现负数或 1 x1, y1 max(0, x1), max(0, y1) x2, y2 min(w, x2), min(h, y2) if x2 x1 or y2 y1: continue # 无效框直接丢弃 cx (x1 x2) / 2.0 / w cy (y1 y2) / 2.0 / h bw (x2 - x1) / w bh (y2 - y1) / h lines.append(f{CLASS_MAP[cls_name]} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) out_file os.path.join(out_label_dir, xml_file.replace(.xml, .txt)) with open(out_file, w) as f: f.write(\n.join(lines)) voc_to_yolo(annotations_xml, images_all, labels_all)逻辑说明CLASS_MAP决定类别顺序必须和data.yaml里的names完全一致否则训练不报错但推理全乱。图片尺寸从 PIL 实时读取而不是用 XML 里的size是因为很多标注工具导出的尺寸和实际图片对不上这是最常见的「训练 loss 不降」元凶之一。边界裁剪和无效框丢弃这两步能避免 YOLOv5 在 dataloader 阶段抛出negative width之类的报错。参数说明cx/cy/bw/bh全部归一化到 0~1保留 6 位小数足够。如果你的数据集里fall类特别少可以在转换后统计一下每类框数量再决定是否用--weights做类别加权。2.3 data.yaml 与训练集划分的三个必调项转换完标注data.yaml是训练入口写错一个字段就是几小时白跑path: /home/user/fall_dataset train: images/train val: images/val test: images/test nc: 2 names: [person, fall]必调项一path用绝对路径别用相对路径YOLOv5 在不同工作目录下启动时相对路径解析经常出玄学问题。必调项二nc必须等于names长度多一个少一个都会在加载时崩。必调项三训练集和验证集的图片文件名不能重名否则 YOLOv5 缓存机制会把标签张冠李戴这个坑我踩过一次排查了两小时。划分比例上如果总图片少于 2000 张建议 train:val:test 8:1:1验证集太小会导致mAP波动大看不出真实效果。划分时按「视频段」而不是「帧」来分同一段视频的帧不能同时出现在训练和验证集否则验证精度虚高这是时序数据划分的铁律。3. YOLOv5 训练摔倒检测模型环境、超参与收敛判断3.1 conda 环境配置与版本锁定yolov5环境配置是搜索量最高的长尾词之一因为版本不匹配的报错能劝退一半人。我一般用 conda 建独立环境锁死这几个版本conda create -n fall_yolo python3.8 -y conda activate fall_yolo # 先装 torch注意 CUDA 版本要和驱动匹配 pip install torch1.13.1 torchvision0.14.1 --index-url https://download.pytorch.org/whl/cu117 # 再装 yolov5 依赖不要直接 pip install -r 全量容易冲突 pip install numpy opencv-python pyyaml tqdm matplotlib pandas seaborn pip install ultralytics8.0.0 # 如果用官方仓库则 clone 后 pip install -e .逻辑说明Python 3.8 是 YOLOv5 兼容性最好的版本3.10 以上在部分torchvision算子上有兼容问题。torch 和 CUDA 必须匹配cu117对应驱动 515装错会报CUDA driver version is insufficient。不要一次性pip install -r requirements.txt里面有些包版本会互相顶按需装更稳。参数说明如果你只有 CPU把--device设为cpu但训练会慢 20 倍以上建议至少用一张 8G 显存的卡。树莓派 5 上只做推理不做训练。3.2 训练命令与超参数怎么改YOLOv5 的训练命令看着简单但每个参数都影响收敛python train.py \ --data data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --hyp data/hyps/hyp.scratch-low.yaml \ --device 0 \ --project runs/fall \ --name exp1逻辑说明--weights yolov5s.pt用预训练权重摔倒检测数据量小从头训几乎不可能收敛。--img 640是精度和速度的平衡点摔倒目标通常占画面 1/3 以上640 够用如果摄像头很远改 1280 但显存翻倍。--batch 16在 8G 显存下比较稳显存不够就降到 8 并加--accumulate 2模拟大 batch。超参数文件hyp.scratch-low.yaml适合小数据集如果数据超过 5000 张换成hyp.scratch-high.yaml。重点看三个值lr0初始学习率默认 0.01小数据集建议降到 0.001mosaic马赛克增强默认 1.0摔倒场景建议降到 0.5因为过度拼接会让「倒地」这种整体姿态被切碎fl_gamma是 focal loss类别不平衡时设 1.5 能明显提升fall类召回。3.3 怎么判断模型真的收敛了yolov5训练自己的数据集最让人焦虑的就是「loss 不降」和「mAP 不涨」。我的判断标准是三条第一看runs/fall/exp1/results.csvtrain/box_loss在前 10 个 epoch 应该明显下降如果平着走八成是标签路径错了或类别数不对。第二metrics/mAP_0.5在 50 epoch 后应该稳定在 0.85 以上摔倒检测这种二分类任务低于 0.7 说明数据质量有问题。第三看val/box_loss和train/box_loss的差距如果验证 loss 持续上升而训练 loss 下降就是过拟合加数据或加--dropout。一个反直觉的点摔倒检测不要盲目追求高 mAP。fall类的召回率比精度重要得多漏检一次跌倒的代价远大于误报一次。所以看指标时优先看metrics/recall必要时把置信度阈值从 0.25 降到 0.15宁可多报不可漏报。4. 推理、报警逻辑与树莓派 5 部署4.1 单帧检测到跌倒判定的规则层YOLOv5 只给你框判定「是否跌倒」需要自己写规则。我一般用「宽高比 框中心高度 连续帧」三条件import cv2 import numpy as np def is_fall(box, img_h, prev_centers, fall_counter): x1, y1, x2, y2 box w, h x2 - x1, y2 - y1 aspect w / max(h, 1) # 宽高比倒地时通常 1.2 center_y (y1 y2) / 2 / img_h # 归一化中心高度倒地时偏下 # 条件一宽高比异常 或 中心明显偏低 shape_flag aspect 1.2 or center_y 0.65 # 条件二连续 N 帧都满足避免单帧误判 if shape_flag: fall_counter 1 else: fall_counter max(0, fall_counter - 1) return fall_counter 5, fall_counter逻辑说明aspect 1.2捕捉横向倒地的框center_y 0.65捕捉画面下方的异常姿态。fall_counter是防抖计数器连续 5 帧满足才报警单帧抖动直接忽略。这个规则层比直接训一个时序模型简单得多实测误报率能压到可接受范围。参数说明1.2和0.65这两个阈值要按你的摄像头高度和视角调。摄像头装得高center_y阈值要调大装得低宽高比更可靠。建议先用测试集跑一遍画出aspect和center_y的分布直方图再定阈值。4.2 树莓派 5 上部署自己训练的 YOLOv5 模型树莓派5上部署自己训练的yolov5模型是最近的热词我实际跑过结论是能跑但必须量化。原始yolov5s.pt在树莓派 5 上单帧要 1.5 秒量化成 ONNX 再转 NCNN 后能到 200ms 左右。# 第一步导出 ONNX python export.py --weights runs/fall/exp1/weights/best.pt --include onnx --img 640 # 第二步ONNX 转 NCNN在 PC 上做树莓派算力不够 pip install onnxsim ncnn python -m onnxsim best.onnx best_sim.onnx # 用 ncnn 官方工具转换 onnx2ncnn best_sim.onnx best.param best.bin逻辑说明onnxsim先做图简化去掉冗余算子否则onnx2ncnn容易报不支持的操作。转换后在树莓派上用ncnn的 Python 绑定推理输入尺寸保持 640预处理用cv2.dnn.blobFromImage保持一致。参数说明树莓派 5 建议开--img 320做推理速度能再快一倍精度掉 3~5 个点摔倒检测够用。如果要用摄像头实时用picamera2库抓帧别用cv2.VideoCapture后者在树莓派上延迟高。4.3 报警联动与误报抑制检测到跌倒后报警方式决定项目能不能落地。我一般做三级本地蜂鸣器、MQTT 推送到网关、截图存证。误报抑制除了前面的连续帧计数再加一个「静止判定」——如果框在 3 秒内位置几乎不变且宽高比异常才最终确认这能过滤掉「蹲下系鞋带」这类动作。MQTT 推送用paho-mqtt消息体带上时间戳和置信度方便后端做二次确认。截图存证按日期/小时分目录避免单目录文件过多导致树莓派 IO 卡顿。5. 摔倒检测项目避坑清单5 个我真实踩过的坑5.1 坑一训练 loss 正常但推理全是 person现象训练时mAP看着有 0.8推理时所有框都标成personfall类一个都不出。原因data.yaml里names顺序和标注转换时的CLASS_MAP不一致模型学到的类别索引错位。解决转换脚本和data.yaml用同一个常量文件定义类别别手写两遍。5.2 坑二验证集精度虚高换场景就崩现象验证集mAP0.95拿到新摄像头上一测正常走路也报警。原因训练集和验证集按帧随机划分同一段视频的相邻帧同时进了两边模型等于「背答案」。解决按视频段划分同一段视频的所有帧只进一个集合。5.3 坑三树莓派上 ONNX 推理结果和 PC 不一致现象PC 上检测正常树莓派上框位置偏移或置信度全乱。原因预处理不一致PC 用了 letterbox 填充树莓派直接 resize 变形。解决两端统一用 YOLOv5 的letterbox函数保持长宽比填充灰边推理后再把框映射回原图坐标。5.4 坑四fall 类召回率低漏检严重现象跌倒动作快模型经常漏掉中间帧。原因fall类样本少且集中在倒地后的静止帧缺少「正在倒」的过渡帧。解决在标注时把倒地过程中的 3~5 帧也标成fall并降低推理置信度阈值到 0.15配合连续帧计数。5.5 坑五长时间运行内存泄漏现象树莓派跑几小时后卡死。原因每帧都新建cv2.Mat和推理 sessionPython GC 跟不上。解决推理 session 全局初始化一次帧缓冲复用每 1000 帧手动gc.collect()并限制截图存证的分辨率。6. 把摔倒检测做到能交付一个提升召回率的采样技巧最后一章讲一个我实际交付时用的技巧难例回采 类别重加权。摔倒检测的瓶颈从来不是模型结构而是fall类样本太少、太相似。我的做法是第一轮训练完不急着调参而是拿模型在验证集和一段真实场景视频上跑推理把所有「漏检的跌倒帧」和「误报的正常帧」单独抽出来人工复核后加进训练集再跑第二轮。具体操作上用下面的脚本把漏检帧自动导出# 用第一轮模型跑推理保存漏检帧 import torch model torch.hub.load(ultralytics/yolov5, custom, pathruns/fall/exp1/weights/best.pt) for frame in video_frames: results model(frame) preds results.pandas().xyxy[0] # 如果该帧有 fall 标注但模型没检出存为难例 if has_fall_gt(frame) and not any(preds[name] fall): cv2.imwrite(fhard_examples/{frame_id}.jpg, frame)逻辑说明has_fall_gt是你自己的标注比对函数判断这一帧是否真的有人跌倒。把漏检帧存下来后重新标注并加入训练集第二轮训练时把fall类的损失权重调高YOLOv5 里可以通过复制fall类样本来近似实现。参数说明难例回采一般做 2~3 轮就够了再多容易过拟合到特定场景。每轮回采后重新划分验证集确保验证集里也有难例否则指标还是虚的。我自己的习惯是任何摔倒检测项目在交付前必须在一段「没参与训练的真实视频」上跑满 24 小时统计误报次数和漏报次数。误报超过 5 次/天就回去加负样本漏报超过 1 次就降阈值加难例。这个笨办法比任何花哨的注意力模块都管用。希望帮到你。本文还有配套的精品资源点击获取