diff --git a/Pose2Sim/common.py b/Pose2Sim/common.py index ebf0da8c..8e25c20e 100644 --- a/Pose2Sim/common.py +++ b/Pose2Sim/common.py @@ -251,7 +251,7 @@ def bounding_boxes(js_file, margin_percent=0.1, around='extremities'): return bounding_boxes -def retrieve_calib_params(calib_file): +def retrieve_calib_params(calib_file, json_pose_dirs_names=None): ''' Compute projection matrices from toml calibration file. @@ -273,22 +273,35 @@ def retrieve_calib_params(calib_file): cal_keys = [c for c in calib.keys() if c not in ['metadata', 'capture_volume', 'charuco', 'checkerboard'] and isinstance(calib[c],dict)] + + if json_pose_dirs_names is None: + pose_keys = cal_keys + else: + pose_keys = [name.replace('_json', '') for name in json_pose_dirs_names] + missing_cams = [cam for cam in pose_keys if cam not in cal_keys] + if missing_cams: + logging.error(f"The following cameras are present in the pose folders but missing in the calibration file: {missing_cams}.") + raise ValueError(f"The following cameras are present in the pose folders but missing in the calibration file: {missing_cams}.") + + S, K, dist, optim_K, inv_K, R, R_mat, T = [], [], [], [], [], [], [], [] - for c, cam in enumerate(cal_keys): + for cam in list(cal_keys): + if cam not in pose_keys: + continue 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])) + optim_K.append(cv2.getOptimalNewCameraMatrix(K[-1], dist[-1], [int(s) for s in S[-1]], 1, [int(s) for s in S[-1]])[0]) + inv_K.append(np.linalg.inv(K[-1])) R.append(np.array(calib[cam]['rotation'])) - R_mat.append(cv2.Rodrigues(R[c])[0]) + R_mat.append(cv2.Rodrigues(R[-1])[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 -def computeP(calib_file, undistort=False): +def computeP(calib_file, json_pose_dirs_names=None, undistort=False): ''' Compute projection matrices from toml calibration file. @@ -305,8 +318,20 @@ def computeP(calib_file, undistort=False): cal_keys = [c for c in calib.keys() if c not in ['metadata', 'capture_volume', 'charuco', 'checkerboard'] and isinstance(calib[c],dict)] + + if json_pose_dirs_names is None: + pose_keys = cal_keys + else: + pose_keys = [name.replace('_json', '') for name in json_pose_dirs_names] + missing_cams = [cam for cam in pose_keys if cam not in cal_keys] + if missing_cams: + logging.error(f"The following cameras are present in the pose folders but missing in the calibration file: {missing_cams}.") + raise ValueError(f"The following cameras are present in the pose folders but missing in the calibration file: {missing_cams}.") + P = [] for cam in list(cal_keys): + if cam not in pose_keys: + continue K = np.array(calib[cam]['matrix']) if undistort: S = np.array(calib[cam]['size']) diff --git a/Pose2Sim/personAssociation.py b/Pose2Sim/personAssociation.py index 6bc4f0f4..1f45f692 100644 --- a/Pose2Sim/personAssociation.py +++ b/Pose2Sim/personAssociation.py @@ -659,10 +659,6 @@ def associate_all(config_dict): pose_dir = os.path.join(project_dir, 'pose') poseSync_dir = os.path.join(project_dir, 'pose-sync') poseTracked_dir = os.path.join(project_dir, 'pose-associated') - - # projection matrix from toml calibration file - P_all = computeP(calib_file, undistort=undistort_points) - calib_params = retrieve_calib_params(calib_file) # selection of tracked keypoint id try: # from skeletons.py @@ -709,11 +705,9 @@ def associate_all(config_dict): f_range = [[0,max([len(j) for j in json_files_names])] if frame_range in ('all', 'auto', []) else frame_range][0] n_cams = len(json_dirs_names) - # Check that camera number is consistent between calibration file and pose folders - if n_cams != len(P_all): - raise Exception(f'Error: The number of cameras is not consistent:\ - Found {len(P_all)} cameras in the calibration file,\ - and {n_cams} cameras based on the number of pose folders.') + # projection matrix from toml calibration file + P = computeP(calib_file, json_dirs_names, undistort=undistort_points) + calib_params = retrieve_calib_params(calib_file, json_dirs_names) if not multi_person: logging.info('\nSingle-person analysis selected.') @@ -744,12 +738,12 @@ def associate_all(config_dict): personsIDs_comb = persons_combinations(json_files_f) # choose persons of interest and exclude cameras with bad pose estimation - error_proposals, proposals, Q_kpt = best_persons_and_cameras_combination(config_dict, json_files_f, personsIDs_comb, P_all, tracked_keypoint_id, calib_params) + error_proposals, proposals, Q_kpt = best_persons_and_cameras_combination(config_dict, json_files_f, personsIDs_comb, P, tracked_keypoint_id, calib_params) if not np.isinf(error_proposals): error_min_tot.append(np.nanmean(error_proposals)) cameras_off_count = np.count_nonzero([np.isnan(comb) for comb in proposals]) / len(proposals) - cameras_off_tot.append(cameras_off_count) + cameras_off_tot.append(cameras_off_count) else: # read data diff --git a/Pose2Sim/triangulation.py b/Pose2Sim/triangulation.py index 94b7b3d6..0738cd63 100644 --- a/Pose2Sim/triangulation.py +++ b/Pose2Sim/triangulation.py @@ -698,7 +698,7 @@ def triangulate_all(config_dict): try: calib_dir = [os.path.join(session_dir, c) for c in os.listdir(session_dir) if os.path.isdir(os.path.join(session_dir, c)) and 'calib' in c.lower()][0] except: - raise Exception(f'No .toml calibration direcctory found.') + raise Exception(f'No .toml calibration directory found.') try: calib_files = glob.glob(os.path.join(calib_dir, '*.toml')) calib_file = max(calib_files, key=os.path.getctime) # lastly created calibration file @@ -707,10 +707,6 @@ def triangulate_all(config_dict): pose_dir = os.path.join(project_dir, 'pose') poseSync_dir = os.path.join(project_dir, 'pose-sync') poseTracked_dir = os.path.join(project_dir, 'pose-associated') - - # Projection matrix from toml calibration file - P = computeP(calib_file, undistort=undistort_points) - calib_params = retrieve_calib_params(calib_file) # Retrieve keypoints from model try: # from skeletons.py @@ -774,10 +770,10 @@ def triangulate_all(config_dict): # frame range selection f_range = [[0,min([len(j) for j in json_files_names])] if frame_range in ('all', 'auto', []) else frame_range][0] frame_nb = f_range[1] - f_range[0] - - # Check that camera number is consistent between calibration file and pose folders - if n_cams != len(P): - raise Exception(f'Error: The number of cameras is not consistent: Found {len(P)} cameras in the calibration file, and {n_cams} cameras based on the number of pose folders.') + + # Projection matrix from toml calibration file + P = computeP(calib_file, json_dirs_names, undistort=undistort_points) + calib_params = retrieve_calib_params(calib_file, json_dirs_names) # Triangulation if multi_person: