特效大片背后的多视角 3D 人体姿态估计技术

目录

0 背景

1 主要算法

1.1 基于匹配和三角化重建的算法

1.2 基于空间体素化的算法

1.3 基于图卷积网络的算法

1.4 基于 Transformer 的算法

2 常用数据集

2.1 Campus

2.2 Shelf

2.3 CMU Panoptic

3 MMPose 中 VoxelPose 的实现

3.1 Model

3.2 Data

3.3 相机模块

3.4 训练配置

4 总结

5 参考文献


0 背景

前面的推送我们简要地介绍过 3D 人体姿态估计任务。本文主要介绍多视角 3D 人体姿态估计任务。这是计算机视觉领域里经典的研究课题,即给定多个已标定的相机拍摄的图像和对应的相机参数,目标是检测并恢复出该场景的所有人体骨架,比如用 N*3 表示的一组关键点。它是视频动作分析和高级人机交互的基础,在运动分析、影视特效等领域具有重要的应用前景

特效大片背后的多视角 3D 人体姿态估计技术_第1张图片

图 1:多视角 3D 人体姿态估计任务

从单个视角的 2D 图像估计 3D 姿态是一个不适定问题,因为可能存在多个不同的 3D 姿态,它们的 2D 投影是同一个 2D 姿态。并且,基于单目图像的方法也面临着自遮挡、物体遮挡、深度的不确定性等问题。利用多视角的图像作为输入,可以有效地解决这些痛点,从而更精确地恢复出 3D 姿态。下面我们将结合 MMPose 的实现介绍多视角 3D 人体姿态估计任务常用的算法、数据集和功能模块。

1 主要算法

目前多视角 3D 人体姿态估计主要有如下方案:

  • 基于匹配 (matching) 和三角化重建 (triangulation) 的算法:首先检测各个视角的 2D 人体骨架;再利用几何关系计算距离,进行多视角人体的匹配;最终,利用多视角的 2D 坐标和相机参数,计算出 3D 坐标,代表方法是 MVPose [1]。
  • 基于空间体素 (voxel) 的算法:通过将 3D 空间划分为等距网格,用概率模型或者 3D 卷积神经网络(CNN)检测关键点,代表方法是 VoxelPose [2]。
  • 基于图卷积神经网络 (Graph Neural Network, GNN) 的自顶向下(top-down)的两阶段算法:结合了上述两种方法的优势,分为 3D 人体中心点定位和 3D 人体姿态估计两个阶段,针对不同的任务设计有效的 GNN 模块,代表方法是 [3] 。
  • 基于 Transformer 的单阶段算法:与上述方法不同的是,此类方法不依赖于人体中心点检测等中间任务,而是直接预测多人关键点三维坐标,代表方法是 MvP [4]。

下面我们将分别介绍这些算法。

1.1 基于匹配和三角化重建的算法

此类算法一般利用训练好的 2D 模型来预测各个视角的 2D 人体关键点,然后将各个视角检测到的人体关键点进行匹配,最后使用相机参数和几何关系重建出 3D 坐标。MVPose [1] 提出了一种快速并且鲁棒的算法,如图 2 所示,整体流程可以分为三步。

特效大片背后的多视角 3D 人体姿态估计技术_第2张图片

图 2:MVPose 算法框架

第一步,利用现成的 2D 模型检测人体的边界框和各个视角的 2D 人体关键点坐标。

第二步,基于 2D 检测器给出的人体边界框,分别使用多视角的极线约束和行人重识别网络来度量人体边界框的几何和外观相似度,构建亲和度矩阵。如果只有两个视角需要匹配,只需使用匈牙利算法就能找到最优的匹配;当存在更多视角时,单纯地运行两两视角之间的匹配,会忽略循环一致性的约束,导致匹配结果不一致,如图 3 红色虚线展示的结果。因此 MVPose 在优化的目标函数中加入了视角间一致性的约束。

特效大片背后的多视角 3D 人体姿态估计技术_第3张图片

图 3:多视角匹配的循环一致性的例子

