forked from cleardusk/3DDFA
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathddfa_utils.py
148 lines (112 loc) · 3.9 KB
/
ddfa_utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env python3
# coding: utf-8
import os.path as osp
from pathlib import Path
import numpy as np
import torch
import torch.utils.data as data
import cv2
import pickle
import argparse
from io_utils import _numpy_to_tensor, _load_cpu, _load_gpu
from params import *
def reconstruct_vertex(param, whitening=True, dense=False):
"""Whitening param -> 3d vertex, based on the 3dmm param: u_base, w_shp, w_exp"""
if len(param) == 12:
param = np.concatenate((param, [0] * 50))
if whitening:
if len(param) == 62:
param = param * param_std + param_mean
else:
param = np.concatenate((param[:11], [0], param[11:]))
param = param * param_std + param_mean
p_ = param[:12].reshape(3, -1)
p = p_[:, :3]
offset = p_[:, -1].reshape(3, 1)
alpha_shp = param[12:52].reshape(-1, 1)
alpha_exp = param[52:].reshape(-1, 1)
if dense:
vertex = p @ (u + w_shp @ alpha_shp + w_exp @ alpha_exp).reshape(3, -1, order='F') + offset
else:
"""For 68 pts"""
vertex = p @ (u_base + w_shp_base @ alpha_shp + w_exp_base @ alpha_exp).reshape(3, -1, order='F') + offset
# for landmarks
vertex[1, :] = std_size + 1 - vertex[1, :]
return vertex
def img_loader(path):
return cv2.imread(path, cv2.IMREAD_COLOR)
def str2bool(v):
if v.lower() in ('yes', 'true', 't', 'y', '1'):
return True
elif v.lower() in ('no', 'false', 'f', 'n', '0'):
return False
else:
raise argparse.ArgumentTypeError('Boolean value expected')
def _parse_param(param):
"""Work for both numpy and tensor"""
p_ = param[:12].reshape(3, -1)
p = p_[:, :3]
offset = p_[:, -1].reshape(3, 1)
alpha_shp = param[12:52].reshape(-1, 1)
alpha_exp = param[52:].reshape(-1, 1)
return p, offset, alpha_shp, alpha_exp
class AverageMeter(object):
"""Computes and stores the average and current value"""
def __init__(self):
self.reset()
def reset(self):
self.val = 0
self.avg = 0
self.sum = 0
self.count = 0
def update(self, val, n=1):
self.val = val
self.sum += val * n
self.count += n
self.avg = self.sum / self.count
class ToTensorGjz(object):
def __call__(self, pic):
if isinstance(pic, np.ndarray):
img = torch.from_numpy(pic.transpose((2, 0, 1)))
return img.float()
def __repr__(self):
return self.__class__.__name__ + '()'
class NormalizeGjz(object):
def __init__(self, mean, std):
self.mean = mean
self.std = std
def __call__(self, tensor):
tensor.sub_(self.mean).div_(self.std)
return tensor
class DDFADataset(data.Dataset):
def __init__(self, root, filelists, param_fp, transform=None, **kargs):
self.root = root
self.transform = transform
self.lines = Path(filelists).read_text().strip().split('\n')
self.params = _numpy_to_tensor(_load_cpu(param_fp))
self.img_loader = img_loader
def _target_loader(self, index):
target = self.params[index]
return target
def __getitem__(self, index):
path = osp.join(self.root, self.lines[index])
img = self.img_loader(path)
target = self._target_loader(index)
if self.transform is not None:
img = self.transform(img)
return img, target
def __len__(self):
return len(self.lines)
class DDFATestDataset(data.Dataset):
def __init__(self, filelists, root='', transform=None):
self.root = root
self.transform = transform
self.lines = Path(filelists).read_text().strip().split('\n')
def __getitem__(self, index):
path = osp.join(self.root, self.lines[index])
img = img_loader(path)
if self.transform is not None:
img = self.transform(img)
return img
def __len__(self):
return len(self.lines)