新闻详情

新闻详情

首页 / 资讯中心 / 详情

目标检测+姿态分析:防摔倒预警系统设计实现

发布时间:2026/10/2 14:41:29来源:尧图网络
目标检测+姿态分析:防摔倒预警系统设计实现
简介这是一套基于计算机视觉的目标检测与姿态分析实时防摔倒预警系统课程设计项目内含完整Python源码与实验报告适合计算机视觉、人工智能、数据科学等相关专业学生用于课程设计、毕业设计或项目实训也适合企业员工进行技术参考。项目覆盖目标检测、人体姿态估计、摔倒行为判断与实时预警等关键环节代码结构清晰可读性和可扩展性较好便于二次开发与功能定制。压缩包共1794个文件大小约230.34MB主要包含C头文件与源文件hpp/cpp、Python脚本py、JSON配置文件、OpenCV模型配置prototxt/cmake、TXT说明文档以及AVI演示视频等兼顾底层算法、接口调用、环境配置与运行演示。目前已有225人学习使用内置实验报告和演示视频能帮助读者快速理解预警流程、复现典型摔倒场景适合希望系统掌握视觉预警系统设计与实现并快速搭建演示环境的开发者。1. 防摔倒预警系统到底在解决谁的什么问题课程设计做防摔倒预警系统听起来是把目标检测和姿态分析两个模型拼在一起落地时却没这么省心。这个方向的真实需求很具体独居老人或病房里的患者在画面中摔倒后摄像头如果只做目标检测只能告诉你“画面里有一个人”没办法判断这个人是在弯腰、下蹲还是已经倒地只做姿态分析又容易把收拾东西、绑鞋带当成摔倒。能交付的方案是用目标检测锁定画面中的人用姿态分析拿到肩膀、髋关节等关键点再靠“高速下落 → 低位静止 → 大倾角”三个时序特征做状态机判断。这篇文章把能直接抄作业的模型组合、摔倒判定算法和阈值调法整理出来适合课程设计、毕业设计也适合想在自己项目里加一个跌倒检测模块的从业者。2. 目标检测 姿态分析先锁定“谁在画面里”再看“人的姿态怎么了”2.1 为什么只用目标框做摔倒判断会翻车早期基于摄像头的摔倒检测常用的是轮廓宽高比、外接框最高点下降速度、前景像素占比这些特征。它们的共同问题是没有结构信息一个蹲在地上系鞋带的人外接框会变扁中心点会下移看起来和摔倒早期很像一个弯腰捡东西的人轮廓高度也会急剧变化和目标框特征几乎重合。把这些特征直接喂给分类器误报率会很高尤其在摄像头有俯仰角时BBox 长宽比受透视影响非常大。姿态分析解决的是“多了结构”的问题——通过回归得到肩膀、髋关节、膝盖等人体关键点坐标把“人躺平了没”“身体倾角多大”“髋部是不是突然快速下降”变成可计算的几何量。摔倒本质上是一连串姿态变化而不是静态画面关键点序列能给状态机提供“过程”而非“瞬间”信息这是目标框做不到的。就课程设计而言姿态估计通常用 2D 关键点就够不需要上 3D。2D 关键点可以从普通监控摄像头获得而 3D 姿态估计通常需要双相机或深度相机对“防摔倒”这个目标用肩髋连线向量和竖直方向的夹角就能定义倒地状态多花深度成本并不会换来等价的回报。把这一条写进实验报告里也能说明你的选型不是拍脑袋。2.2 目标检测与姿态估计的三种协作方式常见有三种组合路线。第一种是“先检测再裁剪后姿态”这也是本项目的默认路线原始帧 → 缩放至 640×640 → YOLO 检测只取 person 类 → 取面积最大的人框 → 裁剪出人体区域 → 缩放至 256×256 → MediaPipe Pose → 33 个关键点 → 归一化坐标恢复原图 → 几何特征 → 摔倒状态机 → 告警/日志第二种是“全图直接跑姿态”不经过目标检测。MediaPipe 本身也可以在全图上输出多人姿态但这意味着每一帧都做全图密集回归CPU 帧率往往从 30 掉到 10 以下如果画面里有多个人还需要额外处理跨人关键点分组的问题。单人、固定机位、背景简单的 demo 可以用但课程设计要面对普通教室或宿舍环境这种方案不稳。第三种是“单模型同时出框和关键点”例如 YOLO-Pose 系列。这类模型效率高、精度也好但实现时依赖 torch hub 或定制推理脚本对新手不够友好部署坑比前两种多。课程设计建议走第一种每个模块都是预训练好的打通管线的时间最短调试时也能单独看是哪一段出了问题。2.3 模型选型课程设计的预训练模型怎么组我给的固定组合是 YOLOv8s MediaPipe Pose。两个都是成熟的预训练模型不需要训练就能跑出可用效果这是和自研网络的明显区别。模型/库用途关键特点在课程设计里的定位YOLOv8sultralyticsperson 目标检测COCO 预训练classes[0] 只取人负责框人、框数量、ROI 裁剪MediaPipe Pose姿态估计33 个关键点归一化坐标CPU 实时负责输出肩髋等关键点喂给状态机RTMPose / MMPose姿态估计精度优先关键点质量高但部署链长课题强调精度、有 GPU 时用OpenPose传统姿态方案老架构配置繁琐不推荐除非实验报告要求复现对比选 YOLOv8s 而不是 YOLOv8n是因为 s 在 CPU 上处理单帧 640 输入只比 n 多 20~30ms但对低头、遮挡、光线变化的鲁棒性更好。检测置信度 conf 设在 0.45~0.55 之间即可。检测结果取“面积最大的人框”后面会单独做跟踪避免多人场景下目标漂移。很多人拿到源码后第一反应是“我要不要用自拍数据微调一下模型”我的建议是不要。目标检测只取 person 类COCO 预训练权重已经学得很充分姿态模型同理MediaPipe 的预训练覆盖了日常姿态。摔倒时的极端姿态才是挑战但那是判断阈值和后续处理的问题不是重新训练模型能解决的。按常见计算机视觉学习路径来看这个项目正好把检测和姿态两条主线串起来重点应该放在管线、状态机和工程验证上。模块拆分上我会把源码组织成这样和 zip 里的实验报告对应fall_alert/ ├── main.py # 摄像头/视频入口主循环 ├── detector.py # YOLO 框人模块 ├── pose_estimator.py # MediaPipe 关键点模块 ├── fall_detector.py # 摔倒状态机 ├── alarm.py # 告警动作与日志 ├── requirements.txt ├── test_videos/ # 测试视频目录 └── experiment_report/ # 实验报告与截图每个模块独立调试时可以对单模块输入输出做断点不互相污染这是实验报告里值得写的一个工程决策。3. 跑通最小闭环YOLO 框人 MediaPipe 出关键点3.1 环境准备一套能直接复现的依赖清单课程设计环境不建议一上来就装整套深度学习全家桶够用就行。用 conda 建一个干净环境Python 版本固定在 3.10conda create -n fall_alert python3.10 -y conda activate fall_alert pip install opencv-python numpy mediapipe ultralytics pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu如果机器有 N 卡最后一行可以换成自己 CUDA 版本对应的 torch 安装命令没有 GPU 也不用担心YOLOv8s 在 CPU 上跑 640 输入单帧大概 100~200ms姿态估计再用裁剪区域单独跑整体延迟在课设验收范围内。MediaPipe 在 Windows 和 Linux 下都能直接 pip 安装不需要额外配置 Visual Studio 或 CUDA。3.2 先跑通姿态估计本身最小可运行代码不要一上来就把两个模型拼起来先把 MediaPipe 单独跑通。下面是只做姿态估计的骨架摄像头每帧读入后直接全图推理import cv2 import mediapipe as mp mp_pose mp.solutions.pose pose mp_pose.Pose( min_detection_confidence0.5, min_tracking_confidence0.5, model_complexity1 ) cap cv2.VideoCapture(0) # 0 表示默认摄像头也可换视频文件路径 while cap.isOpened(): ok, frame cap.read() if not ok: break # MediaPipe 内部按 RGB 处理OpenCV 读出来的是 BGR rgb cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) result pose.process(rgb) if result.pose_landmarks: h, w, _ frame.shape for i, lm in enumerate(result.pose_landmarks.landmark): # lm.x 和 lm.y 是 0~1 的归一化坐标 x int(lm.x * w) y int(lm.y * h) if i in [23, 24]: # 23左髋24右髋 cv2.circle(frame, (x, y), 5, (0, 255, 0), -1) cv2.imshow(pose_demo, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()这段代码里最容易踩的坑是颜色空间忘记cvtColor会让人脸和肢体关键点漂移得像鬼影。另一个概念是 MediaPipe 返回的坐标是相对图像宽高的归一化值画到 OpenCV 窗口上必须乘回原来的宽高。min_detection_confidence控制进入检测的门槛min_tracking_confidence控制跟踪是否维持跟踪失败后模型会重新回到检测模式两者配合决定关键点断帧的频繁程度。3.3 把 YOLO 的人框接给姿态模型跑通单模型后才把它们串成检测加姿态的管线。核心逻辑是YOLO 在全图上找 person拿到框后把框内区域裁剪出来缩放成统一尺寸再喂给姿态模型。这样姿态模型只需要处理一个人计算量小、关键点也更稳定。import cv2 import mediapipe as mp from ultralytics import YOLO class PosePipeline: def __init__(self, det_weightsyolov8s.pt, conf0.5, pose_size256): self.detector YOLO(det_weights) self.conf conf self.pose_size pose_size self.mp_pose mp.solutions.pose self.pose self.mp_pose.Pose( min_detection_confidence0.5, min_tracking_confidence0.5, model_complexity1 ) def detect_person(self, frame_bgr, target_size640): h, w frame_bgr.shape[:2] small cv2.resize(frame_bgr, (target_size, target_size)) results self.detector.predict( small, classes[0], confself.conf, verboseFalse ) scale_x w / target_size scale_y h / target_size boxes [] for r in results: for box in r.boxes: x1, y1, x2, y2 box.xyxy[0].cpu().numpy() boxes.append([ int(x1 * scale_x), int(y1 * scale_y), int(x2 * scale_x), int(y2 * scale_y) ]) return boxes def get_landmarks(self, frame_bgr, box): x1, y1, x2, y2 box person frame_bgr[y1:y2, x1:x2] if person.size 0: return None person cv2.resize(person, (self.pose_size, self.pose_size)) rgb cv2.cvtColor(person, cv2.COLOR_BGR2RGB) result self.pose.process(rgb) if not result.pose_landmarks: return None bw x2 - x1 bh y2 - y1 landmarks [] for lm in result.pose_landmarks.landmark: # 把裁剪框内的归一化坐标换算回原图坐标 landmarks.append((x1 lm.x * bw, y1 lm.y * bh)) return landmarks def process(self, frame_bgr): boxes self.detect_person(frame_bgr) if not boxes: return None, None box max(boxes, keylambda b: (b[2] - b[0]) * (b[3] - b[1])) landmarks self.get_landmarks(frame_bgr, box) return box, landmarks注意detect_person里先缩小到 640 再检测是为了让 yolo 在 CPU 上跑得更快返回坐标时再用scale_x和scale_y放大回原图。get_landmarks返回的关键点坐标是相对整帧图像的绝对坐标而不是裁剪框内的相对坐标后续画图和计算速度时都统一用这套绝对坐标能少踩一半的偏移 bug。3.4 帧率取舍CPU 跑不动时怎么保报警时效目标检测加上姿态估计两个模型的推理耗时会在 CPU 上叠加。我一般会在主循环里做跳帧处理姿态估计是瓶颈就每隔一帧算一次中间帧直接用上一帧关键点顶替保证画面显示不卡顿cap cv2.VideoCapture(0) pipeline PosePipeline() last None frame_id 0 while True: ok, frame cap.read() if not ok: break frame_id 1 # CPU 性能不足时把 1 改成 2表示每两帧做一次完整检测 if frame_id % 1 0: box, landmarks pipeline.process(frame) if landmarks: last (box, landmarks) else: box, landmarks last if last else (None, None) if landmarks: for idx in (11, 12, 23, 24): x, y int(landmarks[idx][0]), int(landmarks[idx][1]) cv2.circle(frame, (x, y), 4, (0, 255, 0), -1) cv2.imshow(fall_alert, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()跳帧带来的风险是速度特征失真。如果上一帧关键点被跳过了状态机里“这一帧的位移”必须用真实时间差来算不能按固定 30fps 来算。摔倒整个过程一般持续 0.5~1 秒跳一帧造成的速度误差可能高达 30%~50%后面状态机里那个速度阈值就会被拖死。所以跳帧只能用于显示和冗余判断核心的fall_detector一定要记录每一帧的真实时间戳。4. 摔倒判定状态机三个特征和一组阈值怎么调4.1 提取哪些特征髋部中心、速度和身体倾角摔倒判定的输入是姿态关键点但关键点本身太原始需要先抽象成特征。我常用的只有三个髋部中心位置、髋部中心速度、肩髋连线与竖直方向的夹角。髋部中心比头部或脚都稳定摔倒时它会经历一次明显下坠身体倾角则能区分“人躺平了”和“人只是站低了”。import math def compute_features(landmarks): landmarks: 长度 33 的 [(x, y), ...] 列表顺序与 MediaPipe 一致 这里只用到 11、12、23、24 号关键点 sh_l landmarks[11] # 左肩 sh_r landmarks[12] # 右肩 hip_l landmarks[23] # 左髋 hip_r landmarks[24] # 右髋 hip_x (hip_l[0] hip_r[0]) / 2.0 hip_y (hip_l[1] hip_r[1]) / 2.0 sh_x (sh_l[0] sh_r[0]) / 2.0 sh_y (sh_l[1] sh_r[1]) / 2.0 dx hip_x - sh_x dy hip_y - sh_y # 肩髋连线与竖直向下方向的夹角站立时约 0~20 度倒地时接近 90 度 cos_angle abs(dy) / (math.hypot(dx, dy) 1e-6) angle math.degrees(math.acos(max(0.0, min(1.0, cos_angle)))) return { hip_x: hip_x, hip_y: hip_y, shoulder_y: sh_y, body_angle: angle }取肩髋连线而不是整条躯干线段是因为左右肩和左右髋各自取中心点后能抵消关键点偶发的左右不对称抖动。无论人往前倒、往后倒还是侧倒肩髋连线与竖直方向的夹角都会从接近 0 度拉到接近 90 度这个特征对摔倒方向不敏感正好适合单摄像头的通用场景。速度特征需要结合时间窗口。我维护一个最近 1 秒的髋部中心坐标列表每秒算一次位移差除以真实时间差得到速度。这个速度值是归一化坐标单位每秒不是米每秒所以阈值只能在固定画面尺寸和摄像头距离下复用。4.2 状态机实现stable → falling → fallen 的完整代码特征值算出来之后单独看任何一个特征都不可靠必须做时序状态机。我的做法是三个状态stable 表示日常站坐活动falling 表示检测到高速下落的疑似过程fallen 表示倒地已经被确认。只有 fallen 状态且持续一段时间才触发报警。class FallDetector: def __init__(self, fps30, vel_thresh0.12, fallen_angle60, fall_height_ratio1.35, trigger_time0.4, cooldown_time8): self.fps fps self.vel_thresh vel_thresh self.fallen_angle fallen_angle self.fall_height_ratio fall_height_ratio self.history [] self.baseline_hip_y None self.state stable self.state_frames 0 self.trigger_frames int(fps * trigger_time) self.cooldown_frames int(fps * cooldown_time) self.cooldown 0 self.alert_count 0 def update(self, hip_x, hip_y, body_angle): self.cooldown max(0, self.cooldown - 1) self.history.append((hip_x, hip_y)) if len(self.history) self.fps: self.history.pop(0) # 站立基线只在躯干直立、髋部高度没有异常下沉时慢更新 if body_angle 25: if self.baseline_hip_y is None: self.baseline_hip_y hip_y elif hip_y self.baseline_hip_y * 1.3: self.baseline_hip_y 0.9 * self.baseline_hip_y 0.1 * hip_y # 速度滑动窗口首尾位移 / 窗口真实时长 speed 0.0 if len(self.history) 2: dx self.history[-1][0] - self.history[0][0] dy self.history[-1][1] - self.history[0][1] dt (len(self.history) - 1) / self.fps speed math.hypot(dx, dy) / dt ratio hip_y / (self.baseline_hip_y 1e-6) if self.baseline_hip_y else 0 if self.state stable: if speed self.vel_thresh: self.state falling self.state_frames 0 elif self.state falling: # 高速阶段结束后必须同时满足“低于基准、大倾角”才算真正倒地 if speed self.vel_thresh * 0.5: if ratio self.fall_height_ratio and body_angle self.fallen_angle: self.state fallen self.state_frames 0 else: self.state stable # 虚惊一场回到正常状态 elif self.state fallen: # 倒地静止持续一段时间才报警抑制瞬时误报 if ratio 1.2 and body_angle 45: self.state_frames 1 if self.state_frames self.trigger_frames and self.cooldown 0: self.cooldown self.cooldown_frames self.alert_count 1 self.state stable return True else: self.state stable return False这个状态机的核心思想是“过程确认”。stable 到 falling 只看速度防止把起身、下蹲这类瞬间动作漏掉falling 到 fallen 必须等速度回落后再检查低位和角度防止把捡东西这种“有向下的位移但最终站了起来”的动作判成摔倒。fallen 状态里再叠加连续帧计数只有倒地维持够 0.4 秒才触发一次报警并用冷却时间避免报警后反复响铃。4.3 参数表与调法先录视频再改阈值下面这些参数是侧视角摄像头、画面里单人、归一化坐标下的参考值不要不做实验直接抄参数默认参考影响调节方向vel_thresh0.12判断“是否发生高速下落”过小会误报捡东西过大漏报快速摔倒fallen_angle60判断“躯干是否接近水平”降到 50 更敏感升到 70 更保守fall_height_ratio1.35判断“髋部是否低于站立基准线”俯视角度下可提到 1.5~2.0trigger_time0.4 秒倒地多久才算确认报警0.3 反应快但易误报0.8 更稳但报警慢cooldown_time8 秒两次报警最小间隔5~15 之间按场景调调参的关键不是看单帧效果而是看整段视频。我会准备 10 段正常行为视频和 10 段摔倒视频先打印每一帧的 speed、angle、ratio 值看两个类别在哪个区间分得开再把阈值取在两端分布的中间。最忌讳的是对着摄像头摆几个动作就拍板那样只能调出一组“对你自己姿势有效”的参数。提示把这些特征值写入日志再做阈值分析比盯着实时画面调参高效得多。后面第六章会给出落盘方法。4.4 摄像头视角不同时哪些判断要重新校准同一个算法在不同安装角度下特征趋势会变。侧视角最舒服angle 和 ratio 都敏感俯视角时人倒地后髋部中心仍在画面中间height_ratio 变化不明显这时要以 body_angle 和 bbox 宽高比为主平视角时髋部的绝对高度受人和摄像头之间距离影响大ratio 不可靠反而 angle 最稳定。所以部署时先固定摄像头位置再录一小段正常活动的参考视频把 baseline_hip_y 的初始化和参数调好。课程设计如果是在实验室演示别把摄像头拿在手里边走边测那样 baseline 一直在变状态机基本没法工作。5. 避坑记录从关键点丢失到误报警的 5 个典型场景5.1 倒地瞬间姿态关键点消失状态机停在 falling现象人在画面里确实摔倒了但倒地那一两帧 MediaPipe 返回的 landmarks 为空状态机一直停在 falling永远进不了 fallen最终没有报警。原因摔倒瞬间身体折叠、肢体遮挡严重姿态模型检测置信度掉到门槛以下画面模糊或运动拖影也会造成关键点输出中断。解决分两层处理。第一层把min_detection_confidence从 0.5 降到 0.4让模型更容易重新进入检测第二层在 landmarks 为空但前一帧状态不是 stable 时用 YOLO 人框的宽高比做兜底——如果框高已经不足站立基准的 60%且框宽大于框高说明人大概率还在地上if landmarks is None and last_box is not None: box_h last_box[3] - last_box[1] box_w last_box[2] - last_box[0] if box_h stand_h * 0.6 and box_w box_h: fall_detector.keep_fallen_state()这里的stand_h来自入场后前 30 帧的人框高度平均值。兜底逻辑不要做得太长连续 10 帧无关键点就得重新锁定目标否则会把后进来的其他人都算进状态里。5.2 弯腰捡东西被当成摔倒现象测试时人在画面里弯腰捡起地上的水瓶躯干一压低就触发了报警。原因弯腰时肩髋连线的夹角很容易超过 60 度髋部位置也会下沉恰好满足了 fallen 的两个条件。问题出在缺少“高速下落”的过程约束。解决状态机必须要求先进入 falling也就是速度先超过 vel_thresh等速度回落再复查低位和角度。弯腰动作再快速度峰值通常也达不到摔倒的一半。把 vel_thresh 调到正常弯腰峰值速度的 1.5 倍以上同时把 trigger_time 提到 0.5~0.6 秒弯腰捡完东西的恢复过程会先让状态机回到 stable自然就不会报警。5.3 多人同框导致报警对象漂移现象画面里两个人交错行走被监测目标本来是画面左侧的老人两人一交叉YOLO 的最大面积框跳到了右侧的年轻人身上老人摔了没报警年轻人蹲了一下反而报警。原因每一帧都取最大面积框没有任何跨帧关联。解决做一个最简单的 IoU 跟踪。上一帧的目标框与当前帧所有框求 IoU选最大的那个作为当前目标如果 IoU 低于 0.3说明目标丢失连续丢失超过 30 帧再重新取最大面积框def iou(a, b): xx1 max(a[0], b[0]); yy1 max(a[1], b[1]) xx2 min(a[2], b[2]); yy2 min(a[3], b[3]) w max(0, xx2 - xx1); h max(0, yy2 - yy1) inter w * h area_a (a[2] - a[0]) * (a[3] - a[1]) area_b (b[2] - b[0]) * (b[3] - b[1]) return inter / (area_a area_b - inter 1e-6) def pick_target(boxes, track_box): if track_box is None: return max(boxes, keylambda b: (b[2] - b[0]) * (b[3] - b[1])) best max(boxes, keylambda b: iou(track_box, b)) return best if iou(track_box, best) 0.3 else NoneIoU 跟踪在课程设计里够用不用上 DeepSORT。实验报告里把这个逻辑画成模块图能明显体现出工程意识。5.4 微调目标检测模型后反而崩了现象有同学用自拍数据集微调 YOLOv8s 后原来能检测的人反而检测不到了val 精度大幅下降。原因项目需要的只是 person 类COCO 预训练已经覆盖得足够好。自作主张用几百张小图微调学习率稍微大一点就发生灾难性遗忘把原有表观特征冲掉了。解决默认不训练直接用预训练权重。如果实验报告要求展示自建数据集的流程一定要把训练参数控制住from ultralytics import YOLO model YOLO(yolov8s.pt) model.train( datafall_person.yaml, # 自建 person 标注数据集 epochs30, lr01e-4, # 微调必须用很小的学习率 batch8, freeze10, # 冻结前 10 层骨干网络 imgsz640 )数据标注可以用 labelme 这类常见标注工具但 person 类目标至少 300 张起步而且要包含站、坐、躺、遮挡、不同光照。freeze 前 10 层骨干是防止把通用特征洗掉lr0 超过 1e-3 基本必崩。5.5 视频帧率不一致速度阈值忽高忽低现象摄像头是 30fps录下来的测试视频只有 15fps用同一组阈值实机演示不报回放测试反而狂报。原因速度特征用的是“每秒位移”但滑动窗口按帧数计算时间。帧率不同实际时间差就不同速度计算值成倍偏移。解决所有速度计算统一用真实时间差。记录每一帧到达的time.time()窗口总时长取窗口首尾时间戳之差不按帧数除以 fps 估算。import time last_ts None history [] def update_history(hip_x, hip_y): now time.time() history.append((now, hip_x, hip_y)) if len(history) 30: history.pop(0) if len(history) 2: return 0.0 dt history[-1][0] - history[0][0] if dt 0: return 0.0 dx history[-1][1] - history[0][1] dy history[-1][2] - history[0][2] return math.hypot(dx, dy) / dt这样不管视频源是摄像头、录制视频还是网上下载的 demo速度特征都能对齐到同一套尺度。6. 再进一步把状态判断变成可回放的日志和验证闭环6.1 小规模测试集 混淆矩阵回答“准不准”课程设计答辩里最容易被问的问题是“你这系统到底准不准”。与其说“感觉挺准的”不如自己录一组小视频做最简单的统计。我一般会准备 12 段短视频6 段正常行走/弯腰/坐下6 段不同方向的摔倒每段 10~20 秒跑完统计报警次数stats {tp: 0, fp: 0, fn: 0, tn: 0} for video_path, label in test_set.items(): alarms run_once(video_path) # 返回整段视频的报警次数 pred 1 if alarms 0 else 0 if pred 1 and label 1: stats[tp] 1 elif pred 1 and label 0: stats[fp] 1 elif pred 0 and label 1: stats[fn] 1 else: stats[tn] 1这个统计很粗糙但对课设来说足够直接。把混淆矩阵画进实验报告比贴十张检测截图都有说服力。6.2 特征时间序列落 CSV让每个报警都能复盘另一个被我写进很多次报告的习惯是特征落盘。每一帧把时间、状态、速度、角度、高度比写进 CSV报警后回去看那一分钟的曲线一眼就能看出阈值设置是否合理import csv, time with open(fall_log.csv, a, newline) as f: writer csv.writer(f) writer.writerow([ time.strftime(%H:%M:%S), state, f{speed:.3f}, f{angle:.1f}, f{ratio:.2f}, 1 if alarm else 0 ])参数调优时这份 CSV 就是“后悔药”。改了阈值后跑同一段视频对比报警点前后的特征值不会出现调完 A 场景又挂掉 B 场景的黑匣子状态。6.3 一个轻量平滑与可替换的告警接口最后补两个小改进。一是对关键点做指数平滑抑制 PortalMedia 输出的小抖动smoothed alpha * raw (1 - alpha) * smoothed # alpha 取 0.3~0.5alpha 不要低于 0.3否则速度峰值会被抹没摔倒的“下落过程”就识别不出来了。二是把告警动作单独抽象成一个接口后续接蜂鸣器、串口、HTTP 推送都只改一个类class AlertHandler: def notify(self, level, info): with open(alarm.txt, a) as f: f.write(f{time.time()} {level} {info}\n)我做这套系统的最大教训是阈值从来不是一次调出来的而是一遍遍回放 CSV 日志磨出来的。每个报警背后都要有数据支撑答辩时才不会被问倒投入产出比最高的时间都在录测试视频和看日志上。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