第三步,使用 3DPS 模型并提出了逼近算法使得推理更高效。

MVPose 在 Campus 和 Shelf 数据集上大幅超过了之前的算法,验证了其有效性,并且运行速度上能够达到实时 (>20fps)。

然而,这类方法的精度十分依赖 2D 检测结果。2D 检测的误差会影响匹配的效果,错误的匹配会进一步导致异常的重建;2D 的误差也会影响 3D 重建的精度,并且匹配和三角重建部分并不是数据驱动的,没有监督训练和损失反传。

1.2 基于空间体素化的算法

为了避免 2D 部分预测的不准确对后续匹配造成的影响,基于空间体素化的算法首先聚合所有视角的信息,然后直接在 3D 空间中进行预测。图 4 展示了 VoxelPose 算法的框架,整体流程同样可以分为三步。

特效大片背后的多视角 3D 人体姿态估计技术_第4张图片

图 4:VoxelPose 算法框架

第一步,使用常用的 2D backbone 预测每个视角的关键点 heatmap,然后将各个视角的 heatmap 投影到一个共同的离散 3D 空间中,构建 3D feature volume。VoxelPose 首先检测人体中心点,再去估计每个人的关键点位置。

第二步,将 3D feature volume 输入 3D CNN,定位出该场景下所有人的中心点位置。

第三步,对第二步定位到的每一个人体中心点,以这个位置为中心,将 2D heatmap 投影到一个空间更小、网格更精细的 3D 空间中,构造更精细的 3D feature volume,输入 3D CNN ,预测 3D 关键点位置。整个网络包括 2D backbone 和 3D CNN 部分,可以端到端地进行训练。

通过消融实验发现,3D 部分的网络可以使用自动合成的 heatmap 来有效训练,而无需输入真实数据集的图像,这极大地提升了它的实用价值。

然而,VoxelPose 也存在明显的弊端。首先,其精度会受到网格大小的制约,不可避免地会产生量化误差;其次,在相同的精度下,其计算复杂度随空间大小三次方增长,无法应用于较大场景。

1.3 基于图卷积网络的算法

针对以上方法的不足,Wu 等人提出了一种基于图卷积神经网络自顶向下的两阶段算法 [3]。图 5 是它跟此前两类方法的对比。

特效大片背后的多视角 3D 人体姿态估计技术_第5张图片

图 5:主流的多视角 3D 人体姿态估计算法框架对比

与 VoxelPose 类似,该算法的整体流程分为两个阶段:3D 人体中心点定位和 3D 人体姿态估计,如图 6 所示。

特效大片背后的多视角 3D 人体姿态估计技术_第6张图片

图 6:基于图卷积网络的多视角 3D 人体姿态估计算法框架 [3]

针对 3D 人体中心点定位,采用了“由粗到精”的策略。首先进行“粗筛选”,设计了多视角匹配图神经网络 ,生成中心点候选区域;再在候选中心点附近“精细”搜索,利用中心点优化图模型,得到精确的人体中心点定位结果。

针对 3D 人体姿态估计,同样采用"由粗到精"的策略,首先采用现有的姿态估计方法 [2] 预测初始 3D 人体姿态。然后利用人体姿态回归图模型,高效地融合多视角的特征和人体骨架的拓扑结构信息。

该算法在 CMU Panoptic 和 Shelf 两个主流的数据集上进行了定量实验,均取得了最优的精度,而且在计算量和耗时方面,相比之前的 SOTA 也有明显优势。

1.4 基于 Transformer 的算法

尽管前面几类方法取得了不错的精度,但它们依赖于一些中间任务,整体流程分成多个阶段,并且需要独立地预测每个人的 3D 姿态,使得计算复杂度随着人数增加而线性增长。受目标检测中的 DETR [5] 和 Deformable DETR [6] 启发,Zhang 等人提出了一种基于 Transformer 的简洁高效的单阶段算法 (Multi-view Pose transformer, MvP) [4],图 7 对比了多阶段的多视角 3D 人体姿态估计算法与 MvP 算法的框架。

特效大片背后的多视角 3D 人体姿态估计技术_第7张图片

