humancalib 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. humancalib-0.3.1/LICENSE +22 -0
  2. humancalib-0.3.1/PKG-INFO +322 -0
  3. humancalib-0.3.1/README.md +269 -0
  4. humancalib-0.3.1/pyproject.toml +119 -0
  5. humancalib-0.3.1/setup.cfg +4 -0
  6. humancalib-0.3.1/src/humancalib/__init__.py +16 -0
  7. humancalib-0.3.1/src/humancalib/__main__.py +6 -0
  8. humancalib-0.3.1/src/humancalib/api.py +87 -0
  9. humancalib-0.3.1/src/humancalib/argument.py +91 -0
  10. humancalib-0.3.1/src/humancalib/calibration/__init__.py +1 -0
  11. humancalib-0.3.1/src/humancalib/calibration/ba.py +673 -0
  12. humancalib-0.3.1/src/humancalib/calibration/ba_jacobian.py +180 -0
  13. humancalib-0.3.1/src/humancalib/calibration/calib_linear.py +493 -0
  14. humancalib-0.3.1/src/humancalib/cli.py +757 -0
  15. humancalib-0.3.1/src/humancalib/core/__init__.py +80 -0
  16. humancalib-0.3.1/src/humancalib/core/filtering.py +66 -0
  17. humancalib-0.3.1/src/humancalib/core/frames.py +42 -0
  18. humancalib-0.3.1/src/humancalib/core/geometry.py +199 -0
  19. humancalib-0.3.1/src/humancalib/core/gpu.py +71 -0
  20. humancalib-0.3.1/src/humancalib/core/log.py +119 -0
  21. humancalib-0.3.1/src/humancalib/core/models.py +20 -0
  22. humancalib-0.3.1/src/humancalib/core/poses_io.py +125 -0
  23. humancalib-0.3.1/src/humancalib/core/sampling.py +80 -0
  24. humancalib-0.3.1/src/humancalib/core/session.py +165 -0
  25. humancalib-0.3.1/src/humancalib/core/sidecars.py +80 -0
  26. humancalib-0.3.1/src/humancalib/core/skeletons.py +390 -0
  27. humancalib-0.3.1/src/humancalib/core/toml_io.py +48 -0
  28. humancalib-0.3.1/src/humancalib/core/videos.py +48 -0
  29. humancalib-0.3.1/src/humancalib/evaluation/__init__.py +6 -0
  30. humancalib-0.3.1/src/humancalib/evaluation/batch.py +267 -0
  31. humancalib-0.3.1/src/humancalib/evaluation/biocv.py +137 -0
  32. humancalib-0.3.1/src/humancalib/evaluation/comfi.py +216 -0
  33. humancalib-0.3.1/src/humancalib/evaluation/compare.py +207 -0
  34. humancalib-0.3.1/src/humancalib/evaluation/diagnose.py +115 -0
  35. humancalib-0.3.1/src/humancalib/evaluation/imove.py +219 -0
  36. humancalib-0.3.1/src/humancalib/evaluation/lbmc.py +144 -0
  37. humancalib-0.3.1/src/humancalib/evaluation/metrics.py +219 -0
  38. humancalib-0.3.1/src/humancalib/evaluation/opencap.py +241 -0
  39. humancalib-0.3.1/src/humancalib/evaluation/plot_rig.py +249 -0
  40. humancalib-0.3.1/src/humancalib/evaluation/rig.py +93 -0
  41. humancalib-0.3.1/src/humancalib/pipeline/__init__.py +1 -0
  42. humancalib-0.3.1/src/humancalib/pipeline/create_cameras_from_toml.py +134 -0
  43. humancalib-0.3.1/src/humancalib/pipeline/detect_outlier_frames.py +187 -0
  44. humancalib-0.3.1/src/humancalib/pipeline/frame_mapping.py +46 -0
  45. humancalib-0.3.1/src/humancalib/pipeline/motion_selection.py +154 -0
  46. humancalib-0.3.1/src/humancalib/pipeline/poses_cache.py +64 -0
  47. humancalib-0.3.1/src/humancalib/pipeline/reselect_person.py +374 -0
  48. humancalib-0.3.1/src/humancalib/pipeline/run_ba.py +132 -0
  49. humancalib-0.3.1/src/humancalib/pipeline/run_calib_linear.py +291 -0
  50. humancalib-0.3.1/src/humancalib/pipeline/write_session.py +73 -0
  51. humancalib-0.3.1/src/humancalib/pose/__init__.py +1 -0
  52. humancalib-0.3.1/src/humancalib/pose/candidates.py +98 -0
  53. humancalib-0.3.1/src/humancalib/pose/inference.py +333 -0
  54. humancalib-0.3.1/src/humancalib/pose/metrabs_inference.py +346 -0
  55. humancalib-0.3.1/src/humancalib/pose/metrabs_outputs.py +229 -0
  56. humancalib-0.3.1/src/humancalib/pose/model_download.py +119 -0
  57. humancalib-0.3.1/src/humancalib/pose/rtmlib_inference.py +399 -0
  58. humancalib-0.3.1/src/humancalib/postprocessing/__init__.py +1 -0
  59. humancalib-0.3.1/src/humancalib/postprocessing/evaluate_calibration.py +290 -0
  60. humancalib-0.3.1/src/humancalib/postprocessing/scale_scene.py +463 -0
  61. humancalib-0.3.1/src/humancalib/postprocessing/visualize_results.py +488 -0
  62. humancalib-0.3.1/src/humancalib/tools/__init__.py +1 -0
  63. humancalib-0.3.1/src/humancalib/tools/convert_calib_rotation.py +155 -0
  64. humancalib-0.3.1/src/humancalib/tools/covisibility_report.py +297 -0
  65. humancalib-0.3.1/src/humancalib/tools/fix_person_association.py +264 -0
  66. humancalib-0.3.1/src/humancalib/tools/rotate_video.py +85 -0
  67. humancalib-0.3.1/src/humancalib.egg-info/PKG-INFO +322 -0
  68. humancalib-0.3.1/src/humancalib.egg-info/SOURCES.txt +92 -0
  69. humancalib-0.3.1/src/humancalib.egg-info/dependency_links.txt +1 -0
  70. humancalib-0.3.1/src/humancalib.egg-info/entry_points.txt +2 -0
  71. humancalib-0.3.1/src/humancalib.egg-info/requires.txt +35 -0
  72. humancalib-0.3.1/src/humancalib.egg-info/top_level.txt +1 -0
  73. humancalib-0.3.1/tests/test_api.py +59 -0
  74. humancalib-0.3.1/tests/test_ba_jacobian.py +154 -0
  75. humancalib-0.3.1/tests/test_cli.py +264 -0
  76. humancalib-0.3.1/tests/test_env_consistency.py +117 -0
  77. humancalib-0.3.1/tests/test_eval_biocv.py +211 -0
  78. humancalib-0.3.1/tests/test_eval_comfi.py +59 -0
  79. humancalib-0.3.1/tests/test_eval_imove.py +80 -0
  80. humancalib-0.3.1/tests/test_eval_lbmc.py +33 -0
  81. humancalib-0.3.1/tests/test_eval_metrics.py +167 -0
  82. humancalib-0.3.1/tests/test_eval_opencap.py +102 -0
  83. humancalib-0.3.1/tests/test_frames.py +34 -0
  84. humancalib-0.3.1/tests/test_golden_run.py +151 -0
  85. humancalib-0.3.1/tests/test_io.py +132 -0
  86. humancalib-0.3.1/tests/test_log.py +107 -0
  87. humancalib-0.3.1/tests/test_model_download.py +86 -0
  88. humancalib-0.3.1/tests/test_pipeline_helpers.py +206 -0
  89. humancalib-0.3.1/tests/test_procrustes.py +90 -0
  90. humancalib-0.3.1/tests/test_reselect_person.py +261 -0
  91. humancalib-0.3.1/tests/test_sampling.py +59 -0
  92. humancalib-0.3.1/tests/test_session_and_sidecars.py +101 -0
  93. humancalib-0.3.1/tests/test_skeletons.py +48 -0
  94. humancalib-0.3.1/tests/test_triangulation.py +161 -0
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Sang-Eun Lee
4
+ Copyright (c) 2025 Florian Delaplace
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
@@ -0,0 +1,322 @@
1
+ Metadata-Version: 2.4
2
+ Name: humancalib
3
+ Version: 0.3.1
4
+ Summary: Multi-camera extrinsic calibration from human pose
5
+ Author: Florian Delaplace
6
+ License-Expression: MIT
7
+ Project-URL: Repository, https://github.com/flodelaplace/HumanCalib
8
+ Project-URL: Documentation, https://github.com/flodelaplace/HumanCalib/blob/main/HOWTO.md
9
+ Project-URL: Issues, https://github.com/flodelaplace/HumanCalib/issues
10
+ Project-URL: Changelog, https://github.com/flodelaplace/HumanCalib/blob/main/CHANGELOG.md
11
+ Keywords: camera calibration,extrinsic calibration,multi-camera,markerless motion capture,human pose estimation,biomechanics,pose2sim,metrabs
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Topic :: Scientific/Engineering :: Image Recognition
15
+ Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Operating System :: POSIX :: Linux
21
+ Classifier: Operating System :: Microsoft :: Windows
22
+ Classifier: Environment :: GPU :: NVIDIA CUDA
23
+ Requires-Python: <3.13,>=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: numpy<2,>=1.22
27
+ Requires-Dist: scipy>=1.9
28
+ Requires-Dist: matplotlib>=3.7
29
+ Requires-Dist: opencv-contrib-python>=4.7
30
+ Requires-Dist: pycalib-simple>=2025.12.5.1
31
+ Requires-Dist: scikit-image<0.25,>=0.20
32
+ Requires-Dist: pandas>=2.0
33
+ Requires-Dist: PyYAML>=6.0
34
+ Requires-Dist: tqdm>=4.64
35
+ Requires-Dist: tomli>=2.0; python_version < "3.11"
36
+ Requires-Dist: toml>=0.10.2
37
+ Provides-Extra: gpu
38
+ Requires-Dist: tensorflow[and-cuda]<2.16,>=2.15; sys_platform == "linux" and extra == "gpu"
39
+ Requires-Dist: tensorflow==2.10.1; sys_platform == "win32" and extra == "gpu"
40
+ Requires-Dist: tensorflow-hub<0.17,>=0.13; extra == "gpu"
41
+ Requires-Dist: setuptools<81; extra == "gpu"
42
+ Requires-Dist: imageio>=2.22; extra == "gpu"
43
+ Requires-Dist: imageio-ffmpeg>=0.4; extra == "gpu"
44
+ Provides-Extra: metrabs
45
+ Requires-Dist: tensorflow<2.16,>=2.10; extra == "metrabs"
46
+ Requires-Dist: tensorflow-hub<0.17,>=0.13; extra == "metrabs"
47
+ Requires-Dist: setuptools<81; extra == "metrabs"
48
+ Requires-Dist: imageio>=2.22; extra == "metrabs"
49
+ Requires-Dist: imageio-ffmpeg>=0.4; extra == "metrabs"
50
+ Provides-Extra: dev
51
+ Requires-Dist: pytest>=8; extra == "dev"
52
+ Dynamic: license-file
53
+
54
+ # HumanCalib
55
+
56
+ **Extrinsic calibration of a multi-camera rig from a person walking through it.**
57
+ No checkerboard, no wand: HumanCalib estimates the pose of every camera from the
58
+ human pose seen by all of them, then gives the rig a metric scale and a vertical
59
+ axis from the subject's height. The output is a
60
+ [Pose2Sim](https://github.com/perfanalytics/pose2sim)-format calibration, ready
61
+ for markerless motion capture.
62
+
63
+ ![Overview](https://raw.githubusercontent.com/flodelaplace/HumanCalib/main/img/graphical_abstract.png)
64
+
65
+ ## How it works
66
+
67
+ 1. **Pose estimation** in every view with [MeTRAbs](https://github.com/isarandi/metrabs),
68
+ which predicts a metric 3D skeleton per camera.
69
+ 2. **Person selection**: the walking subject is kept in every camera, bystanders
70
+ are discarded.
71
+ 3. **Linear initialisation** by aligning the per-camera 3D skeletons (Procrustes).
72
+ 4. **Bundle adjustment** of all cameras on the 2D keypoints.
73
+ 5. **Metric scale and vertical** from the subject's height and walk.
74
+
75
+ Details, design choices and what was measured to justify them:
76
+ [docs/METHOD.md](https://github.com/flodelaplace/HumanCalib/blob/main/docs/METHOD.md).
77
+
78
+ ![3D result](https://raw.githubusercontent.com/flodelaplace/HumanCalib/main/img/visu_3d_FINAL.gif)
79
+
80
+ ## Validation
81
+
82
+ Five public datasets, 77 trials, default settings. The three reported here each
83
+ provide a laboratory-grade reference calibration and enough trials to summarise.
84
+
85
+ **Camera geometry.** Relative rotation between camera pairs, against the
86
+ dataset's own calibration, and reprojection error of our own reconstruction,
87
+ which needs no reference. Median over trials [min–max]:
88
+
89
+ | Dataset | Cameras | Trials | Relative rotation error | Reprojection error (MRE) |
90
+ |---|---|---|---|---|
91
+ | IMOVE-23 | 10 | 11 | 0.40° [0.30–0.96] | 3.30 px [2.95–3.83] |
92
+ | BioCV | 9 | 18 | 0.43° [0.25–0.95] | 2.77 px [2.35–4.07] |
93
+ | OpenCap | 5 | 18 | 1.89° [0.56–2.31] | 1.69 px [1.38–2.16] |
94
+
95
+ Pixels are not comparable between rigs of different focal lengths; in angular
96
+ terms the same errors are 2.4, 2.1 and 1.8 mrad. A low reprojection error means
97
+ the calibration is not broken, not that it is accurate: on OpenCap, five
98
+ smartphones on a tight arc and a walk of about two seconds cap the accuracy
99
+ while leaving the residual low.
100
+
101
+ **What it changes for the biomechanist.** The same
102
+ [Pose2Sim](https://github.com/perfanalytics/pose2sim) chain was run twice per
103
+ trial on the same 2D detections, with the laboratory calibration and with
104
+ HumanCalib's, changing nothing else. The table compares the joint angles the two
105
+ runs produce. Equivalence is declared when the upper bound of the 95 %
106
+ confidence interval stays below the margin, for each of the 9 degrees of freedom
107
+ (pelvis, hip, knee, ankle, subtalar):
108
+
109
+ | Dataset | Trials | RMSD between the two chains, median [min–max] | Worst degree of freedom | Equivalent within 2° |
110
+ |---|---|---|---|---|
111
+ | BioCV | 18 | 0.40° [0.20–2.45] | 0.94° | 9 / 9 |
112
+ | OpenCap | 18 | 0.58° [0.35–1.13] | 0.98° | 9 / 9 |
113
+ | IMOVE-23 | 11 | 0.82° [0.46–1.67] | 1.38° | 8 / 9 |
114
+
115
+ Changing the calibration therefore moves the reported angles by about half a
116
+ degree to one degree, below the 2° margin usually accepted in clinical gait
117
+ analysis, and roughly ten times less than the 4–11° that separates such a chain
118
+ from optical motion capture on the same trials.
119
+
120
+ - No failed calibration out of 77 (with RTMPose + VideoPose3D instead of MeTRAbs: 30).
121
+ - Metric scale within 1.1 % (median, on the four datasets not used to set it).
122
+
123
+ The two remaining datasets are reported in the paper: LBMC, whose two treadmill
124
+ trials are too few to summarise, and COMFI, where HumanCalib proved closer to
125
+ the laboratory's own motion capture than that dataset's own calibration, which
126
+ makes any comparison against that reference a measure of the reference rather
127
+ than of HumanCalib.
128
+
129
+ A paper is in preparation. The evaluation protocol is in
130
+ [docs/EVALUATION_PROTOCOL.md](https://github.com/flodelaplace/HumanCalib/blob/main/docs/EVALUATION_PROTOCOL.md).
131
+
132
+ ## Installation
133
+
134
+ An NVIDIA GPU is needed for pose estimation (driver ≥ 525). Linux, WSL2 and
135
+ Windows are supported.
136
+
137
+ ### pip — Linux or WSL2
138
+
139
+ Python 3.10 or 3.11. The CUDA libraries come from pip, nothing else to install.
140
+
141
+ ```bash
142
+ python -m venv .venv && source .venv/bin/activate
143
+ pip install "humancalib[gpu] @ https://github.com/flodelaplace/HumanCalib/archive/refs/tags/v0.3.1.zip"
144
+ ```
145
+
146
+ ### Windows
147
+
148
+ Python 3.10, in a conda environment that provides CUDA: TensorFlow 2.10 is the
149
+ last version with GPU support on native Windows. CUDA 11.8 also covers recent
150
+ GPUs (RTX 40xx), which CUDA 11.2 does not.
151
+
152
+ ```bat
153
+ conda create -n humancalib -c conda-forge python=3.10 cudatoolkit=11.8 cudnn=8.9
154
+ conda activate humancalib
155
+ pip install "humancalib[gpu] @ https://github.com/flodelaplace/HumanCalib/archive/refs/tags/v0.3.1.zip"
156
+ ```
157
+
158
+ ### Check the install
159
+
160
+ The demo videos are in the repository: unzip the same
161
+ [archive](https://github.com/flodelaplace/HumanCalib/archive/refs/tags/v0.3.1.zip)
162
+ (or `git clone` the repository), then
163
+
164
+ ```bash
165
+ humancalib run HumanCalib-0.3.1/demo HumanCalib-0.3.1/demo/Calib_scene.toml output/demo --height 1.78
166
+ ```
167
+
168
+ It worked if the log shows `Compute device: GPU` and ends with an MRE summary
169
+ table, and `output/demo/results/Calib_scene_calibrated.toml` exists. The first
170
+ run downloads the MeTRAbs model (~700 MB, with a progress bar, resumed if
171
+ interrupted) into `~/.cache/tfhub_modules`; set `TFHUB_CACHE_DIR` to put it
172
+ elsewhere.
173
+
174
+ ### From Python (e.g. inside Pose2Sim)
175
+
176
+ ```python
177
+ from humancalib import calibrate
178
+
179
+ toml = calibrate("session/videos", "session/Calib_intrinsics.toml", "session/humancalib",
180
+ height=1.78)
181
+ ```
182
+
183
+ `calibrate` runs the same pipeline as `humancalib run`, with the same defaults,
184
+ and returns the path of the calibrated TOML in Pose2Sim format. Any command-line
185
+ option can be passed by name (`extract_fps=25`, `ref_frame=120`...); a failure
186
+ raises `humancalib.CalibrationError`.
187
+
188
+ ### Docker
189
+
190
+ The exact environment the published results were obtained with. Requires Docker
191
+ with Compose v2 and the
192
+ [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html).
193
+
194
+ ```bash
195
+ git clone https://github.com/flodelaplace/HumanCalib.git
196
+ cd HumanCalib
197
+ printf 'HOST_UID=%s\nHOST_GID=%s\n' "$(id -u)" "$(id -g)" > .env # results owned by you, not root
198
+ docker compose build # ~2 GB download, resumable
199
+ docker compose run --rm calib demo
200
+ ```
201
+
202
+ The model is kept in a Docker volume after the first run.
203
+
204
+ ### conda, exact environment
205
+
206
+ Every version pinned, as validated (TensorFlow 2.12, CUDA 11.8 from conda):
207
+
208
+ ```bash
209
+ git clone https://github.com/flodelaplace/HumanCalib.git
210
+ cd HumanCalib
211
+ conda env create -f envs/calib.yaml
212
+ conda activate humancalib
213
+ pip install --no-deps -e . # adds the `humancalib` command, keeps the pins
214
+ ```
215
+
216
+ The pip installs above use TensorFlow 2.15 (Linux) and 2.10 (Windows); they give
217
+ the same calibration as this environment: on the demo, 0.02° median difference in
218
+ relative rotation and 1 mm in camera positions; on a BioCV trial, the same error
219
+ against the laboratory calibration (0.43°).
220
+
221
+ Without a GPU, `pip install "humancalib @ https://github.com/flodelaplace/HumanCalib/archive/refs/tags/v0.3.1.zip"`
222
+ installs calibration, bundle adjustment, evaluation and scaling from existing
223
+ pose files. The optional RTMPose + VideoPose3D backend has its own environment:
224
+ see [HOWTO.md](https://github.com/flodelaplace/HumanCalib/blob/main/HOWTO.md#optional-backend-rtmpose--videopose3d).
225
+
226
+ ## Calibrating your own rig
227
+
228
+ **1. Record.** Synchronised videos from static cameras, while one person walks
229
+ across the capture volume for a few passes.
230
+
231
+ **2. Prepare a session folder** with one video per camera and a
232
+ `Calib_scene.toml` holding each camera's intrinsics in Pose2Sim format:
233
+
234
+ ```toml
235
+ [camera01]
236
+ name = "camera01"
237
+ size = [1920.0, 1080.0]
238
+ matrix = [[1057.46, 0.0, 942.23], [0.0, 1056.83, 535.6], [0.0, 0.0, 1.0]]
239
+ distortions = [-0.041, 0.0086, -0.0002, 0.0002]
240
+ fisheye = false
241
+ ```
242
+
243
+ Video names (without extension) must match the TOML sections. Good intrinsics
244
+ matter more than anything else: see [input/README.md](https://github.com/flodelaplace/HumanCalib/blob/main/input/README.md).
245
+
246
+ **3. Run.**
247
+
248
+ ```bash
249
+ humancalib run input/my_session input/my_session/Calib_scene.toml output/my_session \
250
+ --height 1.84
251
+
252
+ # Docker: same arguments, with the container's paths
253
+ docker compose run --rm calib \
254
+ /input/my_session /input/my_session/Calib_scene.toml /output/my_session --height 1.84
255
+ ```
256
+
257
+ `--height` is the subject's height in metres; it sets the metric scale. The
258
+ origin and horizontal axis come from a frame where every camera sees the head and
259
+ both heels, chosen automatically (or `--ref_frame N`). On video faster than
260
+ 50 Hz, add `--extract_fps 25`: same calibration, 2 to 8 times faster. Every
261
+ option is described in [HOWTO.md](https://github.com/flodelaplace/HumanCalib/blob/main/HOWTO.md).
262
+
263
+ **4. Results**, in `output/my_session/results/`:
264
+
265
+ | File | Contents |
266
+ |---|---|
267
+ | `Calib_scene_calibrated.toml` | The calibration: metric, gravity-aligned, Pose2Sim format |
268
+ | `3d_skeleton_FINAL.trc` | Triangulated skeleton |
269
+ | `camera/visu_3d_FINAL.gif` | 3D animation of the skeleton and cameras |
270
+ | `MRE_visualizations/` | Best and worst reprojection per camera, for diagnosis |
271
+
272
+ ## Documentation
273
+
274
+ | | |
275
+ |---|---|
276
+ | [HOWTO.md](https://github.com/flodelaplace/HumanCalib/blob/main/HOWTO.md) | Full command-line reference, examples, diagnosis |
277
+ | [docs/METHOD.md](https://github.com/flodelaplace/HumanCalib/blob/main/docs/METHOD.md) | How each step works and why |
278
+ | [docs/TROUBLESHOOTING.md](https://github.com/flodelaplace/HumanCalib/blob/main/docs/TROUBLESHOOTING.md) | Common errors and fixes |
279
+ | [CONTRIBUTING.md](https://github.com/flodelaplace/HumanCalib/blob/main/CONTRIBUTING.md) | Development setup, tests, conventions |
280
+ | [CHANGELOG.md](https://github.com/flodelaplace/HumanCalib/blob/main/CHANGELOG.md) | Changes between versions |
281
+ | [docs/](https://github.com/flodelaplace/HumanCalib/blob/main/docs/README.md) | Evaluation protocol and research notes |
282
+
283
+ ## Repository layout
284
+
285
+ ```
286
+ src/humancalib/ the Python package: cli.py (the `humancalib` command), core/, pose/,
287
+ calibration/, pipeline/, postprocessing/, evaluation/
288
+ tests/ pytest suite, runs on a CPU in seconds
289
+ envs/ exact conda environments (calib, rtmpose, ci)
290
+ Dockerfile, compose.yaml, docker/ container images and entry point
291
+ demo/ 4-camera demo session
292
+ docs/ documentation and research notes
293
+ input/, output/ your sessions and results (not tracked)
294
+ ```
295
+
296
+ ## Licensing
297
+
298
+ The HumanCalib code is **MIT**. The pretrained pose models are **not free for
299
+ commercial use**:
300
+
301
+ | Component | Licence |
302
+ |---|---|
303
+ | HumanCalib | MIT ([LICENSE](https://github.com/flodelaplace/HumanCalib/blob/main/LICENSE)) |
304
+ | MeTRAbs model (`metrabs_l`) | Non-commercial use only (training data licences) |
305
+ | VideoPose3D code and weights (optional backend) | CC BY-NC 4.0 |
306
+ | rtmlib (optional backend) | Apache-2.0; RTMPose weight licence not stated upstream |
307
+
308
+ The Docker images contain no MeTRAbs weights unless built with `BAKE_MODELS=1`.
309
+ This summary is not legal advice; check the upstream licences for your use.
310
+
311
+ ## Citation
312
+
313
+ Use GitHub's *Cite this repository* button ([CITATION.cff](https://github.com/flodelaplace/HumanCalib/blob/main/CITATION.cff)). Please
314
+ also cite the method HumanCalib builds on and the pose estimator:
315
+
316
+ - S.-E. Lee, K. Shibata, S. Nonaka, S. Nobuhara, K. Nishino. *Extrinsic Camera
317
+ Calibration From a Moving Person.* IEEE Robotics and Automation Letters 7(4),
318
+ 2022. [doi:10.1109/LRA.2022.3192629](https://doi.org/10.1109/LRA.2022.3192629) —
319
+ [original code](https://github.com/kyotovision-public/extrinsic-camera-calibration-from-a-moving-person)
320
+ - I. Sárándi, T. Linder, K. O. Arras, B. Leibe. *MeTRAbs: Metric-Scale
321
+ Truncation-Robust Heatmaps for Absolute 3D Human Pose Estimation.* IEEE T-BIOM,
322
+ 2021.
@@ -0,0 +1,269 @@
1
+ # HumanCalib
2
+
3
+ **Extrinsic calibration of a multi-camera rig from a person walking through it.**
4
+ No checkerboard, no wand: HumanCalib estimates the pose of every camera from the
5
+ human pose seen by all of them, then gives the rig a metric scale and a vertical
6
+ axis from the subject's height. The output is a
7
+ [Pose2Sim](https://github.com/perfanalytics/pose2sim)-format calibration, ready
8
+ for markerless motion capture.
9
+
10
+ ![Overview](https://raw.githubusercontent.com/flodelaplace/HumanCalib/main/img/graphical_abstract.png)
11
+
12
+ ## How it works
13
+
14
+ 1. **Pose estimation** in every view with [MeTRAbs](https://github.com/isarandi/metrabs),
15
+ which predicts a metric 3D skeleton per camera.
16
+ 2. **Person selection**: the walking subject is kept in every camera, bystanders
17
+ are discarded.
18
+ 3. **Linear initialisation** by aligning the per-camera 3D skeletons (Procrustes).
19
+ 4. **Bundle adjustment** of all cameras on the 2D keypoints.
20
+ 5. **Metric scale and vertical** from the subject's height and walk.
21
+
22
+ Details, design choices and what was measured to justify them:
23
+ [docs/METHOD.md](https://github.com/flodelaplace/HumanCalib/blob/main/docs/METHOD.md).
24
+
25
+ ![3D result](https://raw.githubusercontent.com/flodelaplace/HumanCalib/main/img/visu_3d_FINAL.gif)
26
+
27
+ ## Validation
28
+
29
+ Five public datasets, 77 trials, default settings. The three reported here each
30
+ provide a laboratory-grade reference calibration and enough trials to summarise.
31
+
32
+ **Camera geometry.** Relative rotation between camera pairs, against the
33
+ dataset's own calibration, and reprojection error of our own reconstruction,
34
+ which needs no reference. Median over trials [min–max]:
35
+
36
+ | Dataset | Cameras | Trials | Relative rotation error | Reprojection error (MRE) |
37
+ |---|---|---|---|---|
38
+ | IMOVE-23 | 10 | 11 | 0.40° [0.30–0.96] | 3.30 px [2.95–3.83] |
39
+ | BioCV | 9 | 18 | 0.43° [0.25–0.95] | 2.77 px [2.35–4.07] |
40
+ | OpenCap | 5 | 18 | 1.89° [0.56–2.31] | 1.69 px [1.38–2.16] |
41
+
42
+ Pixels are not comparable between rigs of different focal lengths; in angular
43
+ terms the same errors are 2.4, 2.1 and 1.8 mrad. A low reprojection error means
44
+ the calibration is not broken, not that it is accurate: on OpenCap, five
45
+ smartphones on a tight arc and a walk of about two seconds cap the accuracy
46
+ while leaving the residual low.
47
+
48
+ **What it changes for the biomechanist.** The same
49
+ [Pose2Sim](https://github.com/perfanalytics/pose2sim) chain was run twice per
50
+ trial on the same 2D detections, with the laboratory calibration and with
51
+ HumanCalib's, changing nothing else. The table compares the joint angles the two
52
+ runs produce. Equivalence is declared when the upper bound of the 95 %
53
+ confidence interval stays below the margin, for each of the 9 degrees of freedom
54
+ (pelvis, hip, knee, ankle, subtalar):
55
+
56
+ | Dataset | Trials | RMSD between the two chains, median [min–max] | Worst degree of freedom | Equivalent within 2° |
57
+ |---|---|---|---|---|
58
+ | BioCV | 18 | 0.40° [0.20–2.45] | 0.94° | 9 / 9 |
59
+ | OpenCap | 18 | 0.58° [0.35–1.13] | 0.98° | 9 / 9 |
60
+ | IMOVE-23 | 11 | 0.82° [0.46–1.67] | 1.38° | 8 / 9 |
61
+
62
+ Changing the calibration therefore moves the reported angles by about half a
63
+ degree to one degree, below the 2° margin usually accepted in clinical gait
64
+ analysis, and roughly ten times less than the 4–11° that separates such a chain
65
+ from optical motion capture on the same trials.
66
+
67
+ - No failed calibration out of 77 (with RTMPose + VideoPose3D instead of MeTRAbs: 30).
68
+ - Metric scale within 1.1 % (median, on the four datasets not used to set it).
69
+
70
+ The two remaining datasets are reported in the paper: LBMC, whose two treadmill
71
+ trials are too few to summarise, and COMFI, where HumanCalib proved closer to
72
+ the laboratory's own motion capture than that dataset's own calibration, which
73
+ makes any comparison against that reference a measure of the reference rather
74
+ than of HumanCalib.
75
+
76
+ A paper is in preparation. The evaluation protocol is in
77
+ [docs/EVALUATION_PROTOCOL.md](https://github.com/flodelaplace/HumanCalib/blob/main/docs/EVALUATION_PROTOCOL.md).
78
+
79
+ ## Installation
80
+
81
+ An NVIDIA GPU is needed for pose estimation (driver ≥ 525). Linux, WSL2 and
82
+ Windows are supported.
83
+
84
+ ### pip — Linux or WSL2
85
+
86
+ Python 3.10 or 3.11. The CUDA libraries come from pip, nothing else to install.
87
+
88
+ ```bash
89
+ python -m venv .venv && source .venv/bin/activate
90
+ pip install "humancalib[gpu] @ https://github.com/flodelaplace/HumanCalib/archive/refs/tags/v0.3.1.zip"
91
+ ```
92
+
93
+ ### Windows
94
+
95
+ Python 3.10, in a conda environment that provides CUDA: TensorFlow 2.10 is the
96
+ last version with GPU support on native Windows. CUDA 11.8 also covers recent
97
+ GPUs (RTX 40xx), which CUDA 11.2 does not.
98
+
99
+ ```bat
100
+ conda create -n humancalib -c conda-forge python=3.10 cudatoolkit=11.8 cudnn=8.9
101
+ conda activate humancalib
102
+ pip install "humancalib[gpu] @ https://github.com/flodelaplace/HumanCalib/archive/refs/tags/v0.3.1.zip"
103
+ ```
104
+
105
+ ### Check the install
106
+
107
+ The demo videos are in the repository: unzip the same
108
+ [archive](https://github.com/flodelaplace/HumanCalib/archive/refs/tags/v0.3.1.zip)
109
+ (or `git clone` the repository), then
110
+
111
+ ```bash
112
+ humancalib run HumanCalib-0.3.1/demo HumanCalib-0.3.1/demo/Calib_scene.toml output/demo --height 1.78
113
+ ```
114
+
115
+ It worked if the log shows `Compute device: GPU` and ends with an MRE summary
116
+ table, and `output/demo/results/Calib_scene_calibrated.toml` exists. The first
117
+ run downloads the MeTRAbs model (~700 MB, with a progress bar, resumed if
118
+ interrupted) into `~/.cache/tfhub_modules`; set `TFHUB_CACHE_DIR` to put it
119
+ elsewhere.
120
+
121
+ ### From Python (e.g. inside Pose2Sim)
122
+
123
+ ```python
124
+ from humancalib import calibrate
125
+
126
+ toml = calibrate("session/videos", "session/Calib_intrinsics.toml", "session/humancalib",
127
+ height=1.78)
128
+ ```
129
+
130
+ `calibrate` runs the same pipeline as `humancalib run`, with the same defaults,
131
+ and returns the path of the calibrated TOML in Pose2Sim format. Any command-line
132
+ option can be passed by name (`extract_fps=25`, `ref_frame=120`...); a failure
133
+ raises `humancalib.CalibrationError`.
134
+
135
+ ### Docker
136
+
137
+ The exact environment the published results were obtained with. Requires Docker
138
+ with Compose v2 and the
139
+ [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html).
140
+
141
+ ```bash
142
+ git clone https://github.com/flodelaplace/HumanCalib.git
143
+ cd HumanCalib
144
+ printf 'HOST_UID=%s\nHOST_GID=%s\n' "$(id -u)" "$(id -g)" > .env # results owned by you, not root
145
+ docker compose build # ~2 GB download, resumable
146
+ docker compose run --rm calib demo
147
+ ```
148
+
149
+ The model is kept in a Docker volume after the first run.
150
+
151
+ ### conda, exact environment
152
+
153
+ Every version pinned, as validated (TensorFlow 2.12, CUDA 11.8 from conda):
154
+
155
+ ```bash
156
+ git clone https://github.com/flodelaplace/HumanCalib.git
157
+ cd HumanCalib
158
+ conda env create -f envs/calib.yaml
159
+ conda activate humancalib
160
+ pip install --no-deps -e . # adds the `humancalib` command, keeps the pins
161
+ ```
162
+
163
+ The pip installs above use TensorFlow 2.15 (Linux) and 2.10 (Windows); they give
164
+ the same calibration as this environment: on the demo, 0.02° median difference in
165
+ relative rotation and 1 mm in camera positions; on a BioCV trial, the same error
166
+ against the laboratory calibration (0.43°).
167
+
168
+ Without a GPU, `pip install "humancalib @ https://github.com/flodelaplace/HumanCalib/archive/refs/tags/v0.3.1.zip"`
169
+ installs calibration, bundle adjustment, evaluation and scaling from existing
170
+ pose files. The optional RTMPose + VideoPose3D backend has its own environment:
171
+ see [HOWTO.md](https://github.com/flodelaplace/HumanCalib/blob/main/HOWTO.md#optional-backend-rtmpose--videopose3d).
172
+
173
+ ## Calibrating your own rig
174
+
175
+ **1. Record.** Synchronised videos from static cameras, while one person walks
176
+ across the capture volume for a few passes.
177
+
178
+ **2. Prepare a session folder** with one video per camera and a
179
+ `Calib_scene.toml` holding each camera's intrinsics in Pose2Sim format:
180
+
181
+ ```toml
182
+ [camera01]
183
+ name = "camera01"
184
+ size = [1920.0, 1080.0]
185
+ matrix = [[1057.46, 0.0, 942.23], [0.0, 1056.83, 535.6], [0.0, 0.0, 1.0]]
186
+ distortions = [-0.041, 0.0086, -0.0002, 0.0002]
187
+ fisheye = false
188
+ ```
189
+
190
+ Video names (without extension) must match the TOML sections. Good intrinsics
191
+ matter more than anything else: see [input/README.md](https://github.com/flodelaplace/HumanCalib/blob/main/input/README.md).
192
+
193
+ **3. Run.**
194
+
195
+ ```bash
196
+ humancalib run input/my_session input/my_session/Calib_scene.toml output/my_session \
197
+ --height 1.84
198
+
199
+ # Docker: same arguments, with the container's paths
200
+ docker compose run --rm calib \
201
+ /input/my_session /input/my_session/Calib_scene.toml /output/my_session --height 1.84
202
+ ```
203
+
204
+ `--height` is the subject's height in metres; it sets the metric scale. The
205
+ origin and horizontal axis come from a frame where every camera sees the head and
206
+ both heels, chosen automatically (or `--ref_frame N`). On video faster than
207
+ 50 Hz, add `--extract_fps 25`: same calibration, 2 to 8 times faster. Every
208
+ option is described in [HOWTO.md](https://github.com/flodelaplace/HumanCalib/blob/main/HOWTO.md).
209
+
210
+ **4. Results**, in `output/my_session/results/`:
211
+
212
+ | File | Contents |
213
+ |---|---|
214
+ | `Calib_scene_calibrated.toml` | The calibration: metric, gravity-aligned, Pose2Sim format |
215
+ | `3d_skeleton_FINAL.trc` | Triangulated skeleton |
216
+ | `camera/visu_3d_FINAL.gif` | 3D animation of the skeleton and cameras |
217
+ | `MRE_visualizations/` | Best and worst reprojection per camera, for diagnosis |
218
+
219
+ ## Documentation
220
+
221
+ | | |
222
+ |---|---|
223
+ | [HOWTO.md](https://github.com/flodelaplace/HumanCalib/blob/main/HOWTO.md) | Full command-line reference, examples, diagnosis |
224
+ | [docs/METHOD.md](https://github.com/flodelaplace/HumanCalib/blob/main/docs/METHOD.md) | How each step works and why |
225
+ | [docs/TROUBLESHOOTING.md](https://github.com/flodelaplace/HumanCalib/blob/main/docs/TROUBLESHOOTING.md) | Common errors and fixes |
226
+ | [CONTRIBUTING.md](https://github.com/flodelaplace/HumanCalib/blob/main/CONTRIBUTING.md) | Development setup, tests, conventions |
227
+ | [CHANGELOG.md](https://github.com/flodelaplace/HumanCalib/blob/main/CHANGELOG.md) | Changes between versions |
228
+ | [docs/](https://github.com/flodelaplace/HumanCalib/blob/main/docs/README.md) | Evaluation protocol and research notes |
229
+
230
+ ## Repository layout
231
+
232
+ ```
233
+ src/humancalib/ the Python package: cli.py (the `humancalib` command), core/, pose/,
234
+ calibration/, pipeline/, postprocessing/, evaluation/
235
+ tests/ pytest suite, runs on a CPU in seconds
236
+ envs/ exact conda environments (calib, rtmpose, ci)
237
+ Dockerfile, compose.yaml, docker/ container images and entry point
238
+ demo/ 4-camera demo session
239
+ docs/ documentation and research notes
240
+ input/, output/ your sessions and results (not tracked)
241
+ ```
242
+
243
+ ## Licensing
244
+
245
+ The HumanCalib code is **MIT**. The pretrained pose models are **not free for
246
+ commercial use**:
247
+
248
+ | Component | Licence |
249
+ |---|---|
250
+ | HumanCalib | MIT ([LICENSE](https://github.com/flodelaplace/HumanCalib/blob/main/LICENSE)) |
251
+ | MeTRAbs model (`metrabs_l`) | Non-commercial use only (training data licences) |
252
+ | VideoPose3D code and weights (optional backend) | CC BY-NC 4.0 |
253
+ | rtmlib (optional backend) | Apache-2.0; RTMPose weight licence not stated upstream |
254
+
255
+ The Docker images contain no MeTRAbs weights unless built with `BAKE_MODELS=1`.
256
+ This summary is not legal advice; check the upstream licences for your use.
257
+
258
+ ## Citation
259
+
260
+ Use GitHub's *Cite this repository* button ([CITATION.cff](https://github.com/flodelaplace/HumanCalib/blob/main/CITATION.cff)). Please
261
+ also cite the method HumanCalib builds on and the pose estimator:
262
+
263
+ - S.-E. Lee, K. Shibata, S. Nonaka, S. Nobuhara, K. Nishino. *Extrinsic Camera
264
+ Calibration From a Moving Person.* IEEE Robotics and Automation Letters 7(4),
265
+ 2022. [doi:10.1109/LRA.2022.3192629](https://doi.org/10.1109/LRA.2022.3192629) —
266
+ [original code](https://github.com/kyotovision-public/extrinsic-camera-calibration-from-a-moving-person)
267
+ - I. Sárándi, T. Linder, K. O. Arras, B. Leibe. *MeTRAbs: Metric-Scale
268
+ Truncation-Robust Heatmaps for Absolute 3D Human Pose Estimation.* IEEE T-BIOM,
269
+ 2021.