资讯动态

基于Matlab的人体异常行为检测:背景建模+HOG+SVM实现跌倒预警

发布时间:2026/9/17 3:43:50 来源:尧图企业网站定制
简介这套基于Matlab的人体异常行为检测源码面向智能监控与智慧养老场景利用计算机视觉识别快跑、慢跑、跌倒等异常动作适合具备一定编程基础的研究者学习主动监控系统的搭建。资源包共756个文件大小8.82MB其中以741张jpg样本图像为主搭配6个m源码文件、3个avi演示视频、fig界面文件以及doc/txt说明文档便于从数据、代码到界面演示完整对照学习。目前已有349人学习下载通过该源码可掌握基于Matlab的行为识别思路、GUI交互界面设计方法以及从图像序列到动作判别的实现流程还可在实际监控画面中进行扩展验证。1. 从“被动回放”到“主动报警”这套 Matlab 代码在做什么你手上这份基于 Matlab 的人体异常行为检测源代码解决的不是“监控里有没有人”而是“监控里的人怎么了”。它会把画面中的行走、慢跑、快跑、跌倒区分开一旦出现跌倒这类异常姿态就触发提示。这正好对应空巢老人、医院走廊、养老院等场景传统监控只能事后回放而主动预警需要在人摔倒后几秒内就通知到值班端。我拿到这个项目时第一件事不是看算法而是打开 Main_Test.fig因为这个图形界面决定了代码是从视频文件读帧还是从摄像头实时取流。对正在做课程设计、毕业设计或者想给现有监控系统加一层智能判断的工程师来说这份源码的价值在于它用 Matlab 传统视觉工具箱完成了从特征提取到分类报警的完整闭环没有依赖深度学习框架也更容易改造成自己的逻辑。2. 动作特征怎么来帧差、背景建模与 HOG 的取舍2.1 为什么固定机位下先做背景减除而不是直接上目标检测样本视频里“1步行.avi”“2慢跑.avi”“3快跑.avi”都是固定机位拍摄背景基本不变。这种场景下最划算的做法是背景减除先让模型学习若干帧纯净背景再用当前帧减去背景留下变化区域。现在很多人习惯上来就调 YOLO但那是另一套工程需要标注数据、训练权重、处理目标框抖动。传统视觉在固定相机下反而更稳定而且每一步都能可视化方便你向评委解释“跌倒到底是怎么判断出来的”。即使你之后要转向深度学习 matlab 的方案先理解背景建模和姿态特征也有助于设计更有效的输入特征。2.2 用 vision.ForegroundDetector 建立背景模型并做形态学清洗Matlab 的 Computer Vision Toolbox 里vision.ForegroundDetector是基于高斯混合模型的前景检测器。我的习惯是先读入视频给检测器 20 帧左右训练背景再用形态学开闭运算去掉噪声点。下面是核心代码% 读取慢跑视频样本 videoReader VideoReader(2慢跑.avi); % 高斯混合背景模型 foregroundDetector vision.ForegroundDetector(... NumTrainingFrames, 20, ... InitialVariance, 30*30, ... MinimumBackgroundRatio, 0.7, ... AdaptLearningRate, true); while hasFrame(videoReader) frame im2gray(readFrame(videoReader)); foreground foregroundDetector(frame); % 开运算去除孤立噪点闭运算填补人体区域空洞 foreground imopen(foreground, strel(disk, 3)); foreground imclose(foreground, strel(disk, 5)); imshow(foreground); drawnow; end逻辑说明im2gray将 RGB 转为灰度减少计算量strel(disk,3)定义半径为 3 的圆形结构元素开运算先腐蚀后膨胀能清除小噪点闭运算先膨胀后腐蚀能连接同一人体区域断裂的碎片。参数需要根据视频分辨率调整分辨率越高结构元素半径可以适当加大否则人体边缘会被削掉。NumTrainingFrames如果是 5背景模型还没学完就进入检测很容易把整体画面都当成前景。2.3 用 regionprops 提取宽高比、重心高度和 HOG 描述子背景减除得到的是二值图接下来要把它变成可判别的数值特征。最常用的就是连通区域分析找到面积最大的目标提取它的边界框、质心、主轴长度等几何量。% 对二值前景图做连通域分析 stats regionprops(foreground, Area, BoundingBox, Centroid); if ~isempty(stats) [~, idx] max([stats.Area]); box stats(idx).BoundingBox; % [x, y, width, height] centroid stats(idx).Centroid; % 人体重心位置 aspectRatio box(3) / max(box(4), 1); % 宽高比防止除零 heightDrop centroid(2); % y 越大表示中心越靠近画面底部 disp([宽高比: , num2str(aspectRatio)]); end说明BoundingBox返回[x, y, w, h]其中w/h在站立时通常小于 1人在跌倒后横躺w/h会迅速变大。Centroid的y坐标方向是从图像顶部向下增长所以 y 值越大重心越低。除几何特征外我一般还会把人体裁剪区域做 HOG 特征提取用来区分慢跑和快跑时四肢摆动姿态的差异% 裁剪出人体区域 patch imcrop(frame, box); patch imresize(patch, [128 64]); % 统一尺寸 hogFeature extractHOGFeatures(patch, CellSize, [8 8]);CellSize决定了特征粒度。8×8 能保留较多边缘方向信息代价是特征维度更高训练慢一些如果追求速度可以改成 16×16。下表是这三类特征在项目里的定位对比特征计算耗时对跌倒敏感度对慢跑/快跑区分度是否能看门狗解释性宽高比极低高低是重心高度变化率极低高中是HOG 描述子中等中高否3. 跌倒和快跑是怎么被判出来的阈值规则与 SVM 分类器3.1 跌倒的几何特征突变和阈值条件跌倒不是瞬时动作它伴随着“先快速下坠、随后身体横躺、最后短暂静止”三个阶段。理解这个链条后阈值就不只是宽高比大于多少的问题还要考虑运动速度。我一般会维护一个长度为 5 的滑动窗口保存每一帧的aspectRatio和重心的 y 坐标ratioHistory [ratioHistory, aspectRatio]; centroidHistory [centroidHistory, centroid(2)]; if length(ratioHistory) 5 ratioHistory(1) []; centroidHistory(1) []; end % 重心下降速度最近 5 帧 y 坐标的平均差 fallSpeed mean(diff(centroidHistory)); if aspectRatio 1.6 fallSpeed 0.35 disp(检测到疑似跌倒触发报警); end逻辑说明aspectRatio 1.6表示人体宽度已经明显大于高度接近水平姿态fallSpeed 0.35排除掉原地躺下这种缓慢过程。注意fallSpeed的方向符号要和你自己定义的坐标轴一致图像坐标下 y 增大表示向下摔所以diff为正数。1.6和0.35是从样本视频中反复测出来的经验值如果摄像头安装得高画面里人体更小宽高比阈值可以适当降到 1.3如果摄像头贴近地面阈值要调高到 2.0 左右。3.2 用 fitcecoc 做慢跑、快跑、正常行走的四分类识别只靠宽高比区分慢跑和快跑很困难因为两者都是竖直姿态差异主要在四肢摆动频率和位移速度。项目里更适合的做法是对每一段连续视频提取一个固定长度的特征向量然后用 SVM 做分类。Matlab 里多分类 SVM 可以直接用fitcecoc它会自动拆分出一对一模型% 假设已经提取好所有样本视频的特征矩阵 % features: N x M每行是一个视频的统计特征 % labels: N x 1每个视频对应的动作标签 features [meanRatio, meanHog, meanSpeed, heightDropRate]; labels {walk; jog; run; fall}; svmTemplate templateSVM(... KernelFunction, rbf, ... KernelScale, auto, ... BoxConstraint, 1); mdl fitcecoc(features, labels, Learners, svmTemplate);参数说明KernelFunction换成rbf是因为特征之间不是线性可分KernelScale设为auto时Matlab 会依据训练样本分布自动估计尺度但我发现当样本量很小时这个自动值容易过拟合更稳妥的做法是先用fitcsvm对每一对动作做交叉验证找到合适的BoxConstraint。BoxConstraint越大边界越硬训练集准确率高但泛化差这里1是中等强度适合样本量在几十到几百的情况。特征meanHog如果直接把 HOG 向量做平均维度会太高更合理的做法是只取 HOG 能量均值或者用 PCA 降到 20 维。3.3 从 Main_Test.fig 的控件看懂数据流向图形界面是理解整个源码入口的关键。用guide Main_Test.fig打开后你会看到一个显示图像区的坐标轴、几个按钮以及一个文本框用于输出识别结果。典型的数据流是点击“开始检测”按钮触发回调回调内部创建VideoReader读取视频帧后调用 2.2 和 2.3 的特征提取函数再把特征值喂给 3.1 的阈值判断或 3.2 训练好的 SVM 模型最后把结果标签显示在文本框里。控件类型名称示例作用Axesaxes1显示视频当前帧或检测结果框Push ButtonBtnStart开始读视频Push ButtonBtnStop停止循环并释放对象Edit TextTxtResult显示当前动作标签源代码包里的 204.jpg、203.jpg、669.jpg 等图片实际上是 GUI 界面测试时的静态帧用于在拿不到视频时验证检测函数是否可以正常输出。你可以在回调里读取这些图片逐帧测试特征代码再切换回视频流。4. 源码导入与联调让步行、慢跑、快跑三个 avi 样本跑通4.1 工作目录与路径设置拿到源码包后先把整个文件夹放到纯英文路径下比如D:\behavior_detection然后启动 Matlab添加工作路径。这里最容易踩的坑是直接双击 avi 文件系统会自动打开一个不相关的媒体播放器而不是读入 VideoReader。cd(D:\behavior_detection); addpath(genpath(pwd)); % 检查是否能看到视频样本 videoReader VideoReader(1步行.avi); disp([视频帧数: , num2str(videoReader.NumFrames)]);addpath(genpath(pwd))的作用是把当前目录和所有子目录加入搜索路径因为源码里可能把函数子函数放在不同子文件夹少了这步就会报“Undefined function”。如果显示NumFrames为 0不是程序问题而是当前 Matlab 版本缺少对应解码器换用 R2023b 及以上版本通常能解决。4.2 三个样本如何对应不同的检测阈值源码包里三个视频分别代表正常、异常临界、异常三种状态。实际调参时我会先跑“1步行.avi”记录它在正常状态下的宽高比均值再跑“2慢跑.avi”和“3快跑.avi”看特征差异。视频动作预期宽高比重心下降速度适合的检测策略1步行.avi正常行走0.40.70.050.15仅记录基线2慢跑.avi轻度异常0.60.90.20.3阈值 SVM 并查3快跑.avi异常0.71.20.30.5SVM 主判阈值辅助注意这里快跑的宽高比比慢跑大是因为跑动过程身体前倾目标框宽度增加。若你的监控画面是俯视视角宽高比逻辑会完全相反必须把跌倒判断改成“人体区域高度突然减小且长宽比趋近 1”。也就是说这份源代码自带的参数不是通用常量而是从这三个角度拍摄的 avi 样本标定出来的。4.3 高频报错VideoReader 编码、工具箱未装、fig 回调解案我会把联调中的高频问题整理成检查顺序避免浪费时间。Undefined function vision.ForegroundDetector说明没安装 Computer Vision Toolbox。使用ver(vision)检查版本信息没有的话需要重新运行 matlab 安装程序勾选该工具箱。Cannot create VideoReader视频文件用了非法编码比如微信传给 Windows 的 avi 实际是 H.265。先用格式工厂转成 MJPEG 编码的 avi或者用ffmpeg -i input.avi -c:v mjpeg output.avi转码。Error while evaluating uicontrol Callback通常是 fig 里引用的某个函数文件不在路径下。使用which 函数名检查路径如果返回空白就把源码文件夹重新执行一遍addpath(genpath(pwd))。GUI 中文乱码这是 matlab 安装时系统区域与代码注释编码不一致造成的。建议用 R2023b 之后的版本并且在“预设项”里把语言改为 System Locale。5. 把视频文件输入改成实时摄像头主动监控落地的最后一步5.1 用 webcam 或 ipcam 替换 VideoReader源码里主循环基于VideoReader.readFrame()切换成摄像头取流后检测逻辑不用改变的是输入源。本地 USB 摄像头用webcam网络摄像头用ipcam。下面这段代码可以直接替换原项目中VideoReader的初始化部分% 本地 USB 摄像头 camera webcam(USB Camera); % 如果是海康等网络摄像机用 ipcam % camera ipcam(http://192.168.1.64:8080/video, admin, 123456); preview(camera); for k 1:300 frame snapshot(camera); frameGray im2gray(frame); % 下面的 foreground 提取逻辑沿用第 2 章代码 foreground foregroundDetector(frameGray); foreground imopen(foreground, strel(disk, 3)); foreground imclose(foreground, strel(disk, 5)); % 是否报警 if shouldAlert(frameGray, foreground) imwrite(frame, [alert_ datestr(now, yyyymmdd_HHMMSS) .jpg]); insertText(frame, [10 10], FALL DETECTED, FontSize, 18); end imshow(frame); end这段代码实现了主动监控最核心的闭环摄像头捕获帧背景模型提取人体区域阈值或 SVM 判断动作一旦发现跌倒就把报警帧写成alert_时间戳.jpg。注意foregroundDetector在实时场景下必须提前训练至少 20 帧所以我在进入循环前先采集了 30 帧纯背景来做模型初始化。datestr(now,...)生成的文件名能保证重复报警不会覆盖旧记录这个细节在项目答辩里很加分。5.2 报警帧的本地保存与提示保存报警帧不是随便存一下要控制频率同一事件连续 30 帧都在报警不应该存 30 张重复图片。我一般加一个冷却时间变量一旦触发报警记录当前时间戳接下来 5 秒内不再接受新的报警图片保存请求但检测逻辑继续运行。同时把报警信息通过sendmail或写日志的方式留给值班端查询。这样改造完成后这套基于 Matlab 的异常行为检测系统就不只是能读三个 avi 文件的演示源码而是可以接入到真实监控场景的主动预警终端如果你接下来打算把模型迁移到边缘设备也可以把这里的 HOG 特征导出到 ONNX再接嵌入式摄像头。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价