AI智能体Office套件设计与实现:从毕设选题到系统落地 2026/10/2 15:25:03

AI智能体Office套件设计与实现:从毕设选题到系统落地

AI智能体Office套件设计与实现:从毕设选题到可落地系统如果你正在为计算机科学与技术专业的毕业设计选题发愁,或者已经决定做“AI智能体 Office套件”这个方向,那这篇文章应该能帮你省下不少踩坑的时间。这个选题最大的好处是:它…

阅读更多 →
NetBackup备份Oracle配置指南:架构、RMAN策略与故障排查 2026/10/2 15:25:03

NetBackup备份Oracle配置指南:架构、RMAN策略与故障排查

简介:面向Oracle DBA与备份运维人员,这份NetBackup环境下的Oracle数据库备份配置文档,完整覆盖从客户端代理安装、主服务器策略创建到RMAN脚本定制与备份任务执行的全流程。文档以实际操作步骤为主线,先说明在Linux/Unix Oracle主…

阅读更多 →
机器人空间描述与坐标变换:旋转矩阵、齐次变换与位姿计算入门 2026/10/2 15:24:50

机器人空间描述与坐标变换:旋转矩阵、齐次变换与位姿计算入门

1. 从"机器人为什么会撞到自己的胳膊"说起 很多人第一次接触机器人学,是从一个看似很蠢的问题开始的:为什么机械臂抓东西的时候,明明目标就在眼前,它却经常摆出一个拧巴到不行的姿势,甚至差点撞到自己&#…

