Support caliscope calibration + fixed multi-person tracking

This commit is contained in:
davidpagnon 2024-09-22 23:06:07 +02:00
parent 3b2a4fa4c5
commit 4dc4060547
8 changed files with 43 additions and 31 deletions

View File

@ -67,7 +67,8 @@ filter_order = 4
calibration_type = 'convert' # 'convert' or 'calculate'
[calibration.convert]
convert_from = 'qualisys' # 'qualisys', 'optitrack', vicon', 'opencap', 'easymocap', 'biocv', 'anipose', or 'freemocap'
convert_from = 'caliscope' # 'caliscope', 'qualisys', 'optitrack', vicon', 'opencap', 'easymocap', 'biocv', 'anipose', or 'freemocap'
[calibration.convert.caliscope] # No parameter needed
[calibration.convert.qualisys]
binning_factor = 1 # Usually 1, except when filming in 540p where it usually is 2
[calibration.convert.optitrack] # See readme for instructions

View File

@ -67,7 +67,8 @@
# calibration_type = 'convert' # 'convert' or 'calculate'
# [calibration.convert]
# convert_from = 'qualisys' # 'qualisys', 'optitrack', vicon', 'opencap', 'easymocap', 'biocv', 'anipose', or 'freemocap'
# convert_from = 'caliscope' # 'caliscope', 'qualisys', 'optitrack', vicon', 'opencap', 'easymocap', 'biocv', 'anipose', or 'freemocap'
# [calibration.convert.caliscope] # No parameter needed
# [calibration.convert.qualisys]
# binning_factor = 1 # Usually 1, except when filming in 540p where it usually is 2
# [calibration.convert.optitrack] # See readme for instructions

View File

@ -67,7 +67,8 @@ keypoints_to_consider = 'all' # 'all' if all points should be considered, for ex
# calibration_type = 'convert' # 'convert' or 'calculate'
# [calibration.convert]
# convert_from = 'qualisys' # 'qualisys', 'optitrack', vicon', 'opencap', 'easymocap', 'biocv', 'anipose', or 'freemocap'
# convert_from = 'caliscope' # 'caliscope', 'qualisys', 'optitrack', vicon', 'opencap', 'easymocap', 'biocv', 'anipose', or 'freemocap'
# [calibration.convert.caliscope] # No parameter needed
# [calibration.convert.qualisys]
# binning_factor = 1 # Usually 1, except when filming in 540p where it usually is 2
# [calibration.convert.optitrack] # See readme for instructions

View File

@ -67,7 +67,8 @@ filter_order = 4
calibration_type = 'convert' # 'convert' or 'calculate'
[calibration.convert]
convert_from = 'qualisys' # 'qualisys', 'optitrack', vicon', 'opencap', 'easymocap', 'biocv', 'anipose', or 'freemocap'
convert_from = 'caliscope' # 'caliscope', 'qualisys', 'optitrack', vicon', 'opencap', 'easymocap', 'biocv', 'anipose', or 'freemocap'
[calibration.convert.caliscope] # No parameter needed
[calibration.convert.qualisys]
binning_factor = 1 # Usually 1, except when filming in 540p where it usually is 2
[calibration.convert.optitrack] # See readme for instructions

View File

@ -67,8 +67,8 @@ filter_order = 4
calibration_type = 'convert' # 'convert' or 'calculate'
[calibration.convert]
convert_from = 'qualisys' # 'qualisys', 'optitrack', vicon', 'opencap', 'easymocap', 'biocv', 'anipose', or 'freemocap'
[calibration.convert.qualisys]
convert_from = 'caliscope' # 'caliscope', 'qualisys', 'optitrack', vicon', 'opencap', 'easymocap', 'biocv', 'anipose', or 'freemocap'
[calibration.convert.caliscope] # No parameter needed
binning_factor = 1 # Usually 1, except when filming in 540p where it usually is 2
[calibration.convert.optitrack] # See readme for instructions
[calibration.convert.vicon] # No parameter needed

View File

