新闻详情

新闻详情

首页 / 资讯中心 / 详情

基于卷积神经网络的人体动作识别:从输入表示到模型训练与评估

发布时间:2026/9/19 22:38:00来源:尧图网络
基于卷积神经网络的人体动作识别:从输入表示到模型训练与评估
简介这份PDF为《基于卷积神经网络的人体动作识别》论文全文源自《计算机工程与设计》2019年第4期适合从事计算机视觉、深度学习方向的研究者与算法工程师参考。论文针对复杂场景下人体动作识别精度不高的问题提出融合改进的可变形部件模型DPMM与卷积神经网络CNN的识别算法将部件滤波器由5个增至8个以提升人体检测精度用加权求和方式完成特征融合并通过softmax分类器实现动作分类。包内含单个PDF文件共295KB可获取期刊论文全文的摘要、引言、算法原理、实验过程与结论等完整内容了解DPMM与CNN并行提取特征的具体实现思路以及在标准数据集和自搜集数据集上较传统机器学习方法提升约10个百分点的实验评估结果。目前已有261人学习适合需要研究动作识别算法融合策略或复现相关实验的读者。1. 人体动作识别为什么绕不开卷积神经网络视频里的人体动作识别难点不在“看清人”而在“看清人之后知道他在干什么”。单帧图像分类只能看到姿态摔倒、挥手、下蹲这些动作要靠时间上下文才能区分。卷积神经网络在此处的价值是用共享卷积核把空间特征和时间特征一起编码而不是手工设计光流特征再喂给分类器。一个完整的“基于卷积神经网络的人体动作识别”方案通常会包含三件事把视频变成可训练的张量、选一个能同时处理空间与时间的卷积结构、用带时序一致性的训练策略收敛。这套方法适合正在做行为分析、运动评估或视频内容理解的工程师。你会发现真正决定识别精度的往往不是网络有多深而是输入帧数、卷积核的时间宽度和验证方式。2. 人体动作识别输入表示把视频变成卷积神经网络能消费的张量2.1 视频拆帧与张量布局先定 T 再定分辨率拿到一段视频第一件事不是训练而是想清楚“每个样本到底输入多少帧”。常见做法是均匀抽帧。如果整段视频是 5 秒 30fps共 150 帧直接把全部帧塞进 3D 卷积神经网络显存会立刻爆掉。实际工程里我一般先设定 T8、16 或 32再把每帧缩放到 224×224形成一个[T, H, W, C]的序列。对某些每秒 30 帧的输入也可以用 ffmpeg 先抽帧再离线缓存避免训练时反复解码。下面用 OpenCV 和 PyTorch 实现一个等间隔采样import cv2 import numpy as np import torch def sample_frames(video_path, num_frames16, target_size(224, 224)): cap cv2.VideoCapture(video_path) total int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) if total 0: cap.release() raise ValueError(cannot open video: %s % video_path) indices np.linspace(0, total - 1, num_frames, dtypeint) frames [] for idx in indices: cap.set(cv2.CAP_PROP_POS_FRAMES, idx) ok, frame cap.read() if not ok: frame np.zeros((target_size[1], target_size[0], 3), dtypenp.uint8) frame cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) frame cv2.resize(frame, target_size) frames.append(frame) cap.release() frames np.stack(frames).transpose(0, 3, 1, 2) return torch.from_numpy(frames).float() / 255.0这个函数里有两个参数值得反复调整。num_frames决定了模型能观察多长时间的上下文16 帧在大多数单人动作上是一个合理起点8 帧适合手势这类短动作32 帧则明显加重显存负担。target_size影响空间细节和计算量的平衡224×224 是很多预训练网络的标准输入如果换用 MobileNet也可以降到 160×160 换取更快的迭代速度。采样方式同样重要均匀采样对完整片段有效但对流式摄像头输入会引入未来帧生产环境里必须改成固定长度的滑动窗口只用当前时刻之前的数据。2.2 三种输入表示的取舍单帧、多帧堆叠与双流基于卷积神经网络的人体动作识别输入不只是“连续帧”。下面这张表整理了我常用的三种表示以及它们适用的场景。输入表示时间信息计算成本典型表现适合场景单帧 RGB 批量分类无最低只能识别姿态无法区分“起身”和“坐下”预筛候选帧多帧 RGB 堆叠输入通道隐含低能捕捉帧间像素差但对运动模糊和视角敏感短动作、计算受限双流RGB 光流显式高光流通道能捕捉运动方向识别慢动作更稳定有离线光流预算的场景单帧输入严格说不是动作识别但是工程上常用来做级联的第一级把明显没有动作的帧过滤掉再交给时序模型。多帧堆叠实现最简单把 T 帧在通道维拼接成[3T, H, W]输入一个 2D CNN时间信息被当作不同通道的局部统计能学到一定运动模式却无法把同一个空间位置的跨帧关系显式建模。双流 CNN 把空间流和光流流分开卷积最后融合分数时间流对运动边缘更敏感但光流计算本身很费时实时场景通常要牺牲精度换取速度。只有当视频已经离线且标注量偏少时我才会优先尝试双流。如果选双流光流可以用 RAFT 这类网络预计算但要注意光流的尺度。常见做法是把光流的水平和垂直分量量化到[-20, 20]再归一化到[-1, 1]这比直接把原始浮点值喂给 CNN 稳定得多。直接输入未裁剪的光流会导致时间流梯度波动变快训练初期 loss 很难下降。2.3 骨架热图让卷积神经网络直接处理姿态输出如果系统里已经有人体姿态估计模型得到的是 17 个关键点坐标。这时常见做法不是把坐标拉平后接全连接而是把关键点重绘成高斯热图。热图保留了关节之间的空间距离关系还能作为多通道输入与 RGB 帧一起送进网络。import numpy as np import torch def joints_to_heatmap(joints, img_size224, sigma5): # joints: [num_joints, 2]坐标单位为像素顺序为 x, y h, w img_size, img_size heatmap np.zeros((joints.shape[0], h, w), dtypenp.float32) yy, xx np.meshgrid(np.arange(h), np.arange(w)) for k, (x, y) in enumerate(joints): heatmap[k] np.exp(-((xx - x) ** 2 (yy - y) ** 2) / (2 * sigma ** 2)) return torch.from_numpy(heatmap)sigma是唯一需要手动调的超参。sigma 太小时热图只有关键点附近几个像素有响应网络对姿态估计的坐标误差完全没有容错sigma 太大时两个相邻关键点的热图会重叠比如手肘和手腕类别边界变得模糊。我一般会把 sigma 设成关节距离的十分之一左右比如单人全身姿态中设为 58 像素。另一个容易踩的坑是时间维度上坐标抖动姿态估计器偶尔会漏检导致热图在某一帧突然消失。可以在训练时对帧索引做随机偏移 12 帧或者把漏检帧的热图直接置零让 CNN 学会忽略不稳定的关键点。2.4 时序增强随机丢帧和时间偏移在图像领域常用随机裁剪、翻转动作识别里更有效的增强是时间维度的扰动。随机丢帧的实现可以是在均匀采样后把indices加上一个随机噪声例如np.linspace(0, total-1, num_frames) np.random.uniform(-2, 2, num_frames)再取整并 clip。这样模型不容易记住“第 5 帧一定是在下蹲”这种伪规律。从我的经验看时间偏移幅度不超过帧间隔的两倍时既能增强鲁棒性又不会把动作语义破坏掉。同时要对空间方向做统一训练时随机水平翻转翻转后左右关键点的索引要同步交换如果不交换相当于用错误标签训练。这些细节和输入布局同样重要因为基于卷积神经网络的人体动作识别对数据分布的敏感度往往高于结构深度的增加。加了 MixUp 或 CutMix 在视频上效果不稳定建议先用基础增强跑通再逐步加。3. 从 LeNet-5 到 3D 卷积核动作识别里卷积神经网络结构怎么选3.1 时间维怎么引入卷积结构LeNet-5 是卷积神经网络基本结构里最被反复讲的例子卷积、池化、全连接。它用在图像上是 2D 卷积核。对动作识别最常见的误区是“多堆几帧就是视频”。把 T 帧拼到 C 维2D 卷积在通道上做线性组合时间维上的平移不变性仍然不存在。比如一个动作在第 3 帧开始还是第 7 帧开始通道拼接出来的特征完全不同这正是 3D 卷积要解决的问题。3D 卷积核尺寸是D×H×WD 遍历时间维每个输出位置同时聚合前后若干帧的空间块。一个工程技巧是把预训练 2D 卷积核“膨胀”成 3D把[C_out, C_in, H, W]复制 D 份再除以 D。这样做能让 3D 模型复用 ImageNet 特征收敛速度显著提升尤其在训练数据不足时。实现上注意 padding 的设置时间维通常padding(D-1)//2保证输入输出帧数不变。我一般建议在骨干网络前几层做膨胀后几层保持 2D 或使用 2D 全局池化这样既引入时序信息又不会让参数量膨胀到不可控。3.2 一个可直接运行的 3D CNN 代码骨架下面是一个适合动作识别起步的 3D CNN结构参考了 C3D 的基本思路但不追求大模型import torch.nn as nn class BasicConv3D(nn.Module): def __init__(self, in_c, out_c, kernel_size(3, 3, 3), stride1, padding(1, 1, 1)): super().__init__() self.conv nn.Conv3d(in_c, out_c, kernel_size, stridestride, paddingpadding) self.bn nn.BatchNorm3d(out_c) self.relu nn.ReLU(inplaceTrue) def forward(self, x): return self.relu(self.bn(self.conv(x))) class ActionCNN3D(nn.Module): def __init__(self, num_classes10, in_channels3, frames16): super().__init__() self.features nn.Sequential( BasicConv3D(in_channels, 32, (3, 3, 3)), nn.MaxPool3d(kernel_size(1, 2, 2), stride(1, 2, 2)), BasicConv3D(32, 64, (3, 3, 3)), nn.MaxPool3d(kernel_size(2, 2, 2), stride(2, 2, 2)), BasicConv3D(64, 128, (3, 3, 3)), nn.AdaptiveAvgPool3d((1, 1, 1)), ) self.classifier nn.Linear(128, num_classes) def forward(self, x): # x: [B, C, T, H, W] z self.features(x) return self.classifier(z.view(z.size(0), -1))BasicConv3D的kernel_size(3,3,3)意味着在时间、高、宽三个方向都看相邻 3 个位置。第一个MaxPool3d的 kernel 是(1,2,2)故意不在时间维下采样因为 16 帧本来就不多太早压缩时间会让短动作丢失。第二个池化用(2,2,2)把时间减半到 8把空间逐步降到更小的特征图。AdaptiveAvgPool3d把任意输入尺寸压到 1×1×1后面直接接线性分类层。这段代码里可以调整的地方如果显存不够把前两层通道改成 16/32或把frames降到 8如果动作时间跨度很长把第二个池化层的时间维 kernel 改成 1让时间特征保留更久。对只有几百到几千条样本的动作识别任务我不建议在网络最后再加宽大的全连接层数据量不够时过拟合比表示能力更常见。3.3 双流 CNN 与结构图里的关键标注双流结构有两个独立分支空间流输入单帧 RGB时间流输入光流堆叠最后在分类前融合。画一张可复现的卷积神经网络结构图时只画盒子不够我一般会要求每层旁边标出输入输出张量尺寸。下面这个表可以作为画图的标注模板。模块输入形状输出形状作用空间流 2D 主干[B,3,224,224][B,512,7,7]提取单帧外观和姿态时间流 2D 主干[B,20,224,224][B,512,7,7]提取光流运动特征全局池化各分支输出[B,512]降维融合层 Softmax[B,1024][B,C]分类注意时间流的输入通道数不是 3而是光流图像的通道数通常为 2水平与垂直位移也可能是多帧光流堆叠成 10 或 20 通道。训练双流网络时两个分支可以分别加载预训练权重然后对整个网络一起微调融合层的学习率设为主干的三分之一。这样做比端到端随机初始化稳定得多。如果发现空间流贡献远大于时间流可以检查光流是否因为尺度问题退化成噪声或者是否使用了错误的光流通道顺序。4. 训练人体动作识别模型损失函数、优化器与梯度裁剪的参数起点4.1 损失函数选择与类别权重动作识别数据集经常长尾例如“站立”出现几百次“跌倒”只有几十次。直接用CrossEntropyLoss模型会学习“都预测站立”。我一般先算逆类别频率权重weight median_freq / class_freq归一化后传给CrossEntropyLoss。另一个更温和的做法是标签平滑把真实标签从 1 变成 0.9其余类别分摊0.1/(C-1)防止面对相似动作时过分自信。对某些极难样本Focal Loss 的思路是把(1-p_t)^gamma作为调制因子gamma 通常取 2但会把训练轮数拉长因为模型一直被惩罚。我通常先用普通交叉熵跑通再换 Focal Loss 精调。4.2 一组可复用的训练超参与循环代码下面这组参数是我在单人动作识别上常用的起点。参数推荐起点范围说明optimizerSGDAdam 也可选视频任务里 SGD momentum 泛化更好初始学习率0.01SGD/ 0.001Adam0.0010.1批量增大时按 sqrt 比例提高weight_decay1e-41e-51e-3视频序列上不建议设太高label_smoothing0.10.050.2对相似动作类别有效batch_size8432受显存限制3D CNN 常用 8梯度裁剪 max_norm5.01.010.0防止时间维度梯度爆炸训练循环的骨架如下import torch import torch.nn as nn from torch.utils.data import DataLoader model ActionCNN3D(num_classes5).cuda() optimizer torch.optim.SGD(model.parameters(), lr0.01, momentum0.9, weight_decay1e-4) scheduler torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max50) criterion nn.CrossEntropyLoss(label_smoothing0.1) for epoch in range(50): model.train() total_loss 0.0 for videos, labels in train_loader: videos, labels videos.cuda(), labels.cuda() optimizer.zero_grad() logits model(videos) # [B, 5] loss criterion(logits, labels) loss.backward() nn.utils.clip_grad_norm_(model.parameters(), max_norm5.0) optimizer.step() total_loss loss.item() scheduler.step() print(epoch %02d loss %.4f % (epoch, total_loss / len(train_loader)))3D CNN 比 2D CNN 更容易梯度爆炸因为时间维的卷积展开次数更多链式求导会累积很多中间量clip_grad_norm_的max_norm5.0是常见起点。label_smoothing0.1对动作类别有轻微但有效的抑制过拟合作用。CosineAnnealingLR在视频分类里比 StepLR 更常见因为余弦退火对学习率的下降更平滑能缓解后期在局部最优附近的抖动。如果验证集 loss 在 20 轮内不下降首先检查数据采样而不是网络结构很多假性收敛来自训练/推理采样不一致。4.3 训练与推理不一致的典型坑视频动作识别中很多“复现不出来”不是结构有问题而是训练和推理输入不一致。训练时用密集采样或均匀采样推理时却从视频中间随机取帧这是最常见的误用。我一般把采样逻辑封装成一个独立函数在训练、验证、离线测试里都调用同一个版本。另一个问题是归一化均值方差。使用 ImageNet 预训练权重时要用 ImageNet 的mean[0.485,0.456,0.406]、std[0.229,0.224,0.225]而不是自己统计视频数据的均值和方差。如果自己统计分布会随数据集变化换数据集后权重全部失效。3D 卷积神经网络对 BN 的统计量更敏感因为同一个 batch 里可能包含同一视频的不同片段统计偏差更大必要时把 batch size 适当调大或使用 SyncBN。5. 用 Grad-CAM 和帧级评估验证动作识别模型学到的到底是动作还是背景5.1 帧级评估指标比准确率更接近真实场景动作识别通常关心两类错误把 A 动作误判成 B 动作以及把短暂动作漏掉。只看 top-1 准确率会掩盖长尾问题。我一般会同时看 top-1、top-5、加权 F1 和混淆矩阵。在跌倒检测这样的场景里召回率比精确率更重要因为漏报一次跌倒可能造成严重后果。可以通过调整分类阈值或对概率输出做偏置来迁移工作点。对一段 10 秒的连续视频真正上线时还要逐帧滑动窗口做推理这时要把重叠窗口的预测概率做平均而不是简单对最终类别投票。5.2 用 Grad-CAM 定位模型关注区域训练完成后我会用 Grad-CAM 检查模型是否真的在看人的肢体。对 3D CNN特征图带时间维Grad-CAM 计算出的也是三维激活图可以逐帧叠加到原视频上。model.eval() feature model.features[-1] # 取最后一个卷积输出 logits model(x) # x: [1,3,16,224,224] predicted_class logits.argmax(dim1).item() score logits[0, predicted_class] grad torch.autograd.grad(score, feature)[0] # [1,128,4,7,7] weights grad.mean(dim(2, 3, 4), keepdimTrue) cam (weights * feature).sum(dim1, keepdimTrue).relu() cam nn.functional.interpolate( cam, size(16, 224, 224), modetrilinear, align_cornersFalse)grad.mean(dim(2,3,4))是典型的 CAM 权重计算把每个通道上的梯度求平均再与特征图加权求和。trilinear插值把低分辨率激活图放大到输入分辨率。如果 CAM 集中在人体之外的背景说明模型靠场景统计过拟合此时应改用随机裁剪、换背景的数据增强或降低输入分辨率强制模型忽略背景细节。如果 CAM 在时间维上只集中在某一帧而动作本身跨越 8 帧以上说明网络没有真正利用时序上下文可以增大 3D 卷积核的时间尺寸或减少第一个池化层对时间的压缩。在最终发布前可以对相邻帧的类别概率做 5 帧滑动平均这样能直接滤掉单帧误报让输出类别保持时间连续。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

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

