首页 游戏 软件 资讯 排行榜 专题
首页
AI
骨骼点动作识别-基于Paddle复现PoseC3D

骨骼点动作识别-基于Paddle复现PoseC3D

热心网友
32
转载
2025-07-23
本文介绍基于Paddle复现的PoseC3D模型,其以3D热图堆栈为人体骨架表示,用3D-CNN分类,较GCN方法在时空特征学习等方面更优。复现在UCF-101数据集上达87.05%的top1准确率,详述了网络结构、环境依赖、数据集、代码结构及训练测试等流程,还提及复现心得。

骨骼点动作识别-基于paddle复现posec3d - 游乐网

Revisiting Skeleton-based Action Recognition(PoseC3D 基于Paddle复现)

1.简介

人体骨架作为人类行为的一种简洁的表现形式,近年来受到越来越多的关注。许多基于骨架的动作识别方法都采用了图卷积网络(GCN)来提取人体骨架上的特征。尽管在以前的工作中取得了积极的成果,但基于GCN的方法在健壮性、互操作性和可扩展性方面受到限制。

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

在本文中,作者提出了一种新的基于骨架的动作识别方法PoseC3D,它依赖于3D热图堆栈而不是图形序列作为人体骨架的基本表示。与基于GCN的方法相比,PoseC3D在学习时空特征方面更有效,对姿态估计噪声更具鲁棒性,并且在跨数据集环境下具有更好的通用性。

此外,PoseC3D可以在不增加计算成本的情况下处理多人场景,其功能可以在早期融合阶段轻松与其他模式集成,这为进一步提升性能提供了巨大的设计空间。在四个具有挑战性的数据集上,PoseC3D在单独用于Keletons和与RGB模式结合使用时,持续获得优异的性能。

骨骼点动作识别-基于Paddle复现PoseC3D - 游乐网        

上图是网络架构,对于视频中的每一帧,首先使用两阶段姿势估计(检测+姿势估计)进行人体姿势提取。然后沿着时间维度堆叠关节或肢体的heatmap,并对生成的三维heatmap进行预处理。最后,我们使用3D-CNN对三维的heatmap进行分类。

2.复现精度

在UCF-101数据集上spilt1的测试效果如下表。

3.数据集

UCF-101以及预训练模型下载地址:

https://aistudio.baidu.com/aistudio/datasetdetail/140593

4.环境依赖

PaddlePaddle == 2.2.2

5.网络结构

从第一节的图中可以看到,网络的主要结构由Resnet中的Layer构成,网络结构代码如下:

class ResNet3d(nn.Layer):    arch_settings = {        50: (Bottleneck3d, (3, 4, 6, 3)),        101: (Bottleneck3d, (3, 4, 23, 3)),        152: (Bottleneck3d, (3, 8, 36, 3))    }
登录后复制

       

上述代码定义了ResNet3d的网络类,以及定义了不同层数网络的配置。

    def __init__(self,                 depth,                 pretrained,                 stage_blocks=None,                 pretrained2d=True,                 in_channels=3,                 num_stages=4,                 base_channels=64,                 out_indices=(3, ),                 spatial_strides=(1, 2, 2, 2),                 temporal_strides=(1, 1, 1, 1),                 dilations=(1, 1, 1, 1),                 conv1_kernel=(3, 7, 7),                 conv1_stride_s=2,                 conv1_stride_t=1,                 pool1_stride_s=2,                 pool1_stride_t=1,                 with_pool1=True,                 with_pool2=True,                 style='pytorch',                 frozen_stages=-1,                 inflate=(1, 1, 1, 1),                 inflate_style='3x1x1',                 conv_cfg=dict(type='Conv3d'),                 norm_cfg=dict(type='BN3d', requires_grad=True),                 act_cfg=dict(type='ReLU', inplace=True),                 norm_eval=False,                 with_cp=False,                 non_local=(0, 0, 0, 0),                 non_local_cfg=dict(),                 zero_init_residual=True,                 **kwargs):        super().__init__()        if depth not in self.arch_settings:            raise KeyError(f'invalid depth {depth} for resnet')        # 初始化网络参数        self.depth = depth        self.pretrained = pretrained        self.pretrained2d = pretrained2d        self.in_channels = in_channels        self.base_channels = base_channels        self.num_stages = num_stages        assert 1 <= num_stages <= 4        self.stage_blocks = stage_blocks        self.out_indices = out_indices        assert max(out_indices) < num_stages        self.spatial_strides = spatial_strides        self.temporal_strides = temporal_strides        self.dilations = dilations        assert len(spatial_strides) == len(temporal_strides) == len(            dilations) == num_stages        if self.stage_blocks is not None:            assert len(self.stage_blocks) == num_stages        # 保存卷积网络参数        self.conv1_kernel = conv1_kernel        self.conv1_stride_s = conv1_stride_s        self.conv1_stride_t = conv1_stride_t        self.pool1_stride_s = pool1_stride_s        self.pool1_stride_t = pool1_stride_t        self.with_pool1 = with_pool1        self.with_pool2 = with_pool2        self.style = style        self.frozen_stages = frozen_stages        self.stage_inflations = _ntuple(num_stages)(inflate)        self.non_local_stages = _ntuple(num_stages)(non_local)        self.inflate_style = inflate_style        self.conv_cfg = conv_cfg        self.norm_cfg = norm_cfg        self.act_cfg = act_cfg        self.norm_eval = norm_eval        self.with_cp = with_cp        self.zero_init_residual = zero_init_residual        self.block, stage_blocks = self.arch_settings[depth]        if self.stage_blocks is None:            self.stage_blocks = stage_blocks[:num_stages]        self.inplanes = self.base_channels        self.non_local_cfg = non_local_cfg
