
简介基于Matlab的人体异常行为检测系统源码聚焦主动监控场景能够对监控画面中的跌倒、快跑、慢跑等行为进行判别与提示尤其适合独居老人看护等需要及时预警的场合。面向具备一定编程基础的Matlab开发人员内置交互式图形界面便于直观查看检测结果。压缩包为zip格式共756个文件、约8.82MB其中以741张jpg图像为主用于保存各帧检测效果与界面状态6个m文件为核心行为识别算法3个avi视频提供步行、慢跑、快跑三类示例场景另有fig界面文件、doc导入说明和md说明文档。目前已有349人学习/下载。资源体量紧凑而内容完整从示例视频到界面脚本一应俱全既可直接运行查看识别效果也可参照doc说明配置环境并进一步调试算法适合作为课程设计或主动监控项目的实用参考。1. 基于Matlab的人体异常行为检测为什么先从跌倒说起监控室里养老院一位老人从画面边缘倒地护理员二十分钟后才看到回放——这类情况是人体异常行为检测系统最典型的落地场景。跌倒、晕厥、长时间静止、突然蜷缩都属于异常行为范畴而跌倒又是其中发生频率最高、危害最直接的一种。基于Matlab做这件事的优势很实际图像处理、信号处理、机器学习和深度学习工具箱齐备从读入数据、提取特征到训练分类器全流程可以在同一个环境里闭环验证不需要在Python和C之间来回搬数据。这套系统的核心任务是把人体是否跌倒这个二分类问题变成对姿态变化、运动冲击、时序特征的综合判断。适合边做边调的一线工程师和研究者也适合需要在短时间内出原型的学生课题。2. 人体异常行为检测的建模思路与Matlab工具箱选型2.1 人体异常行为检测的两条路线视觉姿态与可穿戴传感人体异常行为检测本质上是把连续的人体运动数据映射成正常或异常的标签。实现路线主流有两条。第一条是视觉路线用摄像头采集画面检测人体关键点头、颈、肩、肘、髋、膝、踝根据关键点坐标计算姿态特征。第二条是可穿戴传感路线把加速度计、陀螺仪固定在人体躯干或四肢直接用惯性数据判断运动状态。两者不冲突实际系统里也常见融合方案。Matlab里这两条路线都有对应的工具箱支持视觉路线用Computer Vision Toolbox加载关键点检测模型传感路线用Signal Processing Toolbox做滤波和特征工程。从落地难度看视觉路线的优势是无需用户佩戴设备但受摄像头视角、遮挡和光照影响可穿戴路线的数据更干净、对隐私更友好但需要用户配合佩戴。做跌倒检测时很多从业者会优先采用可穿戴设备里的加速度计数据因为跌倒瞬间会产生显著的加速度冲击峰值这个特征在信号层面非常明显算法门槛低、可解释性强。2.2 为什么跌倒检测本质上是时间序列分类问题单帧图像判断一个人是否跌倒并不可靠。因为跌倒是一个过程先出现快速下坠的冲击然后躯干姿态从直立变为接近水平最后可能伴随一段时间的静止。这三个阶段在时间上连续在信号上各自有特征。因此把跌倒检测建模成时间序列分类是更稳妥的做法也就是用滑窗截取连续一段时间的数据提取窗口内的统计特征和形态特征再交给分类器判断。这个建模思路决定了整个系统的基本结构数据采集 → 预处理 → 滑窗切分 → 特征提取 → 分类器 → 后处理。后面的章节基本都按这个流水线展开。2.3 Matlab实现路线的选型对比实现路线依赖工具箱精度可解释性开发成本适用阶段纯规则阈值Matlab基础、Signal Processing Toolbox中高低快速原型、可穿戴数据传统机器学习SVM、随机森林Statistics and Machine Learning Toolbox中高中中样本量几百到几千深度学习LSTMDeep Learning Toolbox高低高大量连续时序数据我一般在数据量不足时用规则SVM先保证系统能跑通数据量大、误报要求苛刻时再切LSTM。阈值法是兜底方案任何时候都能用来做交叉验证的基准线。3. 数据准备与预处理跌倒样本从哪来、标签怎么对齐3.1 公开数据集与自采方案的选择训练一个可靠的跌倒检测模型第一步是拿到带标签的行为数据。公开数据集方面UR Fall Detection包含加速度计和视频数据Le2i提供室内监控视频的骨架标注MobiFall则是手机传感器采集的跌倒与日常活动数据。这些数据集在公开研究中被广泛使用可以直接用于跑通算法流程。需要注意不同数据集的采样率、传感器佩戴位置、类别定义不完全一致每换一个数据集阈值和归一化参数都要重新标定。自采数据的常见做法是用智能手机固定在腰部或胸前以50Hz采样率记录三轴加速度同时用视频录制同场景画面再逐段标注标签。Matlab里可以用Video Labeler对视频逐帧标注行为区间导出为ground truth再与传感器时间戳对齐。3.2 Matlab读取CSV并处理时间戳假设传感器数据以CSV存储每行包含时间戳、三轴加速度和标签% 读取IMU数据 data readtable(imu_fall.csv); fs 50; % 采样率50Hz常见可穿戴设备配置 ts seconds(data.timestamp); % 时间戳转duration类型 % 检查是否有丢包 diffs diff(ts); miss sum(diffs seconds(1.5/fs)); % 相邻间隔超过1.5个采样周期算丢包 if miss 0 warning(检测到%d处丢包建议用retime补全, miss); end % 取出三轴加速度列 ax data.acc_x; ay data.acc_y; az data.acc_z; label data.label; % 1为跌倒0为正常这段代码的关键是readtable读入后先检查时间戳是否连续。传感器在传输过程中偶尔丢包如果不处理后续滑窗切分会让窗口内的数据时间轴不均匀直接影响特征计算的准确性。3.3 预处理去重力、滤波与动作分割加速度计测得的数值包含重力分量人体静止站立时重力在Z轴上约为9.8。跌倒识别关心的是运动加速度而非重力所以第一步是去除重力。常见做法使用截止频率0.25Hz的高通滤波器因为人类日常动作的频率成分大多在0.3Hz以上低于0.25Hz则主要是直流和缓慢漂移。% 高通滤波去除重力分量 fc 0.25; % 截止频率0.25Hz [b, a] butter(2, fc/(fs/2), high); ax_hp filtfilt(b, a, ax); ay_hp filtfilt(b, a, ay); az_hp filtfilt(b, a, az); % 移动平均平滑窗口5个点 window 5; ax_smooth movmean(ax_hp, window); ay_smooth movmean(ay_hp, window); az_smooth movmean(az_hp, window); % 合成加速度幅值 SMA sma sqrt(ax_smooth.^2 ay_smooth.^2 az_smooth.^2);filtfilt做零相位滤波避免普通filter带来的相位偏移导致冲击峰位置偏移。这里使用二阶Butterworth即可阶数太高容易出现振铃。合成加速度幅度SMA是后续判断冲击强度的基础信号。提示预处理参数不是固定的。采样率降到20Hz时截止频率应相应下调佩戴位置在手腕和腰部时重力分解方式不同需要单独校准。4. 摔倒特征提取把姿态改变变成一组可计算的数字4.1 基于人体关键点的姿态特征如果系统使用视觉方案人体关键点坐标是特征提取的出发点。假设关键点检测模型输出头部、双肩、双髋、双膝的位置可以定义三个关键特征质心高度比用头部和双髋坐标的平均值估算人体质心高度再除以人体站立时的参考高度得到归一化高度。% 关键点坐标矩阵每行: [x, y] head keypoints(1, :); % 头部 hipL keypoints(8, :); % 左髋 hipR keypoints(11, :); % 右髋 % 质心高度像素坐标下y值越小越高计算时取反向 centerH (head(2) hipL(2) hipR(2)) / 3; % 归一化到站立参考高度 standH 1.2; % 由站立帧统计得到单位与centerH一致 normH centerH / standH;人体倾角用双肩中点和双髋中点连线与竖直方向的夹角表示躯干倾斜程度。shoulderC (keypoints(2, :) keypoints(5, :)) / 2; % 肩中点 hipC (hipL hipR) / 2; % 髋中点 % 躯干向量atan2得到与竖直方向的夹角 vec shoulderC - hipC; angleRad abs(atan2(vec(1), vec(2))); % 单位弧度 angleDeg rad2deg(angleRad); % 转角度便于设定阈值质心高度比直接反映人体是否从直立变成倒地躯干倾角反映横躺程度。这两个特征配合使用能区分蹲下和跌倒蹲下时质心降低但躯干仍然竖直跌倒时两者同时异常。4.2 滑窗统计特征把时序信号压缩成特征向量对于IMU数据单个采样点的幅度值说明不了问题需要在一个窗口内提取统计量。常见做法是设置1秒窗口、50%重叠的滑窗function feat extractWinFeatures(sma, winLen, step) % sma: 合成加速度幅度序列 % winLen: 窗口长度采样点数 % step: 滑动步长采样点数 n length(sma); k 1; for idx 1:step:n-winLen1 seg sma(idx:idxwinLen-1); feat(k,1) mean(seg); % 均值反映整体运动强度 feat(k,2) std(seg); % 标准差反映波动程度 feat(k,3) max(seg); % 峰值跌倒冲击的关键指标 feat(k,4) sum(abs(diff(seg)) 0.3); % 大幅跳变次数 feat(k,5) min(seg); % 最小值捕捉静止期 feat(k,6) sum(seg 2.5) / length(seg); % 高强度活动占比 k k 1; end end函数的输出是每行一个窗口的特征向量行数与数据长度和窗口设置有关。跌倒的典型模式是峰值瞬间抬高冲击、之后均值下降倒地静止、高强度占比在窗口后半段趋近于零。这些特征组合起来比单独看峰值更鲁棒。4.3 特征敏感性对照表特征公式或Matlab实现对跌倒的敏感性说明质心高度比centerH / standH高跌倒后显著低于正常值躯干倾角atan2(dx, dy)高直立时接近0°倒地时接近90°合成加速度峰值max(sma)中高失重撞击两个冲击峰信号幅值过零率sum(abs(diff(seg))thr)中区分陡然动作与平滑动作窗口内能量sum(sma.^2) / winLen中区分剧烈运动与静止注意单独用质心高度容易把坐下蹲下误判为跌倒单独用加速度峰值会把跳起落地误判为跌倒。所以实际特征向量要同时包含高度类特征和冲击类特征分类器才有足够的信息做区分。5. 分类器训练与异常识别阈值、SVM与LSTM三条路5.1 阈值级联先判断冲击再判断姿态阈值法是所有方案里最直观、也最容易调试的起点。跌倒可以拆成一个事件链先有快速下坠的冲击合成加速度峰值超过阈值然后出现低质心、大倾角的姿态最后持续一段时间接近静止。把这三个条件串成级联判断比单一阈值可靠得多。% 阈值级联跌倒检测 g 9.8; smaPeak max(sma); % 当前窗口合成加速度峰值 normH centerH / standH; % 当前窗口质心高度比 angleDeg rad2deg(angle); % 当前窗口躯干倾角 isImpact smaPeak 2.8 * g; % 条件1出现冲击 isLowPos normH 0.4; % 条件2质心明显降低 isHorizon angleDeg 60; % 条件3躯干接近水平 if isImpact isLowPos isHorizon alarm true; else alarm false; end三个阈值的设定依据是数据分布而不是拍脑袋。把训练集里所有跌倒样本的smaPeak做直方图取5%分位点作为冲击阈值质心高度比取正常站立数据的均值减三倍标准差。这样设定的阈值有统计依据换数据集时只需重新计算即可。提示2.8g只是经验起步值。实际佩戴位置在腰部时冲击峰值通常能到3g以上在手腕时可能只有2g因为手臂先着地缓冲了一部分。阈值必须按佩戴位置重新标定。5.2 SVM分类器用特征向量替代手工阈值阈值法的缺点在于难以处理特征之间的复杂组合。SVM可以把特征空间里线性的、非线性的边界学出来。Matlab里用fitcsvm即可完成配合交叉验证和网格搜索选择超参数。% 假设X是特征矩阵y是标签0正常1跌倒 rng(42); % 使用RBF核标准化特征 mdl fitcsvm(X, y, ... KernelFunction, rbf, ... Standardize, true, ... ClassNames, [0, 1]); % 5折交叉验证 cvmdl crossval(mdl, KFold, 5); loss kfoldLoss(cvmdl); fprintf(交叉验证损失: %.3f\n, loss); % 网格搜索C和gamma [C, gamma] meshgrid(2.^(-2:2), 2.^(-4:0)); score zeros(size(C)); for i 1:numel(C) m fitcsvm(X, y, KernelFunction, rbf, ... BoxConstraint, C(i), KernelScale, sqrt(1/gamma(i)), ... Standardize, true, KFold, 5); score(i) kfoldLoss(m); end [minVal, minIdx] min(score(:)); bestC C(minIdx); bestGamma gamma(minIdx);这里有个值得注意的地方跌倒样本远少于正常样本时SVM会偏向多数类表现为所有窗口都判正常。解决方法是设置Prior或Cost参数人为提高跌倒类别的误分代价。fitcsvm的Cost矩阵可以指定两类错误的实际代价例如把跌倒漏检代价设为正常误报的5倍。5.3 LSTM深度模型处理连续时序数据当传感器采样率较高、行为片段较长时滑窗统计特征会丢失时间顺序信息这时可以用LSTM直接吃原始时间序列。Matlab里用bilstmLayer可以让网络同时看到时刻前后的上下文对姿态转变类事件更敏感。% 构建BiLSTM分类网络 layers [ sequenceInputLayer(3) % 输入三轴加速度 bilstmLayer(64, OutputMode, last) % 双向LSTM输出最后时间步 dropoutLayer(0.3) % 防止过拟合 fullyConnectedLayer(2) softmaxLayer classificationLayer ]; % 训练选项 options trainingOptions(adam, ... InitialLearnRate, 0.005, ... MiniBatchSize, 32, ... MaxEpochs, 30, ... GradientThreshold, 1, ... ValidationData, {XVal, YVal}, ... Plots, training-progress, ... Verbose, false);LSTM训练有个现实的痛点样本量不够时比SVM更容易过拟合。如果训练集里跌倒样本只有几十条输出层之前加dropout层还不够可以用数据增强比如对加速度信号加小幅随机噪声、时间轴随机拉伸。现在不少AI辅助编程工具也能直接生成这类训练脚本代码能帮你搭框架但验证逻辑必须自己逐段确认尤其是数据切片时不能把同一样本的相邻窗口同时放进训练集和验证集否则评估结果会虚高。6. 现场验证与误报抑制让检测系统真正可交付6.1 用混淆矩阵验证而不只是看准确率跌倒检测的评估指标首选混淆矩阵。准确率在这个场景里没有意义因为正常行为占绝大多数模型全判正常也能有95%以上的准确率。需要重点看的是真正例率跌倒检出率和假正例率正常误报为跌倒的比例。% 计算敏感性和特异性 cm confusionmat(YTest, YPred); TP cm(2,2); FN cm(2,1); FP cm(1,2); TN cm(1,1); sensitivity TP / (TP FN); % 跌倒检出率 specificity TN / (TN FP); % 正常被正确保留的比例工程上跌倒漏检的后果远严重于误报一次。宁可让灵敏度达到95%以上、特异性略微牺牲也不要反过来。后处理阶段再通过逻辑把部分误报过滤掉。6.2 滞回比较用连续帧一致性抑制单帧误报单帧判断存在的典型问题弯腰系鞋带、猛地坐上沙发都可能触发一次跌倒判断。常见做法是采用滞回比较。跌倒触发需要一个持续过程正常动作往往只有一两个窗口满足条件而真正的跌倒会连续多个窗口满足。% 滞回比较连续M个窗口超过阈值才报警 M 3; count 0; alert false; for i 1:length(probVec) if probVec(i) 0.7 count count 1; else count max(0, count - 1); % 轻微衰减而非直接清零 end if count M alert true; break; end end这里的衰减策略值得注意。如果单次不满足条件就清零会让报警在临界状态下反复开断采用衰减机制既滤除孤立抖动又保留持续异常状态。6.3 现场部署的两个落地技巧摄像头安装角度对视觉方案的检出率影响很大。正俯视角下人体关键点容易被压缩成团特征失真侧视角下倾角特征最清晰。实践中比较稳妥的做法是将摄像头安装在2.5米到3米高度俯角30到45度尽量让画面中的人体侧面朝向镜头。报警系统不要只输出一个布尔值。工程实现里值得多做一步保留报警触发前5秒和后5秒的视频或IMU数据缓存事件带上时间戳、置信度和原始信号切片。这个事件回放能力在实际交付时比模型精度更影响用户是否愿意长期开启这个功能。本文还有配套的精品资源点击获取