较早相关资讯

最新相关资讯

BrewUI:为Homebrew套上图形界面,让macOS包管理更直观 2026/9/19 23:20:07

BrewUI:为Homebrew套上图形界面,让macOS包管理更直观

提到 macOS 上的开发环境,Homebrew 是绕不开的一个词。装了它,装 Node、装 Redis、装各种命令行工具,基本就是一行 brew install 的事。但问题也出在这"一行命令"上——用久了你会发现,自己的终端里积累了一大堆不知道干…

阅读更多 →
Meteor 源码文档自动化:doctool.js 从 JS 注释生成 Markdown 文档的完整指南 2026/9/19 23:20:07

Meteor 源码文档自动化:doctool.js 从 JS 注释生成 Markdown 文档的完整指南

Meteor 源码文档自动化:doctool.js 从 JS 注释生成 Markdown 文档的完整指南 【免费下载链接】meteor Meteor, the JavaScript App Platform 项目地址: https://gitcode.com/gh_mirrors/me/meteor 导读 Meteor 仓库(Meteor, the JavaScript App …

阅读更多 →
2026年国内GitHub镜像站清单:加速clone、release下载与AI大模型部署 2026/9/19 23:20:07

2026年国内GitHub镜像站清单:加速clone、release下载与AI大模型部署

