Package: pose2sim
Pose2SimN.B:. Please set undistort_points and handle_LR_swap to false for now since it currently leads to inaccuracies. I'll try to fix it soon.News: Version 0.7:Multi-person analysis is now supported!Team sports, combat sports, and ballroom dancing can now take advantage of Pose2Sim full potential.Other recently added features: Automatic batch processing, Marker augmentation, Blender visualization.To upgrade, typepip install pose2sim --upgrade.Pose2Simprovides a workflow for 3D markerless kinematics, as an alternative to the more usual marker-based motion capture methods. It aims to provide a free tool to obtain research-grade results from consumer-grade equipment. Any combination of phone, webcam, GoPro, etc. can be used.Pose2Sim stands for "OpenPose to OpenSim", as it uses OpenPose inputs (2D keypoints coordinates obtained from multiple videos) and leads to an OpenSim result (full-body 3D joint angles). Other 2D pose estimators such as BlazePose (MediaPipe), DeepLabCut, AlphaPose, can now be used as inputs.If you can only use one single camera and don't mind losing some accuracy, please consider usingSports2D.N.B.:As always, I am more than happy to welcome contributors (seeHow to contribute).Pose2Sim releases:v0.1: Published onlinev0.2: Published associated paperv0.3: Supported other pose estimation algorithmsv0.4: New calibration tool based on scene measurementsv0.5: Automatic batch processingv0.6: Marker augmentation, Blender visualizerv0.7: Multi-person analysisv0.9: New synchronization toolv0.8: Calibration based on keypoint detection, Handling left/right swaps, Correcting lens distortionsv0.10: Graphical User Interfacev1.0: First accomplished releaseContentsInstallation and DemonstrationInstallationDemonstration Part-1: Triangulate OpenPose outputsDemonstration Part-2: Obtain 3D joint angles with OpenSimDemonstration Part-3 (optional): Visualize your results with BlenderDemonstration Part-4 (optional): Try multi-person analysisUse on your own dataSetting your project upRetrieve the folder structureBatch processing2D pose estimationWith OpenPoseWith BlazePose (Mediapipe)With DeepLabCutWith AlphaPoseCamera synchronizationCamera calibrationConvert from Qualisys, Optitrack, Vicon, OpenCap, EasyMocap, or bioCVCalculate from scratchTracking, Triangulating, FilteringAssociate persons across camerasTriangulating keypointsFiltering 3D coordinatesMarker augmentationOpenSim kinematicsOpenSim ScalingOpenSim Inverse kinematicsCommand LineUtilitiesHow to cite and how to contributeHow to citeHow to contribute and to-do listInstallation and DemonstrationInstallationInstall OpenPose(instructionsthere).Windows portable demo is enough.Install OpenSim 4.x(there).Tested up to v4.4-beta on Windows. Has to be compiled from source on Linux (seethere).Optional.Install Anaconda orMiniconda.Open an Anaconda terminal and create a virtual environment with typing:conda create -n Pose2Sim python=3.8 -y 
conda activate Pose2SimInstall Pose2Sim:If you don't use Anaconda, typepython -Vin terminal to make sure python>=3.8 is installed.OPTION 1:Quick install:Open a terminal.pip install pose2simOPTION 2:Build from source and test the last changes:Open a terminal in the directory of your choice and Clone the Pose2Sim repository.git clone --depth 1 https://github.com/perfanalytics/pose2sim.git
cd pose2sim
pip install .Demonstration Part-1: Build 3D TRC file on PythonThis demonstration provides an example experiment of a person balancing on a beam, filmed with 4 calibrated cameras processed with OpenPose.Open a terminal, enterpip show pose2sim, report package location.Copy this path and go to the Single participant Demo folder:cd <path>\pose2sim\Demo\S00_Demo_Session\S00_P00_SingleParticipant.Typeipython, and try the following code:fromPose2SimimportPose2SimPose2Sim.calibration()Pose2Sim.personAssociation()Pose2Sim.triangulation()Pose2Sim.filtering()Pose2Sim.markerAugmentation()3D results are stored as .trc files in each trial folder in thepose-3ddirectory.N.B.:Default parameters have been provided inConfig.tomlbut can be edited.N.B.:Try the calibration tool by changingcalibration_typetocalculateinstead ofconvert(more infothere).Demonstration Part-2: Obtain 3D joint angles with OpenSimIn the same vein as you would do with marker-based kinematics, start with scaling your model, and then perform inverse kinematics.ScalingOpen OpenSim.Open the providedModel_Pose2Sim_LSTM.osimmodel fromPose2Sim/OpenSim_Setup.(File -> Open Model)Load the providedScaling_Setup_Pose2Sim_LSTM.xmlscaling file fromPose2Sim/OpenSim_Setup.(Tools -> Scale model -> Load)Run. You should see your skeletal model take the static pose.Save your scaled model inS00_P00_OpenSim/Model_Pose2Sim_S00_P00_LSTM_scaled.osim.(File -> Save Model As)Inverse kinematicsLoad the providedIK_Setup_Pose2Sim_LSTM.xmlscaling file fromPose2Sim/OpenSim_Setup.(Tools -> Inverse kinematics -> Load)Run. You should see your skeletal model move in the Vizualizer window.Your IK motion file will be saved inS00_P00_OpenSim.Demonstration Part-3 (optional): Visualize your results with BlenderVisualize your results and look in detail for potential areas of improvement (and more).Install the add-onFollow instructions on thePose2Sim_Blenderadd-on page.Visualize your resultsJust play with the buttons!Visualize camera positions, videos, triangulated keypoints, OpenSim skeleton, and more.N.B.:You need to proceed to the full install to import the inverse kinematic results from OpenSim. See instructionsthere.https://github.com/perfanalytics/pose2sim/assets/54667644/5d7c858f-7e46-40c1-928c-571a5679633aDemonstration Part-4 (optional): Try multi-person analysisAnother person, hidden all along, will appear when multi-person analysis is activated!Go to the Multi-participant Demo folder:cd <path>\pose2sim\S00_Demo_Session\S00_P01_MultiParticipants.Typeipython, and try the following code:fromPose2SimimportPose2SimPose2Sim.personAssociation()Pose2Sim.triangulation()Pose2Sim.filtering()Pose2Sim.markerAugmentation()One .trc file per participant will be generated and stored in thepose-3ddirectory.You can then run OpenSim scaling and inverse kinematics for each resulting .trc file as inDemonstration Part-2.You can also visualize your results with Blender as inDemonstration Part-3.N.B.:Set[project]multi_person = truefor each trial that contains multiple persons.Set[triangulation]reorder_trc = trueif you need to run OpenSim and to match the generated .trc files with the static trials.Make sure that the order of[markerAugmentation]participant_heightandparticipant_massmatches the order of the static trials.N.B.:Note that in the case of our floating ghost participant, marker augmentation may worsen the results. SeeMarker augmentationfor instruction on when and when not to use it.Use on your own dataDeeper explanations and instructions are given below.N.B.: If a step is not relevant for your use case (synchronization, person association, marker augmentation...), you can skip it.Setting your project upGet ready for automatic batch processing.Retrieve the folder structureOpen a terminal, enterpip show pose2sim, report package location.Copy this path and docd <path>\pose2sim.Copy theS00_Demo_Sessionfolder wherever you like, and rename it as you wish.The rest of the tutorial will explain to you how to populate theCalibrationandvideosfolders, edit theConfig.tomlfiles, and run each Pose2Sim step.Batch processingEach session folder should follow aSession -> Participant -> Trialstructure, with aConfig.tomlfile in each of the directory levels:Session_s1         \Config.toml├── Calibration\ 
└── Participant_p1 \Config.toml└── Trial_t1   \Config.tomlRun Pose2Sim from theSessionfolder if you want to batch process the whole session, from theParticipantfolder if you want to batch process all the trials of a participant, or from theTrialfolder if you want to process a single trial. There should be oneCalibrationfolder per session.Global instructions are given in the Config.toml file of theSessionfolder, and can be altered for specificParticipantsorTrialsby uncommenting keys and their values in their respective Config.toml files.Try uncommenting[project]and setframe_range = [10,300]for a Participant for example, or uncomment[filtering.butterworth]and setcut_off_frequency = 10for a Trial.2D pose estimationEstimate 2D pose from images with Openpose or another pose estimation solution.N.B.: First film a short static pose that will be used for scaling the OpenSim model (A-pose for example), and then film your motions of interest.N.B.: Note that the names of your camera folders must follow the same order as in the calibration file, and end with '_json'.With OpenPose:The accuracy and robustness of Pose2Sim have been thoroughly assessed only with OpenPose, and especially with the BODY_25B model. Consequently, we recommend using this 2D pose estimation solution. SeeOpenPose repositoryfor installation and running.Open a command prompt in yourOpenPosedirectory.Launch OpenPose for eachvideosfolder:bin\OpenPoseDemo.exe --model_pose BODY_25B --video <PATH_TO_TRIAL_DIR>\videos\cam01.mp4 --write_json <PATH_TO_TRIAL_DIR>\pose\pose_cam01_jsonTheBODY_25B modelhas more accurate results than the standard BODY_25 one and has been extensively tested for Pose2Sim.You can also use theBODY_135 model, which allows for the evaluation of pronation/supination, wrist flexion, and wrist deviation.All other OpenPose models (BODY_25, COCO, MPII) are also supported.Make sure you modify theConfig.tomlfile accordingly.Use one of thejson_display_with_img.pyorjson_display_with_img.pyscripts (seeUtilities) if you want to display 2D pose detections.N.B.:OpenPose BODY_25B is the default 2D pose estimation model used in Pose2Sim. However, other skeleton models from other 2D pose estimation solutions can be used alternatively.With BlazePose (MediaPipe):Mediapipe BlazePoseis very fast, fully runs under Python, handles upside-down postures and wrist movements (but no subtalar ankle angles).However, it is less robust and accurate than OpenPose, and can only detect a single person.Use the scriptBlazepose_runsave.py(seeUtilities) to run BlazePose under Python, and store the detected coordinates in OpenPose (json) or DeepLabCut (h5 or csv) format:python -m Blazepose_runsave -i input_file -dJsType inpython -m Blazepose_runsave -hfor explanation on parameters.Make sure you changed thepose_modeland thetracked_keypointin theConfig.tomlfile.With DeepLabCut:If you need to detect specific points on a human being, an animal, or an object, you can also train your own model withDeepLabCut. In this case, Pose2Sim is used as an alternative toAniPose, but it may yield better results since 3D reconstruction takes confidence into account (seethis article).Train your DeepLabCut model and run it on your images or videos (more instruction on their repository)Translate the h5 2D coordinates to json files (withDLC_to_OpenPose.pyscript, seeUtilities):python -m DLC_to_OpenPose -i input_h5_fileEditpose.CUSTOMinConfig.toml, and edit the node IDs so that they correspond to the column numbers of the 2D pose file, starting from zero. Make sure you also changed thepose_modeland thetracked_keypoint.You can visualize your skeleton's hierarchy by changing pose_model to CUSTOM and writing these lines:config_path=r'path_to_Config.toml'importtoml,anytreeconfig=toml.load(config_path)pose_model=config.get('pose').get('pose_model')model=anytree.importer.DictImporter().import_(config.get('pose').get(pose_model))forpre,_,nodeinanytree.RenderTree(model):print(f'{pre}{node.name}id={node.id}')Create an OpenSim model if you need inverse kinematics.With AlphaPose:AlphaPoseis one of the main competitors of OpenPose, and its accuracy is comparable. As a top-down approach (unlike OpenPose which is bottom-up), it is faster on single-person detection, but slower on multi-person detection.All AlphaPose models are supported (HALPE_26, HALPE_68, HALPE_136, COCO_133, COCO, MPII). For COCO and MPII, AlphaPose must be run with the flag "--format cmu".Install and run AlphaPose on your videos (more instruction on their repository)Translate the AlphaPose single json file to OpenPose frame-by-frame files (withAlphaPose_to_OpenPose.pyscript, seeUtilities):python -m AlphaPose_to_OpenPose -i input_alphapose_json_fileMake sure you changed thepose_modeland thetracked_keypointin theConfig.tomlfile.Camera synchronizationCameras need to be synchronized, so that 2D points correspond to the same position across cameras.N.B.:Skip this step if your cameras are already synchronized.If your cameras are not natively synchronized, you can usethis script. This is still a draft, and will be updated in the future.Alternatively, use a flashlight or a clap to synchronize them. GoPro cameras can also be synchronized with a timecode, by GPS (outdoors) or with a remote control (slightly less reliable).Camera calibrationCalculate camera intrinsic properties and extrinsic locations and positions.Convert a preexisting calibration file, or calculate intrinsic and extrinsic parameters from scratch.\Open an Anaconda prompt or a terminal in aSession,Participant, orTrialfolder.Typeipython.fromPose2SimimportPose2SimPose2Sim.calibration()Output:Convert from Qualisys, Optitrack, Vicon, OpenCap, EasyMocap, or bioCVIf you already have a calibration file, setcalibration_typetype toconvertin yourConfig.tomlfile.FromQualisys:Export calibration to.qca.txtwithin QTM.Copy it in theCalibrationPose2Sim folder.setconvert_fromto 'qualisys' in yourConfig.tomlfile. Changebinning_factorto 2 if you film in 540p.FromOptitrack:Exporting calibration will be available in Motive 3.2. In the meantime:Calculate intrinsics with a board (see next section).Use their C++ APIto retrieve extrinsic properties. Translation can be copied as is in yourCalib.tomlfile, but TT_CameraOrientationMatrix first needs to beconverted to a Rodrigues vectorwith OpenCV. See instructionshere.Use theCalib.tomlfile as is and do not run Pose2Sim.calibration()FromVicon:Copy your.xcpVicon calibration file to the Pose2SimCalibrationfolder.setconvert_fromto 'vicon' in yourConfig.tomlfile. No other setting is needed.FromOpenCap:Copy your.pickleOpenCap calibration files to the Pose2SimCalibrationfolder.setconvert_fromto 'opencap' in yourConfig.tomlfile. No other setting is needed.FromEasyMocap:Copy yourintri.ymlandextri.ymlfiles to the Pose2SimCalibrationfolder.setconvert_fromto 'easymocap' in yourConfig.tomlfile. No other setting is needed.FrombioCV:Copy your bioCV calibration files (no extension) to the Pose2SimCalibrationfolder.setconvert_fromto 'biocv' in yourConfig.tomlfile. No other setting is needed.FromAniPoseorFreeMocap:Copy your.tomlcalibration file to the Pose2SimCalibrationfolder.Calibration can be skipped since Pose2Sim uses the sameAniposelibformat.Calculate from scratchCalculate calibration parameters with a checkerboard, with measurements on the scene, or automatically with detected keypoints.Take heart, it is not that complicated once you get the hang of it!N.B.:Try the calibration tool on the Demo by changingcalibration_typetocalculateinConfig.toml.For the sake of practicality, there are voluntarily few board images for intrinsic calibration, and few points to click for extrinsic calibration. In spite of this, your reprojection error should be under 1-2 cm, whichdoes not hinder the quality of kinematic results in practice.).Calculate intrinsic parameters with a checkerboard:N.B.:Intrinsic parameters:camera properties (focal length, optical center, distortion), usually need to be calculated only once in their lifetime. In theory, cameras with same model and same settings will have identical intrinsic parameters.N.B.:If you already calculated intrinsic parameters earlier, you can skip this step by settingoverwrite_intrinsicsto false.Create a folder for each camera in yourCalibration\intrinsicsfolder.For each camera, film a checkerboard or a charucoboard. Either the board or the camera can be moved.Adjust parameters in theConfig.tomlfile.Make sure that the board:is filmed from different angles, covers a large part of the video frame, and is in focus.is flat, without reflections, surrounded by a white border, and is not rotationally invariant (Nrows ≠ Ncols, and Nrows odd if Ncols even).A common error is to specify the external, instead of the internal number of corners. This may be one less than you would intuitively think.Intrinsic calibration error should be below 0.5 px.Calculate extrinsic parameters:N.B.:Extrinsic parameters:camera placement in space (position and orientation), need to be calculated every time a camera is moved. Can be calculated from a board, or from points in the scene with known coordinates.N.B.:If there is no measurable item in the scene, you can temporarily bring something in (a table, for example), perform calibration, and then remove it before you start capturing motion.Create a folder for each camera in yourCalibration\extrinsicsfolder.Once your cameras are in place, shortly film either a board laid on the floor, or the raw scene(only one frame is needed, but do not just take a photo unless you are sure it does not change the image format).Adjust parameters in theConfig.tomlfile.Then,With a checkerboard:Make sure that it is seen by all cameras.It should preferably be larger than the one used for intrinsics, as results will not be very accurate out of the covered zone.With scene measurements(more flexible and potentially more accurate if points are spread out):Manually measure the 3D coordinates of 10 or more points in the scene (tiles, lines on wall, boxes, treadmill dimensions...). These points should be as spread out as possible. Replaceobject_coords_3dby these coordinates in Config.toml.Then you will click on the corresponding image points for each view.With keypoints:For a more automatic calibration, OpenPose keypoints could also be used for calibration.COMING SOON!Extrinsic calibration error should be below 1 cm, but depending on your application, results will still be potentially acceptable up to 2.5 cm.Tracking, Triangulating, FilteringAssociate persons across camerasTrack the person viewed by the most cameras, in case of several detections by OpenPose.N.B.:Skip this step if only one person is in the field of view.Want to contribute?Allow for multiple person analysis.Open an Anaconda prompt or a terminal in aSession,Participant, orTrialfolder.Typeipython.fromPose2SimimportPose2SimPose2Sim.personAssociation()Check printed output. If results are not satisfying, try and release the constraints in theConfig.tomlfile.Output:Triangulating keypointsTriangulate your 2D coordinates in a robust way.The triangulation is weighted by the likelihood of each detected 2D keypoint, provided that they meet a likelihood threshold.If the reprojection error is above a threshold, right and left sides are swapped; if it is still above, cameras are removed until the threshold is met. If more cameras are removed than threshold, triangulation is skipped for this point and this frame. In the end, missing values are interpolated.Open an Anaconda prompt or a terminal in aSession,Participant, orTrialfolder.Typeipython.fromPose2SimimportPose2SimPose2Sim.triangulation()Check printed output, and visualize your trc in OpenSim:File -> Preview experimental data.If your triangulation is not satisfying, try and release the constraints in theConfig.tomlfile.Output:Filtering 3D coordinatesFilter your 3D coordinates.Numerous filter types are provided, and can be tuned accordingly.\Open an Anaconda prompt or a terminal in aSession,Participant, orTrialfolder.Typeipython.fromPose2SimimportPose2SimPose2Sim.filtering()Check your filtration with the displayed figures, and visualize your .trc file in OpenSim. If your filtering is not satisfying, try and change the parameters in theConfig.tomlfile.Output:Marker AugmentationUse the Stanford LSTM model to estimate the position of 47 virtual markers.Note that inverse kinematic results are not necessarily better after marker augmentation.Skip if results are not convincing.Make sure thatparticipant_heightis correct in yourConfig.tomlfile.participant_massis mostly optional for IK.Only works with models estimating at least the following keypoints (e.g., not COCO):["Neck","RShoulder","LShoulder","RHip","LHip","RKnee","LKnee","RAnkle","LAnkle","RHeel","LHeel","RSmallToe","LSmallToe","RBigToe","LBigToe","RElbow","LElbow","RWrist","LWrist"]Will not work properly if missing values are not interpolated (i.e., if there are Nan value in the .trc file).Open an Anaconda prompt or a terminal in aSession,Participant, orTrialfolder.Typeipython.fromPose2SimimportPose2SimPose2Sim.markerAugmentation()N.B.:Again, use marker augmentation with good care, as results are worse than without in about half of the cases.Marker augmentation tends to give a more stable, but less precise output. In practice, it is mostly beneficial when using less than 4 cameras.OpenSim kinematicsObtain 3D joint angles.Your OpenSim .osim scaled model and .mot inverse kinematic results will be found in the OpenSim folder of yourParticipantdirectory.OpenSim ScalingUse the previous steps to capture a static pose, typically an A-pose or a T-pose.Open OpenSim.Open the providedModel_Pose2Sim_LSTM.osimmodel fromPose2Sim/OpenSim_Setup.(File -> Open Model)Load the providedScaling_Setup_Pose2Sim_LSTM.xmlscaling file.(Tools -> Scale model -> Load)Replace the example static .trc file with your own data.RunSave the new scaled OpenSim model.OpenSim Inverse kinematicsUse Pose2Sim to generate 3D trajectories.Open OpenSim.Load the providedIK_Setup_Pose2Sim_LSTM.xmlscaling file fromPose2Sim/OpenSim_Setup.(Tools -> Inverse kinematics -> Load)Replace the example .trc file with your own data, and specify the path to your angle kinematics output file.Run.Command lineAlternatively, you can use command-line tools:Open an Anaconda terminal in your OpenSim/bin directory, typicallyC:\OpenSim <Version>\bin.You'll need to adjust thetime_range,output_motion_file, and enter the full paths to the input and output.osim,.trc, and.motfiles in your setup file.opensim-cmd run-tool <PATH TO YOUR SCALING OR IK SETUP FILE>.xmlYou can also run OpenSim directly in Python:importsubprocesssubprocess.call(["opensim-cmd","run-tool",r"<PATH TO YOUR SCALING OR IK SETUP FILE>.xml"])Or take advantage of the full the OpenSim Python API. Seetherefor installation instructions (conda install may take a while).Make sure to replacepy38np120with your Python version (3.8 in this case) and with your numpy version (1.20 here).conda install -c opensim-org opensim-moco=4.4=py38np120 -yIf you run into a DLL error while importing opensim, open the file<Pose2Sim-env>\Lib\opensim\__init__.pyand replacecondabyconda-metaline 4.<Pose2Sim-env>location can be found withconda env list.Then run:ipythonimportopensimopensim.ScaleTool("<PATH TO YOUR SCALING OR IK SETUP FILE>.xml").run()opensim.InverseKinematicsTool("<PATH TO YOUR SCALING OR IK SETUP FILE>.xml").run()You can also run other API commands. Seetherefor more instructions on how to use it.UtilitiesA list of standalone tools (seeUtilities), which can be either run as scripts, or imported as functions. Check usage in the docstrings of each Python file. The figure below shows how some of these toolscan be used to further extend Pose2Sim usage.Converting calibration files(CLICK TO SHOW)Blazepose_runsave.pyRuns BlazePose on a video, and saves coordinates in OpenPose (json) or DeepLabCut (h5 or csv) format.DLC_to_OpenPose.pyConverts a DeepLabCut (h5) 2D pose estimation file into OpenPose (json) files.AlphaPose_to_OpenPose.pyConverts AlphaPose single json file to OpenPose frame-by-frame files.calib_from_checkerboard.pyCalibrates cameras with images or a video of a checkerboard, saves calibration in a Pose2Sim .toml calibration file.
You should probably use Pose2Sim.calibration() instead, which is much easier and better.calib_qca_to_toml.pyConverts a Qualisys .qca.txt calibration file to the Pose2Sim .toml calibration file (similar to what is used inAniPose).calib_toml_to_qca.pyConverts a Pose2Sim .toml calibration file (e.g., from a checkerboard) to a Qualisys .qca.txt calibration file.calib_easymocap_to_toml.pyConverts EasyMocap intrinsic and extrinsic .yml calibration files to an OpenCV .toml calibration file.calib_toml_to_easymocap.pyConverts an OpenCV .toml calibration file to EasyMocap intrinsic and extrinsic .yml calibration files.calib_toml_to_opencap.pyConverts an OpenCV .toml calibration file to OpenCap .pickle calibration files.calib_toml_to_opencap.pyTo convert OpenCap calibration tiles to a .toml file, please use Pose2Sim.calibration() and set convert_from = 'opencap' in Config.toml.Plotting tools(CLICK TO SHOW)json_display_with_img.pyOverlays 2D detected json coordinates on original raw images. High confidence keypoints are green, low confidence ones are red.json_display_without_img.pyPlots an animation of 2D detected json coordinates.trc_plot.pyDisplays X, Y, Z coordinates of each 3D keypoint of a TRC file in a different matplotlib tab.Other trc tools(CLICK TO SHOW)c3d_to_trc.pyConverts 3D point data of a .c3d file to a .trc file compatible with OpenSim. No analog data (force plates, emg) nor computed data (angles, powers, etc.) are retrieved.trc_desample.pyUndersamples a trc file.trc_Zup_to_Yup.pyChanges Z-up system coordinates to Y-up system coordinates.trc_filter.pyFilters trc files. Available filters: Butterworth, Kalman, Butterworth on speed, Gaussian, LOESS, Median.trc_gaitevents.pyDetects gait events from point coordinates according toZeni et al. (2008).trc_combine.pyCombine two trc files, for example a triangulated DeepLabCut trc file and a triangulated OpenPose trc file.trc_from_mot_osim.pyBuild a trc file from a .mot motion file and a .osim model file.bodykin_from_mot_osim.pyConverts a mot file to a .csv file with rotation and orientation of all segments.reproj_from_trc_calib.pyReprojects 3D coordinates of a trc file to the image planes defined by a calibration file. Output in OpenPose or DeepLabCut format.How to cite and how to contributeHow to citeIf you use this code or data, please citePagnon et al., 2022b,Pagnon et al., 2022a, orPagnon et al., 2021.@Article{Pagnon_2022_JOSS, 
  AUTHOR = {Pagnon, David and Domalain, Mathieu and Reveret, Lionel}, 
  TITLE = {Pose2Sim: An open-source Python package for multiview markerless kinematics}, 
  JOURNAL = {Journal of Open Source Software}, 
  YEAR = {2022},
  DOI = {10.21105/joss.04362}, 
  URL = {https://joss.theoj.org/papers/10.21105/joss.04362}
 }

@Article{Pagnon_2022_Accuracy,
  AUTHOR = {Pagnon, David and Domalain, Mathieu and Reveret, Lionel},
  TITLE = {Pose2Sim: An End-to-End Workflow for 3D Markerless Sports Kinematics—Part 2: Accuracy},
  JOURNAL = {Sensors},
  YEAR = {2022},
  DOI = {10.3390/s22072712},
  URL = {https://www.mdpi.com/1424-8220/22/7/2712}
}

@Article{Pagnon_2021_Robustness,
  AUTHOR = {Pagnon, David and Domalain, Mathieu and Reveret, Lionel},
  TITLE = {Pose2Sim: An End-to-End Workflow for 3D Markerless Sports Kinematics—Part 1: Robustness},
  JOURNAL = {Sensors},
  YEAR = {2021},
  DOI = {10.3390/s21196530},
  URL = {https://www.mdpi.com/1424-8220/21/19/6530}
}How to contribute and to-do listI would happily welcome any proposal for new features, code improvement, and more!If you want to contribute to Pose2Sim, please seethis issue.You will be proposed a to-do list, but please feel absolutely free to propose your own ideas and improvements.Main to-do listGraphical User InterfaceMultiple person triangulationSynchronizationSelf-calibration based on keypoint detectionDetailed GOT-DONE and TO-DO list(CLICK TO SHOW)✔Pose:Support OpenPosebody_25bfor more accuracy,body_135for pronation/supination.
✔Pose:SupportBlazePosefor faster inference (on mobile device).
✔Pose:SupportDeepLabCutfor training on custom datasets.
✔Pose:SupportAlphaPoseas an alternative to OpenPose.
✔Pose:Define custom model in config.toml rather than in skeletons.py.
▢Pose:SupportMMPose,SLEAP, etc.
▢Pose:Directly reading from DeepLabCut .csv or .h5 files instead of converting to .json (triangulation, person association, calibration, synchronization...)
▢Pose:GUI help for DeepLabCut model creation.✔Calibration:ConvertQualisys.qca.txt calibration file.
✔Calibration:ConvertOptitrackextrinsic calibration file.
✔Calibration:ConvertVicon.xcp calibration file.
✔Calibration:ConvertOpenCap.pickle calibration files.
✔Calibration:ConvertEasyMocap.yml calibration files.
✔Calibration:ConvertbioCVcalibration files.
✔Calibration:Easier and clearer calibration procedure: separate intrinsic and extrinsic parameter calculation, edit corner detection if some are wrongly detected (or not visible).
✔Calibration:Possibility to evaluate extrinsic parameters from cues on scene.
▢Calibration:Once object points have been detected or clicked once, track them for live calibration of moving cameras. Propose to click again when they are lost.
▢Calibration:Calibrate cameras by pairs and compute average extrinsic calibration withaniposelib.
▢Calibration:Fine-tune calibration with bundle adjustment.
▢Calibration:Support ChArUco board detection (seethere).
▢Calibration:Calculate calibration with points rather than board. (1) SBA calibration with wand (cfArgus, see converterhere). Set world reference frame in the end.
▢Calibration:Alternatively, self-calibrate withOpenPose keypoints. Set world reference frame in the end.
▢Calibration:ConvertfSpy calibrationbased on vanishing point.▢Synchronization:Synchronize cameras on 2D keypoint speeds. Cfthis draft script.✔Person Association:Automatically choose the main person to triangulate.
✔Person Association:Multiple persons association. 1. Triangulate all the persons whose reprojection error is below a certain threshold (instead of only the one with minimum error), and then track in time with speed cfSlembrouck 2020? or 2. Based on affinity matricesDong 2021? or 3. Based on occupancy mapsYildiz 2012? or 4. With a neural networkHuang 2023?✔Triangulation:Triangulation weighted with confidence.
✔Triangulation:Set a likelihood threshold below which a camera should not be used, a reprojection error threshold, and a minimum number of remaining cameras below which triangulation is skipped for this frame.
✔Triangulation:Interpolate missing frames (cubic, bezier, linear, slinear, quadratic)
✔Triangulation:Show mean reprojection error in px and in mm for each keypoint.
✔Triangulation:Show how many cameras on average had to be excluded for each keypoint.
✔Triangulation:Evaluate which cameras were the least reliable.
✔Triangulation:Show which frames had to be interpolated for each keypoint.
✔Triangulation:Solve limb swapping (although not really an issue with Body_25b). Try triangulating with opposite side if reprojection error too large. Alternatively, ignore right and left sides, use RANSAC or SDS triangulation, and then choose right or left by majority voting. More confidence can be given to cameras whose plane is the most coplanar to the right/left line.
✔Triangulation:Undistort2D points before triangulating (anddistortthem before computing reprojection error).
✔Triangulation:Offer the possibility to augment the triangulated data withthe OpenCap LSTM. Create "BODY_25_AUGMENTED" model, Scaling_setup, IK_Setup.
✔Triangulation:Multiple person kinematics (output multiple .trc coordinates files). Triangulate all persons with reprojection error above threshold, and identify them by minimizing their displacement across frames.
▢Triangulation:Pre-compile weighted_triangulation and reprojection with @jit(nopython=True, parallel=True) for faster execution.
▢Triangulation:Offer the possibility of triangulating with Sparse Bundle Adjustment (SBA), Extended Kalman Filter (EKF), Full Trajectory Estimation (FTE) (seeAcinoSet).
▢Triangulation:Implement normalized DLT and RANSAC triangulation, Outlier rejection (sliding z-score?), as well as atriangulation refinement step.
▢Triangulation:Track hands and face (won't be taken into account in OpenSim at this stage).✔Filtering:Available filtering methods: Butterworth, Butterworth on speed, Gaussian, Median, LOESS (polynomial smoothing).
✔Filtering:Implement Kalman filter and Kalman smoother.
▢Filtering:ImplementsmoothNet✔OpenSim:Integrate better spine fromlifting fullbody modelto thegait full-body model, more accurate for the knee.
✔OpenSim:Optimize model marker positions as compared to ground-truth marker-based positions.
✔OpenSim:Add scaling and inverse kinematics setup files.
✔OpenSim:Add full model with contact spheres (SmoothSphereHalfSpaceForce) and full-body muscles (DeGrooteFregly2016Muscle), forMocofor example.
✔OpenSim:Add model withISB shoulder.
▢OpenSim:Implement optimal fixed-interval Kalman smoothing for inverse kinematics (this OpenSim fork), orBiorbd)✔GUI:Blender add-on (cfMPP2SOS), or webapp (e.g., withNapari. See my draft projectMaya-MocapandBlendOsim.
▢GUI:3D plot of cameras and of triangulated keypoints.
▢GUI:Demo on Google Colab (seeSports2Dfor OpenPose and Python package installation on Google Drive).✔Demo:Provide Demo data for users to test the code.
▢Demo:Add videos for users to experiment with other pose detection frameworks
▢Demo:Time shift videos and json to demonstrate synchronization
▢Demo:Add another virtual person to demonstrate personAssociation
▢Tutorials:Make video tutorials.
▢Doc:UseSphinx,MkDocs, or (maybe better),github.iofor clearer documentation.▢Catch errors✔Pip package▢Batch processing▢Conda package▢Docker image▢ Run pose estimation and OpenSim from within Pose2Sim
▢Run from command line via click or typer▢Utilities: Export other data from c3d files into .mot or .sto files (angles, powers, forces, moments, GRF, EMG...)
▢Utilities: Create trc_to_c3d.py script✔Bug:calibration.py. FFMPEG error message when calibration files are images. Seethere.
▢Bug:common.py, class plotWindow(). Python crashes after a few runs ofPose2Sim.filtering()whendisplay_figures=true. Seethere.Acknowledgements:Supervised my PhD:@lreveret(INRIA, Université Grenoble Alpes), and@mdomalai(Université de Poitiers).Provided the Demo data:@aaiaueilfrom Université Gustave Eiffel.Tested the code and provided feedback:@simonozan,@daeyongyang,@ANaaim,@rlagnsalsSubmitted various accepted pull requests:@ANaaim,@rlagnsalsProvided a code snippet for Optitrack calibration:@claraaudap(Université Bretagne Sud).Issued MPP2SOS, a (non-free) Blender extension based on Pose2Sim:@carlosedubarretoBSD 3-Clause LicenseCopyright (c) 2022, perfanalytics
All rights reserved.Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.