图 7: 多阶段的多视角 3D 人体姿态估计算法与 MvP 算法框架对比

算法的整体流程如图 8 所示。

特效大片背后的多视角 3D 人体姿态估计技术_第8张图片

图 8:(a) MvP 算法框架;(b) projective attention 示意图

MvP 使用常用的 2D backbone 提取各个视角的图像特征。在 decoder 处设计了足够多的 query 对关键点进行嵌入表征。每一层 decoder layer 会依次执行 self-attention 和 projective attention,聚合其他 query 和多视角的特征;每一层 decoder layer 都会接上分类头和回归头,输出相对上一层预测的3D 关键点坐标偏移量,逐层优化预测结果。训练时将预测结果与真实值匹配,计算 loss 并反传梯度,更新网络参数;在推理时,设定阈值去除置信度较低的预测结果。

MvP 采用了层级式的 query,如图 9 所示,分别对不同的人和不同类型的关键点设计嵌入表示,还加入了池化后的图像特征,使得模型能够对场景有自适应的表征,提升泛化性能。

特效大片背后的多视角 3D 人体姿态估计技术_第9张图片

图 9:MvP 中的 query 构成

在融合多视角的图像特征时,如果关注所有视角的所有位置点的特征,会引入大量的计算,并且没有引入任何几何先验信息,模型很难优化和收敛。因此,MvP 提出了 projective attention,利用前一层输出的 3D 参考点,根据相机参数将其投影到各个视角的对应位置,在这些位置周围采样固定数量的点,然后对这些位置的特征做融合。此外,MvP 根据各个视角的相机参数生成了 3D 位置编码。

MvP 在 Shelf 和 Campus 数据集上取得了 SOTA 的性能,在 CMU Panoptic 数据集上取得了 92.3% 的 AP25,相比 VoxelPose 提升了 9.8%,并且 MPJPE 更低 (15.8 v.s 17.8)。在运行速度上,比 VoxelPose 快了 2 倍,并且推理时间不随场景中人数的增加而增加,能更好地应对拥挤的场景。

2 常用数据集

目前常用的多视角 3D 人体姿态估计数据集包括 Campus,Shelf [7] 以及 CMU Panoptic [8] 。MMPose 已经支持了这三个数据集。

2.1 Campus

Campus 使用三个经过校准的相机,拍摄内容是三个人在室外环境 (campus) 中相互交流的场景,每个视角提供了 2000 帧图像,通常将编号为 [350, 470] 和 [650, 750] 的帧作为测试,使用 PCP 来评估人体关键点估计的准确性。图 10 展示了 VoxelPose 在 Campus 数据集上的可视化结果。

特效大片背后的多视角 3D 人体姿态估计技术_第10张图片

图 10:VoxelPose 在 Campus 数据集上的可视化结果

2.2 Shelf

与 Campus 相比,Shelf 数据更复杂,使用五个经过校准的相机,拍摄内容是四个人近距离拆卸一个架子 (shelf) 组成,每个视角提供了 3200 帧图像,每个视角都存在严重的遮挡。通常将编号为 [300, 600] 的帧作为测试,同样采用 PCP 来评估预测得到 3D 人体关键点。图 11 展示了 VoxelPose 在 Shelf 数据集上的可视化结果。

特效大片背后的多视角 3D 人体姿态估计技术_第11张图片

图 11:VoxelPose 在 Shelf 数据集上的可视化结果

Campus 和 Shelf 数据集由于体量较小,在训练比较大的模型时,通常会采用现成的 2D 人体姿态估计网络,而只训练 3D 部分的网络,以防止过拟合。

2.3 CMU Panoptic

CMU Panoptic [9] 是一个大规模的多视角图像数据集,提供了包括 480 个 VGA 摄像头、31 个不同视角的高清 (HD) 图像、10 个不同视角的 Kinect 数据以及对应的相机参数,包含了 65 段视频(总时长5.5 h),3D skeleton 总数超过 150 万。该数据集包含了多个多人场景,是多视角 3D 人体姿态估计任务常用的 benchmark 数据集。图 12 是 CMU Panoptic 数据集的示例。