阅读更多 →
Web组态实战:智捷云2D组态与工业监控系统构建指南 2026/10/2 15:24:31

Web组态实战:智捷云2D组态与工业监控系统构建指南

1. 从桌面组态到浏览器组态:这波迁移到底解决了什么实际问题1.1 老组态软件我用了十年,最大的痛不在功能做工业监控这些年,我碰过的组态软件两只手数不过来。早期守着组态王做水厂项目,后来给电厂配过WinCC,也在几个产…

阅读更多 →
24GHz雷达传感器选型指南:频段原理、安装调试与工业应用 2026/10/2 15:24:30

24GHz雷达传感器选型指南:频段原理、安装调试与工业应用

1. 为什么是24GHz:一个频段如何决定了产品的探测上限在物联网感知层摸爬滚打这些年,我上手过的雷达传感器少说也有十几个型号,从几块钱的倒车雷达模块到上万的毫米波工业传感器都碰过。选型时候最容易被忽视、却又最致命的一个参数&#xff0…

阅读更多 →
向量库把 C 盘吃到 0 字节:75M 数据撑出 48.6G 索引的清理复盘 2026/10/2 15:24:24

向量库把 C 盘吃到 0 字节:75M 数据撑出 48.6G 索引的清理复盘

一次真实的磁盘事故:应用数据只有 75MB,它的向量库索引目录却悄悄长到 48.6GB。定位、回收、验收的完整过程,以及为什么索引型存储必须纳入磁盘监控。 事故现场 一台开发机 C 盘可用空间归零,系统开始随机弹"磁盘已满"…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