156 lines
5.8 KiB
Python
156 lines
5.8 KiB
Python
|
#!/usr/bin/env python
|
||
|
# -*- coding: utf-8 -*-
|
||
|
|
||
|
|
||
|
'''
|
||
|
##################################################
|
||
|
## YML 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_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>"
|
||
|
'''
|
||
|
|
||
|
|
||
|
## 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.4'
|
||
|
__maintainer__ = "David Pagnon"
|
||
|
__email__ = "contact@david-pagnon.com"
|
||
|
__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_yml_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='OpenCV intrinsic .yml calibration file')
|
||
|
parser.add_argument('-e', '--extrinsic_file', required = True, help='OpenCV extrinsic .yml calibration file')
|
||
|
parser.add_argument('-t', '--toml_file', required=False, help='OpenCV .toml output calibration file')
|
||
|
args = vars(parser.parse_args())
|
||
|
|
||
|
calib_yml_to_toml_func(args)
|
||
|
|