1. 为什么国内开发者需要一个靠谱的镜像站清单搞开发的人都有过这种体验:急着拉一个开源项目跑通验证,结果浏览器转了半天,最后甩给你一个连接超时的页面。尤其是做AI大模型本地部署、Docker镜像拉取、Python依赖安装这些活儿的时候&#xff…

阅读更多 →
BrewUI:Homebrew的SwiftUI原生图形界面 2026/9/19 23:20:07

BrewUI:Homebrew的SwiftUI原生图形界面

1. BrewUI:当Homebrew遇上SwiftUI,macOS终端工具终于有了“人样”你有没有在Mac上敲过几十遍brew install,只为装一个依赖?有没有盯着终端里滚动的编译日志发呆,等它跑完去干别的事,结果回来发现卡在某个co…

阅读更多 →
Hugo 模板函数 templates.Inner 详解:用 partial decorator 实现内容块注入与组合式布局 2026/9/19 23:20:07

Hugo 模板函数 templates.Inner 详解:用 partial decorator 实现内容块注入与组合式布局

Hugo 模板函数 templates.Inner 详解:用 partial decorator 实现内容块注入与组合式布局 【免费下载链接】hugo The world’s fastest framework for building websites. 项目地址: https://gitcode.com/gh_mirrors/hu/hugo templates.Inner 是 Hugo 0.154.0…

阅读更多 →
地下管廊智能照明节能控制系统设备配置、场景应用解析 2026/9/19 23:17:06

地下管廊智能照明节能控制系统设备配置、场景应用解析

一、概述 地下管廊空间结构复杂,涵盖综合舱、电力舱、燃气舱、变电所、设备间、监控中心等多种功能区域,各区域对照明控制方式的要求各不相同。传统管廊照明多采用“常亮模式”,照明能耗占管廊总运营能耗的近四成,电费占运营费用三…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

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

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