-
Notifications
You must be signed in to change notification settings - Fork 47
/
calib_easymocap_to_toml.py
155 lines (127 loc) · 5.84 KB
/
calib_easymocap_to_toml.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
149
150
151
152
153
154
155
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
##################################################
## EASYMOCAP CALIBRATION TO TOML CALIBRATION ##
##################################################
Converts OpenCV intrinsic and extrinsic .yml calibration files
to an OpenCV .toml calibration file
N.B. : Size is calculated as twice the position of the optical center.
Please correct in the resulting .toml file if needed. Take your image size as a reference.
Usage:
import calib_easymocap_to_toml; calib_yml_to_toml.calib_easymocap_to_toml_func(r'<intrinsic_yml_file>', r'<extrinsic_yml_file>')
OR python -m calib_easymocap_to_toml -i intrinsic_yml_file -e extrinsic_yml_file
OR python -m calib_easymocap_to_toml -i intrinsic_yml_file -e extrinsic_yml_file -o output_toml_file
'''
## INIT
import os
import argparse
import numpy as np
import cv2
## AUTHORSHIP INFORMATION
__author__ = "David Pagnon"
__copyright__ = "Copyright 2021, Pose2Sim"
__credits__ = ["David Pagnon"]
__license__ = "BSD 3-Clause License"
__version__ = "0.9.4"
__maintainer__ = "David Pagnon"
__email__ = "[email protected]"
__status__ = "Development"
## FUNCTIONS
def read_intrinsic_yml(intrinsic_path):
'''
Reads an intrinsic .yml calibration file
Returns 3 lists of size N (N=number of cameras):
- S (image size)
- K (intrinsic parameters)
- D (distorsion)
N.B. : Size is calculated as twice the position of the optical center. Please correct in the .toml file if needed.
'''
intrinsic_yml = cv2.FileStorage(intrinsic_path, cv2.FILE_STORAGE_READ)
N = intrinsic_yml.getNode('names').size()
S, D, K = [], [], []
for i in range(N):
name = intrinsic_yml.getNode('names').at(i).string()
K.append(intrinsic_yml.getNode(f'K_{name}').mat())
D.append(intrinsic_yml.getNode(f'dist_{name}').mat().flatten()[:-1])
S.append([K[i][0,2]*2, K[i][1,2]*2])
return S, K, D
def read_extrinsic_yml(extrinsic_path):
'''
Reads an intrinsic .yml calibration file
Returns 3 lists of size N (N=number of cameras):
- R (extrinsic rotation, Rodrigues vector)
- T (extrinsic translation)
'''
extrinsic_yml = cv2.FileStorage(extrinsic_path, cv2.FILE_STORAGE_READ)
N = extrinsic_yml.getNode('names').size()
R, T = [], []
for i in range(N):
name = extrinsic_yml.getNode('names').at(i).string()
R.append(extrinsic_yml.getNode(f'R_{name}').mat().flatten()) # R_1 pour Rodrigues, Rot_1 pour matrice
T.append(extrinsic_yml.getNode(f'T_{name}').mat().flatten())
return R, T
def read_calib_yml(intrinsic_path, extrinsic_path):
'''
Reads OpenCV .yml calibration files
Returns 5 lists of size N (N=number of cameras):
- C (camera name),
- S (image size),
- D (distorsion),
- K (intrinsic parameters),
- R (extrinsic rotation),
- T (extrinsic translation)
'''
S, K, D = read_intrinsic_yml(intrinsic_path)
R, T = read_extrinsic_yml(extrinsic_path)
C = np.array(range(len(S)))+1
return C, S, D, K, R, T
def toml_write(toml_path, C, S, D, K, R, T):
'''
Writes calibration parameters to a .toml file.
'''
with open(os.path.join(toml_path), 'w+') as cal_f:
for c in range(len(C)):
cam=f'[cam_{c+1}]\n'
name = f'name = "{C[c]}"\n'
size = f'size = [ {S[c][0]}, {S[c][1]},]\n'
mat = f'matrix = [ [ {K[c][0,0]}, 0.0, {K[c][0,2]},], [ 0.0, {K[c][1,1]}, {K[c][1,2]},], [ 0.0, 0.0, 1.0,],]\n'
dist = f'distortions = [ {D[c][0]}, {D[c][1]}, {D[c][2]}, {D[c][3]},]\n'
rot = f'rotation = [ {R[c][0]}, {R[c][1]}, {R[c][2]},]\n'
tran = f'translation = [ {T[c][0]}, {T[c][1]}, {T[c][2]},]\n'
fish = f'fisheye = false\n\n'
cal_f.write(cam + name + size + mat + dist + rot + tran + fish)
meta = '[metadata]\nadjusted = false\nerror = 0.0\n'
cal_f.write(meta)
def calib_easymocap_to_toml_func(*args):
'''
Converts OpenCV intrinsic and extrinsic .yml calibration files
to an OpenCV .toml calibration file
N.B. : Size is calculated as twice the position of the optical center.
Please correct in the resulting .toml file if needed. Take your image size as a reference.
Usage:
import calib_yml_to_toml; calib_yml_to_toml.calib_yml_to_toml_func(r'<intrinsic_yml_file>', r'<extrinsic_yml_file>')
OR python -m calib_yml_to_toml -i intrinsic_yml_file -e extrinsic_yml_file
OR python -m calib_yml_to_toml -i intrinsic_yml_file -e extrinsic_yml_file -o output_toml_file
'''
try:
intrinsic_path = os.path.realpath(args[0].get('intrinsic_file')) # invoked with argparse
extrinsic_path = os.path.realpath(args[0].get('extrinsic_file'))
if args[0]['toml_file'] == None:
toml_path = os.path.join(os.path.dirname(intrinsic_path), 'Calib.toml')
else:
toml_path = os.path.realpath(args[0]['toml_file'])
except:
intrinsic_path = os.path.realpath(args[0]) # invoked as a function
extrinsic_path = os.path.realpath(args[1])
toml_path = os.path.join(os.path.dirname(intrinsic_path), 'Calib.toml')
C, S, D, K, R, T = read_calib_yml(intrinsic_path, extrinsic_path)
toml_write(toml_path, C, S, D, K, R, T)
print(f'Calibration file generated at {toml_path}.\n')
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--intrinsic_file', required = True, help='EasyMocap intrinsic .yml calibration file')
parser.add_argument('-e', '--extrinsic_file', required = True, help='EasyMocap extrinsic .yml calibration file')
parser.add_argument('-t', '--toml_file', required=False, help='OpenCV .toml output calibration file')
args = vars(parser.parse_args())
calib_easymocap_to_toml_func(args)