特效大片背后的多视角 3D 人体姿态估计技术_第12张图片

图 12:CMU Panoptic 数据集示例

VoxelPose 最早在 CMU Panoptic 上做了定量实验,使用了编号为 (3, 6, 12, 13, 23) 五个视角的图像,训练和测试集包含不同的视频序列。一般采用所有关键点预测坐标与真实坐标之间的平均欧式距离 (MPJPE) 来评估算法性能,VoxelPose 还提出了基于 MPJPE 的 AP metric,并被后续工作采用。

3 MMPose 中 VoxelPose 的实现

MMPose 现已支持 VoxelPose 这个经典的多视角 3D 人体姿态估计算法,并且分别在 Campus、Shelf 以及 CMU Panoptic 这三个数据集上完成了训练和测试。我们也提供了相应的 demo,详细介绍可见 3d_multiview_human_pose_demo.md。demo 脚本会加载 MMPose 中的配置文件和预训练模型,可以使用自定义数据,也可以在代码中自动下载默认的多视角图像和相机参数,运行模型推理,最终输出可视化结果。

下面以 VoxelPose 的一个模型为例,介绍算法的具体实现。

3.1 Model

3.1.1 2D Pose Detector

下面这段代码展示了 2D 姿态检测器的配置。detector 采用了 AssociativeEmbedding,backbone 是 ResNet50,Head 部分是 DeconvHead。输入每个视角的图像,输出为 2D heatmap。

backbone = dict( 
    type='AssociativeEmbedding', 
    pretrained=None, 
    backbone=dict(type='ResNet', depth=50), 
    keypoint_head=dict( 
        type='DeconvHead', 
        in_channels=2048, 
        out_channels=num_joints, 
        num_deconv_layers=3, 
        num_deconv_filters=(256, 256, 256), 
        num_deconv_kernels=(4, 4, 4), 
        loss_keypoint=dict( 
            type='MultiLossFactory', 
            num_joints=15, 
            num_stages=1, 
            ae_loss_type='exp', 
            with_ae_loss=[False], 
            push_loss_factor=[0.001], 
            pull_loss_factor=[0.001], 
            with_heatmaps_loss=[True], 
            heatmaps_loss_factor=[1.0], 
        )) 
) 

3.1.2 3D Pose Detector

下面这段代码展示了 3D 姿态检测器的配置。detector 采用了 DetectAndRegress ,顾名思义,就是先检测 (Detect) 人体中心点,再对每个 proposal 回归 (Regress) 出这个人的所有关键点位置。

human_detector 实现了检测人体中心点的 CPN 网络,需要指定整体空间的中心点 space_center,空间大小 space_size 以及划分的网格数目 cube_size,根据输入的 image_size 和 heatmap_size 将每个 3D 网格点坐标投影到 2D heatmap,构造 3D feature volume 。

model = dict( 
    type='DetectAndRegress', 
    backbone=backbone, 
    pretrained='checkpoints/resnet_50_deconv.pth.tar', 
    human_detector=dict( 
        type='VoxelCenterDetector', 
        image_size=image_size, 
        heatmap_size=heatmap_size, 
        space_size=space_size, 
        cube_size=cube_size, 
        space_center=space_center, 
        center_net=dict(type='V2VNet', input_channels=15, output_channels=1), 
        center_head=dict( 
            type='CuboidCenterHead', 
            space_size=space_size, 
            space_center=space_center, 
            cube_size=cube_size, 
            max_num=10, 
            max_pool_kernel=3), 
        train_cfg=dict(dist_threshold=500.0), 
        test_cfg=dict(center_threshold=0.3), 
    ), 
    pose_regressor=dict( 
        type='VoxelSinglePose', 
        image_size=image_size, 
        heatmap_size=heatmap_size, 
        sub_space_size=sub_space_size, 
        sub_cube_size=sub_cube_size, 
        num_joints=15, 
        pose_net=dict(type='V2VNet', input_channels=15, output_channels=15), 
        pose_head=dict(type='CuboidPoseHead', beta=100.0))) 
 

