DavidBoja / SMPL-Fitting

Fit an SMPL body model to a scan
29 stars 2 forks source link
3d dash dashboard fit fitting parametric-model plotly plotly-dash scan smpl smplx

SMPL-Fitting

Fit an SMPL body model (BM) to a given scan and view the optimization process in a plotly dashboard. Fitting supported:

The code supports fitting a single scan ๐Ÿ‘ค or a whole dataset ๐Ÿ‘ฅ.


https://github.com/DavidBoja/SMPL-Fitting/assets/32020857/34f3b1ce-81b8-460c-b645-fa04558bb1af


๐Ÿ”จ Getting started

You can use a docker container to facilitate running the code. After cloning the repo, run in terminal:

cd docker
sh build.sh
sh docker_run.sh CODE_PATH

by adjusting the CODE_PATH to the SMPL-Fitting directory location. This creates a smpl-fitting-container container. You can attach to it by running:

docker exec -it smpl-fitting-container /bin/bash

๐Ÿšง If you do not want to use docker, you can install the docker/requirements.txt into your own environment. ๐Ÿšง

Next, initialize the chamfer distance submodule by running:

git submodule update --init --recursive


Necessary files:


๐Ÿƒโ€โ™€๏ธ Fitting

The configuration files for the fitting are stored in the configs folder:


โš™๏ธ General configurations

The general configuration variables are listed below. The specific variables for fitting the body model are given here, and the specific variables for fitting the vertices are given here.

General variables:

Visualization variables:

Path variables:

Dataset variables for FAUST (these are dataset specific for each dataset you implement):


๐Ÿงโ€โ™‚๏ธ Fit body model (BM)

Optimize the body model parameters of shape and pose (including translation and scale) that best fit the given scan. Check notes on losses to see the losses used.

The optimization-specific configurations to fit a BM to a scan are set under fit_body_model_optimization in config.yaml with the following variables:

The default variables already set should work well for the fitting process.

๐Ÿ‘ค Fit BM to single scan

python fit_body_model.py onto_scan --scan_path {path-to-scan} --landmark_path {path-to-landmarks}

Check Notes to see the supported scan and landmark file extensions.

๐Ÿ‘ฅ Fit BM to dataset

python fit_body_model.py onto_dataset --dataset_name {dataset-to-fit}

The dataset you want to fit needs to be defined in datasets.py as a torch dataset. Check notes on datasets for more details. We already provide the FAUST dataset in datasets.py.


๐Ÿคน Fit vertices

Optimize the vertices of a BM (or mesh) that best fit the given scan. Check notes on losses to see the losses used.

The optimization-specific configuration to fit the vertices to a scan is set under fit_vertices_optimization in config.yaml with the following variables:


๐Ÿ‘ค Fit vertices to scan

python fit_vertices.py onto_scan --scan_path {path-to-scan} --landmark_path {path-to-landmarks} --start_from_previous_results {path-to-YYYY_MM_DD_HH_MM_SS-folder}

Check Notes to see the supported scan and landmark file extensions. You can either use --start_from_previous_results to fit the vertices of the previously fitted BM with the fit_body_model.py script ( โš ๏ธ provide the folder where the fitted .npz is located) or use --start_from_body_model to start fitting a BM with zero shape and pose to the scan (โš ๏ธ results will probably be poor).

๐Ÿ‘ฅ Fit vertices to dataset

python fit_vertices.py onto_dataset --dataset_name {dataset-name} --start_from_previous_results {path-to-previously-fitted-bm-results}

You can either use --start_from_previous_results to fit the vertices of the previously fitted BM with the fit_body_model.py script (โš ๏ธ provide the folder where the fitted .npz are located) or use --start_from_body_model to start fitting a BM with zero shape and pose to the scan (โš ๏ธ results will be poor). The dataset you want to fit needs to be defined in datasets.py as a torch dataset. Check notes on datasets for more details. We already provide the FAUST dataset in datasets.py.



โ†บ Refine fitting

If you already have body model parameters (pose, shape, translation and scale) given, but they are not ideal, you can refine them. The optimization-specific configuration to refine the parmaeters is set under refine_bm_fitting in config.yaml with the following variables:


๐Ÿ‘ฅ Refine parameters fitted to dataset

python refine_fitting.py onto_dataset --dataset_name {dataset-name}



โš–๏ธ Evaluate

Use the evaluate_fitting.py script to evaluate the fitting.


evaluate per-vertex-error

