Compare commits

...

5 Commits

Author SHA1 Message Date
David PAGNON
4a06ee3a6c
add 5% margin in bboxes 2024-11-22 14:47:20 +01:00
David PAGNON
cde7eaa6e3
fixed id in dataset_to_mmpose2d 2024-11-22 00:43:37 +01:00
davidpagnon
116b8f0791 Merge branch 'main' of https://github.com/perfanalytics/pose2sim 2024-11-20 20:51:33 +01:00
davidpagnon
890ac14eb9 realizePosition instead of assemble for faster computation 2024-11-20 20:51:25 +01:00
HunMinKim
cdec5cca45
LSTM with wrist motion (#148)
* LSTM with wrist motion

* remove tab
2024-11-18 05:24:55 +01:00
5 changed files with 123 additions and 23 deletions

View File

@ -276,6 +276,42 @@
<!--Weight given to a marker or coordinate for solving inverse kinematics problems.--> <!--Weight given to a marker or coordinate for solving inverse kinematics problems.-->
<weight>25</weight> <weight>25</weight>
</IKMarkerTask> </IKMarkerTask>
<IKMarkerTask name="RThumb">
<!--Whether or not this task will be used during inverse kinematics solve, default is true.-->
<apply>true</apply>
<!--Weight given to the task when solving inverse kinematics problems, default is 0.-->
<weight>1</weight>
</IKMarkerTask>
<IKMarkerTask name="RIndex">
<!--Whether or not this task will be used during inverse kinematics solve, default is true.-->
<apply>true</apply>
<!--Weight given to the task when solving inverse kinematics problems, default is 0.-->
<weight>1</weight>
</IKMarkerTask>
<IKMarkerTask name="RPinky">
<!--Whether or not this task will be used during inverse kinematics solve, default is true.-->
<apply>true</apply>
<!--Weight given to the task when solving inverse kinematics problems, default is 0.-->
<weight>1</weight>
</IKMarkerTask>
<IKMarkerTask name="LThumb">
<!--Whether or not this task will be used during inverse kinematics solve, default is true.-->
<apply>true</apply>
<!--Weight given to the task when solving inverse kinematics problems, default is 0.-->
<weight>1</weight>
</IKMarkerTask>
<IKMarkerTask name="LIndex">
<!--Whether or not this task will be used during inverse kinematics solve, default is true.-->
<apply>true</apply>
<!--Weight given to the task when solving inverse kinematics problems, default is 0.-->
<weight>1</weight>
</IKMarkerTask>
<IKMarkerTask name="LPinky">
<!--Whether or not this task will be used during inverse kinematics solve, default is true.-->
<apply>true</apply>
<!--Weight given to the task when solving inverse kinematics problems, default is 0.-->
<weight>1</weight>
</IKMarkerTask>
<IKCoordinateTask name="sh_tx_l"> <IKCoordinateTask name="sh_tx_l">
<!--Whether or not this task will be used during inverse kinematics solve, default is true.--> <!--Whether or not this task will be used during inverse kinematics solve, default is true.-->
<apply>true</apply> <apply>true</apply>

View File

@ -6229,7 +6229,7 @@
<!--Flag indicating whether or not the values of the coordinates should be limited to the range, above.--> <!--Flag indicating whether or not the values of the coordinates should be limited to the range, above.-->
<clamped>true</clamped> <clamped>true</clamped>
<!--Flag indicating whether or not the values of the coordinates should be constrained to the current (e.g. default) value, above.--> <!--Flag indicating whether or not the values of the coordinates should be constrained to the current (e.g. default) value, above.-->
<locked>true</locked> <locked>false</locked>
<!--If specified, the coordinate can be prescribed by a function of time. It can be any OpenSim Function with valid second order derivatives.--> <!--If specified, the coordinate can be prescribed by a function of time. It can be any OpenSim Function with valid second order derivatives.-->
<prescribed_function /> <prescribed_function />
<!--Flag indicating whether or not the values of the coordinates should be prescribed according to the function above. It is ignored if the no prescribed function is specified.--> <!--Flag indicating whether or not the values of the coordinates should be prescribed according to the function above. It is ignored if the no prescribed function is specified.-->
@ -6245,7 +6245,7 @@
<!--Flag indicating whether or not the values of the coordinates should be limited to the range, above.--> <!--Flag indicating whether or not the values of the coordinates should be limited to the range, above.-->
<clamped>true</clamped> <clamped>true</clamped>
<!--Flag indicating whether or not the values of the coordinates should be constrained to the current (e.g. default) value, above.--> <!--Flag indicating whether or not the values of the coordinates should be constrained to the current (e.g. default) value, above.-->
<locked>true</locked> <locked>false</locked>
<!--If specified, the coordinate can be prescribed by a function of time. It can be any OpenSim Function with valid second order derivatives.--> <!--If specified, the coordinate can be prescribed by a function of time. It can be any OpenSim Function with valid second order derivatives.-->
<prescribed_function /> <prescribed_function />
<!--Flag indicating whether or not the values of the coordinates should be prescribed according to the function above. It is ignored if the no prescribed function is specified.--> <!--Flag indicating whether or not the values of the coordinates should be prescribed according to the function above. It is ignored if the no prescribed function is specified.-->
@ -6735,7 +6735,7 @@
<!--Flag indicating whether or not the values of the coordinates should be limited to the range, above.--> <!--Flag indicating whether or not the values of the coordinates should be limited to the range, above.-->
<clamped>true</clamped> <clamped>true</clamped>
<!--Flag indicating whether or not the values of the coordinates should be constrained to the current (e.g. default) value, above.--> <!--Flag indicating whether or not the values of the coordinates should be constrained to the current (e.g. default) value, above.-->
<locked>true</locked> <locked>false</locked>
<!--If specified, the coordinate can be prescribed by a function of time. It can be any OpenSim Function with valid second order derivatives.--> <!--If specified, the coordinate can be prescribed by a function of time. It can be any OpenSim Function with valid second order derivatives.-->
<prescribed_function /> <prescribed_function />
<!--Flag indicating whether or not the values of the coordinates should be prescribed according to the function above. It is ignored if the no prescribed function is specified.--> <!--Flag indicating whether or not the values of the coordinates should be prescribed according to the function above. It is ignored if the no prescribed function is specified.-->
@ -6751,7 +6751,7 @@
<!--Flag indicating whether or not the values of the coordinates should be limited to the range, above.--> <!--Flag indicating whether or not the values of the coordinates should be limited to the range, above.-->
<clamped>true</clamped> <clamped>true</clamped>
<!--Flag indicating whether or not the values of the coordinates should be constrained to the current (e.g. default) value, above.--> <!--Flag indicating whether or not the values of the coordinates should be constrained to the current (e.g. default) value, above.-->
<locked>true</locked> <locked>false</locked>
<!--If specified, the coordinate can be prescribed by a function of time. It can be any OpenSim Function with valid second order derivatives.--> <!--If specified, the coordinate can be prescribed by a function of time. It can be any OpenSim Function with valid second order derivatives.-->
<prescribed_function /> <prescribed_function />
<!--Flag indicating whether or not the values of the coordinates should be prescribed according to the function above. It is ignored if the no prescribed function is specified.--> <!--Flag indicating whether or not the values of the coordinates should be prescribed according to the function above. It is ignored if the no prescribed function is specified.-->
@ -7477,7 +7477,69 @@
<location>-0.056276 -0.078490000000000004 -0.077259999999999995</location> <location>-0.056276 -0.078490000000000004 -0.077259999999999995</location>
<!--Flag (true or false) specifying whether the marker is fixed in its parent frame during the marker placement step of scaling. If false, the marker is free to move within its parent Frame to match its experimental counterpart.--> <!--Flag (true or false) specifying whether the marker is fixed in its parent frame during the marker placement step of scaling. If false, the marker is free to move within its parent Frame to match its experimental counterpart.-->
<fixed>false</fixed> <fixed>false</fixed>
</Marker> </Marker>
<Marker name="RThumb">
<!--Path to a Component that satisfies the Socket 'parent_frame' of type PhysicalFrame (description: The frame to which this station is fixed.).-->
<socket_parent_frame>/bodyset/hand_r</socket_parent_frame>
<!--The fixed location of the station expressed in its parent frame.-->
<location>0.015900600000000001 -0.053530099999999997 0.045219599999999999</location>
</Marker>
<Marker name="RIndex">
<!--Path to a Component that satisfies the Socket 'parent_frame' of type PhysicalFrame (description: The frame to which this station is fixed.).-->
<socket_parent_frame>/bodyset/hand_r</socket_parent_frame>
<!--The fixed location of the station expressed in its parent frame.-->
<location>0.0031182900000000001 -0.082610900000000001 0.0160293</location>
</Marker>
<Marker name="RPinky">
<!--Path to a Component that satisfies the Socket 'parent_frame' of type PhysicalFrame (description: The frame to which this station is fixed.).-->
<socket_parent_frame>/bodyset/hand_r</socket_parent_frame>
<!--The fixed location of the station expressed in its parent frame.-->
<location>0.00311312 -0.073810299999999995 -0.0325446</location>
</Marker>
<Marker name="LThumb">
<!--Path to a Component that satisfies the Socket 'parent_frame' of type PhysicalFrame (description: The frame to which this station is fixed.).-->
<socket_parent_frame>/bodyset/hand_l</socket_parent_frame>
<!--The fixed location of the station expressed in its parent frame.-->
<location>0.015900595366914239 -0.053530050744837965 -0.045219604622807212</location>
</Marker>
<Marker name="LIndex">
<!--Path to a Component that satisfies the Socket 'parent_frame' of type PhysicalFrame (description: The frame to which this station is fixed.).-->
<socket_parent_frame>/bodyset/hand_l</socket_parent_frame>
<!--The fixed location of the station expressed in its parent frame.-->
<location>0.0031182929587494357 -0.082610892492083754 -0.016029259621825068</location>
</Marker>
<Marker name="LPinky">
<!--Path to a Component that satisfies the Socket 'parent_frame' of type PhysicalFrame (description: The frame to which this station is fixed.).-->
<socket_parent_frame>/bodyset/hand_l</socket_parent_frame>
<!--The fixed location of the station expressed in its parent frame.-->
<location>0.0031131181410346542 -0.073810317144973658 0.032544599634169884</location>
<!--Flag (true or false) specifying whether the marker is fixed in its parent frame during the marker placement step of scaling. If false, the marker is free to move within its parent Frame to match its experimental counterpart.-->
<fixed>false</fixed>
</Marker>
<Marker name="Nose">
<!--Path to a Component that satisfies the Socket 'parent_frame' of type PhysicalFrame (description: The frame to which this station is fixed.).-->
<socket_parent_frame>/bodyset/head</socket_parent_frame>
<!--The fixed location of the station expressed in its parent frame.-->
<location>0.107623784338859 0.54290490722614126 0.0001528854696219647</location>
<!--Flag (true or false) specifying whether the marker is fixed in its parent frame during the marker placement step of scaling. If false, the marker is free to move within its parent Frame to match its experimental counterpart.-->
<fixed>true</fixed>
</Marker>
<Marker name="REye">
<!--Path to a Component that satisfies the Socket 'parent_frame' of type PhysicalFrame (description: The frame to which this station is fixed.).-->
<socket_parent_frame>/bodyset/head</socket_parent_frame>
<!--The fixed location of the station expressed in its parent frame.-->
<location>0.070157181776970542 0.55784285717609527 0.031106947145128013</location>
<!--Flag (true or false) specifying whether the marker is fixed in its parent frame during the marker placement step of scaling. If false, the marker is free to move within its parent Frame to match its experimental counterpart.-->
<fixed>true</fixed>
</Marker>
<Marker name="LEye">
<!--Path to a Component that satisfies the Socket 'parent_frame' of type PhysicalFrame (description: The frame to which this station is fixed.).-->
<socket_parent_frame>/bodyset/head</socket_parent_frame>
<!--The fixed location of the station expressed in its parent frame.-->
<location>0.070157200000000003 0.55784299999999998 -0.0311069</location>
<!--Flag (true or false) specifying whether the marker is fixed in its parent frame during the marker placement step of scaling. If false, the marker is free to move within its parent Frame to match its experimental counterpart.-->
<fixed>true</fixed>
</Marker>
</objects> </objects>
<groups /> <groups />
</MarkerSet> </MarkerSet>

View File

@ -123,8 +123,9 @@ def bodykin_from_mot_osim_func(*args):
model.getCoordinateSet().get(coord).setValue(state, motion_data_np[n,c], enforceContraints=False) model.getCoordinateSet().get(coord).setValue(state, motion_data_np[n,c], enforceContraints=False)
except: except:
pass pass
model.assemble(state) # model.assemble(state)
model.realizePosition(state) # much faster (IK already done, no need to compute it again)
# Use state of model to get body coordinates in ground # Use state of model to get body coordinates in ground
loc_rot_frame = [] loc_rot_frame = []
for b in bodies: for b in bodies:

View File

@ -56,7 +56,7 @@ biocvplus_markers = ['ACROM_R', 'ACROM_L', 'C7', 'T10', 'CLAV', 'XIP_PROC', 'UA_
## FUNCTIONS ## FUNCTIONS
def str_to_id(string, length=8): def str_to_id(string, length=12):
''' '''
Convert a string to an integer id Convert a string to an integer id
''' '''
@ -285,12 +285,6 @@ def dataset_to_mmpose2d(coords_df, mmpose_json_file, img_size, markerset='custom
- labels2d_json: saved json file - labels2d_json: saved json file
''' '''
# transform first name in integer, and append other numbers from persons
persons = list(set(['_'.join(item.split('_')[:5]) for item in coords_df.columns.levels[1]]))
person_ids = [int(str(str_to_id(p.split('_')[1])) + ''.join(p.split('_')[3:])) if len(p.split('_'))>=3
else str_to_id(p.split('_')[0])
for p in persons]
labels2d_json_data = {} labels2d_json_data = {}
labels2d_json_data['info'] = {'description': f'Bedlam Pose {markerset}', labels2d_json_data['info'] = {'description': f'Bedlam Pose {markerset}',
'url': 'https://github.com/davidpagnon/bedlam_pose', 'url': 'https://github.com/davidpagnon/bedlam_pose',
@ -303,14 +297,14 @@ def dataset_to_mmpose2d(coords_df, mmpose_json_file, img_size, markerset='custom
labels2d_json_data['images'] = [] labels2d_json_data['images'] = []
labels2d_json_data['annotations'] = [] labels2d_json_data['annotations'] = []
labels2d_json_data['categories'] = [{'id': 1, 'name': 'person'}] labels2d_json_data['categories'] = [{'id': 1, 'name': 'person'}]
padding = 0.05
# for each image # for each image
persons = list(set(['_'.join(item.split('_')[:5]) for item in coords_df.columns.levels[1]]))
for i in range(len(coords_df)): for i in range(len(coords_df)):
file_name = coords_df.index[i] file_name = coords_df.index[i][0]
w, h = img_size w, h = int(img_size[0]), int(img_size[1])
# id from concatenation of numbers from path file_id = str_to_id(file_name, length=12)
# file_id = int(''.join(re.findall(r'\d+', str(file_name))))
file_id = int(hashlib.md5(file_name.encode()).hexdigest(), 16) % (10**12) # Keep only 12 digits
labels2d_json_data['images'] += [{'file_name': file_name, labels2d_json_data['images'] += [{'file_name': file_name,
'height': h, 'height': h,
@ -319,7 +313,8 @@ def dataset_to_mmpose2d(coords_df, mmpose_json_file, img_size, markerset='custom
'license': 1}] 'license': 1}]
# for each person # for each person
for p, person in enumerate(persons): for person in persons:
# store 2D keypoints and respect model keypoint order # store 2D keypoints and respect model keypoint order
coords = coords_df.iloc[i, coords_df.columns.get_level_values(1)==person] coords = coords_df.iloc[i, coords_df.columns.get_level_values(1)==person]
coords_list = [] coords_list = []
@ -338,8 +333,13 @@ def dataset_to_mmpose2d(coords_df, mmpose_json_file, img_size, markerset='custom
bbox_height = np.round(max_y - min_y, decimals=1) bbox_height = np.round(max_y - min_y, decimals=1)
# bbox = [min_x, min_y, max_x, max_y] # bbox = [min_x, min_y, max_x, max_y]
bbox = [min_x, min_y, bbox_width, bbox_height] # coco format bbox = [min_x, min_y, bbox_width, bbox_height] # coco format
# add padding
bbox = [min(0, min_x-bbox_width*padding),
min(0, min_y-bbox_height*padding),
bbox_width*(1+padding*2) if max_x+bbox_width*padding < w else bbox_width*(1+padding),
bbox_height*(1+padding*2) if max_y+bbox_height*padding < h else bbox_height*(1+padding)]
person_id = person_ids[p] ann_id = str_to_id(person+file_name)
category_id = 1 category_id = 1
segmentation = [[min_x, min_y, min_x, max_y, max_x, max_y, max_x, min_y]] # no segmentation segmentation = [[min_x, min_y, min_x, max_y, max_x, max_y, max_x, min_y]] # no segmentation
area = np.round(bbox_width * bbox_height, decimals=1) area = np.round(bbox_width * bbox_height, decimals=1)
@ -349,7 +349,7 @@ def dataset_to_mmpose2d(coords_df, mmpose_json_file, img_size, markerset='custom
labels2d_json_data['annotations'] += [{ 'keypoints': coords_list, labels2d_json_data['annotations'] += [{ 'keypoints': coords_list,
'num_keypoints': num_keypoints, 'num_keypoints': num_keypoints,
'bbox': bbox, 'bbox': bbox,
'id': person_id, 'id': ann_id,
'image_id': file_id, 'image_id': file_id,
'category_id': category_id, 'category_id': category_id,
'segmentation': segmentation, 'segmentation': segmentation,

View File

@ -81,7 +81,8 @@ def get_marker_positions(motion_data, model, in_degrees=True, marker_list=[]):
else: else:
value = motion_data_pd.loc[n,coord] value = motion_data_pd.loc[n,coord]
model.getCoordinateSet().get(coord).setValue(state,value, enforceContraints=False) model.getCoordinateSet().get(coord).setValue(state,value, enforceContraints=False)
model.assemble(state) # model.assemble(state)
model.realizePosition(state) # much faster (IK already done, no need to compute it again)
# get marker positions # get marker positions
marker_positions += [np.array([marker_set.get(mk_name).findLocationInFrame(state, model.getGround()).to_numpy() for mk_name in marker_set_names]).flatten()] marker_positions += [np.array([marker_set.get(mk_name).findLocationInFrame(state, model.getGround()).to_numpy() for mk_name in marker_set_names]).flatten()]
marker_positions_pd = pd.DataFrame(marker_positions, columns=marker_set_names_xyz) marker_positions_pd = pd.DataFrame(marker_positions, columns=marker_set_names_xyz)