Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Triangulation error with OpenCap data #142

Closed
sebastianhoefler opened this issue Oct 31, 2024 · 8 comments
Closed

Triangulation error with OpenCap data #142

sebastianhoefler opened this issue Oct 31, 2024 · 8 comments
Labels
help wanted Extra attention is needed

Comments

@sebastianhoefler
Copy link

Hi @davidpagnon,

First, I’d like to thank you for this repo—it's exactly what I need for my project and has been incredibly helpful so far.

Unfortunately, I’m having an issue with the Pose2Sim.triangulation() step.

To provide some context, I’m working on capturing sports motions (golf swings, baseball swings, etc.) using OpenCap with a two-camera setup (two iPhones). For each camera (cam0 and cam1), I have a cameraIntrinsicsExtrinsics.pickle calibration file and a corresponding video (golfswing_cam0_sync.mp4 and golfswing_cam1_sync.mp4). I want to run the pipeline up to and including Pose2Sim.kinematics().

I already want to apologize for the lengthy message; I wanted to be thorough in providing all relevant details.

To begin, I followed the Using your own data section and set up the following folder structure:

SingleTrial
├── calibration
│   ├── cam0.pickle
│   └── cam1.pickle
├── videos
│   ├── cam_00.mp4
│   └── cam_01.mp4
└── Config.toml

I changed the Config.toml file to handle opencap calibration data:

convert_from = 'opencap' # 'caliscope', 'qualisys', 'optitrack', vicon', 'opencap', 'easymocap', 'biocv', 'anipose', or 'freemocap'

Running Pose2Sim.calibration() completes and I get:

Converting ['cam0.pickle', 'cam1.pickle'] to .toml calibration file...

--> Residual (RMS) calibration errors for each camera are respectively [nan, nan] px, 
which corresponds to [nan, nan] mm.

Calibration file is stored at /opt/homebrew/Caskroom/miniconda/base/envs/Pose2Sim/lib/python3.9/site-packages/Pose2Sim/Klara_golf_pose2sim_test2/calibration/Calib_opencap.toml.

Calibration took 0.00 s.

I was a bit skeptical at first since the camera calibration errors seem to be [nan,nan] but I haven't been able to find the source of this error. However, since the Calib_opencap.toml seems to get created, I wasn't sure if this is even an issue. The Calib_opencap.toml looks like this:

[cam_00]
name = "cam_00"
size = [ 720.0, 1280.0]
matrix = [ [ 852.5413529017762, 0.0, 360.67955709952275], [ 0.0, 852.9104074665115, 637.3056748350809], [ 0.0, 0.0, 1.0]]
distortions = [ 0.22587520135789485, -0.675956617100016, -0.001064786565942824, 0.0003276313849505847]
rotation = [ 0.9588256575505364, -1.6244810340986826, 1.5818469803023707]
translation = [ 0.33226973904736823, 0.737306114764763, 3.0423107786068226]
fisheye = false

[cam_01]
name = "cam_01"
size = [ 720.0, 1280.0]
matrix = [ [ 852.5413529017762, 0.0, 360.67955709952275], [ 0.0, 852.9104074665115, 637.3056748350809], [ 0.0, 0.0, 1.0]]
distortions = [ 0.22587520135789485, -0.675956617100016, -0.001064786565942824, 0.0003276313849505847]
rotation = [ 1.048980604090349, 1.5532087370012593, -1.5313673410487025]
translation = [ -0.28656737799100124, 0.7353377563597358, 2.593157744240675]
fisheye = false

[metadata]
adjusted = false
error = 0.0

Next, I ran Pose2Sim.poseEstimation() which completes:

Estimating pose...
Found video files with extension mp4.
load /Users/sebh/.cache/rtmlib/hub/checkpoints/rtmpose-m_simcc-body7_pt-body7-halpe26_700e-256x192-4d3e73dd_20230605.onnx with openvino backend
Processing cam_01.mp4: 100%|██████████| 2369/2369 [05:55<00:00,  6.66it/s]
--> Output video saved to /opt/homebrew/Caskroom/miniconda/base/envs/Pose2Sim/lib/python3.9/site-packages/Pose2Sim/Klara_golf_pose2sim_test2/pose/cam_01_pose.mp4.
Processing cam_00.mp4: 100%|██████████| 2369/2369 [05:53<00:00,  6.70it/s]
--> Output video saved to /opt/homebrew/Caskroom/miniconda/base/envs/Pose2Sim/lib/python3.9/site-packages/Pose2Sim/Klara_golf_pose2sim_test2/pose/cam_00_pose.mp4.

