(
xy_pred,
xy_true,
sigma,
margin=0,
symmetric_kpts=None,
)
| 903 | |
| 904 | |
| 905 | def calc_object_keypoint_similarity( |
| 906 | xy_pred, |
| 907 | xy_true, |
| 908 | sigma, |
| 909 | margin=0, |
| 910 | symmetric_kpts=None, |
| 911 | ): |
| 912 | visible_gt = ~np.isnan(xy_true).all(axis=1) |
| 913 | if visible_gt.sum() < 2: # At least 2 points needed to calculate scale |
| 914 | return np.nan |
| 915 | |
| 916 | true = xy_true[visible_gt] |
| 917 | scale_squared = np.prod(np.ptp(true, axis=0) + np.spacing(1) + margin * 2) |
| 918 | if np.isclose(scale_squared, 0): |
| 919 | return np.nan |
| 920 | |
| 921 | k_squared = (2 * sigma) ** 2 |
| 922 | denom = 2 * scale_squared * k_squared |
| 923 | if isinstance(sigma, np.ndarray): |
| 924 | denom = denom[visible_gt] |
| 925 | |
| 926 | if symmetric_kpts is None: |
| 927 | pred = xy_pred[visible_gt] |
| 928 | pred[np.isnan(pred)] = np.inf |
| 929 | dist_squared = np.sum((pred - true) ** 2, axis=1) |
| 930 | oks = np.exp(-dist_squared / denom) |
| 931 | return np.mean(oks) |
| 932 | else: |
| 933 | oks = [] |
| 934 | xy_preds = [xy_pred] |
| 935 | combos = (pair for l in range(len(symmetric_kpts)) for pair in itertools.combinations(symmetric_kpts, l + 1)) |
| 936 | for pairs in combos: |
| 937 | # Swap corresponding keypoints |
| 938 | tmp = xy_pred.copy() |
| 939 | for pair in pairs: |
| 940 | tmp[pair, :] = tmp[pair[::-1], :] |
| 941 | xy_preds.append(tmp) |
| 942 | for xy_pred in xy_preds: |
| 943 | pred = xy_pred[visible_gt] |
| 944 | pred[np.isnan(pred)] = np.inf |
| 945 | dist_squared = np.sum((pred - true) ** 2, axis=1) |
| 946 | oks.append(np.mean(np.exp(-dist_squared / denom))) |
| 947 | return max(oks) |
| 948 | |
| 949 | |
| 950 | def match_assemblies( |
no outgoing calls
no test coverage detected