登录后复制

       

上述代码初始化网络的超参数。

        # 构建第一个 stem层        self._make_stem_layer()        self.res_layers = []        # 根据stage_blocks的内容构建网络。        # 这里的stage_blocks是(3, 4, 6)。        for i, num_blocks in enumerate(self.stage_blocks):            spatial_stride = spatial_strides[i]            temporal_stride = temporal_strides[i]            dilation = dilations[i]            planes = self.base_channels * 2**i            res_layer = self.make_res_layer(                self.block,                self.inplanes,                planes,                num_blocks,                spatial_stride=spatial_stride,                temporal_stride=temporal_stride,                dilation=dilation,                style=self.style,                norm_cfg=self.norm_cfg,                conv_cfg=self.conv_cfg,                act_cfg=self.act_cfg,                non_local=self.non_local_stages[i],                non_local_cfg=self.non_local_cfg,                inflate=self.stage_inflations[i],                inflate_style=self.inflate_style,                with_cp=with_cp,                **kwargs)            self.inplanes = planes * self.block.expansion            layer_name = f'layer{i + 1}'            self.add_sublayer(layer_name, res_layer)            self.res_layers.append(layer_name)        self.feat_dim = self.block.expansion * self.base_channels * 2**(            len(self.stage_blocks) - 1)
登录后复制

       

上述为构建网络的主要的代码,首先构建一个stem层,然后根据stage_blocks的内容,使用make_res_layer方法构建网络。

def make_res_layer(block,                       inplanes,                       planes,                       blocks,                       spatial_stride=1,                       temporal_stride=1,                       dilation=1,                       style='pytorch',                       inflate=1,                       inflate_style='3x1x1',                       non_local=0,                       non_local_cfg=dict(),                       norm_cfg=None,                       act_cfg=None,                       conv_cfg=None,                       with_cp=False,                       **kwargs):        inflate = inflate if not isinstance(inflate,                                            int) else (inflate, ) * blocks        non_local = non_local if not isinstance(            non_local, int) else (non_local, ) * blocks        assert len(inflate) == blocks and len(non_local) == blocks        downsample = None        # 判断是否需要进行下采样。当输入的通道和输出通道不相等,则根据planes * block.expansion缩减通道数。        if spatial_stride != 1 or inplanes != planes * block.expansion:            downsample = ConvBNLayer(                in_channels=inplanes,                out_channels=planes * block.expansion,                kernel_size=1,                stride=(temporal_stride, spatial_stride, spatial_stride),                bias=False,                act=None            )
登录后复制

       

上述代码为make_res_layer方法,其中包含判断block是否需要进行下采样。当输入的通道和输出通道不相等,则根据planes * block.expansion缩减通道数。在block模块中会对通道数进行缩减。

        layers = []        layers.append(            block(                inplanes,                planes,                spatial_stride=spatial_stride,                temporal_stride=temporal_stride,                dilation=dilation,                downsample=downsample,                style=style,                inflate=(inflate[0] == 1),                inflate_style=inflate_style,                non_local=(non_local[0] == 1),                non_local_cfg=non_local_cfg,                norm_cfg=norm_cfg,                conv_cfg=conv_cfg,                act_cfg=act_cfg,                with_cp=with_cp,                **kwargs))        inplanes = planes * block.expansion