Pose estimation took 00h11m50s.

Pose2Sim.synchronization() also works:

Synchronizing...
2024-10-31 15:35:38.758 python[88924:13409498] The class 'NSSavePanel' overrides the method identifier.  This method is implemented by class 'NSWindow'
--> Camera cam and cam: 3 frames offset, correlation 0.88.
Synchronized json files saved in /opt/homebrew/Caskroom/miniconda/base/envs/Pose2Sim/lib/python3.9/site-packages/Pose2Sim/Klara_golf_pose2sim_test2/pose-sync.

Synchronization took 00h00m14s.

reference_sync_klara_test2

Pose2Sim.personAssociation() also completes:

0%|          | 0/2368 [00:00<?, ?it/s]
/opt/homebrew/Caskroom/miniconda/base/envs/Pose2Sim/lib/python3.9/site-packages/numpy/core/fromnumeric.py:3504: RuntimeWarning: Mean of empty slice.
  return _methods._mean(a, axis=axis, dtype=dtype,
/opt/homebrew/Caskroom/miniconda/base/envs/Pose2Sim/lib/python3.9/site-packages/numpy/core/_methods.py:129: RuntimeWarning: invalid value encountered in scalar divide
  ret = ret.dtype.type(ret / rcount)
/opt/homebrew/Caskroom/miniconda/base/envs/Pose2Sim/lib/python3.9/site-packages/Pose2Sim/personAssociation.py:220: RuntimeWarning: All-NaN axis encountered
  error_min = np.nanmin(error_comb_all)
/opt/homebrew/Caskroom/miniconda/base/envs/Pose2Sim/lib/python3.9/site-packages/Pose2Sim/personAssociation.py:728: RuntimeWarning: Mean of empty slice
  error_min_tot.append(np.nanmean(error_proposals))
100%|██████████| 2368/2368 [00:08<00:00, 294.47it/s]

Single-person analysis selected.
/opt/homebrew/Caskroom/miniconda/base/envs/Pose2Sim/lib/python3.9/site-packages/Pose2Sim/personAssociation.py:588: RuntimeWarning: Mean of empty slice
  mean_error_px = np.around(np.nanmean(error), decimals=1)

--> Mean reprojection error for Neck point on all frames is nan px, which roughly corresponds to nan mm. 
--> In average, 1.0 cameras had to be excluded to reach the demanded 20 px error threshold after excluding points with likelihood below 0.3.

Tracked json files are stored in /opt/homebrew/Caskroom/miniconda/base/envs/Pose2Sim/lib/python3.9/site-packages/Pose2Sim/Klara_golf_pose2sim_test2/pose-associated.

Associating persons took 00h00m08s.

Since I am also receiving nan here for reprojection error, I tried loweringreproj_error_threshold_association to 10 in Config.toml which outputs:

Single-person analysis selected.
--> Mean reprojection error for Neck: 166.6 px (~615.2 mm).
--> Avg. 0.0 cameras excluded to meet 10 px error threshold.

Tracked JSON files saved to:
.../Klara_golf_pose2sim_test2/pose-associated.

Associating persons took 00h00m07s.

However, I am getting an error when trying to run Pose2Sim.triangulation():

---------------------------------------------------------------------
Triangulation of 2D points for Klara_golf_pose2sim_test2, for all frames.
On Thursday 31. October 2024, 16:26:37
Project directory: /opt/homebrew/Caskroom/miniconda/base/envs/Pose2Sim/lib/python3.9/site-packages/Pose2Sim/Klara_golf_pose2sim_test2
---------------------------------------------------------------------

100%|██████████| 2365/2365 [00:11<00:00, 210.77it/s]
{
    "name": "Exception",
    "message": "No persons have been triangulated. Please check your calibration and your synchronization, or the triangulation parameters in Config.toml.",
    "stack": "---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
Cell In[24], line 1
----> 1 Pose2Sim.triangulation()

File /opt/homebrew/Caskroom/miniconda/base/envs/Pose2Sim/lib/python3.9/site-packages/Pose2Sim/Pose2Sim.py:375, in triangulation(config)
    372 logging.info(f\"Project directory: {project_dir}\")
    373 logging.info(\"---------------------------------------------------------------------\")
--> 375 triangulate_all(config_dict)
    377 end = time.time()
    378 elapsed = end-start

File /opt/homebrew/Caskroom/miniconda/base/envs/Pose2Sim/lib/python3.9/site-packages/Pose2Sim/triangulation.py:900, in triangulate_all(config_dict)
    897 nb_persons_to_detect = len(Q_tot)
    899 if nb_persons_to_detect == 0:
--> 900     raise Exception('No persons have been triangulated. Please check your calibration and your synchronization, or the triangulation parameters in Config.toml.')
    902 id_excluded_cams_tot = [np.hstack(np.hstack(np.array(id_excluded_cams_tot[n]))) for n in range(nb_persons_to_detect)]

Exception: No persons have been triangulated. Please check your calibration and your synchronization, or the triangulation parameters in Config.toml."
}

Maybe I am missing something. I would really appreciate your help. Thank you very much!

@davidpagnon
Copy link
Collaborator

davidpagnon commented Nov 3, 2024

Hi @sebastianhoefler,
Apologies for the delay, I was away for a week.

Thank you for pointing out the NaNs in the logs, you are right it was not clear and I updated the documentation: "If the original calibration file does not provide any residual errors, they will be logged as NaN. This is not an error and can be ignored."

2 cameras are the very minimum for any triangulation to be mathematically possible. But I do not think it is your problem, as we've been able to run challenging pose estimation with several people using only 2 cameras

From what you are saying, I am pretty sure that the issue starts with calibration. I guess your iPhones are in portrait mode. when you run pose estimation, are the videos upright or sideways? If they are sideways, it means that the pose estimation algorithm does not detect the rotation metainformation of the video. In that case, first of all pose estimation results are not great, and then the triangulation stage will not be good since triangulation will not be coherent with calibration.

Two things:

@sebastianhoefler
Copy link
Author

sebastianhoefler commented Nov 3, 2024

Hi @davidpagnon,

thank you very much for getting back to me. Unfortunately, due to privacy concerns (this is a pre-trial and I don't have permission from the test subject), I cannot share the .mp4 video files. I am guessing you would need those in the project folder. I am allowed to share some "anonymized" images of one frame of the camera view if that helps picture the camera perspectives.

perspective1 perspective2

When recording, the cameras (iPhone 13) were upright and not sideways. Data capture was done via opencapai.

I tinkered a bit with the Config.toml file and found that setting the following values for reproj_error_threshold_triangulation = 140 makes Pose2Sim.triangulation() pass (I attached a sample from the output).

Click to expand log details

INFO:root:

INFO:root:Triangulation of 2D points for Klara_golf_pose2sim_test3, for all frames.
INFO:root:On Sunday 03. November 2024, 20:24:31
INFO:root:Project directory: /opt/homebrew/Caskroom/miniconda/base/envs/Pose2Sim/lib/python3.9/site-packages/Pose2Sim/Klara_golf_pose2sim_test3
INFO:root:---------------------------------------------------------------------

100%|██████████| 2365/2365 [00:11<00:00, 214.18it/s]
/opt/homebrew/Caskroom/miniconda/base/envs/Pose2Sim/lib/python3.9/site-packages/c3d/c3d.py:2457: RuntimeWarning: invalid value encountered in cast
raw[valid, :3] = points[valid, :3] / point_scale
INFO:root:
INFO:root:Mean reprojection error for Hip is 138.3 px (~ 0.511 m), reached with 0.0 excluded cameras.
INFO:root: Frames 0 to 0, 33 to 33, 35 to 42, 45 to 45, 236 to 236, 239 to 243, 245 to 245, 247 to 247, 252 to 255, 259 to 259, 294 to 295, 389 to 391, 1265 to 1269, 1284 to 1288, 1393 to 1394, 1398 to 1398, 1401 to 1402, 1410 to 1411, 1414 to 1414, 1419 to 1420, 1425 to 1427, 1950 to 1950, 1952 to 1952, 1972 to 1972, 2035 to 2035, 2037 to 2037, 2039 to 2041, 2047 to 2048, 2056 to 2056 were interpolated.
INFO:root: Frames 47 to 233, 273 to 284, 297 to 387, 400 to 1203, 1205 to 1263, 1271 to 1282, 1290 to 1301, 1332 to 1389, 1429 to 1802, 1816 to 1948, 1974 to 2028, 2062 to 2364 were not interpolated.
INFO:root:Mean reprojection error for RHip is nan px (~ nan m), reached with 0.0 excluded cameras.
INFO:root: Frames 0 to 2364 were not interpolated.
INFO:root:Mean reprojection error for RKnee is 139.1 px (~ 0.514 m), reached with 0.0 excluded cameras.
INFO:root: Frames 2036 to 2036, 2043 to 2043, 2055 to 2055, 2058 to 2059, 2077 to 2079, 2082 to 2083, 2085 to 2087, 2092 to 2095, 2097 to 2101 were interpolated.
INFO:root: Frames 0 to 2015, 2017 to 2028, 2061 to 2074, 2106 to 2364 were not interpolated.
INFO:root:Mean reprojection error for RAnkle is 135.9 px (~ 0.502 m), reached with 0.0 excluded cameras.
INFO:root: Frames 0 to 0, 263 to 263, 419 to 420, 422 to 422, 424 to 424, 426 to 432, 458 to 458, 467 to 467, 469 to 471, 473 to 475, 508 to 511, 515 to 518, 520 to 524, 1169 to 1169, 1339 to 1339, 1380 to 1382, 1384 to 1388, 1413 to 1415, 1419 to 1419, 1425 to 1427, 1451 to 1451, 1453 to 1453, 1455 to 1455, 1509 to 1510, 1807 to 1807, 2013 to 2015, 2106 to 2106, 2120 to 2120 were interpolated.
INFO:root: Frames 477 to 506, 529 to 563, 1354 to 1378, 1429 to 1446, 1459 to 1507, 1988 to 2011, 2017 to 2030, 2032 to 2072, 2086 to 2103 were not interpolated.
INFO:root:Mean reprojection error for RBigToe is 135.2 px (~ 0.499 m), reached with 0.0 excluded cameras.
INFO:root: Frames 0 to 0, 88 to 89, 104 to 104, 108 to 108, 123 to 127, 133 to 133, 135 to 137, 139 to 139, 141 to 142, 144 to 151, 153 to 160, 162 to 162, 165 to 169, 186 to 188, 191 to 191, 194 to 194, 210 to 210, 214 to 214, 216 to 216, 219 to 222, 224 to 228, 230 to 231, 236 to 236, 572 to 572, 596 to 601, 604 to 604, 606 to 607, 613 to 613, 615 to 616, 619 to 619, 622 to 623, 625 to 625, 627 to 630, 633 to 633, 638 to 638, 640 to 643, 645 to 645, 648 to 651, 653 to 653, 655 to 655, 657 to 657, 675 to 675, 680 to 680, 684 to 684, 688 to 688, 691 to 692, 694 to 697, 699 to 700, 705 to 707, 709 to 711, 714 to 716, 718 to 719, 722 to 722, 739 to 739, 741 to 745, 747 to 749, 752 to 756, 758 to 759, 776 to 778, 782 to 783, 785 to 785, 810 to 811, 977 to 978, 980 to 980, 983 to 984, 987 to 987, 989 to 989, 993 to 993, 995 to 998, 1040 to 1042, 1044 to 1044, 1048 to 1048, 1050 to 1050, 1052 to 1055, 1058 to 1059, 1062 to 1062, 1064 to 1066, 1068 to 1077, 1083 to 1085, 1087 to 1088, 1090 to 1090, 1093 to 1098, 1527 to 1527, 1534 to 1536, 1539 to 1545, 1548 to 1548, 1550 to 1553, 1555 to 1555, 1557 to 1557, 1560 to 1560, 1564 to 1564, 1581 to 1581, 1583 to 1584, 1588 to 1588, 1595 to 1600, 1602 to 1603, 1605 to 1609, 1611 to 1613, 1615 to 1617, 1619 to 1619, 1622 to 1622, 1624 to 1624, 1626 to 1626, 1628 to 1632, 1635 to 1635, 1638 to 1639, 1641 to 1641, 1644 to 1645, 1647 to 1648, 1650 to 1652, 1655 to 1655, 1678 to 1678, 1680 to 1682, 1688 to 1688, 1690 to 1690, 2153 to 2153, 2175 to 2179, 2189 to 2189, 2193 to 2195, 2197 to 2199, 2203 to 2203, 2212 to 2212, 2222 to 2223, 2305 to 2307, 2309 to 2310, 2313 to 2320, 2323 to 2324, 2326 to 2327, 2329 to 2329, 2336 to 2336, 2338 to 2342, 2346 to 2346, 2349 to 2349, 2353 to 2354, 2358 to 2359, 2361 to 2361, 2363 to 2363 were interpolated.
INFO:root: Frames 75 to 86, 91 to 102, 110 to 121, 174 to 184, 239 to 404, 725 to 737, 763 to 774, 787 to 808, 813 to 891, 893 to 973, 1000 to 1022, 1024 to 1038, 1101 to 1120, 1122 to 1341, 1657 to 1676, 1693 to 1714, 1716 to 1749, 1751 to 1972, 2161 to 2173 were not interpolated.
INFO:root:Mean reprojection error for RSmallToe is 138.2 px (~ 0.51 m), reached with 0.0 excluded cameras.
INFO:root: Frames 0 to 0, 41 to 42, 55 to 60, 410 to 410, 412 to 415, 419 to 419, 423 to 429, 433 to 433, 435 to 437, 441 to 441, 443 to 444, 460 to 460, 462 to 464, 510 to 510, 512 to 514, 518 to 518, 560 to 561, 1345 to 1346, 1349 to 1352, 1354 to 1357, 1376 to 1376, 1390 to 1392, 1394 to 1394, 1396 to 1399, 1401 to 1408, 1411 to 1412, 1414 to 1414, 1425 to 1428, 1430 to 1439, 1442 to 1446, 1981 to 1982, 1985 to 1985, 1992 to 1992, 1995 to 1995, 1998 to 2001, 2003 to 2004, 2008 to 2008, 2010 to 2010, 2012 to 2015, 2020 to 2022, 2024 to 2028, 2030 to 2030, 2033 to 2033, 2036 to 2044, 2046 to 2046, 2048 to 2048, 2050 to 2050, 2052 to 2052, 2055 to 2055, 2059 to 2059, 2061 to 2061, 2063 to 2063, 2066 to 2066, 2069 to 2069, 2074 to 2074, 2106 to 2106, 2108 to 2109, 2112 to 2112, 2114 to 2114, 2116 to 2117 were interpolated.
INFO:root: Frames 62 to 408, 446 to 458, 467 to 508, 520 to 558, 563 to 1343, 1360 to 1374, 1378 to 1388, 1452 to 1978, 2076 to 2103, 2119 to 2364 were not interpolated.
INFO:root:Mean reprojection error for RHeel is 127.8 px (~ 0.472 m), reached with 0.0 excluded cameras.
INFO:root: Frames 0 to 0, 1168 to 1170, 1807 to 1807 were interpolated.
INFO:root:Mean reprojection error for LHip is 136.5 px (~ 0.504 m), reached with 0.0 excluded cameras.
INFO:root: Frames 0 to 0, 39 to 39, 53 to 53, 56 to 57, 60 to 60, 69 to 69, 71 to 78, 124 to 124, 126 to 127, 129 to 131, 149 to 149, 151 to 151, 154 to 154, 157 to 157, 168 to 169, 171 to 174, 181 to 183, 185 to 185, 189 to 189, 192 to 193, 196 to 196, 265 to 266, 420 to 420, 440 to 440, 598 to 598, 600 to 600, 605 to 605, 753 to 753, 784 to 786, 788 to 788, 791 to 791, 794 to 796, 800 to 808, 810 to 810, 812 to 818, 821 to 822, 824 to 828, 830 to 833, 835 to 837, 839 to 840, 842 to 844, 846 to 846, 848 to 850, 853 to 856, 860 to 860, 862 to 862, 867 to 867, 869 to 869, 872 to 872, 876 to 884, 886 to 890, 1183 to 1190, 1192 to 1192, 1344 to 1344, 1378 to 1378, 1385 to 1385, 1560 to 1560, 1566 to 1566, 1825 to 1828, 1830 to 1830, 1845 to 1845, 1847 to 1847, 1855 to 1856, 1863 to 1863, 1867 to 1867, 1991 to 1995, 1998 to 2007, 2013 to 2015, 2176 to 2176, 2182 to 2182, 2184 to 2186 were interpolated.
INFO:root: Frames 104 to 122, 202 to 249, 251 to 261, 423 to 434, 607 to 728, 730 to 751, 755 to 780, 892 to 1181, 1359 to 1373, 1568 to 1685, 1687 to 1821, 2188 to 2364 were not interpolated.
INFO:root:Mean reprojection error for LKnee is 116.1 px (~ 0.429 m), reached with 0.0 excluded cameras.
INFO:root: Frames 0 to 0 were interpolated.
INFO:root:Mean reprojection error for LAnkle is 78.1 px (~ 0.288 m), reached with 0.0 excluded cameras.
INFO:root: Frames 0 to 0 were interpolated.
INFO:root:Mean reprojection error for LBigToe is 73.3 px (~ 0.271 m), reached with 0.0 excluded cameras.
INFO:root: Frames 0 to 0 were interpolated.
INFO:root:Mean reprojection error for LSmallToe is 66.2 px (~ 0.244 m), reached with 0.0 excluded cameras.
INFO:root: Frames 0 to 0 were interpolated.
INFO:root:Mean reprojection error for LHeel is 73.7 px (~ 0.272 m), reached with 0.0 excluded cameras.
INFO:root: Frames 0 to 0 were interpolated.
INFO:root:Mean reprojection error for Neck is 137.3 px (~ 0.507 m), reached with 0.0 excluded cameras.
INFO:root: Frames 459 to 459, 463 to 463, 1420 to 1420, 1423 to 1426, 1433 to 1433 were interpolated.
INFO:root: Frames 0 to 456, 525 to 1411, 1446 to 2364 were not interpolated.
INFO:root:Mean reprojection error for Head is 137.8 px (~ 0.509 m), reached with 0.0 excluded cameras.
INFO:root: Frames 1402 to 1403, 1433 to 1433 were interpolated.
INFO:root: Frames 0 to 455, 517 to 1399, 1436 to 2028, 2030 to 2364 were not interpolated.
INFO:root:Mean reprojection error for Nose is 137.3 px (~ 0.507 m), reached with 0.0 excluded cameras.
INFO:root: Frames 454 to 454, 456 to 456, 511 to 511, 534 to 534, 1386 to 1386, 1451 to 1454, 1458 to 1458, 1462 to 1463, 1466 to 1466, 2011 to 2011, 2074 to 2077, 2099 to 2100, 2104 to 2105 were interpolated.
INFO:root: Frames 0 to 452, 538 to 1383, 1388 to 1399, 1468 to 2009, 2086 to 2097, 2109 to 2364 were not interpolated.
INFO:root:Mean reprojection error for RShoulder is nan px (~ nan m), reached with 0.0 excluded cameras.
INFO:root: Frames 0 to 2364 were not interpolated.
INFO:root:Mean reprojection error for RElbow is 129.2 px (~ 0.477 m), reached with 0.0 excluded cameras.
INFO:root: Frames 349 to 350, 353 to 353, 356 to 357, 359 to 359, 1158 to 1158, 1242 to 1242, 1308 to 1317 were interpolated.
INFO:root: Frames 0 to 316, 361 to 425, 541 to 1156, 1163 to 1238, 1319 to 1334, 1336 to 1362, 1473 to 1805, 1813 to 1870, 1937 to 1995, 2091 to 2364 were not interpolated.
INFO:root:Mean reprojection error for RWrist is 124.7 px (~ 0.46 m), reached with 0.07 excluded cameras.
INFO:root: Frames 566 to 566, 569 to 569, 1155 to 1156, 1225 to 1230, 1232 to 1232, 1235 to 1236, 1243 to 1243, 1269 to 1270, 1275 to 1276, 1278 to 1278, 1314 to 1314, 1504 to 1504, 1506 to 1507, 1899 to 1899, 1904 to 1904, 1906 to 1912, 1914 to 1914, 1917 to 1917 were interpolated.
INFO:root: Frames 0 to 342, 346 to 412, 571 to 1153, 1158 to 1222, 1245 to 1267, 1280 to 1305, 1317 to 1346, 1509 to 1866, 1936 to 1982, 2117 to 2364 were not interpolated.
INFO:root:Mean reprojection error for LShoulder is 133.2 px (~ 0.492 m), reached with 0.0 excluded cameras.
INFO:root: Frames 535 to 535, 537 to 537, 1382 to 1383, 2008 to 2008 were interpolated.
INFO:root: Frames 0 to 438, 539 to 1380, 1468 to 2006, 2089 to 2364 were not interpolated.
INFO:root:Mean reprojection error for LElbow is 135.8 px (~ 0.501 m), reached with 0.0 excluded cameras.
INFO:root: Frames 0 to 6, 8 to 8, 10 to 11, 13 to 15, 127 to 127, 412 to 414, 600 to 600, 616 to 616, 619 to 619, 622 to 623, 625 to 627, 632 to 632, 996 to 996, 998 to 998, 1005 to 1005, 1008 to 1008, 1061 to 1061, 1076 to 1076, 1347 to 1352, 1401 to 1401, 1702 to 1705, 1707 to 1714, 1982 to 1984, 1999 to 1999, 2014 to 2014, 2017 to 2019, 2021 to 2021 were interpolated.
INFO:root: Frames 17 to 74, 76 to 125, 214 to 402, 566 to 598, 1086 to 1340, 1366 to 1399, 1495 to 1529, 1716 to 1749, 1753 to 1970, 2002 to 2012, 2127 to 2145 were not interpolated.
INFO:root:Mean reprojection error for LWrist is 123.3 px (~ 0.455 m), reached with 0.0 excluded cameras.
INFO:root: Frames 1383 to 1383 were interpolated.
INFO:root: Frames 0 to 415, 566 to 1352, 1492 to 1984, 2116 to 2364 were not interpolated.
INFO:root:
--> Mean reprojection error for all points on all frames is 104.6 px, which roughly corresponds to 386.2 mm.
INFO:root:Cameras were excluded if likelihood was below 0.3 and if the reprojection error was above 140 px.
INFO:root:Gaps were interpolated with linear method if smaller than 10 frames. Larger gaps were filled with the last valid value.
INFO:root:In average, 0.0 cameras had to be excluded to reach these thresholds.
INFO:root:Camera cam_01 was excluded 0% of the time, and Camera cam_00: 0%.
INFO:root:
3D coordinates are stored at /opt/homebrew/Caskroom/miniconda/base/envs/Pose2Sim/lib/python3.9/site-packages/Pose2Sim/Klara_golf_pose2sim_test3/pose-3d/Klara_golf_pose2sim_test3_0-2365.trc.
INFO:root:

INFO:root:All trc files have been converted to c3d.
INFO:root:Limb swapping was not handled.
INFO:root:Lens distortions were not taken into account.
INFO:root:
Triangulation took 00h00m11s.

As you can see, the reprojection errors are very high and the consqequent steps don't yield any meaningful results and we get many nan in the .trc file.

This, in addition with the high mean reprojection error I mentioned above:

Single-person analysis selected.
--> Mean reprojection error for Neck: 166.6 px (~615.2 mm).
--> Avg. 0.0 cameras excluded to meet 10 px error threshold.

Tracked JSON files saved to:
.../Klara_golf_pose2sim_test2/pose-associated.

Associating persons took 00h00m07s.

makes me think that there might be some issue with calibration or with how the data was collected in the first place since reprojection errors this high are quite unusual. So either:

  1. There is some underlying issue with calibration. I can share the .pickle-files and opecnapai calibration images with you if that would help.
  2. The camera angles (camera setup) are not working well with the Pose2Sim.triangulation() step.
  3. We need to include a 3rd camera to make keypoint detection more robust
  4. Some issue in the code/pipeline (or how I am using the code) that is leading to high reprojection errors.

Would be interesting to hear your thoughts on the setup. Thank you again for your help!

@davidpagnon
Copy link
Collaborator

Hi again,

Is there any way you could record yourself doing anything, even if it is just raising your hand, so that I can check the project?
In any case, over 60 cm of triangulation error is definitely not normal. It would save me time if I could have a full project folder, so that I can check everything in one go.

I expect your first assumption is the correct one. You can also install the Pose2Sim_Blender extension to see if your cameras and videos look like they are in the right position. Quick install is enough since you don't need to visualize OpenSim skeletons yet.

N.B.: Just to let you know, you don't need to run personAssociation if you have only one person in the field of view.

@sebastianhoefler
Copy link
Author

Hi David,

I’ve received permission from one of the participants of the pre-trial to send the video data to you at contact@david-pagnon.com.

Since this is a different participant, the reprojection errors are also somewhat different. However, I’m still encountering similar issues. For Pose2Sim.triangulation() to pass, I need to set the reproj_error_threshold_triangulation to a very high value of 55. Although the reprojection errors are not as high as before, they still reach about 20 cm for some markers. I believe this may be preventing Pose2Sim.kinematics() from running properly.

@davidpagnon
Copy link
Collaborator

Hi, thank you for your data. It will remain confidential of course.

The first thing that strikes me is that your video format is 360x640, while the calibration file is 720x1280. This is also the case in your original pickle files. Did you do anything to your videos, or set something up that could explain it in the OpenCap GUI?

@davidpagnon
Copy link
Collaborator

So I just checked, if you divide all the "matrix" values by 2 in your calibration file, it works fine. Now we need to figure out why the video resolution is divided by two. Please tell me if you figure out why!

(in any case, unlike what I first thought, the portrait mode had nothing to do with your issue and it is correctly detected)

@sebastianhoefler
Copy link
Author

Thank you! Great find! I didn't even realize it was scaled down by half. I don't think I am doing anything "wrong" in the opencap GUI. I simply download the data from the interface:

opencap_data_download

The downloaded folder looks like this:


OpenCapData
├── CalibrationImages
├── MarkerData
├── OpenSimData
├── README.txt
├── sessionMetadata.yaml
├── Videos
│   ├── Cam0
│   │   ├── cameraIntrinsicsExtrinsics.pickle
│   │   ├── InputMedia
│   │   │   ├── trial_01
│   │   │   │   ├── video_sync.mp4
│   │   │   │   └── video.mov
│   │   │   └── neutral
│   │   └── OutputPkI
│   ├── Cam1
│   │   ├── cameraIntrinsicsExtrinsics.pickle
│   │   ├── InputMedia
│   │   │   ├── trial_01
│   │   │   │   ├── video_sync.mp4
│   │   │   │   └── video.mov
│   │   │   └── neutral
│   │   └── OutputPkI
│   └── mappingCamDevice.pickle

From the README.txt file:

- Videos
    -> This folder contains raw and processed video data.
        -> There are as many subfolders as there are cameras used for data collection; the subfolders are named Cam<i> where i is the index of the camera.
    - Cam<i>:
        - InputMedia
            -> This folder contains one subfolder per trial; the subfolders are named as per trial name.
            - <trial name>
                -> <trial name>.mov is the raw recorded video.
                -> <trial name>_sync.mp4 is the processed video synced across cameras.

The .mov file is 720x1280 while the synced version is 360x640. This could be a bug.

I converted the .mov files myself now and re-ran the pipeline. Everything works perfectly and Pose2Sim.kinematics() is currently running. I am running on CPU at them moment so it is taking a while (currently at around 9 minutes). I will close the issue if (or as soon as) it completes. Thank you very much for your help!

@davidpagnon
Copy link
Collaborator

davidpagnon commented Nov 4, 2024

Happy to learn it is solved!
My guess is that OpenCap is providing synchronized videos but they are not meant to be used for analysis, so they compress it as much as possible.

@davidpagnon davidpagnon changed the title Pose2Sim.triangulation() Error: No persons have been triangulated Triangulation error with OpenCap data Nov 4, 2024
@davidpagnon davidpagnon added the help wanted Extra attention is needed label Nov 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants