228 lines
9.2 KiB
Python
228 lines
9.2 KiB
Python
|
'''
|
|||
|
@ Date: 2022-07-15 19:25:33
|
|||
|
@ Author: Qing Shuai
|
|||
|
@ Mail: s_q@zju.edu.cn
|
|||
|
@ LastEditors: Qing Shuai
|
|||
|
@ LastEditTime: 2022-07-15 21:00:40
|
|||
|
@ FilePath: /EasyMocapPublic/easymocap/neuralbody/dataset/mirror.py
|
|||
|
'''
|
|||
|
from os.path import join
|
|||
|
import numpy as np
|
|||
|
import cv2
|
|||
|
from tqdm import trange
|
|||
|
import copy
|
|||
|
from .mvbase import BaseDataset, read_json, get_bounds
|
|||
|
from ...multistage.mirror import calc_mirror_transform
|
|||
|
import torch
|
|||
|
from .utils_sample import AABBwMask
|
|||
|
|
|||
|
def mirror_params(params, mirror, T0=np.eye(4, dtype=np.float32)):
|
|||
|
params = params.copy()
|
|||
|
M = np.eye(4, dtype=np.float32)
|
|||
|
M[:3] = calc_mirror_transform(torch.Tensor(mirror))[0].numpy()
|
|||
|
T1 = M @ T0
|
|||
|
T1[0, :] *= -1
|
|||
|
Rh = cv2.Rodrigues(params['Rh'])[0]
|
|||
|
Th = params['Th'].T
|
|||
|
Rnew = T1[:3, :3] @ Rh
|
|||
|
Tnew = T1[:3, :3] @ Th + T1[:3, 3:]
|
|||
|
params['Rh'] = cv2.Rodrigues(Rnew)[0].reshape(1, 3)
|
|||
|
params['Th'] = Tnew.T
|
|||
|
params['vertices'] = params['vertices'] @ T1[:3, :3].T + T1[:3, 3:].T
|
|||
|
return params
|
|||
|
|
|||
|
class MirrorDataset(BaseDataset):
|
|||
|
def get_allnames(self, root, subs, ranges, image_args):
|
|||
|
assert len(subs) == 1, 'Only support 1 sub-folder'
|
|||
|
infos = []
|
|||
|
index = 0
|
|||
|
nv = 0
|
|||
|
sub = subs[0]
|
|||
|
camera = self.cameras[sub].copy()
|
|||
|
K = camera['K'].copy()
|
|||
|
K[:2] *= image_args.scale
|
|||
|
camera['K'] = K
|
|||
|
# load mirror
|
|||
|
for nnf, nf in enumerate(trange(*ranges, desc='cache parameters')):
|
|||
|
annot = read_json(join(root, 'output-smpl-3d','smpl', sub, '{:06d}.json'.format(nf)))
|
|||
|
mirror = np.array(annot['mirror'], dtype=np.float32)
|
|||
|
vertices = read_json(join(root, 'output-smpl-3d','vertices', sub, '{:06d}.json'.format(nf)))
|
|||
|
annots = annot['annots']
|
|||
|
imgname = join(root, image_args.root, sub, '{:06d}{}'.format(nf, image_args.ext))
|
|||
|
info = {
|
|||
|
'imgname': imgname,
|
|||
|
'sub': sub,
|
|||
|
'frame': nf,
|
|||
|
'nf': nnf,
|
|||
|
'nv': nv,
|
|||
|
'index': index,
|
|||
|
'camera': camera,
|
|||
|
'flip_lr': False,
|
|||
|
'pid': 0
|
|||
|
}
|
|||
|
annots[0]['vertices'] = vertices[0]['vertices']
|
|||
|
annots[1]['vertices'] = vertices[0]['vertices']
|
|||
|
info_mirror = info.copy()
|
|||
|
for annot in annots:
|
|||
|
for key, val in annot.items():
|
|||
|
if key == 'id':continue
|
|||
|
annot[key] = np.array(val, dtype=np.float32)
|
|||
|
info['params'] = annots[0]
|
|||
|
info_mirror['params'] = mirror_params(annots[0], mirror)
|
|||
|
info_mirror['flip_lr'] = True
|
|||
|
info_mirror['pid'] = 1
|
|||
|
info_mirror['nv'] = 1
|
|||
|
info['bounds'] = get_bounds(info['params']['vertices'], delta=0.1)
|
|||
|
info_mirror['bounds'] = get_bounds(info_mirror['params']['vertices'], delta=0.1)
|
|||
|
info['params']['R'] = cv2.Rodrigues(info['params']['Rh'])[0]
|
|||
|
info_mirror['params']['R'] = cv2.Rodrigues(info_mirror['params']['Rh'])[0]
|
|||
|
infos.append(info)
|
|||
|
infos.append(info_mirror)
|
|||
|
return infos
|
|||
|
|
|||
|
def get_objects(self, root, info, object_keys, object_args):
|
|||
|
sub, frame, pid = info['sub'], info['frame'], info['pid']
|
|||
|
mskname = join(root, object_args['human_0'].args.reader.mask.root, sub, '{:06d}_{}.png'.format(frame, pid))
|
|||
|
msk = cv2.imread(mskname, 0)
|
|||
|
msk = self.scale_and_undistort(msk, info, undis=False)
|
|||
|
if info['flip_lr']:
|
|||
|
msk = cv2.flip(msk, 1)
|
|||
|
msk = msk > 0
|
|||
|
obj = AABBwMask(split=self.split, bounds=info['bounds'],
|
|||
|
mask=msk,
|
|||
|
label=None,
|
|||
|
dilate=False, # 这里假设mask很准,或者使用了patch
|
|||
|
rate_body=0.85)
|
|||
|
for key in ['R', 'Rh', 'Th', 'vertices', 'poses', 'shapes']:
|
|||
|
obj.feature[key] = info['params'][key]
|
|||
|
vertices_canonical = (info['params']['vertices'] - info['params']['Th']) @ info['params']['R'].T.T
|
|||
|
obj.feature['bounds_canonical'] = get_bounds(vertices_canonical,
|
|||
|
delta=object_args['human_0'].args.reader.vertices.padding)
|
|||
|
return {'human_0': obj}
|
|||
|
|
|||
|
def read_image(self, imgname, image_args, info, isgray=False, skip_mask=False, mask_global='_0.png'):
|
|||
|
if info['flip_lr']:
|
|||
|
return super().read_image(imgname, image_args, info, isgray, skip_mask, mask_global='_1.png')
|
|||
|
else:
|
|||
|
return super().read_image(imgname, image_args, info, isgray, skip_mask, mask_global)
|
|||
|
|
|||
|
def augment_rotation(self, info, rot, rotvec=[0., 1., 0.]):
|
|||
|
# method 1: rotate on its self
|
|||
|
rot = rot / 180 * np.pi
|
|||
|
rotvec = np.array([rotvec],dtype=np.float32)
|
|||
|
R = cv2.Rodrigues(rot*rotvec)[0]
|
|||
|
info = copy.deepcopy(info)
|
|||
|
params = info['params']
|
|||
|
T0 = params['Th']
|
|||
|
R0 = cv2.Rodrigues(params['Rh'])[0]
|
|||
|
v0 = params['vertices']
|
|||
|
v1 = (v0 - T0) @ R.T + T0
|
|||
|
params['vertices'] = v1
|
|||
|
R1 = R @ R0
|
|||
|
params['Rh'] = cv2.Rodrigues(R1)[0].reshape(1, 3)
|
|||
|
params['R'] = R1
|
|||
|
info['bounds'] = get_bounds(params['vertices'], delta=0.1)
|
|||
|
return info
|
|||
|
|
|||
|
class MirrorDatasetDemo(MirrorDataset):
|
|||
|
def __init__(self, keyframes, **cfg):
|
|||
|
self.keyframes = keyframes
|
|||
|
# 注意:初始化里面调用了get_allnames,所以要预先写进去
|
|||
|
super().__init__(**cfg)
|
|||
|
|
|||
|
def __len__(self):
|
|||
|
return super().__len__()//2
|
|||
|
|
|||
|
def get_allnames(self, root, subs, ranges, image_args):
|
|||
|
infos = super().get_allnames(root, subs, ranges, image_args)
|
|||
|
infos_new = []
|
|||
|
for nf in range(len(infos)//2):
|
|||
|
infos_l = infos[2*nf]
|
|||
|
infos_r = infos[2*nf+1]
|
|||
|
if nf in self.keyframes:
|
|||
|
for rot in range(0, 360, 4):
|
|||
|
infos_r_ = self.augment_rotation(infos_r, rot, rotvec=[0,1,0])
|
|||
|
infos_new.append(infos_l)
|
|||
|
infos_new.append(infos_r_)
|
|||
|
else:
|
|||
|
infos_new.append(infos_l)
|
|||
|
infos_new.append(infos_r)
|
|||
|
return infos_new
|
|||
|
|
|||
|
def __getitem__(self, index):
|
|||
|
left = super().__getitem__(2*index)
|
|||
|
right = super().__getitem__(2*index+1)
|
|||
|
return {'left': left, 'right': right, 'meta': {'type': 'mirror'}}
|
|||
|
|
|||
|
class MirrorDatasetDemoCool(BaseDataset):
|
|||
|
def __init__(self, **cfg):
|
|||
|
super().__init__(**cfg)
|
|||
|
|
|||
|
def get_allnames(self, root, subs, ranges, image_args):
|
|||
|
assert len(subs) == 1, 'Only support 1 sub-folder'
|
|||
|
infos = []
|
|||
|
index = 0
|
|||
|
nv = 0
|
|||
|
sub = subs[0]
|
|||
|
camera = self.cameras[sub].copy()
|
|||
|
K = camera['K'].copy()
|
|||
|
K[:2] *= image_args.scale
|
|||
|
camera['K'] = K
|
|||
|
# load mirror
|
|||
|
for nnf, nf in enumerate(trange(*ranges, desc='cache parameters')):
|
|||
|
annot = read_json(join(root, 'output-smpl-3d','smpl', sub, '{:06d}.json'.format(nf)))
|
|||
|
mirror = np.array(annot['mirror'], dtype=np.float32)
|
|||
|
vertices = read_json(join(root, 'output-smpl-3d','vertices', sub, '{:06d}.json'.format(nf)))
|
|||
|
# only use outer person
|
|||
|
annots = annot['annots'][:1]
|
|||
|
imgname = join(root, image_args.root, sub, '{:06d}{}'.format(nf, image_args.ext))
|
|||
|
info = {
|
|||
|
'imgname': imgname,
|
|||
|
'sub': sub,
|
|||
|
'frame': nf,
|
|||
|
'nf': nnf,
|
|||
|
'nv': nv,
|
|||
|
'index': index,
|
|||
|
'camera': camera,
|
|||
|
'flip_lr': False,
|
|||
|
'pid': 0
|
|||
|
}
|
|||
|
annots[0]['vertices'] = vertices[0]['vertices']
|
|||
|
for annot in annots:
|
|||
|
for key, val in annot.items():
|
|||
|
if key == 'id':continue
|
|||
|
annot[key] = np.array(val, dtype=np.float32)
|
|||
|
info['params'] = annots[0]
|
|||
|
# TODO: augment the rotation
|
|||
|
# method 1: rotate on its self
|
|||
|
rot = nnf / 180 * np.pi
|
|||
|
rotvec = np.array([[0., 1., 0.]],dtype=np.float32)
|
|||
|
R = cv2.Rodrigues(rot*rotvec)[0]
|
|||
|
T0 = info['params']['Th']
|
|||
|
R0 = cv2.Rodrigues(info['params']['Rh'])[0]
|
|||
|
v0 = info['params']['vertices']
|
|||
|
v1 = (v0 - T0) @ R.T + T0
|
|||
|
info['params']['vertices'] = v1
|
|||
|
R1 = R @ R0
|
|||
|
info['params']['Rh'] = cv2.Rodrigues(R1)[0].reshape(1, 3)
|
|||
|
info['params']['R'] = R1
|
|||
|
info['bounds'] = get_bounds(info['params']['vertices'], delta=0.1)
|
|||
|
infos.append(info)
|
|||
|
return infos
|
|||
|
|
|||
|
def get_objects(self, root, info, object_keys, object_args):
|
|||
|
sub, frame, pid = info['sub'], info['frame'], info['pid']
|
|||
|
mskname = join(root, object_args['human_0'].args.reader.mask.root, sub, '{:06d}_{}.png'.format(frame, pid))
|
|||
|
msk = cv2.imread(mskname, 0)
|
|||
|
msk = self.scale_and_undistort(msk, info, undis=False)
|
|||
|
if info['flip_lr']:
|
|||
|
msk = cv2.flip(msk, 1)
|
|||
|
msk = msk > 0
|
|||
|
obj = AABBwMask(split=self.split, bounds=info['bounds'],
|
|||
|
mask=msk,
|
|||
|
label=None,
|
|||
|
dilate=True,
|
|||
|
rate_body=0.85)
|
|||
|
for key in ['R', 'Rh', 'Th', 'vertices', 'poses', 'shapes']:
|
|||
|
obj.feature[key] = info['params'][key]
|
|||
|
return {'human_0': obj}
|