import osimport subprocessimport globimport tempfilefrom IPython.display import Videoimport randomcurfolder = os.getcwd()# Openpose demo.exe locationopenposefol = os.path.join(curfolder, 'openpose')openpose_demo_loc = os.path.join(openposefol, 'bin', 'OpenPoseDemo.exe')# This is the model to employmodel_to_employ ='BODY_135'# List folders in a main folderfolderstotrack = glob.glob(os.path.join(curfolder, 'projectdata', '*'))# Get all folders per participant, per sessionpcnfolders = []for i in folderstotrack: pcnfolders_in_session = glob.glob(os.path.join(i, '*')) pcnfolders = pcnfolders + pcnfolders_in_session# There might be some other things we don't want nowpcnfolders = [x for x in pcnfolders if'Config'notin x]pcnfolders = [x for x in pcnfolders if'opensim'notin x]pcnfolders = [x for x in pcnfolders if'xml'notin x]pcnfolders = [x for x in pcnfolders if'ResultsInverseDynamics'notin x]pcnfolders = [x for x in pcnfolders if'ResultsInverseKinematics'notin x]pcnfolders = [x for x in pcnfolders if'sto'notin x]pcnfolders = [x for x in pcnfolders if'txt'notin x]pcnfolders = [x for x in pcnfolders if'calibration'notin x]print(pcnfolders[0:10])
Instead of running OpenPose in the notebook, we will send commands to the OpenPose executable as a subprocess. This is more efficient and allows us to run OpenPose in parallel for multiple videos.
Code to run OpenPose as a subprocess
def runcommand(command):''' Run a command in the command line. '''import subprocess# Run the command using subprocess for OPENPOSE TRACKINGtry: subprocess.run(command, shell=True, check=True)except subprocess.CalledProcessError as e:print(f"Command execution failed with error code {e.returncode}")exceptFileNotFoundError:print("The OpenPoseDemo.exe executable was not found.")
for i in pcnfolders: os.chdir(openposefol)print('working on '+ i)# Identify all avi files in folder direc = glob.glob(os.path.join(i, 'raw-2d', '*.avi'))# 3 cameras video0 = direc[0] video1 = direc[1] video2 = direc[2] videolist = [video0, video1, video2]# Make a new directory if it doesn't existifnot os.path.exists(os.path.join(i, 'pose')): os.makedirs(os.path.join(i, 'pose'))ifnot os.path.exists(os.path.join(i, 'pose', 'pose_cam1_json')): os.makedirs(os.path.join(i, 'pose', 'pose_cam1_json'))ifnot os.path.exists(os.path.join(i, 'pose', 'pose_cam2_json')): os.makedirs(os.path.join(i, 'pose', 'pose_cam2_json'))ifnot os.path.exists(os.path.join(i, 'pose', 'pose_cam3_json')): os.makedirs(os.path.join(i, 'pose', 'pose_cam3_json'))# Also make directory for openpose videos (pose-2d-trackingvideos)ifnot os.path.exists(os.path.join(i, 'pose-2d-trackingvideos')): os.makedirs(os.path.join(i, 'pose-2d-trackingvideos'))# if in trackingvideos are three videos, skip existingtrackingvideos = glob.glob(os.path.join(i, 'pose-2d-trackingvideos', '*.avi'))iflen(existingtrackingvideos) ==3:print('Skipping '+ i +' as tracking already exist')continue# Initialize the pose2 folder outputfol1 = os.path.join(i, 'pose', 'pose_cam1_json') outputfol2 = os.path.join(i, 'pose', 'pose_cam2_json') outputfol3 = os.path.join(i, 'pose', 'pose_cam3_json') outputfollist = [outputfol1, outputfol2, outputfol3]for it, j inenumerate(outputfollist):# Prepare the command openposelocation =' '+ openpose_demo_loc +' ' model ='--model_pose'+' '+ model_to_employ +' ' video ='--video '+ videolist[it] +' ' todo ='--write_json ' outputfol = j +' ' videoadd ='--write_video ' videopath = os.path.join(i, 'pose-2d-trackingvideos', 'video'+str(it)+'.avi') +' '# Send the command via subprocess command =r' '+openposelocation+model+video+todo+outputfol+videoadd+videopathprint('were going to send this to command prompt: '+ command) runcommand(command)
Now we check that all trials have been processed by checking the number of output videos (original videos with overlayed skeleton)
pcnfolders = []for i in folderstotrack: pcnfolders_in_session = glob.glob(os.path.join(i, '*'))# Append to the list pcnfolders = pcnfolders + pcnfolders_in_session# There might be some other things we don't want nowpcnfolders = [x for x in pcnfolders if'Config'notin x]pcnfolders = [x for x in pcnfolders if'opensim'notin x]pcnfolders = [x for x in pcnfolders if'xml'notin x]pcnfolders = [x for x in pcnfolders if'ResultsInverseDynamics'notin x]pcnfolders = [x for x in pcnfolders if'ResultsInverseKinematics'notin x]pcnfolders = [x for x in pcnfolders if'sto'notin x]pcnfolders = [x for x in pcnfolders if'txt'notin x]pcnfolders = [x for x in pcnfolders if'calibration'notin x]for i in pcnfolders: existingtrackingvideos = glob.glob(os.path.join(i, 'pose-2d-trackingvideos', '*.avi'))iflen(existingtrackingvideos) !=3:print('Warning: '+ i +' has '+str(len(existingtrackingvideos)) +' tracking videos.')
The results are saved in /pose folder in json format, and are used for triangulation via Pose2sim (Pagnon et al., 2022) in the next script.
The videos with the estimated poses are saved in the /pose-2d-trackingvideos folder
Here is an example of the output:
References
Cao, Z., Hidalgo, G., Simon, T., Wei, S.-E., & Sheikh, Y. (2019). OpenPose: Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields. https://doi.org/10.48550/arXiv.1812.08008
Pagnon, D., Domalain, M., & Reveret, L. (2022). Pose2Sim: An End-to-End Workflow for 3D Markerless Sports Kinematics—Part 2: Accuracy. Sensors, 22(7, 7), 2712. https://doi.org/10.3390/s22072712