@ -112,17 +112,19 @@ def retrieve_calib_params(calib_file):
calib = toml.load(calib_file)
cal_keys = [c for c in calib.keys()
if c not in ['metadata', 'capture_volume', 'charuco', 'checkerboard']
and isinstance(calib[c],dict)]
S, K, dist, optim_K, inv_K, R, R_mat, T = [], [], [], [], [], [], [], []
for c, cam in enumerate(calib.keys()):
if cam != 'metadata':
S.append(np.array(calib[cam]['size']))
K.append(np.array(calib[cam]['matrix']))
dist.append(np.array(calib[cam]['distortions']))
optim_K.append(cv2.getOptimalNewCameraMatrix(K[c], dist[c], [int(s) for s in S[c]], 1, [int(s) for s in S[c]])[0])
inv_K.append(np.linalg.inv(K[c]))
R.append(np.array(calib[cam]['rotation']))
R_mat.append(cv2.Rodrigues(R[c])[0])
T.append(np.array(calib[cam]['translation']))
for c, cam in enumerate(cal_keys):
S.append(np.array(calib[cam]['size']))
K.append(np.array(calib[cam]['matrix']))
dist.append(np.array(calib[cam]['distortions']))
optim_K.append(cv2.getOptimalNewCameraMatrix(K[c], dist[c], [int(s) for s in S[c]], 1, [int(s) for s in S[c]])[0])
inv_K.append(np.linalg.inv(K[c]))
R.append(np.array(calib[cam]['rotation']))
R_mat.append(cv2.Rodrigues(R[c])[0])
T.append(np.array(calib[cam]['translation']))
calib_params = {'S': S, 'K': K, 'dist': dist, 'inv_K': inv_K, 'optim_K': optim_K, 'R': R, 'R_mat': R_mat, 'T': T}
return calib_params
@ -142,22 +144,24 @@ def computeP(calib_file, undistort=False):
calib = toml.load(calib_file)
cal_keys = [c for c in calib.keys()
if c not in ['metadata', 'capture_volume', 'charuco', 'checkerboard']
and isinstance(calib[c],dict)]
P = []
for cam in list(calib.keys()):
if cam != 'metadata':
K = np.array(calib[cam]['matrix'])
if undistort:
S = np.array(calib[cam]['size'])
dist = np.array(calib[cam]['distortions'])
optim_K = cv2.getOptimalNewCameraMatrix(K, dist, [int(s) for s in S], 1, [int(s) for s in S])[0]
Kh = np.block([optim_K, np.zeros(3).reshape(3,1)])
else:
Kh = np.block([K, np.zeros(3).reshape(3,1)])
R, _ = cv2.Rodrigues(np.array(calib[cam]['rotation']))
T = np.array(calib[cam]['translation'])
H = np.block([[R,T.reshape(3,1)], [np.zeros(3), 1 ]])
P.append(Kh @ H)
for cam in list(cal_keys):
K = np.array(calib[cam]['matrix'])
if undistort:
S = np.array(calib[cam]['size'])
dist = np.array(calib[cam]['distortions'])
optim_K = cv2.getOptimalNewCameraMatrix(K, dist, [int(s) for s in S], 1, [int(s) for s in S])[0]
Kh = np.block([optim_K, np.zeros(3).reshape(3,1)])
else:
Kh = np.block([K, np.zeros(3).reshape(3,1)])
R, _ = cv2.Rodrigues(np.array(calib[cam]['rotation']))
T = np.array(calib[cam]['translation'])
H = np.block([[R,T.reshape(3,1)], [np.zeros(3), 1 ]])
P.append(Kh @ H)
return P

View File

@ -133,6 +133,7 @@ def sort_people_sports2d(keyptpre, keypt, scores):
frame_by_frame_dist = []
for comb in personsIDs_comb:
frame_by_frame_dist += [euclidean_distance(keyptpre[comb[0]],keypt[comb[1]])]
frame_by_frame_dist = np.mean(frame_by_frame_dist, axis=1)
# Sort correspondences by distance
_, _, associated_tuples = min_with_single_indices(frame_by_frame_dist, personsIDs_comb)

View File

@ -449,6 +449,9 @@ Output file:
### Convert from Qualisys, Optitrack, Vicon, OpenCap, EasyMocap, or bioCV
If you already have a calibration file, set `calibration_type` type to `convert` in your [Config.toml](https://github.com/perfanalytics/pose2sim/blob/main/Pose2Sim/Empty_project/User/Config.toml) file.
- **From [Caliscope](https://mprib.github.io/caliscope/):**
- Copy your Caliscope `.toml` calibration file to the Pose2Sim `Calibration` folder.
- Calibration can be skipped since Pose2Sim can natively read the Caliscope format.
- **From [Qualisys](https://www.qualisys.com):**
- Export calibration to `.qca.txt` within QTM.
- Copy it in the `Calibration` Pose2Sim folder.