File size: 5,101 Bytes
e34aada
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import numpy as np
import torch
import copy
from utils.commons.tensor_utils import convert_to_tensor, convert_to_np
from deep_3drecon.deep_3drecon_models.bfm import ParametricFaceModel


def _fix_intrinsics(intrinsics):
    """
    intrinsics: [3,3], not batch-wise
    """
    # unnormalized                                normalized

    # [[ f_x, s=0,    x_0]             [[ f_x/size_x,   s=0,            x_0/size_x=0.5]
    #  [ 0,   f_y,  y_0]      ->      [ 0,            f_y/size_y,   y_0/size_y=0.5]
    #  [ 0,   0,    1  ]]             [ 0,            0,            1         ]]
    intrinsics = np.array(intrinsics).copy()
    assert intrinsics.shape == (3, 3), intrinsics
    intrinsics[0,0] = 2985.29/700
    intrinsics[1,1] = 2985.29/700
    intrinsics[0,2] = 1/2
    intrinsics[1,2] = 1/2
    assert intrinsics[0,1] == 0
    assert intrinsics[2,2] == 1
    assert intrinsics[1,0] == 0
    assert intrinsics[2,0] == 0
    assert intrinsics[2,1] == 0
    return intrinsics

# Used in original submission
def _fix_pose_orig(pose):
    """
    pose: [4,4], not batch-wise
    """
    pose = np.array(pose).copy()
    location = pose[:3, 3]
    radius = np.linalg.norm(location)
    pose[:3, 3] = pose[:3, 3]/radius * 2.7
    return pose


def get_eg3d_convention_camera_pose_intrinsic(item):
    """
    item: a dict during binarize

    """
    if item['euler'].ndim == 1:
        angle = convert_to_tensor(copy.copy(item['euler']))
        trans = copy.deepcopy(item['trans'])

        # handle the difference of euler axis between eg3d and ours
        # see data_gen/process_ffhq_for_eg3d/transplant_eg3d_ckpt_into_our_convention.ipynb
        # angle += torch.tensor([0, 3.1415926535, 3.1415926535], device=angle.device)
        R = ParametricFaceModel.compute_rotation(angle.unsqueeze(0))[0].cpu().numpy()
        trans[2] += -10
        c = -np.dot(R, trans)
        pose = np.eye(4)
        pose[:3,:3] = R
        c *= 0.27 # normalize camera radius
        c[1] += 0.006 # additional offset used in submission
        c[2] += 0.161 # additional offset used in submission
        pose[0,3] = c[0]
        pose[1,3] = c[1]
        pose[2,3] = c[2]

        focal = 2985.29 # = 1015*1024/224*(300/466.285),
        # todo: 如果修改了fit 3dmm阶段的camera intrinsic,这里也要跟着改
        pp = 512#112
        w = 1024#224
        h = 1024#224

        K = np.eye(3)
        K[0][0] = focal
        K[1][1] = focal
        K[0][2] = w/2.0
        K[1][2] = h/2.0
        convention_K = _fix_intrinsics(K)

        Rot = np.eye(3)
        Rot[0, 0] = 1
        Rot[1, 1] = -1
        Rot[2, 2] = -1        
        pose[:3, :3] = np.dot(pose[:3, :3], Rot) # permute axes
        convention_pose = _fix_pose_orig(pose)

        item['c2w'] = pose
        item['convention_c2w'] = convention_pose
        item['intrinsics'] = convention_K
        return item
    else:
        num_samples = len(item['euler'])
        eulers_all = convert_to_tensor(copy.deepcopy(item['euler'])) # [B, 3]
        trans_all = copy.deepcopy(item['trans']) # [B, 3]

        # handle the difference of euler axis between eg3d and ours
        # see data_gen/process_ffhq_for_eg3d/transplant_eg3d_ckpt_into_our_convention.ipynb
        # eulers_all += torch.tensor([0, 3.1415926535, 3.1415926535], device=eulers_all.device).unsqueeze(0).repeat([eulers_all.shape[0],1])

        intrinsics = []
        poses = []
        convention_poses = []
        for i in range(num_samples):
            angle = eulers_all[i]
            trans = trans_all[i]
            R = ParametricFaceModel.compute_rotation(angle.unsqueeze(0))[0].cpu().numpy()
            trans[2] += -10
            c = -np.dot(R, trans)
            pose = np.eye(4)
            pose[:3,:3] = R
            c *= 0.27 # normalize camera radius
            c[1] += 0.006 # additional offset used in submission
            c[2] += 0.161 # additional offset used in submission
            pose[0,3] = c[0]
            pose[1,3] = c[1]
            pose[2,3] = c[2]

            focal = 2985.29 # = 1015*1024/224*(300/466.285),
            # todo: 如果修改了fit 3dmm阶段的camera intrinsic,这里也要跟着改
            pp = 512#112
            w = 1024#224
            h = 1024#224

            K = np.eye(3)
            K[0][0] = focal
            K[1][1] = focal
            K[0][2] = w/2.0
            K[1][2] = h/2.0
            convention_K = _fix_intrinsics(K)
            intrinsics.append(convention_K)

            Rot = np.eye(3)
            Rot[0, 0] = 1
            Rot[1, 1] = -1
            Rot[2, 2] = -1        
            pose[:3, :3] = np.dot(pose[:3, :3], Rot)
            convention_pose = _fix_pose_orig(pose)
            convention_poses.append(convention_pose)
            poses.append(pose)

        intrinsics = np.stack(intrinsics) # [B, 3, 3]
        poses = np.stack(poses) # [B, 4, 4]
        convention_poses = np.stack(convention_poses) # [B, 4, 4]
        item['intrinsics'] = intrinsics
        item['c2w'] = poses
        item['convention_c2w'] = convention_poses
        return item