
简介面向计算机专业毕业设计与课程设计需求这份人工智能深度学习项目整合YOLOv5人体检测与OpenPose姿态估计实现视频场景中的摔倒行为识别可作为高分毕业设计评审98分的完整参考。项目源码与模型打包为zip压缩包约40.25MB核心代码和预训练权重均包含在内便于直接复现与二次开发。项目亮点在于将目标检测与关键点姿态估计相结合YOLOv5负责实时定位人体OpenPose提取骨骼关键点再通过角度、速度等特征判定摔倒状态覆盖数据预处理、模型加载、推理逻辑到结果可视化的完整流程。读者可从中学习两套算法的协作方式、参数调优思路以及摔倒判断阈值设计对于做大作业、期末项目或毕设开题均有实用价值。当前已有167人学习下载适合具备一定Python和深度学习基础、希望快速搭建完整落地方案的学习者。1. 摔倒检测为什么绕不开YOLOv5人体检测OpenPose姿态检测在养老院、独居老人家庭和医院病房的监控画面里摔倒检测真正要回答的问题不是“画面里有没有人”而是“这个人是不是以异常姿态倒到地面”。标题把 YOLOv5 人体检测和 OpenPose 姿态检测放在一起是实际项目里最常见的组合YOLOv5 先把人从背景里捞出来OpenPose 再提取骨骼关键点最后真正判断摔倒的是关键点之上的规则。只做人体框加宽高比判断遇到弯腰和下蹲会误报只上 OpenPose多人遮挡时关键点会互相串速度也不够。这个方向适合正在做监控告警、银发经济相关产品的工程师也适合拿这套组合做毕业设计的学生。本文会按我自己的工程习惯拆开讲模型选型、训练数据、摔倒判据、组合代码骨架、常见坑和验收方法。你可以照着写一套能跑的流程也能提前避开那些让人反复返工的问题。2. 用YOLOv5训练和部署人体检测网络结构、微调命令与最小推理2.1 YOLOv5网络结构图和人体检测的最小模型选型YOLOv5 不是单个黑盒模型它由三块组成CSPDarknet 骨干网络负责提取图像特征PANet 路径聚合结构负责把不同尺度的特征融合起来最后的检测头在三个尺度上分别输出预测框。yolov5网络结构图里最容易看到的是两个关键点骨干网络借鉴了 CSPNet 的做法把特征图分成两路再合并减少重复梯度计算检测头输出三层特征分别对应小目标、中目标和大目标。对摔倒检测来说小目标这一层尤其重要因为远端摄像头下的人可能只占几十个像素。我一般会选 YOLOv5s 作为默认起点。摔倒检测需要的是“人框”和“框内裁剪区域”不需要像素级精细分割也不需要对人的身份做长期识别所以没必要上 YOLOv5l 或更重的模型。如果部署在树莓派这类设备上可以再降一档到 YOLOv5n后续通过量化把推理速度拉回来。选型时还要看摄像头安装高度斜向下 45 度视角最舒服人体的长宽比变化和关键点可见度都比较理想真正的俯视视角压力很大建议不要只依赖预训练权重。还有一种常见误区拿 COCO 预训练模型直接做人体检测认为已经包含 person 类就不用再训练了。COCO 的 person 类在水平视角、日常场景下效果很好但在病房、楼道、单人间这类固定视角下会出现很多异常姿态比如人蜷缩在地上、被被褥部分遮挡、只露出腿预训练模型很容易漏检。所以凡是长期固定安装的摄像头我都建议抽帧补训。后面几节就按“微调自有数据”来写。2.2 用YOLOv5训练自己的数据集数据准备、配置YAML和超参数先解决标注。用 LabelImg 或 Labelme 都可以导出 YOLO 格式的 txt 文件。每行是class x_center y_center width height四个坐标值都除以了图片宽高所以是 0 到 1 之间的比例值。标注时有个容易踩的问题人体框只框可见部分还是框完整身体我的经验是可见部分超过一半就框可见区域被严重遮挡的不要硬框。摔倒检测中“半个人”的框会造成关键点裁剪不完整反而干扰后续 OpenPose。标注内容不要只标行人。要从部署摄像头的真实视频里抽帧既包含站姿、走路、坐姿也要包含倒地、侧卧、蜷缩、被椅子遮挡。负样本也很重要空房间、无人时段、光影变化剧烈的帧都留一部分防止模型在没人时把其他物体当成人。数据规模上我做过最小可用的项目是 2000 张左右其中 400 张是倒地姿态效果已经能支撑后续报警逻辑如果只有几百张建议直接用公开人体检测数据集的 person 类先凑。目录结构按这样组织datasets/person/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── person.yamlperson.yaml的内容很简单path: datasets/person train: images/train val: images/val nc: 1 names: 0: person这个文件告诉训练脚本只有一类类别名是 person。path建议写相对路径或者写你当前机器上的绝对路径换机器训练时第一件事就是检查这个路径有没有对应错。训练命令我常用下面这条python train.py --img 640 --batch 16 --epochs 50 \ --data datasets/person/person.yaml \ --weights yolov5s.pt \ --freeze 10--img 640是训练输入尺寸。监控画面如果超过 1080p可以保留 640因为人体检测不需要看清人脸。--batch 16在 8G 显存上下比较稳妥显存紧张可以改成 8批量太小时 BN 层统计会不稳定。--freeze 10表示冻结前 10 层也就是 backbone 的大部分让训练只更新 neck 和 head用少量数据也能微调成功。--epochs 50对这种单类微调足够更多轮次反而容易把预训练特征学坏。训练超参数要改的话我一般关注学习率、数据增强和早停。yolov5 的--hyp参数可以指定 hyp 文件其中lr0控制初始学习率微调时建议从 0.01 降到 0.005mosaic是马赛克增强开启后小幅提升目标检测能力但会把人切成碎片对监控场景不是越强越好。还有一点要克制不要给degrees设置太大监控摄像头不会旋转画面旋转增强过多会让模型学习到“倒着的人”这种错误先验。训练结束看runs/train/exp/weights/best.pt推理和后续组合都用这个权重。2.3 人体检测最小推理脚本一个人体框怎么从帧里出来拿到best.pt后先单独验证人体检测不要急着接 OpenPose。下面这个脚本从本地 YOLOv5 仓库加载模型推理一帧图并画出框import cv2 import torch # 从本地仓库加载自定义权重 model torch.hub.load(., custom, pathruns/train/exp/weights/best.pt, sourcelocal) model.conf 0.25 # 置信度阈值摔倒检测常用 0.25~0.35 model.iou 0.45 # NMS 的 IoU 阈值yolov5 后处理默认 0.45 model.classes [0] # 只保留 person 类过滤其他 79 类 model.imgsz 640 # 推理分辨率 cap cv2.VideoCapture(0) while True: ret, frame cap.read() if not ret: break results model(frame) dets results.xyxy[0].cpu().numpy() # 每行: x1 y1 x2 y2 conf cls persons [d for d in dets if int(d[5]) 0] for x1, y1, x2, y2, conf, cls in persons: cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) cv2.imshow(person detect, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()torch.hub.load(., custom, path..., sourcelocal)是从本地仓库加载sourcelocal避免了每次都去访问远端库。model.conf和model.iou对应 YOLOv5 后处理里的两个关键参数先按置信度阈值挑出候选框再通过非极大值抑制去掉重叠框。model.classes [0]会让所有非 person 类不出现在结果里也减少后处理时间。results.xyxy[0]是单张图的检测结果每一行是x1, y1, x2, y2, conf, cls。这里我只保留了cls 0的项因为训练时 person 的类别 id 就是 0。需要注意conf不要调太高监控场景中存在俯视、遮挡0.5 以上的阈值会把倒地的人漏掉。我通常先用 0.25把更多候选交给后面的姿态检测和状态机去过滤。待会把persons里的 x1 y1 x2 y2 传给 OpenPose 时很多坑都出在“框太紧”“框太偏”上。3. OpenPose姿态检测摔倒的关键点特征从哪来3.1 OpenPose在做什么从关键点检测到摔倒判定的距离OpenPose 的输出不是“这个人摔了”而是每一个人的关键点坐标和置信度。它的核心思想是同时预测关键点热图每个像素是某个关节的概率和部分亲和场 PAF编码关节之间连接方向的矢量场再通过图匹配把关键点组装成完整骨架。常见权重输出 COCO 17 点或者 BODY_25 的 25 点摔倒检测真正关心的是头、双肩、双肘、双髋、双膝、双踝这几组点。很多人第一次用 OpenPose 会有错觉既然它能输出所有人体的骨架是不是可以替代 YOLOv5直接用关键点框住人实践里不行。OpenPose 在多人场景下的关键点匹配会互相串尤其是两个人靠近、交叉、遮挡时左肩可能接上另一个人的右手。摔倒检测要求的是“对同一个人的连续帧判断”串点之后特征完全失真。另一个现实问题是速度OpenPose 原版全图推理很慢直接放在实时视频流里会卡。所以我更愿意把 OpenPose 当“单人体检器”用先用 YOLOv5 给出人的框从框里裁剪出一个人再让 OpenPose 输出这一人的关键点。这样既降低匹配难度也减少算力消耗。不要被“项目源码”里的网络结构带偏真正要设计的不是两个模型怎么拼接而是关键点怎么变成告警信号。3.2 摔倒检测三种特征人体倾角、高度比率、速度突变在关键点之上我常用三种特征判断摔倒。第一个是躯干倾角取左右肩中点与左右髋中点连线计算它和竖直方向的夹角。正常站立时这个夹角接近 0 度倒下去时会到 50 到 90 度。第二个是高度比率用肩髋距离除以图片高度或者除以这个人自己的站姿基准高度。倒地后这个值会明显变小。第三个是速度突变取髋部中心的垂直速度摔倒过程通常伴随一个明显加速下跌。下面这个函数把三组特征都算出来def get_fall_features(kps, prev_kps, img_h): # kps 为 dict: {left_shoulder:(x,y,conf), right_shoulder:...} shoulder_c midpoint(kps[left_shoulder], kps[right_shoulder]) hip_c midpoint(kps[left_hip], kps[right_hip]) # 特征1肩髋连线与重力方向的夹角 angle angle_with_gravity(shoulder_c, hip_c) # 特征2肩髋距离归一化到图像高度 body_h distance(shoulder_c, hip_c) / img_h # 特征3髋部垂直速度单位像素/帧 vert_vel 0.0 if prev_hip_c is not None: vert_vel hip_c[1] - prev_hip_c[1] return angle, body_h, vert_vel单独用倾角一定会误判弯腰捡东西时躯干倾角也能超过 50 度。所以判定逻辑要组合先出现速度突变随后 0.5 秒内倾角超过阈值同时高度比率跌到该人的站立基准以下。用代码表达就是if vert_vel 15 and angle 50 and body_h fall_ref_height * 0.6: fall_count 1 else: fall_count 0这里的fall_ref_height是这个人最初进入画面时记录下来的肩髋距离。为什么要用“该人自己的基准”因为摄像头远近不同同样的像素高度在不同距离代表不同真实高度。如果不做归一化靠近摄像头的人弯腰会被当成摔倒远处的人真摔了也检测不到。OpenPose 给出的关键点坐标是像素值必须先除以基准尺度再做阈值比较。3.3 防抖与关键点置信别让姿态噪声骗过判定器关键点不是每次都可靠。OpenPose 输出的每个点带着置信度遮挡、低分辨率、快速运动都会让置信度掉到 0.3 以下。如果直接拿低置信点算角度会出现单帧内倾角来回跳 20 度。我的处理分两步先过滤再平滑。过滤规则是低于MIN_CONF的关键点直接置空不参与计算两个肩点缺一个时用另一个代替两个都缺就跳过当前帧的倾角计算。平滑用指数移动平均也就是常见的 EMAsmooth_kps alpha * current_kps (1 - alpha) * previous_smooth_kpsalpha取 0.6 左右比较合适。太高会跟随噪声太低会把摔倒那个“突然加速下跌”的信号抹平。摔倒过程通常在 0.5 到 1 秒内完成如果 alpha 超过 0.8速度突变几乎看不见。还有一个细节左右肩点会在人体转身时交换导致肩线方向突变。我不会直接用左右肩坐标算角度而是先算肩线中点再把“距离图像顶部更近的那个肩”记为上方避免左右互换造成倾角虚假跳变。4. YOLOv5OpenPose组合工程代码骨架、状态机与告警参数4.1 组合流程和帧间关联同一人跨帧怎么对应组合流程我一般这样拆第一YOLOv5 检测当前帧拿到所有人框第二对每个框做外扩裁剪送入 OpenPose 得到该人的关键点第三用 IoU 方式把当前帧的人框和上一帧的人框关联起来给同一人分配同一个轨迹 ID第四每个轨迹内部维护关键点历史和平滑结果由摔倒状态机判断是否触发告警。顺序必须是检测、裁剪、姿态、跟踪、判定不能反过来。为什么要先做裁剪而不是全图姿态因为 OpenPose 对输入分辨率很敏感。全图 1920x1080 直接送进去人体只占很小区域小目标关键点置信度普遍偏低先用 YOLOv5 把范围缩小到一个人再缩放到姿态模型输入尺寸关键点质量会好很多。同时也能省算力。裁剪时有个坑不要按检测框严丝合缝地切。YOLOv5 的框通常紧贴身体但 OpenPose 需要看到脚踝、手腕和头顶框太紧会把关键点切掉一半。我会把检测框外扩 15% 左右def crop_person(frame, box, expand0.15): x1, y1, x2, y2 [int(v) for v in box] w, h x2 - x1, y2 - y1 x1 max(0, int(x1 - expand * w)) y1 max(0, int(y1 - expand * h)) x2 min(frame.shape[1], int(x2 expand * w)) y2 min(frame.shape[0], int(y2 expand * h)) return frame[y1:y2, x1:x2]expand可以根据人体框长宽比调整站立的人上下各留多一些倒地的人左右留多一些。这块没有统一标准建议先固定 0.15再用几段真实视频看关键点缺失情况。帧间关联采用 IoU 追踪器。对当前帧每个检测框和上一帧所有轨迹的框计算 IoU最大 IoU 超过 0.3 就认为属于同一个人否则新建轨迹。这个阈值比多目标跟踪常用的 0.5 低因为摔倒过程中人体框形变很大同一人前后两帧的框重叠度不一定高。跌倒检测不要求长期身份识别只要求摔倒前后 1 秒内不要换 ID所以 0.3 够用。4.2 摔倒状态机与告警代码骨架组合工程的代码骨架关键是维护每个轨迹的“连续摔倒帧数”。下面是一个简化实现但结构可以迁移到你的项目里class FallDetector: def __init__(self, angle_thresh50, vel_thresh15, need_frames5): self.angle_thresh angle_thresh self.vel_thresh vel_thresh self.need_frames need_frames self.tracks {} def update(self, dets, poses, frame_id): alerts [] for det, pose in zip(dets, poses): track_id self._match_track(det) if track_id is None: track_id self._create_track(det) tr self.tracks[track_id] features tr.update_features(det, pose) if features and self._is_fall(features, tr): tr.fall_cnt 1 else: tr.fall_cnt 0 if tr.fall_cnt self.need_frames: alerts.append(track_id) tr.fall_cnt 0 tr.last_alert_frame frame_id return alerts def _is_fall(self, feat, tr): # tr.ref_height 是该人站姿基准 if tr.ref_height is None: return False return (feat.angle self.angle_thresh and feat.vert_vel self.vel_thresh and feat.body_h tr.ref_height * 0.6)这个类没有包含追踪匹配的全部细节但已经能表达核心fall_cnt连续累加累计到 5 帧才告警。need_frames5按 25 帧视频算约 0.2 秒既能滤掉单帧毛刺也不会把告警拖到倒地之后好几秒。vel_thresh15要小心像素速度受图像分辨率影响1080p 下取 15 像素/帧如果改到 720p 需要等比缩小改成 4K 则要放大。更稳妥的做法是把垂直速度除以肩髋基准高度得到“每秒下跌几个身位”这样阈值基本不随分辨率变化。状态机里还有一个容易被忽略的点告警后不要连续报警。同一个摔倒事件如果状态机一直保持躺姿fall_cnt可能会再累积导致后台收到十几条重复消息。我习惯在告警后进入 10 秒冷却冷却期间即使fall_cnt达标也不再推送。真正的中风和晕厥是摔倒后一直不动需要的是 10 秒后进行一次“长时间未起身”复核而不是反复报警。4.3 yolov5后处理、量化与边缘部署参数取舍把组合模型部署到边缘设备前先要分清瓶颈在哪。yolov5 后处理包括缩放、锚框解码、NMS这部分在 GPU 上耗时很低OpenPose 的关键点热图计算才是大头。如果跑在树莓派 4B 这类设备上官方 OpenPose 基本没有实时可能常见做法是换用轻量姿态估计模型或者把姿态分支输入降到 192x192。我自己在树莓派上部署时把 YOLOv5 输入从 640 降到 320再把 OpenPose 换成 ONNX 导出的单人姿态模型勉强能跑到可用帧率代价是远距离小目标会漏检。对 rk3568 这类 NPU 平台量化是绕不开的。YOLOv5 可以导出 ONNX 后用 RKNN Toolkit 做 int8 量化姿态模型也可以量但关键点热图对量化更敏感。量化后一定重新跑一遍测试集不要只看正常帧要看低对比度、暗光、快速倒地这几类帧。我的经验是姿态模型量化后误报概率会上升常表现为脚踝点漂移到墙上、肩点跳到另一个人身上所以边缘端更推荐把角度阈值调严格 5 到 10 度用漏报率换误报率。如果用 ROS 做机器人平台可以单独把 YOLOv5 检测结果发成人体检测话题姿态节点订阅话题后只处理人体框。这套解耦能让树莓派上的检测和姿态两个进程分开调度避免一帧卡死整条链路崩溃。给后续维护留一点余地代码结构比模型本身更重要。5. 摔倒检测常见问题排查五个坑与对应解法5.1 俯视相机下YOLO漏检人体框时有时无【现象】摄像头装在屋顶或墙角高处人走到画面正下方时YOLOv5 经常不输出框人侧躺在地上时框只框住上半身下半身被切掉。摔倒检测流程里最关键的人框都拿不到后续姿态检测直接被跳过。【原因】预训练 COCO 权重学到的“人”大多是水平视角的直立形象。俯视视角下头顶、肩背占据画面大部分腿脚被遮挡这种特征分布和 COCO 差得很远。单纯把置信度阈值从 0.25 降到 0.1只会把椅子、阴影、地上的包全检测成人问题并没有解决。【解决】必须从实际摄像头角度补样本。部署几台摄像头后抽 24 小时视频把俯视、斜俯视、倒地蜷缩的姿态专门标出来重新微调 YOLOv5。训练时关闭旋转增强限制degrees0不然模型会学到“倒过来的人”这种不存在的情况。如果短期内拿不到足够的俯视数据可以先保留预训练模型同时加一个兜底检测规则当 OpenPose 在全图模式下的关键点数量异常但 YOLO 没框时触发一次弱置信度检测不要直接丢掉。5.2 关键点抖动导致摔倒误判脚踝跳来跳去【现象】OpenPose 输出的脚踝坐标在相邻帧之间跳动 20 到 30 像素有时左脚踝和右脚踝互换位置。肩点在人体转身时也会左右交换导致倾角特征瞬间从 10 度跳到 70 度状态机因此误报。【原因】一是单人裁剪图分辨率不够脚踝只占十几个像素热图峰值定位不稳定二是 OpenPose 对左右关键点的匹配本身就按邻近关系转身和遮挡时容易出现标签互换三是对关键点没有做时间域平滑单帧噪声直接进入判定。【解决】把裁剪框外扩到 0.15 以上并保留原始宽高比用 letterbox 而不是拉伸方式缩放。关键点进入特征计算前做 EMA 平滑alpha取 0.6 左右。左右肩、左右髋的计算改用中点不要直接依赖某一侧坐标。如果脚踝抖动特别严重可以在摔倒判定中降低脚踝权重把主要判据放在肩髋连线和髋部下落速度上脚踝只用来确认“人体已经接触地面”而不是用来计算角度。5.3 弯腰捡东西误报成摔倒特征阈值失效【现象】老人在画面里弯腰捡钥匙躯干倾角达到 60 度持续时间超过 0.5 秒状态机里fall_cnt一路累加最后触发误报护理人员在后台白跑一趟。【原因】弯腰和摔倒的瞬间姿态非常像躯干前倾、头部下移、肩髋连线倾斜。如果只靠倾角单特征判断无论如何调阈值都会误伤。区别在于过程弯腰时髋部高度变化不大站立速度和倒地速度差一个数量级而且弯腰结束后会主动恢复站姿真正摔倒后基本不会在 1 秒内站起来。【解决】把判定条件改成“速度突变 姿态保持”。先要求髋部垂直速度超过阈值比如vert_vel 12再要求倾角大于 50 度且持续多帧。加入“倒地保持”后验条件触发预备状态后如果 0.8 秒内人体没有恢复到倾角小于 30 度才推送告警。捡东西的人通常在 0.5 秒内恢复不会跨过后验条件。代价是告警延迟增加 0.8 秒对摔倒检测来说可以接受因为摔倒过程本身会持续更久。5.4 推理太慢帧率不足管线串行卡成PPT【现象】GPU 工作站上单看 YOLOv5 只要几毫秒单看 OpenPose 也还好但组合起来帧率掉到 5 到 8 帧视频明显卡顿摔倒动作被跳过很多细节。【原因】很多工程把两个模型简单串在同一线程里YOLOv5 跑完才跑 OpenPose整帧延迟就是两者相加。OpenPose 在全图输入时计算量很大而且 CPU 和 GPU 之间频繁拷贝图像数据真正耗时在等待和数据搬运上。【解决】先给系统分层。YOLOv5 固定跑在 GPU 上只输出人体框OpenPose 只对裁剪后的小图推理不要全图跑。用两个线程或者两个队列解耦检测线程持续出框姿态线程从队列里取裁剪图处理允许姿态结果比当前帧慢 100 到 200 毫秒。你可以在代码里把queue_size控制在 5超过就丢弃最旧的帧防止内存堆积。更极端的做法是每两帧跑一次姿态检测中间帧用上一帧关键点线性插值这样速度提升接近一倍摔倒判断仍然连续。部署到树莓派 5 这类设备时把 YOLOv5 输入降到 320姿态输入降到 192再做模型量化比买更贵的硬件更实际。5.5 画面边缘的小人体关键点全低置信倒地检测不到【现象】摔倒发生在画面左上角或者远端走廊YOLOv5 给出的框只有 60x100 像素裁剪后送入 OpenPose所有关键点置信度都低于 0.3过滤器直接把这些关键点置空摔倒判定无法启动。最危险的是远处老人倒地画面不是完全没人但算法就是没反应。【原因】OpenPose 对输入分辨率非常敏感。60x100 的人体缩小到姿态模型输入尺寸后关键点真实信息只有几个像素热图峰值不明确。另一方面监控视频本身可能有 2K 甚至 4K 分辨率但我们在读取帧时往往直接缩到 640远端信息在预处理阶段就丢了一部分。【解决】不要一上来就缩全图。用cv2.VideoCapture保持原始分辨率YOLOv5 推理时使用 960 或 1280 输入等拿到人体框再裁剪。注意model.imgsz越大GPU 显存占用越高实测时要看显存余量。另一个办法是为远端小目标单独开一路低置信度检测conf0.15把结果交给跟踪器用前一帧的姿态作为当前帧的预测先验而不是直接丢弃。如果项目允许优先调整摄像头点位让关键区域的人体高度不小于画面的 5%这是成本最低的解决方式。6. 校准阈值用难例视频做验收别只看训练指标模型训练完yolov5 的 mAP 和 pose 的关键点准确率再高也不代表报警系统能用。我在每个摔倒检测项目里都会单独建一个“验收视频集”里面是现场采集的片段标注出每一段是否真的摔倒、摔倒发生在第几秒。验收指标不用多就要三个召回率、误报次数、平均告警延迟。计算方式可以很简单。把真实摔倒时间点记为true_fall报警时间点记为alarm在 2 秒内算一次命中true_fall [12.5, 45.2] alarm [12.4, 47.0, 103.8] tp 0 for a in alarm: if any(abs(a - t) 2 for t in true_fall): tp 1 fp len(alarm) - tp fn len(true_fall) - tp recall tp / len(true_fall) precision tp / len(alarm)这段代码不是统计级严谨但足够衡量状态机是否“能用”。真正要盯的是fp也就是误报次数。养老院场景里一周超过 3 次误报护理人员就会习惯性忽略告警系统直接失效。我的调参习惯是先把阈值调到偏灵敏让所有可疑事件都触发把angle_thresh降到 40、need_frames降到 3跑完整个难例集然后逐条看误报把弯腰、下蹲、跪地这些片段对应的特征值打印出来再决定阈值放宽还是收紧到多少。比如发现弯腰片段角度是 55 度但髋部速度只有 3就把“速度阈值从 12 提到 15”或“增加持续时间确认”作为对策而不是单纯提高角度阈值。最后一次调完我会把难例视频单独存成一个目录不删掉每次改网络结构或者更换部署平台都重新跑一遍。方法是从这套代码帮你解决上线 80% 问题但真正能不能上线取决于你手里的难例视频够不够真实。摔倒检测最怕的不是模型不聪明而是你以为它已经稳定工作了结果被一个蹲下系鞋带的人轻易骗过。希望这套流程能帮你少走一段弯路也希望你调试得顺手。希望帮到你。本文还有配套的精品资源点击获取