登录后复制

       

构建网络,downsample作为参数传递进去。

        for i in range(1, blocks):            layers.append(                block(                    inplanes,                    planes,                    spatial_stride=1,                    temporal_stride=1,                    dilation=dilation,                    style=style,                    inflate=(inflate[i] == 1),                    inflate_style=inflate_style,                    non_local=(non_local[i] == 1),                    non_local_cfg=non_local_cfg,                    norm_cfg=norm_cfg,                    conv_cfg=conv_cfg,                    act_cfg=act_cfg,                    with_cp=with_cp,                    **kwargs))        return nn.Sequential(*layers)
登录后复制

       

上述根据blocks中的数量构建网络,这里的block为Bottleneck3d层。主要是用来构建一个在通道数上类似瓶颈的一个层,与ResNet系列网络一致。

class ConvBNLayer(nn.Layer):    def __init__(        self,        in_channels,        out_channels,        kernel_size,        padding=0,        stride=1,        dilation=1,        groups=1,        act=None,        bias=None,    ):        super(ConvBNLayer, self).__init__()        self._conv = nn.Conv3D(            in_channels=in_channels,            out_channels=out_channels,            kernel_size=kernel_size,            stride=stride,            padding=padding,            dilation=dilation,            groups=groups,            bias_attr=bias)        self._batch_norm = nn.BatchNorm3D(out_channels, momentum=0.1)        self.act = act        if act is not None:            self._act_op = nn.ReLU()
登录后复制

       

上述代码为网络的卷积的基本单元,通过该方法可以构建一个Conv3D+BN+Relu的结构。该结构也是Bottleneck3d模块的重要组成部分。

6.快速开始

训练:

In [ ]
%cd /home/aistudio/PaddlePoseC3D!python train.py --dataset_root ../data/data140593/ucf101.pkl \--pretrained ../data/data140593/res3d_k400.pdparams --max_epochs 12 \--batch_size 16  --log_iters 100
登录后复制    

dataset_root: 训练集路径

pretrained: 预训练模型路径

max_epochs: 最大epoch数量

batch_size: 批次大小

测试:

使用最优模型进行评估.

最优模型下载地址:

链接: https://pan.baidu.com/s/1J9_X_CNkXQbhBhj-xHHBDw

提取码: uq9m

In [ ]
!python -u test.py --dataset_root ucf101.pkl --pretrained best_model/model.pdparams
登录后复制    

dataset_root: 训练集路径

pretrained: 预训练模型路径

单张图片预测

输入文件v_BaseballPitch_g07_c01.pkl的视频如下图所示,同时可视化v_BaseballPitch_g07_c01.pkl文件。通过predict.py可预测出该文件的所属分类。

In [3]
%cd /home/aistudio/PaddlePoseC3D!python predict.py --input_file v_BaseballPitch_g07_c01.pkl \--pretrained best_model/model.pdparams
登录后复制        
/home/aistudio/PaddlePoseC3D/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/setuptools/depends.py:2: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses  import impLoading pretrained model from best_model/model.pdparamsThere are 217/217 variables loaded into Recognizer3D.File v_BaseballPitch_g07_c01 is class BaseballPitch
登录后复制        
骨骼点动作识别-基于Paddle复现PoseC3D - 游乐网 骨骼点动作识别-基于Paddle复现PoseC3D - 游乐网
           原始频与关节点可视化

参数说明:

input_file: 输入文件,按照ucf-101.pkl格式。可以使用test_tipc/data中的predict_example.pkl数据进行测试。

pretrained: 训练好的模型

模型导出

模型导出可执行以下命令:

In [ ]
!python export_model.py --model_path best_model.pdparams --save_dir ./output/
登录后复制    

参数说明:

model_path: 模型路径

save_dir: 输出图片保存路径

Inference推理

可使用以下命令进行模型推理。该脚本依赖auto_log, 请参考下面TIPC部分先安装auto_log。infer命令运行如下:

In [ ]
!python infer.py --use_gpu=False --enable_mkldnn=False \--cpu_threads=2 --model_file=output/model.pdmodel --batch_size=2 \--input_file=validation/BSD300/test --enable_benchmark=True --precision=fp32 \--params_file=output/model.pdiparams --save_dir output/inference_img
登录后复制    

参数说明:

use_gpu:是否使用GPU