pose_regressor采用 VoxelSinglePose,实现了 VoxelPose 的 PRN。同样需要指定每个人的空间大小 sub_space_size 、划分的网格数目 sub_cube_size、输入的 image_size 和 heatmap_size 等。注意此处并不是直接取 heatmap 值最大的网格点作为预测的坐标,而是结合 3D 网格点的坐标对 heatmap 求平均,以减小量化误差。

3.2 Data

3.2.1 Dataset

下面这段代码列出了与训练数据相关的一些配置。

train_data_cfg = dict( 
    image_size=image_size, 
    heatmap_size=[heatmap_size], 
    num_joints=num_joints, 
    seq_list=[ 
        '160422_ultimatum1', '160224_haggling1', '160226_haggling1', 
        '161202_haggling1', '160906_ian1', '160906_ian2', '160906_ian3', 
        '160906_band1', '160906_band2' 
    ], 
    cam_list=[(0, 12), (0, 6), (0, 23), (0, 13), (0, 3)], 
    num_cameras=5, 
    seq_frame_interval=3, 
    subset='train', 
    root_id=2, 
    max_num=10, 
    space_size=space_size, 
    space_center=space_center, 
    cube_size=cube_size, 
) 

关于 CMU Panoptic 的数据集信息可见 panoptic_body3d.py。配置文件中使用了 Body3DMviewDirectPanopticDataset,具体实现可见 body3d_mview_direct_panoptic_dataset.py。其中 seq_list 指定了采用的视频序列,cam_list指定了采用的相机编号,root_id 用于过滤根节点不可见的 pose。

3.2.2 Pipeline

下面这段代码展示了每个样本进入网络之前的数据预处理流水线,这些预处理会按顺序执行,完成数据读取、数据增强、目标 heatmap 生成等,具体的实现可见 pipelines。

train_pipeline = [ 
    dict( 
        type='MultiItemProcess', 
        pipeline=[ 
            dict(type='LoadImageFromFile'), 
            dict( 
                type='BottomUpRandomAffine', 
                rot_factor=0, 
                scale_factor=[1.0, 1.0], 
                scale_type='long', 
                trans_factor=0), 
            dict(type='ToTensor'), 
            dict( 
                type='NormalizeTensor', 
                mean=[0.485, 0.456, 0.406], 
                std=[0.229, 0.224, 0.225]), 
        ]), 
    dict( 
        type='DiscardDuplicatedItems', 
        keys_list=[ 
            'joints_3d', 'joints_3d_visible', 'ann_info', 'roots_3d', 
            'num_persons', 'sample_id' 
        ]), 
    dict(type='GenerateVoxel3DHeatmapTarget', sigma=200.0, joint_indices=[2]), 
    dict( 
        type='Collect', 
        keys=['img', 'targets_3d'], 
        meta_keys=[ 
            'num_persons', 'joints_3d', 'camera', 'center', 'scale', 
            'joints_3d_visible', 'roots_3d' 
        ]), 
] 
 
  1. MultiItemProcess: 由于每个样本存储了多个视角的图像、2D 人体关键点标记坐标等信息,需要对列表的每一个 item 处理,包括读取特定路径的图片、图像的仿射变换、转换为 PyTorch 的张量 、归一化等。
  2. DiscardDuplicatedItems:由于一个样本的多个视角存在某些重复的信息,如标签信息等,需去除重复的信息。
  3. GenerateVoxel3DHeatmapTarget:生成目标的 3D heatmap,这一步仅用于训练。
  4. Collect:整合训练中需要用到的数据。

3.3 相机模块

对于多视角 3D 人体姿态估计任务,常用的操作是根据相机参数将 3D 坐标投影至 2D,因此 MMPose 将与相机相关的操作封装成一个模块,详见 camera,它包括以下功能:

  • world_to_camera:将世界坐标系下的点的 3D 坐标转换到相机坐标系下的 3D 坐标;
  • camera_to_world:将相机坐标系下的点的 3D 坐标转换到世界坐标系下的 3D 坐标;
  • camera_to_pixel:将相机坐标系下的点的 3D 坐标投影到像素坐标下的 2D 坐标;
  • world_to_pixel:将世界坐标系下的点的 3D 坐标投影到像素坐标下的 2D 坐标,会先调用 world_to_camera 再调用 camera_to_pixel

