Open AndreAhmed opened 1 month ago
tried the following also
measurer.measure(measurement_names)
new_height = 175
measurer.height_normalize_measurements(new_height)
measurer.label_measurements(STANDARD_LABELS)
# Add measurements to the result dictionary
results[min_idx]['result']['measurements'] = measurer.measurements
results[min_idx]['result']['labeled_measurements'] = measurer.labeled_measurements
Hi @AndreAhmed ,
Could you also provide the results for the updated height? Are the measurements now more accurate?
Note that the results you get from a single image might not necessarily reflect your actual body shape, especially with methods that are not state-of-the-art, such as "vanilla" Smplify-X. You have correctly identified the problem of scale ambiguity from a single image, hence, the inaccurate body height estimation.
The purpose of this repository is that, once you have an SMPL(-X) mesh, you can extract a set of body measurements. The purpose is not to serve as a tool for accurate body measurement estimation. In addition, the problem of single-view human shape estimation is still an active area of research.
For better estimation results, try SHAPY: https://shapy.is.tue.mpg.de.
@kristijanbartol Thanks for your quick input. But how about other measurements, like Waist, stomach,..etc? I assume they are fixed ?
All the measurements are extracted exactly as shown in the Figure you attached. You might say their definition is "fixed" w.r.t. SMPL(-X) meshes, yes. If you specify a different height, the mesh is scaled and so are the corresponding body measurements. Maybe I misunderstood your question...
@kristijanbartol I have tried to export the betas, but they are not reflecting the actual shape parameters. Is what I did wrong? I mean the exported body. So What I did is to export the json, and render the SMPLX in Unity3D, and attach the shape parameters, but the body is not exactly the same as the one you constructed for measurments, in terms of height, body size,..etc.
def export_smpl_data_for_unity(updated_length_definitions, body_model, body_pose, measurer, camera, result_fn='smpl_data_for_unity.json'):
# Extract SMPL keypoints (joints) and vertices
model_output = body_model(return_verts=True, body_pose=body_pose) # Run the body model
vertices = model_output.vertices.detach().cpu().numpy().squeeze()
faces = body_model.faces.astype(int)
betas = body_model.betas.detach().cpu().numpy().squeeze()
print("Available landmarks:")
for key, value in measurer.landmarks.items():
print(f"{key}: {value}")
# Extract landmarks and their corresponding vertex indices
landmarks = {}
landmark_to_vertex = {} # To map landmarks to their corresponding vertices
for landmark_name, landmark_index in measurer.landmarks.items():
if isinstance(landmark_index, tuple):
# If it's a tuple, take the average of the specified vertices
landmark_position = np.mean(vertices[list(landmark_index)], axis=0)
landmark_to_vertex[landmark_name] = list(landmark_index)
else:
landmark_position = vertices[landmark_index]
landmark_to_vertex[landmark_name] = [landmark_index]
# Convert landmark position to a dict with x, y, z keys
landmarks[landmark_name] = {
"x": float(landmark_position[0]),
"y": float(landmark_position[1]),
"z": float(landmark_position[2])
}
# Prepare measurement definitions
length_definitions = {}
for name, definition in updated_length_definitions.items():
valid_landmarks = [lm for lm in definition if lm in landmarks]
if len(valid_landmarks) == len(definition):
# Convert the landmarks to dict format for Unity
length_definitions[name] = [landmarks[lm] for lm in valid_landmarks]
else:
print(f"Warning: Some landmarks missing for length definition '{name}'")
circumference_definitions = {}
for name, definition in measurer.circumf_definitions.items():
circumference_definitions[name] = {
"LANDMARKS": definition["LANDMARKS"],
"JOINTS": definition["JOINTS"]
}
# Convert vertices to dict format with x, y, z keys
vertex_dicts = [{"x": float(v[0]), "y": float(v[1]), "z": float(v[2])} for v in vertices]
# Prepare data for export
unity_data = {
"landmarks": landmarks,
"shape_parameters": betas.tolist(), # Add shape parameters (betas) to the output
"vertices": vertex_dicts,
"faces": faces.tolist()
}
# Export to JSON
with open(result_fn, 'w') as f:
json.dump(unity_data, f, indent=2)
print(f"SMPL data exported to {result_fn}")
Hi @AndreAhmed
Thanks for your contributions, I have integrated your code, into https://github.com/vchoutas/smplify-x I fitted an image then I get a 3D SMPLX Model, then I have used your code to calculate the measurments The pose is little bit correct, however as first insight, my height is not 162.31, it's around 176.
Problem 1: ambiguity problem of estimating anything from a single image you discussed with @kristijanbartol
Problem 2: you are estimating measurements from a posed subject (as you show in the image attached). The measurements in this repo are estimated with cutting planes or simple distances between landmarks and are therefore meant to be estimated from T-pose. If you pose a subject, the measurements change (ex. the height is estimated as the distance between the top of the head and the floor located in between the heels - if you crouch, this distance changes)
@kristijanbartol Thanks for your quick input. But how about other measurements, like Waist, stomach,..etc? I assume they are fixed ?
Measurements are defined in measurement_definitions.py
and adding new measurements is explained in the Readme
@kristijanbartol I have tried to export the betas, but they are not reflecting the actual shape parameters. Is what I did wrong? I mean the exported body. So What I did is to export the json, and render the SMPLX in Unity3D, and attach the shape parameters, but the body is not exactly the same as the one you constructed for measurments, in terms of height, body size,..etc.
Are you using the same SMPL / SMPLX model in all cases?
@DavidBoja Yes I'm using the same SMPL/SMPLX
@DavidBoja The triangulated mesh has exact same shape parameters in terms of belly stomach, and other features. but using just the betas alone, they don't define well the exact smplx mesh if they are used alone.
@DavidBoja The triangulated mesh has exact same shape parameters in terms of belly stomach, and other features. but using just the betas alone, they don't define well the exact smplx mesh if they are used alone.
So you have an SMPL with its shape parameters. You load those shape parameters into Unity3D to create the SMPL. And then the SMPL mesh from this repository and from from Unity3D do not correspond?
@DavidBoja
Yes they don't correspond at all, I asked Shapy guys, but they didn't answer. Also how do I export your measurment points done in python to Unity3D ? If you notice the woman, I just exported her betas, and they don't correspond at all.
Well, then I'd presume that you are using different models; they should be equal if you are using the same model. There are several SMPL models: SMPL, SMPL+H, SMPLX, STAR,.. so check what are you using. This repo uses either SMPL or SMPLX. I'm not familiar with Unity so I really couldn't tell you what is going on under the hood.
Measurement points for lengths are basically the landmarks which are defined in landmark_definitons.py
.
To get the circumference points, you can edit the code here:
and take the slice_segments_hull
, which are basically segment points on the mesh that create the circumference measurement.
Thanks for your contributions, I have integrated your code, into https://github.com/vchoutas/smplify-x I fitted an image then I get a 3D SMPLX Model, then I have used your code to calculate the measurments The pose is little bit correct, however as first insight, my height is not 162.31, it's around 176.
And the following has been integrated into :
` measurer = MeasureBody(model_type) measurer.from_verts(torch.tensor(vertices)) measurement_names = measurer.all_possible_measurements measurer.measure(measurement_names) measurer.label_measurements(STANDARD_LABELS)
in the following line :
https://github.com/vchoutas/smplify-x/blob/master/smplifyx/fit_single_frame.py#L508