enable_mkldnn:是否使用mkldnn

cpu_threads: cpu线程数

model_file: 模型路径

batch_size: 批次大小

input_file: 输入文件路径

enable_benchmark: 是否开启benchmark

precision: 运算精度

params_file: 模型权重文件,由export_model.py脚本导出。

save_dir: 保存推理预测图片的路径

TIPC基础链条测试

该部分依赖auto_log,需要进行安装,安装方式如下:

auto_log的详细介绍参考https://github.com/LDOUBLEV/AutoLog。

In [ ]
%cd /home/aistudio/!git clone https://gitee.com/Double_V/AutoLog!cd AutoLog/!pip3 install -r requirements.txt!python3 setup.py bdist_wheel!pip3 install ./dist/auto_log-1.2.0-py3-none-any.whl!bash test_tipc/prepare.sh test_tipc/configs/posec3d/train_infer_python.txt 'lite_train_lite_infer'!bash test_tipc/test_train_inference_python.sh test_tipc/configs/posec3d/train_infer_python.txt 'lite_train_lite_infer'
登录后复制    

测试结果如截图所示:

骨骼点动作识别-基于Paddle复现PoseC3D - 游乐网        

7.代码结构与详细说明

PaddlePoseC3D├── README.md # 使用说明├── datasets # 数据集包│   ├── __init__.py│   ├── base.py #数据集基类│   ├── file_client.py # 文件处理类│   ├── pipelines│   │   └── transforms.py # 数据增强类│   ├── pose_dataset.py # 数据集类│   ├── dataset_wrappers.py # 数据集类│   └── utils.py #数据集工具类├── models│   ├── __init__.py│   ├── base.py # 模型基类│   ├── resnet3d.py # backbone│   ├── resnet3d_slowfast.py # backbone│   └── resnet3d_slowonly.py # backbone│   ├── i3d_head.py # c3d模型头部实现│   └── recognizer3d.py # 识别模型框架├── progress_bar.py #进度条工具├── test.py # 评估程序├── test_tipc # TIPC脚本│   ├── README.md│   ├── common_func.sh # 通用脚本程序│   ├── configs│   │   └── posec3d│   │       └── train_infer_python.txt # 单机单卡配置│   ├── data│   │   ├── example.npy # 推理用样例数据│   │   └── mini_ucf.zip # 训练用小规模数据集│   ├── output│   ├── prepare.sh # 数据准备脚本│   └── test_train_inference_python.sh # 训练推理测试脚本├── timer.py # 时间工具类├── train.log # 训练日志├── test.log # 测试日志├── train.py # 训练脚本└── utils.py # 训练工具包
登录后复制        

8.模型信息

9.复现心得

在之前的复现赛中复现过C3D,这次看到了PoseC3D的复现就参加了。复用了部分之前部分C3D的代码,所以这篇论文代码完成的速度比较快。参考repo使用的是8卡,我使用的Notebook的1卡V100环境,所以每个batch是参考repo的1/8,所以学习率也调整为原来的1/8。最终精度为87.05%跟源repo的87%基本一致,也是符合预期的。最后感谢飞桨举办本次比赛,也感谢AI Stuido提供算力支持。

来源:https://www.php.cn/faq/1421724.html
免责声明: 游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

相关攻略

openclaw在飞书测试报错access not configured.
AI
openclaw在飞书测试报错access not configured.

常见报错解析:“Access Not Configured”故障排除指南 许多开发者和团队成员在使用OpenClaw集成飞书时,都曾遭遇过一个典型的中断提示:“access not configured”(访问未配置)。该提示会明确显示您的飞书账户ID及一组唯一的配对验证码,并指出需要联系机器人所有

热心网友
04.02
OpenClaw 常用指令速查
AI
OpenClaw 常用指令速查

OpenClaw 常用指令大全与使用详解 openclaw status:此命令是查看OpenClaw系统整体健康状态的核心指令,执行后即获取服务运行状况的全面报告,是日常运维的首要诊断工具。 openclaw gateway restart:在修改网关配置后,必须运行此指令以重启网关服务,使配置文

热心网友
04.02
OpenClaw 操控浏览器
AI
OpenClaw 操控浏览器

如何通过 OpenClaw 实现 Chrome 浏览器自动化操控 在软件开发与自动化测试领域,持续学习是常态。本文旨在详细介绍如何利用 OpenClaw 连接并控制一个已开启的 Chrome 浏览器实例,实现点击、文本输入、文件上传、页面滚动、屏幕截图以及执行 JavaScript 等自动化操作。整