可以利用相机的内参和外参初始化一个 camera 实例,然后就能方便地完成坐标的转换,目前 MMPose 已支持使用 numpy 和 torch 两种计算方式实现的 camera。基于强大的 MMCV 注册器机制,用户也可以增加自定义的相机模块。

3.4 训练配置

3.4.1 Optimizer

采用 Adam 作为优化器,与论文中保持一致,这里初始学习率设为 1e-4:

optimizer = dict(type='Adam',lr=0.0001) 
optimizer_config = dict(grad_clip=None) 

3.4.2 Learning Policy

下面这段代码展示了训练过程中的学习率调整策略:

lr_config = dict( 
    policy='step', 
    warmup='linear', 
    warmup_iters=500, 
    warmup_ratio=0.001, 
    step=[8, 9]) 
total_epochs = 15 
  • policy:这里学习率采用多阶段调整的策略。
  • warmup:学习率预热的类型,用于初始时稳定训练过程,可选 constantlinear 或 exp
  • warmup_iters:预热的迭代次数。
  • warmup_ratio:预热学习率与比值,当使用linear类型时,在初始的迭代次数里,使用

1 - (1 - cur_iters / warmup_iters) * (1 - warmup_ratio)获取当前迭代轮次的学习率,因此越靠前的轮次学习率越小,更多细节可见 MMCV 的 lr_updater.py。

  • step=[8, 9]:分别在第 8 和第 9 个 epoch 之后将学习率降为之前的 0.1。
  • total_epochs = 15:与原论文不一样的是,这里一共训练 15 个 epochs。

4 总结

本文介绍了多视角 3D 人体姿态估计任务的主流算法和常用数据集,并以 VoxelPose 为例,简要介绍了 MMPose 中的算法和相机模块的实现。希望大家通过本文的阅读能够对多视角 3D 人体姿态估计有一个大致的了解,也欢迎大家使用 MMPose 来支持相关的研究与应用~

https://github.com/open-mmlab/mmpose​github.com/open-mmlab/mmpose

5 参考文献

[1] Dong J, Jiang W, Huang Q, et al. Fast and robust multi-person 3d pose estimation from multiple views[C]//Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2019: 7792-7801.

[2] Tu H, Wang C, Zeng W. Voxelpose: Towards multi-camera 3d human pose estimation in wild environment[C]//European Conference on Computer Vision. Springer, Cham, 2020: 197-212.

[3] Wu S, Jin S, Liu W, et al. Graph-based 3d multi-person pose estimation using multi-view images[C]//Proceedings of the IEEE/CVF International Conference on Computer Vision. 2021: 11148-11157.

[4] Zhang J, Cai Y, Yan S, et al. Direct Multi-view Multi-person 3D Pose Estimation[J]. Advances in Neural Information Processing Systems, 2021, 34.

[5] Carion N, Massa F, Synnaeve G, et al. End-to-end object detection with transformers[C]//European conference on computer vision. Springer, Cham, 2020: 213-229.

[6] Zhu X, Su W, Lu L, et al. Deformable detr: Deformable transformers for end-to-end object detection[J]. arXiv preprint arXiv:2010.04159, 2020.

[7] Belagiannis V, Amin S, Andriluka M, et al. 3D pictorial structures for multiple human pose estimation[C]//Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition. 2014: 1669-1676.

[8] Joo, H., Liu, H., Tan, L., Gui, L., Nabbe, B., Matthews, I., ... & Sheikh, Y. (2015). Panoptic studio: A massively multiview system for social motion capture. In Proceedings of the IEEE International Conference on Computer Vision (pp. 3334-3342).

你可能感兴趣的:(技术干货,3d,计算机视觉,人工智能,3D,姿态估计)