ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于KTH数据集与MATLAB的人体动作识别实战:从HOG特征到SVM分类

基于KTH数据集与MATLAB的人体动作识别实战:从HOG特征到SVM分类 简介这是一份面向毕业设计的MATLAB人体动作识别资料包基于公开的KTH数据集实现步行、跑步、跳跃、挥手、坐下和站立等六类动作的识别流程。内容覆盖视频帧读取、灰度化与尺寸标准化等预处理HOG与光流特征提取SVM分类器训练与准确率评估并带有可交互界面。包内共94个文件以62张动作帧JPG图像和19个M源代码文件为主另有MAT数据文件保存真值标签与训练特征FIG/PNG用于展示实验图表AVI为KTH样本视频HTML为代码说明整体约19.49MB。目前已有161人学习下载适合需要快速搭建动作识别实验、掌握视频处理与机器学习结合方法的计算机视觉方向学生参考。1. 用MATLAB和KTH数据集做人体动作识别到底在研究什么人体动作识别Human Action Recognition, HAR这几年在计算机视觉里被反复提起但很多初学者拿到KTH这类经典数据集后第一反应往往是这不就是把视频帧丢进神经网络里让它自己学吗实际动手做一次你会发现最耗时间的根本不是搭建网络而是如何把一段段视频转成可计算的时空特征、如何在MATLAB里管理不同长度的帧序列、以及如何让分类器在动作类内差异大、类间差异小的KTH数据上拿到能写进论文的结果。KTH数据集包含6类动作走路、慢跑、跑步、拳击、挥手、拍手由25个人在4种场景下拍摄总计599段视频。它最大的特点是每个动作都有明显的周期性对传统手工特征如时空兴趣点、光流直方图和深度学习模型都适用。本文沿着数据预处理 - 特征提取 - 分类器设计 - 实验评估这条工程主线来展开使用的工具是MATLAB不依赖外部深度学习框架。对于做毕业设计的人来说这套流程的好处是每个环节都可以单独可视化、调参、写进论文且对硬件几乎没有要求。下面先从最关键的数据准备工作说起因为KTH的视频文件并不是拿来就能直接用的。2. KTH视频数据的载入、抽帧与基础预处理2.1 理解KTH数据集的目录结构和视频编码特征KTH数据集解压后通常按person01_boxing_d4_uncomp.avi、person02_walking_d1_uncomp.avi这样的规则命名。名称中的personXX代表受试者编号boxing/walking等是动作类别d1~d4是场景序号uncomp表明这是未压缩的AVI格式方便直接用VideoReader读取。需要注意MATLAB 的VideoReader对不同编码格式的支持是有限的。KTH官方提供的是未压缩AVI在Windows和Linux上的MATLAB里基本都能直接读。如果遇到读不出来的情况最常见原因是系统中缺少对应的解码器解决办法是用FFmpeg重新转码为MPEG-4或Motion JPEG格式而不是去修改代码逻辑。% 读取单个KTH视频文件并输出基本信息 v VideoReader(person01_boxing_d1_uncomp.avi); fprintf(视频帧数: %d\n, v.NumFrames); fprintf(帧宽: %d, 帧高: %d\n, v.Width, v.Height); fprintf(帧率: %.2f\n, v.FrameRate);这段代码的核心作用是验证MATLAB是否能正常解码该视频文件。如果NumFrames返回 -1 或读取时报错说明当前环境不支持这种编码格式。在写批量处理脚本之前先跑通这一句否则后面所有环节都会卡住。2.2 抽帧策略均匀采样与光流计算的取舍KTH数据集的分辨率是160x120帧率25fps每段视频长度约4秒。做动作识别时极少有人把全部帧都送进模型原因有两个一是相邻帧之间信息冗余度极高二是传统特征比如光流计算复杂度与帧数成正比。常用的做法是均匀抽帧每段视频抽取固定的帧数比如16帧或32帧这样可以保证输入到分类器的特征维度是一致的。% 均匀抽帧从视频中抽取 N 帧返回灰度图像序列 function frames extractUniformFrames(videoPath, N) v VideoReader(videoPath); totalFrames v.NumFrames; if totalFrames N % 帧数不足时用重复最后一帧的方式补齐 idxs [1:totalFrames, ones(1, N-totalFrames)*totalFrames]; else idxs round(linspace(1, totalFrames, N)); end frames zeros(v.Height, v.Width, N, uint8); for i 1:N frame read(v, idxs(i)); frames(:,:,i) rgb2gray(frame); end end这里的linspace(1, totalFrames, N)是均匀抽帧的关键参数。如果N取16则从视频的首帧到末帧等间隔地取16个位置这样既保证覆盖了整个动作周期又避免了连续的重复信息。read(v, idxs(i))是随机读取在循环中并不会重头播放视频所以即使抽帧位置不连续也不会漏帧。需要注意的是KTH数据的原始帧尺寸较小在做光流或HOG特征提取前通常先双线性插值缩放到固定尺寸比如128x128。这能降低边界干扰同时让后续的特征维度更稳定。2.3 前景提取与背景减除的必要性KTH数据集的场景大多是静态的背景基本不变前景就是运动中的人体。直接用原始灰度图做特征提取会把墙、门、地面这些不携带动作信息的像素也算进去导致分类器学到的是这个人在哪而不是这个人在做什么。所以工程上会先做背景建模把运动区域裁剪出来再做后续处理。MATLAB中做前景提取最直接的是帧差法或高斯混合模型GMM。帧差法适合起步计算量小但容易在人体运动慢时产生空洞。GMM对慢运动更鲁棒不过在初试阶段帧差法加形态学闭运算已经能拿到不错的效果。% 基于帧差法的前景掩码提取 function mask getForegroundMask(frames, threshold) refFrame double(frames(:,:,1)); % 以第一帧为参考背景 current double(frames(:,:,end)); diff abs(current - refFrame); mask diff threshold; % 形态学闭运算填补人体内部的空洞 se strel(disk, 3); mask imclose(mask, se); mask imfill(mask, holes); endthreshold是这里最需要调的参数通常在15到30之间灰度值范围0~255。取值过小背景的微小抖动会被判为前景产生大量噪声点取值过大人体四肢的浅色区域会被漏掉导致掩码不完整。你可以把每段视频的掩码用imshow(mask)逐一显示根据目测效果确定阈值。提示KTH数据集中存在部分视频的人物与背景对比度很低比如白衣人在白墙前此时单一阈值会失效建议改为自适应阈值graythresh或直接在原始灰度图上提取方向梯度特征不做前景分离。3. 特征工程从HOG到时空运动描述子3.1 为什么毕业设计不直接用视频帧作为特征很多人在毕业设计里尝试直接把下采样后的灰度帧拼接成向量用SVM分类结果准确率卡在70%以下。原因在于原始像素对光照、视角、衣着颜色过于敏感而KTH数据集里同一动作在不同人身上、不同场景中底层视觉差异远超动作本身的差异。特征工程的目的就是把这些无关变量剔掉只保留运动模式。在MATLAB中计算机视觉工具箱提供了extractHOGFeatures函数可直接从灰度图像中提取HOG描述子。HOG统计的是局部区域内梯度方向的分布对光照变化不敏感对人体的轮廓和四肢姿态却描述得很好。KTH中的动作拳击、挥手、拍手主要区别在上半身的姿态变化走路、慢跑、跑步则区别在腿部运动频率和幅度这些信息恰好是HOG能捕捉的。% 提取单帧HOG特征 img imresize(frames(:,:,i), [128, 128]); cellSize [8 8]; % 每个cell大小 hog extractHOGFeatures(img, CellSize, cellSize, BlockSize, [2 2]);CellSize决定了特征的分辨率。8x8的cell在128x128的输入图上会得到16x16的cell网格最终特征维数在几千数量级。如果把CellSize改成 [16 16]特征维度会大幅下降但空间细节也会丢失对拳击这类上半身小幅度动作会明显不利。反过来用 [4 4] 会让维度爆炸训练时长剧增而准确率提升有限。3.2 单帧特征到视频级特征的聚合方法拿到每帧的HOG向量后需要把一段视频的所有帧特征合并成一个全局特征向量才能交给分类器。最简单的聚合方法是取平均但会造成时间信息的丢失。比如慢跑和跑步的区别主要在运动周期快慢上单纯平均会抹平这种速度差异。更常用的方案是采用分块时序统计。把抽出的N帧分成三段前段、中段、后段对每段分别计算HOG均值与标准差最后拼接成超向量。这样既保有一定的时序结构又不会让特征维度变得无法管理。% 视频级特征聚合每段视频拼接一个特征向量 function featVector videoFeatureAggregation(frames) numFrames size(frames, 3); segLen floor(numFrames / 3); feats []; for s 1:3 segFrames frames(:,:,((s-1)*segLen1) : min(s*segLen, numFrames)); segHog zeros(1, 0); for i 1:size(segFrames, 3) img imresize(segFrames(:,:,i), [128, 128]); hog extractHOGFeatures(img, CellSize, [8 8]); segHog [segHog; hog]; % 行拼接 end segMean mean(segHog, 1); segStd std(segHog, 0, 1); feats [feats, segMean, segStd]; end featVector feats; end这段代码把每段视频的特征维度从单个HOG维度 * N帧压缩为单个HOG维度 * 2 * 3在保留了动作阶段信息的同时大幅降低了过拟合风险。如果你对运行时序特征有更高要求可以在分段后叠加光流直方图不过这会显著增加计算量需要根据毕设时间安排取舍。3.3 光流方向直方图补充运动方向信息HOG描述的是静态姿态光流描述的是运动方向和幅度。KTH数据集最有价值的地方在于动作模式相对规整运动方向的可分性很强跑步是水平方向主运动挥手是垂直方向为主。MATLAB中可以用opticalFlowLK或者opticalFlowFarneback来计算稠密光流。% 使用Farneback光流计算并生成方向直方图 flow opticalFlowFarneback; for i 1:size(frames, 3)-1 imgA im2double(frames(:,:,i)); imgB im2double(frames(:,:,i1)); estimateFlow(flow, imgA); estimateFlow(flow, imgB); magnitude flow.Magnitude; direction flow.Orientation; % 弧度值 % 将方向量化到9个bin binIdx max(1, min(9, floor((direction pi) / (2*pi/9)) 1)); histFeat accumarray(binIdx(:), magnitude(:), [9 1]); % 归一化 histFeat histFeat / (sum(histFeat) eps); end光流直方图的核心是把每个像素的运动方向映射到离散的bin中并用该像素的运动幅度作为加权值。opticalFlowFarneback的参数如NumIterations、NeighborhoodSize会影响光流密度和计算速度默认值在KTH数据集上已经够用。如果实验中发现慢跑和跑步的分类混淆严重可以尝试提高光流计算的层数金字塔层数从3增加到5这能捕捉更大尺度的运动。4. 用MATLAB搭建KTH动作识别的最小分类系统4.1 选型多分类SVM是毕业设计最稳的起点在特征已经提取完毕的前提下分类器的选择直接影响最终论文的对比实验部分。K近邻KNN实现最简单但准确率偏低随机森林调参容易但在高维特征上表现平庸深度学习入门门槛高在KTH这种小数据集上容易过拟合。多分类SVM采用一对多的编码设计是动作识别论文中出现频率最高的组合原因是它天然适合中等规模样本、高维稀疏特征并且在MATLAB里有现成的fitcecoc函数。KTH训练集通常选用前16个人的视频测试集选用后9个人的视频。这个划分原则必须保证训练集和测试集的人员不重叠否则会出现身份泄露同一人的不同视频片段同时出现在训练和测试中导致准确率虚高到98%以上。% 使用fitcecoc训练多分类SVM % trainFeatures: MxN 矩阵M为视频片段数N为特征维数 % trainLabels: Mx1 分类标签向量 t templateSVM(KernelFunction, rbf, BoxConstraint, 1, KernelScale, auto); mdl fitcecoc(trainFeatures, trainLabels, Learners, t, Coding, onevsone);BoxConstraint是最关键的参数它控制错误分类的惩罚力度。值越大决策边界越复杂容易过拟合值越小边界越平滑容易欠拟合。KTH数据集特征维度高但样本量只有几百通常建议从0.1开始尝试观察交叉验证准确率的曲线。KernelScale设为auto时MATLAB会用启发式方法自动估计RBF核的宽度这比手动指定固定值更省心不过会在训练时增加少量计算开销。4.2 训练集构建与标签管理在进入fitcecoc之前需要把从600余段视频中提取的特征和标签正确组织成矩阵。一个常见错误是把所有视频的特征直接拼接而忘记记录每个特征向量对应的动作类别导致后面无法评估模型。% 构建训练数据集 trainFeatures []; trainLabels []; actionNames {boxing, handclapping, handwaving, jogging, running, walking}; for p 1:16 % 前16人作为训练 for a 1:length(actionNames) action actionNames{a}; files dir(fullfile(KTH, sprintf(person%02d_%s_*, p, action))); for f 1:length(files) videoPath fullfile(files(f).folder, files(f).name); frames extractUniformFrames(videoPath, 16); feat videoFeatureAggregation(frames); trainFeatures [trainFeatures; feat]; trainLabels [trainLabels; categorical({action})]; end end end这段代码中的dir(sprintf(...))模式匹配利用了KTH文件名中的规律比如person01_boxing_d1_uncomp.avi和person01_boxing_d2_uncomp.avi都会被匹配到。这里建议将HOG特征提取部分单独写成函数因为每次运行都会重新读取视频并提取特征耗时长可以把中间结果保存为.mat文件后续调参时直接load即可。4.3 测试集评估与混淆矩阵训练完成后对后9个人的视频提取同样的特征用predict函数获得预测结果再与真实标签比较。不要只看整体准确率要打印出混淆矩阵因为KTH数据集中跑和走两类动作的混淆度通常最高混淆矩阵能帮你定位问题出在哪个动作对。% 测试集评估 testFeatures []; testLabels []; % ... 与训练集相同的特征提取逻辑 ... predLabels predict(mdl, testFeatures); acc mean(predLabels testLabels); fprintf(测试集准确率: %.2f%%\n, acc*100); figure; confusionchart(testLabels, predLabels);confusionchart会自动生成带颜色深浅的混淆矩阵图这个图可以直接用于毕业设计论文。KTH数据集在这种传统特征SVM的框架下准确率通常在85%~93%之间具体取决于特征设计和参数如果能超过90%说明特征提取设计得比较到位。提示如果你发现混淆矩阵里跑步和走路互相混淆不要急着调SVM参数优先回头检查光流直方图的时间聚合方式。可以考虑把光流特征单独可视化看两段视频在特征空间中的距离是否真的可分。5. 实验评估与毕业设计答辩必备的对比基准5.1 交叉验证策略留出法 vs 留一法毕业设计论文里动作识别部分的实验设计是否严谨比最终准确率数字更重要。KTH数据集的标准评估协议是留出法即按人员ID划分训练集和测试集。但很多本科论文会在这个基础上加一组留一法Leave-One-Person-Out实验作为对比即在25个人中依次选1人作为测试、其余24人作为训练循环25次取平均准确率。留一法得到的准确率通常比留出法高1~3个百分点因为它使用了更多的训练样本。但这会让训练时间变成原来的25倍需要提前估算如果留出法训练一次要30秒留一法就是12.5分钟这在毕业设计的时间预算里还能接受。% LOPO留一法评估片段 personIDs 1:25; accList zeros(1, 25); for testID 1:25 trainIdx personIDs ~ testID; % 用 personIDs 划分特征矩阵... mdl fitcecoc(trainFeatures(trainIdx,:), trainLabels(trainIdx), ... Learners, t, Coding, onevsone); pred predict(mdl, testFeatures(~trainIdx,:)); accList(testID) mean(pred testLabels(~trainIdx)); end meanAcc mean(accList);LOPO实验还能额外输出每个测试人的准确率这比单一的平均准确率更有说服力。答辩时如果被问到你的方法在哪些人上表现不稳定你能直接针对准确率偏低的personID来分析原因——是帧率问题、动作幅度差异还是场景影响。5.2 特征组合实验与维度分析毕业设计论文中对比实验通常需要说明为什么最终选择这种特征组合。常见的做法是设置三组实验仅HOG特征、仅光流直方图、HOG光流拼接。用表格记录每组特征在相同SVM参数下的准确率。特征方案特征维度平均准确率训练时间秒HOG均值标准差约800088.3%18.6光流直方图约100082.1%5.2HOG 光流拼接约900091.7%24.3需要说明的是特征维度并越高越好。如果拼接后准确率没有明显提升反而训练时间翻倍那就要考虑做特征筛选比如用relieff算法计算特征权重保留topN特征。这既是论文的加分项也能让分类器训练更快、泛化更好。有些同学会在论文里声称用了PCA降维但如果只是把所有特征直接PCA到50维后果是准确率明显下降。KTH数据集的类内差异较复杂直接无监督降维会破坏类间判别信息。更合理的做法是先用LDA线性判别分析监督降维到5维类别数-1再送入SVM。LDA在MATLAB里的实现很简单LDA函数在统计工具箱中可直接调用不过需要注意的是它要求特征数小于样本数因此在PCA降维后再做LDA是常见组合。5.3 毕业设计论文中的结果表述技巧最终的实验结果部分准确率数字只是基础更重要的是分析错误模式。答辩时老师大概率会问为什么跑步和慢跑容易混淆此时你需要能从特征层面作答跑步和慢跑的运动频率差异不大而KTH数据集中的帧率只有25fps抽16帧后每帧间隔约100毫秒这导致光流时间窗口内的累计位移差异不够明显如果增加每秒采样帧数或使用更长时间窗口区分度会上升。另外可以准备一张特征可视化图用TSNE或PCA将HOG特征投影到二维平面不同颜色表示不同动作类别。这张图能直观展示特征的可分性比任何文字描述都有说服力。6. 进阶技巧用TimeSformer替代手工特征的验证路径在毕业设计中如果你的选题偏向深度学习方向或想在期末赶上新方向可以考虑把前面手工特征SVM的框架当作baseline再引入TimeSformer一个基于Transformer的视频理解模型作为对比。之所以在这个阶段才提深度学习是因为KTH数据集只有599段视频直接用VideoMAE或SlowFast从头训练会严重过拟合。TimeSformer的优势在于它把视频分成时空patch后用注意力机制建模长程运动关系在KTH这种规模的数据上反而可以在预训练权重的基础上做微调达成不错的迁移效果。在MATLAB中直接实现完整的TimeSformer训练并不方便但可以借助MATLAB的深度学习工具箱加载ONNX模型或者用MATLAB调用Python环境中的PyTorch模型。常见做法是用Python训练好TimeSformer模型通过ONNX导出后在MATLAB中对特征提取结果做一致性对比。这里更推荐的做法是只做推理验证% 加载ONNX格式的TimeSformer模型到MATLAB net importNetworkFromONNX(timesformer_kth.onnx); % 输入尺寸通常为 (numFrames, Height, Width, Channels) inputData zeros(8, 224, 224, 3, single); output predict(net, inputData); % output 的最后一维是类别得分 [~, predIdx] max(output);importNetworkFromONNX是深度学习工具箱提供的函数能直接导入外部的ONNX模型。这里有两个常见问题一是KTH的原始视频分辨率只有160x120如果直接放大到224x224姿态会变糊建议先做双三次插值再送入模型二是TimeSformer的输入通常是8帧或32帧帧数不同会直接影响网络的时序注意力长度需要与你训练时的设置保持一致。在毕业设计论文里你可以在实验章节放一张红外热力图用Grad-CAM展示TimeSformer在KTH视频上关注的注意力区域。这个图能直观说明深度学习模型的决策依据与手工特征SVM方案形成互补。最终的结论部分强调TimeSformer更强大但在工业界的可解释性和部署成本上远不如手工特征方案两者不是互相取代的关系而是在不同限制条件下各有适用场景。本文还有配套的精品资源点击获取
返回列表