Evaluate the per vertex error (pve) which is the average euclidean distance between the given ground truth BM to the fitted BM.

python evaluate_fitting.py pve -F {path-to-results}

The pve unit is determined by the data. For the FAUST dataset the unit is given in meters.

You can use:


evaluate chamfer distance

Evaluate the (various definitions of) chamfer distance (CD) from the estimated body model to the scan with:

python evaluate_fitting.py chamfer -F {path-to-results}

where the different definitions are:

and are averaged over the examples. The unit of these metrics is determined by the data. For the FAUST dataset the unit is given in meters.

You can use:


๐Ÿ“ˆ Visualization

  1. Visualize SMPL landmarks with:

    python visualization.py visualize_smpl_landmarks
  2. Visualize scan landmarks with:
    python visualization.py visualize_scan_landmarks --scan_path {path-to-scan} --landmark_path {path-to-landmarks}

    Check Notes section to find out the possible landmark definitions.

  3. Visualize fitting:
    python visualization.py visualize_fitting --scan_path {path-to-scan} --fit_paths {path-to-.npz-file}

    where the .npz is obtained with the fitting scripts.


๐Ÿ“ Notes

Notes on landmarks

The list of available landmarks for each BM are listed in landmarks.py. \ The supported ways of loading landmarks for a scan are:

where x y z indicate the coordinates of the landmark and landmark_index indicates the index of the scan vertex representing the landmark.


Notes on losses

Losses for fitting the BM:

Losses for fitting the vertices:


Notes on datasets

The dataset you want to fit needs to be defined in datasets.py as a torch dataset with the following variables:

If you additionally want to evaluate the per vertex error (pve) after fitting (check โš–๏ธ Evaluate) which compares the mean L2 between the fitted BM and the ground truth BM, you need to provide the ground truth BM as:

If you want to refine the parameters that have already been fitted, the dataset needs to additionally return:

We provide the FAUST and CAESAR and 4DHumanOutfit dataset implementations in datasets.py. You can obtain the datasets from here, here and here.


Notes on supported BM

Currently, we support the SMPL body model. If you want to add another BM, you can follow these steps:

  1. Add the body models into data/body_models
  2. Implement the body model in body_models.py
  3. Implement the body model parameters in body_parameters.py
  4. Implement the body landmarks in landmarks.py


๐Ÿ’ฟ Demos

Fit body model onto scan:

python fit_body_model.py onto_scan --scan_path data/demo/tr_scan_000.ply --landmark_path data/demo/tr_scan_000_landmarks.json

Fit body model onto dataset (๐Ÿšง you need to provide the FAUST dataset files as mentioned above ๐Ÿšง):

python fit_body_model.py onto_dataset -D FAUST

Fit the vertices of the previously fitted BM onto the scan even further:

python fit_vertices.py onto_scan --scan_path data/FAUST/training/scans/tr_scan_000.ply --landmark_path data/FAUST/training/landmarks/tr_scan_000_landmarks.json --start_from_previous_results data/demo

Fit the vertices of the previously fitted BM onto FAUST dataset further:

python fit_vertices.py onto_dataset --dataset_name FAUST --start_from_previous_results data/demo

๐Ÿšง We provide only the fitted paths for scans tr_scan_000 and tr_scan_001. Therefore the rest of the scans are going to be skipped ๐Ÿšง

Evaluate PVE of fitted scan for the two provided fittings:

python evaluate_fitting.py pve -F data/demo -G data/demo

Evaluate chamfer of fitted scan for the two provided fittings:

python evaluate_fitting.py chamfer -F data/demo

Visualize SMPL landmarks:

python visualization.py visualize_smpl_landmarks

Visualize FAUST scan landmarks:

python visualization.py visualize_scan_landmarks --scan_path data/demo/tr_scan_000.ply --landmark_path data/demo/tr_scan_000_landmarks.json

Visualize the fitted vertices of the BM onto the FAUST scan:

python visualization.py visualize_fitting --scan_path data/demo/tr_scan_000.ply --fit_paths data/demo/tr_scan_000.npz


Citation

Please cite our work and leave a star โญ if you find the repository useful.

@misc{SMPL-Fitting,
  author = {Bojani\'{c}, D.},
  title = {SMPL-Fitting},
  year = {2024},
  publisher = {GitHub},
  journal = {GitHub repository},
  howpublished = {\url{https://github.com/DavidBoja/SMPL-Fitting}},
}

Todo


References

[1] Keep it SMPL: Automatic Estimation of 3D Human Pose and Shape from a Single Image