拓冰建站拓冰建站
首页 / 资讯中心 / 正文

基于YOLOv8-Pose的实时跌倒检测系统设计与实现

1. 项目概述为什么我要做老人跌倒检测先从一次真实经历说起。家里长辈去年在卫生间滑倒人躺在地上将近两个小时才被发现。幸好没造成严重后果但这件事让我开始认真琢磨能不能用摄像头加AI在老人跌倒的瞬间就发出告警而不是等几个小时后才发现市面上其实有穿戴式跌倒报警器但实际使用中问题很多——老人记不住充电、觉得戴手环不舒服、洗澡时摘下来就失去保护。而基于视觉的AI跌倒检测不需要老人做任何额外动作摄像头装好之后保护是全天候无感的。这恰恰是它最大的价值。这个项目做的是基于 YOLOv8-Pose 的实时跌倒检测系统。简单说就是让AI通过摄像头画面识别人体骨骼关键点眼睛、肩膀、手肘、髋部、膝盖、脚踝共17个点再根据这些点的空间位置关系判断一个人到底是站着、坐着、走路还是已经摔倒在地一旦判定跌倒就立刻推送告警。核心用途是居家养老、社区养老机构、医院病房、独居老人住所等场景同时兼容实时视频流和本地视频文件两种处理模式也为低功耗端侧AI视觉模块的移植预留了接口。如果你正在考虑给家里老人装一套跌倒检测或者你是做智能养老产品开发、算法落地部署的工程师这篇内容会把整条技术路线讲清楚从模型选型、数据标注、算法逻辑到实际部署踩坑全部覆盖。2. 方案选型为什么是 YOLOv8-Pose而不是别的主流方案2.1 三种主流跌倒检测路线的横向对比做视觉跌倒检测绕不开三个方向传统图像处理方案、基于检测框的方案、基于人体姿态估计的方案。我逐一说明它们的特点和适用场景。传统图像处理方法是最早的方案典型做法是背景差分加人体轮廓分析。摄像头固定不动先建立纯背景模型人进入画面后通过帧差法把人体前景提取出来再算轮廓的外接矩形宽高比、人体质心高度变化率等特征来判断跌倒。这类方案实现简单在老设备上也能跑但缺陷非常致命——极度依赖摄像头静止稍微有点树叶晃动、光照突变就会误报而且对画面中同时出现多个人和多类物体时基本束手无策。基于检测框的方案比较常见用 YOLO 系列这类目标检测模型框出人的位置然后跟踪人体框的宽高比和中心点坐标变化。人在正常站立时框通常是高大于宽跌倒躺下时会变成宽大于高再配合中心点下降速度做判断。这个方法实现难度低、速度快但一个明显短板是人体框的形状变化受姿态影响太大——老人弯腰捡东西、蹲下系鞋带检测框宽高比也会剧烈变化很容易误报。基于人体姿态估计的方案也就是本项目采用的路线。它不光告诉你人在哪还告诉你人的手在哪、脚在哪、髋在哪。通过 YOLOv8-Pose 输出的17个骨骼关键点我们能算出头与髋部连线的倾斜角度、两个髋关节中心点的高度、躯干与地面的夹角、关键点位移速度等一整套精细特征。有了这些骨骼级别的信息对弯腰和跌倒的区分能力就完全不一样——弯腰时躯干角度虽然变化但髋关节高度不会骤降而真正的跌倒伴随着髋关节中心点快速下坠这两个物理特征叠加起来判断准确率能显著提升。2.2 YOLOv8-Pose 自身的技术优势YOLOv8-Pose 是 Ultralytics 在 YOLOv8 目标检测框架上扩展出的姿态估计版本。它继承了 YOLOv8 的 C2f 特征提取结构跨阶段部分连接的新改进版和 anchor-free 检测头同时增加了专门用于关键点回归的分支。相比前代 YOLOv5-Pose 等方案它的骨干网络和损失函数设计都有更新轻量版本的 mAP 更高训练和部署也更简单。具体到我的使用体验YOLOv8-Pose 有几个非常实用的工程特性。一是模型体积和推理速度的弹性。它有 n/s/m/l/x 五个规格n 版本权重只有约 6MB在 CPU 上跑一帧也就几十毫秒而 x 版本精度更高适合有 GPU 的服务器端。我最终在边缘设备上用的是 s 版本的 int8 量化模型精度损失可控速度几乎翻倍。二是关键点输出格式统一。YOLOv8-Pose 输出的关键点坐标已经归一化到 0~1不管输入图像是 640x640 还是 1280x1280输出的坐标都直接能用省去了手动换算的步骤。这个细节在做后处理时特别省心。三是和同生态工具链的配合顺畅。Ultralytics 提供训练、验证、导出一步到位的API模型可以直接导出为 ONNX、TensorRT、OpenVINO 等格式部署路径非常短。对于我这种既要快速验证算法又要落地到边缘设备的场景这套工具链省下了大量时间。2.3 为什么没有直接用电网之外的穿戴方案可能有人会问现在很多智能手表、手环也有跌倒检测功能为什么还要做视觉方案我整理过一个对比两者在实际使用中的体验差异非常大。穿戴设备最大的问题是佩戴依从性。老年人普遍存在嫌麻烦怕戴出去不好看忘充电的情况我调研时甚至遇到过老人为了让手环多管几天故意不戴、只在出门时戴的例子。而设备不戴在身上再好的算法也是零。视觉方案完全不需要老人配合只要摄像头覆盖老人活动区域保护就是持续的。穿戴设备另一个问题是跌倒判定的延迟感。部分手环依赖加速度计和陀螺仪的突变信号算法上需要多个条件同时满足才报警有时会出现跌倒后十几秒甚至更久才响铃或者剧烈甩手、从床上坐起等动作引发误报。视觉方案通过捕捉完整的跌倒轨迹来判定比如躯干倾角快速增大、髋部高度快速下坠这两个关键特征同时触发判断更贴合真实的跌倒物理过程。当然穿戴设备和视觉方案并非互斥在实际养老项目中两者结合使用效果最好。视觉负责固定区域的全天候监控穿戴设备作为离开监控区域后的补充。3. 跌倒检测的算法核心如何从骨骼关键点判断摔倒了3.1 17个关键点的含义与坐标系约定要理解跌倒判断逻辑先得知道 YOLOv8-Pose 输出的到底是什么。模型每检测到一个人会输出 17 个关键点依次对应鼻子、左眼、右眼、左耳、右耳、左肩、右肩、左肘、右肘、左腕、右腕、左髋、右髋、左膝、右膝、左踝、右踝。每个关键点的输出内容包括像素坐标x、像素坐标y以及置信度conf。在实际做跌倒分析时不需要全部17个点我重点关注的是一组核心点左右肩膀的中点用来代表躯干上部、左右髋部的中心点代表身体重心所在区域高度、左右膝盖和脚踝辅助判断腿的状态。这些点在正常站姿和躺卧姿态下的相对位置差异极大非常适合作为跌倒判别的输入特征。坐标体系沿用图像处理的标准约定——原点在左上角x轴向右y轴向下。这意味着画面中越往下的位置y坐标数值越大。很多初学者在这里容易搞混比如判断人倒地了要看关键点是否位于画面底部区域别把y轴的增减方向弄反。3.2 三个核心特征的计算方法我最终采用的跌倒判定模型建立在三个量化的特征上。第一个特征是躯干倾角。先取左右肩中点坐标为 shoulder_center左右髋中点坐标为 hip_center然后计算过这两个点的直线与图像水平面的夹角。计算方式如下设两点坐标差为 dx hip_center_x - shoulder_center_xdy hip_center_y - shoulder_center_y角度为 angle atan2(dy, dx) * 180 / PI。当人直立时肩髋连线几乎是垂直的如果以水平方向为0度这个角度约在 65~90 度之间人完全躺平时角度会降到 20 度以下。利用这个特征能很好地区分站姿和卧姿。第二个特征是髋部中心点的相对高度变化。髋部是人体重心的近似位置正常站立时髋部高度约占画面中人体框高度的 45%~55%跌倒在地后髋部关键点会大幅下移。我采用的计算方法是用髋部中心点y坐标除以整个人体检测框的高度得到一个归一化比例系数。站立时这个系数较小倒地时明显增大。用归一化比例而不是绝对像素高度能避免摄像头安装高度不同带来的尺度差异。第三个特征是髋部中心点的垂直速度。跌倒过程在时间上表现为快速下坠这个物理特征比单帧的姿态变化更可靠。我通过连续帧之间髋部中心点y坐标的变化量除以时间间隔来计算速度单位可换算为像素每秒。弯腰捡东西时髋部虽然也会下降但速度远低于真正的跌倒。三个特征并非简单叠加判定而是有一个状态流转的逻辑——先靠姿态特征确认当前状态站立、弯腰、倒地再靠运动速度特征确认是否存在眨眼间从站立变为倒地的过程两者配合才能把误报降到最低。3.3 判定阈值怎么定才合理阈值是整个系统中需要反复调试的部分。我最初使用固定阈值躯干倾角低于 25 度、髋部相对高度大于 0.55、髋部垂直速度大于每秒 0.3 倍人体框高度三者同时满足即判定跌倒。测试下来发现弯腰系鞋带时倾角会短暂小于 25 度髋部相对高度也接近 0.5速度却不达标——速度特征把这类误报拦截了。但坐在椅子上打盹导致身体歪斜时三个特征又可能同时触发需要增加处于地面区域持续时间超过 0.5 秒的条件进行二次确认。我后来优化的策略是调整阈值区间倾角小于 30 度触发疑似跌倒状态髋部高度和速度条件同时满足且持续 0.5 秒以上才确认为跌倒告警。这套「两阶段确认」逻辑把误报率下降了一半以上。阈值的具体数值受摄像头安装高度和角度影响很大没有一劳永逸的万能值后面我会专门讲怎么针对自己的场景做校准。4. 实操过程从数据准备到系统部署的完整实现4.1 数据来源与标注方案跌倒检测的深度学习模型需要使用带人体关键点标注的数据集进行训练。这里要说明一个关键问题YOLOv8-Pose 内部的人体检测和姿态估计是共同训练的因此数据集中每张图都得同时标注人体框和17个关键点而不能只标关键点。公开数据集中COCO 数据集Common Objects in Context包含超过25万张带有人体的标注图像是当前姿态估计模型训练的基础另外还有一些专门的跌倒检测数据集如 UR Fall Detection Dataset、Le2i Fall Detection Dataset这些数据集包含大量的跌倒姿态视频帧缺点是场景相对单一多为实验室环境。我自己的做法是先用 COCO 预训练权重作为起点再用自己拍摄的模拟跌倒场景视频做微调finetune这样模型对真实居家环境的适应性会好很多。如果你要自己采集数据务必注意几个问题摄像头安装高度要尽量模拟实际部署场景离地2.2~2.5米场景要覆盖客厅、卧室、卫生间门口跌倒姿态要包含前向扑倒、侧向滑倒、后仰倒地这三类最常见的情况数据中还要加入大量非跌倒但姿态类似的样本比如弯腰扫地、蹲下找东西、坐倒到沙发上这些负样本对降低误报极其重要。4.2 训练环境的搭建与关键参数我用的是单张消费级 GPU 完成微调显存 8GB 的级别就足够跑 YOLOv8s-pose 的小规模微调。训练的核心命令需要说明几个关键参数。首先是数据集配置文件的格式需要标注 train 和 val 的图片路径以及标注文件的目录地址具体格式是path: ../datasets/fall_dataset train: images/train val: images/val kpt_shape: [17, 3] flip_idx: [0, 2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 12, 11, 14, 13, 16, 15]kpt_shape 中的 [17, 3] 表示17个关键点每个点有(x, y, visibility)三个值。flip_idx 表示左右对称关键点的对应关系做数据增强时用于镜像翻转如果配错模型训练出来的左右手、左右脚关键点会互相调换。训练启动命令大致是这样的from ultralytics import YOLO # 加载COCO预训练权重 model YOLO(yolov8s-pose.pt) # 微调训练 model.train( datafall_dataset.yaml, epochs100, imgsz640, batch16, lr00.001, patience20, device0, )关于 imgsz 这个参数值得多说一句。更大的输入分辨率意味着能检测到更小的人体也意味着推理更慢。如果你的摄像头监控的是一个 6 米见方的客厅人在画面上尺寸不小640 分辨率完全够用但如果是大范围的养老走廊建议用 960 甚至 1280否则远离摄像头的人体关键点会识别失败。训练和推理时的分辨率尽量保持一致否则精度会有损失。4.3 推理代码的骨架和实时视频流处理模型训练完后推理阶段的核心任务是从每一帧画面中获取所有行人的骨骼关键点再交给跌倒判定模块。下面的代码展示了最简单的推理流程from ultralytics import YOLO import cv2 import math # 加载模型 model YOLO(best_pose.pt) cap cv2.VideoCapture(test_video.mp4) while cap.isOpened(): ret, frame cap.read() if not ret: break results model(frame, imgsz640, conf0.45, verboseFalse) for result in results: if result.keypoints is None or len(result.keypoints) 0: continue # 关键点数据: [num_person, 17, 3] keypoints result.keypoints.data.cpu().numpy() # 检测框数据: [num_person, 4] boxes result.boxes.xyxy.cpu().numpy() for person_idx in range(len(boxes)): kpts keypoints[person_idx] score fall_detect(kpts, boxes[person_idx]) if score 0.8: # 通知逻辑推送消息到手机 pass这里有一个非常容易出错的细节result.keypoints.data在 GPU 显存中必须用.cpu().numpy()转换到 CPU 的 numpy 数组才能做后续计算。如果不转换下一步做特征运算时类型不匹配会直接报错这类小问题在现场调试时最耗时间提前注意能省不少事。4.4 跌倒判定函数的核心实现下面是我实际封装的一个跌倒判定函数它整合了上文提到的三个特征并且加入了时间窗口的二次确认机制def fall_detect(kpts, bbox, prev_stateNone, frame_height640, frame_width640): kpts: shape [17, 3], 每行对应一个关键点 (x, y, conf) bbox: [x1, y1, x2, y2] 返回: is_fall(bool), warning_score(float) # 1. 提取关键点 left_shoulder kpts[5][:2] right_shoulder kpts[6][:2] left_hip kpts[11][:2] right_hip kpts[12][:2] shoulder_center (left_shoulder right_shoulder) / 2.0 hip_center (left_hip right_hip) / 2.0 # 防止关键点置信度过低导致无效数据 hip_conf (kpts[11][2] kpts[12][2]) / 2.0 if hip_conf 0.5: return False, 0.0 # 2. 计算躯干倾角与水平面的夹角 dx hip_center[0] - shoulder_center[0] dy hip_center[1] - shoulder_center[1] torso_angle abs(math.degrees(math.atan2(dy, dx))) # 3. 计算髋部相对高度 box_height bbox[3] - bbox[1] hip_ratio (hip_center[1] - bbox[1]) / box_height # 4. 计算髋部垂直速度 v_y 0.0 if prev_state is not None: prev_hip_y prev_state[hip_center_y] dt prev_state.get(dt, 0.033) # 默认30fps v_y (hip_center[1] - prev_hip_y) / dt # 5. 评分逻辑 score 0.0 if torso_angle 35: score 0.4 if hip_ratio 0.55: score 0.3 if v_y 0.3 * box_height: score 0.3 return score 0.7, score这个函数的输出是一个0~1的评分。需要注意的是单帧评分高不代表真的跌倒了我用一个队列维护最近 15 帧的评分如果连续 5 帧以上评分都大于 0.7才触发真正的告警。这样设计能滤掉大部分因画面抖动、快速蹲起带来的误报。4.5 部署到端侧从服务器到超低功耗AI视觉模块项目验证完成之后我一直在思考一个问题要想真正保护老人的日常安全总不能为了一个检测功能配一台高性能服务器。近期行业里提到较多的超低功耗端侧AI视觉模块给了我很大启发——这类模块把视觉AI模型集成在电池供电的小型设备里功耗可以压到毫瓦级别不需要连接电源线可以在老人家中独立部署。实际部署中我采用的是两级结构前端用低功耗AI视觉模块做常开检测后端服务器只做告警汇总和消息推送。端侧模块运行的是经过量化和剪枝的 YOLOv8-Pose 小模型以 int8 精度推理帧率可以保持在 10~15 FPS功耗大约只有 0.5W一块 5000mAh 的电池可以支撑数天。这个功耗水平远低于运行原版深度学习模型的开发板或迷你主机真正解决了摄像头长期通电的部署难题。这种端侧模块的部署流程通常是把训练好的模型导出为 ONNX再通过模块厂商提供的转换工具转为特定推理引擎格式然后调用 SDK 在板端推理。模型量化这一步要特别注意int8 量化后关键点坐标的抖动会比 float32 大表现为同一姿态下连续几帧的骨骼点位置有微小波动。解决方案有两个一是采集足够多的校准数据通常 100~200 张代表性图片二是对抗抖动在算法层面增加关键点坐标的时序平滑我用了简单的指数移动平均效果很明显。5. 常见问题与排查技巧实录5.1 关键点识别失败或精度差这个问题在光线昏暗、老人背影对着摄像头、穿宽大衣物遮挡身体轮廓时最常出现。排查思路可以从三个层面入手先确认图像输入分辨率是否过低人体在画面中的像素高度应至少大于 100 像素否则小模型很难提取出准确的骨骼点再检查置信度阈值YOLOv8-Pose 默认的关键点置信度阈值是 0.25如果场景中误检多可以提高到 0.5 以上最后考虑有没有做针对性数据增强训练时对图像做随机旋转、亮度扰动能提升模型在弱光环境下的鲁棒性。另一个隐蔽的问题是关键点编号错乱典型表现是左肩和右肩的输出互换。这往往是训练数据标注时左右搞反或者配置文件中的 flip_idx 配错导致的。建议训练前用一张正面站立的人像图做推理验证如果发现左右肩点交叉优先检查数据集标注其次检查 flip_idx 是否与关键点定义顺序一致。5.2 误报和漏报的取舍误报和漏报是一对矛盾降低误报率必然会在一定程度上提高漏报率反之亦然。实际使用中老人及其家属对漏报的容忍度远低于误报——宁可偶尔误报绝不能该响不响。因此我建议把判定阈值调得相对保守倾向识别为跌倒同时做好误报的处置设计告警消息里附带一段10秒的录像截图家属可以在手机上快速判断是不是真的跌倒减少不必要的上门查看。如果你发现误报特别集中在某个特定区域比如窗户边的光影变化、风扇转动引起的背景扰动可以考虑给摄像头画面设置检测区域掩码只对老人常活动的区域做推理判断。这在 OpenCV 里用一个多边形 ROI 就能实现处理起来很简单但能筛掉大量无效告警。5.3 端侧部署的延迟和功耗优化端侧模块性能不够时首先要做的不是换更贵的硬件而是检查推理管线是否有浪费。我用 profiling 工具排查后发现resize 和归一化操作占用了将近 20% 的耗时这些操作完全可以用更高效的 SIMD 指令优化另外把视频解码后的 BGR 格式直接输入模型减少一次颜色空间转换也能省下几毫秒。功耗方面的优化可以分两级。一级是模型推理频率——夜间老人睡觉场景下跌倒风险主要集中在上厕所时可以把检测帧率降低到 5 FPS功耗随帧率近似线性下降。二级是采用事件驱动模式模块平时以极低功耗运行简单的运动检测用标准摄像头硬件就能完成一旦检测到画面中有大幅运动才唤醒姿态估计模型跑推理。这种模式下平均功耗能再降一个数量级是目前端侧视觉AI落地的常用做法。5.4 隐私问题的处理视觉方案的天然缺点是摄像头无死角观察这对很多老人会造成心理压力。我的处理方案是所有视频流只在端侧做推理原始画面不传送到云端只有在触发跌倒告警时才把前后10秒的检测结果而非视频流发送给家属手机系统提供隐私模式开关休息时间段只检测不入库或不保存任何视频记录。这一套隐私保护方案在向老人和家属说明后接受度会明显提高。6. 实操心得与后续扩展方向整个项目做下来我最深的体会是模型精度不是落地的最难点真正的难点在场景适配。家家户户的客厅格局不同、光线条件不同、摄像头安装位置不同一套固定参数的系统很难通吃所有场景。解决思路是把阈值校准工具做成可视化界面——在部署时用一个调试页面实时展示当前画面的关键点叠加效果和三个特征值的曲线实施人员看着曲线微调阈值一般十几分钟就能把误报率调到可接受范围。系统的后续扩展空间也很大。一是加入轨迹预测如果能在老人正常行走时持续跟踪其步态就可以提前识别步态不稳的高风险状态做跌倒前的预防式干预二是接入智能家居生态检测到跌倒后除了推送告警还可以联动打开室内灯光、门锁解锁方便救援人员进入三是多摄像头融合覆盖老人的全屋活动轨迹解决单摄像头存在遮挡盲区的问题四是加入语音交互模块检测到疑似跌倒状态时先通过语音询问老人是否需要帮助如果老人回应没事就不触发告警这套交互逻辑能进一步降低误报带来的打扰。最后再分享一个实用小技巧在模型推理前对每一帧画面做一次水平翻转的数据增强在代码里用 cv2.flip 实现可以让模型对画面中人体朝向的适应性更好实际测试中能减少约 10% 的漏检成本几乎为零。这个技巧我在多个项目中验证过效果稳定值得一试。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门