Initial snapshot: hand motion pipeline (Dyn-HaMR + dex-retargeting + SPIDER)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 14:13:49 +08:00
commit 7e4ef6f98b
7002 changed files with 1452249 additions and 0 deletions
@@ -0,0 +1,122 @@
# Copyright (c) OpenMMLab. All rights reserved.
import numpy as np
import torch
from mmpose.models.detectors import AssociativeEmbedding
def test_ae_forward():
model_cfg = dict(
type='AssociativeEmbedding',
pretrained=None,
backbone=dict(type='ResNet', depth=18),
keypoint_head=dict(
type='AESimpleHead',
in_channels=512,
num_joints=17,
num_deconv_layers=0,
tag_per_joint=True,
with_ae_loss=[True],
extra=dict(final_conv_kernel=1, ),
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=1,
ae_loss_type='exp',
with_ae_loss=[True],
push_loss_factor=[0.001],
pull_loss_factor=[0.001],
with_heatmaps_loss=[True],
heatmaps_loss_factor=[1.0])),
train_cfg=dict(),
test_cfg=dict(
num_joints=17,
max_num_people=30,
scale_factor=[1],
with_heatmaps=[True],
with_ae=[True],
project2image=True,
nms_kernel=5,
nms_padding=2,
tag_per_joint=True,
detection_threshold=0.1,
tag_threshold=1,
use_detection_val=True,
ignore_too_much=False,
adjust=True,
refine=True,
soft_nms=False,
flip_test=True,
post_process=True,
shift_heatmap=True,
use_gt_bbox=True,
flip_pairs=[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12],
[13, 14], [15, 16]],
))
detector = AssociativeEmbedding(model_cfg['backbone'],
model_cfg['keypoint_head'],
model_cfg['train_cfg'],
model_cfg['test_cfg'],
model_cfg['pretrained'])
detector.init_weights()
input_shape = (1, 3, 256, 256)
mm_inputs = _demo_mm_inputs(input_shape)
imgs = mm_inputs.pop('imgs')
target = mm_inputs.pop('target')
mask = mm_inputs.pop('mask')
joints = mm_inputs.pop('joints')
img_metas = mm_inputs.pop('img_metas')
# Test forward train
losses = detector.forward(
imgs, target, mask, joints, img_metas, return_loss=True)
assert isinstance(losses, dict)
# Test forward test
with torch.no_grad():
_ = detector.forward(imgs, img_metas=img_metas, return_loss=False)
_ = detector.forward_dummy(imgs)
def _demo_mm_inputs(input_shape=(1, 3, 256, 256)):
"""Create a superset of inputs needed to run test or train batches.
Args:
input_shape (tuple):
input batch dimensions
"""
(N, C, H, W) = input_shape
rng = np.random.RandomState(0)
imgs = rng.rand(*input_shape)
target = np.zeros([N, 17, H // 32, W // 32], dtype=np.float32)
mask = np.ones([N, H // 32, W // 32], dtype=np.float32)
joints = np.zeros([N, 30, 17, 2], dtype=np.float32)
img_metas = [{
'image_file':
'test.jpg',
'aug_data': [torch.zeros(1, 3, 256, 256)],
'test_scale_factor': [1],
'base_size': (256, 256),
'center':
np.array([128, 128]),
'scale':
np.array([1.28, 1.28]),
'flip_index':
[0, 2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 12, 11, 14, 13, 16, 15]
} for _ in range(N)]
mm_inputs = {
'imgs': torch.FloatTensor(imgs).requires_grad_(True),
'target': [torch.FloatTensor(target)],
'mask': [torch.FloatTensor(mask)],
'joints': [torch.FloatTensor(joints)],
'img_metas': img_metas
}
return mm_inputs
@@ -0,0 +1,483 @@
# Copyright (c) OpenMMLab. All rights reserved.
import numpy as np
import pytest
import torch
from mmpose.models import AEHigherResolutionHead, AESimpleHead
def test_ae_simple_head():
"""test bottom up AE simple head."""
with pytest.raises(TypeError):
# extra
_ = AESimpleHead(
in_channels=512,
num_joints=17,
with_ae_loss=[True],
extra=[],
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=1,
ae_loss_type='exp',
with_ae_loss=[True],
push_loss_factor=[0.001],
pull_loss_factor=[0.001],
with_heatmaps_loss=[True],
heatmaps_loss_factor=[1.0]))
# test final_conv_kernel
with pytest.raises(AssertionError):
_ = AESimpleHead(
in_channels=512,
num_joints=17,
with_ae_loss=[True],
extra={'final_conv_kernel': -1},
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=1,
ae_loss_type='exp',
with_ae_loss=[True],
push_loss_factor=[0.001],
pull_loss_factor=[0.001],
with_heatmaps_loss=[True],
heatmaps_loss_factor=[1.0]))
head = AESimpleHead(
in_channels=512,
num_joints=17,
with_ae_loss=[True],
extra={'final_conv_kernel': 3},
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=1,
ae_loss_type='exp',
with_ae_loss=[True],
push_loss_factor=[0.001],
pull_loss_factor=[0.001],
with_heatmaps_loss=[True],
heatmaps_loss_factor=[1.0]))
head.init_weights()
assert head.final_layer.padding == (1, 1)
head = AESimpleHead(
in_channels=512,
num_joints=17,
with_ae_loss=[True],
extra={'final_conv_kernel': 1},
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=1,
ae_loss_type='exp',
with_ae_loss=[True],
push_loss_factor=[0.001],
pull_loss_factor=[0.001],
with_heatmaps_loss=[True],
heatmaps_loss_factor=[1.0]))
head.init_weights()
assert head.final_layer.padding == (0, 0)
head = AESimpleHead(
in_channels=512,
num_joints=17,
with_ae_loss=[True],
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=1,
ae_loss_type='exp',
with_ae_loss=[True],
push_loss_factor=[0.001],
pull_loss_factor=[0.001],
with_heatmaps_loss=[True],
heatmaps_loss_factor=[1.0]))
head.init_weights()
assert head.final_layer.padding == (0, 0)
# test with_ae_loss
head = AESimpleHead(
in_channels=512,
num_joints=17,
num_deconv_layers=0,
with_ae_loss=[True],
extra={'final_conv_kernel': 3},
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=1,
ae_loss_type='exp',
with_ae_loss=[True],
push_loss_factor=[0.001],
pull_loss_factor=[0.001],
with_heatmaps_loss=[True],
heatmaps_loss_factor=[1.0]))
head.init_weights()
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head(inputs)
assert out[0].shape == torch.Size([1, 34, 32, 32])
head = AESimpleHead(
in_channels=512,
num_joints=17,
num_deconv_layers=0,
with_ae_loss=[False],
extra={'final_conv_kernel': 3},
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=1,
ae_loss_type='exp',
with_ae_loss=[True],
push_loss_factor=[0.001],
pull_loss_factor=[0.001],
with_heatmaps_loss=[True],
heatmaps_loss_factor=[1.0]))
head.init_weights()
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head(inputs)
assert out[0].shape == torch.Size([1, 17, 32, 32])
# test tag_per_joint
head = AESimpleHead(
in_channels=512,
num_joints=17,
num_deconv_layers=0,
tag_per_joint=False,
with_ae_loss=[False],
extra={'final_conv_kernel': 3},
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=1,
ae_loss_type='exp',
with_ae_loss=[True],
push_loss_factor=[0.001],
pull_loss_factor=[0.001],
with_heatmaps_loss=[True],
heatmaps_loss_factor=[1.0]))
head.init_weights()
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head(inputs)
assert out[0].shape == torch.Size([1, 17, 32, 32])
head = AESimpleHead(
in_channels=512,
num_joints=17,
num_deconv_layers=0,
tag_per_joint=False,
with_ae_loss=[True],
extra={'final_conv_kernel': 3},
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=1,
ae_loss_type='exp',
with_ae_loss=[True],
push_loss_factor=[0.001],
pull_loss_factor=[0.001],
with_heatmaps_loss=[True],
heatmaps_loss_factor=[1.0]))
head.init_weights()
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head(inputs)
assert out[0].shape == torch.Size([1, 18, 32, 32])
head = AESimpleHead(
in_channels=512,
num_joints=17,
num_deconv_layers=0,
tag_per_joint=False,
with_ae_loss=[True],
extra={'final_conv_kernel': 3},
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=1,
ae_loss_type='exp',
with_ae_loss=[True],
push_loss_factor=[0.001],
pull_loss_factor=[0.001],
with_heatmaps_loss=[True],
heatmaps_loss_factor=[1.0]))
head.init_weights()
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head([inputs])
assert out[0].shape == torch.Size([1, 18, 32, 32])
def test_ae_higherresolution_head():
"""test bottom up AE higherresolution head."""
# test final_conv_kernel
with pytest.raises(AssertionError):
_ = AEHigherResolutionHead(
in_channels=512,
num_joints=17,
with_ae_loss=[True, False],
extra={'final_conv_kernel': 0},
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=2,
ae_loss_type='exp',
with_ae_loss=[True, False],
push_loss_factor=[0.001, 0.001],
pull_loss_factor=[0.001, 0.001],
with_heatmaps_loss=[True, True],
heatmaps_loss_factor=[1.0, 1.0]))
head = AEHigherResolutionHead(
in_channels=512,
num_joints=17,
with_ae_loss=[True, False],
extra={'final_conv_kernel': 3},
cat_output=[True],
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=2,
ae_loss_type='exp',
with_ae_loss=[True, False],
push_loss_factor=[0.001, 0.001],
pull_loss_factor=[0.001, 0.001],
with_heatmaps_loss=[True, True],
heatmaps_loss_factor=[1.0, 1.0]))
head.init_weights()
assert head.final_layers[0].padding == (1, 1)
head = AEHigherResolutionHead(
in_channels=512,
num_joints=17,
with_ae_loss=[True, False],
extra={'final_conv_kernel': 1},
cat_output=[True],
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=2,
ae_loss_type='exp',
with_ae_loss=[True, False],
push_loss_factor=[0.001, 0.001],
pull_loss_factor=[0.001, 0.001],
with_heatmaps_loss=[True, True],
heatmaps_loss_factor=[1.0, 1.0]))
head.init_weights()
assert head.final_layers[0].padding == (0, 0)
head = AEHigherResolutionHead(
in_channels=512,
num_joints=17,
with_ae_loss=[True, False],
cat_output=[True],
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=2,
ae_loss_type='exp',
with_ae_loss=[True, False],
push_loss_factor=[0.001, 0.001],
pull_loss_factor=[0.001, 0.001],
with_heatmaps_loss=[True, True],
heatmaps_loss_factor=[1.0, 1.0]))
head.init_weights()
assert head.final_layers[0].padding == (0, 0)
# test deconv layers
with pytest.raises(ValueError):
_ = AEHigherResolutionHead(
in_channels=512,
num_joints=17,
with_ae_loss=[True, False],
num_deconv_kernels=[1],
cat_output=[True],
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=2,
ae_loss_type='exp',
with_ae_loss=[True, False],
push_loss_factor=[0.001, 0.001],
pull_loss_factor=[0.001, 0.001],
with_heatmaps_loss=[True, True],
heatmaps_loss_factor=[1.0, 1.0]))
head = AEHigherResolutionHead(
in_channels=512,
num_joints=17,
with_ae_loss=[True, False],
num_deconv_kernels=[4],
cat_output=[True],
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=2,
ae_loss_type='exp',
with_ae_loss=[True, False],
push_loss_factor=[0.001, 0.001],
pull_loss_factor=[0.001, 0.001],
with_heatmaps_loss=[True, True],
heatmaps_loss_factor=[1.0, 1.0]))
head.init_weights()
assert head.deconv_layers[0][0][0].output_padding == (0, 0)
head = AEHigherResolutionHead(
in_channels=512,
num_joints=17,
with_ae_loss=[True, False],
num_deconv_kernels=[3],
cat_output=[True],
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=2,
ae_loss_type='exp',
with_ae_loss=[True, False],
push_loss_factor=[0.001, 0.001],
pull_loss_factor=[0.001, 0.001],
with_heatmaps_loss=[True, True],
heatmaps_loss_factor=[1.0, 1.0]))
head.init_weights()
assert head.deconv_layers[0][0][0].output_padding == (1, 1)
head = AEHigherResolutionHead(
in_channels=512,
num_joints=17,
with_ae_loss=[True, False],
num_deconv_kernels=[2],
cat_output=[True],
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=2,
ae_loss_type='exp',
with_ae_loss=[True, False],
push_loss_factor=[0.001, 0.001],
pull_loss_factor=[0.001, 0.001],
with_heatmaps_loss=[True, True],
heatmaps_loss_factor=[1.0, 1.0]))
head.init_weights()
assert head.deconv_layers[0][0][0].output_padding == (0, 0)
# test tag_per_joint & ae loss
head = AEHigherResolutionHead(
in_channels=512,
num_joints=17,
tag_per_joint=False,
with_ae_loss=[False, False],
extra={'final_conv_kernel': 3},
cat_output=[True],
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=2,
ae_loss_type='exp',
with_ae_loss=[False, False],
push_loss_factor=[0.001, 0.001],
pull_loss_factor=[0.001, 0.001],
with_heatmaps_loss=[True, True],
heatmaps_loss_factor=[1.0, 1.0]))
head.init_weights()
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head(inputs)
assert out[0].shape == torch.Size([1, 17, 32, 32])
assert out[1].shape == torch.Size([1, 17, 64, 64])
head = AEHigherResolutionHead(
in_channels=512,
num_joints=17,
tag_per_joint=False,
with_ae_loss=[True, False],
extra={'final_conv_kernel': 3},
cat_output=[True],
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=2,
ae_loss_type='exp',
with_ae_loss=[True, False],
push_loss_factor=[0.001, 0.001],
pull_loss_factor=[0.001, 0.001],
with_heatmaps_loss=[True, True],
heatmaps_loss_factor=[1.0, 1.0]))
head.init_weights()
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head(inputs)
assert out[0].shape == torch.Size([1, 18, 32, 32])
assert out[1].shape == torch.Size([1, 17, 64, 64])
head = AEHigherResolutionHead(
in_channels=512,
num_joints=17,
tag_per_joint=True,
with_ae_loss=[True, True],
extra={'final_conv_kernel': 3},
cat_output=[True],
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=2,
ae_loss_type='exp',
with_ae_loss=[True, True],
push_loss_factor=[0.001, 0.001],
pull_loss_factor=[0.001, 0.001],
with_heatmaps_loss=[True, True],
heatmaps_loss_factor=[1.0, 1.0]))
head.init_weights()
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head(inputs)
assert out[0].shape == torch.Size([1, 34, 32, 32])
assert out[1].shape == torch.Size([1, 34, 64, 64])
# cat_output
head = AEHigherResolutionHead(
in_channels=512,
num_joints=17,
tag_per_joint=True,
with_ae_loss=[True, True],
extra={'final_conv_kernel': 3},
cat_output=[False],
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=2,
ae_loss_type='exp',
with_ae_loss=[True, True],
push_loss_factor=[0.001, 0.001],
pull_loss_factor=[0.001, 0.001],
with_heatmaps_loss=[True, True],
heatmaps_loss_factor=[1.0, 1.0]))
head.init_weights()
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head(inputs)
assert out[0].shape == torch.Size([1, 34, 32, 32])
assert out[1].shape == torch.Size([1, 34, 64, 64])
head = AEHigherResolutionHead(
in_channels=512,
num_joints=17,
tag_per_joint=True,
with_ae_loss=[True, True],
extra={'final_conv_kernel': 3},
cat_output=[False],
loss_keypoint=dict(
type='MultiLossFactory',
num_joints=17,
num_stages=2,
ae_loss_type='exp',
with_ae_loss=[True, True],
push_loss_factor=[0.001, 0.001],
pull_loss_factor=[0.001, 0.001],
with_heatmaps_loss=[True, True],
heatmaps_loss_factor=[1.0, 1.0]))
head.init_weights()
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head([inputs])
assert out[0].shape == torch.Size([1, 34, 32, 32])
assert out[1].shape == torch.Size([1, 34, 64, 64])
def _demo_inputs(input_shape=(1, 3, 64, 64)):
"""Create a superset of inputs needed to run backbone.
Args:
input_shape (tuple): input batch dimensions.
Default: (1, 3, 64, 64).
Returns:
Random input tensor with the size of input_shape.
"""
inps = np.random.random(input_shape)
inps = torch.FloatTensor(inps)
return inps
@@ -0,0 +1,107 @@
# Copyright (c) OpenMMLab. All rights reserved.
import numpy as np
import torch
from mmpose.models import build_posenet
def test_interhand3d_forward():
# model settings
model_cfg = dict(
type='Interhand3D',
pretrained='torchvision://resnet50',
backbone=dict(type='ResNet', depth=50),
keypoint_head=dict(
type='Interhand3DHead',
keypoint_head_cfg=dict(
in_channels=2048,
out_channels=21 * 64,
depth_size=64,
num_deconv_layers=3,
num_deconv_filters=(256, 256, 256),
num_deconv_kernels=(4, 4, 4),
),
root_head_cfg=dict(
in_channels=2048,
heatmap_size=64,
hidden_dims=(512, ),
),
hand_type_head_cfg=dict(
in_channels=2048,
num_labels=2,
hidden_dims=(512, ),
),
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True),
loss_root_depth=dict(type='L1Loss'),
loss_hand_type=dict(type='BCELoss', use_target_weight=True),
),
train_cfg={},
test_cfg=dict(flip_test=True, shift_heatmap=True))
detector = build_posenet(model_cfg)
detector.init_weights()
input_shape = (2, 3, 256, 256)
mm_inputs = _demo_mm_inputs(input_shape)
imgs = mm_inputs.pop('imgs')
target = mm_inputs.pop('target')
target_weight = mm_inputs.pop('target_weight')
img_metas = mm_inputs.pop('img_metas')
# Test forward train
losses = detector.forward(
imgs, target, target_weight, img_metas, return_loss=True)
assert isinstance(losses, dict)
# Test forward test
with torch.no_grad():
_ = detector.forward(imgs, img_metas=img_metas, return_loss=False)
_ = detector.forward_dummy(imgs)
def _demo_mm_inputs(input_shape=(1, 3, 256, 256), num_outputs=None):
"""Create a superset of inputs needed to run test or train batches.
Args:
input_shape (tuple):
input batch dimensions
"""
(N, C, H, W) = input_shape
rng = np.random.RandomState(0)
imgs = rng.rand(*input_shape)
imgs = torch.FloatTensor(imgs)
target = [
imgs.new_zeros(N, 42, 64, H // 4, W // 4),
imgs.new_zeros(N, 1),
imgs.new_zeros(N, 2),
]
target_weight = [
imgs.new_ones(N, 42, 1),
imgs.new_ones(N, 1),
imgs.new_ones(N),
]
img_metas = [{
'img_shape': (H, W, C),
'center': np.array([W / 2, H / 2]),
'scale': np.array([0.5, 0.5]),
'bbox_score': 1.0,
'bbox_id': 0,
'flip_pairs': [],
'inference_channel': np.arange(42),
'image_file': '<demo>.png',
'heatmap3d_depth_bound': 400.0,
'root_depth_bound': 400.0,
} for _ in range(N)]
mm_inputs = {
'imgs': imgs.requires_grad_(True),
'target': target,
'target_weight': target_weight,
'img_metas': img_metas
}
return mm_inputs
@@ -0,0 +1,91 @@
# Copyright (c) OpenMMLab. All rights reserved.
import numpy as np
import torch
from mmpose.models import Interhand3DHead
def test_interhand_3d_head():
"""Test interhand 3d head."""
N = 4
input_shape = (N, 2048, 8, 8)
inputs = torch.rand(input_shape, dtype=torch.float32)
target = [
inputs.new_zeros(N, 42, 64, 64, 64),
inputs.new_zeros(N, 1),
inputs.new_zeros(N, 2),
]
target_weight = [
inputs.new_ones(N, 42, 1),
inputs.new_ones(N, 1),
inputs.new_ones(N),
]
img_metas = [{
'img_shape': (256, 256, 3),
'center': np.array([112, 112]),
'scale': np.array([0.5, 0.5]),
'bbox_score': 1.0,
'bbox_id': 0,
'flip_pairs': [],
'inference_channel': np.arange(42),
'image_file': '<demo>.png',
'heatmap3d_depth_bound': 400.0,
'root_depth_bound': 400.0,
} for _ in range(N)]
head = Interhand3DHead(
keypoint_head_cfg=dict(
in_channels=2048,
out_channels=21 * 64,
depth_size=64,
num_deconv_layers=3,
num_deconv_filters=(256, 256, 256),
num_deconv_kernels=(4, 4, 4),
),
root_head_cfg=dict(
in_channels=2048,
heatmap_size=64,
hidden_dims=(512, ),
),
hand_type_head_cfg=dict(
in_channels=2048,
num_labels=2,
hidden_dims=(512, ),
),
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True),
loss_root_depth=dict(type='L1Loss'),
loss_hand_type=dict(type='BCELoss', use_target_weight=True),
train_cfg={},
test_cfg={},
)
head.init_weights()
# test forward
output = head(inputs)
assert isinstance(output, list)
assert len(output) == 3
assert output[0].shape == (N, 42, 64, 64, 64)
assert output[1].shape == (N, 1)
assert output[2].shape == (N, 2)
# test loss computation
losses = head.get_loss(output, target, target_weight)
assert 'hand_loss' in losses
assert 'rel_root_loss' in losses
assert 'hand_type_loss' in losses
# test inference model
flip_pairs = [[i, 21 + i] for i in range(21)]
output = head.inference_model(inputs, flip_pairs)
assert isinstance(output, list)
assert len(output) == 3
assert output[0].shape == (N, 42, 64, 64, 64)
assert output[1].shape == (N, 1)
assert output[2].shape == (N, 2)
# test decode
result = head.decode(img_metas, output)
assert 'preds' in result
assert 'rel_root_depth' in result
assert 'hand_type' in result
@@ -0,0 +1,68 @@
# Copyright (c) OpenMMLab. All rights reserved.
import numpy as np
import torch
import torch.nn as nn
from mmcv.cnn import build_conv_layer, build_upsample_layer
def test_build_upsample_layer():
layer1 = nn.ConvTranspose2d(
in_channels=3,
out_channels=10,
kernel_size=3,
stride=2,
padding=1,
output_padding=1,
bias=False)
layer2 = build_upsample_layer(
dict(type='deconv'),
in_channels=3,
out_channels=10,
kernel_size=3,
stride=2,
padding=1,
output_padding=1,
bias=False)
layer2.load_state_dict(layer1.state_dict())
input_shape = (1, 3, 32, 32)
inputs = _demo_inputs(input_shape)
out1 = layer1(inputs)
out2 = layer2(inputs)
assert torch.equal(out1, out2)
def test_build_conv_layer():
layer1 = nn.Conv2d(
in_channels=3, out_channels=10, kernel_size=3, stride=1, padding=1)
layer2 = build_conv_layer(
cfg=dict(type='Conv2d'),
in_channels=3,
out_channels=10,
kernel_size=3,
stride=1,
padding=1)
layer2.load_state_dict(layer1.state_dict())
input_shape = (1, 3, 32, 32)
inputs = _demo_inputs(input_shape)
out1 = layer1(inputs)
out2 = layer2(inputs)
assert torch.equal(out1, out2)
def _demo_inputs(input_shape=(1, 3, 64, 64)):
"""Create a superset of inputs needed to run backbone.
Args:
input_shape (tuple): input batch dimensions.
Default: (1, 3, 64, 64).
Returns:
Random input tensor with the size of input_shape.
"""
inps = np.random.random(input_shape)
inps = torch.FloatTensor(inps)
return inps
@@ -0,0 +1,153 @@
# Copyright (c) OpenMMLab. All rights reserved.
import os.path as osp
import tempfile
import numpy as np
import torch
from mmpose.core.optimizer import build_optimizers
from mmpose.models.detectors.mesh import ParametricMesh
from tests.utils.mesh_utils import generate_smpl_weight_file
def test_parametric_mesh_forward():
"""Test parametric mesh forward."""
tmpdir = tempfile.TemporaryDirectory()
# generate weight file for SMPL model.
generate_smpl_weight_file(tmpdir.name)
# Test ParametricMesh without discriminator
model_cfg = dict(
pretrained=None,
backbone=dict(type='ResNet', depth=50),
mesh_head=dict(
type='HMRMeshHead',
in_channels=2048,
smpl_mean_params='tests/data/smpl/smpl_mean_params.npz'),
disc=None,
smpl=dict(
type='SMPL',
smpl_path=tmpdir.name,
joints_regressor=osp.join(tmpdir.name,
'test_joint_regressor.npy')),
train_cfg=dict(disc_step=1),
test_cfg=dict(
flip_test=False,
post_process='default',
shift_heatmap=True,
modulate_kernel=11),
loss_mesh=dict(
type='MeshLoss',
joints_2d_loss_weight=1,
joints_3d_loss_weight=1,
vertex_loss_weight=1,
smpl_pose_loss_weight=1,
smpl_beta_loss_weight=1,
focal_length=5000,
img_res=256),
loss_gan=None)
detector = ParametricMesh(**model_cfg)
detector.init_weights()
optimizers_config = dict(generator=dict(type='Adam', lr=0.0001))
optims = build_optimizers(detector, optimizers_config)
input_shape = (1, 3, 256, 256)
mm_inputs = _demo_mm_inputs(input_shape)
# Test forward train
output = detector.train_step(mm_inputs, optims)
assert isinstance(output, dict)
# Test forward test
with torch.no_grad():
output = detector.val_step(data_batch=mm_inputs)
assert isinstance(output, dict)
imgs = mm_inputs.pop('img')
img_metas = mm_inputs.pop('img_metas')
output = detector.forward(imgs, img_metas=img_metas, return_loss=False)
assert isinstance(output, dict)
# Test ParametricMesh with discriminator
model_cfg['disc'] = dict()
model_cfg['loss_gan'] = dict(
type='GANLoss',
gan_type='lsgan',
real_label_val=1.0,
fake_label_val=0.0,
loss_weight=1)
optimizers_config['discriminator'] = dict(type='Adam', lr=0.0001)
detector = ParametricMesh(**model_cfg)
detector.init_weights()
optims = build_optimizers(detector, optimizers_config)
input_shape = (1, 3, 256, 256)
mm_inputs = _demo_mm_inputs(input_shape)
# Test forward train
output = detector.train_step(mm_inputs, optims)
assert isinstance(output, dict)
# Test forward test
with torch.no_grad():
output = detector.val_step(data_batch=mm_inputs)
assert isinstance(output, dict)
imgs = mm_inputs.pop('img')
img_metas = mm_inputs.pop('img_metas')
output = detector.forward(imgs, img_metas=img_metas, return_loss=False)
assert isinstance(output, dict)
_ = detector.forward_dummy(imgs)
tmpdir.cleanup()
def _demo_mm_inputs(input_shape=(1, 3, 256, 256)):
"""Create a superset of inputs needed to run test or train batches.
Args:
input_shape (tuple):
input batch dimensions
"""
(N, C, H, W) = input_shape
rng = np.random.RandomState(0)
imgs = rng.rand(*input_shape)
joints_2d = np.zeros([N, 24, 2])
joints_2d_visible = np.ones([N, 24, 1])
joints_3d = np.zeros([N, 24, 3])
joints_3d_visible = np.ones([N, 24, 1])
pose = np.zeros([N, 72])
beta = np.zeros([N, 10])
has_smpl = np.ones([N])
mosh_theta = np.zeros([N, 3 + 72 + 10])
img_metas = [{
'img_shape': (H, W, C),
'center': np.array([W / 2, H / 2]),
'scale': np.array([0.5, 0.5]),
'bbox_score': 1.0,
'flip_pairs': [],
'inference_channel': np.arange(17),
'image_file': '<demo>.png',
} for _ in range(N)]
mm_inputs = {
'img': torch.FloatTensor(imgs).requires_grad_(True),
'joints_2d': torch.FloatTensor(joints_2d),
'joints_2d_visible': torch.FloatTensor(joints_2d_visible),
'joints_3d': torch.FloatTensor(joints_3d),
'joints_3d_visible': torch.FloatTensor(joints_3d_visible),
'pose': torch.FloatTensor(pose),
'beta': torch.FloatTensor(beta),
'has_smpl': torch.FloatTensor(has_smpl),
'img_metas': img_metas,
'mosh_theta': torch.FloatTensor(mosh_theta)
}
return mm_inputs
@@ -0,0 +1,76 @@
# Copyright (c) OpenMMLab. All rights reserved.
import numpy as np
import pytest
import torch
from mmpose.models import HMRMeshHead
from mmpose.models.misc.discriminator import SMPLDiscriminator
def test_mesh_hmr_head():
"""Test hmr mesh head."""
head = HMRMeshHead(in_channels=512)
head.init_weights()
input_shape = (1, 512, 8, 8)
inputs = _demo_inputs(input_shape)
out = head(inputs)
smpl_rotmat, smpl_shape, camera = out
assert smpl_rotmat.shape == torch.Size([1, 24, 3, 3])
assert smpl_shape.shape == torch.Size([1, 10])
assert camera.shape == torch.Size([1, 3])
"""Test hmr mesh head with assigned mean parameters and n_iter """
head = HMRMeshHead(
in_channels=512,
smpl_mean_params='tests/data/smpl/smpl_mean_params.npz',
n_iter=3)
head.init_weights()
input_shape = (1, 512, 8, 8)
inputs = _demo_inputs(input_shape)
out = head(inputs)
smpl_rotmat, smpl_shape, camera = out
assert smpl_rotmat.shape == torch.Size([1, 24, 3, 3])
assert smpl_shape.shape == torch.Size([1, 10])
assert camera.shape == torch.Size([1, 3])
# test discriminator with SMPL pose parameters
# in rotation matrix representation
disc = SMPLDiscriminator(
beta_channel=(10, 10, 5, 1),
per_joint_channel=(9, 32, 32, 16, 1),
full_pose_channel=(23 * 16, 256, 1))
pred_theta = (camera, smpl_rotmat, smpl_shape)
pred_score = disc(pred_theta)
assert pred_score.shape[1] == 25
# test discriminator with SMPL pose parameters
# in axis-angle representation
pred_theta = (camera, camera.new_zeros([1, 72]), smpl_shape)
pred_score = disc(pred_theta)
assert pred_score.shape[1] == 25
with pytest.raises(TypeError):
_ = SMPLDiscriminator(
beta_channel=[10, 10, 5, 1],
per_joint_channel=(9, 32, 32, 16, 1),
full_pose_channel=(23 * 16, 256, 1))
with pytest.raises(ValueError):
_ = SMPLDiscriminator(
beta_channel=(10, ),
per_joint_channel=(9, 32, 32, 16, 1),
full_pose_channel=(23 * 16, 256, 1))
def _demo_inputs(input_shape=(1, 3, 64, 64)):
"""Create a superset of inputs needed to run mesh head.
Args:
input_shape (tuple): input batch dimensions.
Default: (1, 3, 64, 64).
Returns:
Random input tensor with the size of input_shape.
"""
inps = np.random.random(input_shape)
inps = torch.FloatTensor(inps)
return inps
@@ -0,0 +1,116 @@
# Copyright (c) OpenMMLab. All rights reserved.
import numpy as np
import torch
from mmpose.models.detectors import MultiTask
def test_multitask_forward():
"""Test multitask forward."""
# build MultiTask detector
model_cfg = dict(
backbone=dict(type='ResNet', depth=50),
heads=[
dict(
type='DeepposeRegressionHead',
in_channels=2048,
num_joints=17,
loss_keypoint=dict(
type='SmoothL1Loss', use_target_weight=False)),
],
necks=[dict(type='GlobalAveragePooling')],
head2neck={0: 0},
pretrained=None,
)
model = MultiTask(**model_cfg)
# build inputs and target
mm_inputs = _demo_mm_inputs()
inputs = mm_inputs['img']
target = [mm_inputs['target_keypoints']]
target_weight = [mm_inputs['target_weight']]
img_metas = mm_inputs['img_metas']
# Test forward train
losses = model(inputs, target, target_weight, return_loss=True)
assert 'reg_loss' in losses and 'acc_pose' in losses
# Test forward test
outputs = model(inputs, img_metas=img_metas, return_loss=False)
assert 'preds' in outputs
# Test dummy forward
outputs = model.forward_dummy(inputs)
assert outputs[0].shape == torch.Size([1, 17, 2])
# Build multitask detector with no neck
model_cfg = dict(
backbone=dict(type='ResNet', depth=50),
heads=[
dict(
type='TopdownHeatmapSimpleHead',
in_channels=2048,
out_channels=17,
num_deconv_layers=3,
num_deconv_filters=(256, 256, 256),
num_deconv_kernels=(4, 4, 4),
loss_keypoint=dict(
type='JointsMSELoss', use_target_weight=True))
],
pretrained=None,
)
model = MultiTask(**model_cfg)
# build inputs and target
target = [mm_inputs['target_heatmap']]
# Test forward train
losses = model(inputs, target, target_weight, return_loss=True)
assert 'heatmap_loss' in losses and 'acc_pose' in losses
# Test forward test
outputs = model(inputs, img_metas=img_metas, return_loss=False)
assert 'preds' in outputs
# Test dummy forward
outputs = model.forward_dummy(inputs)
assert outputs[0].shape == torch.Size([1, 17, 64, 64])
def _demo_mm_inputs(input_shape=(1, 3, 256, 256)):
"""Create a superset of inputs needed to run test or train.
Args:
input_shape (tuple):
input batch dimensions
"""
(N, C, H, W) = input_shape
rng = np.random.RandomState(0)
imgs = rng.rand(*input_shape)
target_keypoints = np.zeros([N, 17, 2])
target_heatmap = np.zeros([N, 17, H // 4, W // 4])
target_weight = np.ones([N, 17, 1])
img_metas = [{
'img_shape': (H, W, C),
'center': np.array([W / 2, H / 2]),
'scale': np.array([0.5, 0.5]),
'bbox_score': 1.0,
'bbox_id': 0,
'flip_pairs': [],
'inference_channel': np.arange(17),
'image_file': '<demo>.png',
} for _ in range(N)]
mm_inputs = {
'img': torch.FloatTensor(imgs).requires_grad_(True),
'target_keypoints': torch.FloatTensor(target_keypoints),
'target_heatmap': torch.FloatTensor(target_heatmap),
'target_weight': torch.FloatTensor(target_weight),
'img_metas': img_metas,
}
return mm_inputs
@@ -0,0 +1,129 @@
# Copyright (c) OpenMMLab. All rights reserved.
import tempfile
from mmcv import Config
from mmpose.datasets import DATASETS, build_dataloader
from mmpose.models import builder
def test_voxelpose_forward():
dataset = 'Body3DMviewDirectPanopticDataset'
dataset_class = DATASETS.get(dataset)
dataset_info = Config.fromfile(
'configs/_base_/datasets/panoptic_body3d.py').dataset_info
space_size = [8000, 8000, 2000]
space_center = [0, -500, 800]
cube_size = [20, 20, 8]
data_cfg = dict(
image_size=[960, 512],
heatmap_size=[[240, 128]],
space_size=space_size,
space_center=space_center,
cube_size=cube_size,
num_joints=15,
seq_list=['160906_band1'],
cam_list=[(0, 12), (0, 6)],
num_cameras=2,
seq_frame_interval=1,
subset='train',
need_2d_label=True,
need_camera_param=True,
root_id=2)
pipeline = [
dict(
type='MultiItemProcess',
pipeline=[
dict(
type='BottomUpGenerateTarget', sigma=3, max_num_people=20)
]),
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='RenameKeys', key_pairs=[('targets', 'input_heatmaps')]),
dict(
type='Collect',
keys=['targets_3d', 'input_heatmaps'],
meta_keys=[
'camera', 'center', 'scale', 'joints_3d', 'num_persons',
'joints_3d_visible', 'roots_3d', 'sample_id'
]),
]
model_cfg = dict(
type='DetectAndRegress',
backbone=None,
human_detector=dict(
type='VoxelCenterDetector',
image_size=[960, 512],
heatmap_size=[240, 128],
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=3,
max_pool_kernel=3),
train_cfg=dict(dist_threshold=500000000.0),
test_cfg=dict(center_threshold=0.0),
),
pose_regressor=dict(
type='VoxelSinglePose',
image_size=[960, 512],
heatmap_size=[240, 128],
sub_space_size=[2000, 2000, 2000],
sub_cube_size=[20, 20, 8],
num_joints=15,
pose_net=dict(
type='V2VNet', input_channels=15, output_channels=15),
pose_head=dict(type='CuboidPoseHead', beta=100.0),
train_cfg=None,
test_cfg=None))
model = builder.build_posenet(model_cfg)
with tempfile.TemporaryDirectory() as tmpdir:
dataset = dataset_class(
ann_file=tmpdir + '/tmp_train.pkl',
img_prefix='tests/data/panoptic_body3d/',
data_cfg=data_cfg,
pipeline=pipeline,
dataset_info=dataset_info,
test_mode=False)
data_loader = build_dataloader(
dataset,
seed=None,
dist=False,
shuffle=False,
drop_last=False,
workers_per_gpu=1,
samples_per_gpu=1)
for data in data_loader:
# test forward_train
_ = model(
img=None,
img_metas=data['img_metas'].data[0],
return_loss=True,
targets_3d=data['targets_3d'],
input_heatmaps=data['input_heatmaps'])
# test forward_test
_ = model(
img=None,
img_metas=data['img_metas'].data[0],
return_loss=False,
input_heatmaps=data['input_heatmaps'])
@@ -0,0 +1,197 @@
# Copyright (c) OpenMMLab. All rights reserved.
import mmcv
import numpy as np
import torch
from mmpose.models import build_posenet
def _create_inputs(joint_num_in,
joint_channel_in,
joint_num_out,
joint_channel_out,
seq_len,
batch_size,
semi=False):
rng = np.random.RandomState(0)
pose_in = rng.rand(batch_size, joint_num_in * joint_channel_in, seq_len)
target = np.zeros((batch_size, joint_num_out, joint_channel_out),
dtype=np.float32)
target_weight = np.ones((batch_size, joint_num_out, joint_channel_out),
dtype=np.float32)
meta_info = {
'root_position': np.zeros((1, joint_channel_out), np.float32),
'root_position_index': 0,
'target_mean': np.zeros((joint_num_out, joint_channel_out),
np.float32),
'target_std': np.ones((joint_num_out, joint_channel_out), np.float32)
}
metas = [meta_info.copy() for _ in range(batch_size)]
inputs = {
'input': torch.FloatTensor(pose_in).requires_grad_(True),
'target': torch.FloatTensor(target),
'target_weight': torch.FloatTensor(target_weight),
'metas': metas,
}
if semi:
traj_target = np.zeros((batch_size, 1, joint_channel_out), np.float32)
unlabeled_pose_in = rng.rand(batch_size,
joint_num_in * joint_channel_in, seq_len)
unlabeled_target_2d = np.zeros(
(batch_size, joint_num_out, joint_channel_in), dtype=np.float32)
intrinsics = np.ones((batch_size, 4))
inputs['traj_target'] = torch.FloatTensor(traj_target)
inputs['unlabeled_input'] = torch.FloatTensor(
unlabeled_pose_in).requires_grad_(True)
inputs['unlabeled_target_2d'] = torch.FloatTensor(unlabeled_target_2d)
inputs['intrinsics'] = torch.FloatTensor(intrinsics)
return inputs
def test_pose_lifter_forward():
# Test forward train for supervised learning with pose model only
model_cfg = dict(
type='PoseLifter',
pretrained=None,
backbone=dict(type='TCN', in_channels=2 * 17),
keypoint_head=dict(
type='TemporalRegressionHead',
in_channels=1024,
num_joints=16,
max_norm=1.0,
loss_keypoint=dict(type='MPJPELoss'),
test_cfg=dict(restore_global_position=True)),
train_cfg=dict(),
test_cfg=dict())
cfg = mmcv.Config({'model': model_cfg})
detector = build_posenet(cfg.model)
detector.init_weights()
inputs = _create_inputs(
joint_num_in=17,
joint_channel_in=2,
joint_num_out=16,
joint_channel_out=3,
seq_len=27,
batch_size=8)
losses = detector.forward(
inputs['input'],
inputs['target'],
inputs['target_weight'],
inputs['metas'],
return_loss=True)
assert isinstance(losses, dict)
# Test forward test for supervised learning with pose model only
with torch.no_grad():
_ = detector.forward(
inputs['input'],
inputs['target'],
inputs['target_weight'],
inputs['metas'],
return_loss=False)
_ = detector.forward_dummy(inputs['input'])
# Test forward train for semi-supervised learning
model_cfg = dict(
type='PoseLifter',
pretrained=None,
backbone=dict(type='TCN', in_channels=2 * 17),
keypoint_head=dict(
type='TemporalRegressionHead',
in_channels=1024,
num_joints=17,
loss_keypoint=dict(type='MPJPELoss'),
test_cfg=dict(restore_global_position=True)),
traj_backbone=dict(type='TCN', in_channels=2 * 17),
traj_head=dict(
type='TemporalRegressionHead',
in_channels=1024,
num_joints=1,
loss_keypoint=dict(type='MPJPELoss'),
is_trajectory=True),
loss_semi=dict(
type='SemiSupervisionLoss',
joint_parents=[
0, 0, 1, 2, 0, 4, 5, 0, 7, 8, 9, 8, 11, 12, 8, 14, 15
]),
train_cfg=dict(),
test_cfg=dict())
cfg = mmcv.Config({'model': model_cfg})
detector = build_posenet(cfg.model)
detector.init_weights()
inputs = _create_inputs(
joint_num_in=17,
joint_channel_in=2,
joint_num_out=17,
joint_channel_out=3,
seq_len=27,
batch_size=8,
semi=True)
losses = detector.forward(**inputs, return_loss=True)
assert isinstance(losses, dict)
assert 'proj_loss' in losses
# Test forward test for semi-supervised learning
with torch.no_grad():
_ = detector.forward(**inputs, return_loss=False)
_ = detector.forward_dummy(inputs['input'])
# Test forward train for supervised learning with pose model and trajectory
# model sharing one backbone
model_cfg = dict(
type='PoseLifter',
pretrained=None,
backbone=dict(type='TCN', in_channels=2 * 17),
keypoint_head=dict(
type='TemporalRegressionHead',
in_channels=1024,
num_joints=17,
loss_keypoint=dict(type='MPJPELoss'),
test_cfg=dict(restore_global_position=True)),
traj_head=dict(
type='TemporalRegressionHead',
in_channels=1024,
num_joints=1,
loss_keypoint=dict(type='MPJPELoss'),
is_trajectory=True),
train_cfg=dict(),
test_cfg=dict())
cfg = mmcv.Config({'model': model_cfg})
detector = build_posenet(cfg.model)
detector.init_weights()
inputs = _create_inputs(
joint_num_in=17,
joint_channel_in=2,
joint_num_out=17,
joint_channel_out=3,
seq_len=27,
batch_size=8,
semi=True)
losses = detector.forward(**inputs, return_loss=True)
assert isinstance(losses, dict)
assert 'traj_loss' in losses
# Test forward test for semi-supervised learning with pose model and
# trajectory model sharing one backbone
with torch.no_grad():
_ = detector.forward(**inputs, return_loss=False)
_ = detector.forward_dummy(inputs['input'])
@@ -0,0 +1,104 @@
# Copyright (c) OpenMMLab. All rights reserved.
import numpy as np
import pytest
import torch
from mmpose.models import TemporalRegressionHead
def test_temporal_regression_head():
"""Test temporal head."""
# w/o global position restoration
head = TemporalRegressionHead(
in_channels=1024,
num_joints=17,
loss_keypoint=dict(type='MPJPELoss', use_target_weight=True),
test_cfg=dict(restore_global_position=False))
head.init_weights()
with pytest.raises(AssertionError):
# ndim of the input tensor should be 3
input_shape = (1, 1024, 1, 1)
inputs = _demo_inputs(input_shape)
_ = head(inputs)
with pytest.raises(AssertionError):
# size of the last dim should be 1
input_shape = (1, 1024, 3)
inputs = _demo_inputs(input_shape)
_ = head(inputs)
input_shape = (1, 1024, 1)
inputs = _demo_inputs(input_shape)
out = head(inputs)
assert out.shape == torch.Size([1, 17, 3])
loss = head.get_loss(out, out, None)
assert torch.allclose(loss['reg_loss'], torch.tensor(0.))
_ = head.inference_model(inputs)
_ = head.inference_model(inputs, [(0, 1), (2, 3)])
metas = [{}]
acc = head.get_accuracy(out, out, None, metas=metas)
assert acc['mpjpe'] == 0.
np.testing.assert_almost_equal(acc['p_mpjpe'], 0., decimal=6)
# w/ global position restoration
head = TemporalRegressionHead(
in_channels=1024,
num_joints=16,
loss_keypoint=dict(type='MPJPELoss', use_target_weight=True),
test_cfg=dict(restore_global_position=True))
head.init_weights()
input_shape = (1, 1024, 1)
inputs = _demo_inputs(input_shape)
metas = [{
'root_position': np.zeros((1, 3)),
'root_position_index': 0,
'root_weight': 1.
}]
out = head(inputs)
assert out.shape == torch.Size([1, 16, 3])
inference_out = head.inference_model(inputs)
acc = head.get_accuracy(out, out, torch.ones_like(out), metas)
assert acc['mpjpe'] == 0.
np.testing.assert_almost_equal(acc['p_mpjpe'], 0.)
_ = head.decode(metas, inference_out)
# trajectory model (only predict root position)
head = TemporalRegressionHead(
in_channels=1024,
num_joints=1,
loss_keypoint=dict(type='MPJPELoss', use_target_weight=True),
is_trajectory=True,
test_cfg=dict(restore_global_position=False))
head.init_weights()
input_shape = (1, 1024, 1)
inputs = _demo_inputs(input_shape)
out = head(inputs)
assert out.shape == torch.Size([1, 1, 3])
loss = head.get_loss(out, out.squeeze(1), torch.ones_like(out))
assert torch.allclose(loss['traj_loss'], torch.tensor(0.))
def _demo_inputs(input_shape=(1, 1024, 1)):
"""Create a superset of inputs needed to run head.
Args:
input_shape (tuple): input batch dimensions.
Default: (1, 1024, 1).
Returns:
Random input tensor with the size of input_shape.
"""
inps = np.random.random(input_shape)
inps = torch.FloatTensor(inps)
return inps
@@ -0,0 +1,517 @@
# Copyright (c) OpenMMLab. All rights reserved.
import copy
import numpy as np
import torch
from mmpose.models.detectors import PoseWarper, TopDown
def test_vipnas_forward():
# model settings
channel_cfg = dict(
num_output_channels=17,
dataset_joints=17,
dataset_channel=[
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
],
inference_channel=[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
])
model_cfg = dict(
type='TopDown',
pretrained=None,
backbone=dict(type='ViPNAS_ResNet', depth=50),
keypoint_head=dict(
type='ViPNASHeatmapSimpleHead',
in_channels=608,
out_channels=channel_cfg['num_output_channels'],
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True)),
train_cfg=dict(),
test_cfg=dict(
flip_test=True,
post_process='default',
shift_heatmap=True,
modulate_kernel=11))
detector = TopDown(model_cfg['backbone'], None, model_cfg['keypoint_head'],
model_cfg['train_cfg'], model_cfg['test_cfg'],
model_cfg['pretrained'])
input_shape = (1, 3, 256, 256)
mm_inputs = _demo_mm_inputs(input_shape)
imgs = mm_inputs.pop('imgs')
target = mm_inputs.pop('target')
target_weight = mm_inputs.pop('target_weight')
img_metas = mm_inputs.pop('img_metas')
# Test forward train
losses = detector.forward(
imgs, target, target_weight, img_metas, return_loss=True)
assert isinstance(losses, dict)
# Test forward test
with torch.no_grad():
_ = detector.forward(imgs, img_metas=img_metas, return_loss=False)
def test_topdown_forward():
model_cfg = dict(
type='TopDown',
pretrained=None,
backbone=dict(type='ResNet', depth=18),
keypoint_head=dict(
type='TopdownHeatmapSimpleHead',
in_channels=512,
out_channels=17,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True)),
train_cfg=dict(),
test_cfg=dict(
flip_test=True,
post_process='default',
shift_heatmap=True,
modulate_kernel=11))
detector = TopDown(model_cfg['backbone'], None, model_cfg['keypoint_head'],
model_cfg['train_cfg'], model_cfg['test_cfg'],
model_cfg['pretrained'])
detector.init_weights()
input_shape = (1, 3, 256, 256)
mm_inputs = _demo_mm_inputs(input_shape)
imgs = mm_inputs.pop('imgs')
target = mm_inputs.pop('target')
target_weight = mm_inputs.pop('target_weight')
img_metas = mm_inputs.pop('img_metas')
# Test forward train
losses = detector.forward(
imgs, target, target_weight, img_metas, return_loss=True)
assert isinstance(losses, dict)
# Test forward test
with torch.no_grad():
_ = detector.forward(imgs, img_metas=img_metas, return_loss=False)
# flip test
model_cfg = dict(
type='TopDown',
pretrained=None,
backbone=dict(
type='HourglassNet',
num_stacks=1,
),
keypoint_head=dict(
type='TopdownHeatmapMultiStageHead',
in_channels=256,
out_channels=17,
num_stages=1,
num_deconv_layers=0,
extra=dict(final_conv_kernel=1, ),
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=False)),
train_cfg=dict(),
test_cfg=dict(
flip_test=True,
post_process='default',
shift_heatmap=True,
modulate_kernel=11))
detector = TopDown(model_cfg['backbone'], None, model_cfg['keypoint_head'],
model_cfg['train_cfg'], model_cfg['test_cfg'],
model_cfg['pretrained'])
# Test forward train
losses = detector.forward(
imgs, target, target_weight, img_metas, return_loss=True)
assert isinstance(losses, dict)
# Test forward test
with torch.no_grad():
_ = detector.forward(imgs, img_metas=img_metas, return_loss=False)
model_cfg = dict(
type='TopDown',
pretrained=None,
backbone=dict(
type='HourglassNet',
num_stacks=1,
),
keypoint_head=dict(
type='TopdownHeatmapMultiStageHead',
in_channels=256,
out_channels=17,
num_stages=1,
num_deconv_layers=0,
extra=dict(final_conv_kernel=1, ),
loss_keypoint=[
dict(
type='JointsMSELoss',
use_target_weight=True,
loss_weight=1.)
]),
train_cfg=dict(),
test_cfg=dict(
flip_test=True,
post_process='default',
shift_heatmap=True,
modulate_kernel=11))
detector = TopDown(model_cfg['backbone'], None, model_cfg['keypoint_head'],
model_cfg['train_cfg'], model_cfg['test_cfg'],
model_cfg['pretrained'])
detector.init_weights()
input_shape = (1, 3, 256, 256)
mm_inputs = _demo_mm_inputs(input_shape, num_outputs=None)
imgs = mm_inputs.pop('imgs')
target = mm_inputs.pop('target')
target_weight = mm_inputs.pop('target_weight')
img_metas = mm_inputs.pop('img_metas')
# Test forward train
losses = detector.forward(
imgs, target, target_weight, img_metas, return_loss=True)
assert isinstance(losses, dict)
# Test forward test
with torch.no_grad():
_ = detector.forward(imgs, img_metas=img_metas, return_loss=False)
model_cfg = dict(
type='TopDown',
pretrained=None,
backbone=dict(
type='RSN',
unit_channels=256,
num_stages=1,
num_units=4,
num_blocks=[2, 2, 2, 2],
num_steps=4,
norm_cfg=dict(type='BN')),
keypoint_head=dict(
type='TopdownHeatmapMSMUHead',
out_shape=(64, 48),
unit_channels=256,
out_channels=17,
num_stages=1,
num_units=4,
use_prm=False,
norm_cfg=dict(type='BN'),
loss_keypoint=[dict(type='JointsMSELoss', use_target_weight=True)]
* 3 + [dict(type='JointsOHKMMSELoss', use_target_weight=True)]),
train_cfg=dict(num_units=4),
test_cfg=dict(
flip_test=True,
post_process='default',
shift_heatmap=False,
unbiased_decoding=False,
modulate_kernel=5))
detector = TopDown(model_cfg['backbone'], None, model_cfg['keypoint_head'],
model_cfg['train_cfg'], model_cfg['test_cfg'],
model_cfg['pretrained'])
detector.init_weights()
input_shape = (1, 3, 256, 192)
mm_inputs = _demo_mm_inputs(input_shape, num_outputs=4)
imgs = mm_inputs.pop('imgs')
target = mm_inputs.pop('target')
target_weight = mm_inputs.pop('target_weight')
img_metas = mm_inputs.pop('img_metas')
# Test forward train
losses = detector.forward(
imgs, target, target_weight, img_metas, return_loss=True)
assert isinstance(losses, dict)
# Test forward test
with torch.no_grad():
_ = detector.forward(imgs, img_metas=img_metas, return_loss=False)
_ = detector.forward_dummy(imgs)
def test_posewarper_forward():
# test PoseWarper
model_cfg = dict(
type='PoseWarper',
pretrained=None,
backbone=dict(
type='HRNet',
in_channels=3,
extra=dict(
stage1=dict(
num_modules=1,
num_branches=1,
block='BOTTLENECK',
num_blocks=(4, ),
num_channels=(64, )),
stage2=dict(
num_modules=1,
num_branches=2,
block='BASIC',
num_blocks=(4, 4),
num_channels=(48, 96)),
stage3=dict(
num_modules=4,
num_branches=3,
block='BASIC',
num_blocks=(4, 4, 4),
num_channels=(48, 96, 192)),
stage4=dict(
num_modules=3,
num_branches=4,
block='BASIC',
num_blocks=(4, 4, 4, 4),
num_channels=(48, 96, 192, 384))),
frozen_stages=4,
),
concat_tensors=True,
neck=dict(
type='PoseWarperNeck',
in_channels=48,
freeze_trans_layer=True,
out_channels=17,
inner_channels=128,
deform_groups=17,
dilations=(3, 6, 12, 18, 24),
trans_conv_kernel=1,
res_blocks_cfg=dict(block='BASIC', num_blocks=20),
offsets_kernel=3,
deform_conv_kernel=3),
keypoint_head=dict(
type='TopdownHeatmapSimpleHead',
in_channels=17,
out_channels=17,
num_deconv_layers=0,
extra=dict(final_conv_kernel=0, ),
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True)),
train_cfg=dict(),
test_cfg=dict(
flip_test=False,
post_process='default',
shift_heatmap=True,
modulate_kernel=11))
detector = PoseWarper(model_cfg['backbone'], model_cfg['neck'],
model_cfg['keypoint_head'], model_cfg['train_cfg'],
model_cfg['test_cfg'], model_cfg['pretrained'], None,
model_cfg['concat_tensors'])
assert detector.concat_tensors
detector.init_weights()
input_shape = (2, 3, 64, 64)
num_frames = 2
mm_inputs = _demo_mm_inputs(input_shape, None, num_frames)
imgs = mm_inputs.pop('imgs')
target = mm_inputs.pop('target')
target_weight = mm_inputs.pop('target_weight')
img_metas = mm_inputs.pop('img_metas')
# Test forward train
losses = detector.forward(
imgs, target, target_weight, img_metas, return_loss=True)
assert isinstance(losses, dict)
# Test forward test
with torch.no_grad():
_ = detector.forward(imgs, img_metas=img_metas, return_loss=False)
_ = detector.forward_dummy(imgs)
# test argument 'concat_tensors'
model_cfg_copy = copy.deepcopy(model_cfg)
model_cfg_copy['concat_tensors'] = False
detector = PoseWarper(model_cfg_copy['backbone'], model_cfg_copy['neck'],
model_cfg_copy['keypoint_head'],
model_cfg_copy['train_cfg'],
model_cfg_copy['test_cfg'],
model_cfg_copy['pretrained'], None,
model_cfg_copy['concat_tensors'])
assert not detector.concat_tensors
detector.init_weights()
input_shape = (2, 3, 64, 64)
num_frames = 2
mm_inputs = _demo_mm_inputs(input_shape, None, num_frames)
imgs = mm_inputs.pop('imgs')
target = mm_inputs.pop('target')
target_weight = mm_inputs.pop('target_weight')
img_metas = mm_inputs.pop('img_metas')
# Test forward train
losses = detector.forward(
imgs, target, target_weight, img_metas, return_loss=True)
assert isinstance(losses, dict)
# Test forward test
with torch.no_grad():
_ = detector.forward(imgs, img_metas=img_metas, return_loss=False)
_ = detector.forward_dummy(imgs)
# flip test
model_cfg_copy = copy.deepcopy(model_cfg)
model_cfg_copy['test_cfg']['flip_test'] = True
detector = PoseWarper(model_cfg_copy['backbone'], model_cfg_copy['neck'],
model_cfg_copy['keypoint_head'],
model_cfg_copy['train_cfg'],
model_cfg_copy['test_cfg'],
model_cfg_copy['pretrained'], None,
model_cfg_copy['concat_tensors'])
detector.init_weights()
input_shape = (1, 3, 64, 64)
num_frames = 2
mm_inputs = _demo_mm_inputs(input_shape, None, num_frames)
imgs = mm_inputs.pop('imgs')
target = mm_inputs.pop('target')
target_weight = mm_inputs.pop('target_weight')
img_metas = mm_inputs.pop('img_metas')
# Test forward train
losses = detector.forward(
imgs, target, target_weight, img_metas, return_loss=True)
assert isinstance(losses, dict)
# Test forward test
with torch.no_grad():
_ = detector.forward(imgs, img_metas=img_metas, return_loss=False)
_ = detector.forward_dummy(imgs)
# test different number of dilations
model_cfg_copy = copy.deepcopy(model_cfg)
model_cfg_copy['neck']['dilations'] = (3, 6, 12)
detector = PoseWarper(model_cfg_copy['backbone'], model_cfg_copy['neck'],
model_cfg_copy['keypoint_head'],
model_cfg_copy['train_cfg'],
model_cfg_copy['test_cfg'],
model_cfg_copy['pretrained'], None,
model_cfg_copy['concat_tensors'])
detector.init_weights()
input_shape = (2, 3, 64, 64)
num_frames = 2
mm_inputs = _demo_mm_inputs(input_shape, None, num_frames)
imgs = mm_inputs.pop('imgs')
target = mm_inputs.pop('target')
target_weight = mm_inputs.pop('target_weight')
img_metas = mm_inputs.pop('img_metas')
# Test forward train
losses = detector.forward(
imgs, target, target_weight, img_metas, return_loss=True)
assert isinstance(losses, dict)
# Test forward test
with torch.no_grad():
_ = detector.forward(imgs, img_metas=img_metas, return_loss=False)
_ = detector.forward_dummy(imgs)
# test different backbone, change head accordingly
model_cfg_copy = copy.deepcopy(model_cfg)
model_cfg_copy['backbone'] = dict(type='ResNet', depth=18)
model_cfg_copy['neck']['in_channels'] = 512
model_cfg_copy['keypoint_head'] = dict(
type='TopdownHeatmapSimpleHead',
in_channels=17,
out_channels=17,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
detector = PoseWarper(model_cfg_copy['backbone'], model_cfg_copy['neck'],
model_cfg_copy['keypoint_head'],
model_cfg_copy['train_cfg'],
model_cfg_copy['test_cfg'],
model_cfg_copy['pretrained'], None,
model_cfg_copy['concat_tensors'])
detector.init_weights()
input_shape = (1, 3, 64, 64)
num_frames = 2
mm_inputs = _demo_mm_inputs(input_shape, None, num_frames)
imgs = mm_inputs.pop('imgs')
target = mm_inputs.pop('target')
target_weight = mm_inputs.pop('target_weight')
img_metas = mm_inputs.pop('img_metas')
# Test forward train
losses = detector.forward(
imgs, target, target_weight, img_metas, return_loss=True)
assert isinstance(losses, dict)
# Test forward test
with torch.no_grad():
_ = detector.forward(imgs, img_metas=img_metas, return_loss=False)
_ = detector.forward_dummy(imgs)
def _demo_mm_inputs(
input_shape=(1, 3, 256, 256), num_outputs=None, num_frames=1):
"""Create a superset of inputs needed to run test or train batches.
Args:
input_shape (tuple):
input batch dimensions
num_frames (int):
number of frames for each sample, default: 1,
if larger than 1, return a list of tensors
"""
(N, C, H, W) = input_shape
rng = np.random.RandomState(0)
imgs = rng.rand(*input_shape)
if num_outputs is not None:
target = np.zeros([N, num_outputs, 17, H // 4, W // 4],
dtype=np.float32)
target_weight = np.ones([N, num_outputs, 17, 1], dtype=np.float32)
else:
target = np.zeros([N, 17, H // 4, W // 4], dtype=np.float32)
target_weight = np.ones([N, 17, 1], dtype=np.float32)
img_metas = [{
'img_shape': (H, W, C),
'center': np.array([W / 2, H / 2]),
'scale': np.array([0.5, 0.5]),
'bbox_score': 1.0,
'bbox_id': 0,
'flip_pairs': [],
'inference_channel': np.arange(17),
'image_file': '<demo>.png',
'frame_weight': np.random.uniform(0, 1, num_frames),
} for _ in range(N)]
mm_inputs = {
'target': torch.FloatTensor(target),
'target_weight': torch.FloatTensor(target_weight),
'img_metas': img_metas
}
if num_frames == 1:
imgs = torch.FloatTensor(rng.rand(*input_shape)).requires_grad_(True)
else:
imgs = [
torch.FloatTensor(rng.rand(*input_shape)).requires_grad_(True)
for _ in range(num_frames)
]
mm_inputs['imgs'] = imgs
return mm_inputs
@@ -0,0 +1,518 @@
# Copyright (c) OpenMMLab. All rights reserved.
import numpy as np
import pytest
import torch
from mmpose.models import (DeepposeRegressionHead, TopdownHeatmapMSMUHead,
TopdownHeatmapMultiStageHead,
TopdownHeatmapSimpleHead, ViPNASHeatmapSimpleHead)
def test_vipnas_simple_head():
"""Test simple head."""
with pytest.raises(TypeError):
# extra
_ = ViPNASHeatmapSimpleHead(
out_channels=3,
in_channels=512,
extra=[],
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
with pytest.raises(TypeError):
head = ViPNASHeatmapSimpleHead(
out_channels=3, in_channels=512, extra={'final_conv_kernel': 1})
# test num deconv layers
with pytest.raises(ValueError):
_ = ViPNASHeatmapSimpleHead(
out_channels=3,
in_channels=512,
num_deconv_layers=-1,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
_ = ViPNASHeatmapSimpleHead(
out_channels=3,
in_channels=512,
num_deconv_layers=0,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
with pytest.raises(ValueError):
# the number of layers should match
_ = ViPNASHeatmapSimpleHead(
out_channels=3,
in_channels=512,
num_deconv_layers=3,
num_deconv_filters=(256, 256),
num_deconv_kernels=(4, 4),
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
with pytest.raises(ValueError):
# the number of kernels should match
_ = ViPNASHeatmapSimpleHead(
out_channels=3,
in_channels=512,
num_deconv_layers=3,
num_deconv_filters=(256, 256, 256),
num_deconv_kernels=(4, 4),
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
with pytest.raises(ValueError):
# the deconv kernels should be 4, 3, 2
_ = ViPNASHeatmapSimpleHead(
out_channels=3,
in_channels=512,
num_deconv_layers=3,
num_deconv_filters=(256, 256, 256),
num_deconv_kernels=(3, 2, 0),
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
with pytest.raises(ValueError):
# the deconv kernels should be 4, 3, 2
_ = ViPNASHeatmapSimpleHead(
out_channels=3,
in_channels=512,
num_deconv_layers=3,
num_deconv_filters=(256, 256, 256),
num_deconv_kernels=(4, 4, -1),
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
# test final_conv_kernel
head = ViPNASHeatmapSimpleHead(
out_channels=3,
in_channels=512,
extra={'final_conv_kernel': 3},
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
head.init_weights()
assert head.final_layer.padding == (1, 1)
head = ViPNASHeatmapSimpleHead(
out_channels=3,
in_channels=512,
extra={'final_conv_kernel': 1},
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
assert head.final_layer.padding == (0, 0)
_ = ViPNASHeatmapSimpleHead(
out_channels=3,
in_channels=512,
extra={'final_conv_kernel': 0},
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
head = ViPNASHeatmapSimpleHead(
out_channels=3,
in_channels=512,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True),
extra=dict(
final_conv_kernel=1, num_conv_layers=1, num_conv_kernels=(1, )))
assert len(head.final_layer) == 4
head = ViPNASHeatmapSimpleHead(
out_channels=3,
in_channels=512,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head(inputs)
assert out.shape == torch.Size([1, 3, 256, 256])
head = ViPNASHeatmapSimpleHead(
out_channels=3,
in_channels=512,
num_deconv_layers=0,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head(inputs)
assert out.shape == torch.Size([1, 3, 32, 32])
head = ViPNASHeatmapSimpleHead(
out_channels=3,
in_channels=512,
num_deconv_layers=0,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head([inputs])
assert out.shape == torch.Size([1, 3, 32, 32])
head.init_weights()
def test_top_down_simple_head():
"""Test simple head."""
with pytest.raises(TypeError):
# extra
_ = TopdownHeatmapSimpleHead(
out_channels=3,
in_channels=512,
extra=[],
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
with pytest.raises(TypeError):
head = TopdownHeatmapSimpleHead(
out_channels=3, in_channels=512, extra={'final_conv_kernel': 1})
# test num deconv layers
with pytest.raises(ValueError):
_ = TopdownHeatmapSimpleHead(
out_channels=3,
in_channels=512,
num_deconv_layers=-1,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
_ = TopdownHeatmapSimpleHead(
out_channels=3,
in_channels=512,
num_deconv_layers=0,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
with pytest.raises(ValueError):
# the number of layers should match
_ = TopdownHeatmapSimpleHead(
out_channels=3,
in_channels=512,
num_deconv_layers=3,
num_deconv_filters=(256, 256),
num_deconv_kernels=(4, 4),
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
with pytest.raises(ValueError):
# the number of kernels should match
_ = TopdownHeatmapSimpleHead(
out_channels=3,
in_channels=512,
num_deconv_layers=3,
num_deconv_filters=(256, 256, 256),
num_deconv_kernels=(4, 4),
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
with pytest.raises(ValueError):
# the deconv kernels should be 4, 3, 2
_ = TopdownHeatmapSimpleHead(
out_channels=3,
in_channels=512,
num_deconv_layers=3,
num_deconv_filters=(256, 256, 256),
num_deconv_kernels=(3, 2, 0),
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
with pytest.raises(ValueError):
# the deconv kernels should be 4, 3, 2
_ = TopdownHeatmapSimpleHead(
out_channels=3,
in_channels=512,
num_deconv_layers=3,
num_deconv_filters=(256, 256, 256),
num_deconv_kernels=(4, 4, -1),
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
# test final_conv_kernel
head = TopdownHeatmapSimpleHead(
out_channels=3,
in_channels=512,
extra={'final_conv_kernel': 3},
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
head.init_weights()
assert head.final_layer.padding == (1, 1)
head = TopdownHeatmapSimpleHead(
out_channels=3,
in_channels=512,
extra={'final_conv_kernel': 1},
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
assert head.final_layer.padding == (0, 0)
_ = TopdownHeatmapSimpleHead(
out_channels=3,
in_channels=512,
extra={'final_conv_kernel': 0},
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
head = TopdownHeatmapSimpleHead(
out_channels=3,
in_channels=512,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True),
extra=dict(
final_conv_kernel=1, num_conv_layers=1, num_conv_kernels=(1, )))
assert len(head.final_layer) == 4
head = TopdownHeatmapSimpleHead(
out_channels=3,
in_channels=512,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head(inputs)
assert out.shape == torch.Size([1, 3, 256, 256])
head = TopdownHeatmapSimpleHead(
out_channels=3,
in_channels=512,
num_deconv_layers=0,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head(inputs)
assert out.shape == torch.Size([1, 3, 32, 32])
head = TopdownHeatmapSimpleHead(
out_channels=3,
in_channels=512,
num_deconv_layers=0,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head([inputs])
assert out.shape == torch.Size([1, 3, 32, 32])
head.init_weights()
def test_top_down_multistage_head():
"""Test multistage head."""
with pytest.raises(TypeError):
# the number of layers should match
_ = TopdownHeatmapMultiStageHead(
out_channels=3,
in_channels=512,
num_stages=1,
extra=[],
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
# test num deconv layers
with pytest.raises(ValueError):
_ = TopdownHeatmapMultiStageHead(
out_channels=3,
in_channels=512,
num_deconv_layers=-1,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
_ = TopdownHeatmapMultiStageHead(
out_channels=3,
in_channels=512,
num_deconv_layers=0,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
with pytest.raises(ValueError):
# the number of layers should match
_ = TopdownHeatmapMultiStageHead(
out_channels=3,
in_channels=512,
num_stages=1,
num_deconv_layers=3,
num_deconv_filters=(256, 256),
num_deconv_kernels=(4, 4),
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
with pytest.raises(ValueError):
# the number of kernels should match
_ = TopdownHeatmapMultiStageHead(
out_channels=3,
in_channels=512,
num_stages=1,
num_deconv_layers=3,
num_deconv_filters=(256, 256, 256),
num_deconv_kernels=(4, 4),
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
with pytest.raises(ValueError):
# the deconv kernels should be 4, 3, 2
_ = TopdownHeatmapMultiStageHead(
out_channels=3,
in_channels=512,
num_stages=1,
num_deconv_layers=3,
num_deconv_filters=(256, 256, 256),
num_deconv_kernels=(3, 2, 0),
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
with pytest.raises(ValueError):
# the deconv kernels should be 4, 3, 2
_ = TopdownHeatmapMultiStageHead(
out_channels=3,
in_channels=512,
num_deconv_layers=3,
num_deconv_filters=(256, 256, 256),
num_deconv_kernels=(4, 4, -1),
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
with pytest.raises(AssertionError):
# inputs should be list
head = TopdownHeatmapMultiStageHead(
out_channels=3,
in_channels=512,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head(inputs)
# test final_conv_kernel
head = TopdownHeatmapMultiStageHead(
out_channels=3,
in_channels=512,
extra={'final_conv_kernel': 3},
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
head.init_weights()
assert head.multi_final_layers[0].padding == (1, 1)
head = TopdownHeatmapMultiStageHead(
out_channels=3,
in_channels=512,
extra={'final_conv_kernel': 1},
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
assert head.multi_final_layers[0].padding == (0, 0)
_ = TopdownHeatmapMultiStageHead(
out_channels=3,
in_channels=512,
extra={'final_conv_kernel': 0},
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
head = TopdownHeatmapMultiStageHead(
out_channels=3,
in_channels=512,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head([inputs])
assert len(out) == 1
assert out[0].shape == torch.Size([1, 3, 256, 256])
head = TopdownHeatmapMultiStageHead(
out_channels=3,
in_channels=512,
num_deconv_layers=0,
loss_keypoint=dict(type='JointsMSELoss', use_target_weight=True))
input_shape = (1, 512, 32, 32)
inputs = _demo_inputs(input_shape)
out = head([inputs])
assert out[0].shape == torch.Size([1, 3, 32, 32])
head.init_weights()
def test_top_down_msmu_head():
"""Test multi-stage multi-unit head."""
with pytest.raises(AssertionError):
# inputs should be list
head = TopdownHeatmapMSMUHead(
out_shape=(64, 48),
unit_channels=256,
num_stages=2,
num_units=2,
loss_keypoint=(
[dict(type='JointsMSELoss', use_target_weight=True)] * 2 +
[dict(type='JointsOHKMMSELoss', use_target_weight=True)]) * 2)
input_shape = (1, 256, 32, 32)
inputs = _demo_inputs(input_shape)
_ = head(inputs)
with pytest.raises(AssertionError):
# inputs should be list[list, ...]
head = TopdownHeatmapMSMUHead(
out_shape=(64, 48),
unit_channels=256,
num_stages=2,
num_units=2,
loss_keypoint=(
[dict(type='JointsMSELoss', use_target_weight=True)] * 2 +
[dict(type='JointsOHKMMSELoss', use_target_weight=True)]) * 2)
input_shape = (1, 256, 32, 32)
inputs = _demo_inputs(input_shape)
inputs = [inputs] * 2
_ = head(inputs)
with pytest.raises(AssertionError):
# len(inputs) should equal to num_stages
head = TopdownHeatmapMSMUHead(
out_shape=(64, 48),
unit_channels=256,
num_stages=2,
num_units=2,
loss_keypoint=(
[dict(type='JointsMSELoss', use_target_weight=True)] * 2 +
[dict(type='JointsOHKMMSELoss', use_target_weight=True)]) * 2)
input_shape = (1, 256, 32, 32)
inputs = _demo_inputs(input_shape)
inputs = [[inputs] * 2] * 3
_ = head(inputs)
with pytest.raises(AssertionError):
# len(inputs[0]) should equal to num_units
head = TopdownHeatmapMSMUHead(
out_shape=(64, 48),
unit_channels=256,
num_stages=2,
num_units=2,
loss_keypoint=(
[dict(type='JointsMSELoss', use_target_weight=True)] * 2 +
[dict(type='JointsOHKMMSELoss', use_target_weight=True)]) * 2)
input_shape = (1, 256, 32, 32)
inputs = _demo_inputs(input_shape)
inputs = [[inputs] * 3] * 2
_ = head(inputs)
with pytest.raises(AssertionError):
# input channels should equal to param unit_channels
head = TopdownHeatmapMSMUHead(
out_shape=(64, 48),
unit_channels=256,
num_stages=2,
num_units=2,
loss_keypoint=(
[dict(type='JointsMSELoss', use_target_weight=True)] * 2 +
[dict(type='JointsOHKMMSELoss', use_target_weight=True)]) * 2)
input_shape = (1, 128, 32, 32)
inputs = _demo_inputs(input_shape)
inputs = [[inputs] * 2] * 2
_ = head(inputs)
head = TopdownHeatmapMSMUHead(
out_shape=(64, 48),
unit_channels=256,
out_channels=17,
num_stages=2,
num_units=2,
loss_keypoint=(
[dict(type='JointsMSELoss', use_target_weight=True)] * 2 +
[dict(type='JointsOHKMMSELoss', use_target_weight=True)]) * 2)
input_shape = (1, 256, 32, 32)
inputs = _demo_inputs(input_shape)
inputs = [[inputs] * 2] * 2
out = head(inputs)
assert len(out) == 2 * 2
assert out[0].shape == torch.Size([1, 17, 64, 48])
head.init_weights()
def test_fc_head():
"""Test fc head."""
head = DeepposeRegressionHead(
in_channels=2048,
num_joints=17,
loss_keypoint=dict(type='SmoothL1Loss', use_target_weight=True))
head.init_weights()
input_shape = (1, 2048)
inputs = _demo_inputs(input_shape)
out = head(inputs)
assert out.shape == torch.Size([1, 17, 2])
loss = head.get_loss(out, out, torch.ones_like(out))
assert torch.allclose(loss['reg_loss'], torch.tensor(0.))
_ = head.inference_model(inputs)
_ = head.inference_model(inputs, [])
acc = head.get_accuracy(out, out, torch.ones_like(out))
assert acc['acc_pose'] == 1.
def _demo_inputs(input_shape=(1, 3, 64, 64)):
"""Create a superset of inputs needed to run backbone.
Args:
input_shape (tuple): input batch dimensions.
Default: (1, 3, 64, 64).
Returns:
Random input tensor with the size of input_shape.
"""
inps = np.random.random(input_shape)
inps = torch.FloatTensor(inps)
return inps