Initial snapshot: hand motion pipeline (Dyn-HaMR + dex-retargeting + SPIDER)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+427
@@ -0,0 +1,427 @@
|
||||
# Copyright (c) OpenMMLab. All rights reserved.
|
||||
import copy
|
||||
import os.path as osp
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
import xtcocotools
|
||||
from xtcocotools.coco import COCO
|
||||
|
||||
from mmpose.datasets.pipelines import (BottomUpGenerateHeatmapTarget,
|
||||
BottomUpGeneratePAFTarget,
|
||||
BottomUpGenerateTarget,
|
||||
BottomUpGetImgSize,
|
||||
BottomUpRandomAffine,
|
||||
BottomUpRandomFlip, BottomUpResizeAlign,
|
||||
LoadImageFromFile)
|
||||
|
||||
|
||||
def _get_mask(coco, anno, img_id):
|
||||
img_info = coco.loadImgs(img_id)[0]
|
||||
|
||||
m = np.zeros((img_info['height'], img_info['width']), dtype=np.float32)
|
||||
|
||||
for obj in anno:
|
||||
if obj['iscrowd']:
|
||||
rle = xtcocotools.mask.frPyObjects(obj['segmentation'],
|
||||
img_info['height'],
|
||||
img_info['width'])
|
||||
m += xtcocotools.mask.decode(rle)
|
||||
elif obj['num_keypoints'] == 0:
|
||||
rles = xtcocotools.mask.frPyObjects(obj['segmentation'],
|
||||
img_info['height'],
|
||||
img_info['width'])
|
||||
for rle in rles:
|
||||
m += xtcocotools.mask.decode(rle)
|
||||
|
||||
return m < 0.5
|
||||
|
||||
|
||||
def _get_joints(anno, ann_info, int_sigma):
|
||||
num_people = len(anno)
|
||||
|
||||
if ann_info['scale_aware_sigma']:
|
||||
joints = np.zeros((num_people, ann_info['num_joints'], 4),
|
||||
dtype=np.float32)
|
||||
else:
|
||||
joints = np.zeros((num_people, ann_info['num_joints'], 3),
|
||||
dtype=np.float32)
|
||||
|
||||
for i, obj in enumerate(anno):
|
||||
joints[i, :ann_info['num_joints'], :3] = \
|
||||
np.array(obj['keypoints']).reshape([-1, 3])
|
||||
if ann_info['scale_aware_sigma']:
|
||||
# get person box
|
||||
box = obj['bbox']
|
||||
size = max(box[2], box[3])
|
||||
sigma = size / 256 * 2
|
||||
if int_sigma:
|
||||
sigma = int(np.ceil(sigma))
|
||||
assert sigma > 0, sigma
|
||||
joints[i, :, 3] = sigma
|
||||
|
||||
return joints
|
||||
|
||||
|
||||
def _check_flip(origin_imgs, result_imgs):
|
||||
"""Check if the origin_imgs are flipped correctly."""
|
||||
h, w, c = origin_imgs.shape
|
||||
for i in range(h):
|
||||
for j in range(w):
|
||||
for k in range(c):
|
||||
if result_imgs[i, j, k] != origin_imgs[i, w - 1 - j, k]:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def test_bottomup_pipeline():
|
||||
|
||||
data_prefix = 'tests/data/coco/'
|
||||
ann_file = osp.join(data_prefix, 'test_coco.json')
|
||||
coco = COCO(ann_file)
|
||||
|
||||
ann_info = {}
|
||||
ann_info['flip_pairs'] = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10],
|
||||
[11, 12], [13, 14], [15, 16]]
|
||||
ann_info['flip_index'] = [
|
||||
0, 2, 1, 4, 3, 6, 5, 8, 7, 10, 9, 12, 11, 14, 13, 16, 15
|
||||
]
|
||||
|
||||
ann_info['use_different_joint_weights'] = False
|
||||
ann_info['joint_weights'] = np.array([
|
||||
1., 1., 1., 1., 1., 1., 1., 1.2, 1.2, 1.5, 1.5, 1., 1., 1.2, 1.2, 1.5,
|
||||
1.5
|
||||
],
|
||||
dtype=np.float32).reshape((17, 1))
|
||||
ann_info['image_size'] = np.array([384, 512])
|
||||
ann_info['heatmap_size'] = np.array([[96, 128], [192, 256]])
|
||||
ann_info['num_joints'] = 17
|
||||
ann_info['num_scales'] = 2
|
||||
ann_info['scale_aware_sigma'] = False
|
||||
|
||||
ann_ids = coco.getAnnIds(785)
|
||||
anno = coco.loadAnns(ann_ids)
|
||||
mask = _get_mask(coco, anno, 785)
|
||||
|
||||
anno = [
|
||||
obj for obj in anno if obj['iscrowd'] == 0 or obj['num_keypoints'] > 0
|
||||
]
|
||||
joints = _get_joints(anno, ann_info, False)
|
||||
|
||||
mask_list = [mask.copy() for _ in range(ann_info['num_scales'])]
|
||||
joints_list = [joints.copy() for _ in range(ann_info['num_scales'])]
|
||||
|
||||
results = {}
|
||||
results['dataset'] = 'coco'
|
||||
results['image_file'] = osp.join(data_prefix, '000000000785.jpg')
|
||||
results['mask'] = mask_list
|
||||
results['joints'] = joints_list
|
||||
results['ann_info'] = ann_info
|
||||
|
||||
transform = LoadImageFromFile()
|
||||
results = transform(copy.deepcopy(results))
|
||||
assert results['img'].shape == (425, 640, 3)
|
||||
|
||||
# test HorizontalFlip
|
||||
random_horizontal_flip = BottomUpRandomFlip(flip_prob=1.)
|
||||
results_horizontal_flip = random_horizontal_flip(copy.deepcopy(results))
|
||||
assert _check_flip(results['img'], results_horizontal_flip['img'])
|
||||
|
||||
random_horizontal_flip = BottomUpRandomFlip(flip_prob=0.)
|
||||
results_horizontal_flip = random_horizontal_flip(copy.deepcopy(results))
|
||||
assert (results['img'] == results_horizontal_flip['img']).all()
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['mask'] = mask_list[0]
|
||||
with pytest.raises(AssertionError):
|
||||
results_horizontal_flip = random_horizontal_flip(
|
||||
copy.deepcopy(results_copy))
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['joints'] = joints_list[0]
|
||||
with pytest.raises(AssertionError):
|
||||
results_horizontal_flip = random_horizontal_flip(
|
||||
copy.deepcopy(results_copy))
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['joints'] = joints_list[:1]
|
||||
with pytest.raises(AssertionError):
|
||||
results_horizontal_flip = random_horizontal_flip(
|
||||
copy.deepcopy(results_copy))
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['mask'] = mask_list[:1]
|
||||
with pytest.raises(AssertionError):
|
||||
results_horizontal_flip = random_horizontal_flip(
|
||||
copy.deepcopy(results_copy))
|
||||
|
||||
# test TopDownAffine
|
||||
random_affine_transform = BottomUpRandomAffine(30, [0.75, 1.5], 'short', 0)
|
||||
results_affine_transform = random_affine_transform(copy.deepcopy(results))
|
||||
assert results_affine_transform['img'].shape == (512, 384, 3)
|
||||
|
||||
random_affine_transform = BottomUpRandomAffine(30, [0.75, 1.5], 'short',
|
||||
40)
|
||||
results_affine_transform = random_affine_transform(copy.deepcopy(results))
|
||||
assert results_affine_transform['img'].shape == (512, 384, 3)
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['ann_info']['scale_aware_sigma'] = True
|
||||
joints = _get_joints(anno, results_copy['ann_info'], False)
|
||||
results_copy['joints'] = \
|
||||
[joints.copy() for _ in range(results_copy['ann_info']['num_scales'])]
|
||||
results_affine_transform = random_affine_transform(results_copy)
|
||||
assert results_affine_transform['img'].shape == (512, 384, 3)
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['mask'] = mask_list[0]
|
||||
with pytest.raises(AssertionError):
|
||||
results_horizontal_flip = random_affine_transform(
|
||||
copy.deepcopy(results_copy))
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['joints'] = joints_list[0]
|
||||
with pytest.raises(AssertionError):
|
||||
results_horizontal_flip = random_affine_transform(
|
||||
copy.deepcopy(results_copy))
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['joints'] = joints_list[:1]
|
||||
with pytest.raises(AssertionError):
|
||||
results_horizontal_flip = random_affine_transform(
|
||||
copy.deepcopy(results_copy))
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['mask'] = mask_list[:1]
|
||||
with pytest.raises(AssertionError):
|
||||
results_horizontal_flip = random_affine_transform(
|
||||
copy.deepcopy(results_copy))
|
||||
|
||||
random_affine_transform = BottomUpRandomAffine(30, [0.75, 1.5], 'long', 40)
|
||||
results_affine_transform = random_affine_transform(copy.deepcopy(results))
|
||||
assert results_affine_transform['img'].shape == (512, 384, 3)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
random_affine_transform = BottomUpRandomAffine(30, [0.75, 1.5],
|
||||
'short-long', 40)
|
||||
results_affine_transform = random_affine_transform(
|
||||
copy.deepcopy(results))
|
||||
|
||||
# test BottomUpGenerateTarget
|
||||
generate_multi_target = BottomUpGenerateTarget(2, 30)
|
||||
results_generate_multi_target = generate_multi_target(
|
||||
copy.deepcopy(results))
|
||||
assert 'targets' in results_generate_multi_target
|
||||
assert len(results_generate_multi_target['targets']
|
||||
) == results['ann_info']['num_scales']
|
||||
|
||||
# test BottomUpGetImgSize when W > H
|
||||
get_multi_scale_size = BottomUpGetImgSize([1])
|
||||
results_get_multi_scale_size = get_multi_scale_size(copy.deepcopy(results))
|
||||
assert 'test_scale_factor' in results_get_multi_scale_size['ann_info']
|
||||
assert 'base_size' in results_get_multi_scale_size['ann_info']
|
||||
assert 'center' in results_get_multi_scale_size['ann_info']
|
||||
assert 'scale' in results_get_multi_scale_size['ann_info']
|
||||
assert results_get_multi_scale_size['ann_info']['base_size'][1] == 512
|
||||
|
||||
# test BottomUpResizeAlign
|
||||
transforms = [
|
||||
dict(type='ToTensor'),
|
||||
dict(
|
||||
type='NormalizeTensor',
|
||||
mean=[0.485, 0.456, 0.406],
|
||||
std=[0.229, 0.224, 0.225]),
|
||||
]
|
||||
resize_align_multi_scale = BottomUpResizeAlign(transforms=transforms)
|
||||
results_copy = copy.deepcopy(results_get_multi_scale_size)
|
||||
results_resize_align_multi_scale = resize_align_multi_scale(results_copy)
|
||||
assert 'aug_data' in results_resize_align_multi_scale['ann_info']
|
||||
|
||||
# test when W < H
|
||||
ann_info['image_size'] = np.array([512, 384])
|
||||
ann_info['heatmap_size'] = np.array([[128, 96], [256, 192]])
|
||||
results = {}
|
||||
results['dataset'] = 'coco'
|
||||
results['image_file'] = osp.join(data_prefix, '000000000785.jpg')
|
||||
results['mask'] = mask_list
|
||||
results['joints'] = joints_list
|
||||
results['ann_info'] = ann_info
|
||||
results['img'] = np.random.rand(640, 425, 3)
|
||||
|
||||
# test HorizontalFlip
|
||||
random_horizontal_flip = BottomUpRandomFlip(flip_prob=1.)
|
||||
results_horizontal_flip = random_horizontal_flip(copy.deepcopy(results))
|
||||
assert _check_flip(results['img'], results_horizontal_flip['img'])
|
||||
|
||||
random_horizontal_flip = BottomUpRandomFlip(flip_prob=0.)
|
||||
results_horizontal_flip = random_horizontal_flip(copy.deepcopy(results))
|
||||
assert (results['img'] == results_horizontal_flip['img']).all()
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['mask'] = mask_list[0]
|
||||
with pytest.raises(AssertionError):
|
||||
results_horizontal_flip = random_horizontal_flip(
|
||||
copy.deepcopy(results_copy))
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['joints'] = joints_list[0]
|
||||
with pytest.raises(AssertionError):
|
||||
results_horizontal_flip = random_horizontal_flip(
|
||||
copy.deepcopy(results_copy))
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['joints'] = joints_list[:1]
|
||||
with pytest.raises(AssertionError):
|
||||
results_horizontal_flip = random_horizontal_flip(
|
||||
copy.deepcopy(results_copy))
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['mask'] = mask_list[:1]
|
||||
with pytest.raises(AssertionError):
|
||||
results_horizontal_flip = random_horizontal_flip(
|
||||
copy.deepcopy(results_copy))
|
||||
|
||||
# test TopDownAffine
|
||||
random_affine_transform = BottomUpRandomAffine(30, [0.75, 1.5], 'short', 0)
|
||||
results_affine_transform = random_affine_transform(copy.deepcopy(results))
|
||||
assert results_affine_transform['img'].shape == (384, 512, 3)
|
||||
|
||||
random_affine_transform = BottomUpRandomAffine(30, [0.75, 1.5], 'short',
|
||||
40)
|
||||
results_affine_transform = random_affine_transform(copy.deepcopy(results))
|
||||
assert results_affine_transform['img'].shape == (384, 512, 3)
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['ann_info']['scale_aware_sigma'] = True
|
||||
joints = _get_joints(anno, results_copy['ann_info'], False)
|
||||
results_copy['joints'] = \
|
||||
[joints.copy() for _ in range(results_copy['ann_info']['num_scales'])]
|
||||
results_affine_transform = random_affine_transform(results_copy)
|
||||
assert results_affine_transform['img'].shape == (384, 512, 3)
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['mask'] = mask_list[0]
|
||||
with pytest.raises(AssertionError):
|
||||
results_horizontal_flip = random_affine_transform(
|
||||
copy.deepcopy(results_copy))
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['joints'] = joints_list[0]
|
||||
with pytest.raises(AssertionError):
|
||||
results_horizontal_flip = random_affine_transform(
|
||||
copy.deepcopy(results_copy))
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['joints'] = joints_list[:1]
|
||||
with pytest.raises(AssertionError):
|
||||
results_horizontal_flip = random_affine_transform(
|
||||
copy.deepcopy(results_copy))
|
||||
|
||||
results_copy = copy.deepcopy(results)
|
||||
results_copy['mask'] = mask_list[:1]
|
||||
with pytest.raises(AssertionError):
|
||||
results_horizontal_flip = random_affine_transform(
|
||||
copy.deepcopy(results_copy))
|
||||
|
||||
random_affine_transform = BottomUpRandomAffine(30, [0.75, 1.5], 'long', 40)
|
||||
results_affine_transform = random_affine_transform(copy.deepcopy(results))
|
||||
assert results_affine_transform['img'].shape == (384, 512, 3)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
random_affine_transform = BottomUpRandomAffine(30, [0.75, 1.5],
|
||||
'short-long', 40)
|
||||
results_affine_transform = random_affine_transform(
|
||||
copy.deepcopy(results))
|
||||
|
||||
# test BottomUpGenerateTarget
|
||||
generate_multi_target = BottomUpGenerateTarget(2, 30)
|
||||
results_generate_multi_target = generate_multi_target(
|
||||
copy.deepcopy(results))
|
||||
assert 'targets' in results_generate_multi_target
|
||||
assert len(results_generate_multi_target['targets']
|
||||
) == results['ann_info']['num_scales']
|
||||
|
||||
# test BottomUpGetImgSize when W < H
|
||||
get_multi_scale_size = BottomUpGetImgSize([1])
|
||||
results_get_multi_scale_size = get_multi_scale_size(copy.deepcopy(results))
|
||||
assert 'test_scale_factor' in results_get_multi_scale_size['ann_info']
|
||||
assert 'base_size' in results_get_multi_scale_size['ann_info']
|
||||
assert 'center' in results_get_multi_scale_size['ann_info']
|
||||
assert 'scale' in results_get_multi_scale_size['ann_info']
|
||||
assert results_get_multi_scale_size['ann_info']['base_size'][0] == 512
|
||||
|
||||
|
||||
def test_BottomUpGenerateHeatmapTarget():
|
||||
|
||||
data_prefix = 'tests/data/coco/'
|
||||
ann_file = osp.join(data_prefix, 'test_coco.json')
|
||||
coco = COCO(ann_file)
|
||||
|
||||
ann_info = {}
|
||||
ann_info['heatmap_size'] = np.array([128, 256])
|
||||
ann_info['num_joints'] = 17
|
||||
ann_info['num_scales'] = 2
|
||||
ann_info['scale_aware_sigma'] = False
|
||||
|
||||
ann_ids = coco.getAnnIds(785)
|
||||
anno = coco.loadAnns(ann_ids)
|
||||
mask = _get_mask(coco, anno, 785)
|
||||
|
||||
anno = [
|
||||
obj for obj in anno if obj['iscrowd'] == 0 or obj['num_keypoints'] > 0
|
||||
]
|
||||
joints = _get_joints(anno, ann_info, False)
|
||||
|
||||
mask_list = [mask.copy() for _ in range(ann_info['num_scales'])]
|
||||
joints_list = [joints.copy() for _ in range(ann_info['num_scales'])]
|
||||
|
||||
results = {}
|
||||
results['dataset'] = 'coco'
|
||||
results['image_file'] = osp.join(data_prefix, '000000000785.jpg')
|
||||
results['mask'] = mask_list
|
||||
results['joints'] = joints_list
|
||||
results['ann_info'] = ann_info
|
||||
|
||||
generate_heatmap_target = BottomUpGenerateHeatmapTarget(2)
|
||||
results_generate_heatmap_target = generate_heatmap_target(results)
|
||||
assert 'target' in results_generate_heatmap_target
|
||||
assert len(results_generate_heatmap_target['target']
|
||||
) == results['ann_info']['num_scales']
|
||||
|
||||
|
||||
def test_BottomUpGeneratePAFTarget():
|
||||
|
||||
ann_info = {}
|
||||
ann_info['skeleton'] = [[0, 1], [2, 3]]
|
||||
ann_info['heatmap_size'] = np.array([5])
|
||||
ann_info['num_joints'] = 4
|
||||
ann_info['num_scales'] = 1
|
||||
|
||||
mask = np.ones((5, 5), dtype=bool)
|
||||
joints = np.array([[[1, 1, 2], [3, 3, 2], [0, 0, 0], [0, 0, 0]],
|
||||
[[1, 3, 2], [3, 1, 2], [0, 0, 0], [0, 0, 0]]])
|
||||
|
||||
mask_list = [mask.copy() for _ in range(ann_info['num_scales'])]
|
||||
joints_list = [joints.copy() for _ in range(ann_info['num_scales'])]
|
||||
|
||||
results = {}
|
||||
results['dataset'] = 'coco'
|
||||
results['mask'] = mask_list
|
||||
results['joints'] = joints_list
|
||||
results['ann_info'] = ann_info
|
||||
|
||||
generate_paf_target = BottomUpGeneratePAFTarget(1)
|
||||
results_generate_paf_target = generate_paf_target(results)
|
||||
sqrt = np.sqrt(2) / 2
|
||||
assert (results_generate_paf_target['target'] == np.array(
|
||||
[[[sqrt, sqrt, 0, sqrt, sqrt], [sqrt, sqrt, sqrt, sqrt, sqrt],
|
||||
[0, sqrt, sqrt, sqrt, 0], [sqrt, sqrt, sqrt, sqrt, sqrt],
|
||||
[sqrt, sqrt, 0, sqrt, sqrt]],
|
||||
[[sqrt, sqrt, 0, -sqrt, -sqrt], [sqrt, sqrt, 0, -sqrt, -sqrt],
|
||||
[0, 0, 0, 0, 0], [-sqrt, -sqrt, 0, sqrt, sqrt],
|
||||
[-sqrt, -sqrt, 0, sqrt, sqrt]],
|
||||
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0]],
|
||||
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0]]],
|
||||
dtype=np.float32)).all()
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
# Copyright (c) OpenMMLab. All rights reserved.
|
||||
import copy
|
||||
|
||||
import numpy as np
|
||||
|
||||
from mmpose.datasets.pipelines import Compose
|
||||
|
||||
|
||||
def _check_flip(origin_imgs, result_imgs):
|
||||
"""Check if the origin_imgs are flipped correctly."""
|
||||
h, w, c = origin_imgs.shape
|
||||
for i in range(h):
|
||||
for j in range(w):
|
||||
for k in range(c):
|
||||
if result_imgs[i, j, k] != origin_imgs[i, w - 1 - j, k]:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def get_sample_data():
|
||||
ann_info = {}
|
||||
ann_info['image_size'] = np.array([256, 256])
|
||||
ann_info['heatmap_size'] = np.array([64, 64, 64])
|
||||
ann_info['heatmap3d_depth_bound'] = 400.0
|
||||
ann_info['heatmap_size_root'] = 64
|
||||
ann_info['root_depth_bound'] = 400.0
|
||||
ann_info['num_joints'] = 42
|
||||
ann_info['joint_weights'] = np.ones((ann_info['num_joints'], 1),
|
||||
dtype=np.float32)
|
||||
ann_info['use_different_joint_weights'] = False
|
||||
ann_info['flip_pairs'] = [[i, 21 + i] for i in range(21)]
|
||||
ann_info['inference_channel'] = list(range(42))
|
||||
ann_info['num_output_channels'] = 42
|
||||
ann_info['dataset_channel'] = list(range(42))
|
||||
|
||||
results = {
|
||||
'image_file': 'tests/data/interhand2.6m/image69148.jpg',
|
||||
'center': np.asarray([200, 200], dtype=np.float32),
|
||||
'scale': 1.0,
|
||||
'rotation': 0,
|
||||
'joints_3d': np.zeros([42, 3], dtype=np.float32),
|
||||
'joints_3d_visible': np.ones([42, 3], dtype=np.float32),
|
||||
'hand_type': np.asarray([1, 0], dtype=np.float32),
|
||||
'hand_type_valid': 1,
|
||||
'rel_root_depth': 50.0,
|
||||
'rel_root_valid': 1,
|
||||
'ann_info': ann_info
|
||||
}
|
||||
return results
|
||||
|
||||
|
||||
def test_hand_transforms():
|
||||
results = get_sample_data()
|
||||
|
||||
# load image
|
||||
pipeline = Compose([dict(type='LoadImageFromFile')])
|
||||
results = pipeline(results)
|
||||
|
||||
# test random flip
|
||||
pipeline = Compose([dict(type='HandRandomFlip', flip_prob=1)])
|
||||
results_flip = pipeline(copy.deepcopy(results))
|
||||
assert _check_flip(results['img'], results_flip['img'])
|
||||
|
||||
# test root depth target generation
|
||||
pipeline = Compose([dict(type='HandGenerateRelDepthTarget')])
|
||||
results_depth = pipeline(copy.deepcopy(results))
|
||||
assert results_depth['target'].shape == (1, )
|
||||
assert results_depth['target_weight'].shape == (1, )
|
||||
+255
@@ -0,0 +1,255 @@
|
||||
# Copyright (c) OpenMMLab. All rights reserved.
|
||||
import copy
|
||||
import os
|
||||
|
||||
import numpy as np
|
||||
import torch
|
||||
from numpy.testing import assert_array_almost_equal
|
||||
|
||||
from mmpose.datasets.pipelines import (Collect, IUVToTensor, LoadImageFromFile,
|
||||
LoadIUVFromFile, MeshAffine,
|
||||
MeshGetRandomScaleRotation,
|
||||
MeshRandomChannelNoise, MeshRandomFlip,
|
||||
NormalizeTensor, ToTensor)
|
||||
|
||||
|
||||
def _check_keys_contain(result_keys, target_keys):
|
||||
"""Check if all elements in target_keys is in result_keys."""
|
||||
return set(target_keys).issubset(set(result_keys))
|
||||
|
||||
|
||||
def _check_flip(origin_imgs, result_imgs):
|
||||
"""Check if the origin_imgs are flipped correctly."""
|
||||
h, w, c = origin_imgs.shape
|
||||
for i in range(h):
|
||||
for j in range(w):
|
||||
for k in range(c):
|
||||
if result_imgs[i, j, k] != origin_imgs[i, w - 1 - j, k]:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _check_rot90(origin_imgs, result_imgs):
|
||||
if origin_imgs.shape[0] == result_imgs.shape[1] and \
|
||||
origin_imgs.shape[1] == result_imgs.shape[0]:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def _check_normalize(origin_imgs, result_imgs, norm_cfg):
|
||||
"""Check if the origin_imgs are normalized correctly into result_imgs in a
|
||||
given norm_cfg."""
|
||||
target_imgs = result_imgs.copy()
|
||||
for i in range(3):
|
||||
target_imgs[i] *= norm_cfg['std'][i]
|
||||
target_imgs[i] += norm_cfg['mean'][i]
|
||||
assert_array_almost_equal(origin_imgs, target_imgs, decimal=4)
|
||||
|
||||
|
||||
def _box2cs(box, image_size):
|
||||
x, y, w, h = box[:4]
|
||||
|
||||
aspect_ratio = 1. * image_size[0] / image_size[1]
|
||||
center = np.zeros((2), dtype=np.float32)
|
||||
center[0] = x + w * 0.5
|
||||
center[1] = y + h * 0.5
|
||||
|
||||
if w > aspect_ratio * h:
|
||||
h = w * 1.0 / aspect_ratio
|
||||
elif w < aspect_ratio * h:
|
||||
w = h * aspect_ratio
|
||||
scale = np.array([w * 1.0 / 200.0, h * 1.0 / 200.0], dtype=np.float32)
|
||||
scale = scale * 1.25
|
||||
return center, scale
|
||||
|
||||
|
||||
def _load_test_data():
|
||||
data_cfg = dict(
|
||||
image_size=[256, 256],
|
||||
iuv_size=[64, 64],
|
||||
num_joints=24,
|
||||
use_IUV=True,
|
||||
uv_type='BF')
|
||||
ann_file = 'tests/data/h36m/test_h36m.npz'
|
||||
img_prefix = 'tests/data/h36m'
|
||||
index = 0
|
||||
|
||||
ann_info = dict(image_size=np.array(data_cfg['image_size']))
|
||||
ann_info['iuv_size'] = np.array(data_cfg['iuv_size'])
|
||||
ann_info['num_joints'] = data_cfg['num_joints']
|
||||
ann_info['flip_pairs'] = [[0, 5], [1, 4], [2, 3], [6, 11], [7, 10], [8, 9],
|
||||
[20, 21], [22, 23]]
|
||||
ann_info['use_different_joint_weights'] = False
|
||||
ann_info['joint_weights'] = \
|
||||
np.ones(ann_info['num_joints'], dtype=np.float32
|
||||
).reshape(ann_info['num_joints'], 1)
|
||||
ann_info['uv_type'] = data_cfg['uv_type']
|
||||
ann_info['use_IUV'] = data_cfg['use_IUV']
|
||||
uv_type = ann_info['uv_type']
|
||||
iuv_prefix = os.path.join(img_prefix, f'{uv_type}_IUV_gt')
|
||||
|
||||
ann_data = np.load(ann_file)
|
||||
|
||||
results = dict(ann_info=ann_info)
|
||||
results['rotation'] = 0
|
||||
results['image_file'] = os.path.join(img_prefix,
|
||||
ann_data['imgname'][index])
|
||||
scale = ann_data['scale'][index]
|
||||
results['scale'] = np.array([scale, scale]).astype(np.float32)
|
||||
results['center'] = ann_data['center'][index].astype(np.float32)
|
||||
|
||||
# Get gt 2D joints, if available
|
||||
if 'part' in ann_data.keys():
|
||||
keypoints = ann_data['part'][index].astype(np.float32)
|
||||
results['joints_2d'] = keypoints[:, :2]
|
||||
results['joints_2d_visible'] = keypoints[:, -1][:, np.newaxis]
|
||||
else:
|
||||
results['joints_2d'] = np.zeros((24, 2), dtype=np.float32)
|
||||
results['joints_2d_visible'] = np.zeros((24, 1), dtype=np.float32)
|
||||
|
||||
# Get gt 3D joints, if available
|
||||
if 'S' in ann_data.keys():
|
||||
joints_3d = ann_data['S'][index].astype(np.float32)
|
||||
results['joints_3d'] = joints_3d[:, :3]
|
||||
results['joints_3d_visible'] = joints_3d[:, -1][:, np.newaxis]
|
||||
else:
|
||||
results['joints_3d'] = np.zeros((24, 3), dtype=np.float32)
|
||||
results['joints_3d_visible'] = np.zeros((24, 1), dtype=np.float32)
|
||||
|
||||
# Get gt SMPL parameters, if available
|
||||
if 'pose' in ann_data.keys() and 'shape' in ann_data.keys():
|
||||
results['pose'] = ann_data['pose'][index].astype(np.float32)
|
||||
results['beta'] = ann_data['shape'][index].astype(np.float32)
|
||||
results['has_smpl'] = 1
|
||||
else:
|
||||
results['pose'] = np.zeros(72, dtype=np.float32)
|
||||
results['beta'] = np.zeros(10, dtype=np.float32)
|
||||
results['has_smpl'] = 0
|
||||
|
||||
# Get gender data, if available
|
||||
if 'gender' in ann_data.keys():
|
||||
gender = ann_data['gender'][index]
|
||||
results['gender'] = 0 if str(gender) == 'm' else 1
|
||||
else:
|
||||
results['gender'] = -1
|
||||
|
||||
# Get IUV image, if available
|
||||
if 'iuv_names' in ann_data.keys():
|
||||
results['iuv_file'] = os.path.join(iuv_prefix,
|
||||
ann_data['iuv_names'][index])
|
||||
results['has_iuv'] = results['has_smpl']
|
||||
else:
|
||||
results['iuv_file'] = ''
|
||||
results['has_iuv'] = 0
|
||||
|
||||
return copy.deepcopy(results)
|
||||
|
||||
|
||||
def test_mesh_pipeline():
|
||||
# load data
|
||||
results = _load_test_data()
|
||||
|
||||
# data_prefix = 'tests/data/coco/'
|
||||
# ann_file = osp.join(data_prefix, 'test_coco.json')
|
||||
# coco = COCO(ann_file)
|
||||
#
|
||||
# results = dict(image_file=osp.join(data_prefix, '000000000785.jpg'))
|
||||
|
||||
# test loading image
|
||||
transform = LoadImageFromFile()
|
||||
results = transform(copy.deepcopy(results))
|
||||
assert results['img'].shape == (1002, 1000, 3)
|
||||
|
||||
# test loading densepose IUV image without GT iuv image
|
||||
transform = LoadIUVFromFile()
|
||||
results_no_iuv = copy.deepcopy(results)
|
||||
results_no_iuv['has_iuv'] = 0
|
||||
results_no_iuv = transform(results_no_iuv)
|
||||
assert results_no_iuv['iuv'] is None
|
||||
|
||||
# test loading densepose IUV image
|
||||
results = transform(results)
|
||||
assert results['iuv'].shape == (1002, 1000, 3)
|
||||
assert results['iuv'][:, :, 0].max() <= 1
|
||||
|
||||
# test flip
|
||||
random_flip = MeshRandomFlip(flip_prob=1.)
|
||||
results_flip = random_flip(copy.deepcopy(results))
|
||||
assert _check_flip(results['img'], results_flip['img'])
|
||||
flip_iuv = results_flip['iuv']
|
||||
flip_iuv[:, :, 1] = 255 - flip_iuv[:, :, 1]
|
||||
assert _check_flip(results['iuv'], flip_iuv)
|
||||
results = results_flip
|
||||
|
||||
# test flip without IUV image
|
||||
results_no_iuv = random_flip(copy.deepcopy(results_no_iuv))
|
||||
assert results_no_iuv['iuv'] is None
|
||||
|
||||
# test random scale and rotation
|
||||
random_scale_rotation = MeshGetRandomScaleRotation()
|
||||
results = random_scale_rotation(results)
|
||||
|
||||
# test affine
|
||||
affine_transform = MeshAffine()
|
||||
results_affine = affine_transform(copy.deepcopy(results))
|
||||
assert results_affine['img'].shape == (256, 256, 3)
|
||||
assert results_affine['iuv'].shape == (64, 64, 3)
|
||||
results = results_affine
|
||||
|
||||
# test affine without IUV image
|
||||
results_no_iuv['rotation'] = 30
|
||||
results_no_iuv = affine_transform(copy.deepcopy(results_no_iuv))
|
||||
assert results_no_iuv['iuv'] is None
|
||||
|
||||
# test channel noise
|
||||
random_noise = MeshRandomChannelNoise()
|
||||
results_noise = random_noise(copy.deepcopy(results))
|
||||
results = results_noise
|
||||
|
||||
# transfer image to tensor
|
||||
to_tensor = ToTensor()
|
||||
results_tensor = to_tensor(copy.deepcopy(results))
|
||||
assert isinstance(results_tensor['img'], torch.Tensor)
|
||||
assert results_tensor['img'].shape == torch.Size([3, 256, 256])
|
||||
|
||||
# transfer IUV image to tensor
|
||||
iuv_to_tensor = IUVToTensor()
|
||||
results_tensor = iuv_to_tensor(results_tensor)
|
||||
assert isinstance(results_tensor['part_index'], torch.LongTensor)
|
||||
assert results_tensor['part_index'].shape == torch.Size([1, 64, 64])
|
||||
max_I = results_tensor['part_index'].max().item()
|
||||
assert (max_I == 0 or max_I == 1)
|
||||
assert isinstance(results_tensor['uv_coordinates'], torch.FloatTensor)
|
||||
assert results_tensor['uv_coordinates'].shape == torch.Size([2, 64, 64])
|
||||
|
||||
# transfer IUV image to tensor without GT IUV image
|
||||
results_no_iuv = iuv_to_tensor(results_no_iuv)
|
||||
assert isinstance(results_no_iuv['part_index'], torch.LongTensor)
|
||||
assert results_no_iuv['part_index'].shape == torch.Size([1, 64, 64])
|
||||
max_I = results_no_iuv['part_index'].max().item()
|
||||
assert (max_I == 0)
|
||||
assert isinstance(results_no_iuv['uv_coordinates'], torch.FloatTensor)
|
||||
assert results_no_iuv['uv_coordinates'].shape == torch.Size([2, 64, 64])
|
||||
|
||||
# test norm
|
||||
norm_cfg = {}
|
||||
norm_cfg['mean'] = [0.485, 0.456, 0.406]
|
||||
norm_cfg['std'] = [0.229, 0.224, 0.225]
|
||||
normalize = NormalizeTensor(mean=norm_cfg['mean'], std=norm_cfg['std'])
|
||||
|
||||
results_normalize = normalize(copy.deepcopy(results_tensor))
|
||||
_check_normalize(results_tensor['img'].data.numpy(),
|
||||
results_normalize['img'].data.numpy(), norm_cfg)
|
||||
|
||||
# test collect
|
||||
collect = Collect(
|
||||
keys=[
|
||||
'img', 'joints_2d', 'joints_2d_visible', 'joints_3d',
|
||||
'joints_3d_visible', 'pose', 'beta', 'part_index', 'uv_coordinates'
|
||||
],
|
||||
meta_keys=['image_file', 'center', 'scale', 'rotation', 'iuv_file'])
|
||||
results_final = collect(results_normalize)
|
||||
|
||||
assert 'img_size' not in results_final['img_metas'].data
|
||||
assert 'image_file' in results_final['img_metas'].data
|
||||
+336
@@ -0,0 +1,336 @@
|
||||
# Copyright (c) OpenMMLab. All rights reserved.
|
||||
import copy
|
||||
import os.path as osp
|
||||
import tempfile
|
||||
|
||||
import mmcv
|
||||
import numpy as np
|
||||
import pytest
|
||||
from numpy.testing import assert_array_almost_equal
|
||||
|
||||
from mmpose.core import SimpleCamera
|
||||
from mmpose.datasets.pipelines import Compose
|
||||
|
||||
H36M_JOINT_IDX = [14, 2, 1, 0, 3, 4, 5, 16, 12, 17, 18, 9, 10, 11, 8, 7, 6]
|
||||
|
||||
|
||||
def get_data_sample():
|
||||
|
||||
def _parse_h36m_imgname(imgname):
|
||||
"""Parse imgname to get information of subject, action and camera.
|
||||
|
||||
A typical h36m image filename is like:
|
||||
S1_Directions_1.54138969_000001.jpg
|
||||
"""
|
||||
subj, rest = osp.basename(imgname).split('_', 1)
|
||||
action, rest = rest.split('.', 1)
|
||||
camera, rest = rest.split('_', 1)
|
||||
return subj, action, camera
|
||||
|
||||
ann_flle = 'tests/data/h36m/test_h36m.npz'
|
||||
camera_param_file = 'tests/data/h36m/cameras.pkl'
|
||||
|
||||
data = np.load(ann_flle)
|
||||
cameras = mmcv.load(camera_param_file)
|
||||
|
||||
_imgnames = data['imgname']
|
||||
_joints_2d = data['part'][:, H36M_JOINT_IDX].astype(np.float32)
|
||||
_joints_3d = data['S'][:, H36M_JOINT_IDX].astype(np.float32)
|
||||
_centers = data['center'].astype(np.float32)
|
||||
_scales = data['scale'].astype(np.float32)
|
||||
|
||||
frame_ids = [0]
|
||||
target_frame_id = 0
|
||||
|
||||
results = {
|
||||
'frame_ids': frame_ids,
|
||||
'target_frame_id': target_frame_id,
|
||||
'input_2d': _joints_2d[frame_ids, :, :2],
|
||||
'input_2d_visible': _joints_2d[frame_ids, :, -1:],
|
||||
'input_3d': _joints_3d[frame_ids, :, :3],
|
||||
'input_3d_visible': _joints_3d[frame_ids, :, -1:],
|
||||
'target': _joints_3d[target_frame_id, :, :3],
|
||||
'target_visible': _joints_3d[target_frame_id, :, -1:],
|
||||
'imgnames': _imgnames[frame_ids],
|
||||
'scales': _scales[frame_ids],
|
||||
'centers': _centers[frame_ids],
|
||||
}
|
||||
|
||||
# add camera parameters
|
||||
subj, _, camera = _parse_h36m_imgname(_imgnames[frame_ids[0]])
|
||||
results['camera_param'] = cameras[(subj, camera)]
|
||||
|
||||
# add image size
|
||||
results['image_width'] = results['camera_param']['w']
|
||||
results['image_height'] = results['camera_param']['h']
|
||||
|
||||
# add ann_info
|
||||
ann_info = {}
|
||||
ann_info['num_joints'] = 17
|
||||
ann_info['joint_weights'] = np.full(17, 1.0, dtype=np.float32)
|
||||
ann_info['flip_pairs'] = [[1, 4], [2, 5], [3, 6], [11, 14], [12, 15],
|
||||
[13, 16]]
|
||||
ann_info['upper_body_ids'] = (0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
|
||||
ann_info['lower_body_ids'] = (1, 2, 3, 4, 5, 6)
|
||||
ann_info['use_different_joint_weights'] = False
|
||||
|
||||
results['ann_info'] = ann_info
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def test_joint_transforms():
|
||||
results = get_data_sample()
|
||||
|
||||
mean = np.random.rand(16, 3).astype(np.float32)
|
||||
std = np.random.rand(16, 3).astype(np.float32) + 1e-6
|
||||
|
||||
pipeline = [
|
||||
dict(
|
||||
type='RelativeJointRandomFlip',
|
||||
item='target',
|
||||
flip_cfg=dict(center_mode='root', center_index=0),
|
||||
visible_item='target_visible',
|
||||
flip_prob=1.,
|
||||
flip_camera=True),
|
||||
dict(
|
||||
type='GetRootCenteredPose',
|
||||
item='target',
|
||||
root_index=0,
|
||||
root_name='global_position',
|
||||
remove_root=True),
|
||||
dict(
|
||||
type='NormalizeJointCoordinate', item='target', mean=mean,
|
||||
std=std),
|
||||
dict(type='PoseSequenceToTensor', item='target'),
|
||||
dict(
|
||||
type='ImageCoordinateNormalization',
|
||||
item='input_2d',
|
||||
norm_camera=True),
|
||||
dict(type='CollectCameraIntrinsics'),
|
||||
dict(
|
||||
type='Collect',
|
||||
keys=[('input_2d', 'input'), ('target', 'output'), 'flip_pairs',
|
||||
'intrinsics'],
|
||||
meta_name='metas',
|
||||
meta_keys=['camera_param'])
|
||||
]
|
||||
|
||||
pipeline = Compose(pipeline)
|
||||
output = pipeline(copy.deepcopy(results))
|
||||
|
||||
# test transformation of target
|
||||
joints_0 = results['target']
|
||||
joints_1 = output['output'].numpy()
|
||||
# manually do transformations
|
||||
flip_pairs = output['flip_pairs']
|
||||
_joints_0_flipped = joints_0.copy()
|
||||
for _l, _r in flip_pairs:
|
||||
_joints_0_flipped[..., _l, :] = joints_0[..., _r, :]
|
||||
_joints_0_flipped[..., _r, :] = joints_0[..., _l, :]
|
||||
_joints_0_flipped[...,
|
||||
0] = 2 * joints_0[..., 0:1, 0] - _joints_0_flipped[...,
|
||||
0]
|
||||
joints_0 = _joints_0_flipped
|
||||
joints_0 = (joints_0[..., 1:, :] - joints_0[..., 0:1, :] - mean) / std
|
||||
# convert to [K*C, T]
|
||||
joints_0 = joints_0.reshape(-1)[..., None]
|
||||
np.testing.assert_array_almost_equal(joints_0, joints_1)
|
||||
|
||||
# test transformation of input
|
||||
joints_0 = results['input_2d']
|
||||
joints_1 = output['input']
|
||||
# manually do transformations
|
||||
center = np.array(
|
||||
[0.5 * results['image_width'], 0.5 * results['image_height']],
|
||||
dtype=np.float32)
|
||||
scale = np.array(0.5 * results['image_width'], dtype=np.float32)
|
||||
joints_0 = (joints_0 - center) / scale
|
||||
np.testing.assert_array_almost_equal(joints_0, joints_1)
|
||||
|
||||
# test transformation of camera parameters
|
||||
camera_param_0 = results['camera_param']
|
||||
camera_param_1 = output['metas'].data['camera_param']
|
||||
# manually flip and normalization
|
||||
camera_param_0['c'][0] *= -1
|
||||
camera_param_0['p'][0] *= -1
|
||||
camera_param_0['c'] = (camera_param_0['c'] -
|
||||
np.array(center)[:, None]) / scale
|
||||
camera_param_0['f'] = camera_param_0['f'] / scale
|
||||
np.testing.assert_array_almost_equal(camera_param_0['c'],
|
||||
camera_param_1['c'])
|
||||
np.testing.assert_array_almost_equal(camera_param_0['f'],
|
||||
camera_param_1['f'])
|
||||
|
||||
# test CollectCameraIntrinsics
|
||||
intrinsics_0 = np.concatenate([
|
||||
results['camera_param']['f'].reshape(2),
|
||||
results['camera_param']['c'].reshape(2),
|
||||
results['camera_param']['k'].reshape(3),
|
||||
results['camera_param']['p'].reshape(2)
|
||||
])
|
||||
intrinsics_1 = output['intrinsics']
|
||||
np.testing.assert_array_almost_equal(intrinsics_0, intrinsics_1)
|
||||
|
||||
# test load mean/std from file
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
norm_param = {'mean': mean, 'std': std}
|
||||
norm_param_file = osp.join(tmpdir, 'norm_param.pkl')
|
||||
mmcv.dump(norm_param, norm_param_file)
|
||||
|
||||
pipeline = [
|
||||
dict(
|
||||
type='NormalizeJointCoordinate',
|
||||
item='target',
|
||||
norm_param_file=norm_param_file),
|
||||
]
|
||||
pipeline = Compose(pipeline)
|
||||
|
||||
|
||||
def test_camera_projection():
|
||||
results = get_data_sample()
|
||||
pipeline_1 = [
|
||||
dict(
|
||||
type='CameraProjection',
|
||||
item='input_3d',
|
||||
output_name='input_3d_w',
|
||||
camera_type='SimpleCamera',
|
||||
mode='camera_to_world'),
|
||||
dict(
|
||||
type='CameraProjection',
|
||||
item='input_3d_w',
|
||||
output_name='input_3d_wp',
|
||||
camera_type='SimpleCamera',
|
||||
mode='world_to_pixel'),
|
||||
dict(
|
||||
type='CameraProjection',
|
||||
item='input_3d',
|
||||
output_name='input_3d_p',
|
||||
camera_type='SimpleCamera',
|
||||
mode='camera_to_pixel'),
|
||||
dict(type='Collect', keys=['input_3d_wp', 'input_3d_p'], meta_keys=[])
|
||||
]
|
||||
camera_param = results['camera_param'].copy()
|
||||
camera_param['K'] = np.concatenate(
|
||||
(np.diagflat(camera_param['f']), camera_param['c']), axis=-1)
|
||||
pipeline_2 = [
|
||||
dict(
|
||||
type='CameraProjection',
|
||||
item='input_3d',
|
||||
output_name='input_3d_w',
|
||||
camera_type='SimpleCamera',
|
||||
camera_param=camera_param,
|
||||
mode='camera_to_world'),
|
||||
dict(
|
||||
type='CameraProjection',
|
||||
item='input_3d_w',
|
||||
output_name='input_3d_wp',
|
||||
camera_type='SimpleCamera',
|
||||
camera_param=camera_param,
|
||||
mode='world_to_pixel'),
|
||||
dict(
|
||||
type='CameraProjection',
|
||||
item='input_3d',
|
||||
output_name='input_3d_p',
|
||||
camera_type='SimpleCamera',
|
||||
camera_param=camera_param,
|
||||
mode='camera_to_pixel'),
|
||||
dict(
|
||||
type='CameraProjection',
|
||||
item='input_3d_w',
|
||||
output_name='input_3d_wc',
|
||||
camera_type='SimpleCamera',
|
||||
camera_param=camera_param,
|
||||
mode='world_to_camera'),
|
||||
dict(
|
||||
type='Collect',
|
||||
keys=['input_3d_wp', 'input_3d_p', 'input_2d'],
|
||||
meta_keys=[])
|
||||
]
|
||||
|
||||
output1 = Compose(pipeline_1)(results)
|
||||
output2 = Compose(pipeline_2)(results)
|
||||
|
||||
np.testing.assert_allclose(
|
||||
output1['input_3d_wp'], output1['input_3d_p'], rtol=1e-6)
|
||||
|
||||
np.testing.assert_allclose(
|
||||
output2['input_3d_wp'], output2['input_3d_p'], rtol=1e-6)
|
||||
|
||||
np.testing.assert_allclose(
|
||||
output2['input_3d_p'], output2['input_2d'], rtol=1e-3, atol=1e-1)
|
||||
|
||||
# test invalid camera parameters
|
||||
with pytest.raises(ValueError):
|
||||
# missing intrinsic parameters
|
||||
camera_param_wo_intrinsic = camera_param.copy()
|
||||
camera_param_wo_intrinsic.pop('K')
|
||||
camera_param_wo_intrinsic.pop('f')
|
||||
camera_param_wo_intrinsic.pop('c')
|
||||
_ = Compose([
|
||||
dict(
|
||||
type='CameraProjection',
|
||||
item='input_3d',
|
||||
camera_type='SimpleCamera',
|
||||
camera_param=camera_param_wo_intrinsic,
|
||||
mode='camera_to_pixel')
|
||||
])
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
# invalid mode
|
||||
_ = Compose([
|
||||
dict(
|
||||
type='CameraProjection',
|
||||
item='input_3d',
|
||||
camera_type='SimpleCamera',
|
||||
camera_param=camera_param,
|
||||
mode='dummy')
|
||||
])
|
||||
|
||||
# test camera without undistortion
|
||||
camera_param_wo_undistortion = camera_param.copy()
|
||||
camera_param_wo_undistortion.pop('k')
|
||||
camera_param_wo_undistortion.pop('p')
|
||||
_ = Compose([
|
||||
dict(
|
||||
type='CameraProjection',
|
||||
item='input_3d',
|
||||
camera_type='SimpleCamera',
|
||||
camera_param=camera_param_wo_undistortion,
|
||||
mode='camera_to_pixel')
|
||||
])
|
||||
|
||||
# test pixel to camera transformation
|
||||
camera = SimpleCamera(camera_param_wo_undistortion)
|
||||
kpt_camera = np.random.rand(14, 3)
|
||||
kpt_pixel = camera.camera_to_pixel(kpt_camera)
|
||||
_kpt_camera = camera.pixel_to_camera(
|
||||
np.concatenate([kpt_pixel, kpt_camera[:, [2]]], -1))
|
||||
assert_array_almost_equal(_kpt_camera, kpt_camera, decimal=4)
|
||||
|
||||
|
||||
def test_3d_heatmap_generation():
|
||||
ann_info = dict(
|
||||
image_size=np.array([256, 256]),
|
||||
heatmap_size=np.array([64, 64, 64]),
|
||||
heatmap3d_depth_bound=400.0,
|
||||
num_joints=17,
|
||||
joint_weights=np.ones((17, 1), dtype=np.float32),
|
||||
use_different_joint_weights=False)
|
||||
|
||||
results = dict(
|
||||
joints_3d=np.zeros([17, 3]),
|
||||
joints_3d_visible=np.ones([17, 3]),
|
||||
ann_info=ann_info)
|
||||
|
||||
pipeline = Compose([dict(type='Generate3DHeatmapTarget')])
|
||||
results_3d = pipeline(results)
|
||||
assert results_3d['target'].shape == (17, 64, 64, 64)
|
||||
assert results_3d['target_weight'].shape == (17, 1)
|
||||
|
||||
# test joint_indices
|
||||
pipeline = Compose(
|
||||
[dict(type='Generate3DHeatmapTarget', joint_indices=[0, 8, 16])])
|
||||
results_3d = pipeline(results)
|
||||
assert results_3d['target'].shape == (3, 64, 64, 64)
|
||||
assert results_3d['target_weight'].shape == (3, 1)
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
# Copyright (c) OpenMMLab. All rights reserved.
|
||||
import os.path as osp
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
from mmcv import bgr2rgb, build_from_cfg
|
||||
|
||||
from mmpose.datasets import PIPELINES
|
||||
from mmpose.datasets.pipelines import Compose
|
||||
|
||||
|
||||
def check_keys_equal(result_keys, target_keys):
|
||||
"""Check if all elements in target_keys is in result_keys."""
|
||||
return set(target_keys) == set(result_keys)
|
||||
|
||||
|
||||
def check_keys_contain(result_keys, target_keys):
|
||||
"""Check if elements in target_keys is in result_keys."""
|
||||
return set(target_keys).issubset(set(result_keys))
|
||||
|
||||
|
||||
def test_compose():
|
||||
with pytest.raises(TypeError):
|
||||
# transform must be callable or a dict
|
||||
Compose('LoadImageFromFile')
|
||||
|
||||
target_keys = ['img', 'img_rename', 'img_metas']
|
||||
|
||||
# test Compose given a data pipeline
|
||||
img = np.random.randn(256, 256, 3)
|
||||
results = dict(img=img, img_file='test_image.png')
|
||||
test_pipeline = [
|
||||
dict(
|
||||
type='Collect',
|
||||
keys=['img', ('img', 'img_rename')],
|
||||
meta_keys=['img_file'])
|
||||
]
|
||||
compose = Compose(test_pipeline)
|
||||
compose_results = compose(results)
|
||||
assert check_keys_equal(compose_results.keys(), target_keys)
|
||||
assert check_keys_equal(compose_results['img_metas'].data.keys(),
|
||||
['img_file'])
|
||||
|
||||
# test Compose when forward data is None
|
||||
results = None
|
||||
|
||||
class ExamplePipeline:
|
||||
|
||||
def __call__(self, results):
|
||||
return None
|
||||
|
||||
nonePipeline = ExamplePipeline()
|
||||
test_pipeline = [nonePipeline]
|
||||
compose = Compose(test_pipeline)
|
||||
compose_results = compose(results)
|
||||
assert compose_results is None
|
||||
|
||||
assert repr(compose) == compose.__class__.__name__ + \
|
||||
f'(\n {nonePipeline}\n)'
|
||||
|
||||
|
||||
def test_load_image_from_file():
|
||||
# Define simple pipeline
|
||||
load = dict(type='LoadImageFromFile')
|
||||
load = build_from_cfg(load, PIPELINES)
|
||||
|
||||
data_prefix = 'tests/data/coco/'
|
||||
image_file = osp.join(data_prefix, '00000000078.jpg')
|
||||
results = dict(image_file=image_file)
|
||||
|
||||
# load an image that doesn't exist
|
||||
with pytest.raises(FileNotFoundError):
|
||||
results = load(results)
|
||||
|
||||
# mormal loading
|
||||
image_file = osp.join(data_prefix, '000000000785.jpg')
|
||||
results = dict(image_file=image_file)
|
||||
results = load(results)
|
||||
assert results['img'].shape == (425, 640, 3)
|
||||
|
||||
# load a single image from a list
|
||||
image_file = [osp.join(data_prefix, '000000000785.jpg')]
|
||||
results = dict(image_file=image_file)
|
||||
results = load(results)
|
||||
assert len(results['img']) == 1
|
||||
|
||||
# test loading multi images from a list
|
||||
image_file = [
|
||||
osp.join(data_prefix, '000000000785.jpg'),
|
||||
osp.join(data_prefix, '00000004008.jpg'),
|
||||
]
|
||||
results = dict(image_file=image_file)
|
||||
|
||||
with pytest.raises(FileNotFoundError):
|
||||
results = load(results)
|
||||
|
||||
image_file = [
|
||||
osp.join(data_prefix, '000000000785.jpg'),
|
||||
osp.join(data_prefix, '000000040083.jpg'),
|
||||
]
|
||||
results = dict(image_file=image_file)
|
||||
|
||||
results = load(results)
|
||||
assert len(results['img']) == 2
|
||||
|
||||
# manually set image outside the pipeline
|
||||
img = np.random.randint(0, 255, (32, 32, 3), dtype=np.uint8)
|
||||
results = load(dict(img=img))
|
||||
np.testing.assert_equal(results['img'], bgr2rgb(img))
|
||||
|
||||
imgs = np.random.randint(0, 255, (2, 32, 32, 3), dtype=np.uint8)
|
||||
desired = np.concatenate([bgr2rgb(img) for img in imgs], axis=0)
|
||||
results = load(dict(img=imgs))
|
||||
np.testing.assert_equal(results['img'], desired)
|
||||
|
||||
# neither 'image_file' or valid 'img' is given
|
||||
results = dict()
|
||||
with pytest.raises(KeyError):
|
||||
_ = load(results)
|
||||
|
||||
results = dict(img=np.random.randint(0, 255, (32, 32), dtype=np.uint8))
|
||||
with pytest.raises(ValueError):
|
||||
_ = load(results)
|
||||
|
||||
|
||||
def test_albu_transform():
|
||||
data_prefix = 'tests/data/coco/'
|
||||
results = dict(image_file=osp.join(data_prefix, '000000000785.jpg'))
|
||||
|
||||
# Define simple pipeline
|
||||
load = dict(type='LoadImageFromFile')
|
||||
load = build_from_cfg(load, PIPELINES)
|
||||
|
||||
albu_transform = dict(
|
||||
type='Albumentation',
|
||||
transforms=[
|
||||
dict(type='RandomBrightnessContrast', p=0.2),
|
||||
dict(type='ToFloat')
|
||||
])
|
||||
albu_transform = build_from_cfg(albu_transform, PIPELINES)
|
||||
|
||||
# Execute transforms
|
||||
results = load(results)
|
||||
|
||||
results = albu_transform(results)
|
||||
|
||||
assert results['img'].dtype == np.float32
|
||||
|
||||
|
||||
def test_photometric_distortion_transform():
|
||||
data_prefix = 'tests/data/coco/'
|
||||
results = dict(image_file=osp.join(data_prefix, '000000000785.jpg'))
|
||||
|
||||
# Define simple pipeline
|
||||
load = dict(type='LoadImageFromFile')
|
||||
load = build_from_cfg(load, PIPELINES)
|
||||
|
||||
photo_transform = dict(type='PhotometricDistortion')
|
||||
photo_transform = build_from_cfg(photo_transform, PIPELINES)
|
||||
|
||||
# Execute transforms
|
||||
results = load(results)
|
||||
|
||||
results = photo_transform(results)
|
||||
|
||||
assert results['img'].dtype == np.uint8
|
||||
|
||||
|
||||
def test_multitask_gather():
|
||||
ann_info = dict(
|
||||
image_size=np.array([256, 256]),
|
||||
heatmap_size=np.array([64, 64]),
|
||||
num_joints=17,
|
||||
joint_weights=np.ones((17, 1), dtype=np.float32),
|
||||
use_different_joint_weights=False)
|
||||
|
||||
results = dict(
|
||||
joints_3d=np.zeros([17, 3]),
|
||||
joints_3d_visible=np.ones([17, 3]),
|
||||
ann_info=ann_info)
|
||||
|
||||
pipeline_list = [[dict(type='TopDownGenerateTarget', sigma=2)],
|
||||
[dict(type='TopDownGenerateTargetRegression')]]
|
||||
pipeline = dict(
|
||||
type='MultitaskGatherTarget',
|
||||
pipeline_list=pipeline_list,
|
||||
pipeline_indices=[0, 1, 0],
|
||||
)
|
||||
pipeline = build_from_cfg(pipeline, PIPELINES)
|
||||
|
||||
results = pipeline(results)
|
||||
target = results['target']
|
||||
target_weight = results['target_weight']
|
||||
assert isinstance(target, list)
|
||||
assert isinstance(target_weight, list)
|
||||
assert target[0].shape == (17, 64, 64)
|
||||
assert target_weight[0].shape == (17, 1)
|
||||
assert target[1].shape == (17, 2)
|
||||
assert target_weight[1].shape == (17, 2)
|
||||
assert target[2].shape == (17, 64, 64)
|
||||
assert target_weight[2].shape == (17, 1)
|
||||
|
||||
|
||||
def test_rename_keys():
|
||||
results = dict(
|
||||
joints_3d=np.ones([17, 3]), joints_3d_visible=np.ones([17, 3]))
|
||||
pipeline = dict(
|
||||
type='RenameKeys',
|
||||
key_pairs=[('joints_3d', 'target'),
|
||||
('joints_3d_visible', 'target_weight')])
|
||||
pipeline = build_from_cfg(pipeline, PIPELINES)
|
||||
results = pipeline(results)
|
||||
assert 'joints_3d' not in results
|
||||
assert 'joints_3d_visible' not in results
|
||||
assert 'target' in results
|
||||
assert 'target_weight' in results
|
||||
assert results['target'].shape == (17, 3)
|
||||
assert results['target_weight'].shape == (17, 3)
|
||||
+243
@@ -0,0 +1,243 @@
|
||||
# Copyright (c) OpenMMLab. All rights reserved.
|
||||
import copy
|
||||
import os.path as osp
|
||||
|
||||
import numpy as np
|
||||
import torch
|
||||
from numpy.testing import assert_array_almost_equal
|
||||
from xtcocotools.coco import COCO
|
||||
|
||||
from mmpose.datasets.pipelines import (Collect, LoadImageFromFile,
|
||||
NormalizeTensor, TopDownAffine,
|
||||
TopDownGenerateTarget,
|
||||
TopDownGetRandomScaleRotation,
|
||||
TopDownHalfBodyTransform,
|
||||
TopDownRandomFlip,
|
||||
TopDownRandomTranslation, ToTensor)
|
||||
|
||||
|
||||
def _check_keys_contain(result_keys, target_keys):
|
||||
"""Check if all elements in target_keys is in result_keys."""
|
||||
return set(target_keys).issubset(set(result_keys))
|
||||
|
||||
|
||||
def _check_flip(origin_imgs, result_imgs):
|
||||
"""Check if the origin_imgs are flipped correctly."""
|
||||
h, w, c = origin_imgs.shape
|
||||
for i in range(h):
|
||||
for j in range(w):
|
||||
for k in range(c):
|
||||
if result_imgs[i, j, k] != origin_imgs[i, w - 1 - j, k]:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _check_rot90(origin_imgs, result_imgs):
|
||||
if origin_imgs.shape[0] == result_imgs.shape[1] and \
|
||||
origin_imgs.shape[1] == result_imgs.shape[0]:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def _check_normalize(origin_imgs, result_imgs, norm_cfg):
|
||||
"""Check if the origin_imgs are normalized correctly into result_imgs in a
|
||||
given norm_cfg."""
|
||||
target_imgs = result_imgs.copy()
|
||||
for i in range(3):
|
||||
target_imgs[i] *= norm_cfg['std'][i]
|
||||
target_imgs[i] += norm_cfg['mean'][i]
|
||||
assert_array_almost_equal(origin_imgs, target_imgs, decimal=4)
|
||||
|
||||
|
||||
def _box2cs(box, image_size):
|
||||
x, y, w, h = box[:4]
|
||||
|
||||
aspect_ratio = 1. * image_size[0] / image_size[1]
|
||||
center = np.zeros((2), dtype=np.float32)
|
||||
center[0] = x + w * 0.5
|
||||
center[1] = y + h * 0.5
|
||||
|
||||
if w > aspect_ratio * h:
|
||||
h = w * 1.0 / aspect_ratio
|
||||
elif w < aspect_ratio * h:
|
||||
w = h * aspect_ratio
|
||||
scale = np.array([w * 1.0 / 200.0, h * 1.0 / 200.0], dtype=np.float32)
|
||||
scale = scale * 1.25
|
||||
return center, scale
|
||||
|
||||
|
||||
def test_top_down_pipeline():
|
||||
# test loading
|
||||
data_prefix = 'tests/data/coco/'
|
||||
ann_file = osp.join(data_prefix, 'test_coco.json')
|
||||
coco = COCO(ann_file)
|
||||
|
||||
results = dict(image_file=osp.join(data_prefix, '000000000785.jpg'))
|
||||
transform = LoadImageFromFile()
|
||||
results = transform(copy.deepcopy(results))
|
||||
assert results['image_file'] == osp.join(data_prefix, '000000000785.jpg')
|
||||
|
||||
assert results['img'].shape == (425, 640, 3)
|
||||
image_size = (425, 640)
|
||||
|
||||
ann_ids = coco.getAnnIds(785)
|
||||
ann = coco.anns[ann_ids[0]]
|
||||
|
||||
num_joints = 17
|
||||
joints_3d = np.zeros((num_joints, 3), dtype=np.float32)
|
||||
joints_3d_visible = np.zeros((num_joints, 3), dtype=np.float32)
|
||||
for ipt in range(num_joints):
|
||||
joints_3d[ipt, 0] = ann['keypoints'][ipt * 3 + 0]
|
||||
joints_3d[ipt, 1] = ann['keypoints'][ipt * 3 + 1]
|
||||
joints_3d[ipt, 2] = 0
|
||||
t_vis = ann['keypoints'][ipt * 3 + 2]
|
||||
if t_vis > 1:
|
||||
t_vis = 1
|
||||
joints_3d_visible[ipt, 0] = t_vis
|
||||
joints_3d_visible[ipt, 1] = t_vis
|
||||
joints_3d_visible[ipt, 2] = 0
|
||||
|
||||
center, scale = _box2cs(ann['bbox'][:4], image_size)
|
||||
|
||||
results['joints_3d'] = joints_3d
|
||||
results['joints_3d_visible'] = joints_3d_visible
|
||||
results['center'] = center
|
||||
results['scale'] = scale
|
||||
results['bbox_score'] = 1
|
||||
results['bbox_id'] = 0
|
||||
|
||||
results['ann_info'] = {}
|
||||
results['ann_info']['flip_pairs'] = [[1, 2], [3, 4], [5, 6], [7, 8],
|
||||
[9, 10], [11, 12], [13, 14], [15, 16]]
|
||||
results['ann_info']['num_joints'] = num_joints
|
||||
results['ann_info']['upper_body_ids'] = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
|
||||
results['ann_info']['lower_body_ids'] = (11, 12, 13, 14, 15, 16)
|
||||
results['ann_info']['use_different_joint_weights'] = False
|
||||
results['ann_info']['joint_weights'] = np.array([
|
||||
1., 1., 1., 1., 1., 1., 1., 1.2, 1.2, 1.5, 1.5, 1., 1., 1.2, 1.2, 1.5,
|
||||
1.5
|
||||
],
|
||||
dtype=np.float32).reshape(
|
||||
(num_joints, 1))
|
||||
results['ann_info']['image_size'] = np.array([192, 256])
|
||||
results['ann_info']['heatmap_size'] = np.array([48, 64])
|
||||
|
||||
# test flip
|
||||
random_flip = TopDownRandomFlip(flip_prob=1.)
|
||||
results_flip = random_flip(copy.deepcopy(results))
|
||||
assert _check_flip(results['img'], results_flip['img'])
|
||||
|
||||
# test random scale and rotate
|
||||
random_scale_rotate = TopDownGetRandomScaleRotation(90, 0.3, 1.0)
|
||||
results_scale_rotate = random_scale_rotate(copy.deepcopy(results))
|
||||
assert results_scale_rotate['rotation'] <= 180
|
||||
assert results_scale_rotate['rotation'] >= -180
|
||||
assert (results_scale_rotate['scale'] / results['scale'] <= 1.3).all()
|
||||
assert (results_scale_rotate['scale'] / results['scale'] >= 0.7).all()
|
||||
|
||||
# test halfbody transform
|
||||
halfbody_transform = TopDownHalfBodyTransform(
|
||||
num_joints_half_body=8, prob_half_body=1.)
|
||||
results_halfbody = halfbody_transform(copy.deepcopy(results))
|
||||
assert (results_halfbody['scale'] <= results['scale']).all()
|
||||
|
||||
affine_transform = TopDownAffine()
|
||||
results['rotation'] = 90
|
||||
results_affine = affine_transform(copy.deepcopy(results))
|
||||
assert results_affine['img'].shape == (256, 192, 3)
|
||||
|
||||
results = results_affine
|
||||
to_tensor = ToTensor()
|
||||
results_tensor = to_tensor(copy.deepcopy(results))
|
||||
assert isinstance(results_tensor['img'], torch.Tensor)
|
||||
assert results_tensor['img'].shape == torch.Size([3, 256, 192])
|
||||
|
||||
norm_cfg = {}
|
||||
norm_cfg['mean'] = [0.485, 0.456, 0.406]
|
||||
norm_cfg['std'] = [0.229, 0.224, 0.225]
|
||||
|
||||
normalize = NormalizeTensor(mean=norm_cfg['mean'], std=norm_cfg['std'])
|
||||
|
||||
results_normalize = normalize(copy.deepcopy(results_tensor))
|
||||
_check_normalize(results_tensor['img'].data.numpy(),
|
||||
results_normalize['img'].data.numpy(), norm_cfg)
|
||||
|
||||
generate_target = TopDownGenerateTarget(
|
||||
sigma=2, target_type='GaussianHeatMap', unbiased_encoding=True)
|
||||
results_target = generate_target(copy.deepcopy(results_tensor))
|
||||
assert 'target' in results_target
|
||||
assert results_target['target'].shape == (
|
||||
num_joints, results['ann_info']['heatmap_size'][1],
|
||||
results['ann_info']['heatmap_size'][0])
|
||||
assert 'target_weight' in results_target
|
||||
assert results_target['target_weight'].shape == (num_joints, 1)
|
||||
|
||||
generate_target = TopDownGenerateTarget(
|
||||
sigma=2, target_type='GaussianHeatmap', unbiased_encoding=True)
|
||||
results_target = generate_target(copy.deepcopy(results_tensor))
|
||||
assert 'target' in results_target
|
||||
assert results_target['target'].shape == (
|
||||
num_joints, results['ann_info']['heatmap_size'][1],
|
||||
results['ann_info']['heatmap_size'][0])
|
||||
assert 'target_weight' in results_target
|
||||
assert results_target['target_weight'].shape == (num_joints, 1)
|
||||
|
||||
generate_target = TopDownGenerateTarget(sigma=2, unbiased_encoding=False)
|
||||
results_target = generate_target(copy.deepcopy(results_tensor))
|
||||
assert 'target' in results_target
|
||||
assert results_target['target'].shape == (
|
||||
num_joints, results['ann_info']['heatmap_size'][1],
|
||||
results['ann_info']['heatmap_size'][0])
|
||||
assert 'target_weight' in results_target
|
||||
assert results_target['target_weight'].shape == (num_joints, 1)
|
||||
|
||||
generate_target = TopDownGenerateTarget(
|
||||
sigma=[2, 3], unbiased_encoding=False)
|
||||
results_target = generate_target(copy.deepcopy(results_tensor))
|
||||
assert 'target' in results_target
|
||||
assert results_target['target'].shape == (
|
||||
2, num_joints, results['ann_info']['heatmap_size'][1],
|
||||
results['ann_info']['heatmap_size'][0])
|
||||
assert 'target_weight' in results_target
|
||||
assert results_target['target_weight'].shape == (2, num_joints, 1)
|
||||
|
||||
generate_target = TopDownGenerateTarget(
|
||||
kernel=(11, 11), encoding='Megvii', unbiased_encoding=False)
|
||||
results_target = generate_target(copy.deepcopy(results_tensor))
|
||||
assert 'target' in results_target
|
||||
assert results_target['target'].shape == (
|
||||
num_joints, results['ann_info']['heatmap_size'][1],
|
||||
results['ann_info']['heatmap_size'][0])
|
||||
assert 'target_weight' in results_target
|
||||
assert results_target['target_weight'].shape == (num_joints, 1)
|
||||
|
||||
generate_target = TopDownGenerateTarget(
|
||||
kernel=[(11, 11), (7, 7)], encoding='Megvii', unbiased_encoding=False)
|
||||
results_target = generate_target(copy.deepcopy(results_tensor))
|
||||
assert 'target' in results_target
|
||||
assert results_target['target'].shape == (
|
||||
2, num_joints, results['ann_info']['heatmap_size'][1],
|
||||
results['ann_info']['heatmap_size'][0])
|
||||
assert 'target_weight' in results_target
|
||||
assert results_target['target_weight'].shape == (2, num_joints, 1)
|
||||
|
||||
collect = Collect(
|
||||
keys=['img', 'target', 'target_weight'],
|
||||
meta_keys=[
|
||||
'image_file', 'center', 'scale', 'rotation', 'bbox_score',
|
||||
'flip_pairs'
|
||||
])
|
||||
results_final = collect(results_target)
|
||||
assert 'img_size' not in results_final['img_metas'].data
|
||||
assert 'image_file' in results_final['img_metas'].data
|
||||
|
||||
|
||||
def test_random_translation():
|
||||
results = dict(
|
||||
center=np.zeros([2]),
|
||||
scale=1,
|
||||
)
|
||||
pipeline = TopDownRandomTranslation()
|
||||
results = pipeline(results)
|
||||
assert results['center'].shape == (2, )
|
||||
Reference in New Issue
Block a user