热心网友
04.01
# OpenClaw QQ 机器人接入完整指南
AI
# OpenClaw QQ 机器人接入完整指南

项目概述 你是否希望将强大的 AI 助手带入日常聊天?本教程将指导你完成搭建流程,让你能在 QQ 上直接调用 OpenClaw 智能助手,实现无门槛的 AI 对话体验。 架构说明 ┌─────────────┐ ┌──────────────┐ ┌─────────────┐ │ QQ 用户 │ ─

热心网友
04.01
OpenClaw 保姆级 window部署
AI
OpenClaw 保姆级 window部署

一 下载并安装Node js,全程保持默认设置 首先,请前往Node js官方网站的下载中心:https: nodejs org zh-cn download。根据您的操作系统(Windows Mac Linux)下载对应的安装程序。运行安装向导时,整个过程非常简单,您只需连续点击“下一步”按钮

热心网友
04.01

最新APP

火柴人传奇
火柴人传奇
动作冒险 04-01
街球艺术
街球艺术
体育竞技 04-01
飞行员模拟
飞行员模拟
休闲益智 04-01
史莱姆农场
史莱姆农场
休闲益智 04-01
绝区零
绝区零
角色扮演 04-01

热门推荐

《洛克王国》世界圣羽翼王打法攻略-圣羽翼王技能与实战详解
游戏攻略
《洛克王国》世界圣羽翼王打法攻略-圣羽翼王技能与实战详解

速览攻略:世界圣羽翼王核心打法与全面解析 本攻略将为你完整呈现《洛克王国》世界圣羽翼王的通关秘籍,深度剖析两种高效实战打法:追求极致速度的“燃薪虫四回合速通”与稳定输出的“酷拉无限连击流”。文章将进一步解析这位翼系精灵王的技能机制、属性克制关系及其在PVE与PVP中的实战定位,帮助你彻底掌握应对其隐

热心网友
04.06
《异种航员2》工程系统详解-工作坊与资源管理指南
游戏攻略
《异种航员2》工程系统详解-工作坊与资源管理指南

速览:工程系统核心机制解析 在《异种航员2》中,工程系统是整个抵抗力量赖以运转的“战略后勤中枢”。无论是研发新武器、生产重型装甲还是制造先进飞行器,所有实体装备的产出都依赖于此。简言之,该系统的核心运作围绕着两大关键:工程师人力的高效配置与全球稀缺资源的精细化调度。工程师的数量直接决定了每个项目的建

热心网友
04.06
《洛克王国世界》治愈兔位置详解-任务与战斗关键精灵
游戏攻略
《洛克王国世界》治愈兔位置详解-任务与战斗关键精灵

核心速览 在《洛克王国世界》中,治愈兔是一位兼具功能性任务角色与实战辅助能力的精灵。它的价值不仅在剧情推进中体现,更在于对战里出色的治疗与防护表现。本文将为你全面解析治愈兔的精准获取位置、种族属性特点以及实战技能搭配,助你顺利捕捉并最大化其在队伍中的作用。所有关键信息将通过清晰的图文内容详细展示,确

热心网友
04.06
《红色沙漠》传说之狼打法-传说之狼击杀流程详解
游戏攻略
《红色沙漠》传说之狼打法-传说之狼击杀流程详解

速览 在《红色沙漠》中,挑战传说之狼这一强大的任务BOSS,需要玩家进行充分的准备并遵循完整的任务流程。整个过程环环相扣,你必须首先参与塞莱斯特家族的势力任务,通过完成任务将家族声望提升至指定等级,才能解锁【传说之狼】的专属讨伐任务,最终直面这个传说中的强大生物。 红色沙漠传说之狼怎么打 归根结底,

热心网友
04.06
《宝可梦Pokopia》舒适度提升攻略-环境等级与栖息地优化指南
游戏攻略
《宝可梦Pokopia》舒适度提升攻略-环境等级与栖息地优化指南

【宝可梦Pokopia】舒适度全解析:快速提升环境等级的核心秘诀 你是否正在探索《宝可梦Pokopia》世界,并希望有效提升宝可梦栖息地的舒适度?舒适度不仅是衡量宝可梦快乐程度的晴雨表,更是解锁游戏核心内容、加速发展的关键驱动指标。本攻略将系统性地为你揭示提升舒适度的核心途径,涵盖从装饰栖息地、建造

热心网友
04.06