Initial snapshot: hand motion pipeline (Dyn-HaMR + dex-retargeting + SPIDER)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 UC Regents, Georgios Pavlakos
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
Vendored
+130
@@ -0,0 +1,130 @@
|
||||
# HaMeR: Hand Mesh Recovery
|
||||
Code repository for the paper:
|
||||
**Reconstructing Hands in 3D with Transformers**
|
||||
|
||||
[Georgios Pavlakos](https://geopavlakos.github.io/), [Dandan Shan](https://ddshan.github.io/), [Ilija Radosavovic](https://people.eecs.berkeley.edu/~ilija/), [Angjoo Kanazawa](https://people.eecs.berkeley.edu/~kanazawa/), [David Fouhey](https://cs.nyu.edu/~fouhey/), [Jitendra Malik](http://people.eecs.berkeley.edu/~malik/)
|
||||
|
||||
[](https://arxiv.org/pdf/2312.05251.pdf) [](https://geopavlakos.github.io/hamer/) [](https://colab.research.google.com/drive/1rQbQzegFWGVOm1n1d-S6koOWDo7F2ucu?usp=sharing) [](https://huggingface.co/spaces/geopavlakos/HaMeR)
|
||||
|
||||

|
||||
|
||||
## News
|
||||
|
||||
- [2026/02] Check out our [new work](https://gkarv.github.io/hand-texture-module/) using learned texture priors to improve HaMeR.
|
||||
- [2024/06] HaMeR received the 2nd place award in the Ego-Pose Hands task of the Ego-Exo4D Challenge! Please check the [validation report](https://www.cs.utexas.edu/~pavlakos/hamer/resources/egoexo4d_challenge.pdf).
|
||||
- [2024/05] We have released the evaluation pipeline!
|
||||
- [2024/05] We have released the HInt dataset annotations! Please check [here](https://github.com/ddshan/hint).
|
||||
- [2023/12] Original release!
|
||||
|
||||
## Installation
|
||||
First you need to clone the repo:
|
||||
```
|
||||
git clone --recursive https://github.com/geopavlakos/hamer.git
|
||||
cd hamer
|
||||
```
|
||||
|
||||
We recommend creating a virtual environment for HaMeR. You can use venv:
|
||||
```bash
|
||||
python3.10 -m venv .hamer
|
||||
source .hamer/bin/activate
|
||||
```
|
||||
|
||||
or alternatively conda:
|
||||
```bash
|
||||
conda create --name hamer python=3.10
|
||||
conda activate hamer
|
||||
```
|
||||
|
||||
Then, you can install the rest of the dependencies. This is for CUDA 11.7, but you can adapt accordingly:
|
||||
```bash
|
||||
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu117
|
||||
pip install -e .[all]
|
||||
pip install -v -e third-party/ViTPose
|
||||
```
|
||||
|
||||
You also need to download the trained models:
|
||||
```bash
|
||||
bash fetch_demo_data.sh
|
||||
```
|
||||
|
||||
Besides these files, you also need to download the MANO model. Please visit the [MANO website](https://mano.is.tue.mpg.de) and register to get access to the downloads section. We only require the right hand model. You need to put `MANO_RIGHT.pkl` under the `_DATA/data/mano` folder.
|
||||
|
||||
### Docker Compose
|
||||
|
||||
If you wish to use HaMeR with Docker, you can use the following command:
|
||||
|
||||
```
|
||||
docker compose -f ./docker/docker-compose.yml up -d
|
||||
```
|
||||
|
||||
After the image is built successfully, enter the container and run the steps as above:
|
||||
|
||||
```
|
||||
docker compose -f ./docker/docker-compose.yml exec hamer-dev /bin/bash
|
||||
```
|
||||
|
||||
Continue with the installation steps:
|
||||
|
||||
```bash
|
||||
bash fetch_demo_data.sh
|
||||
```
|
||||
|
||||
## Demo
|
||||
```bash
|
||||
python demo.py \
|
||||
--img_folder example_data --out_folder demo_out \
|
||||
--batch_size=48 --side_view --save_mesh --full_frame
|
||||
```
|
||||
|
||||
## HInt Dataset
|
||||
We have released the annotations for the HInt dataset. Please follow the instructions [here](https://github.com/ddshan/hint)
|
||||
|
||||
## Training
|
||||
First, download the training data to `./hamer_training_data/` by running:
|
||||
```
|
||||
bash fetch_training_data.sh
|
||||
```
|
||||
|
||||
Then you can start training using the following command:
|
||||
```
|
||||
python train.py exp_name=hamer data=mix_all experiment=hamer_vit_transformer trainer=gpu launcher=local
|
||||
```
|
||||
Checkpoints and logs will be saved to `./logs/`.
|
||||
|
||||
## Evaluation
|
||||
Download the [evaluation metadata](https://www.dropbox.com/scl/fi/7ip2vnnu355e2kqbyn1bc/hamer_evaluation_data.tar.gz?rlkey=nb4x10uc8mj2qlfq934t5mdlh) to `./hamer_evaluation_data/`. Additionally, download the FreiHAND, HO-3D, and HInt dataset images and update the corresponding paths in `hamer/configs/datasets_eval.yaml`.
|
||||
|
||||
Run evaluation on multiple datasets as follows, results are stored in `results/eval_regression.csv`.
|
||||
```bash
|
||||
python eval.py --dataset 'FREIHAND-VAL,HO3D-VAL,NEWDAYS-TEST-ALL,NEWDAYS-TEST-VIS,NEWDAYS-TEST-OCC,EPICK-TEST-ALL,EPICK-TEST-VIS,EPICK-TEST-OCC,EGO4D-TEST-ALL,EGO4D-TEST-VIS,EGO4D-TEST-OCC'
|
||||
```
|
||||
|
||||
Results for HInt are stored in `results/eval_regression.csv`. For [FreiHAND](https://github.com/lmb-freiburg/freihand) and [HO-3D](https://codalab.lisn.upsaclay.fr/competitions/4318) you get as output a `.json` file that can be used for evaluation using their corresponding evaluation processes.
|
||||
|
||||
## Acknowledgements
|
||||
Parts of the code are taken or adapted from the following repos:
|
||||
- [4DHumans](https://github.com/shubham-goel/4D-Humans)
|
||||
- [SLAHMR](https://github.com/vye16/slahmr)
|
||||
- [ProHMR](https://github.com/nkolot/ProHMR)
|
||||
- [SPIN](https://github.com/nkolot/SPIN)
|
||||
- [SMPLify-X](https://github.com/vchoutas/smplify-x)
|
||||
- [HMR](https://github.com/akanazawa/hmr)
|
||||
- [ViTPose](https://github.com/ViTAE-Transformer/ViTPose)
|
||||
- [Detectron2](https://github.com/facebookresearch/detectron2)
|
||||
|
||||
Additionally, we thank [StabilityAI](https://stability.ai/) for a generous compute grant that enabled this work.
|
||||
|
||||
## Open-Source Contributions
|
||||
- [Wentao Hu](https://vincenthu19.github.io/) integrated the hand parameters predicted by HaMeR into SMPL-X - [Mano2Smpl-X](https://github.com/VincentHu19/Mano2Smpl-X)
|
||||
|
||||
## Citing
|
||||
If you find this code useful for your research, please consider citing the following paper:
|
||||
|
||||
```bibtex
|
||||
@inproceedings{pavlakos2024reconstructing,
|
||||
title={Reconstructing Hands in 3{D} with Transformers},
|
||||
author={Pavlakos, Georgios and Shan, Dandan and Radosavovic, Ilija and Kanazawa, Angjoo and Fouhey, David and Malik, Jitendra},
|
||||
booktitle={CVPR},
|
||||
year={2024}
|
||||
}
|
||||
```
|
||||
Vendored
+208
@@ -0,0 +1,208 @@
|
||||
from pathlib import Path
|
||||
import torch
|
||||
import argparse
|
||||
import os
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
from hamer.configs import CACHE_DIR_HAMER
|
||||
from hamer.models import HAMER, download_models, load_hamer, DEFAULT_CHECKPOINT
|
||||
from hamer.utils import recursive_to
|
||||
from hamer.datasets.vitdet_dataset import ViTDetDataset, DEFAULT_MEAN, DEFAULT_STD
|
||||
from hamer.utils.renderer import Renderer, cam_crop_to_full
|
||||
|
||||
LIGHT_BLUE=(0.65098039, 0.74117647, 0.85882353)
|
||||
|
||||
from vitpose_model import ViTPoseModel
|
||||
|
||||
import json
|
||||
from typing import Dict, Optional
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='HaMeR demo code')
|
||||
parser.add_argument('--checkpoint', type=str, default=DEFAULT_CHECKPOINT, help='Path to pretrained model checkpoint')
|
||||
parser.add_argument('--img_folder', type=str, default='images', help='Folder with input images')
|
||||
parser.add_argument('--out_folder', type=str, default='out_demo', help='Output folder to save rendered results')
|
||||
parser.add_argument('--side_view', dest='side_view', action='store_true', default=False, help='If set, render side view also')
|
||||
parser.add_argument('--full_frame', dest='full_frame', action='store_true', default=True, help='If set, render all people together also')
|
||||
parser.add_argument('--save_mesh', dest='save_mesh', action='store_true', default=False, help='If set, save meshes to disk also')
|
||||
parser.add_argument('--batch_size', type=int, default=1, help='Batch size for inference/fitting')
|
||||
parser.add_argument('--rescale_factor', type=float, default=2.0, help='Factor for padding the bbox')
|
||||
parser.add_argument('--body_detector', type=str, default='vitdet', choices=['vitdet', 'regnety'], help='Using regnety improves runtime and reduces memory')
|
||||
parser.add_argument('--file_type', nargs='+', default=['*.jpg', '*.png'], help='List of file extensions to consider')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Download and load checkpoints
|
||||
download_models(CACHE_DIR_HAMER)
|
||||
model, model_cfg = load_hamer(args.checkpoint)
|
||||
|
||||
# Setup HaMeR model
|
||||
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
|
||||
model = model.to(device)
|
||||
model.eval()
|
||||
|
||||
# Load detector
|
||||
from hamer.utils.utils_detectron2 import DefaultPredictor_Lazy
|
||||
if args.body_detector == 'vitdet':
|
||||
from detectron2.config import LazyConfig
|
||||
import hamer
|
||||
cfg_path = Path(hamer.__file__).parent/'configs'/'cascade_mask_rcnn_vitdet_h_75ep.py'
|
||||
detectron2_cfg = LazyConfig.load(str(cfg_path))
|
||||
detectron2_cfg.train.init_checkpoint = "https://dl.fbaipublicfiles.com/detectron2/ViTDet/COCO/cascade_mask_rcnn_vitdet_h/f328730692/model_final_f05665.pkl"
|
||||
for i in range(3):
|
||||
detectron2_cfg.model.roi_heads.box_predictors[i].test_score_thresh = 0.25
|
||||
detector = DefaultPredictor_Lazy(detectron2_cfg)
|
||||
elif args.body_detector == 'regnety':
|
||||
from detectron2 import model_zoo
|
||||
from detectron2.config import get_cfg
|
||||
detectron2_cfg = model_zoo.get_config('new_baselines/mask_rcnn_regnety_4gf_dds_FPN_400ep_LSJ.py', trained=True)
|
||||
detectron2_cfg.model.roi_heads.box_predictor.test_score_thresh = 0.5
|
||||
detectron2_cfg.model.roi_heads.box_predictor.test_nms_thresh = 0.4
|
||||
detector = DefaultPredictor_Lazy(detectron2_cfg)
|
||||
|
||||
# keypoint detector
|
||||
cpm = ViTPoseModel(device)
|
||||
|
||||
# Setup the renderer
|
||||
renderer = Renderer(model_cfg, faces=model.mano.faces)
|
||||
|
||||
# Make output directory if it does not exist
|
||||
os.makedirs(args.out_folder, exist_ok=True)
|
||||
|
||||
# Get all demo images ends with .jpg or .png
|
||||
img_paths = [img for end in args.file_type for img in Path(args.img_folder).glob(end)]
|
||||
|
||||
# Iterate over all images in folder
|
||||
for img_path in img_paths:
|
||||
img_cv2 = cv2.imread(str(img_path))
|
||||
|
||||
# Detect humans in image
|
||||
det_out = detector(img_cv2)
|
||||
img = img_cv2.copy()[:, :, ::-1]
|
||||
|
||||
det_instances = det_out['instances']
|
||||
valid_idx = (det_instances.pred_classes==0) & (det_instances.scores > 0.5)
|
||||
pred_bboxes=det_instances.pred_boxes.tensor[valid_idx].cpu().numpy()
|
||||
pred_scores=det_instances.scores[valid_idx].cpu().numpy()
|
||||
|
||||
# Detect human keypoints for each person
|
||||
vitposes_out = cpm.predict_pose(
|
||||
img,
|
||||
[np.concatenate([pred_bboxes, pred_scores[:, None]], axis=1)],
|
||||
)
|
||||
|
||||
bboxes = []
|
||||
is_right = []
|
||||
|
||||
# Use hands based on hand keypoint detections
|
||||
for vitposes in vitposes_out:
|
||||
left_hand_keyp = vitposes['keypoints'][-42:-21]
|
||||
right_hand_keyp = vitposes['keypoints'][-21:]
|
||||
|
||||
# Rejecting not confident detections
|
||||
keyp = left_hand_keyp
|
||||
valid = keyp[:,2] > 0.5
|
||||
if sum(valid) > 3:
|
||||
bbox = [keyp[valid,0].min(), keyp[valid,1].min(), keyp[valid,0].max(), keyp[valid,1].max()]
|
||||
bboxes.append(bbox)
|
||||
is_right.append(0)
|
||||
keyp = right_hand_keyp
|
||||
valid = keyp[:,2] > 0.5
|
||||
if sum(valid) > 3:
|
||||
bbox = [keyp[valid,0].min(), keyp[valid,1].min(), keyp[valid,0].max(), keyp[valid,1].max()]
|
||||
bboxes.append(bbox)
|
||||
is_right.append(1)
|
||||
|
||||
if len(bboxes) == 0:
|
||||
continue
|
||||
|
||||
boxes = np.stack(bboxes)
|
||||
right = np.stack(is_right)
|
||||
|
||||
# Run reconstruction on all detected hands
|
||||
dataset = ViTDetDataset(model_cfg, img_cv2, boxes, right, rescale_factor=args.rescale_factor)
|
||||
dataloader = torch.utils.data.DataLoader(dataset, batch_size=8, shuffle=False, num_workers=0)
|
||||
|
||||
all_verts = []
|
||||
all_cam_t = []
|
||||
all_right = []
|
||||
|
||||
for batch in dataloader:
|
||||
batch = recursive_to(batch, device)
|
||||
with torch.no_grad():
|
||||
out = model(batch)
|
||||
|
||||
multiplier = (2*batch['right']-1)
|
||||
pred_cam = out['pred_cam']
|
||||
pred_cam[:,1] = multiplier*pred_cam[:,1]
|
||||
box_center = batch["box_center"].float()
|
||||
box_size = batch["box_size"].float()
|
||||
img_size = batch["img_size"].float()
|
||||
multiplier = (2*batch['right']-1)
|
||||
scaled_focal_length = model_cfg.EXTRA.FOCAL_LENGTH / model_cfg.MODEL.IMAGE_SIZE * img_size.max()
|
||||
pred_cam_t_full = cam_crop_to_full(pred_cam, box_center, box_size, img_size, scaled_focal_length).detach().cpu().numpy()
|
||||
|
||||
# Render the result
|
||||
batch_size = batch['img'].shape[0]
|
||||
for n in range(batch_size):
|
||||
# Get filename from path img_path
|
||||
img_fn, _ = os.path.splitext(os.path.basename(img_path))
|
||||
person_id = int(batch['personid'][n])
|
||||
white_img = (torch.ones_like(batch['img'][n]).cpu() - DEFAULT_MEAN[:,None,None]/255) / (DEFAULT_STD[:,None,None]/255)
|
||||
input_patch = batch['img'][n].cpu() * (DEFAULT_STD[:,None,None]/255) + (DEFAULT_MEAN[:,None,None]/255)
|
||||
input_patch = input_patch.permute(1,2,0).numpy()
|
||||
|
||||
regression_img = renderer(out['pred_vertices'][n].detach().cpu().numpy(),
|
||||
out['pred_cam_t'][n].detach().cpu().numpy(),
|
||||
batch['img'][n],
|
||||
mesh_base_color=LIGHT_BLUE,
|
||||
scene_bg_color=(1, 1, 1),
|
||||
)
|
||||
|
||||
if args.side_view:
|
||||
side_img = renderer(out['pred_vertices'][n].detach().cpu().numpy(),
|
||||
out['pred_cam_t'][n].detach().cpu().numpy(),
|
||||
white_img,
|
||||
mesh_base_color=LIGHT_BLUE,
|
||||
scene_bg_color=(1, 1, 1),
|
||||
side_view=True)
|
||||
final_img = np.concatenate([input_patch, regression_img, side_img], axis=1)
|
||||
else:
|
||||
final_img = np.concatenate([input_patch, regression_img], axis=1)
|
||||
|
||||
cv2.imwrite(os.path.join(args.out_folder, f'{img_fn}_{person_id}.png'), 255*final_img[:, :, ::-1])
|
||||
|
||||
# Add all verts and cams to list
|
||||
verts = out['pred_vertices'][n].detach().cpu().numpy()
|
||||
is_right = batch['right'][n].cpu().numpy()
|
||||
verts[:,0] = (2*is_right-1)*verts[:,0]
|
||||
cam_t = pred_cam_t_full[n]
|
||||
all_verts.append(verts)
|
||||
all_cam_t.append(cam_t)
|
||||
all_right.append(is_right)
|
||||
|
||||
# Save all meshes to disk
|
||||
if args.save_mesh:
|
||||
camera_translation = cam_t.copy()
|
||||
tmesh = renderer.vertices_to_trimesh(verts, camera_translation, LIGHT_BLUE, is_right=is_right)
|
||||
tmesh.export(os.path.join(args.out_folder, f'{img_fn}_{person_id}.obj'))
|
||||
|
||||
# Render front view
|
||||
if args.full_frame and len(all_verts) > 0:
|
||||
misc_args = dict(
|
||||
mesh_base_color=LIGHT_BLUE,
|
||||
scene_bg_color=(1, 1, 1),
|
||||
focal_length=scaled_focal_length,
|
||||
)
|
||||
cam_view = renderer.render_rgba_multiple(all_verts, cam_t=all_cam_t, render_res=img_size[n], is_right=all_right, **misc_args)
|
||||
|
||||
# Overlay image
|
||||
input_img = img_cv2.astype(np.float32)[:,:,::-1]/255.0
|
||||
input_img = np.concatenate([input_img, np.ones_like(input_img[:,:,:1])], axis=2) # Add alpha channel
|
||||
input_img_overlay = input_img[:,:,:3] * (1-cam_view[:,:,3:]) + cam_view[:,:,:3] * cam_view[:,:,3:]
|
||||
|
||||
cv2.imwrite(os.path.join(args.out_folder, f'{img_fn}_all.jpg'), 255*input_img_overlay[:, :, ::-1])
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
services:
|
||||
hamer-dev:
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: ./docker/hamer-dev.Dockerfile
|
||||
volumes:
|
||||
- ../:/app
|
||||
tty: true
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
count: 1 # alternatively, use `count: all` for all GPUs
|
||||
capabilities: [gpu]
|
||||
|
||||
Vendored
+166
@@ -0,0 +1,166 @@
|
||||
import argparse
|
||||
import os
|
||||
import json
|
||||
from pathlib import Path
|
||||
import traceback
|
||||
from typing import List, Optional
|
||||
|
||||
import pandas as pd
|
||||
import torch
|
||||
from filelock import FileLock
|
||||
from hamer.configs import dataset_eval_config
|
||||
from hamer.datasets import create_dataset
|
||||
from hamer.utils import Evaluator, recursive_to
|
||||
from tqdm import tqdm
|
||||
|
||||
from hamer.configs import CACHE_DIR_HAMER
|
||||
from hamer.models import HAMER, download_models, load_hamer, DEFAULT_CHECKPOINT
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Evaluate trained models')
|
||||
parser.add_argument('--checkpoint', type=str, default=DEFAULT_CHECKPOINT, help='Path to pretrained model checkpoint')
|
||||
parser.add_argument('--results_folder', type=str, default='results', help='Path to results folder.')
|
||||
parser.add_argument('--dataset', type=str, default='FREIHAND-VAL,HO3D-VAL,NEWDAYS-TEST-ALL,NEWDAYS-TEST-VIS,NEWDAYS-TEST-OCC,EPICK-TEST-ALL,EPICK-TEST-VIS,EPICK-TEST-OCC,EGO4D-TEST-ALL,EGO4D-TEST-VIS,EGO4D-TEST-OCC', help='Dataset to evaluate')
|
||||
parser.add_argument('--batch_size', type=int, default=16, help='Batch size for inference')
|
||||
parser.add_argument('--num_samples', type=int, default=1, help='Number of test samples to draw')
|
||||
parser.add_argument('--num_workers', type=int, default=8, help='Number of workers used for data loading')
|
||||
parser.add_argument('--log_freq', type=int, default=10, help='How often to log results')
|
||||
parser.add_argument('--shuffle', dest='shuffle', action='store_true', default=False, help='Shuffle the dataset during evaluation')
|
||||
parser.add_argument('--exp_name', type=str, default=None, help='Experiment name')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Download and load checkpoints
|
||||
download_models(CACHE_DIR_HAMER)
|
||||
model, model_cfg = load_hamer(args.checkpoint)
|
||||
|
||||
# Setup HMR2.0 model
|
||||
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
|
||||
model = model.to(device)
|
||||
model.eval()
|
||||
|
||||
# Load config and run eval, one dataset at a time
|
||||
print('Evaluating on datasets: {}'.format(args.dataset), flush=True)
|
||||
for dataset in args.dataset.split(','):
|
||||
dataset_cfg = dataset_eval_config()[dataset]
|
||||
args.dataset = dataset
|
||||
run_eval(model, model_cfg, dataset_cfg, device, args)
|
||||
|
||||
def run_eval(model, model_cfg, dataset_cfg, device, args):
|
||||
|
||||
# List of metrics to log
|
||||
if args.dataset in ['FREIHAND-VAL', 'HO3D-VAL']:
|
||||
metrics = None
|
||||
preds = ['vertices', 'keypoints_3d']
|
||||
pck_thresholds = None
|
||||
rescale_factor = -1
|
||||
elif args.dataset in ['NEWDAYS-TEST-ALL', 'NEWDAYS-TEST-VIS', 'NEWDAYS-TEST-OCC',
|
||||
'EPICK-TEST-ALL', 'EPICK-TEST-VIS', 'EPICK-TEST-OCC',
|
||||
'EGO4D-TEST-ALL', 'EGO4D-TEST-VIS', 'EGO4D-TEST-OCC']:
|
||||
metrics = ['mode_kpl2']
|
||||
preds = None
|
||||
pck_thresholds = [0.05, 0.1, 0.15]
|
||||
rescale_factor = 2
|
||||
|
||||
# Create dataset and data loader
|
||||
dataset = create_dataset(model_cfg, dataset_cfg, train=False, rescale_factor=rescale_factor)
|
||||
dataloader = torch.utils.data.DataLoader(dataset, args.batch_size, shuffle=args.shuffle, num_workers=args.num_workers)
|
||||
|
||||
# Setup evaluator object
|
||||
evaluator = Evaluator(
|
||||
dataset_length=dataset.__len__(),
|
||||
dataset=args.dataset,
|
||||
keypoint_list=dataset_cfg.KEYPOINT_LIST,
|
||||
pelvis_ind=model_cfg.EXTRA.PELVIS_IND,
|
||||
metrics=metrics,
|
||||
preds=preds,
|
||||
pck_thresholds=pck_thresholds,
|
||||
)
|
||||
|
||||
# Go over the images in the dataset.
|
||||
try:
|
||||
for i, batch in enumerate(tqdm(dataloader)):
|
||||
batch = recursive_to(batch, device)
|
||||
with torch.no_grad():
|
||||
out = model(batch)
|
||||
evaluator(out, batch)
|
||||
if i % args.log_freq == args.log_freq - 1:
|
||||
evaluator.log()
|
||||
evaluator.log()
|
||||
error = None
|
||||
except (Exception, KeyboardInterrupt) as e:
|
||||
traceback.print_exc()
|
||||
error = repr(e)
|
||||
i = 0
|
||||
|
||||
# Append results to file
|
||||
if metrics is not None:
|
||||
metrics_dict = evaluator.get_metrics_dict()
|
||||
results_csv = os.path.join(args.results_folder, 'eval_regression.csv')
|
||||
save_eval_result(results_csv, metrics_dict, args.checkpoint, args.dataset, error=error, iters_done=i, exp_name=args.exp_name)
|
||||
if preds is not None:
|
||||
results_json = os.path.join(args.results_folder, '%s.json' % args.dataset.lower())
|
||||
preds_dict = evaluator.get_preds_dict()
|
||||
save_preds_result(results_json, preds_dict)
|
||||
|
||||
def save_eval_result(
|
||||
csv_path: str,
|
||||
metric_dict: float,
|
||||
checkpoint_path: str,
|
||||
dataset_name: str,
|
||||
# start_time: pd.Timestamp,
|
||||
error: Optional[str] = None,
|
||||
iters_done=None,
|
||||
exp_name=None,
|
||||
) -> None:
|
||||
"""Save evaluation results for a single scene file to a common CSV file."""
|
||||
|
||||
timestamp = pd.Timestamp.now()
|
||||
exists: bool = os.path.exists(csv_path)
|
||||
exp_name = exp_name or Path(checkpoint_path).parent.parent.name
|
||||
|
||||
# save each metric as different row to the csv path
|
||||
metric_names = list(metric_dict.keys())
|
||||
metric_values = list(metric_dict.values())
|
||||
N = len(metric_names)
|
||||
df = pd.DataFrame(
|
||||
dict(
|
||||
timestamp=[timestamp] * N,
|
||||
checkpoint_path=[checkpoint_path] * N,
|
||||
exp_name=[exp_name] * N,
|
||||
dataset=[dataset_name] * N,
|
||||
metric_name=metric_names,
|
||||
metric_value=metric_values,
|
||||
error=[error] * N,
|
||||
iters_done=[iters_done] * N,
|
||||
),
|
||||
index=list(range(N)),
|
||||
)
|
||||
|
||||
# Lock the file to prevent multiple processes from writing to it at the same time.
|
||||
lock = FileLock(f"{csv_path}.lock", timeout=10)
|
||||
with lock:
|
||||
df.to_csv(csv_path, mode="a", header=not exists, index=False)
|
||||
|
||||
def save_preds_result(
|
||||
pred_out_path: str,
|
||||
preds_dict: float,
|
||||
) -> None:
|
||||
""" Save predictions into a json file. """
|
||||
xyz_pred_list = preds_dict['keypoints_3d']
|
||||
verts_pred_list = preds_dict['vertices']
|
||||
# make sure its only lists
|
||||
xyz_pred_list = [x.tolist() for x in xyz_pred_list]
|
||||
verts_pred_list = [x.tolist() for x in verts_pred_list]
|
||||
|
||||
# save to a json
|
||||
with open(pred_out_path, 'w') as fo:
|
||||
json.dump(
|
||||
[
|
||||
xyz_pred_list,
|
||||
verts_pred_list
|
||||
], fo)
|
||||
print('Dumped %d joints and %d verts predictions to %s' % (len(xyz_pred_list), len(verts_pred_list), pred_out_path))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
# Google drive link to download the model
|
||||
gdown https://drive.google.com/uc?id=1mv7CUAnm73oKsEEG1xE3xH2C_oqcFSzT
|
||||
|
||||
# Alternatively, you can use wget
|
||||
#wget https://www.cs.utexas.edu/~pavlakos/hamer/data/hamer_demo_data.tar.gz
|
||||
|
||||
tar --warning=no-unknown-keyword --exclude=".*" -xvf hamer_demo_data.tar.gz
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
# Google drive links to download the training data
|
||||
gdown https://drive.google.com/uc?id=1BuKEc9qoBVgF8ApTTgAKRFVvDagWHPt7 # hamer_training_data_part1.tar.gz
|
||||
gdown https://drive.google.com/uc?id=1lNqBsifaxMP3NHIV_KKJVCT1zDvUn2T_ # hamer_training_data_part2.tar.gz
|
||||
gdown https://drive.google.com/uc?id=16xfV_ALY_M3VZeXKpjlB3MhnCNiS5XSq # hamer_training_data_part3.tar.gz
|
||||
gdown https://drive.google.com/uc?id=1SqzFHH2-UI6PlGTMd0Ds2FJKALBBOaEO # hamer_training_data_part4a.tar.gz
|
||||
gdown https://drive.google.com/uc?id=1xQxEjpaa3WqJt60UMtX_wpnOZ3bpj-u9 # hamer_training_data_part4b.tar.gz
|
||||
gdown https://drive.google.com/uc?id=1ozejeAue1M-p4boIfpnpX0E8RFIeHUZH # hamer_training_data_part4c.tar.gz
|
||||
|
||||
# Alternatively, consider using the dropbox links:
|
||||
#wget -O hamer_training_data_part1.tar.gz https://www.dropbox.com/scl/fi/bqq0jheev3626q1wiijs1/hamer_training_data_part1.tar.gz?rlkey=8fv4ktvk7r3txofd90q0trgxr
|
||||
#wget -O hamer_training_data_part2.tar.gz https://www.dropbox.com/scl/fi/l9l5udalchu0mh4qxnw2t/hamer_training_data_part2.tar.gz?rlkey=i0n2lzix4q6jxmhm4sr5rtmkt
|
||||
#wget -O hamer_training_data_part3.tar.gz https://www.dropbox.com/scl/fi/6lamcbwt79ri0oj4knwm3/hamer_training_data_part3.tar.gz?rlkey=j5y7ea7xrlu440ud12otaj2ne
|
||||
#wget -O hamer_training_data_part4a.tar.gz https://www.dropbox.com/scl/fi/vp6cw7he8t0eigjf6001l/hamer_training_data_part4a.tar.gz?rlkey=wylmufft4a5nq3yxep2olifrk
|
||||
#wget -O hamer_training_data_part4b.tar.gz https://www.dropbox.com/scl/fi/vyjasngr67ru14fb8s108/hamer_training_data_part4b.tar.gz?rlkey=qgotg1v9lkgo5eu78gh8b007t
|
||||
#wget -O hamer_training_data_part4c.tar.gz https://www.dropbox.com/scl/fi/nfvz5zpcmhz8hkwzc6ji4/hamer_training_data_part4c.tar.gz?rlkey=ygh0wvse04twhh1ri3xiw2sag
|
||||
|
||||
for f in hamer_training_data_part*.tar.gz; do
|
||||
tar --warning=no-unknown-keyword --exclude=".*" -xvf $f
|
||||
done
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
import os
|
||||
from typing import Dict
|
||||
from yacs.config import CfgNode as CN
|
||||
|
||||
CACHE_DIR_HAMER = "./_DATA"
|
||||
|
||||
def to_lower(x: Dict) -> Dict:
|
||||
"""
|
||||
Convert all dictionary keys to lowercase
|
||||
Args:
|
||||
x (dict): Input dictionary
|
||||
Returns:
|
||||
dict: Output dictionary with all keys converted to lowercase
|
||||
"""
|
||||
return {k.lower(): v for k, v in x.items()}
|
||||
|
||||
_C = CN(new_allowed=True)
|
||||
|
||||
_C.GENERAL = CN(new_allowed=True)
|
||||
_C.GENERAL.RESUME = True
|
||||
_C.GENERAL.TIME_TO_RUN = 3300
|
||||
_C.GENERAL.VAL_STEPS = 100
|
||||
_C.GENERAL.LOG_STEPS = 100
|
||||
_C.GENERAL.CHECKPOINT_STEPS = 20000
|
||||
_C.GENERAL.CHECKPOINT_DIR = "checkpoints"
|
||||
_C.GENERAL.SUMMARY_DIR = "tensorboard"
|
||||
_C.GENERAL.NUM_GPUS = 1
|
||||
_C.GENERAL.NUM_WORKERS = 4
|
||||
_C.GENERAL.MIXED_PRECISION = True
|
||||
_C.GENERAL.ALLOW_CUDA = True
|
||||
_C.GENERAL.PIN_MEMORY = False
|
||||
_C.GENERAL.DISTRIBUTED = False
|
||||
_C.GENERAL.LOCAL_RANK = 0
|
||||
_C.GENERAL.USE_SYNCBN = False
|
||||
_C.GENERAL.WORLD_SIZE = 1
|
||||
|
||||
_C.TRAIN = CN(new_allowed=True)
|
||||
_C.TRAIN.NUM_EPOCHS = 100
|
||||
_C.TRAIN.BATCH_SIZE = 32
|
||||
_C.TRAIN.SHUFFLE = True
|
||||
_C.TRAIN.WARMUP = False
|
||||
_C.TRAIN.NORMALIZE_PER_IMAGE = False
|
||||
_C.TRAIN.CLIP_GRAD = False
|
||||
_C.TRAIN.CLIP_GRAD_VALUE = 1.0
|
||||
_C.LOSS_WEIGHTS = CN(new_allowed=True)
|
||||
|
||||
_C.DATASETS = CN(new_allowed=True)
|
||||
|
||||
_C.MODEL = CN(new_allowed=True)
|
||||
_C.MODEL.IMAGE_SIZE = 224
|
||||
|
||||
_C.EXTRA = CN(new_allowed=True)
|
||||
_C.EXTRA.FOCAL_LENGTH = 5000
|
||||
|
||||
_C.DATASETS.CONFIG = CN(new_allowed=True)
|
||||
_C.DATASETS.CONFIG.SCALE_FACTOR = 0.3
|
||||
_C.DATASETS.CONFIG.ROT_FACTOR = 30
|
||||
_C.DATASETS.CONFIG.TRANS_FACTOR = 0.02
|
||||
_C.DATASETS.CONFIG.COLOR_SCALE = 0.2
|
||||
_C.DATASETS.CONFIG.ROT_AUG_RATE = 0.6
|
||||
_C.DATASETS.CONFIG.TRANS_AUG_RATE = 0.5
|
||||
_C.DATASETS.CONFIG.DO_FLIP = False
|
||||
_C.DATASETS.CONFIG.FLIP_AUG_RATE = 0.5
|
||||
_C.DATASETS.CONFIG.EXTREME_CROP_AUG_RATE = 0.10
|
||||
|
||||
def default_config() -> CN:
|
||||
"""
|
||||
Get a yacs CfgNode object with the default config values.
|
||||
"""
|
||||
# Return a clone so that the defaults will not be altered
|
||||
# This is for the "local variable" use pattern
|
||||
return _C.clone()
|
||||
|
||||
def dataset_config(name='datasets_tar.yaml') -> CN:
|
||||
"""
|
||||
Get dataset config file
|
||||
Returns:
|
||||
CfgNode: Dataset config as a yacs CfgNode object.
|
||||
"""
|
||||
cfg = CN(new_allowed=True)
|
||||
config_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), name)
|
||||
cfg.merge_from_file(config_file)
|
||||
cfg.freeze()
|
||||
return cfg
|
||||
|
||||
def dataset_eval_config() -> CN:
|
||||
return dataset_config('datasets_eval.yaml')
|
||||
|
||||
def get_config(config_file: str, merge: bool = True, update_cachedir: bool = False) -> CN:
|
||||
"""
|
||||
Read a config file and optionally merge it with the default config file.
|
||||
Args:
|
||||
config_file (str): Path to config file.
|
||||
merge (bool): Whether to merge with the default config or not.
|
||||
Returns:
|
||||
CfgNode: Config as a yacs CfgNode object.
|
||||
"""
|
||||
if merge:
|
||||
cfg = default_config()
|
||||
else:
|
||||
cfg = CN(new_allowed=True)
|
||||
cfg.merge_from_file(config_file)
|
||||
|
||||
if update_cachedir:
|
||||
def update_path(path: str) -> str:
|
||||
if os.path.isabs(path):
|
||||
return path
|
||||
return os.path.join(CACHE_DIR_HAMER, path)
|
||||
|
||||
cfg.MANO.MODEL_PATH = update_path(cfg.MANO.MODEL_PATH)
|
||||
cfg.MANO.MEAN_PARAMS = update_path(cfg.MANO.MEAN_PARAMS)
|
||||
|
||||
cfg.freeze()
|
||||
return cfg
|
||||
@@ -0,0 +1,129 @@
|
||||
## coco_loader_lsj.py
|
||||
|
||||
import detectron2.data.transforms as T
|
||||
from detectron2 import model_zoo
|
||||
from detectron2.config import LazyCall as L
|
||||
|
||||
# Data using LSJ
|
||||
image_size = 1024
|
||||
dataloader = model_zoo.get_config("common/data/coco.py").dataloader
|
||||
dataloader.train.mapper.augmentations = [
|
||||
L(T.RandomFlip)(horizontal=True), # flip first
|
||||
L(T.ResizeScale)(
|
||||
min_scale=0.1, max_scale=2.0, target_height=image_size, target_width=image_size
|
||||
),
|
||||
L(T.FixedSizeCrop)(crop_size=(image_size, image_size), pad=False),
|
||||
]
|
||||
dataloader.train.mapper.image_format = "RGB"
|
||||
dataloader.train.total_batch_size = 64
|
||||
# recompute boxes due to cropping
|
||||
dataloader.train.mapper.recompute_boxes = True
|
||||
|
||||
dataloader.test.mapper.augmentations = [
|
||||
L(T.ResizeShortestEdge)(short_edge_length=image_size, max_size=image_size),
|
||||
]
|
||||
|
||||
from functools import partial
|
||||
from fvcore.common.param_scheduler import MultiStepParamScheduler
|
||||
|
||||
from detectron2 import model_zoo
|
||||
from detectron2.config import LazyCall as L
|
||||
from detectron2.solver import WarmupParamScheduler
|
||||
from detectron2.modeling.backbone.vit import get_vit_lr_decay_rate
|
||||
|
||||
# mask_rcnn_vitdet_b_100ep.py
|
||||
|
||||
model = model_zoo.get_config("common/models/mask_rcnn_vitdet.py").model
|
||||
|
||||
# Initialization and trainer settings
|
||||
train = model_zoo.get_config("common/train.py").train
|
||||
train.amp.enabled = True
|
||||
train.ddp.fp16_compression = True
|
||||
train.init_checkpoint = "detectron2://ImageNetPretrained/MAE/mae_pretrain_vit_base.pth"
|
||||
|
||||
|
||||
# Schedule
|
||||
# 100 ep = 184375 iters * 64 images/iter / 118000 images/ep
|
||||
train.max_iter = 184375
|
||||
|
||||
lr_multiplier = L(WarmupParamScheduler)(
|
||||
scheduler=L(MultiStepParamScheduler)(
|
||||
values=[1.0, 0.1, 0.01],
|
||||
milestones=[163889, 177546],
|
||||
num_updates=train.max_iter,
|
||||
),
|
||||
warmup_length=250 / train.max_iter,
|
||||
warmup_factor=0.001,
|
||||
)
|
||||
|
||||
# Optimizer
|
||||
optimizer = model_zoo.get_config("common/optim.py").AdamW
|
||||
optimizer.params.lr_factor_func = partial(get_vit_lr_decay_rate, num_layers=12, lr_decay_rate=0.7)
|
||||
optimizer.params.overrides = {"pos_embed": {"weight_decay": 0.0}}
|
||||
|
||||
# cascade_mask_rcnn_vitdet_b_100ep.py
|
||||
|
||||
from detectron2.config import LazyCall as L
|
||||
from detectron2.layers import ShapeSpec
|
||||
from detectron2.modeling.box_regression import Box2BoxTransform
|
||||
from detectron2.modeling.matcher import Matcher
|
||||
from detectron2.modeling.roi_heads import (
|
||||
FastRCNNOutputLayers,
|
||||
FastRCNNConvFCHead,
|
||||
CascadeROIHeads,
|
||||
)
|
||||
|
||||
# arguments that don't exist for Cascade R-CNN
|
||||
[model.roi_heads.pop(k) for k in ["box_head", "box_predictor", "proposal_matcher"]]
|
||||
|
||||
model.roi_heads.update(
|
||||
_target_=CascadeROIHeads,
|
||||
box_heads=[
|
||||
L(FastRCNNConvFCHead)(
|
||||
input_shape=ShapeSpec(channels=256, height=7, width=7),
|
||||
conv_dims=[256, 256, 256, 256],
|
||||
fc_dims=[1024],
|
||||
conv_norm="LN",
|
||||
)
|
||||
for _ in range(3)
|
||||
],
|
||||
box_predictors=[
|
||||
L(FastRCNNOutputLayers)(
|
||||
input_shape=ShapeSpec(channels=1024),
|
||||
test_score_thresh=0.05,
|
||||
box2box_transform=L(Box2BoxTransform)(weights=(w1, w1, w2, w2)),
|
||||
cls_agnostic_bbox_reg=True,
|
||||
num_classes="${...num_classes}",
|
||||
)
|
||||
for (w1, w2) in [(10, 5), (20, 10), (30, 15)]
|
||||
],
|
||||
proposal_matchers=[
|
||||
L(Matcher)(thresholds=[th], labels=[0, 1], allow_low_quality_matches=False)
|
||||
for th in [0.5, 0.6, 0.7]
|
||||
],
|
||||
)
|
||||
|
||||
# cascade_mask_rcnn_vitdet_h_75ep.py
|
||||
|
||||
from functools import partial
|
||||
|
||||
train.init_checkpoint = "detectron2://ImageNetPretrained/MAE/mae_pretrain_vit_huge_p14to16.pth"
|
||||
|
||||
model.backbone.net.embed_dim = 1280
|
||||
model.backbone.net.depth = 32
|
||||
model.backbone.net.num_heads = 16
|
||||
model.backbone.net.drop_path_rate = 0.5
|
||||
# 7, 15, 23, 31 for global attention
|
||||
model.backbone.net.window_block_indexes = (
|
||||
list(range(0, 7)) + list(range(8, 15)) + list(range(16, 23)) + list(range(24, 31))
|
||||
)
|
||||
|
||||
optimizer.params.lr_factor_func = partial(get_vit_lr_decay_rate, lr_decay_rate=0.9, num_layers=32)
|
||||
optimizer.params.overrides = {}
|
||||
optimizer.params.weight_decay_norm = None
|
||||
|
||||
train.max_iter = train.max_iter * 3 // 4 # 100ep -> 75ep
|
||||
lr_multiplier.scheduler.milestones = [
|
||||
milestone * 3 // 4 for milestone in lr_multiplier.scheduler.milestones
|
||||
]
|
||||
lr_multiplier.scheduler.num_updates = train.max_iter
|
||||
@@ -0,0 +1,65 @@
|
||||
FREIHAND-VAL:
|
||||
TYPE: ImageDataset
|
||||
DATASET_FILE: hamer_evaluation_data/freihand_val.npz
|
||||
IMG_DIR: /home/user/datasets/FreiHAND_pub_v2_eval/evaluation/rgb/
|
||||
KEYPOINT_LIST: [0] # Dummy
|
||||
|
||||
HO3D-VAL:
|
||||
TYPE: ImageDataset
|
||||
DATASET_FILE: hamer_evaluation_data/ho3d_val.npz
|
||||
IMG_DIR: /home/user/datasets/HO3D_v2/evaluation/
|
||||
KEYPOINT_LIST: [0] # Dummy
|
||||
|
||||
EGO4D-TEST-ALL:
|
||||
TYPE: ImageDataset
|
||||
DATASET_FILE: hamer_evaluation_data/TEST_ego4d_img_all.npz
|
||||
IMG_DIR: /home/user/datasets/HInt_annotation_partial/TEST_ego4d_img/
|
||||
KEYPOINT_LIST: [0] # Dummy
|
||||
|
||||
EGO4D-TEST-VIS:
|
||||
TYPE: ImageDataset
|
||||
DATASET_FILE: hamer_evaluation_data/TEST_ego4d_img_vis.npz
|
||||
IMG_DIR: /home/user/datasets/HInt_annotation_partial/TEST_ego4d_img/
|
||||
KEYPOINT_LIST: [0] # Dummy
|
||||
|
||||
EGO4D-TEST-OCC:
|
||||
TYPE: ImageDataset
|
||||
DATASET_FILE: hamer_evaluation_data/TEST_ego4d_img_occ.npz
|
||||
IMG_DIR: /home/user/datasets/HInt_annotation_partial/TEST_ego4d_img/
|
||||
KEYPOINT_LIST: [0] # Dummy
|
||||
|
||||
EPICK-TEST-ALL:
|
||||
TYPE: ImageDataset
|
||||
DATASET_FILE: hamer_evaluation_data/TEST_epick_img_all.npz
|
||||
IMG_DIR: /home/user/datasets/HInt_annotation_partial/TEST_epick_img/
|
||||
KEYPOINT_LIST: [0] # Dummy
|
||||
|
||||
EPICK-TEST-VIS:
|
||||
TYPE: ImageDataset
|
||||
DATASET_FILE: hamer_evaluation_data/TEST_epick_img_vis.npz
|
||||
IMG_DIR: /home/user/datasets/HInt_annotation_partial/TEST_epick_img/
|
||||
KEYPOINT_LIST: [0] # Dummy
|
||||
|
||||
EPICK-TEST-OCC:
|
||||
TYPE: ImageDataset
|
||||
DATASET_FILE: hamer_evaluation_data/TEST_epick_img_occ.npz
|
||||
IMG_DIR: /home/user/datasets/HInt_annotation_partial/TEST_epick_img/
|
||||
KEYPOINT_LIST: [0] # Dummy
|
||||
|
||||
NEWDAYS-TEST-ALL:
|
||||
TYPE: ImageDataset
|
||||
DATASET_FILE: hamer_evaluation_data/TEST_newdays_img_all.npz
|
||||
IMG_DIR: /home/user/datasets/HInt_annotation_partial/TEST_newdays_img/
|
||||
KEYPOINT_LIST: [0] # Dummy
|
||||
|
||||
NEWDAYS-TEST-VIS:
|
||||
TYPE: ImageDataset
|
||||
DATASET_FILE: hamer_evaluation_data/TEST_newdays_img_vis.npz
|
||||
IMG_DIR: /home/user/datasets/HInt_annotation_partial/TEST_newdays_img/
|
||||
KEYPOINT_LIST: [0] # Dummy
|
||||
|
||||
NEWDAYS-TEST-OCC:
|
||||
TYPE: ImageDataset
|
||||
DATASET_FILE: hamer_evaluation_data/TEST_newdays_img_occ.npz
|
||||
IMG_DIR: /home/user/datasets/HInt_annotation_partial/TEST_newdays_img/
|
||||
KEYPOINT_LIST: [0] # Dummy
|
||||
@@ -0,0 +1,42 @@
|
||||
FREIHAND-TRAIN:
|
||||
TYPE: ImageDataset
|
||||
URLS: hamer_training_data/dataset_tars/freihand-train/{000000..000130}.tar
|
||||
epoch_size: 130_240
|
||||
INTERHAND26M-TRAIN:
|
||||
TYPE: ImageDataset
|
||||
URLS: hamer_training_data/dataset_tars/interhand26m-train/{000000..001056}.tar
|
||||
epoch_size: 1_424_632
|
||||
HALPE-TRAIN:
|
||||
TYPE: ImageDataset
|
||||
URLS: hamer_training_data/dataset_tars/halpe-train/{000000..000022}.tar
|
||||
epoch_size: 34_289
|
||||
COCOW-TRAIN:
|
||||
TYPE: ImageDataset
|
||||
URLS: hamer_training_data/dataset_tars/cocow-train/{000000..000036}.tar
|
||||
epoch_size: 78_666
|
||||
MTC-TRAIN:
|
||||
TYPE: ImageDataset
|
||||
URLS: hamer_training_data/dataset_tars/mtc-train/{000000..000306}.tar
|
||||
epoch_size: 363_947
|
||||
RHD-TRAIN:
|
||||
TYPE: ImageDataset
|
||||
URLS: hamer_training_data/dataset_tars/rhd-train/{000000..000041}.tar
|
||||
epoch_size: 61_705
|
||||
MPIINZSL-TRAIN:
|
||||
TYPE: ImageDataset
|
||||
URLS: hamer_training_data/dataset_tars/mpiinzsl-train/{000000..000015}.tar
|
||||
epoch_size: 15_184
|
||||
HO3D-TRAIN:
|
||||
TYPE: ImageDataset
|
||||
URLS: hamer_training_data/dataset_tars/ho3d-train/{000000..000083}.tar
|
||||
epoch_size: 83_325
|
||||
H2O3D-TRAIN:
|
||||
TYPE: ImageDataset
|
||||
URLS: hamer_training_data/dataset_tars/h2o3d-train/{000000..000060}.tar
|
||||
epoch_size: 121_996
|
||||
DEX-TRAIN:
|
||||
TYPE: ImageDataset
|
||||
URLS: hamer_training_data/dataset_tars/dex-train/{000000..000406}.tar
|
||||
epoch_size: 406_888
|
||||
FREIHAND-MOCAP:
|
||||
DATASET_FILE: hamer_training_data/freihand_mocap.npz
|
||||
@@ -0,0 +1,31 @@
|
||||
# @package _global_
|
||||
defaults:
|
||||
- /data_filtering: low1
|
||||
|
||||
DATASETS:
|
||||
TRAIN:
|
||||
FREIHAND-TRAIN:
|
||||
WEIGHT: 0.25
|
||||
INTERHAND26M-TRAIN:
|
||||
WEIGHT: 0.25
|
||||
MTC-TRAIN:
|
||||
WEIGHT: 0.1
|
||||
RHD-TRAIN:
|
||||
WEIGHT: 0.05
|
||||
COCOW-TRAIN:
|
||||
WEIGHT: 0.1
|
||||
HALPE-TRAIN:
|
||||
WEIGHT: 0.05
|
||||
MPIINZSL-TRAIN:
|
||||
WEIGHT: 0.05
|
||||
HO3D-TRAIN:
|
||||
WEIGHT: 0.05
|
||||
H2O3D-TRAIN:
|
||||
WEIGHT: 0.05
|
||||
DEX-TRAIN:
|
||||
WEIGHT: 0.05
|
||||
VAL:
|
||||
FREIHAND-TRAIN:
|
||||
WEIGHT: 1.0
|
||||
|
||||
MOCAP: FREIHAND-MOCAP
|
||||
@@ -0,0 +1,13 @@
|
||||
# @package _global_
|
||||
|
||||
DATASETS:
|
||||
# Data filtering during training
|
||||
SUPPRESS_KP_CONF_THRESH: 0.3
|
||||
FILTER_NUM_KP: 4
|
||||
FILTER_NUM_KP_THRESH: 0.0
|
||||
FILTER_REPROJ_THRESH: 31000
|
||||
|
||||
SUPPRESS_BETAS_THRESH: 3.0
|
||||
SUPPRESS_BAD_POSES: False
|
||||
POSES_BETAS_SIMULTANEOUS: True
|
||||
FILTER_NO_POSES: False # If True, filters images that don't have poses
|
||||
@@ -0,0 +1,29 @@
|
||||
# @package _global_
|
||||
|
||||
MANO:
|
||||
DATA_DIR: _DATA/data/
|
||||
MODEL_PATH: ${MANO.DATA_DIR}/mano
|
||||
GENDER: neutral
|
||||
NUM_HAND_JOINTS: 15
|
||||
MEAN_PARAMS: ${MANO.DATA_DIR}/mano_mean_params.npz
|
||||
CREATE_BODY_POSE: FALSE
|
||||
|
||||
EXTRA:
|
||||
FOCAL_LENGTH: 5000
|
||||
NUM_LOG_IMAGES: 4
|
||||
NUM_LOG_SAMPLES_PER_IMAGE: 8
|
||||
PELVIS_IND: 0
|
||||
|
||||
DATASETS:
|
||||
BETAS_REG: True
|
||||
CONFIG:
|
||||
SCALE_FACTOR: 0.3
|
||||
ROT_FACTOR: 30
|
||||
TRANS_FACTOR: 0.02
|
||||
COLOR_SCALE: 0.2
|
||||
ROT_AUG_RATE: 0.6
|
||||
TRANS_AUG_RATE: 0.5
|
||||
DO_FLIP: False
|
||||
FLIP_AUG_RATE: 0.0
|
||||
EXTREME_CROP_AUG_RATE: 0.0
|
||||
EXTREME_CROP_AUG_LEVEL: 1
|
||||
@@ -0,0 +1,51 @@
|
||||
# @package _global_
|
||||
|
||||
defaults:
|
||||
- default.yaml
|
||||
|
||||
GENERAL:
|
||||
TOTAL_STEPS: 1_000_000
|
||||
LOG_STEPS: 1000
|
||||
VAL_STEPS: 1000
|
||||
CHECKPOINT_STEPS: 1000
|
||||
CHECKPOINT_SAVE_TOP_K: 1
|
||||
NUM_WORKERS: 4
|
||||
PREFETCH_FACTOR: 2
|
||||
|
||||
TRAIN:
|
||||
LR: 1e-5
|
||||
WEIGHT_DECAY: 1e-4
|
||||
BATCH_SIZE: 8
|
||||
LOSS_REDUCTION: mean
|
||||
NUM_TRAIN_SAMPLES: 2
|
||||
NUM_TEST_SAMPLES: 64
|
||||
POSE_2D_NOISE_RATIO: 0.01
|
||||
SMPL_PARAM_NOISE_RATIO: 0.005
|
||||
|
||||
MODEL:
|
||||
IMAGE_SIZE: 256
|
||||
IMAGE_MEAN: [0.485, 0.456, 0.406]
|
||||
IMAGE_STD: [0.229, 0.224, 0.225]
|
||||
BACKBONE:
|
||||
TYPE: vit
|
||||
PRETRAINED_WEIGHTS: hamer_training_data/vitpose_backbone.pth
|
||||
MANO_HEAD:
|
||||
TYPE: transformer_decoder
|
||||
IN_CHANNELS: 2048
|
||||
TRANSFORMER_DECODER:
|
||||
depth: 6
|
||||
heads: 8
|
||||
mlp_dim: 1024
|
||||
dim_head: 64
|
||||
dropout: 0.0
|
||||
emb_dropout: 0.0
|
||||
norm: layer
|
||||
context_dim: 1280 # from vitpose-H
|
||||
|
||||
LOSS_WEIGHTS:
|
||||
KEYPOINTS_3D: 0.05
|
||||
KEYPOINTS_2D: 0.01
|
||||
GLOBAL_ORIENT: 0.001
|
||||
HAND_POSE: 0.001
|
||||
BETAS: 0.0005
|
||||
ADVERSARIAL: 0.0005
|
||||
@@ -0,0 +1,8 @@
|
||||
# disable python warnings if they annoy you
|
||||
ignore_warnings: False
|
||||
|
||||
# ask user for tags if none are provided in the config
|
||||
enforce_tags: True
|
||||
|
||||
# pretty print config tree at the start of the run using Rich library
|
||||
print_config: True
|
||||
@@ -0,0 +1,26 @@
|
||||
# @package _global_
|
||||
# https://hydra.cc/docs/configure_hydra/intro/
|
||||
|
||||
# enable color logging
|
||||
defaults:
|
||||
- override /hydra/hydra_logging: colorlog
|
||||
- override /hydra/job_logging: colorlog
|
||||
|
||||
# exp_name: ovrd_${hydra:job.override_dirname}
|
||||
exp_name: ${now:%Y-%m-%d}_${now:%H-%M-%S}
|
||||
|
||||
hydra:
|
||||
run:
|
||||
dir: ${paths.log_dir}/${task_name}/runs/${exp_name}
|
||||
sweep:
|
||||
dir: ${paths.log_dir}/${task_name}/multiruns/${exp_name}
|
||||
subdir: ${hydra.job.num}
|
||||
job:
|
||||
config:
|
||||
override_dirname:
|
||||
exclude_keys:
|
||||
- trainer
|
||||
- trainer.devices
|
||||
- trainer.num_nodes
|
||||
- callbacks
|
||||
- debug
|
||||
@@ -0,0 +1,13 @@
|
||||
# @package _global_
|
||||
|
||||
defaults:
|
||||
- override /hydra/launcher: submitit_local
|
||||
|
||||
hydra:
|
||||
launcher:
|
||||
timeout_min: 10_080 # 7 days
|
||||
nodes: 1
|
||||
tasks_per_node: ${trainer.devices}
|
||||
cpus_per_task: 6
|
||||
gpus_per_node: ${trainer.devices}
|
||||
name: hamer
|
||||
@@ -0,0 +1,22 @@
|
||||
# @package _global_
|
||||
|
||||
defaults:
|
||||
- override /hydra/launcher: submitit_slurm
|
||||
|
||||
hydra:
|
||||
launcher:
|
||||
timeout_min: 10_080 # 7 days
|
||||
max_num_timeout: 3
|
||||
partition: g40
|
||||
qos: idle
|
||||
nodes: 1
|
||||
tasks_per_node: ${trainer.devices}
|
||||
gpus_per_task: null
|
||||
cpus_per_task: 12
|
||||
gpus_per_node: ${trainer.devices}
|
||||
cpus_per_gpu: null
|
||||
comment: laion
|
||||
name: hamer
|
||||
setup:
|
||||
- module load cuda openmpi libfabric-aws
|
||||
- export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
|
||||
@@ -0,0 +1,18 @@
|
||||
# path to root directory
|
||||
# this requires PROJECT_ROOT environment variable to exist
|
||||
# PROJECT_ROOT is inferred and set by pyrootutils package in `train.py` and `eval.py`
|
||||
root_dir: ${oc.env:PROJECT_ROOT}
|
||||
|
||||
# path to data directory
|
||||
data_dir: ${paths.root_dir}/data/
|
||||
|
||||
# path to logging directory
|
||||
log_dir: logs/
|
||||
|
||||
# path to output directory, created dynamically by hydra
|
||||
# path generation pattern is specified in `configs/hydra/default.yaml`
|
||||
# use it to store all files generated during the run, like ckpts and metrics
|
||||
output_dir: ${hydra:runtime.output_dir}
|
||||
|
||||
# path to working directory
|
||||
work_dir: ${hydra:runtime.cwd}
|
||||
@@ -0,0 +1,47 @@
|
||||
# @package _global_
|
||||
|
||||
# specify here default configuration
|
||||
# order of defaults determines the order in which configs override each other
|
||||
defaults:
|
||||
- _self_
|
||||
- data: mix_all.yaml
|
||||
- trainer: ddp.yaml
|
||||
- paths: default.yaml
|
||||
- extras: default.yaml
|
||||
- hydra: default.yaml
|
||||
|
||||
# experiment configs allow for version control of specific hyperparameters
|
||||
# e.g. best hyperparameters for given model and datamodule
|
||||
- experiment: null
|
||||
- texture_exp: null
|
||||
|
||||
# optional local config for machine/user specific settings
|
||||
# it's optional since it doesn't need to exist and is excluded from version control
|
||||
- optional launcher: local.yaml
|
||||
# - optional launcher: slurm.yaml
|
||||
|
||||
# debugging config (enable through command line, e.g. `python train.py debug=default)
|
||||
- debug: null
|
||||
|
||||
# task name, determines output directory path
|
||||
task_name: "train"
|
||||
|
||||
# tags to help you identify your experiments
|
||||
# you can overwrite this in experiment configs
|
||||
# overwrite from command line with `python train.py tags="[first_tag, second_tag]"`
|
||||
# appending lists from command line is currently not supported :(
|
||||
# https://github.com/facebookresearch/hydra/issues/1547
|
||||
tags: ["dev"]
|
||||
|
||||
# set False to skip model training
|
||||
train: True
|
||||
|
||||
# evaluate on test set, using best model weights achieved during training
|
||||
# lightning chooses best weights based on the metric specified in checkpoint callback
|
||||
test: False
|
||||
|
||||
# simply provide checkpoint path to resume training
|
||||
ckpt_path: null
|
||||
|
||||
# seed for random number generators in pytorch, numpy and python.random
|
||||
seed: null
|
||||
@@ -0,0 +1,6 @@
|
||||
defaults:
|
||||
- default.yaml
|
||||
- default_hamer.yaml
|
||||
|
||||
accelerator: cpu
|
||||
devices: 1
|
||||
@@ -0,0 +1,14 @@
|
||||
defaults:
|
||||
- default.yaml
|
||||
- default_hamer.yaml
|
||||
|
||||
# use "ddp_spawn" instead of "ddp",
|
||||
# it's slower but normal "ddp" currently doesn't work ideally with hydra
|
||||
# https://github.com/facebookresearch/hydra/issues/2070
|
||||
# https://pytorch-lightning.readthedocs.io/en/latest/accelerators/gpu_intermediate.html#distributed-data-parallel-spawn
|
||||
strategy: ddp
|
||||
|
||||
accelerator: gpu
|
||||
devices: 8
|
||||
num_nodes: 1
|
||||
sync_batchnorm: True
|
||||
@@ -0,0 +1,10 @@
|
||||
_target_: pytorch_lightning.Trainer
|
||||
|
||||
default_root_dir: ${paths.output_dir}
|
||||
|
||||
accelerator: cpu
|
||||
devices: 1
|
||||
|
||||
# set True to to ensure deterministic results
|
||||
# makes training slower but gives more reproducibility than just setting seeds
|
||||
deterministic: False
|
||||
@@ -0,0 +1,8 @@
|
||||
num_sanity_val_steps: 0
|
||||
log_every_n_steps: ${GENERAL.LOG_STEPS}
|
||||
val_check_interval: ${GENERAL.VAL_STEPS}
|
||||
precision: 16
|
||||
max_steps: ${GENERAL.TOTAL_STEPS}
|
||||
# move_metrics_to_cpu: True
|
||||
limit_val_batches: 1
|
||||
# track_grad_norm: -1
|
||||
@@ -0,0 +1,6 @@
|
||||
defaults:
|
||||
- default.yaml
|
||||
- default_hamer.yaml
|
||||
|
||||
accelerator: gpu
|
||||
devices: 1
|
||||
@@ -0,0 +1,6 @@
|
||||
defaults:
|
||||
- default.yaml
|
||||
- default_hamer.yaml
|
||||
|
||||
accelerator: mps
|
||||
devices: 1
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
from typing import Dict, Optional
|
||||
|
||||
import torch
|
||||
import numpy as np
|
||||
import pytorch_lightning as pl
|
||||
from yacs.config import CfgNode
|
||||
|
||||
import webdataset as wds
|
||||
from ..configs import to_lower
|
||||
from .dataset import Dataset
|
||||
from .image_dataset import ImageDataset
|
||||
from .mocap_dataset import MoCapDataset
|
||||
|
||||
def create_dataset(cfg: CfgNode, dataset_cfg: CfgNode, train: bool = True, **kwargs) -> Dataset:
|
||||
"""
|
||||
Instantiate a dataset from a config file.
|
||||
Args:
|
||||
cfg (CfgNode): Model configuration file.
|
||||
dataset_cfg (CfgNode): Dataset configuration info.
|
||||
train (bool): Variable to select between train and val datasets.
|
||||
"""
|
||||
|
||||
dataset_type = Dataset.registry[dataset_cfg.TYPE]
|
||||
return dataset_type(cfg, **to_lower(dataset_cfg), train=train, **kwargs)
|
||||
|
||||
def create_webdataset(cfg: CfgNode, dataset_cfg: CfgNode, train: bool = True) -> Dataset:
|
||||
"""
|
||||
Like `create_dataset` but load data from tars.
|
||||
"""
|
||||
dataset_type = Dataset.registry[dataset_cfg.TYPE]
|
||||
return dataset_type.load_tars_as_webdataset(cfg, **to_lower(dataset_cfg), train=train)
|
||||
|
||||
|
||||
class MixedWebDataset(wds.WebDataset):
|
||||
def __init__(self, cfg: CfgNode, dataset_cfg: CfgNode, train: bool = True) -> None:
|
||||
super(wds.WebDataset, self).__init__()
|
||||
dataset_list = cfg.DATASETS.TRAIN if train else cfg.DATASETS.VAL
|
||||
datasets = [create_webdataset(cfg, dataset_cfg[dataset], train=train) for dataset, v in dataset_list.items()]
|
||||
weights = np.array([v.WEIGHT for dataset, v in dataset_list.items()])
|
||||
weights = weights / weights.sum() # normalize
|
||||
self.append(wds.RandomMix(datasets, weights))
|
||||
|
||||
class HAMERDataModule(pl.LightningDataModule):
|
||||
|
||||
def __init__(self, cfg: CfgNode, dataset_cfg: CfgNode) -> None:
|
||||
"""
|
||||
Initialize LightningDataModule for HAMER training
|
||||
Args:
|
||||
cfg (CfgNode): Config file as a yacs CfgNode containing necessary dataset info.
|
||||
dataset_cfg (CfgNode): Dataset configuration file
|
||||
"""
|
||||
super().__init__()
|
||||
self.cfg = cfg
|
||||
self.dataset_cfg = dataset_cfg
|
||||
self.train_dataset = None
|
||||
self.val_dataset = None
|
||||
self.test_dataset = None
|
||||
self.mocap_dataset = None
|
||||
|
||||
def setup(self, stage: Optional[str] = None) -> None:
|
||||
"""
|
||||
Load datasets necessary for training
|
||||
Args:
|
||||
cfg (CfgNode): Config file as a yacs CfgNode containing necessary dataset info.
|
||||
"""
|
||||
if self.train_dataset == None:
|
||||
self.train_dataset = MixedWebDataset(self.cfg, self.dataset_cfg, train=True).with_epoch(100_000).shuffle(4000)
|
||||
self.val_dataset = MixedWebDataset(self.cfg, self.dataset_cfg, train=False).shuffle(4000)
|
||||
self.mocap_dataset = MoCapDataset(**to_lower(self.dataset_cfg[self.cfg.DATASETS.MOCAP]))
|
||||
|
||||
def train_dataloader(self) -> Dict:
|
||||
"""
|
||||
Setup training data loader.
|
||||
Returns:
|
||||
Dict: Dictionary containing image and mocap data dataloaders
|
||||
"""
|
||||
train_dataloader = torch.utils.data.DataLoader(self.train_dataset, self.cfg.TRAIN.BATCH_SIZE, drop_last=True, num_workers=self.cfg.GENERAL.NUM_WORKERS, prefetch_factor=self.cfg.GENERAL.PREFETCH_FACTOR)
|
||||
mocap_dataloader = torch.utils.data.DataLoader(self.mocap_dataset, self.cfg.TRAIN.NUM_TRAIN_SAMPLES * self.cfg.TRAIN.BATCH_SIZE, shuffle=True, drop_last=True, num_workers=1)
|
||||
return {'img': train_dataloader, 'mocap': mocap_dataloader}
|
||||
|
||||
def val_dataloader(self) -> torch.utils.data.DataLoader:
|
||||
"""
|
||||
Setup val data loader.
|
||||
Returns:
|
||||
torch.utils.data.DataLoader: Validation dataloader
|
||||
"""
|
||||
val_dataloader = torch.utils.data.DataLoader(self.val_dataset, self.cfg.TRAIN.BATCH_SIZE, drop_last=True, num_workers=self.cfg.GENERAL.NUM_WORKERS)
|
||||
return val_dataloader
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
"""
|
||||
This file contains the defition of the base Dataset class.
|
||||
"""
|
||||
|
||||
class DatasetRegistration(type):
|
||||
"""
|
||||
Metaclass for registering different datasets
|
||||
"""
|
||||
def __init__(cls, name, bases, nmspc):
|
||||
super().__init__(name, bases, nmspc)
|
||||
if not hasattr(cls, 'registry'):
|
||||
cls.registry = dict()
|
||||
cls.registry[name] = cls
|
||||
|
||||
# Metamethods, called on class objects:
|
||||
def __iter__(cls):
|
||||
return iter(cls.registry)
|
||||
|
||||
def __str__(cls):
|
||||
return str(cls.registry)
|
||||
|
||||
class Dataset(metaclass=DatasetRegistration):
|
||||
"""
|
||||
Base Dataset class
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
+434
@@ -0,0 +1,434 @@
|
||||
import copy
|
||||
import os
|
||||
import numpy as np
|
||||
import torch
|
||||
from typing import Any, Dict, List
|
||||
from yacs.config import CfgNode
|
||||
import braceexpand
|
||||
import cv2
|
||||
|
||||
from .dataset import Dataset
|
||||
from .utils import get_example, expand_to_aspect_ratio
|
||||
|
||||
def expand(s):
|
||||
return os.path.expanduser(os.path.expandvars(s))
|
||||
def expand_urls(urls: str|List[str]):
|
||||
if isinstance(urls, str):
|
||||
urls = [urls]
|
||||
urls = [u for url in urls for u in braceexpand.braceexpand(expand(url))]
|
||||
return urls
|
||||
|
||||
FLIP_KEYPOINT_PERMUTATION = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||
|
||||
DEFAULT_MEAN = 255. * np.array([0.485, 0.456, 0.406])
|
||||
DEFAULT_STD = 255. * np.array([0.229, 0.224, 0.225])
|
||||
DEFAULT_IMG_SIZE = 256
|
||||
|
||||
class ImageDataset(Dataset):
|
||||
|
||||
def __init__(self,
|
||||
cfg: CfgNode,
|
||||
dataset_file: str,
|
||||
img_dir: str,
|
||||
train: bool = True,
|
||||
rescale_factor = 2,
|
||||
prune: Dict[str, Any] = {},
|
||||
**kwargs):
|
||||
"""
|
||||
Dataset class used for loading images and corresponding annotations.
|
||||
Args:
|
||||
cfg (CfgNode): Model config file.
|
||||
dataset_file (str): Path to npz file containing dataset info.
|
||||
img_dir (str): Path to image folder.
|
||||
train (bool): Whether it is for training or not (enables data augmentation).
|
||||
"""
|
||||
super(ImageDataset, self).__init__()
|
||||
self.train = train
|
||||
self.cfg = cfg
|
||||
|
||||
self.img_size = cfg.MODEL.IMAGE_SIZE
|
||||
self.mean = 255. * np.array(self.cfg.MODEL.IMAGE_MEAN)
|
||||
self.std = 255. * np.array(self.cfg.MODEL.IMAGE_STD)
|
||||
self.rescale_factor = rescale_factor
|
||||
|
||||
self.img_dir = img_dir
|
||||
self.data = np.load(dataset_file, allow_pickle=True)
|
||||
|
||||
self.imgname = self.data['imgname']
|
||||
self.personid = np.zeros(len(self.imgname), dtype=np.int32)
|
||||
self.extra_info = self.data.get('extra_info', [{} for _ in range(len(self.imgname))])
|
||||
|
||||
self.flip_keypoint_permutation = copy.copy(FLIP_KEYPOINT_PERMUTATION)
|
||||
|
||||
num_pose = 3 * (self.cfg.MANO.NUM_HAND_JOINTS + 1)
|
||||
|
||||
# Bounding boxes are assumed to be in the center and scale format
|
||||
self.center = self.data['center']
|
||||
self.scale = self.data['scale'].reshape(len(self.center), -1) / 200.0
|
||||
if self.scale.shape[1] == 1:
|
||||
self.scale = np.tile(self.scale, (1, 2))
|
||||
assert self.scale.shape == (len(self.center), 2)
|
||||
|
||||
try:
|
||||
self.right = self.data['right']
|
||||
except KeyError:
|
||||
self.right = np.ones(len(self.imgname), dtype=np.float32)
|
||||
|
||||
# Get gt MANO parameters, if available
|
||||
try:
|
||||
self.hand_pose = self.data['hand_pose'].astype(np.float32)
|
||||
self.has_hand_pose = self.data['has_hand_pose'].astype(np.float32)
|
||||
except KeyError:
|
||||
self.hand_pose = np.zeros((len(self.imgname), num_pose), dtype=np.float32)
|
||||
self.has_hand_pose = np.zeros(len(self.imgname), dtype=np.float32)
|
||||
try:
|
||||
self.betas = self.data['betas'].astype(np.float32)
|
||||
self.has_betas = self.data['has_betas'].astype(np.float32)
|
||||
except KeyError:
|
||||
self.betas = np.zeros((len(self.imgname), 10), dtype=np.float32)
|
||||
self.has_betas = np.zeros(len(self.imgname), dtype=np.float32)
|
||||
|
||||
# Try to get 2d keypoints, if available
|
||||
try:
|
||||
hand_keypoints_2d = self.data['hand_keypoints_2d']
|
||||
except KeyError:
|
||||
hand_keypoints_2d = np.zeros((len(self.center), 21, 3))
|
||||
|
||||
self.keypoints_2d = hand_keypoints_2d
|
||||
|
||||
# Try to get 3d keypoints, if available
|
||||
try:
|
||||
hand_keypoints_3d = self.data['hand_keypoints_3d'].astype(np.float32)
|
||||
except KeyError:
|
||||
hand_keypoints_3d = np.zeros((len(self.center), 21, 4), dtype=np.float32)
|
||||
|
||||
self.keypoints_3d = hand_keypoints_3d
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self.scale)
|
||||
|
||||
def __getitem__(self, idx: int) -> Dict:
|
||||
"""
|
||||
Returns an example from the dataset.
|
||||
"""
|
||||
try:
|
||||
image_file_rel = self.imgname[idx].decode('utf-8')
|
||||
except AttributeError:
|
||||
image_file_rel = self.imgname[idx]
|
||||
image_file = os.path.join(self.img_dir, image_file_rel)
|
||||
keypoints_2d = self.keypoints_2d[idx].copy()
|
||||
keypoints_3d = self.keypoints_3d[idx].copy()
|
||||
|
||||
center = self.center[idx].copy()
|
||||
center_x = center[0]
|
||||
center_y = center[1]
|
||||
scale = self.scale[idx]
|
||||
right = self.right[idx].copy()
|
||||
if self.rescale_factor == -1:
|
||||
BBOX_SHAPE = self.cfg.MODEL.get('BBOX_SHAPE', None)
|
||||
bbox_size = expand_to_aspect_ratio(scale*200, target_aspect_ratio=BBOX_SHAPE).max()
|
||||
bbox_expand_factor = bbox_size / ((scale*200).max())
|
||||
else:
|
||||
bbox_expand_factor = self.rescale_factor
|
||||
bbox_size = bbox_expand_factor*scale.max()*200
|
||||
hand_pose = self.hand_pose[idx].copy().astype(np.float32)
|
||||
betas = self.betas[idx].copy().astype(np.float32)
|
||||
|
||||
has_hand_pose = self.has_hand_pose[idx].copy()
|
||||
has_betas = self.has_betas[idx].copy()
|
||||
|
||||
mano_params = {'global_orient': hand_pose[:3],
|
||||
'hand_pose': hand_pose[3:],
|
||||
'betas': betas
|
||||
}
|
||||
|
||||
has_mano_params = {'global_orient': has_hand_pose,
|
||||
'hand_pose': has_hand_pose,
|
||||
'betas': has_betas
|
||||
}
|
||||
|
||||
mano_params_is_axis_angle = {'global_orient': True,
|
||||
'hand_pose': True,
|
||||
'betas': False
|
||||
}
|
||||
|
||||
augm_config = self.cfg.DATASETS.CONFIG
|
||||
# Crop image and (possibly) perform data augmentation
|
||||
img_patch, keypoints_2d, keypoints_3d, mano_params, has_mano_params, img_size = get_example(image_file,
|
||||
center_x, center_y,
|
||||
bbox_size, bbox_size,
|
||||
keypoints_2d, keypoints_3d,
|
||||
mano_params, has_mano_params,
|
||||
self.flip_keypoint_permutation,
|
||||
self.img_size, self.img_size,
|
||||
self.mean, self.std, self.train, right, augm_config)
|
||||
item = {}
|
||||
# These are the keypoints in the original image coordinates (before cropping)
|
||||
orig_keypoints_2d = self.keypoints_2d[idx].copy()
|
||||
|
||||
item['img'] = img_patch
|
||||
item['keypoints_2d'] = keypoints_2d.astype(np.float32)
|
||||
item['keypoints_3d'] = keypoints_3d.astype(np.float32)
|
||||
item['orig_keypoints_2d'] = orig_keypoints_2d
|
||||
item['box_center'] = self.center[idx].copy()
|
||||
item['box_size'] = bbox_size
|
||||
item['bbox_expand_factor'] = bbox_expand_factor
|
||||
item['img_size'] = 1.0 * img_size[::-1].copy()
|
||||
item['mano_params'] = mano_params
|
||||
item['has_mano_params'] = has_mano_params
|
||||
item['mano_params_is_axis_angle'] = mano_params_is_axis_angle
|
||||
item['imgname'] = image_file
|
||||
item['imgname_rel'] = image_file_rel
|
||||
item['personid'] = int(self.personid[idx])
|
||||
item['extra_info'] = copy.deepcopy(self.extra_info[idx])
|
||||
item['idx'] = idx
|
||||
item['_scale'] = scale
|
||||
item['right'] = self.right[idx].copy()
|
||||
return item
|
||||
|
||||
@staticmethod
|
||||
def load_tars_as_webdataset(cfg: CfgNode, urls: str|List[str], train: bool,
|
||||
resampled=False,
|
||||
epoch_size=None,
|
||||
cache_dir=None,
|
||||
**kwargs) -> Dataset:
|
||||
"""
|
||||
Loads the dataset from a webdataset tar file.
|
||||
"""
|
||||
|
||||
IMG_SIZE = cfg.MODEL.IMAGE_SIZE
|
||||
BBOX_SHAPE = cfg.MODEL.get('BBOX_SHAPE', None)
|
||||
MEAN = 255. * np.array(cfg.MODEL.IMAGE_MEAN)
|
||||
STD = 255. * np.array(cfg.MODEL.IMAGE_STD)
|
||||
|
||||
def split_data(source):
|
||||
for item in source:
|
||||
datas = item['data.pyd']
|
||||
for data in datas:
|
||||
if 'detection.npz' in item:
|
||||
det_idx = data['extra_info']['detection_npz_idx']
|
||||
mask = item['detection.npz']['masks'][det_idx]
|
||||
else:
|
||||
mask = np.ones_like(item['jpg'][:,:,0], dtype=bool)
|
||||
yield {
|
||||
'__key__': item['__key__'],
|
||||
'jpg': item['jpg'],
|
||||
'data.pyd': data,
|
||||
'mask': mask,
|
||||
}
|
||||
|
||||
def suppress_bad_kps(item, thresh=0.0):
|
||||
if thresh > 0:
|
||||
kp2d = item['data.pyd']['keypoints_2d']
|
||||
kp2d_conf = np.where(kp2d[:, 2] < thresh, 0.0, kp2d[:, 2])
|
||||
item['data.pyd']['keypoints_2d'] = np.concatenate([kp2d[:,:2], kp2d_conf[:,None]], axis=1)
|
||||
return item
|
||||
|
||||
def filter_numkp(item, numkp=4, thresh=0.0):
|
||||
kp_conf = item['data.pyd']['keypoints_2d'][:, 2]
|
||||
return (kp_conf > thresh).sum() > numkp
|
||||
|
||||
def filter_reproj_error(item, thresh=10**4.5):
|
||||
losses = item['data.pyd'].get('extra_info', {}).get('fitting_loss', np.array({})).item()
|
||||
reproj_loss = losses.get('reprojection_loss', None)
|
||||
return reproj_loss is None or reproj_loss < thresh
|
||||
|
||||
def filter_bbox_size(item, thresh=1):
|
||||
bbox_size_min = item['data.pyd']['scale'].min().item() * 200.
|
||||
return bbox_size_min > thresh
|
||||
|
||||
def filter_no_poses(item):
|
||||
return (item['data.pyd']['has_hand_pose'] > 0)
|
||||
|
||||
def supress_bad_betas(item, thresh=3):
|
||||
has_betas = item['data.pyd']['has_betas']
|
||||
if thresh > 0 and has_betas:
|
||||
betas_abs = np.abs(item['data.pyd']['betas'])
|
||||
if (betas_abs > thresh).any():
|
||||
item['data.pyd']['has_betas'] = False
|
||||
return item
|
||||
|
||||
def supress_bad_poses(item):
|
||||
has_hand_pose = item['data.pyd']['has_hand_pose']
|
||||
if has_hand_pose:
|
||||
hand_pose = item['data.pyd']['hand_pose']
|
||||
pose_is_probable = poses_check_probable(torch.from_numpy(hand_pose)[None, 3:], amass_poses_hist100_smooth).item()
|
||||
if not pose_is_probable:
|
||||
item['data.pyd']['has_hand_pose'] = False
|
||||
return item
|
||||
|
||||
def poses_betas_simultaneous(item):
|
||||
# We either have both hand_pose and betas, or neither
|
||||
has_betas = item['data.pyd']['has_betas']
|
||||
has_hand_pose = item['data.pyd']['has_hand_pose']
|
||||
item['data.pyd']['has_betas'] = item['data.pyd']['has_hand_pose'] = np.array(float((has_hand_pose>0) and (has_betas>0)))
|
||||
return item
|
||||
|
||||
def set_betas_for_reg(item):
|
||||
# Always have betas set to true
|
||||
has_betas = item['data.pyd']['has_betas']
|
||||
betas = item['data.pyd']['betas']
|
||||
|
||||
if not (has_betas>0):
|
||||
item['data.pyd']['has_betas'] = np.array(float((True)))
|
||||
item['data.pyd']['betas'] = betas * 0
|
||||
return item
|
||||
|
||||
# Load the dataset
|
||||
if epoch_size is not None:
|
||||
resampled = True
|
||||
#corrupt_filter = lambda sample: (sample['__key__'] not in CORRUPT_KEYS)
|
||||
import webdataset as wds
|
||||
dataset = wds.WebDataset(expand_urls(urls),
|
||||
nodesplitter=wds.split_by_node,
|
||||
shardshuffle=True,
|
||||
resampled=resampled,
|
||||
cache_dir=cache_dir,
|
||||
) #.select(corrupt_filter)
|
||||
if train:
|
||||
dataset = dataset.shuffle(100)
|
||||
dataset = dataset.decode('rgb8').rename(jpg='jpg;jpeg;png')
|
||||
|
||||
# Process the dataset
|
||||
dataset = dataset.compose(split_data)
|
||||
|
||||
# Filter/clean the dataset
|
||||
SUPPRESS_KP_CONF_THRESH = cfg.DATASETS.get('SUPPRESS_KP_CONF_THRESH', 0.0)
|
||||
SUPPRESS_BETAS_THRESH = cfg.DATASETS.get('SUPPRESS_BETAS_THRESH', 0.0)
|
||||
SUPPRESS_BAD_POSES = cfg.DATASETS.get('SUPPRESS_BAD_POSES', False)
|
||||
POSES_BETAS_SIMULTANEOUS = cfg.DATASETS.get('POSES_BETAS_SIMULTANEOUS', False)
|
||||
BETAS_REG = cfg.DATASETS.get('BETAS_REG', False)
|
||||
FILTER_NO_POSES = cfg.DATASETS.get('FILTER_NO_POSES', False)
|
||||
FILTER_NUM_KP = cfg.DATASETS.get('FILTER_NUM_KP', 4)
|
||||
FILTER_NUM_KP_THRESH = cfg.DATASETS.get('FILTER_NUM_KP_THRESH', 0.0)
|
||||
FILTER_REPROJ_THRESH = cfg.DATASETS.get('FILTER_REPROJ_THRESH', 0.0)
|
||||
FILTER_MIN_BBOX_SIZE = cfg.DATASETS.get('FILTER_MIN_BBOX_SIZE', 0.0)
|
||||
if SUPPRESS_KP_CONF_THRESH > 0:
|
||||
dataset = dataset.map(lambda x: suppress_bad_kps(x, thresh=SUPPRESS_KP_CONF_THRESH))
|
||||
if SUPPRESS_BETAS_THRESH > 0:
|
||||
dataset = dataset.map(lambda x: supress_bad_betas(x, thresh=SUPPRESS_BETAS_THRESH))
|
||||
if SUPPRESS_BAD_POSES:
|
||||
dataset = dataset.map(lambda x: supress_bad_poses(x))
|
||||
if POSES_BETAS_SIMULTANEOUS:
|
||||
dataset = dataset.map(lambda x: poses_betas_simultaneous(x))
|
||||
if FILTER_NO_POSES:
|
||||
dataset = dataset.select(lambda x: filter_no_poses(x))
|
||||
if FILTER_NUM_KP > 0:
|
||||
dataset = dataset.select(lambda x: filter_numkp(x, numkp=FILTER_NUM_KP, thresh=FILTER_NUM_KP_THRESH))
|
||||
if FILTER_REPROJ_THRESH > 0:
|
||||
dataset = dataset.select(lambda x: filter_reproj_error(x, thresh=FILTER_REPROJ_THRESH))
|
||||
if FILTER_MIN_BBOX_SIZE > 0:
|
||||
dataset = dataset.select(lambda x: filter_bbox_size(x, thresh=FILTER_MIN_BBOX_SIZE))
|
||||
if BETAS_REG:
|
||||
dataset = dataset.map(lambda x: set_betas_for_reg(x)) # NOTE: Must be at the end
|
||||
|
||||
use_skimage_antialias = cfg.DATASETS.get('USE_SKIMAGE_ANTIALIAS', False)
|
||||
border_mode = {
|
||||
'constant': cv2.BORDER_CONSTANT,
|
||||
'replicate': cv2.BORDER_REPLICATE,
|
||||
}[cfg.DATASETS.get('BORDER_MODE', 'constant')]
|
||||
|
||||
# Process the dataset further
|
||||
dataset = dataset.map(lambda x: ImageDataset.process_webdataset_tar_item(x, train,
|
||||
augm_config=cfg.DATASETS.CONFIG,
|
||||
MEAN=MEAN, STD=STD, IMG_SIZE=IMG_SIZE,
|
||||
BBOX_SHAPE=BBOX_SHAPE,
|
||||
use_skimage_antialias=use_skimage_antialias,
|
||||
border_mode=border_mode,
|
||||
))
|
||||
if epoch_size is not None:
|
||||
dataset = dataset.with_epoch(epoch_size)
|
||||
|
||||
return dataset
|
||||
|
||||
@staticmethod
|
||||
def process_webdataset_tar_item(item, train,
|
||||
augm_config=None,
|
||||
MEAN=DEFAULT_MEAN,
|
||||
STD=DEFAULT_STD,
|
||||
IMG_SIZE=DEFAULT_IMG_SIZE,
|
||||
BBOX_SHAPE=None,
|
||||
use_skimage_antialias=False,
|
||||
border_mode=cv2.BORDER_CONSTANT,
|
||||
):
|
||||
# Read data from item
|
||||
key = item['__key__']
|
||||
image = item['jpg']
|
||||
data = item['data.pyd']
|
||||
mask = item['mask']
|
||||
|
||||
keypoints_2d = data['keypoints_2d']
|
||||
keypoints_3d = data['keypoints_3d']
|
||||
center = data['center']
|
||||
scale = data['scale']
|
||||
hand_pose = data['hand_pose']
|
||||
betas = data['betas']
|
||||
right = data['right']
|
||||
has_hand_pose = data['has_hand_pose']
|
||||
has_betas = data['has_betas']
|
||||
# image_file = data['image_file']
|
||||
|
||||
# Process data
|
||||
orig_keypoints_2d = keypoints_2d.copy()
|
||||
center_x = center[0]
|
||||
center_y = center[1]
|
||||
bbox_size = expand_to_aspect_ratio(scale*200, target_aspect_ratio=BBOX_SHAPE).max()
|
||||
if bbox_size < 1:
|
||||
breakpoint()
|
||||
|
||||
|
||||
mano_params = {'global_orient': hand_pose[:3],
|
||||
'hand_pose': hand_pose[3:],
|
||||
'betas': betas
|
||||
}
|
||||
|
||||
has_mano_params = {'global_orient': has_hand_pose,
|
||||
'hand_pose': has_hand_pose,
|
||||
'betas': has_betas
|
||||
}
|
||||
|
||||
mano_params_is_axis_angle = {'global_orient': True,
|
||||
'hand_pose': True,
|
||||
'betas': False
|
||||
}
|
||||
|
||||
augm_config = copy.deepcopy(augm_config)
|
||||
# Crop image and (possibly) perform data augmentation
|
||||
img_rgba = np.concatenate([image, mask.astype(np.uint8)[:,:,None]*255], axis=2)
|
||||
img_patch_rgba, keypoints_2d, keypoints_3d, mano_params, has_mano_params, img_size, trans = get_example(img_rgba,
|
||||
center_x, center_y,
|
||||
bbox_size, bbox_size,
|
||||
keypoints_2d, keypoints_3d,
|
||||
mano_params, has_mano_params,
|
||||
FLIP_KEYPOINT_PERMUTATION,
|
||||
IMG_SIZE, IMG_SIZE,
|
||||
MEAN, STD, train, right, augm_config,
|
||||
is_bgr=False, return_trans=True,
|
||||
use_skimage_antialias=use_skimage_antialias,
|
||||
border_mode=border_mode,
|
||||
)
|
||||
img_patch = img_patch_rgba[:3,:,:]
|
||||
mask_patch = (img_patch_rgba[3,:,:] / 255.0).clip(0,1)
|
||||
if (mask_patch < 0.5).all():
|
||||
mask_patch = np.ones_like(mask_patch)
|
||||
|
||||
item = {}
|
||||
|
||||
item['img'] = img_patch
|
||||
item['mask'] = mask_patch
|
||||
# item['img_og'] = image
|
||||
# item['mask_og'] = mask
|
||||
item['keypoints_2d'] = keypoints_2d.astype(np.float32)
|
||||
item['keypoints_3d'] = keypoints_3d.astype(np.float32)
|
||||
item['orig_keypoints_2d'] = orig_keypoints_2d
|
||||
item['box_center'] = center.copy()
|
||||
item['box_size'] = bbox_size
|
||||
item['img_size'] = 1.0 * img_size[::-1].copy()
|
||||
item['mano_params'] = mano_params
|
||||
item['has_mano_params'] = has_mano_params
|
||||
item['mano_params_is_axis_angle'] = mano_params_is_axis_angle
|
||||
item['_scale'] = scale
|
||||
item['_trans'] = trans
|
||||
item['imgname'] = key
|
||||
# item['idx'] = idx
|
||||
return item
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
import copy
|
||||
import os
|
||||
import json
|
||||
import glob
|
||||
import numpy as np
|
||||
import torch
|
||||
from typing import Any, Dict, List
|
||||
from yacs.config import CfgNode
|
||||
import braceexpand
|
||||
import cv2
|
||||
|
||||
from .dataset import Dataset
|
||||
from .utils import get_example, expand_to_aspect_ratio
|
||||
from .smplh_prob_filter import poses_check_probable, load_amass_hist_smooth
|
||||
|
||||
def expand(s):
|
||||
return os.path.expanduser(os.path.expandvars(s))
|
||||
def expand_urls(urls: str|List[str]):
|
||||
if isinstance(urls, str):
|
||||
urls = [urls]
|
||||
urls = [u for url in urls for u in braceexpand.braceexpand(expand(url))]
|
||||
return urls
|
||||
|
||||
AIC_TRAIN_CORRUPT_KEYS = {
|
||||
'0a047f0124ae48f8eee15a9506ce1449ee1ba669',
|
||||
'1a703aa174450c02fbc9cfbf578a5435ef403689',
|
||||
'0394e6dc4df78042929b891dbc24f0fd7ffb6b6d',
|
||||
'5c032b9626e410441544c7669123ecc4ae077058',
|
||||
'ca018a7b4c5f53494006ebeeff9b4c0917a55f07',
|
||||
'4a77adb695bef75a5d34c04d589baf646fe2ba35',
|
||||
'a0689017b1065c664daef4ae2d14ea03d543217e',
|
||||
'39596a45cbd21bed4a5f9c2342505532f8ec5cbb',
|
||||
'3d33283b40610d87db660b62982f797d50a7366b',
|
||||
}
|
||||
CORRUPT_KEYS = {
|
||||
*{f'aic-train/{k}' for k in AIC_TRAIN_CORRUPT_KEYS},
|
||||
*{f'aic-train-vitpose/{k}' for k in AIC_TRAIN_CORRUPT_KEYS},
|
||||
}
|
||||
|
||||
FLIP_KEYPOINT_PERMUTATION = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||
|
||||
DEFAULT_MEAN = 255. * np.array([0.485, 0.456, 0.406])
|
||||
DEFAULT_STD = 255. * np.array([0.229, 0.224, 0.225])
|
||||
DEFAULT_IMG_SIZE = 256
|
||||
|
||||
class JsonDataset(Dataset):
|
||||
|
||||
def __init__(self,
|
||||
cfg: CfgNode,
|
||||
dataset_file: str,
|
||||
img_dir: str,
|
||||
right: bool,
|
||||
train: bool = False,
|
||||
prune: Dict[str, Any] = {},
|
||||
**kwargs):
|
||||
"""
|
||||
Dataset class used for loading images and corresponding annotations.
|
||||
Args:
|
||||
cfg (CfgNode): Model config file.
|
||||
dataset_file (str): Path to npz file containing dataset info.
|
||||
img_dir (str): Path to image folder.
|
||||
train (bool): Whether it is for training or not (enables data augmentation).
|
||||
"""
|
||||
super(JsonDataset, self).__init__()
|
||||
self.train = train
|
||||
self.cfg = cfg
|
||||
|
||||
self.img_size = cfg.MODEL.IMAGE_SIZE
|
||||
self.mean = 255. * np.array(self.cfg.MODEL.IMAGE_MEAN)
|
||||
self.std = 255. * np.array(self.cfg.MODEL.IMAGE_STD)
|
||||
|
||||
self.img_dir = img_dir
|
||||
boxes = np.array(json.load(open(dataset_file, 'rb')))
|
||||
|
||||
self.imgname = glob.glob(os.path.join(self.img_dir,'*.jpg'))
|
||||
self.imgname.sort()
|
||||
|
||||
self.flip_keypoint_permutation = copy.copy(FLIP_KEYPOINT_PERMUTATION)
|
||||
|
||||
num_pose = 3 * (self.cfg.MANO.NUM_HAND_JOINTS + 1)
|
||||
|
||||
# Bounding boxes are assumed to be in the center and scale format
|
||||
boxes = boxes.astype(np.float32)
|
||||
self.center = (boxes[:, 2:4] + boxes[:, 0:2]) / 2.0
|
||||
self.scale = 2 * (boxes[:, 2:4] - boxes[:, 0:2]) / 200.0
|
||||
self.personid = np.arange(len(boxes), dtype=np.int32)
|
||||
if right:
|
||||
self.right = np.ones(len(self.imgname), dtype=np.float32)
|
||||
else:
|
||||
self.right = np.zeros(len(self.imgname), dtype=np.float32)
|
||||
assert self.scale.shape == (len(self.center), 2)
|
||||
|
||||
# Get gt SMPLX parameters, if available
|
||||
try:
|
||||
self.hand_pose = self.data['hand_pose'].astype(np.float32)
|
||||
self.has_hand_pose = self.data['has_hand_pose'].astype(np.float32)
|
||||
except:
|
||||
self.hand_pose = np.zeros((len(self.imgname), num_pose), dtype=np.float32)
|
||||
self.has_hand_pose = np.zeros(len(self.imgname), dtype=np.float32)
|
||||
try:
|
||||
self.betas = self.data['betas'].astype(np.float32)
|
||||
self.has_betas = self.data['has_betas'].astype(np.float32)
|
||||
except:
|
||||
self.betas = np.zeros((len(self.imgname), 10), dtype=np.float32)
|
||||
self.has_betas = np.zeros(len(self.imgname), dtype=np.float32)
|
||||
|
||||
# Try to get 2d keypoints, if available
|
||||
try:
|
||||
hand_keypoints_2d = self.data['hand_keypoints_2d']
|
||||
except:
|
||||
hand_keypoints_2d = np.zeros((len(self.center), 21, 3))
|
||||
## Try to get extra 2d keypoints, if available
|
||||
#try:
|
||||
# extra_keypoints_2d = self.data['extra_keypoints_2d']
|
||||
#except KeyError:
|
||||
# extra_keypoints_2d = np.zeros((len(self.center), 19, 3))
|
||||
|
||||
#self.keypoints_2d = np.concatenate((hand_keypoints_2d, extra_keypoints_2d), axis=1).astype(np.float32)
|
||||
self.keypoints_2d = hand_keypoints_2d
|
||||
|
||||
# Try to get 3d keypoints, if available
|
||||
try:
|
||||
hand_keypoints_3d = self.data['hand_keypoints_3d'].astype(np.float32)
|
||||
except:
|
||||
hand_keypoints_3d = np.zeros((len(self.center), 21, 4), dtype=np.float32)
|
||||
## Try to get extra 3d keypoints, if available
|
||||
#try:
|
||||
# extra_keypoints_3d = self.data['extra_keypoints_3d'].astype(np.float32)
|
||||
#except KeyError:
|
||||
# extra_keypoints_3d = np.zeros((len(self.center), 19, 4), dtype=np.float32)
|
||||
|
||||
self.keypoints_3d = hand_keypoints_3d
|
||||
|
||||
#body_keypoints_3d[:, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], -1] = 0
|
||||
|
||||
#self.keypoints_3d = np.concatenate((body_keypoints_3d, extra_keypoints_3d), axis=1).astype(np.float32)
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self.scale)
|
||||
|
||||
def __getitem__(self, idx: int) -> Dict:
|
||||
"""
|
||||
Returns an example from the dataset.
|
||||
"""
|
||||
try:
|
||||
image_file = self.imgname[idx].decode('utf-8')
|
||||
except AttributeError:
|
||||
image_file = self.imgname[idx]
|
||||
keypoints_2d = self.keypoints_2d[idx].copy()
|
||||
keypoints_3d = self.keypoints_3d[idx].copy()
|
||||
|
||||
center = self.center[idx].copy()
|
||||
center_x = center[0]
|
||||
center_y = center[1]
|
||||
scale = self.scale[idx]
|
||||
right = self.right[idx].copy()
|
||||
BBOX_SHAPE = self.cfg.MODEL.get('BBOX_SHAPE', None)
|
||||
#bbox_size = expand_to_aspect_ratio(scale*200, target_aspect_ratio=BBOX_SHAPE).max()
|
||||
bbox_size = ((scale*200).max())
|
||||
bbox_expand_factor = bbox_size / ((scale*200).max())
|
||||
hand_pose = self.hand_pose[idx].copy().astype(np.float32)
|
||||
betas = self.betas[idx].copy().astype(np.float32)
|
||||
|
||||
has_hand_pose = self.has_hand_pose[idx].copy()
|
||||
has_betas = self.has_betas[idx].copy()
|
||||
|
||||
mano_params = {'global_orient': hand_pose[:3],
|
||||
'hand_pose': hand_pose[3:],
|
||||
'betas': betas
|
||||
}
|
||||
|
||||
has_mano_params = {'global_orient': has_hand_pose,
|
||||
'hand_pose': has_hand_pose,
|
||||
'betas': has_betas
|
||||
}
|
||||
|
||||
mano_params_is_axis_angle = {'global_orient': True,
|
||||
'hand_pose': True,
|
||||
'betas': False
|
||||
}
|
||||
|
||||
augm_config = self.cfg.DATASETS.CONFIG
|
||||
# Crop image and (possibly) perform data augmentation
|
||||
img_patch, keypoints_2d, keypoints_3d, mano_params, has_mano_params, img_size = get_example(image_file,
|
||||
center_x, center_y,
|
||||
bbox_size, bbox_size,
|
||||
keypoints_2d, keypoints_3d,
|
||||
mano_params, has_mano_params,
|
||||
self.flip_keypoint_permutation,
|
||||
self.img_size, self.img_size,
|
||||
self.mean, self.std, self.train, right, augm_config)
|
||||
|
||||
item = {}
|
||||
# These are the keypoints in the original image coordinates (before cropping)
|
||||
orig_keypoints_2d = self.keypoints_2d[idx].copy()
|
||||
|
||||
item['img'] = img_patch
|
||||
item['keypoints_2d'] = keypoints_2d.astype(np.float32)
|
||||
item['keypoints_3d'] = keypoints_3d.astype(np.float32)
|
||||
item['orig_keypoints_2d'] = orig_keypoints_2d
|
||||
item['box_center'] = self.center[idx].copy()
|
||||
item['box_size'] = bbox_size
|
||||
item['bbox_expand_factor'] = bbox_expand_factor
|
||||
item['img_size'] = 1.0 * img_size[::-1].copy()
|
||||
item['mano_params'] = mano_params
|
||||
item['has_mano_params'] = has_mano_params
|
||||
item['mano_params_is_axis_angle'] = mano_params_is_axis_angle
|
||||
item['imgname'] = image_file
|
||||
item['personid'] = int(self.personid[idx])
|
||||
item['idx'] = idx
|
||||
item['_scale'] = scale
|
||||
item['right'] = self.right[idx].copy()
|
||||
return item
|
||||
@@ -0,0 +1,25 @@
|
||||
import numpy as np
|
||||
from typing import Dict
|
||||
|
||||
class MoCapDataset:
|
||||
|
||||
def __init__(self, dataset_file: str):
|
||||
"""
|
||||
Dataset class used for loading a dataset of unpaired MANO parameter annotations
|
||||
Args:
|
||||
cfg (CfgNode): Model config file.
|
||||
dataset_file (str): Path to npz file containing dataset info.
|
||||
"""
|
||||
data = np.load(dataset_file)
|
||||
self.pose = data['hand_pose'].astype(np.float32)[:, 3:]
|
||||
self.betas = data['betas'].astype(np.float32)
|
||||
self.length = len(self.pose)
|
||||
|
||||
def __getitem__(self, idx: int) -> Dict:
|
||||
pose = self.pose[idx].copy()
|
||||
betas = self.betas[idx].copy()
|
||||
item = {'hand_pose': pose, 'betas': betas}
|
||||
return item
|
||||
|
||||
def __len__(self) -> int:
|
||||
return self.length
|
||||
+993
@@ -0,0 +1,993 @@
|
||||
"""
|
||||
Parts of the code are taken or adapted from
|
||||
https://github.com/mkocabas/EpipolarPose/blob/master/lib/utils/img_utils.py
|
||||
"""
|
||||
import torch
|
||||
import numpy as np
|
||||
from skimage.transform import rotate, resize
|
||||
from skimage.filters import gaussian
|
||||
import random
|
||||
import cv2
|
||||
from typing import List, Dict, Tuple
|
||||
from yacs.config import CfgNode
|
||||
|
||||
def expand_to_aspect_ratio(input_shape, target_aspect_ratio=None):
|
||||
"""Increase the size of the bounding box to match the target shape."""
|
||||
if target_aspect_ratio is None:
|
||||
return input_shape
|
||||
|
||||
try:
|
||||
w , h = input_shape
|
||||
except (ValueError, TypeError):
|
||||
return input_shape
|
||||
|
||||
w_t, h_t = target_aspect_ratio
|
||||
if h / w < h_t / w_t:
|
||||
h_new = max(w * h_t / w_t, h)
|
||||
w_new = w
|
||||
else:
|
||||
h_new = h
|
||||
w_new = max(h * w_t / h_t, w)
|
||||
if h_new < h or w_new < w:
|
||||
breakpoint()
|
||||
return np.array([w_new, h_new])
|
||||
|
||||
def do_augmentation(aug_config: CfgNode) -> Tuple:
|
||||
"""
|
||||
Compute random augmentation parameters.
|
||||
Args:
|
||||
aug_config (CfgNode): Config containing augmentation parameters.
|
||||
Returns:
|
||||
scale (float): Box rescaling factor.
|
||||
rot (float): Random image rotation.
|
||||
do_flip (bool): Whether to flip image or not.
|
||||
do_extreme_crop (bool): Whether to apply extreme cropping (as proposed in EFT).
|
||||
color_scale (List): Color rescaling factor
|
||||
tx (float): Random translation along the x axis.
|
||||
ty (float): Random translation along the y axis.
|
||||
"""
|
||||
|
||||
tx = np.clip(np.random.randn(), -1.0, 1.0) * aug_config.TRANS_FACTOR
|
||||
ty = np.clip(np.random.randn(), -1.0, 1.0) * aug_config.TRANS_FACTOR
|
||||
scale = np.clip(np.random.randn(), -1.0, 1.0) * aug_config.SCALE_FACTOR + 1.0
|
||||
rot = np.clip(np.random.randn(), -2.0,
|
||||
2.0) * aug_config.ROT_FACTOR if random.random() <= aug_config.ROT_AUG_RATE else 0
|
||||
do_flip = aug_config.DO_FLIP and random.random() <= aug_config.FLIP_AUG_RATE
|
||||
do_extreme_crop = random.random() <= aug_config.EXTREME_CROP_AUG_RATE
|
||||
extreme_crop_lvl = aug_config.get('EXTREME_CROP_AUG_LEVEL', 0)
|
||||
# extreme_crop_lvl = 0
|
||||
c_up = 1.0 + aug_config.COLOR_SCALE
|
||||
c_low = 1.0 - aug_config.COLOR_SCALE
|
||||
color_scale = [random.uniform(c_low, c_up), random.uniform(c_low, c_up), random.uniform(c_low, c_up)]
|
||||
return scale, rot, do_flip, do_extreme_crop, extreme_crop_lvl, color_scale, tx, ty
|
||||
|
||||
def rotate_2d(pt_2d: np.array, rot_rad: float) -> np.array:
|
||||
"""
|
||||
Rotate a 2D point on the x-y plane.
|
||||
Args:
|
||||
pt_2d (np.array): Input 2D point with shape (2,).
|
||||
rot_rad (float): Rotation angle
|
||||
Returns:
|
||||
np.array: Rotated 2D point.
|
||||
"""
|
||||
x = pt_2d[0]
|
||||
y = pt_2d[1]
|
||||
sn, cs = np.sin(rot_rad), np.cos(rot_rad)
|
||||
xx = x * cs - y * sn
|
||||
yy = x * sn + y * cs
|
||||
return np.array([xx, yy], dtype=np.float32)
|
||||
|
||||
|
||||
def gen_trans_from_patch_cv(c_x: float, c_y: float,
|
||||
src_width: float, src_height: float,
|
||||
dst_width: float, dst_height: float,
|
||||
scale: float, rot: float) -> np.array:
|
||||
"""
|
||||
Create transformation matrix for the bounding box crop.
|
||||
Args:
|
||||
c_x (float): Bounding box center x coordinate in the original image.
|
||||
c_y (float): Bounding box center y coordinate in the original image.
|
||||
src_width (float): Bounding box width.
|
||||
src_height (float): Bounding box height.
|
||||
dst_width (float): Output box width.
|
||||
dst_height (float): Output box height.
|
||||
scale (float): Rescaling factor for the bounding box (augmentation).
|
||||
rot (float): Random rotation applied to the box.
|
||||
Returns:
|
||||
trans (np.array): Target geometric transformation.
|
||||
"""
|
||||
# augment size with scale
|
||||
src_w = src_width * scale
|
||||
src_h = src_height * scale
|
||||
src_center = np.zeros(2)
|
||||
src_center[0] = c_x
|
||||
src_center[1] = c_y
|
||||
# augment rotation
|
||||
rot_rad = np.pi * rot / 180
|
||||
src_downdir = rotate_2d(np.array([0, src_h * 0.5], dtype=np.float32), rot_rad)
|
||||
src_rightdir = rotate_2d(np.array([src_w * 0.5, 0], dtype=np.float32), rot_rad)
|
||||
|
||||
dst_w = dst_width
|
||||
dst_h = dst_height
|
||||
dst_center = np.array([dst_w * 0.5, dst_h * 0.5], dtype=np.float32)
|
||||
dst_downdir = np.array([0, dst_h * 0.5], dtype=np.float32)
|
||||
dst_rightdir = np.array([dst_w * 0.5, 0], dtype=np.float32)
|
||||
|
||||
src = np.zeros((3, 2), dtype=np.float32)
|
||||
src[0, :] = src_center
|
||||
src[1, :] = src_center + src_downdir
|
||||
src[2, :] = src_center + src_rightdir
|
||||
|
||||
dst = np.zeros((3, 2), dtype=np.float32)
|
||||
dst[0, :] = dst_center
|
||||
dst[1, :] = dst_center + dst_downdir
|
||||
dst[2, :] = dst_center + dst_rightdir
|
||||
|
||||
trans = cv2.getAffineTransform(np.float32(src), np.float32(dst))
|
||||
|
||||
return trans
|
||||
|
||||
|
||||
def trans_point2d(pt_2d: np.array, trans: np.array):
|
||||
"""
|
||||
Transform a 2D point using translation matrix trans.
|
||||
Args:
|
||||
pt_2d (np.array): Input 2D point with shape (2,).
|
||||
trans (np.array): Transformation matrix.
|
||||
Returns:
|
||||
np.array: Transformed 2D point.
|
||||
"""
|
||||
src_pt = np.array([pt_2d[0], pt_2d[1], 1.]).T
|
||||
dst_pt = np.dot(trans, src_pt)
|
||||
return dst_pt[0:2]
|
||||
|
||||
def get_transform(center, scale, res, rot=0):
|
||||
"""Generate transformation matrix."""
|
||||
"""Taken from PARE: https://github.com/mkocabas/PARE/blob/6e0caca86c6ab49ff80014b661350958e5b72fd8/pare/utils/image_utils.py"""
|
||||
h = 200 * scale
|
||||
t = np.zeros((3, 3))
|
||||
t[0, 0] = float(res[1]) / h
|
||||
t[1, 1] = float(res[0]) / h
|
||||
t[0, 2] = res[1] * (-float(center[0]) / h + .5)
|
||||
t[1, 2] = res[0] * (-float(center[1]) / h + .5)
|
||||
t[2, 2] = 1
|
||||
if not rot == 0:
|
||||
rot = -rot # To match direction of rotation from cropping
|
||||
rot_mat = np.zeros((3, 3))
|
||||
rot_rad = rot * np.pi / 180
|
||||
sn, cs = np.sin(rot_rad), np.cos(rot_rad)
|
||||
rot_mat[0, :2] = [cs, -sn]
|
||||
rot_mat[1, :2] = [sn, cs]
|
||||
rot_mat[2, 2] = 1
|
||||
# Need to rotate around center
|
||||
t_mat = np.eye(3)
|
||||
t_mat[0, 2] = -res[1] / 2
|
||||
t_mat[1, 2] = -res[0] / 2
|
||||
t_inv = t_mat.copy()
|
||||
t_inv[:2, 2] *= -1
|
||||
t = np.dot(t_inv, np.dot(rot_mat, np.dot(t_mat, t)))
|
||||
return t
|
||||
|
||||
|
||||
def transform(pt, center, scale, res, invert=0, rot=0, as_int=True):
|
||||
"""Transform pixel location to different reference."""
|
||||
"""Taken from PARE: https://github.com/mkocabas/PARE/blob/6e0caca86c6ab49ff80014b661350958e5b72fd8/pare/utils/image_utils.py"""
|
||||
t = get_transform(center, scale, res, rot=rot)
|
||||
if invert:
|
||||
t = np.linalg.inv(t)
|
||||
new_pt = np.array([pt[0] - 1, pt[1] - 1, 1.]).T
|
||||
new_pt = np.dot(t, new_pt)
|
||||
if as_int:
|
||||
new_pt = new_pt.astype(int)
|
||||
return new_pt[:2] + 1
|
||||
|
||||
def crop_img(img, ul, br, border_mode=cv2.BORDER_CONSTANT, border_value=0):
|
||||
c_x = (ul[0] + br[0])/2
|
||||
c_y = (ul[1] + br[1])/2
|
||||
bb_width = patch_width = br[0] - ul[0]
|
||||
bb_height = patch_height = br[1] - ul[1]
|
||||
trans = gen_trans_from_patch_cv(c_x, c_y, bb_width, bb_height, patch_width, patch_height, 1.0, 0)
|
||||
img_patch = cv2.warpAffine(img, trans, (int(patch_width), int(patch_height)),
|
||||
flags=cv2.INTER_LINEAR,
|
||||
borderMode=border_mode,
|
||||
borderValue=border_value
|
||||
)
|
||||
|
||||
# Force borderValue=cv2.BORDER_CONSTANT for alpha channel
|
||||
if (img.shape[2] == 4) and (border_mode != cv2.BORDER_CONSTANT):
|
||||
img_patch[:,:,3] = cv2.warpAffine(img[:,:,3], trans, (int(patch_width), int(patch_height)),
|
||||
flags=cv2.INTER_LINEAR,
|
||||
borderMode=cv2.BORDER_CONSTANT,
|
||||
)
|
||||
|
||||
return img_patch
|
||||
|
||||
def generate_image_patch_skimage(img: np.array, c_x: float, c_y: float,
|
||||
bb_width: float, bb_height: float,
|
||||
patch_width: float, patch_height: float,
|
||||
do_flip: bool, scale: float, rot: float,
|
||||
border_mode=cv2.BORDER_CONSTANT, border_value=0) -> Tuple[np.array, np.array]:
|
||||
"""
|
||||
Crop image according to the supplied bounding box.
|
||||
Args:
|
||||
img (np.array): Input image of shape (H, W, 3)
|
||||
c_x (float): Bounding box center x coordinate in the original image.
|
||||
c_y (float): Bounding box center y coordinate in the original image.
|
||||
bb_width (float): Bounding box width.
|
||||
bb_height (float): Bounding box height.
|
||||
patch_width (float): Output box width.
|
||||
patch_height (float): Output box height.
|
||||
do_flip (bool): Whether to flip image or not.
|
||||
scale (float): Rescaling factor for the bounding box (augmentation).
|
||||
rot (float): Random rotation applied to the box.
|
||||
Returns:
|
||||
img_patch (np.array): Cropped image patch of shape (patch_height, patch_height, 3)
|
||||
trans (np.array): Transformation matrix.
|
||||
"""
|
||||
|
||||
img_height, img_width, img_channels = img.shape
|
||||
if do_flip:
|
||||
img = img[:, ::-1, :]
|
||||
c_x = img_width - c_x - 1
|
||||
|
||||
trans = gen_trans_from_patch_cv(c_x, c_y, bb_width, bb_height, patch_width, patch_height, scale, rot)
|
||||
|
||||
#img_patch = cv2.warpAffine(img, trans, (int(patch_width), int(patch_height)), flags=cv2.INTER_LINEAR)
|
||||
|
||||
# skimage
|
||||
center = np.zeros(2)
|
||||
center[0] = c_x
|
||||
center[1] = c_y
|
||||
res = np.zeros(2)
|
||||
res[0] = patch_width
|
||||
res[1] = patch_height
|
||||
# assumes bb_width = bb_height
|
||||
# assumes patch_width = patch_height
|
||||
assert bb_width == bb_height, f'{bb_width=} != {bb_height=}'
|
||||
assert patch_width == patch_height, f'{patch_width=} != {patch_height=}'
|
||||
scale1 = scale*bb_width/200.
|
||||
|
||||
# Upper left point
|
||||
ul = np.array(transform([1, 1], center, scale1, res, invert=1, as_int=False)) - 1
|
||||
# Bottom right point
|
||||
br = np.array(transform([res[0] + 1,
|
||||
res[1] + 1], center, scale1, res, invert=1, as_int=False)) - 1
|
||||
|
||||
# Padding so that when rotated proper amount of context is included
|
||||
try:
|
||||
pad = int(np.linalg.norm(br - ul) / 2 - float(br[1] - ul[1]) / 2) + 1
|
||||
except:
|
||||
breakpoint()
|
||||
if not rot == 0:
|
||||
ul -= pad
|
||||
br += pad
|
||||
|
||||
|
||||
if False:
|
||||
# Old way of cropping image
|
||||
ul_int = ul.astype(int)
|
||||
br_int = br.astype(int)
|
||||
new_shape = [br_int[1] - ul_int[1], br_int[0] - ul_int[0]]
|
||||
if len(img.shape) > 2:
|
||||
new_shape += [img.shape[2]]
|
||||
new_img = np.zeros(new_shape)
|
||||
|
||||
# Range to fill new array
|
||||
new_x = max(0, -ul_int[0]), min(br_int[0], len(img[0])) - ul_int[0]
|
||||
new_y = max(0, -ul_int[1]), min(br_int[1], len(img)) - ul_int[1]
|
||||
# Range to sample from original image
|
||||
old_x = max(0, ul_int[0]), min(len(img[0]), br_int[0])
|
||||
old_y = max(0, ul_int[1]), min(len(img), br_int[1])
|
||||
new_img[new_y[0]:new_y[1], new_x[0]:new_x[1]] = img[old_y[0]:old_y[1],
|
||||
old_x[0]:old_x[1]]
|
||||
|
||||
# New way of cropping image
|
||||
new_img = crop_img(img, ul, br, border_mode=border_mode, border_value=border_value).astype(np.float32)
|
||||
|
||||
# print(f'{new_img.shape=}')
|
||||
# print(f'{new_img1.shape=}')
|
||||
# print(f'{np.allclose(new_img, new_img1)=}')
|
||||
# print(f'{img.dtype=}')
|
||||
|
||||
|
||||
if not rot == 0:
|
||||
# Remove padding
|
||||
|
||||
new_img = rotate(new_img, rot) # scipy.misc.imrotate(new_img, rot)
|
||||
new_img = new_img[pad:-pad, pad:-pad]
|
||||
|
||||
if new_img.shape[0] < 1 or new_img.shape[1] < 1:
|
||||
print(f'{img.shape=}')
|
||||
print(f'{new_img.shape=}')
|
||||
print(f'{ul=}')
|
||||
print(f'{br=}')
|
||||
print(f'{pad=}')
|
||||
print(f'{rot=}')
|
||||
|
||||
breakpoint()
|
||||
|
||||
# resize image
|
||||
new_img = resize(new_img, res) # scipy.misc.imresize(new_img, res)
|
||||
|
||||
new_img = np.clip(new_img, 0, 255).astype(np.uint8)
|
||||
|
||||
return new_img, trans
|
||||
|
||||
|
||||
def generate_image_patch_cv2(img: np.array, c_x: float, c_y: float,
|
||||
bb_width: float, bb_height: float,
|
||||
patch_width: float, patch_height: float,
|
||||
do_flip: bool, scale: float, rot: float,
|
||||
border_mode=cv2.BORDER_CONSTANT, border_value=0) -> Tuple[np.array, np.array]:
|
||||
"""
|
||||
Crop the input image and return the crop and the corresponding transformation matrix.
|
||||
Args:
|
||||
img (np.array): Input image of shape (H, W, 3)
|
||||
c_x (float): Bounding box center x coordinate in the original image.
|
||||
c_y (float): Bounding box center y coordinate in the original image.
|
||||
bb_width (float): Bounding box width.
|
||||
bb_height (float): Bounding box height.
|
||||
patch_width (float): Output box width.
|
||||
patch_height (float): Output box height.
|
||||
do_flip (bool): Whether to flip image or not.
|
||||
scale (float): Rescaling factor for the bounding box (augmentation).
|
||||
rot (float): Random rotation applied to the box.
|
||||
Returns:
|
||||
img_patch (np.array): Cropped image patch of shape (patch_height, patch_height, 3)
|
||||
trans (np.array): Transformation matrix.
|
||||
"""
|
||||
|
||||
img_height, img_width, img_channels = img.shape
|
||||
if do_flip:
|
||||
img = img[:, ::-1, :]
|
||||
c_x = img_width - c_x - 1
|
||||
|
||||
|
||||
trans = gen_trans_from_patch_cv(c_x, c_y, bb_width, bb_height, patch_width, patch_height, scale, rot)
|
||||
|
||||
img_patch = cv2.warpAffine(img, trans, (int(patch_width), int(patch_height)),
|
||||
flags=cv2.INTER_LINEAR,
|
||||
borderMode=border_mode,
|
||||
borderValue=border_value,
|
||||
)
|
||||
# Force borderValue=cv2.BORDER_CONSTANT for alpha channel
|
||||
if (img.shape[2] == 4) and (border_mode != cv2.BORDER_CONSTANT):
|
||||
img_patch[:,:,3] = cv2.warpAffine(img[:,:,3], trans, (int(patch_width), int(patch_height)),
|
||||
flags=cv2.INTER_LINEAR,
|
||||
borderMode=cv2.BORDER_CONSTANT,
|
||||
)
|
||||
|
||||
return img_patch, trans
|
||||
|
||||
|
||||
def convert_cvimg_to_tensor(cvimg: np.array):
|
||||
"""
|
||||
Convert image from HWC to CHW format.
|
||||
Args:
|
||||
cvimg (np.array): Image of shape (H, W, 3) as loaded by OpenCV.
|
||||
Returns:
|
||||
np.array: Output image of shape (3, H, W).
|
||||
"""
|
||||
# from h,w,c(OpenCV) to c,h,w
|
||||
img = cvimg.copy()
|
||||
img = np.transpose(img, (2, 0, 1))
|
||||
# from int to float
|
||||
img = img.astype(np.float32)
|
||||
return img
|
||||
|
||||
def fliplr_params(mano_params: Dict, has_mano_params: Dict) -> Tuple[Dict, Dict]:
|
||||
"""
|
||||
Flip MANO parameters when flipping the image.
|
||||
Args:
|
||||
mano_params (Dict): MANO parameter annotations.
|
||||
has_mano_params (Dict): Whether MANO annotations are valid.
|
||||
Returns:
|
||||
Dict, Dict: Flipped MANO parameters and valid flags.
|
||||
"""
|
||||
global_orient = mano_params['global_orient'].copy()
|
||||
hand_pose = mano_params['hand_pose'].copy()
|
||||
betas = mano_params['betas'].copy()
|
||||
has_global_orient = has_mano_params['global_orient'].copy()
|
||||
has_hand_pose = has_mano_params['hand_pose'].copy()
|
||||
has_betas = has_mano_params['betas'].copy()
|
||||
|
||||
global_orient[1::3] *= -1
|
||||
global_orient[2::3] *= -1
|
||||
hand_pose[1::3] *= -1
|
||||
hand_pose[2::3] *= -1
|
||||
|
||||
mano_params = {'global_orient': global_orient.astype(np.float32),
|
||||
'hand_pose': hand_pose.astype(np.float32),
|
||||
'betas': betas.astype(np.float32)
|
||||
}
|
||||
|
||||
has_mano_params = {'global_orient': has_global_orient,
|
||||
'hand_pose': has_hand_pose,
|
||||
'betas': has_betas
|
||||
}
|
||||
|
||||
return mano_params, has_mano_params
|
||||
|
||||
|
||||
def fliplr_keypoints(joints: np.array, width: float, flip_permutation: List[int]) -> np.array:
|
||||
"""
|
||||
Flip 2D or 3D keypoints.
|
||||
Args:
|
||||
joints (np.array): Array of shape (N, 3) or (N, 4) containing 2D or 3D keypoint locations and confidence.
|
||||
flip_permutation (List): Permutation to apply after flipping.
|
||||
Returns:
|
||||
np.array: Flipped 2D or 3D keypoints with shape (N, 3) or (N, 4) respectively.
|
||||
"""
|
||||
joints = joints.copy()
|
||||
# Flip horizontal
|
||||
joints[:, 0] = width - joints[:, 0] - 1
|
||||
joints = joints[flip_permutation, :]
|
||||
|
||||
return joints
|
||||
|
||||
def keypoint_3d_processing(keypoints_3d: np.array, flip_permutation: List[int], rot: float, do_flip: float) -> np.array:
|
||||
"""
|
||||
Process 3D keypoints (rotation/flipping).
|
||||
Args:
|
||||
keypoints_3d (np.array): Input array of shape (N, 4) containing the 3D keypoints and confidence.
|
||||
flip_permutation (List): Permutation to apply after flipping.
|
||||
rot (float): Random rotation applied to the keypoints.
|
||||
do_flip (bool): Whether to flip keypoints or not.
|
||||
Returns:
|
||||
np.array: Transformed 3D keypoints with shape (N, 4).
|
||||
"""
|
||||
if do_flip:
|
||||
keypoints_3d = fliplr_keypoints(keypoints_3d, 1, flip_permutation)
|
||||
# in-plane rotation
|
||||
rot_mat = np.eye(3)
|
||||
if not rot == 0:
|
||||
rot_rad = -rot * np.pi / 180
|
||||
sn,cs = np.sin(rot_rad), np.cos(rot_rad)
|
||||
rot_mat[0,:2] = [cs, -sn]
|
||||
rot_mat[1,:2] = [sn, cs]
|
||||
keypoints_3d[:, :-1] = np.einsum('ij,kj->ki', rot_mat, keypoints_3d[:, :-1])
|
||||
# flip the x coordinates
|
||||
keypoints_3d = keypoints_3d.astype('float32')
|
||||
return keypoints_3d
|
||||
|
||||
def rot_aa(aa: np.array, rot: float) -> np.array:
|
||||
"""
|
||||
Rotate axis angle parameters.
|
||||
Args:
|
||||
aa (np.array): Axis-angle vector of shape (3,).
|
||||
rot (np.array): Rotation angle in degrees.
|
||||
Returns:
|
||||
np.array: Rotated axis-angle vector.
|
||||
"""
|
||||
# pose parameters
|
||||
R = np.array([[np.cos(np.deg2rad(-rot)), -np.sin(np.deg2rad(-rot)), 0],
|
||||
[np.sin(np.deg2rad(-rot)), np.cos(np.deg2rad(-rot)), 0],
|
||||
[0, 0, 1]])
|
||||
# find the rotation of the hand in camera frame
|
||||
per_rdg, _ = cv2.Rodrigues(aa)
|
||||
# apply the global rotation to the global orientation
|
||||
resrot, _ = cv2.Rodrigues(np.dot(R,per_rdg))
|
||||
aa = (resrot.T)[0]
|
||||
return aa.astype(np.float32)
|
||||
|
||||
def mano_param_processing(mano_params: Dict, has_mano_params: Dict, rot: float, do_flip: bool) -> Tuple[Dict, Dict]:
|
||||
"""
|
||||
Apply random augmentations to the MANO parameters.
|
||||
Args:
|
||||
mano_params (Dict): MANO parameter annotations.
|
||||
has_mano_params (Dict): Whether mano annotations are valid.
|
||||
rot (float): Random rotation applied to the keypoints.
|
||||
do_flip (bool): Whether to flip keypoints or not.
|
||||
Returns:
|
||||
Dict, Dict: Transformed MANO parameters and valid flags.
|
||||
"""
|
||||
if do_flip:
|
||||
mano_params, has_mano_params = fliplr_params(mano_params, has_mano_params)
|
||||
mano_params['global_orient'] = rot_aa(mano_params['global_orient'], rot)
|
||||
return mano_params, has_mano_params
|
||||
|
||||
|
||||
|
||||
def get_example(img_path: str|np.ndarray, center_x: float, center_y: float,
|
||||
width: float, height: float,
|
||||
keypoints_2d: np.array, keypoints_3d: np.array,
|
||||
mano_params: Dict, has_mano_params: Dict,
|
||||
flip_kp_permutation: List[int],
|
||||
patch_width: int, patch_height: int,
|
||||
mean: np.array, std: np.array,
|
||||
do_augment: bool, is_right: bool, augm_config: CfgNode,
|
||||
is_bgr: bool = True,
|
||||
use_skimage_antialias: bool = False,
|
||||
border_mode: int = cv2.BORDER_CONSTANT,
|
||||
return_trans: bool = False) -> Tuple:
|
||||
"""
|
||||
Get an example from the dataset and (possibly) apply random augmentations.
|
||||
Args:
|
||||
img_path (str): Image filename
|
||||
center_x (float): Bounding box center x coordinate in the original image.
|
||||
center_y (float): Bounding box center y coordinate in the original image.
|
||||
width (float): Bounding box width.
|
||||
height (float): Bounding box height.
|
||||
keypoints_2d (np.array): Array with shape (N,3) containing the 2D keypoints in the original image coordinates.
|
||||
keypoints_3d (np.array): Array with shape (N,4) containing the 3D keypoints.
|
||||
mano_params (Dict): MANO parameter annotations.
|
||||
has_mano_params (Dict): Whether MANO annotations are valid.
|
||||
flip_kp_permutation (List): Permutation to apply to the keypoints after flipping.
|
||||
patch_width (float): Output box width.
|
||||
patch_height (float): Output box height.
|
||||
mean (np.array): Array of shape (3,) containing the mean for normalizing the input image.
|
||||
std (np.array): Array of shape (3,) containing the std for normalizing the input image.
|
||||
do_augment (bool): Whether to apply data augmentation or not.
|
||||
aug_config (CfgNode): Config containing augmentation parameters.
|
||||
Returns:
|
||||
return img_patch, keypoints_2d, keypoints_3d, mano_params, has_mano_params, img_size
|
||||
img_patch (np.array): Cropped image patch of shape (3, patch_height, patch_height)
|
||||
keypoints_2d (np.array): Array with shape (N,3) containing the transformed 2D keypoints.
|
||||
keypoints_3d (np.array): Array with shape (N,4) containing the transformed 3D keypoints.
|
||||
mano_params (Dict): Transformed MANO parameters.
|
||||
has_mano_params (Dict): Valid flag for transformed MANO parameters.
|
||||
img_size (np.array): Image size of the original image.
|
||||
"""
|
||||
if isinstance(img_path, str):
|
||||
# 1. load image
|
||||
cvimg = cv2.imread(img_path, cv2.IMREAD_COLOR | cv2.IMREAD_IGNORE_ORIENTATION)
|
||||
if not isinstance(cvimg, np.ndarray):
|
||||
raise IOError("Fail to read %s" % img_path)
|
||||
elif isinstance(img_path, np.ndarray):
|
||||
cvimg = img_path
|
||||
else:
|
||||
raise TypeError('img_path must be either a string or a numpy array')
|
||||
img_height, img_width, img_channels = cvimg.shape
|
||||
|
||||
img_size = np.array([img_height, img_width])
|
||||
|
||||
# 2. get augmentation params
|
||||
if do_augment:
|
||||
scale, rot, do_flip, do_extreme_crop, extreme_crop_lvl, color_scale, tx, ty = do_augmentation(augm_config)
|
||||
else:
|
||||
scale, rot, do_flip, do_extreme_crop, extreme_crop_lvl, color_scale, tx, ty = 1.0, 0, False, False, 0, [1.0, 1.0, 1.0], 0., 0.
|
||||
|
||||
# if it's a left hand, we flip
|
||||
if not is_right:
|
||||
do_flip = True
|
||||
|
||||
if width < 1 or height < 1:
|
||||
breakpoint()
|
||||
|
||||
if do_extreme_crop:
|
||||
if extreme_crop_lvl == 0:
|
||||
center_x1, center_y1, width1, height1 = extreme_cropping(center_x, center_y, width, height, keypoints_2d)
|
||||
elif extreme_crop_lvl == 1:
|
||||
center_x1, center_y1, width1, height1 = extreme_cropping_aggressive(center_x, center_y, width, height, keypoints_2d)
|
||||
|
||||
THRESH = 4
|
||||
if width1 < THRESH or height1 < THRESH:
|
||||
# print(f'{do_extreme_crop=}')
|
||||
# print(f'width: {width}, height: {height}')
|
||||
# print(f'width1: {width1}, height1: {height1}')
|
||||
# print(f'center_x: {center_x}, center_y: {center_y}')
|
||||
# print(f'center_x1: {center_x1}, center_y1: {center_y1}')
|
||||
# print(f'keypoints_2d: {keypoints_2d}')
|
||||
# print(f'\n\n', flush=True)
|
||||
# breakpoint()
|
||||
pass
|
||||
# print(f'skip ==> width1: {width1}, height1: {height1}, width: {width}, height: {height}')
|
||||
else:
|
||||
center_x, center_y, width, height = center_x1, center_y1, width1, height1
|
||||
|
||||
center_x += width * tx
|
||||
center_y += height * ty
|
||||
|
||||
# Process 3D keypoints
|
||||
keypoints_3d = keypoint_3d_processing(keypoints_3d, flip_kp_permutation, rot, do_flip)
|
||||
|
||||
# 3. generate image patch
|
||||
if use_skimage_antialias:
|
||||
# Blur image to avoid aliasing artifacts
|
||||
downsampling_factor = (patch_width / (width*scale))
|
||||
if downsampling_factor > 1.1:
|
||||
cvimg = gaussian(cvimg, sigma=(downsampling_factor-1)/2, channel_axis=2, preserve_range=True, truncate=3.0)
|
||||
|
||||
img_patch_cv, trans = generate_image_patch_cv2(cvimg,
|
||||
center_x, center_y,
|
||||
width, height,
|
||||
patch_width, patch_height,
|
||||
do_flip, scale, rot,
|
||||
border_mode=border_mode)
|
||||
# img_patch_cv, trans = generate_image_patch_skimage(cvimg,
|
||||
# center_x, center_y,
|
||||
# width, height,
|
||||
# patch_width, patch_height,
|
||||
# do_flip, scale, rot,
|
||||
# border_mode=border_mode)
|
||||
|
||||
image = img_patch_cv.copy()
|
||||
if is_bgr:
|
||||
image = image[:, :, ::-1]
|
||||
img_patch_cv = image.copy()
|
||||
img_patch = convert_cvimg_to_tensor(image)
|
||||
|
||||
|
||||
mano_params, has_mano_params = mano_param_processing(mano_params, has_mano_params, rot, do_flip)
|
||||
|
||||
# apply normalization
|
||||
for n_c in range(min(img_channels, 3)):
|
||||
img_patch[n_c, :, :] = np.clip(img_patch[n_c, :, :] * color_scale[n_c], 0, 255)
|
||||
if mean is not None and std is not None:
|
||||
img_patch[n_c, :, :] = (img_patch[n_c, :, :] - mean[n_c]) / std[n_c]
|
||||
if do_flip:
|
||||
keypoints_2d = fliplr_keypoints(keypoints_2d, img_width, flip_kp_permutation)
|
||||
|
||||
|
||||
for n_jt in range(len(keypoints_2d)):
|
||||
keypoints_2d[n_jt, 0:2] = trans_point2d(keypoints_2d[n_jt, 0:2], trans)
|
||||
keypoints_2d[:, :-1] = keypoints_2d[:, :-1] / patch_width - 0.5
|
||||
|
||||
if not return_trans:
|
||||
return img_patch, keypoints_2d, keypoints_3d, mano_params, has_mano_params, img_size
|
||||
else:
|
||||
return img_patch, keypoints_2d, keypoints_3d, mano_params, has_mano_params, img_size, trans
|
||||
|
||||
def crop_to_hips(center_x: float, center_y: float, width: float, height: float, keypoints_2d: np.array) -> Tuple:
|
||||
"""
|
||||
Extreme cropping: Crop the box up to the hip locations.
|
||||
Args:
|
||||
center_x (float): x coordinate of the bounding box center.
|
||||
center_y (float): y coordinate of the bounding box center.
|
||||
width (float): Bounding box width.
|
||||
height (float): Bounding box height.
|
||||
keypoints_2d (np.array): Array of shape (N, 3) containing 2D keypoint locations.
|
||||
Returns:
|
||||
center_x (float): x coordinate of the new bounding box center.
|
||||
center_y (float): y coordinate of the new bounding box center.
|
||||
width (float): New bounding box width.
|
||||
height (float): New bounding box height.
|
||||
"""
|
||||
keypoints_2d = keypoints_2d.copy()
|
||||
lower_body_keypoints = [10, 11, 13, 14, 19, 20, 21, 22, 23, 24, 25+0, 25+1, 25+4, 25+5]
|
||||
keypoints_2d[lower_body_keypoints, :] = 0
|
||||
if keypoints_2d[:, -1].sum() > 1:
|
||||
center, scale = get_bbox(keypoints_2d)
|
||||
center_x = center[0]
|
||||
center_y = center[1]
|
||||
width = 1.1 * scale[0]
|
||||
height = 1.1 * scale[1]
|
||||
return center_x, center_y, width, height
|
||||
|
||||
|
||||
def crop_to_shoulders(center_x: float, center_y: float, width: float, height: float, keypoints_2d: np.array):
|
||||
"""
|
||||
Extreme cropping: Crop the box up to the shoulder locations.
|
||||
Args:
|
||||
center_x (float): x coordinate of the bounding box center.
|
||||
center_y (float): y coordinate of the bounding box center.
|
||||
width (float): Bounding box width.
|
||||
height (float): Bounding box height.
|
||||
keypoints_2d (np.array): Array of shape (N, 3) containing 2D keypoint locations.
|
||||
Returns:
|
||||
center_x (float): x coordinate of the new bounding box center.
|
||||
center_y (float): y coordinate of the new bounding box center.
|
||||
width (float): New bounding box width.
|
||||
height (float): New bounding box height.
|
||||
"""
|
||||
keypoints_2d = keypoints_2d.copy()
|
||||
lower_body_keypoints = [3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 19, 20, 21, 22, 23, 24] + [25 + i for i in [0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 14, 15, 16]]
|
||||
keypoints_2d[lower_body_keypoints, :] = 0
|
||||
center, scale = get_bbox(keypoints_2d)
|
||||
if keypoints_2d[:, -1].sum() > 1:
|
||||
center, scale = get_bbox(keypoints_2d)
|
||||
center_x = center[0]
|
||||
center_y = center[1]
|
||||
width = 1.2 * scale[0]
|
||||
height = 1.2 * scale[1]
|
||||
return center_x, center_y, width, height
|
||||
|
||||
def crop_to_head(center_x: float, center_y: float, width: float, height: float, keypoints_2d: np.array):
|
||||
"""
|
||||
Extreme cropping: Crop the box and keep on only the head.
|
||||
Args:
|
||||
center_x (float): x coordinate of the bounding box center.
|
||||
center_y (float): y coordinate of the bounding box center.
|
||||
width (float): Bounding box width.
|
||||
height (float): Bounding box height.
|
||||
keypoints_2d (np.array): Array of shape (N, 3) containing 2D keypoint locations.
|
||||
Returns:
|
||||
center_x (float): x coordinate of the new bounding box center.
|
||||
center_y (float): y coordinate of the new bounding box center.
|
||||
width (float): New bounding box width.
|
||||
height (float): New bounding box height.
|
||||
"""
|
||||
keypoints_2d = keypoints_2d.copy()
|
||||
lower_body_keypoints = [3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 19, 20, 21, 22, 23, 24] + [25 + i for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15, 16]]
|
||||
keypoints_2d[lower_body_keypoints, :] = 0
|
||||
if keypoints_2d[:, -1].sum() > 1:
|
||||
center, scale = get_bbox(keypoints_2d)
|
||||
center_x = center[0]
|
||||
center_y = center[1]
|
||||
width = 1.3 * scale[0]
|
||||
height = 1.3 * scale[1]
|
||||
return center_x, center_y, width, height
|
||||
|
||||
def crop_torso_only(center_x: float, center_y: float, width: float, height: float, keypoints_2d: np.array):
|
||||
"""
|
||||
Extreme cropping: Crop the box and keep on only the torso.
|
||||
Args:
|
||||
center_x (float): x coordinate of the bounding box center.
|
||||
center_y (float): y coordinate of the bounding box center.
|
||||
width (float): Bounding box width.
|
||||
height (float): Bounding box height.
|
||||
keypoints_2d (np.array): Array of shape (N, 3) containing 2D keypoint locations.
|
||||
Returns:
|
||||
center_x (float): x coordinate of the new bounding box center.
|
||||
center_y (float): y coordinate of the new bounding box center.
|
||||
width (float): New bounding box width.
|
||||
height (float): New bounding box height.
|
||||
"""
|
||||
keypoints_2d = keypoints_2d.copy()
|
||||
nontorso_body_keypoints = [0, 3, 4, 6, 7, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] + [25 + i for i in [0, 1, 4, 5, 6, 7, 10, 11, 13, 17, 18]]
|
||||
keypoints_2d[nontorso_body_keypoints, :] = 0
|
||||
if keypoints_2d[:, -1].sum() > 1:
|
||||
center, scale = get_bbox(keypoints_2d)
|
||||
center_x = center[0]
|
||||
center_y = center[1]
|
||||
width = 1.1 * scale[0]
|
||||
height = 1.1 * scale[1]
|
||||
return center_x, center_y, width, height
|
||||
|
||||
def crop_rightarm_only(center_x: float, center_y: float, width: float, height: float, keypoints_2d: np.array):
|
||||
"""
|
||||
Extreme cropping: Crop the box and keep on only the right arm.
|
||||
Args:
|
||||
center_x (float): x coordinate of the bounding box center.
|
||||
center_y (float): y coordinate of the bounding box center.
|
||||
width (float): Bounding box width.
|
||||
height (float): Bounding box height.
|
||||
keypoints_2d (np.array): Array of shape (N, 3) containing 2D keypoint locations.
|
||||
Returns:
|
||||
center_x (float): x coordinate of the new bounding box center.
|
||||
center_y (float): y coordinate of the new bounding box center.
|
||||
width (float): New bounding box width.
|
||||
height (float): New bounding box height.
|
||||
"""
|
||||
keypoints_2d = keypoints_2d.copy()
|
||||
nonrightarm_body_keypoints = [0, 1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] + [25 + i for i in [0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]]
|
||||
keypoints_2d[nonrightarm_body_keypoints, :] = 0
|
||||
if keypoints_2d[:, -1].sum() > 1:
|
||||
center, scale = get_bbox(keypoints_2d)
|
||||
center_x = center[0]
|
||||
center_y = center[1]
|
||||
width = 1.1 * scale[0]
|
||||
height = 1.1 * scale[1]
|
||||
return center_x, center_y, width, height
|
||||
|
||||
def crop_leftarm_only(center_x: float, center_y: float, width: float, height: float, keypoints_2d: np.array):
|
||||
"""
|
||||
Extreme cropping: Crop the box and keep on only the left arm.
|
||||
Args:
|
||||
center_x (float): x coordinate of the bounding box center.
|
||||
center_y (float): y coordinate of the bounding box center.
|
||||
width (float): Bounding box width.
|
||||
height (float): Bounding box height.
|
||||
keypoints_2d (np.array): Array of shape (N, 3) containing 2D keypoint locations.
|
||||
Returns:
|
||||
center_x (float): x coordinate of the new bounding box center.
|
||||
center_y (float): y coordinate of the new bounding box center.
|
||||
width (float): New bounding box width.
|
||||
height (float): New bounding box height.
|
||||
"""
|
||||
keypoints_2d = keypoints_2d.copy()
|
||||
nonleftarm_body_keypoints = [0, 1, 2, 3, 4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] + [25 + i for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 13, 14, 15, 16, 17, 18]]
|
||||
keypoints_2d[nonleftarm_body_keypoints, :] = 0
|
||||
if keypoints_2d[:, -1].sum() > 1:
|
||||
center, scale = get_bbox(keypoints_2d)
|
||||
center_x = center[0]
|
||||
center_y = center[1]
|
||||
width = 1.1 * scale[0]
|
||||
height = 1.1 * scale[1]
|
||||
return center_x, center_y, width, height
|
||||
|
||||
def crop_legs_only(center_x: float, center_y: float, width: float, height: float, keypoints_2d: np.array):
|
||||
"""
|
||||
Extreme cropping: Crop the box and keep on only the legs.
|
||||
Args:
|
||||
center_x (float): x coordinate of the bounding box center.
|
||||
center_y (float): y coordinate of the bounding box center.
|
||||
width (float): Bounding box width.
|
||||
height (float): Bounding box height.
|
||||
keypoints_2d (np.array): Array of shape (N, 3) containing 2D keypoint locations.
|
||||
Returns:
|
||||
center_x (float): x coordinate of the new bounding box center.
|
||||
center_y (float): y coordinate of the new bounding box center.
|
||||
width (float): New bounding box width.
|
||||
height (float): New bounding box height.
|
||||
"""
|
||||
keypoints_2d = keypoints_2d.copy()
|
||||
nonlegs_body_keypoints = [0, 1, 2, 3, 4, 5, 6, 7, 15, 16, 17, 18] + [25 + i for i in [6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18]]
|
||||
keypoints_2d[nonlegs_body_keypoints, :] = 0
|
||||
if keypoints_2d[:, -1].sum() > 1:
|
||||
center, scale = get_bbox(keypoints_2d)
|
||||
center_x = center[0]
|
||||
center_y = center[1]
|
||||
width = 1.1 * scale[0]
|
||||
height = 1.1 * scale[1]
|
||||
return center_x, center_y, width, height
|
||||
|
||||
def crop_rightleg_only(center_x: float, center_y: float, width: float, height: float, keypoints_2d: np.array):
|
||||
"""
|
||||
Extreme cropping: Crop the box and keep on only the right leg.
|
||||
Args:
|
||||
center_x (float): x coordinate of the bounding box center.
|
||||
center_y (float): y coordinate of the bounding box center.
|
||||
width (float): Bounding box width.
|
||||
height (float): Bounding box height.
|
||||
keypoints_2d (np.array): Array of shape (N, 3) containing 2D keypoint locations.
|
||||
Returns:
|
||||
center_x (float): x coordinate of the new bounding box center.
|
||||
center_y (float): y coordinate of the new bounding box center.
|
||||
width (float): New bounding box width.
|
||||
height (float): New bounding box height.
|
||||
"""
|
||||
keypoints_2d = keypoints_2d.copy()
|
||||
nonrightleg_body_keypoints = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21] + [25 + i for i in [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]]
|
||||
keypoints_2d[nonrightleg_body_keypoints, :] = 0
|
||||
if keypoints_2d[:, -1].sum() > 1:
|
||||
center, scale = get_bbox(keypoints_2d)
|
||||
center_x = center[0]
|
||||
center_y = center[1]
|
||||
width = 1.1 * scale[0]
|
||||
height = 1.1 * scale[1]
|
||||
return center_x, center_y, width, height
|
||||
|
||||
def crop_leftleg_only(center_x: float, center_y: float, width: float, height: float, keypoints_2d: np.array):
|
||||
"""
|
||||
Extreme cropping: Crop the box and keep on only the left leg.
|
||||
Args:
|
||||
center_x (float): x coordinate of the bounding box center.
|
||||
center_y (float): y coordinate of the bounding box center.
|
||||
width (float): Bounding box width.
|
||||
height (float): Bounding box height.
|
||||
keypoints_2d (np.array): Array of shape (N, 3) containing 2D keypoint locations.
|
||||
Returns:
|
||||
center_x (float): x coordinate of the new bounding box center.
|
||||
center_y (float): y coordinate of the new bounding box center.
|
||||
width (float): New bounding box width.
|
||||
height (float): New bounding box height.
|
||||
"""
|
||||
keypoints_2d = keypoints_2d.copy()
|
||||
nonleftleg_body_keypoints = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 15, 16, 17, 18, 22, 23, 24] + [25 + i for i in [0, 1, 2, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]]
|
||||
keypoints_2d[nonleftleg_body_keypoints, :] = 0
|
||||
if keypoints_2d[:, -1].sum() > 1:
|
||||
center, scale = get_bbox(keypoints_2d)
|
||||
center_x = center[0]
|
||||
center_y = center[1]
|
||||
width = 1.1 * scale[0]
|
||||
height = 1.1 * scale[1]
|
||||
return center_x, center_y, width, height
|
||||
|
||||
def full_body(keypoints_2d: np.array) -> bool:
|
||||
"""
|
||||
Check if all main body joints are visible.
|
||||
Args:
|
||||
keypoints_2d (np.array): Array of shape (N, 3) containing 2D keypoint locations.
|
||||
Returns:
|
||||
bool: True if all main body joints are visible.
|
||||
"""
|
||||
|
||||
body_keypoints_openpose = [2, 3, 4, 5, 6, 7, 10, 11, 13, 14]
|
||||
body_keypoints = [25 + i for i in [8, 7, 6, 9, 10, 11, 1, 0, 4, 5]]
|
||||
return (np.maximum(keypoints_2d[body_keypoints, -1], keypoints_2d[body_keypoints_openpose, -1]) > 0).sum() == len(body_keypoints)
|
||||
|
||||
def upper_body(keypoints_2d: np.array):
|
||||
"""
|
||||
Check if all upper body joints are visible.
|
||||
Args:
|
||||
keypoints_2d (np.array): Array of shape (N, 3) containing 2D keypoint locations.
|
||||
Returns:
|
||||
bool: True if all main body joints are visible.
|
||||
"""
|
||||
lower_body_keypoints_openpose = [10, 11, 13, 14]
|
||||
lower_body_keypoints = [25 + i for i in [1, 0, 4, 5]]
|
||||
upper_body_keypoints_openpose = [0, 1, 15, 16, 17, 18]
|
||||
upper_body_keypoints = [25+8, 25+9, 25+12, 25+13, 25+17, 25+18]
|
||||
return ((keypoints_2d[lower_body_keypoints + lower_body_keypoints_openpose, -1] > 0).sum() == 0)\
|
||||
and ((keypoints_2d[upper_body_keypoints + upper_body_keypoints_openpose, -1] > 0).sum() >= 2)
|
||||
|
||||
def get_bbox(keypoints_2d: np.array, rescale: float = 1.2) -> Tuple:
|
||||
"""
|
||||
Get center and scale for bounding box from openpose detections.
|
||||
Args:
|
||||
keypoints_2d (np.array): Array of shape (N, 3) containing 2D keypoint locations.
|
||||
rescale (float): Scale factor to rescale bounding boxes computed from the keypoints.
|
||||
Returns:
|
||||
center (np.array): Array of shape (2,) containing the new bounding box center.
|
||||
scale (float): New bounding box scale.
|
||||
"""
|
||||
valid = keypoints_2d[:,-1] > 0
|
||||
valid_keypoints = keypoints_2d[valid][:,:-1]
|
||||
center = 0.5 * (valid_keypoints.max(axis=0) + valid_keypoints.min(axis=0))
|
||||
bbox_size = (valid_keypoints.max(axis=0) - valid_keypoints.min(axis=0))
|
||||
# adjust bounding box tightness
|
||||
scale = bbox_size
|
||||
scale *= rescale
|
||||
return center, scale
|
||||
|
||||
def extreme_cropping(center_x: float, center_y: float, width: float, height: float, keypoints_2d: np.array) -> Tuple:
|
||||
"""
|
||||
Perform extreme cropping
|
||||
Args:
|
||||
center_x (float): x coordinate of bounding box center.
|
||||
center_y (float): y coordinate of bounding box center.
|
||||
width (float): bounding box width.
|
||||
height (float): bounding box height.
|
||||
keypoints_2d (np.array): Array of shape (N, 3) containing 2D keypoint locations.
|
||||
rescale (float): Scale factor to rescale bounding boxes computed from the keypoints.
|
||||
Returns:
|
||||
center_x (float): x coordinate of bounding box center.
|
||||
center_y (float): y coordinate of bounding box center.
|
||||
width (float): bounding box width.
|
||||
height (float): bounding box height.
|
||||
"""
|
||||
p = torch.rand(1).item()
|
||||
if full_body(keypoints_2d):
|
||||
if p < 0.7:
|
||||
center_x, center_y, width, height = crop_to_hips(center_x, center_y, width, height, keypoints_2d)
|
||||
elif p < 0.9:
|
||||
center_x, center_y, width, height = crop_to_shoulders(center_x, center_y, width, height, keypoints_2d)
|
||||
else:
|
||||
center_x, center_y, width, height = crop_to_head(center_x, center_y, width, height, keypoints_2d)
|
||||
elif upper_body(keypoints_2d):
|
||||
if p < 0.9:
|
||||
center_x, center_y, width, height = crop_to_shoulders(center_x, center_y, width, height, keypoints_2d)
|
||||
else:
|
||||
center_x, center_y, width, height = crop_to_head(center_x, center_y, width, height, keypoints_2d)
|
||||
|
||||
return center_x, center_y, max(width, height), max(width, height)
|
||||
|
||||
def extreme_cropping_aggressive(center_x: float, center_y: float, width: float, height: float, keypoints_2d: np.array) -> Tuple:
|
||||
"""
|
||||
Perform aggressive extreme cropping
|
||||
Args:
|
||||
center_x (float): x coordinate of bounding box center.
|
||||
center_y (float): y coordinate of bounding box center.
|
||||
width (float): bounding box width.
|
||||
height (float): bounding box height.
|
||||
keypoints_2d (np.array): Array of shape (N, 3) containing 2D keypoint locations.
|
||||
rescale (float): Scale factor to rescale bounding boxes computed from the keypoints.
|
||||
Returns:
|
||||
center_x (float): x coordinate of bounding box center.
|
||||
center_y (float): y coordinate of bounding box center.
|
||||
width (float): bounding box width.
|
||||
height (float): bounding box height.
|
||||
"""
|
||||
p = torch.rand(1).item()
|
||||
if full_body(keypoints_2d):
|
||||
if p < 0.2:
|
||||
center_x, center_y, width, height = crop_to_hips(center_x, center_y, width, height, keypoints_2d)
|
||||
elif p < 0.3:
|
||||
center_x, center_y, width, height = crop_to_shoulders(center_x, center_y, width, height, keypoints_2d)
|
||||
elif p < 0.4:
|
||||
center_x, center_y, width, height = crop_to_head(center_x, center_y, width, height, keypoints_2d)
|
||||
elif p < 0.5:
|
||||
center_x, center_y, width, height = crop_torso_only(center_x, center_y, width, height, keypoints_2d)
|
||||
elif p < 0.6:
|
||||
center_x, center_y, width, height = crop_rightarm_only(center_x, center_y, width, height, keypoints_2d)
|
||||
elif p < 0.7:
|
||||
center_x, center_y, width, height = crop_leftarm_only(center_x, center_y, width, height, keypoints_2d)
|
||||
elif p < 0.8:
|
||||
center_x, center_y, width, height = crop_legs_only(center_x, center_y, width, height, keypoints_2d)
|
||||
elif p < 0.9:
|
||||
center_x, center_y, width, height = crop_rightleg_only(center_x, center_y, width, height, keypoints_2d)
|
||||
else:
|
||||
center_x, center_y, width, height = crop_leftleg_only(center_x, center_y, width, height, keypoints_2d)
|
||||
elif upper_body(keypoints_2d):
|
||||
if p < 0.2:
|
||||
center_x, center_y, width, height = crop_to_shoulders(center_x, center_y, width, height, keypoints_2d)
|
||||
elif p < 0.4:
|
||||
center_x, center_y, width, height = crop_to_head(center_x, center_y, width, height, keypoints_2d)
|
||||
elif p < 0.6:
|
||||
center_x, center_y, width, height = crop_torso_only(center_x, center_y, width, height, keypoints_2d)
|
||||
elif p < 0.8:
|
||||
center_x, center_y, width, height = crop_rightarm_only(center_x, center_y, width, height, keypoints_2d)
|
||||
else:
|
||||
center_x, center_y, width, height = crop_leftarm_only(center_x, center_y, width, height, keypoints_2d)
|
||||
return center_x, center_y, max(width, height), max(width, height)
|
||||
@@ -0,0 +1,95 @@
|
||||
from typing import Dict
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
from skimage.filters import gaussian
|
||||
from yacs.config import CfgNode
|
||||
import torch
|
||||
|
||||
from .utils import (convert_cvimg_to_tensor,
|
||||
expand_to_aspect_ratio,
|
||||
generate_image_patch_cv2)
|
||||
|
||||
DEFAULT_MEAN = 255. * np.array([0.485, 0.456, 0.406])
|
||||
DEFAULT_STD = 255. * np.array([0.229, 0.224, 0.225])
|
||||
|
||||
class ViTDetDataset(torch.utils.data.Dataset):
|
||||
|
||||
def __init__(self,
|
||||
cfg: CfgNode,
|
||||
img_cv2: np.array,
|
||||
boxes: np.array,
|
||||
right: np.array,
|
||||
rescale_factor=2.5,
|
||||
train: bool = False,
|
||||
**kwargs):
|
||||
super().__init__()
|
||||
self.cfg = cfg
|
||||
self.img_cv2 = img_cv2
|
||||
# self.boxes = boxes
|
||||
|
||||
assert train == False, "ViTDetDataset is only for inference"
|
||||
self.train = train
|
||||
self.img_size = cfg.MODEL.IMAGE_SIZE
|
||||
self.mean = 255. * np.array(self.cfg.MODEL.IMAGE_MEAN)
|
||||
self.std = 255. * np.array(self.cfg.MODEL.IMAGE_STD)
|
||||
|
||||
# Preprocess annotations
|
||||
boxes = boxes.astype(np.float32)
|
||||
self.center = (boxes[:, 2:4] + boxes[:, 0:2]) / 2.0
|
||||
self.scale = rescale_factor * (boxes[:, 2:4] - boxes[:, 0:2]) / 200.0
|
||||
self.personid = np.arange(len(boxes), dtype=np.int32)
|
||||
self.right = right.astype(np.float32)
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self.personid)
|
||||
|
||||
def __getitem__(self, idx: int) -> Dict[str, np.array]:
|
||||
|
||||
center = self.center[idx].copy()
|
||||
center_x = center[0]
|
||||
center_y = center[1]
|
||||
|
||||
scale = self.scale[idx]
|
||||
BBOX_SHAPE = self.cfg.MODEL.get('BBOX_SHAPE', None)
|
||||
bbox_size = expand_to_aspect_ratio(scale*200, target_aspect_ratio=BBOX_SHAPE).max()
|
||||
|
||||
patch_width = patch_height = self.img_size
|
||||
|
||||
right = self.right[idx].copy()
|
||||
flip = right == 0
|
||||
|
||||
# 3. generate image patch
|
||||
# if use_skimage_antialias:
|
||||
cvimg = self.img_cv2.copy()
|
||||
if True:
|
||||
# Blur image to avoid aliasing artifacts
|
||||
downsampling_factor = ((bbox_size*1.0) / patch_width)
|
||||
print(f'{downsampling_factor=}')
|
||||
downsampling_factor = downsampling_factor / 2.0
|
||||
if downsampling_factor > 1.1:
|
||||
cvimg = gaussian(cvimg, sigma=(downsampling_factor-1)/2, channel_axis=2, preserve_range=True)
|
||||
|
||||
|
||||
img_patch_cv, trans = generate_image_patch_cv2(cvimg,
|
||||
center_x, center_y,
|
||||
bbox_size, bbox_size,
|
||||
patch_width, patch_height,
|
||||
flip, 1.0, 0,
|
||||
border_mode=cv2.BORDER_CONSTANT)
|
||||
img_patch_cv = img_patch_cv[:, :, ::-1]
|
||||
img_patch = convert_cvimg_to_tensor(img_patch_cv)
|
||||
|
||||
# apply normalization
|
||||
for n_c in range(min(self.img_cv2.shape[2], 3)):
|
||||
img_patch[n_c, :, :] = (img_patch[n_c, :, :] - self.mean[n_c]) / self.std[n_c]
|
||||
|
||||
item = {
|
||||
'img': img_patch,
|
||||
'personid': int(self.personid[idx]),
|
||||
}
|
||||
item['box_center'] = self.center[idx].copy()
|
||||
item['box_size'] = bbox_size
|
||||
item['img_size'] = 1.0 * np.array([cvimg.shape[1], cvimg.shape[0]])
|
||||
item['right'] = self.right[idx].copy()
|
||||
return item
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
from .mano_wrapper import MANO
|
||||
from .hamer import HAMER
|
||||
from .discriminator import Discriminator
|
||||
|
||||
from ..utils.download import cache_url
|
||||
from ..configs import CACHE_DIR_HAMER
|
||||
|
||||
|
||||
def download_models(folder=CACHE_DIR_HAMER):
|
||||
"""Download checkpoints and files for running inference.
|
||||
"""
|
||||
import os
|
||||
os.makedirs(folder, exist_ok=True)
|
||||
download_files = {
|
||||
"hamer_demo_data.tar.gz" : ["https://www.cs.utexas.edu/~pavlakos/hamer/data/hamer_demo_data.tar.gz", folder],
|
||||
}
|
||||
|
||||
for file_name, url in download_files.items():
|
||||
output_path = os.path.join(url[1], file_name)
|
||||
if not os.path.exists(output_path):
|
||||
print("Downloading file: " + file_name)
|
||||
# output = gdown.cached_download(url[0], output_path, fuzzy=True)
|
||||
output = cache_url(url[0], output_path)
|
||||
assert os.path.exists(output_path), f"{output} does not exist"
|
||||
|
||||
# if ends with tar.gz, tar -xzf
|
||||
if file_name.endswith(".tar.gz"):
|
||||
print("Extracting file: " + file_name)
|
||||
os.system("tar -xvf " + output_path)
|
||||
|
||||
DEFAULT_CHECKPOINT=f'{CACHE_DIR_HAMER}/hamer_ckpts/checkpoints/hamer.ckpt'
|
||||
def load_hamer(checkpoint_path=DEFAULT_CHECKPOINT):
|
||||
from pathlib import Path
|
||||
from ..configs import get_config
|
||||
model_cfg = str(Path(checkpoint_path).parent.parent / 'model_config.yaml')
|
||||
model_cfg = get_config(model_cfg, update_cachedir=True)
|
||||
|
||||
# Override some config values, to crop bbox correctly
|
||||
if (model_cfg.MODEL.BACKBONE.TYPE == 'vit') and ('BBOX_SHAPE' not in model_cfg.MODEL):
|
||||
model_cfg.defrost()
|
||||
assert model_cfg.MODEL.IMAGE_SIZE == 256, f"MODEL.IMAGE_SIZE ({model_cfg.MODEL.IMAGE_SIZE}) should be 256 for ViT backbone"
|
||||
model_cfg.MODEL.BBOX_SHAPE = [192,256]
|
||||
model_cfg.freeze()
|
||||
|
||||
# Update config to be compatible with demo
|
||||
if ('PRETRAINED_WEIGHTS' in model_cfg.MODEL.BACKBONE):
|
||||
model_cfg.defrost()
|
||||
model_cfg.MODEL.BACKBONE.pop('PRETRAINED_WEIGHTS')
|
||||
model_cfg.freeze()
|
||||
|
||||
model = HAMER.load_from_checkpoint(checkpoint_path, strict=False, cfg=model_cfg)
|
||||
return model, model_cfg
|
||||
@@ -0,0 +1,7 @@
|
||||
from .vit import vit
|
||||
|
||||
def create_backbone(cfg):
|
||||
if cfg.MODEL.BACKBONE.TYPE == 'vit':
|
||||
return vit(cfg)
|
||||
else:
|
||||
raise NotImplementedError('Backbone type is not implemented')
|
||||
+348
@@ -0,0 +1,348 @@
|
||||
# Copyright (c) OpenMMLab. All rights reserved.
|
||||
import math
|
||||
|
||||
import torch
|
||||
from functools import partial
|
||||
import torch.nn as nn
|
||||
import torch.nn.functional as F
|
||||
import torch.utils.checkpoint as checkpoint
|
||||
|
||||
from timm.models.layers import drop_path, to_2tuple, trunc_normal_
|
||||
|
||||
def vit(cfg):
|
||||
return ViT(
|
||||
img_size=(256, 192),
|
||||
patch_size=16,
|
||||
embed_dim=1280,
|
||||
depth=32,
|
||||
num_heads=16,
|
||||
ratio=1,
|
||||
use_checkpoint=False,
|
||||
mlp_ratio=4,
|
||||
qkv_bias=True,
|
||||
drop_path_rate=0.55,
|
||||
)
|
||||
|
||||
def get_abs_pos(abs_pos, h, w, ori_h, ori_w, has_cls_token=True):
|
||||
"""
|
||||
Calculate absolute positional embeddings. If needed, resize embeddings and remove cls_token
|
||||
dimension for the original embeddings.
|
||||
Args:
|
||||
abs_pos (Tensor): absolute positional embeddings with (1, num_position, C).
|
||||
has_cls_token (bool): If true, has 1 embedding in abs_pos for cls token.
|
||||
hw (Tuple): size of input image tokens.
|
||||
|
||||
Returns:
|
||||
Absolute positional embeddings after processing with shape (1, H, W, C)
|
||||
"""
|
||||
cls_token = None
|
||||
B, L, C = abs_pos.shape
|
||||
if has_cls_token:
|
||||
cls_token = abs_pos[:, 0:1]
|
||||
abs_pos = abs_pos[:, 1:]
|
||||
|
||||
if ori_h != h or ori_w != w:
|
||||
new_abs_pos = F.interpolate(
|
||||
abs_pos.reshape(1, ori_h, ori_w, -1).permute(0, 3, 1, 2),
|
||||
size=(h, w),
|
||||
mode="bicubic",
|
||||
align_corners=False,
|
||||
).permute(0, 2, 3, 1).reshape(B, -1, C)
|
||||
|
||||
else:
|
||||
new_abs_pos = abs_pos
|
||||
|
||||
if cls_token is not None:
|
||||
new_abs_pos = torch.cat([cls_token, new_abs_pos], dim=1)
|
||||
return new_abs_pos
|
||||
|
||||
class DropPath(nn.Module):
|
||||
"""Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks).
|
||||
"""
|
||||
def __init__(self, drop_prob=None):
|
||||
super(DropPath, self).__init__()
|
||||
self.drop_prob = drop_prob
|
||||
|
||||
def forward(self, x):
|
||||
return drop_path(x, self.drop_prob, self.training)
|
||||
|
||||
def extra_repr(self):
|
||||
return 'p={}'.format(self.drop_prob)
|
||||
|
||||
class Mlp(nn.Module):
|
||||
def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0.):
|
||||
super().__init__()
|
||||
out_features = out_features or in_features
|
||||
hidden_features = hidden_features or in_features
|
||||
self.fc1 = nn.Linear(in_features, hidden_features)
|
||||
self.act = act_layer()
|
||||
self.fc2 = nn.Linear(hidden_features, out_features)
|
||||
self.drop = nn.Dropout(drop)
|
||||
|
||||
def forward(self, x):
|
||||
x = self.fc1(x)
|
||||
x = self.act(x)
|
||||
x = self.fc2(x)
|
||||
x = self.drop(x)
|
||||
return x
|
||||
|
||||
class Attention(nn.Module):
|
||||
def __init__(
|
||||
self, dim, num_heads=8, qkv_bias=False, qk_scale=None, attn_drop=0.,
|
||||
proj_drop=0., attn_head_dim=None,):
|
||||
super().__init__()
|
||||
self.num_heads = num_heads
|
||||
head_dim = dim // num_heads
|
||||
self.dim = dim
|
||||
|
||||
if attn_head_dim is not None:
|
||||
head_dim = attn_head_dim
|
||||
all_head_dim = head_dim * self.num_heads
|
||||
|
||||
self.scale = qk_scale or head_dim ** -0.5
|
||||
|
||||
self.qkv = nn.Linear(dim, all_head_dim * 3, bias=qkv_bias)
|
||||
|
||||
self.attn_drop = nn.Dropout(attn_drop)
|
||||
self.proj = nn.Linear(all_head_dim, dim)
|
||||
self.proj_drop = nn.Dropout(proj_drop)
|
||||
|
||||
def forward(self, x):
|
||||
B, N, C = x.shape
|
||||
qkv = self.qkv(x)
|
||||
qkv = qkv.reshape(B, N, 3, self.num_heads, -1).permute(2, 0, 3, 1, 4)
|
||||
q, k, v = qkv[0], qkv[1], qkv[2] # make torchscript happy (cannot use tensor as tuple)
|
||||
|
||||
q = q * self.scale
|
||||
attn = (q @ k.transpose(-2, -1))
|
||||
|
||||
attn = attn.softmax(dim=-1)
|
||||
attn = self.attn_drop(attn)
|
||||
|
||||
x = (attn @ v).transpose(1, 2).reshape(B, N, -1)
|
||||
x = self.proj(x)
|
||||
x = self.proj_drop(x)
|
||||
|
||||
return x
|
||||
|
||||
class Block(nn.Module):
|
||||
|
||||
def __init__(self, dim, num_heads, mlp_ratio=4., qkv_bias=False, qk_scale=None,
|
||||
drop=0., attn_drop=0., drop_path=0., act_layer=nn.GELU,
|
||||
norm_layer=nn.LayerNorm, attn_head_dim=None
|
||||
):
|
||||
super().__init__()
|
||||
|
||||
self.norm1 = norm_layer(dim)
|
||||
self.attn = Attention(
|
||||
dim, num_heads=num_heads, qkv_bias=qkv_bias, qk_scale=qk_scale,
|
||||
attn_drop=attn_drop, proj_drop=drop, attn_head_dim=attn_head_dim
|
||||
)
|
||||
|
||||
# NOTE: drop path for stochastic depth, we shall see if this is better than dropout here
|
||||
self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()
|
||||
self.norm2 = norm_layer(dim)
|
||||
mlp_hidden_dim = int(dim * mlp_ratio)
|
||||
self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop)
|
||||
|
||||
def forward(self, x):
|
||||
x = x + self.drop_path(self.attn(self.norm1(x)))
|
||||
x = x + self.drop_path(self.mlp(self.norm2(x)))
|
||||
return x
|
||||
|
||||
|
||||
class PatchEmbed(nn.Module):
|
||||
""" Image to Patch Embedding
|
||||
"""
|
||||
def __init__(self, img_size=224, patch_size=16, in_chans=3, embed_dim=768, ratio=1):
|
||||
super().__init__()
|
||||
img_size = to_2tuple(img_size)
|
||||
patch_size = to_2tuple(patch_size)
|
||||
num_patches = (img_size[1] // patch_size[1]) * (img_size[0] // patch_size[0]) * (ratio ** 2)
|
||||
self.patch_shape = (int(img_size[0] // patch_size[0] * ratio), int(img_size[1] // patch_size[1] * ratio))
|
||||
self.origin_patch_shape = (int(img_size[0] // patch_size[0]), int(img_size[1] // patch_size[1]))
|
||||
self.img_size = img_size
|
||||
self.patch_size = patch_size
|
||||
self.num_patches = num_patches
|
||||
|
||||
self.proj = nn.Conv2d(in_chans, embed_dim, kernel_size=patch_size, stride=(patch_size[0] // ratio), padding=4 + 2 * (ratio//2-1))
|
||||
|
||||
def forward(self, x, **kwargs):
|
||||
B, C, H, W = x.shape
|
||||
x = self.proj(x)
|
||||
Hp, Wp = x.shape[2], x.shape[3]
|
||||
|
||||
x = x.flatten(2).transpose(1, 2)
|
||||
return x, (Hp, Wp)
|
||||
|
||||
|
||||
class HybridEmbed(nn.Module):
|
||||
""" CNN Feature Map Embedding
|
||||
Extract feature map from CNN, flatten, project to embedding dim.
|
||||
"""
|
||||
def __init__(self, backbone, img_size=224, feature_size=None, in_chans=3, embed_dim=768):
|
||||
super().__init__()
|
||||
assert isinstance(backbone, nn.Module)
|
||||
img_size = to_2tuple(img_size)
|
||||
self.img_size = img_size
|
||||
self.backbone = backbone
|
||||
if feature_size is None:
|
||||
with torch.no_grad():
|
||||
training = backbone.training
|
||||
if training:
|
||||
backbone.eval()
|
||||
o = self.backbone(torch.zeros(1, in_chans, img_size[0], img_size[1]))[-1]
|
||||
feature_size = o.shape[-2:]
|
||||
feature_dim = o.shape[1]
|
||||
backbone.train(training)
|
||||
else:
|
||||
feature_size = to_2tuple(feature_size)
|
||||
feature_dim = self.backbone.feature_info.channels()[-1]
|
||||
self.num_patches = feature_size[0] * feature_size[1]
|
||||
self.proj = nn.Linear(feature_dim, embed_dim)
|
||||
|
||||
def forward(self, x):
|
||||
x = self.backbone(x)[-1]
|
||||
x = x.flatten(2).transpose(1, 2)
|
||||
x = self.proj(x)
|
||||
return x
|
||||
|
||||
|
||||
class ViT(nn.Module):
|
||||
|
||||
def __init__(self,
|
||||
img_size=224, patch_size=16, in_chans=3, num_classes=80, embed_dim=768, depth=12,
|
||||
num_heads=12, mlp_ratio=4., qkv_bias=False, qk_scale=None, drop_rate=0., attn_drop_rate=0.,
|
||||
drop_path_rate=0., hybrid_backbone=None, norm_layer=None, use_checkpoint=False,
|
||||
frozen_stages=-1, ratio=1, last_norm=True,
|
||||
patch_padding='pad', freeze_attn=False, freeze_ffn=False,
|
||||
):
|
||||
# Protect mutable default arguments
|
||||
super(ViT, self).__init__()
|
||||
norm_layer = norm_layer or partial(nn.LayerNorm, eps=1e-6)
|
||||
self.num_classes = num_classes
|
||||
self.num_features = self.embed_dim = embed_dim # num_features for consistency with other models
|
||||
self.frozen_stages = frozen_stages
|
||||
self.use_checkpoint = use_checkpoint
|
||||
self.patch_padding = patch_padding
|
||||
self.freeze_attn = freeze_attn
|
||||
self.freeze_ffn = freeze_ffn
|
||||
self.depth = depth
|
||||
|
||||
if hybrid_backbone is not None:
|
||||
self.patch_embed = HybridEmbed(
|
||||
hybrid_backbone, img_size=img_size, in_chans=in_chans, embed_dim=embed_dim)
|
||||
else:
|
||||
self.patch_embed = PatchEmbed(
|
||||
img_size=img_size, patch_size=patch_size, in_chans=in_chans, embed_dim=embed_dim, ratio=ratio)
|
||||
num_patches = self.patch_embed.num_patches
|
||||
|
||||
# since the pretraining model has class token
|
||||
self.pos_embed = nn.Parameter(torch.zeros(1, num_patches + 1, embed_dim))
|
||||
|
||||
dpr = [x.item() for x in torch.linspace(0, drop_path_rate, depth)] # stochastic depth decay rule
|
||||
|
||||
self.blocks = nn.ModuleList([
|
||||
Block(
|
||||
dim=embed_dim, num_heads=num_heads, mlp_ratio=mlp_ratio, qkv_bias=qkv_bias, qk_scale=qk_scale,
|
||||
drop=drop_rate, attn_drop=attn_drop_rate, drop_path=dpr[i], norm_layer=norm_layer,
|
||||
)
|
||||
for i in range(depth)])
|
||||
|
||||
self.last_norm = norm_layer(embed_dim) if last_norm else nn.Identity()
|
||||
|
||||
if self.pos_embed is not None:
|
||||
trunc_normal_(self.pos_embed, std=.02)
|
||||
|
||||
self._freeze_stages()
|
||||
|
||||
def _freeze_stages(self):
|
||||
"""Freeze parameters."""
|
||||
if self.frozen_stages >= 0:
|
||||
self.patch_embed.eval()
|
||||
for param in self.patch_embed.parameters():
|
||||
param.requires_grad = False
|
||||
|
||||
for i in range(1, self.frozen_stages + 1):
|
||||
m = self.blocks[i]
|
||||
m.eval()
|
||||
for param in m.parameters():
|
||||
param.requires_grad = False
|
||||
|
||||
if self.freeze_attn:
|
||||
for i in range(0, self.depth):
|
||||
m = self.blocks[i]
|
||||
m.attn.eval()
|
||||
m.norm1.eval()
|
||||
for param in m.attn.parameters():
|
||||
param.requires_grad = False
|
||||
for param in m.norm1.parameters():
|
||||
param.requires_grad = False
|
||||
|
||||
if self.freeze_ffn:
|
||||
self.pos_embed.requires_grad = False
|
||||
self.patch_embed.eval()
|
||||
for param in self.patch_embed.parameters():
|
||||
param.requires_grad = False
|
||||
for i in range(0, self.depth):
|
||||
m = self.blocks[i]
|
||||
m.mlp.eval()
|
||||
m.norm2.eval()
|
||||
for param in m.mlp.parameters():
|
||||
param.requires_grad = False
|
||||
for param in m.norm2.parameters():
|
||||
param.requires_grad = False
|
||||
|
||||
def init_weights(self):
|
||||
"""Initialize the weights in backbone.
|
||||
Args:
|
||||
pretrained (str, optional): Path to pre-trained weights.
|
||||
Defaults to None.
|
||||
"""
|
||||
def _init_weights(m):
|
||||
if isinstance(m, nn.Linear):
|
||||
trunc_normal_(m.weight, std=.02)
|
||||
if isinstance(m, nn.Linear) and m.bias is not None:
|
||||
nn.init.constant_(m.bias, 0)
|
||||
elif isinstance(m, nn.LayerNorm):
|
||||
nn.init.constant_(m.bias, 0)
|
||||
nn.init.constant_(m.weight, 1.0)
|
||||
|
||||
self.apply(_init_weights)
|
||||
|
||||
def get_num_layers(self):
|
||||
return len(self.blocks)
|
||||
|
||||
@torch.jit.ignore
|
||||
def no_weight_decay(self):
|
||||
return {'pos_embed', 'cls_token'}
|
||||
|
||||
def forward_features(self, x):
|
||||
B, C, H, W = x.shape
|
||||
x, (Hp, Wp) = self.patch_embed(x)
|
||||
|
||||
if self.pos_embed is not None:
|
||||
# fit for multiple GPU training
|
||||
# since the first element for pos embed (sin-cos manner) is zero, it will cause no difference
|
||||
x = x + self.pos_embed[:, 1:] + self.pos_embed[:, :1]
|
||||
|
||||
for blk in self.blocks:
|
||||
if self.use_checkpoint:
|
||||
x = checkpoint.checkpoint(blk, x)
|
||||
else:
|
||||
x = blk(x)
|
||||
|
||||
x = self.last_norm(x)
|
||||
|
||||
xp = x.permute(0, 2, 1).reshape(B, -1, Hp, Wp).contiguous()
|
||||
|
||||
return xp
|
||||
|
||||
def forward(self, x):
|
||||
x = self.forward_features(x)
|
||||
return x
|
||||
|
||||
def train(self, mode=True):
|
||||
"""Convert the model into training mode."""
|
||||
super().train(mode)
|
||||
self._freeze_stages()
|
||||
@@ -0,0 +1,358 @@
|
||||
from inspect import isfunction
|
||||
from typing import Callable, Optional
|
||||
|
||||
import torch
|
||||
from einops import rearrange
|
||||
from einops.layers.torch import Rearrange
|
||||
from torch import nn
|
||||
|
||||
from .t_cond_mlp import (
|
||||
AdaptiveLayerNorm1D,
|
||||
FrequencyEmbedder,
|
||||
normalization_layer,
|
||||
)
|
||||
# from .vit import Attention, FeedForward
|
||||
|
||||
|
||||
def exists(val):
|
||||
return val is not None
|
||||
|
||||
|
||||
def default(val, d):
|
||||
if exists(val):
|
||||
return val
|
||||
return d() if isfunction(d) else d
|
||||
|
||||
|
||||
class PreNorm(nn.Module):
|
||||
def __init__(self, dim: int, fn: Callable, norm: str = "layer", norm_cond_dim: int = -1):
|
||||
super().__init__()
|
||||
self.norm = normalization_layer(norm, dim, norm_cond_dim)
|
||||
self.fn = fn
|
||||
|
||||
def forward(self, x: torch.Tensor, *args, **kwargs):
|
||||
if isinstance(self.norm, AdaptiveLayerNorm1D):
|
||||
return self.fn(self.norm(x, *args), **kwargs)
|
||||
else:
|
||||
return self.fn(self.norm(x), **kwargs)
|
||||
|
||||
|
||||
class FeedForward(nn.Module):
|
||||
def __init__(self, dim, hidden_dim, dropout=0.0):
|
||||
super().__init__()
|
||||
self.net = nn.Sequential(
|
||||
nn.Linear(dim, hidden_dim),
|
||||
nn.GELU(),
|
||||
nn.Dropout(dropout),
|
||||
nn.Linear(hidden_dim, dim),
|
||||
nn.Dropout(dropout),
|
||||
)
|
||||
|
||||
def forward(self, x):
|
||||
return self.net(x)
|
||||
|
||||
|
||||
class Attention(nn.Module):
|
||||
def __init__(self, dim, heads=8, dim_head=64, dropout=0.0):
|
||||
super().__init__()
|
||||
inner_dim = dim_head * heads
|
||||
project_out = not (heads == 1 and dim_head == dim)
|
||||
|
||||
self.heads = heads
|
||||
self.scale = dim_head**-0.5
|
||||
|
||||
self.attend = nn.Softmax(dim=-1)
|
||||
self.dropout = nn.Dropout(dropout)
|
||||
|
||||
self.to_qkv = nn.Linear(dim, inner_dim * 3, bias=False)
|
||||
|
||||
self.to_out = (
|
||||
nn.Sequential(nn.Linear(inner_dim, dim), nn.Dropout(dropout))
|
||||
if project_out
|
||||
else nn.Identity()
|
||||
)
|
||||
|
||||
def forward(self, x):
|
||||
qkv = self.to_qkv(x).chunk(3, dim=-1)
|
||||
q, k, v = map(lambda t: rearrange(t, "b n (h d) -> b h n d", h=self.heads), qkv)
|
||||
|
||||
dots = torch.matmul(q, k.transpose(-1, -2)) * self.scale
|
||||
|
||||
attn = self.attend(dots)
|
||||
attn = self.dropout(attn)
|
||||
|
||||
out = torch.matmul(attn, v)
|
||||
out = rearrange(out, "b h n d -> b n (h d)")
|
||||
return self.to_out(out)
|
||||
|
||||
|
||||
class CrossAttention(nn.Module):
|
||||
def __init__(self, dim, context_dim=None, heads=8, dim_head=64, dropout=0.0):
|
||||
super().__init__()
|
||||
inner_dim = dim_head * heads
|
||||
project_out = not (heads == 1 and dim_head == dim)
|
||||
|
||||
self.heads = heads
|
||||
self.scale = dim_head**-0.5
|
||||
|
||||
self.attend = nn.Softmax(dim=-1)
|
||||
self.dropout = nn.Dropout(dropout)
|
||||
|
||||
context_dim = default(context_dim, dim)
|
||||
self.to_kv = nn.Linear(context_dim, inner_dim * 2, bias=False)
|
||||
self.to_q = nn.Linear(dim, inner_dim, bias=False)
|
||||
|
||||
self.to_out = (
|
||||
nn.Sequential(nn.Linear(inner_dim, dim), nn.Dropout(dropout))
|
||||
if project_out
|
||||
else nn.Identity()
|
||||
)
|
||||
|
||||
def forward(self, x, context=None):
|
||||
context = default(context, x)
|
||||
k, v = self.to_kv(context).chunk(2, dim=-1)
|
||||
q = self.to_q(x)
|
||||
q, k, v = map(lambda t: rearrange(t, "b n (h d) -> b h n d", h=self.heads), [q, k, v])
|
||||
|
||||
dots = torch.matmul(q, k.transpose(-1, -2)) * self.scale
|
||||
|
||||
attn = self.attend(dots)
|
||||
attn = self.dropout(attn)
|
||||
|
||||
out = torch.matmul(attn, v)
|
||||
out = rearrange(out, "b h n d -> b n (h d)")
|
||||
return self.to_out(out)
|
||||
|
||||
|
||||
class Transformer(nn.Module):
|
||||
def __init__(
|
||||
self,
|
||||
dim: int,
|
||||
depth: int,
|
||||
heads: int,
|
||||
dim_head: int,
|
||||
mlp_dim: int,
|
||||
dropout: float = 0.0,
|
||||
norm: str = "layer",
|
||||
norm_cond_dim: int = -1,
|
||||
):
|
||||
super().__init__()
|
||||
self.layers = nn.ModuleList([])
|
||||
for _ in range(depth):
|
||||
sa = Attention(dim, heads=heads, dim_head=dim_head, dropout=dropout)
|
||||
ff = FeedForward(dim, mlp_dim, dropout=dropout)
|
||||
self.layers.append(
|
||||
nn.ModuleList(
|
||||
[
|
||||
PreNorm(dim, sa, norm=norm, norm_cond_dim=norm_cond_dim),
|
||||
PreNorm(dim, ff, norm=norm, norm_cond_dim=norm_cond_dim),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
def forward(self, x: torch.Tensor, *args):
|
||||
for attn, ff in self.layers:
|
||||
x = attn(x, *args) + x
|
||||
x = ff(x, *args) + x
|
||||
return x
|
||||
|
||||
|
||||
class TransformerCrossAttn(nn.Module):
|
||||
def __init__(
|
||||
self,
|
||||
dim: int,
|
||||
depth: int,
|
||||
heads: int,
|
||||
dim_head: int,
|
||||
mlp_dim: int,
|
||||
dropout: float = 0.0,
|
||||
norm: str = "layer",
|
||||
norm_cond_dim: int = -1,
|
||||
context_dim: Optional[int] = None,
|
||||
):
|
||||
super().__init__()
|
||||
self.layers = nn.ModuleList([])
|
||||
for _ in range(depth):
|
||||
sa = Attention(dim, heads=heads, dim_head=dim_head, dropout=dropout)
|
||||
ca = CrossAttention(
|
||||
dim, context_dim=context_dim, heads=heads, dim_head=dim_head, dropout=dropout
|
||||
)
|
||||
ff = FeedForward(dim, mlp_dim, dropout=dropout)
|
||||
self.layers.append(
|
||||
nn.ModuleList(
|
||||
[
|
||||
PreNorm(dim, sa, norm=norm, norm_cond_dim=norm_cond_dim),
|
||||
PreNorm(dim, ca, norm=norm, norm_cond_dim=norm_cond_dim),
|
||||
PreNorm(dim, ff, norm=norm, norm_cond_dim=norm_cond_dim),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
def forward(self, x: torch.Tensor, *args, context=None, context_list=None):
|
||||
if context_list is None:
|
||||
context_list = [context] * len(self.layers)
|
||||
if len(context_list) != len(self.layers):
|
||||
raise ValueError(f"len(context_list) != len(self.layers) ({len(context_list)} != {len(self.layers)})")
|
||||
|
||||
for i, (self_attn, cross_attn, ff) in enumerate(self.layers):
|
||||
x = self_attn(x, *args) + x
|
||||
x = cross_attn(x, *args, context=context_list[i]) + x
|
||||
x = ff(x, *args) + x
|
||||
return x
|
||||
|
||||
|
||||
class DropTokenDropout(nn.Module):
|
||||
def __init__(self, p: float = 0.1):
|
||||
super().__init__()
|
||||
if p < 0 or p > 1:
|
||||
raise ValueError(
|
||||
"dropout probability has to be between 0 and 1, " "but got {}".format(p)
|
||||
)
|
||||
self.p = p
|
||||
|
||||
def forward(self, x: torch.Tensor):
|
||||
# x: (batch_size, seq_len, dim)
|
||||
if self.training and self.p > 0:
|
||||
zero_mask = torch.full_like(x[0, :, 0], self.p).bernoulli().bool()
|
||||
# TODO: permutation idx for each batch using torch.argsort
|
||||
if zero_mask.any():
|
||||
x = x[:, ~zero_mask, :]
|
||||
return x
|
||||
|
||||
|
||||
class ZeroTokenDropout(nn.Module):
|
||||
def __init__(self, p: float = 0.1):
|
||||
super().__init__()
|
||||
if p < 0 or p > 1:
|
||||
raise ValueError(
|
||||
"dropout probability has to be between 0 and 1, " "but got {}".format(p)
|
||||
)
|
||||
self.p = p
|
||||
|
||||
def forward(self, x: torch.Tensor):
|
||||
# x: (batch_size, seq_len, dim)
|
||||
if self.training and self.p > 0:
|
||||
zero_mask = torch.full_like(x[:, :, 0], self.p).bernoulli().bool()
|
||||
# Zero-out the masked tokens
|
||||
x[zero_mask, :] = 0
|
||||
return x
|
||||
|
||||
|
||||
class TransformerEncoder(nn.Module):
|
||||
def __init__(
|
||||
self,
|
||||
num_tokens: int,
|
||||
token_dim: int,
|
||||
dim: int,
|
||||
depth: int,
|
||||
heads: int,
|
||||
mlp_dim: int,
|
||||
dim_head: int = 64,
|
||||
dropout: float = 0.0,
|
||||
emb_dropout: float = 0.0,
|
||||
emb_dropout_type: str = "drop",
|
||||
emb_dropout_loc: str = "token",
|
||||
norm: str = "layer",
|
||||
norm_cond_dim: int = -1,
|
||||
token_pe_numfreq: int = -1,
|
||||
):
|
||||
super().__init__()
|
||||
if token_pe_numfreq > 0:
|
||||
token_dim_new = token_dim * (2 * token_pe_numfreq + 1)
|
||||
self.to_token_embedding = nn.Sequential(
|
||||
Rearrange("b n d -> (b n) d", n=num_tokens, d=token_dim),
|
||||
FrequencyEmbedder(token_pe_numfreq, token_pe_numfreq - 1),
|
||||
Rearrange("(b n) d -> b n d", n=num_tokens, d=token_dim_new),
|
||||
nn.Linear(token_dim_new, dim),
|
||||
)
|
||||
else:
|
||||
self.to_token_embedding = nn.Linear(token_dim, dim)
|
||||
self.pos_embedding = nn.Parameter(torch.randn(1, num_tokens, dim))
|
||||
if emb_dropout_type == "drop":
|
||||
self.dropout = DropTokenDropout(emb_dropout)
|
||||
elif emb_dropout_type == "zero":
|
||||
self.dropout = ZeroTokenDropout(emb_dropout)
|
||||
else:
|
||||
raise ValueError(f"Unknown emb_dropout_type: {emb_dropout_type}")
|
||||
self.emb_dropout_loc = emb_dropout_loc
|
||||
|
||||
self.transformer = Transformer(
|
||||
dim, depth, heads, dim_head, mlp_dim, dropout, norm=norm, norm_cond_dim=norm_cond_dim
|
||||
)
|
||||
|
||||
def forward(self, inp: torch.Tensor, *args, **kwargs):
|
||||
x = inp
|
||||
|
||||
if self.emb_dropout_loc == "input":
|
||||
x = self.dropout(x)
|
||||
x = self.to_token_embedding(x)
|
||||
|
||||
if self.emb_dropout_loc == "token":
|
||||
x = self.dropout(x)
|
||||
b, n, _ = x.shape
|
||||
x += self.pos_embedding[:, :n]
|
||||
|
||||
if self.emb_dropout_loc == "token_afterpos":
|
||||
x = self.dropout(x)
|
||||
x = self.transformer(x, *args)
|
||||
return x
|
||||
|
||||
|
||||
class TransformerDecoder(nn.Module):
|
||||
def __init__(
|
||||
self,
|
||||
num_tokens: int,
|
||||
token_dim: int,
|
||||
dim: int,
|
||||
depth: int,
|
||||
heads: int,
|
||||
mlp_dim: int,
|
||||
dim_head: int = 64,
|
||||
dropout: float = 0.0,
|
||||
emb_dropout: float = 0.0,
|
||||
emb_dropout_type: str = 'drop',
|
||||
norm: str = "layer",
|
||||
norm_cond_dim: int = -1,
|
||||
context_dim: Optional[int] = None,
|
||||
skip_token_embedding: bool = False,
|
||||
):
|
||||
super().__init__()
|
||||
if not skip_token_embedding:
|
||||
self.to_token_embedding = nn.Linear(token_dim, dim)
|
||||
else:
|
||||
self.to_token_embedding = nn.Identity()
|
||||
if token_dim != dim:
|
||||
raise ValueError(
|
||||
f"token_dim ({token_dim}) != dim ({dim}) when skip_token_embedding is True"
|
||||
)
|
||||
|
||||
self.pos_embedding = nn.Parameter(torch.randn(1, num_tokens, dim))
|
||||
if emb_dropout_type == "drop":
|
||||
self.dropout = DropTokenDropout(emb_dropout)
|
||||
elif emb_dropout_type == "zero":
|
||||
self.dropout = ZeroTokenDropout(emb_dropout)
|
||||
elif emb_dropout_type == "normal":
|
||||
self.dropout = nn.Dropout(emb_dropout)
|
||||
|
||||
self.transformer = TransformerCrossAttn(
|
||||
dim,
|
||||
depth,
|
||||
heads,
|
||||
dim_head,
|
||||
mlp_dim,
|
||||
dropout,
|
||||
norm=norm,
|
||||
norm_cond_dim=norm_cond_dim,
|
||||
context_dim=context_dim,
|
||||
)
|
||||
|
||||
def forward(self, inp: torch.Tensor, *args, context=None, context_list=None):
|
||||
x = self.to_token_embedding(inp)
|
||||
b, n, _ = x.shape
|
||||
|
||||
x = self.dropout(x)
|
||||
x += self.pos_embedding[:, :n]
|
||||
|
||||
x = self.transformer(x, *args, context=context, context_list=context_list)
|
||||
return x
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
import copy
|
||||
from typing import List, Optional
|
||||
|
||||
import torch
|
||||
|
||||
|
||||
class AdaptiveLayerNorm1D(torch.nn.Module):
|
||||
def __init__(self, data_dim: int, norm_cond_dim: int):
|
||||
super().__init__()
|
||||
if data_dim <= 0:
|
||||
raise ValueError(f"data_dim must be positive, but got {data_dim}")
|
||||
if norm_cond_dim <= 0:
|
||||
raise ValueError(f"norm_cond_dim must be positive, but got {norm_cond_dim}")
|
||||
self.norm = torch.nn.LayerNorm(
|
||||
data_dim
|
||||
) # TODO: Check if elementwise_affine=True is correct
|
||||
self.linear = torch.nn.Linear(norm_cond_dim, 2 * data_dim)
|
||||
torch.nn.init.zeros_(self.linear.weight)
|
||||
torch.nn.init.zeros_(self.linear.bias)
|
||||
|
||||
def forward(self, x: torch.Tensor, t: torch.Tensor) -> torch.Tensor:
|
||||
# x: (batch, ..., data_dim)
|
||||
# t: (batch, norm_cond_dim)
|
||||
# return: (batch, data_dim)
|
||||
x = self.norm(x)
|
||||
alpha, beta = self.linear(t).chunk(2, dim=-1)
|
||||
|
||||
# Add singleton dimensions to alpha and beta
|
||||
if x.dim() > 2:
|
||||
alpha = alpha.view(alpha.shape[0], *([1] * (x.dim() - 2)), alpha.shape[1])
|
||||
beta = beta.view(beta.shape[0], *([1] * (x.dim() - 2)), beta.shape[1])
|
||||
|
||||
return x * (1 + alpha) + beta
|
||||
|
||||
|
||||
class SequentialCond(torch.nn.Sequential):
|
||||
def forward(self, input, *args, **kwargs):
|
||||
for module in self:
|
||||
if isinstance(module, (AdaptiveLayerNorm1D, SequentialCond, ResidualMLPBlock)):
|
||||
# print(f'Passing on args to {module}', [a.shape for a in args])
|
||||
input = module(input, *args, **kwargs)
|
||||
else:
|
||||
# print(f'Skipping passing args to {module}', [a.shape for a in args])
|
||||
input = module(input)
|
||||
return input
|
||||
|
||||
|
||||
def normalization_layer(norm: Optional[str], dim: int, norm_cond_dim: int = -1):
|
||||
if norm == "batch":
|
||||
return torch.nn.BatchNorm1d(dim)
|
||||
elif norm == "layer":
|
||||
return torch.nn.LayerNorm(dim)
|
||||
elif norm == "ada":
|
||||
assert norm_cond_dim > 0, f"norm_cond_dim must be positive, got {norm_cond_dim}"
|
||||
return AdaptiveLayerNorm1D(dim, norm_cond_dim)
|
||||
elif norm is None:
|
||||
return torch.nn.Identity()
|
||||
else:
|
||||
raise ValueError(f"Unknown norm: {norm}")
|
||||
|
||||
|
||||
def linear_norm_activ_dropout(
|
||||
input_dim: int,
|
||||
output_dim: int,
|
||||
activation: torch.nn.Module = torch.nn.ReLU(),
|
||||
bias: bool = True,
|
||||
norm: Optional[str] = "layer", # Options: ada/batch/layer
|
||||
dropout: float = 0.0,
|
||||
norm_cond_dim: int = -1,
|
||||
) -> SequentialCond:
|
||||
layers = []
|
||||
layers.append(torch.nn.Linear(input_dim, output_dim, bias=bias))
|
||||
if norm is not None:
|
||||
layers.append(normalization_layer(norm, output_dim, norm_cond_dim))
|
||||
layers.append(copy.deepcopy(activation))
|
||||
if dropout > 0.0:
|
||||
layers.append(torch.nn.Dropout(dropout))
|
||||
return SequentialCond(*layers)
|
||||
|
||||
|
||||
def create_simple_mlp(
|
||||
input_dim: int,
|
||||
hidden_dims: List[int],
|
||||
output_dim: int,
|
||||
activation: torch.nn.Module = torch.nn.ReLU(),
|
||||
bias: bool = True,
|
||||
norm: Optional[str] = "layer", # Options: ada/batch/layer
|
||||
dropout: float = 0.0,
|
||||
norm_cond_dim: int = -1,
|
||||
) -> SequentialCond:
|
||||
layers = []
|
||||
prev_dim = input_dim
|
||||
for hidden_dim in hidden_dims:
|
||||
layers.extend(
|
||||
linear_norm_activ_dropout(
|
||||
prev_dim, hidden_dim, activation, bias, norm, dropout, norm_cond_dim
|
||||
)
|
||||
)
|
||||
prev_dim = hidden_dim
|
||||
layers.append(torch.nn.Linear(prev_dim, output_dim, bias=bias))
|
||||
return SequentialCond(*layers)
|
||||
|
||||
|
||||
class ResidualMLPBlock(torch.nn.Module):
|
||||
def __init__(
|
||||
self,
|
||||
input_dim: int,
|
||||
hidden_dim: int,
|
||||
num_hidden_layers: int,
|
||||
output_dim: int,
|
||||
activation: torch.nn.Module = torch.nn.ReLU(),
|
||||
bias: bool = True,
|
||||
norm: Optional[str] = "layer", # Options: ada/batch/layer
|
||||
dropout: float = 0.0,
|
||||
norm_cond_dim: int = -1,
|
||||
):
|
||||
super().__init__()
|
||||
if not (input_dim == output_dim == hidden_dim):
|
||||
raise NotImplementedError(
|
||||
f"input_dim {input_dim} != output_dim {output_dim} is not implemented"
|
||||
)
|
||||
|
||||
layers = []
|
||||
prev_dim = input_dim
|
||||
for i in range(num_hidden_layers):
|
||||
layers.append(
|
||||
linear_norm_activ_dropout(
|
||||
prev_dim, hidden_dim, activation, bias, norm, dropout, norm_cond_dim
|
||||
)
|
||||
)
|
||||
prev_dim = hidden_dim
|
||||
self.model = SequentialCond(*layers)
|
||||
self.skip = torch.nn.Identity()
|
||||
|
||||
def forward(self, x: torch.Tensor, *args, **kwargs) -> torch.Tensor:
|
||||
return x + self.model(x, *args, **kwargs)
|
||||
|
||||
|
||||
class ResidualMLP(torch.nn.Module):
|
||||
def __init__(
|
||||
self,
|
||||
input_dim: int,
|
||||
hidden_dim: int,
|
||||
num_hidden_layers: int,
|
||||
output_dim: int,
|
||||
activation: torch.nn.Module = torch.nn.ReLU(),
|
||||
bias: bool = True,
|
||||
norm: Optional[str] = "layer", # Options: ada/batch/layer
|
||||
dropout: float = 0.0,
|
||||
num_blocks: int = 1,
|
||||
norm_cond_dim: int = -1,
|
||||
):
|
||||
super().__init__()
|
||||
self.input_dim = input_dim
|
||||
self.model = SequentialCond(
|
||||
linear_norm_activ_dropout(
|
||||
input_dim, hidden_dim, activation, bias, norm, dropout, norm_cond_dim
|
||||
),
|
||||
*[
|
||||
ResidualMLPBlock(
|
||||
hidden_dim,
|
||||
hidden_dim,
|
||||
num_hidden_layers,
|
||||
hidden_dim,
|
||||
activation,
|
||||
bias,
|
||||
norm,
|
||||
dropout,
|
||||
norm_cond_dim,
|
||||
)
|
||||
for _ in range(num_blocks)
|
||||
],
|
||||
torch.nn.Linear(hidden_dim, output_dim, bias=bias),
|
||||
)
|
||||
|
||||
def forward(self, x: torch.Tensor, *args, **kwargs) -> torch.Tensor:
|
||||
return self.model(x, *args, **kwargs)
|
||||
|
||||
|
||||
class FrequencyEmbedder(torch.nn.Module):
|
||||
def __init__(self, num_frequencies, max_freq_log2):
|
||||
super().__init__()
|
||||
frequencies = 2 ** torch.linspace(0, max_freq_log2, steps=num_frequencies)
|
||||
self.register_buffer("frequencies", frequencies)
|
||||
|
||||
def forward(self, x):
|
||||
# x should be of size (N,) or (N, D)
|
||||
N = x.size(0)
|
||||
if x.dim() == 1: # (N,)
|
||||
x = x.unsqueeze(1) # (N, D) where D=1
|
||||
x_unsqueezed = x.unsqueeze(-1) # (N, D, 1)
|
||||
scaled = self.frequencies.view(1, 1, -1) * x_unsqueezed # (N, D, num_frequencies)
|
||||
s = torch.sin(scaled)
|
||||
c = torch.cos(scaled)
|
||||
embedded = torch.cat([s, c, x_unsqueezed], dim=-1).view(
|
||||
N, -1
|
||||
) # (N, D * 2 * num_frequencies + D)
|
||||
return embedded
|
||||
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
class Discriminator(nn.Module):
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Pose + Shape discriminator proposed in HMR
|
||||
"""
|
||||
super(Discriminator, self).__init__()
|
||||
|
||||
self.num_joints = 15
|
||||
# poses_alone
|
||||
self.D_conv1 = nn.Conv2d(9, 32, kernel_size=1)
|
||||
nn.init.xavier_uniform_(self.D_conv1.weight)
|
||||
nn.init.zeros_(self.D_conv1.bias)
|
||||
self.relu = nn.ReLU(inplace=True)
|
||||
self.D_conv2 = nn.Conv2d(32, 32, kernel_size=1)
|
||||
nn.init.xavier_uniform_(self.D_conv2.weight)
|
||||
nn.init.zeros_(self.D_conv2.bias)
|
||||
pose_out = []
|
||||
for i in range(self.num_joints):
|
||||
pose_out_temp = nn.Linear(32, 1)
|
||||
nn.init.xavier_uniform_(pose_out_temp.weight)
|
||||
nn.init.zeros_(pose_out_temp.bias)
|
||||
pose_out.append(pose_out_temp)
|
||||
self.pose_out = nn.ModuleList(pose_out)
|
||||
|
||||
# betas
|
||||
self.betas_fc1 = nn.Linear(10, 10)
|
||||
nn.init.xavier_uniform_(self.betas_fc1.weight)
|
||||
nn.init.zeros_(self.betas_fc1.bias)
|
||||
self.betas_fc2 = nn.Linear(10, 5)
|
||||
nn.init.xavier_uniform_(self.betas_fc2.weight)
|
||||
nn.init.zeros_(self.betas_fc2.bias)
|
||||
self.betas_out = nn.Linear(5, 1)
|
||||
nn.init.xavier_uniform_(self.betas_out.weight)
|
||||
nn.init.zeros_(self.betas_out.bias)
|
||||
|
||||
# poses_joint
|
||||
self.D_alljoints_fc1 = nn.Linear(32*self.num_joints, 1024)
|
||||
nn.init.xavier_uniform_(self.D_alljoints_fc1.weight)
|
||||
nn.init.zeros_(self.D_alljoints_fc1.bias)
|
||||
self.D_alljoints_fc2 = nn.Linear(1024, 1024)
|
||||
nn.init.xavier_uniform_(self.D_alljoints_fc2.weight)
|
||||
nn.init.zeros_(self.D_alljoints_fc2.bias)
|
||||
self.D_alljoints_out = nn.Linear(1024, 1)
|
||||
nn.init.xavier_uniform_(self.D_alljoints_out.weight)
|
||||
nn.init.zeros_(self.D_alljoints_out.bias)
|
||||
|
||||
|
||||
def forward(self, poses: torch.Tensor, betas: torch.Tensor) -> torch.Tensor:
|
||||
"""
|
||||
Forward pass of the discriminator.
|
||||
Args:
|
||||
poses (torch.Tensor): Tensor of shape (B, 23, 3, 3) containing a batch of MANO hand poses (excluding the global orientation).
|
||||
betas (torch.Tensor): Tensor of shape (B, 10) containign a batch of MANO beta coefficients.
|
||||
Returns:
|
||||
torch.Tensor: Discriminator output with shape (B, 25)
|
||||
"""
|
||||
#bn = poses.shape[0]
|
||||
# poses B x 207
|
||||
#poses = poses.reshape(bn, -1)
|
||||
# poses B x num_joints x 1 x 9
|
||||
poses = poses.reshape(-1, self.num_joints, 1, 9)
|
||||
bn = poses.shape[0]
|
||||
# poses B x 9 x num_joints x 1
|
||||
poses = poses.permute(0, 3, 1, 2).contiguous()
|
||||
|
||||
# poses_alone
|
||||
poses = self.D_conv1(poses)
|
||||
poses = self.relu(poses)
|
||||
poses = self.D_conv2(poses)
|
||||
poses = self.relu(poses)
|
||||
|
||||
poses_out = []
|
||||
for i in range(self.num_joints):
|
||||
poses_out_ = self.pose_out[i](poses[:, :, i, 0])
|
||||
poses_out.append(poses_out_)
|
||||
poses_out = torch.cat(poses_out, dim=1)
|
||||
|
||||
# betas
|
||||
betas = self.betas_fc1(betas)
|
||||
betas = self.relu(betas)
|
||||
betas = self.betas_fc2(betas)
|
||||
betas = self.relu(betas)
|
||||
betas_out = self.betas_out(betas)
|
||||
|
||||
# poses_joint
|
||||
poses = poses.reshape(bn,-1)
|
||||
poses_all = self.D_alljoints_fc1(poses)
|
||||
poses_all = self.relu(poses_all)
|
||||
poses_all = self.D_alljoints_fc2(poses_all)
|
||||
poses_all = self.relu(poses_all)
|
||||
poses_all_out = self.D_alljoints_out(poses_all)
|
||||
|
||||
disc_out = torch.cat((poses_out, betas_out, poses_all_out), 1)
|
||||
return disc_out
|
||||
+355
@@ -0,0 +1,355 @@
|
||||
import torch
|
||||
import pytorch_lightning as pl
|
||||
from typing import Any, Dict, Mapping, Tuple
|
||||
|
||||
from yacs.config import CfgNode
|
||||
|
||||
from ..utils import SkeletonRenderer, MeshRenderer
|
||||
from ..utils.geometry import aa_to_rotmat, perspective_projection
|
||||
from ..utils.pylogger import get_pylogger
|
||||
from .backbones import create_backbone
|
||||
from .heads import build_mano_head
|
||||
from .discriminator import Discriminator
|
||||
from .losses import Keypoint3DLoss, Keypoint2DLoss, ParameterLoss
|
||||
from . import MANO
|
||||
|
||||
log = get_pylogger(__name__)
|
||||
|
||||
class HAMER(pl.LightningModule):
|
||||
|
||||
def __init__(self, cfg: CfgNode, init_renderer: bool = True):
|
||||
"""
|
||||
Setup HAMER model
|
||||
Args:
|
||||
cfg (CfgNode): Config file as a yacs CfgNode
|
||||
"""
|
||||
super().__init__()
|
||||
|
||||
# Save hyperparameters
|
||||
self.save_hyperparameters(logger=False, ignore=['init_renderer'])
|
||||
|
||||
self.cfg = cfg
|
||||
# Create backbone feature extractor
|
||||
self.backbone = create_backbone(cfg)
|
||||
if cfg.MODEL.BACKBONE.get('PRETRAINED_WEIGHTS', None):
|
||||
log.info(f'Loading backbone weights from {cfg.MODEL.BACKBONE.PRETRAINED_WEIGHTS}')
|
||||
self.backbone.load_state_dict(torch.load(cfg.MODEL.BACKBONE.PRETRAINED_WEIGHTS, map_location='cpu')['state_dict'])
|
||||
|
||||
# Create MANO head
|
||||
self.mano_head = build_mano_head(cfg)
|
||||
|
||||
# Create discriminator
|
||||
if self.cfg.LOSS_WEIGHTS.ADVERSARIAL > 0:
|
||||
self.discriminator = Discriminator()
|
||||
|
||||
# Define loss functions
|
||||
self.keypoint_3d_loss = Keypoint3DLoss(loss_type='l1')
|
||||
self.keypoint_2d_loss = Keypoint2DLoss(loss_type='l1')
|
||||
self.mano_parameter_loss = ParameterLoss()
|
||||
|
||||
# Instantiate MANO model
|
||||
mano_cfg = {k.lower(): v for k,v in dict(cfg.MANO).items()}
|
||||
self.mano = MANO(**mano_cfg)
|
||||
|
||||
# Buffer that shows whetheer we need to initialize ActNorm layers
|
||||
self.register_buffer('initialized', torch.tensor(False))
|
||||
# Setup renderer for visualization
|
||||
if init_renderer:
|
||||
self.renderer = SkeletonRenderer(self.cfg)
|
||||
self.mesh_renderer = MeshRenderer(self.cfg, faces=self.mano.faces)
|
||||
else:
|
||||
self.renderer = None
|
||||
self.mesh_renderer = None
|
||||
|
||||
# Disable automatic optimization since we use adversarial training
|
||||
self.automatic_optimization = False
|
||||
|
||||
def get_parameters(self):
|
||||
all_params = list(self.mano_head.parameters())
|
||||
all_params += list(self.backbone.parameters())
|
||||
return all_params
|
||||
|
||||
def configure_optimizers(self) -> Tuple[torch.optim.Optimizer, torch.optim.Optimizer]:
|
||||
"""
|
||||
Setup model and distriminator Optimizers
|
||||
Returns:
|
||||
Tuple[torch.optim.Optimizer, torch.optim.Optimizer]: Model and discriminator optimizers
|
||||
"""
|
||||
param_groups = [{'params': filter(lambda p: p.requires_grad, self.get_parameters()), 'lr': self.cfg.TRAIN.LR}]
|
||||
|
||||
optimizer = torch.optim.AdamW(params=param_groups,
|
||||
# lr=self.cfg.TRAIN.LR,
|
||||
weight_decay=self.cfg.TRAIN.WEIGHT_DECAY)
|
||||
optimizer_disc = torch.optim.AdamW(params=self.discriminator.parameters(),
|
||||
lr=self.cfg.TRAIN.LR,
|
||||
weight_decay=self.cfg.TRAIN.WEIGHT_DECAY)
|
||||
|
||||
return optimizer, optimizer_disc
|
||||
|
||||
def forward_step(self, batch: Dict, train: bool = False) -> Dict:
|
||||
"""
|
||||
Run a forward step of the network
|
||||
Args:
|
||||
batch (Dict): Dictionary containing batch data
|
||||
train (bool): Flag indicating whether it is training or validation mode
|
||||
Returns:
|
||||
Dict: Dictionary containing the regression output
|
||||
"""
|
||||
|
||||
# Use RGB image as input
|
||||
x = batch['img']
|
||||
batch_size = x.shape[0]
|
||||
|
||||
# Compute conditioning features using the backbone
|
||||
# if using ViT backbone, we need to use a different aspect ratio
|
||||
conditioning_feats = self.backbone(x[:,:,:,32:-32])
|
||||
|
||||
pred_mano_params, pred_cam, _ = self.mano_head(conditioning_feats)
|
||||
|
||||
# Store useful regression outputs to the output dict
|
||||
output = {}
|
||||
output['pred_cam'] = pred_cam
|
||||
output['pred_mano_params'] = {k: v.clone() for k,v in pred_mano_params.items()}
|
||||
|
||||
# Compute camera translation
|
||||
device = pred_mano_params['hand_pose'].device
|
||||
dtype = pred_mano_params['hand_pose'].dtype
|
||||
focal_length = self.cfg.EXTRA.FOCAL_LENGTH * torch.ones(batch_size, 2, device=device, dtype=dtype)
|
||||
pred_cam_t = torch.stack([pred_cam[:, 1],
|
||||
pred_cam[:, 2],
|
||||
2*focal_length[:, 0]/(self.cfg.MODEL.IMAGE_SIZE * pred_cam[:, 0] +1e-9)],dim=-1)
|
||||
output['pred_cam_t'] = pred_cam_t
|
||||
output['focal_length'] = focal_length
|
||||
|
||||
# Compute model vertices, joints and the projected joints
|
||||
pred_mano_params['global_orient'] = pred_mano_params['global_orient'].reshape(batch_size, -1, 3, 3)
|
||||
pred_mano_params['hand_pose'] = pred_mano_params['hand_pose'].reshape(batch_size, -1, 3, 3)
|
||||
pred_mano_params['betas'] = pred_mano_params['betas'].reshape(batch_size, -1)
|
||||
mano_output = self.mano(**{k: v.float() for k,v in pred_mano_params.items()}, pose2rot=False)
|
||||
pred_keypoints_3d = mano_output.joints
|
||||
pred_vertices = mano_output.vertices
|
||||
output['pred_keypoints_3d'] = pred_keypoints_3d.reshape(batch_size, -1, 3)
|
||||
output['pred_vertices'] = pred_vertices.reshape(batch_size, -1, 3)
|
||||
pred_cam_t = pred_cam_t.reshape(-1, 3)
|
||||
focal_length = focal_length.reshape(-1, 2)
|
||||
pred_keypoints_2d = perspective_projection(pred_keypoints_3d,
|
||||
translation=pred_cam_t,
|
||||
focal_length=focal_length / self.cfg.MODEL.IMAGE_SIZE)
|
||||
|
||||
output['pred_keypoints_2d'] = pred_keypoints_2d.reshape(batch_size, -1, 2)
|
||||
return output
|
||||
|
||||
def compute_loss(self, batch: Dict, output: Dict, train: bool = True) -> torch.Tensor:
|
||||
"""
|
||||
Compute losses given the input batch and the regression output
|
||||
Args:
|
||||
batch (Dict): Dictionary containing batch data
|
||||
output (Dict): Dictionary containing the regression output
|
||||
train (bool): Flag indicating whether it is training or validation mode
|
||||
Returns:
|
||||
torch.Tensor : Total loss for current batch
|
||||
"""
|
||||
|
||||
pred_mano_params = output['pred_mano_params']
|
||||
pred_keypoints_2d = output['pred_keypoints_2d']
|
||||
pred_keypoints_3d = output['pred_keypoints_3d']
|
||||
|
||||
|
||||
batch_size = pred_mano_params['hand_pose'].shape[0]
|
||||
device = pred_mano_params['hand_pose'].device
|
||||
dtype = pred_mano_params['hand_pose'].dtype
|
||||
|
||||
# Get annotations
|
||||
gt_keypoints_2d = batch['keypoints_2d']
|
||||
gt_keypoints_3d = batch['keypoints_3d']
|
||||
gt_mano_params = batch['mano_params']
|
||||
has_mano_params = batch['has_mano_params']
|
||||
is_axis_angle = batch['mano_params_is_axis_angle']
|
||||
|
||||
# Compute 3D keypoint loss
|
||||
loss_keypoints_2d = self.keypoint_2d_loss(pred_keypoints_2d, gt_keypoints_2d)
|
||||
loss_keypoints_3d = self.keypoint_3d_loss(pred_keypoints_3d, gt_keypoints_3d, pelvis_id=0)
|
||||
|
||||
# Compute loss on MANO parameters
|
||||
loss_mano_params = {}
|
||||
for k, pred in pred_mano_params.items():
|
||||
gt = gt_mano_params[k].view(batch_size, -1)
|
||||
if is_axis_angle[k].all():
|
||||
gt = aa_to_rotmat(gt.reshape(-1, 3)).view(batch_size, -1, 3, 3)
|
||||
has_gt = has_mano_params[k]
|
||||
loss_mano_params[k] = self.mano_parameter_loss(pred.reshape(batch_size, -1), gt.reshape(batch_size, -1), has_gt)
|
||||
|
||||
loss = self.cfg.LOSS_WEIGHTS['KEYPOINTS_3D'] * loss_keypoints_3d+\
|
||||
self.cfg.LOSS_WEIGHTS['KEYPOINTS_2D'] * loss_keypoints_2d+\
|
||||
sum([loss_mano_params[k] * self.cfg.LOSS_WEIGHTS[k.upper()] for k in loss_mano_params])
|
||||
|
||||
losses = dict(loss=loss.detach(),
|
||||
loss_keypoints_2d=loss_keypoints_2d.detach(),
|
||||
loss_keypoints_3d=loss_keypoints_3d.detach())
|
||||
|
||||
for k, v in loss_mano_params.items():
|
||||
losses['loss_' + k] = v.detach()
|
||||
|
||||
output['losses'] = losses
|
||||
|
||||
return loss
|
||||
|
||||
# Tensoroboard logging should run from first rank only
|
||||
@pl.utilities.rank_zero.rank_zero_only
|
||||
def tensorboard_logging(self, batch: Dict, output: Dict, step_count: int, train: bool = True, write_to_summary_writer: bool = True) -> None:
|
||||
"""
|
||||
Log results to Tensorboard
|
||||
Args:
|
||||
batch (Dict): Dictionary containing batch data
|
||||
output (Dict): Dictionary containing the regression output
|
||||
step_count (int): Global training step count
|
||||
train (bool): Flag indicating whether it is training or validation mode
|
||||
"""
|
||||
|
||||
mode = 'train' if train else 'val'
|
||||
batch_size = batch['keypoints_2d'].shape[0]
|
||||
images = batch['img']
|
||||
images = images * torch.tensor([0.229, 0.224, 0.225], device=images.device).reshape(1,3,1,1)
|
||||
images = images + torch.tensor([0.485, 0.456, 0.406], device=images.device).reshape(1,3,1,1)
|
||||
#images = 255*images.permute(0, 2, 3, 1).cpu().numpy()
|
||||
|
||||
pred_keypoints_3d = output['pred_keypoints_3d'].detach().reshape(batch_size, -1, 3)
|
||||
pred_vertices = output['pred_vertices'].detach().reshape(batch_size, -1, 3)
|
||||
focal_length = output['focal_length'].detach().reshape(batch_size, 2)
|
||||
gt_keypoints_3d = batch['keypoints_3d']
|
||||
gt_keypoints_2d = batch['keypoints_2d']
|
||||
losses = output['losses']
|
||||
pred_cam_t = output['pred_cam_t'].detach().reshape(batch_size, 3)
|
||||
pred_keypoints_2d = output['pred_keypoints_2d'].detach().reshape(batch_size, -1, 2)
|
||||
|
||||
if write_to_summary_writer:
|
||||
summary_writer = self.logger.experiment
|
||||
for loss_name, val in losses.items():
|
||||
summary_writer.add_scalar(mode +'/' + loss_name, val.detach().item(), step_count)
|
||||
num_images = min(batch_size, self.cfg.EXTRA.NUM_LOG_IMAGES)
|
||||
|
||||
gt_keypoints_3d = batch['keypoints_3d']
|
||||
pred_keypoints_3d = output['pred_keypoints_3d'].detach().reshape(batch_size, -1, 3)
|
||||
|
||||
# We render the skeletons instead of the full mesh because rendering a lot of meshes will make the training slow.
|
||||
#predictions = self.renderer(pred_keypoints_3d[:num_images],
|
||||
# gt_keypoints_3d[:num_images],
|
||||
# 2 * gt_keypoints_2d[:num_images],
|
||||
# images=images[:num_images],
|
||||
# camera_translation=pred_cam_t[:num_images])
|
||||
predictions = self.mesh_renderer.visualize_tensorboard(pred_vertices[:num_images].cpu().numpy(),
|
||||
pred_cam_t[:num_images].cpu().numpy(),
|
||||
images[:num_images].cpu().numpy(),
|
||||
pred_keypoints_2d[:num_images].cpu().numpy(),
|
||||
gt_keypoints_2d[:num_images].cpu().numpy(),
|
||||
focal_length=focal_length[:num_images].cpu().numpy())
|
||||
if write_to_summary_writer:
|
||||
summary_writer.add_image('%s/predictions' % mode, predictions, step_count)
|
||||
|
||||
return predictions
|
||||
|
||||
def forward(self, batch: Dict) -> Dict:
|
||||
"""
|
||||
Run a forward step of the network in val mode
|
||||
Args:
|
||||
batch (Dict): Dictionary containing batch data
|
||||
Returns:
|
||||
Dict: Dictionary containing the regression output
|
||||
"""
|
||||
return self.forward_step(batch, train=False)
|
||||
|
||||
def training_step_discriminator(self, batch: Dict,
|
||||
hand_pose: torch.Tensor,
|
||||
betas: torch.Tensor,
|
||||
optimizer: torch.optim.Optimizer) -> torch.Tensor:
|
||||
"""
|
||||
Run a discriminator training step
|
||||
Args:
|
||||
batch (Dict): Dictionary containing mocap batch data
|
||||
hand_pose (torch.Tensor): Regressed hand pose from current step
|
||||
betas (torch.Tensor): Regressed betas from current step
|
||||
optimizer (torch.optim.Optimizer): Discriminator optimizer
|
||||
Returns:
|
||||
torch.Tensor: Discriminator loss
|
||||
"""
|
||||
batch_size = hand_pose.shape[0]
|
||||
gt_hand_pose = batch['hand_pose']
|
||||
gt_betas = batch['betas']
|
||||
gt_rotmat = aa_to_rotmat(gt_hand_pose.view(-1,3)).view(batch_size, -1, 3, 3)
|
||||
disc_fake_out = self.discriminator(hand_pose.detach(), betas.detach())
|
||||
loss_fake = ((disc_fake_out - 0.0) ** 2).sum() / batch_size
|
||||
disc_real_out = self.discriminator(gt_rotmat, gt_betas)
|
||||
loss_real = ((disc_real_out - 1.0) ** 2).sum() / batch_size
|
||||
loss_disc = loss_fake + loss_real
|
||||
loss = self.cfg.LOSS_WEIGHTS.ADVERSARIAL * loss_disc
|
||||
optimizer.zero_grad()
|
||||
self.manual_backward(loss)
|
||||
optimizer.step()
|
||||
return loss_disc.detach()
|
||||
|
||||
def training_step(self, joint_batch: Dict, batch_idx: int) -> Dict:
|
||||
"""
|
||||
Run a full training step
|
||||
Args:
|
||||
joint_batch (Dict): Dictionary containing image and mocap batch data
|
||||
batch_idx (int): Unused.
|
||||
batch_idx (torch.Tensor): Unused.
|
||||
Returns:
|
||||
Dict: Dictionary containing regression output.
|
||||
"""
|
||||
batch = joint_batch['img']
|
||||
mocap_batch = joint_batch['mocap']
|
||||
optimizer = self.optimizers(use_pl_optimizer=True)
|
||||
if self.cfg.LOSS_WEIGHTS.ADVERSARIAL > 0:
|
||||
optimizer, optimizer_disc = optimizer
|
||||
|
||||
batch_size = batch['img'].shape[0]
|
||||
output = self.forward_step(batch, train=True)
|
||||
pred_mano_params = output['pred_mano_params']
|
||||
if self.cfg.get('UPDATE_GT_SPIN', False):
|
||||
self.update_batch_gt_spin(batch, output)
|
||||
loss = self.compute_loss(batch, output, train=True)
|
||||
if self.cfg.LOSS_WEIGHTS.ADVERSARIAL > 0:
|
||||
disc_out = self.discriminator(pred_mano_params['hand_pose'].reshape(batch_size, -1), pred_mano_params['betas'].reshape(batch_size, -1))
|
||||
loss_adv = ((disc_out - 1.0) ** 2).sum() / batch_size
|
||||
loss = loss + self.cfg.LOSS_WEIGHTS.ADVERSARIAL * loss_adv
|
||||
|
||||
# Error if Nan
|
||||
if torch.isnan(loss):
|
||||
raise ValueError('Loss is NaN')
|
||||
|
||||
optimizer.zero_grad()
|
||||
self.manual_backward(loss)
|
||||
# Clip gradient
|
||||
if self.cfg.TRAIN.get('GRAD_CLIP_VAL', 0) > 0:
|
||||
gn = torch.nn.utils.clip_grad_norm_(self.get_parameters(), self.cfg.TRAIN.GRAD_CLIP_VAL, error_if_nonfinite=True)
|
||||
self.log('train/grad_norm', gn, on_step=True, on_epoch=True, prog_bar=True, logger=True)
|
||||
optimizer.step()
|
||||
if self.cfg.LOSS_WEIGHTS.ADVERSARIAL > 0:
|
||||
loss_disc = self.training_step_discriminator(mocap_batch, pred_mano_params['hand_pose'].reshape(batch_size, -1), pred_mano_params['betas'].reshape(batch_size, -1), optimizer_disc)
|
||||
output['losses']['loss_gen'] = loss_adv
|
||||
output['losses']['loss_disc'] = loss_disc
|
||||
|
||||
if self.global_step > 0 and self.global_step % self.cfg.GENERAL.LOG_STEPS == 0:
|
||||
self.tensorboard_logging(batch, output, self.global_step, train=True)
|
||||
|
||||
self.log('train/loss', output['losses']['loss'], on_step=True, on_epoch=True, prog_bar=True, logger=False)
|
||||
|
||||
return output
|
||||
|
||||
def validation_step(self, batch: Dict, batch_idx: int, dataloader_idx=0) -> Dict:
|
||||
"""
|
||||
Run a validation step and log to Tensorboard
|
||||
Args:
|
||||
batch (Dict): Dictionary containing batch data
|
||||
batch_idx (int): Unused.
|
||||
Returns:
|
||||
Dict: Dictionary containing regression output.
|
||||
"""
|
||||
# batch_size = batch['img'].shape[0]
|
||||
output = self.forward_step(batch, train=False)
|
||||
loss = self.compute_loss(batch, output, train=False)
|
||||
output['loss'] = loss
|
||||
self.tensorboard_logging(batch, output, self.global_step, train=False)
|
||||
|
||||
return output
|
||||
@@ -0,0 +1 @@
|
||||
from .mano_head import build_mano_head
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
import torch.nn.functional as F
|
||||
import numpy as np
|
||||
import einops
|
||||
|
||||
from ...utils.geometry import rot6d_to_rotmat, aa_to_rotmat
|
||||
from ..components.pose_transformer import TransformerDecoder
|
||||
|
||||
def build_mano_head(cfg):
|
||||
mano_head_type = cfg.MODEL.MANO_HEAD.get('TYPE', 'hamer')
|
||||
if mano_head_type == 'transformer_decoder':
|
||||
return MANOTransformerDecoderHead(cfg)
|
||||
else:
|
||||
raise ValueError('Unknown MANO head type: {}'.format(mano_head_type))
|
||||
|
||||
class MANOTransformerDecoderHead(nn.Module):
|
||||
""" Cross-attention based MANO Transformer decoder
|
||||
"""
|
||||
|
||||
def __init__(self, cfg):
|
||||
super().__init__()
|
||||
self.cfg = cfg
|
||||
self.joint_rep_type = cfg.MODEL.MANO_HEAD.get('JOINT_REP', '6d')
|
||||
self.joint_rep_dim = {'6d': 6, 'aa': 3}[self.joint_rep_type]
|
||||
npose = self.joint_rep_dim * (cfg.MANO.NUM_HAND_JOINTS + 1)
|
||||
self.npose = npose
|
||||
self.input_is_mean_shape = cfg.MODEL.MANO_HEAD.get('TRANSFORMER_INPUT', 'zero') == 'mean_shape'
|
||||
transformer_args = dict(
|
||||
num_tokens=1,
|
||||
token_dim=(npose + 10 + 3) if self.input_is_mean_shape else 1,
|
||||
dim=1024,
|
||||
)
|
||||
transformer_args = (transformer_args | dict(cfg.MODEL.MANO_HEAD.TRANSFORMER_DECODER))
|
||||
self.transformer = TransformerDecoder(
|
||||
**transformer_args
|
||||
)
|
||||
dim=transformer_args['dim']
|
||||
self.decpose = nn.Linear(dim, npose)
|
||||
self.decshape = nn.Linear(dim, 10)
|
||||
self.deccam = nn.Linear(dim, 3)
|
||||
|
||||
if cfg.MODEL.MANO_HEAD.get('INIT_DECODER_XAVIER', False):
|
||||
# True by default in MLP. False by default in Transformer
|
||||
nn.init.xavier_uniform_(self.decpose.weight, gain=0.01)
|
||||
nn.init.xavier_uniform_(self.decshape.weight, gain=0.01)
|
||||
nn.init.xavier_uniform_(self.deccam.weight, gain=0.01)
|
||||
|
||||
mean_params = np.load(cfg.MANO.MEAN_PARAMS)
|
||||
init_hand_pose = torch.from_numpy(mean_params['pose'].astype(np.float32)).unsqueeze(0)
|
||||
init_betas = torch.from_numpy(mean_params['shape'].astype('float32')).unsqueeze(0)
|
||||
init_cam = torch.from_numpy(mean_params['cam'].astype(np.float32)).unsqueeze(0)
|
||||
self.register_buffer('init_hand_pose', init_hand_pose)
|
||||
self.register_buffer('init_betas', init_betas)
|
||||
self.register_buffer('init_cam', init_cam)
|
||||
|
||||
def forward(self, x, **kwargs):
|
||||
|
||||
batch_size = x.shape[0]
|
||||
# vit pretrained backbone is channel-first. Change to token-first
|
||||
x = einops.rearrange(x, 'b c h w -> b (h w) c')
|
||||
|
||||
init_hand_pose = self.init_hand_pose.expand(batch_size, -1)
|
||||
init_betas = self.init_betas.expand(batch_size, -1)
|
||||
init_cam = self.init_cam.expand(batch_size, -1)
|
||||
|
||||
# TODO: Convert init_hand_pose to aa rep if needed
|
||||
if self.joint_rep_type == 'aa':
|
||||
raise NotImplementedError
|
||||
|
||||
pred_hand_pose = init_hand_pose
|
||||
pred_betas = init_betas
|
||||
pred_cam = init_cam
|
||||
pred_hand_pose_list = []
|
||||
pred_betas_list = []
|
||||
pred_cam_list = []
|
||||
for i in range(self.cfg.MODEL.MANO_HEAD.get('IEF_ITERS', 1)):
|
||||
# Input token to transformer is zero token
|
||||
if self.input_is_mean_shape:
|
||||
token = torch.cat([pred_hand_pose, pred_betas, pred_cam], dim=1)[:,None,:]
|
||||
else:
|
||||
token = torch.zeros(batch_size, 1, 1).to(x.device)
|
||||
|
||||
# Pass through transformer
|
||||
token_out = self.transformer(token, context=x)
|
||||
token_out = token_out.squeeze(1) # (B, C)
|
||||
|
||||
# Readout from token_out
|
||||
pred_hand_pose = self.decpose(token_out) + pred_hand_pose
|
||||
pred_betas = self.decshape(token_out) + pred_betas
|
||||
pred_cam = self.deccam(token_out) + pred_cam
|
||||
pred_hand_pose_list.append(pred_hand_pose)
|
||||
pred_betas_list.append(pred_betas)
|
||||
pred_cam_list.append(pred_cam)
|
||||
|
||||
# Convert self.joint_rep_type -> rotmat
|
||||
joint_conversion_fn = {
|
||||
'6d': rot6d_to_rotmat,
|
||||
'aa': lambda x: aa_to_rotmat(x.view(-1, 3).contiguous())
|
||||
}[self.joint_rep_type]
|
||||
|
||||
pred_mano_params_list = {}
|
||||
pred_mano_params_list['hand_pose'] = torch.cat([joint_conversion_fn(pbp).view(batch_size, -1, 3, 3)[:, 1:, :, :] for pbp in pred_hand_pose_list], dim=0)
|
||||
pred_mano_params_list['betas'] = torch.cat(pred_betas_list, dim=0)
|
||||
pred_mano_params_list['cam'] = torch.cat(pred_cam_list, dim=0)
|
||||
pred_hand_pose = joint_conversion_fn(pred_hand_pose).view(batch_size, self.cfg.MANO.NUM_HAND_JOINTS+1, 3, 3)
|
||||
|
||||
pred_mano_params = {'global_orient': pred_hand_pose[:, [0]],
|
||||
'hand_pose': pred_hand_pose[:, 1:],
|
||||
'betas': pred_betas}
|
||||
return pred_mano_params, pred_cam, pred_mano_params_list
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
|
||||
class Keypoint2DLoss(nn.Module):
|
||||
|
||||
def __init__(self, loss_type: str = 'l1'):
|
||||
"""
|
||||
2D keypoint loss module.
|
||||
Args:
|
||||
loss_type (str): Choose between l1 and l2 losses.
|
||||
"""
|
||||
super(Keypoint2DLoss, self).__init__()
|
||||
if loss_type == 'l1':
|
||||
self.loss_fn = nn.L1Loss(reduction='none')
|
||||
elif loss_type == 'l2':
|
||||
self.loss_fn = nn.MSELoss(reduction='none')
|
||||
else:
|
||||
raise NotImplementedError('Unsupported loss function')
|
||||
|
||||
def forward(self, pred_keypoints_2d: torch.Tensor, gt_keypoints_2d: torch.Tensor) -> torch.Tensor:
|
||||
"""
|
||||
Compute 2D reprojection loss on the keypoints.
|
||||
Args:
|
||||
pred_keypoints_2d (torch.Tensor): Tensor of shape [B, S, N, 2] containing projected 2D keypoints (B: batch_size, S: num_samples, N: num_keypoints)
|
||||
gt_keypoints_2d (torch.Tensor): Tensor of shape [B, S, N, 3] containing the ground truth 2D keypoints and confidence.
|
||||
Returns:
|
||||
torch.Tensor: 2D keypoint loss.
|
||||
"""
|
||||
conf = gt_keypoints_2d[:, :, -1].unsqueeze(-1).clone()
|
||||
batch_size = conf.shape[0]
|
||||
loss = (conf * self.loss_fn(pred_keypoints_2d, gt_keypoints_2d[:, :, :-1])).sum(dim=(1,2))
|
||||
return loss.sum()
|
||||
|
||||
|
||||
class Keypoint3DLoss(nn.Module):
|
||||
|
||||
def __init__(self, loss_type: str = 'l1'):
|
||||
"""
|
||||
3D keypoint loss module.
|
||||
Args:
|
||||
loss_type (str): Choose between l1 and l2 losses.
|
||||
"""
|
||||
super(Keypoint3DLoss, self).__init__()
|
||||
if loss_type == 'l1':
|
||||
self.loss_fn = nn.L1Loss(reduction='none')
|
||||
elif loss_type == 'l2':
|
||||
self.loss_fn = nn.MSELoss(reduction='none')
|
||||
else:
|
||||
raise NotImplementedError('Unsupported loss function')
|
||||
|
||||
def forward(self, pred_keypoints_3d: torch.Tensor, gt_keypoints_3d: torch.Tensor, pelvis_id: int = 0):
|
||||
"""
|
||||
Compute 3D keypoint loss.
|
||||
Args:
|
||||
pred_keypoints_3d (torch.Tensor): Tensor of shape [B, S, N, 3] containing the predicted 3D keypoints (B: batch_size, S: num_samples, N: num_keypoints)
|
||||
gt_keypoints_3d (torch.Tensor): Tensor of shape [B, S, N, 4] containing the ground truth 3D keypoints and confidence.
|
||||
Returns:
|
||||
torch.Tensor: 3D keypoint loss.
|
||||
"""
|
||||
batch_size = pred_keypoints_3d.shape[0]
|
||||
gt_keypoints_3d = gt_keypoints_3d.clone()
|
||||
pred_keypoints_3d = pred_keypoints_3d - pred_keypoints_3d[:, pelvis_id, :].unsqueeze(dim=1)
|
||||
gt_keypoints_3d[:, :, :-1] = gt_keypoints_3d[:, :, :-1] - gt_keypoints_3d[:, pelvis_id, :-1].unsqueeze(dim=1)
|
||||
conf = gt_keypoints_3d[:, :, -1].unsqueeze(-1).clone()
|
||||
gt_keypoints_3d = gt_keypoints_3d[:, :, :-1]
|
||||
loss = (conf * self.loss_fn(pred_keypoints_3d, gt_keypoints_3d)).sum(dim=(1,2))
|
||||
return loss.sum()
|
||||
|
||||
class ParameterLoss(nn.Module):
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
MANO parameter loss module.
|
||||
"""
|
||||
super(ParameterLoss, self).__init__()
|
||||
self.loss_fn = nn.MSELoss(reduction='none')
|
||||
|
||||
def forward(self, pred_param: torch.Tensor, gt_param: torch.Tensor, has_param: torch.Tensor):
|
||||
"""
|
||||
Compute MANO parameter loss.
|
||||
Args:
|
||||
pred_param (torch.Tensor): Tensor of shape [B, S, ...] containing the predicted parameters (body pose / global orientation / betas)
|
||||
gt_param (torch.Tensor): Tensor of shape [B, S, ...] containing the ground truth MANO parameters.
|
||||
Returns:
|
||||
torch.Tensor: L2 parameter loss loss.
|
||||
"""
|
||||
batch_size = pred_param.shape[0]
|
||||
num_dims = len(pred_param.shape)
|
||||
mask_dimension = [batch_size] + [1] * (num_dims-1)
|
||||
has_param = has_param.type(pred_param.type()).view(*mask_dimension)
|
||||
loss_param = (has_param * self.loss_fn(pred_param, gt_param))
|
||||
return loss_param.sum()
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
import torch
|
||||
import numpy as np
|
||||
import pickle
|
||||
from typing import Optional
|
||||
import smplx
|
||||
from smplx.lbs import vertices2joints
|
||||
from smplx.utils import MANOOutput, to_tensor
|
||||
from smplx.vertex_ids import vertex_ids
|
||||
|
||||
|
||||
class MANO(smplx.MANOLayer):
|
||||
def __init__(self, *args, joint_regressor_extra: Optional[str] = None, **kwargs):
|
||||
"""
|
||||
Extension of the official MANO implementation to support more joints.
|
||||
Args:
|
||||
Same as MANOLayer.
|
||||
joint_regressor_extra (str): Path to extra joint regressor.
|
||||
"""
|
||||
super(MANO, self).__init__(*args, **kwargs)
|
||||
mano_to_openpose = [0, 13, 14, 15, 16, 1, 2, 3, 17, 4, 5, 6, 18, 10, 11, 12, 19, 7, 8, 9, 20]
|
||||
|
||||
#2, 3, 5, 4, 1
|
||||
if joint_regressor_extra is not None:
|
||||
self.register_buffer('joint_regressor_extra', torch.tensor(pickle.load(open(joint_regressor_extra, 'rb'), encoding='latin1'), dtype=torch.float32))
|
||||
self.register_buffer('extra_joints_idxs', to_tensor(list(vertex_ids['mano'].values()), dtype=torch.long))
|
||||
self.register_buffer('joint_map', torch.tensor(mano_to_openpose, dtype=torch.long))
|
||||
|
||||
def forward(self, *args, **kwargs) -> MANOOutput:
|
||||
"""
|
||||
Run forward pass. Same as MANO and also append an extra set of joints if joint_regressor_extra is specified.
|
||||
"""
|
||||
mano_output = super(MANO, self).forward(*args, **kwargs)
|
||||
extra_joints = torch.index_select(mano_output.vertices, 1, self.extra_joints_idxs)
|
||||
joints = torch.cat([mano_output.joints, extra_joints], dim=1)
|
||||
joints = joints[:, self.joint_map, :]
|
||||
if hasattr(self, 'joint_regressor_extra'):
|
||||
extra_joints = vertices2joints(self.joint_regressor_extra, mano_output.vertices)
|
||||
joints = torch.cat([joints, extra_joints], dim=1)
|
||||
mano_output.joints = joints
|
||||
return mano_output
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import torch
|
||||
from typing import Any
|
||||
|
||||
from .renderer import Renderer
|
||||
from .mesh_renderer import MeshRenderer
|
||||
from .skeleton_renderer import SkeletonRenderer
|
||||
from .pose_utils import eval_pose, Evaluator
|
||||
|
||||
def recursive_to(x: Any, target: torch.device):
|
||||
"""
|
||||
Recursively transfer a batch of data to the target device
|
||||
Args:
|
||||
x (Any): Batch of data.
|
||||
target (torch.device): Target device.
|
||||
Returns:
|
||||
Batch of data where all tensors are transfered to the target device.
|
||||
"""
|
||||
if isinstance(x, dict):
|
||||
return {k: recursive_to(v, target) for k, v in x.items()}
|
||||
elif isinstance(x, torch.Tensor):
|
||||
return x.to(target)
|
||||
elif isinstance(x, list):
|
||||
return [recursive_to(i, target) for i in x]
|
||||
else:
|
||||
return x
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from urllib import request as urlrequest
|
||||
|
||||
|
||||
def _progress_bar(count, total):
|
||||
"""Report download progress. Credit:
|
||||
https://stackoverflow.com/questions/3173320/text-progress-bar-in-the-console/27871113
|
||||
"""
|
||||
bar_len = 60
|
||||
filled_len = int(round(bar_len * count / float(total)))
|
||||
percents = round(100.0 * count / float(total), 1)
|
||||
bar = "=" * filled_len + "-" * (bar_len - filled_len)
|
||||
sys.stdout.write(
|
||||
" [{}] {}% of {:.1f}MB file \r".format(bar, percents, total / 1024 / 1024)
|
||||
)
|
||||
sys.stdout.flush()
|
||||
if count >= total:
|
||||
sys.stdout.write("\n")
|
||||
|
||||
|
||||
def download_url(url, dst_file_path, chunk_size=8192, progress_hook=_progress_bar):
|
||||
"""Download url and write it to dst_file_path. Credit:
|
||||
https://stackoverflow.com/questions/2028517/python-urllib2-progress-hook
|
||||
"""
|
||||
# url = url + "?dl=1" if "dropbox" in url else url
|
||||
req = urlrequest.Request(url)
|
||||
response = urlrequest.urlopen(req)
|
||||
total_size = response.info().get("Content-Length")
|
||||
if total_size is None:
|
||||
raise ValueError("Cannot determine size of download from {}".format(url))
|
||||
total_size = int(total_size.strip())
|
||||
bytes_so_far = 0
|
||||
|
||||
with open(dst_file_path, "wb") as f:
|
||||
while 1:
|
||||
chunk = response.read(chunk_size)
|
||||
bytes_so_far += len(chunk)
|
||||
if not chunk:
|
||||
break
|
||||
|
||||
if progress_hook:
|
||||
progress_hook(bytes_so_far, total_size)
|
||||
|
||||
f.write(chunk)
|
||||
return bytes_so_far
|
||||
|
||||
|
||||
def cache_url(url_or_file, cache_file_path, download=True):
|
||||
"""Download the file specified by the URL to the cache_dir and return the path to
|
||||
the cached file. If the argument is not a URL, simply return it as is.
|
||||
"""
|
||||
is_url = re.match(r"^(?:http)s?://", url_or_file, re.IGNORECASE) is not None
|
||||
if not is_url:
|
||||
return url_or_file
|
||||
url = url_or_file
|
||||
if os.path.exists(cache_file_path):
|
||||
return cache_file_path
|
||||
cache_file_dir = os.path.dirname(cache_file_path)
|
||||
if not os.path.exists(cache_file_dir):
|
||||
os.makedirs(cache_file_dir)
|
||||
if download:
|
||||
print("Downloading remote file {} to {}".format(url, cache_file_path))
|
||||
download_url(url, cache_file_path)
|
||||
return cache_file_path
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
from typing import Optional
|
||||
import torch
|
||||
from torch.nn import functional as F
|
||||
|
||||
def aa_to_rotmat(theta: torch.Tensor):
|
||||
"""
|
||||
Convert axis-angle representation to rotation matrix.
|
||||
Works by first converting it to a quaternion.
|
||||
Args:
|
||||
theta (torch.Tensor): Tensor of shape (B, 3) containing axis-angle representations.
|
||||
Returns:
|
||||
torch.Tensor: Corresponding rotation matrices with shape (B, 3, 3).
|
||||
"""
|
||||
norm = torch.norm(theta + 1e-8, p = 2, dim = 1)
|
||||
angle = torch.unsqueeze(norm, -1)
|
||||
normalized = torch.div(theta, angle)
|
||||
angle = angle * 0.5
|
||||
v_cos = torch.cos(angle)
|
||||
v_sin = torch.sin(angle)
|
||||
quat = torch.cat([v_cos, v_sin * normalized], dim = 1)
|
||||
return quat_to_rotmat(quat)
|
||||
|
||||
def quat_to_rotmat(quat: torch.Tensor) -> torch.Tensor:
|
||||
"""
|
||||
Convert quaternion representation to rotation matrix.
|
||||
Args:
|
||||
quat (torch.Tensor) of shape (B, 4); 4 <===> (w, x, y, z).
|
||||
Returns:
|
||||
torch.Tensor: Corresponding rotation matrices with shape (B, 3, 3).
|
||||
"""
|
||||
norm_quat = quat
|
||||
norm_quat = norm_quat/norm_quat.norm(p=2, dim=1, keepdim=True)
|
||||
w, x, y, z = norm_quat[:,0], norm_quat[:,1], norm_quat[:,2], norm_quat[:,3]
|
||||
|
||||
B = quat.size(0)
|
||||
|
||||
w2, x2, y2, z2 = w.pow(2), x.pow(2), y.pow(2), z.pow(2)
|
||||
wx, wy, wz = w*x, w*y, w*z
|
||||
xy, xz, yz = x*y, x*z, y*z
|
||||
|
||||
rotMat = torch.stack([w2 + x2 - y2 - z2, 2*xy - 2*wz, 2*wy + 2*xz,
|
||||
2*wz + 2*xy, w2 - x2 + y2 - z2, 2*yz - 2*wx,
|
||||
2*xz - 2*wy, 2*wx + 2*yz, w2 - x2 - y2 + z2], dim=1).view(B, 3, 3)
|
||||
return rotMat
|
||||
|
||||
|
||||
def rot6d_to_rotmat(x: torch.Tensor) -> torch.Tensor:
|
||||
"""
|
||||
Convert 6D rotation representation to 3x3 rotation matrix.
|
||||
Based on Zhou et al., "On the Continuity of Rotation Representations in Neural Networks", CVPR 2019
|
||||
Args:
|
||||
x (torch.Tensor): (B,6) Batch of 6-D rotation representations.
|
||||
Returns:
|
||||
torch.Tensor: Batch of corresponding rotation matrices with shape (B,3,3).
|
||||
"""
|
||||
x = x.reshape(-1,2,3).permute(0, 2, 1).contiguous()
|
||||
a1 = x[:, :, 0]
|
||||
a2 = x[:, :, 1]
|
||||
b1 = F.normalize(a1)
|
||||
b2 = F.normalize(a2 - torch.einsum('bi,bi->b', b1, a2).unsqueeze(-1) * b1)
|
||||
b3 = torch.cross(b1, b2)
|
||||
return torch.stack((b1, b2, b3), dim=-1)
|
||||
|
||||
def perspective_projection(points: torch.Tensor,
|
||||
translation: torch.Tensor,
|
||||
focal_length: torch.Tensor,
|
||||
camera_center: Optional[torch.Tensor] = None,
|
||||
rotation: Optional[torch.Tensor] = None) -> torch.Tensor:
|
||||
"""
|
||||
Computes the perspective projection of a set of 3D points.
|
||||
Args:
|
||||
points (torch.Tensor): Tensor of shape (B, N, 3) containing the input 3D points.
|
||||
translation (torch.Tensor): Tensor of shape (B, 3) containing the 3D camera translation.
|
||||
focal_length (torch.Tensor): Tensor of shape (B, 2) containing the focal length in pixels.
|
||||
camera_center (torch.Tensor): Tensor of shape (B, 2) containing the camera center in pixels.
|
||||
rotation (torch.Tensor): Tensor of shape (B, 3, 3) containing the camera rotation.
|
||||
Returns:
|
||||
torch.Tensor: Tensor of shape (B, N, 2) containing the projection of the input points.
|
||||
"""
|
||||
batch_size = points.shape[0]
|
||||
if rotation is None:
|
||||
rotation = torch.eye(3, device=points.device, dtype=points.dtype).unsqueeze(0).expand(batch_size, -1, -1)
|
||||
if camera_center is None:
|
||||
camera_center = torch.zeros(batch_size, 2, device=points.device, dtype=points.dtype)
|
||||
# Populate intrinsic camera matrix K.
|
||||
K = torch.zeros([batch_size, 3, 3], device=points.device, dtype=points.dtype)
|
||||
K[:,0,0] = focal_length[:,0]
|
||||
K[:,1,1] = focal_length[:,1]
|
||||
K[:,2,2] = 1.
|
||||
K[:,:-1, -1] = camera_center
|
||||
|
||||
# Transform points
|
||||
points = torch.einsum('bij,bkj->bki', rotation, points)
|
||||
points = points + translation.unsqueeze(1)
|
||||
|
||||
# Apply perspective distortion
|
||||
projected_points = points / points[:,:,-1].unsqueeze(-1)
|
||||
|
||||
# Apply camera intrinsics
|
||||
projected_points = torch.einsum('bij,bkj->bki', K, projected_points)
|
||||
|
||||
return projected_points[:, :, :-1]
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
import os
|
||||
if 'PYOPENGL_PLATFORM' not in os.environ:
|
||||
os.environ['PYOPENGL_PLATFORM'] = 'egl'
|
||||
import torch
|
||||
from torchvision.utils import make_grid
|
||||
import numpy as np
|
||||
import pyrender
|
||||
import trimesh
|
||||
import cv2
|
||||
import torch.nn.functional as F
|
||||
|
||||
from .render_openpose import render_openpose
|
||||
|
||||
def create_raymond_lights():
|
||||
import pyrender
|
||||
thetas = np.pi * np.array([1.0 / 6.0, 1.0 / 6.0, 1.0 / 6.0])
|
||||
phis = np.pi * np.array([0.0, 2.0 / 3.0, 4.0 / 3.0])
|
||||
|
||||
nodes = []
|
||||
|
||||
for phi, theta in zip(phis, thetas):
|
||||
xp = np.sin(theta) * np.cos(phi)
|
||||
yp = np.sin(theta) * np.sin(phi)
|
||||
zp = np.cos(theta)
|
||||
|
||||
z = np.array([xp, yp, zp])
|
||||
z = z / np.linalg.norm(z)
|
||||
x = np.array([-z[1], z[0], 0.0])
|
||||
if np.linalg.norm(x) == 0:
|
||||
x = np.array([1.0, 0.0, 0.0])
|
||||
x = x / np.linalg.norm(x)
|
||||
y = np.cross(z, x)
|
||||
|
||||
matrix = np.eye(4)
|
||||
matrix[:3,:3] = np.c_[x,y,z]
|
||||
nodes.append(pyrender.Node(
|
||||
light=pyrender.DirectionalLight(color=np.ones(3), intensity=1.0),
|
||||
matrix=matrix
|
||||
))
|
||||
|
||||
return nodes
|
||||
|
||||
class MeshRenderer:
|
||||
|
||||
def __init__(self, cfg, faces=None):
|
||||
self.cfg = cfg
|
||||
self.focal_length = cfg.EXTRA.FOCAL_LENGTH
|
||||
self.img_res = cfg.MODEL.IMAGE_SIZE
|
||||
self.renderer = pyrender.OffscreenRenderer(viewport_width=self.img_res,
|
||||
viewport_height=self.img_res,
|
||||
point_size=1.0)
|
||||
|
||||
self.camera_center = [self.img_res // 2, self.img_res // 2]
|
||||
self.faces = faces
|
||||
|
||||
def visualize(self, vertices, camera_translation, images, focal_length=None, nrow=3, padding=2):
|
||||
images_np = np.transpose(images, (0,2,3,1))
|
||||
rend_imgs = []
|
||||
for i in range(vertices.shape[0]):
|
||||
fl = self.focal_length
|
||||
rend_img = torch.from_numpy(np.transpose(self.__call__(vertices[i], camera_translation[i], images_np[i], focal_length=fl, side_view=False), (2,0,1))).float()
|
||||
rend_img_side = torch.from_numpy(np.transpose(self.__call__(vertices[i], camera_translation[i], images_np[i], focal_length=fl, side_view=True), (2,0,1))).float()
|
||||
rend_imgs.append(torch.from_numpy(images[i]))
|
||||
rend_imgs.append(rend_img)
|
||||
rend_imgs.append(rend_img_side)
|
||||
rend_imgs = make_grid(rend_imgs, nrow=nrow, padding=padding)
|
||||
return rend_imgs
|
||||
|
||||
def visualize_tensorboard(self, vertices, camera_translation, images, pred_keypoints, gt_keypoints, focal_length=None, nrow=5, padding=2):
|
||||
images_np = np.transpose(images, (0,2,3,1))
|
||||
rend_imgs = []
|
||||
pred_keypoints = np.concatenate((pred_keypoints, np.ones_like(pred_keypoints)[:, :, [0]]), axis=-1)
|
||||
pred_keypoints = self.img_res * (pred_keypoints + 0.5)
|
||||
gt_keypoints[:, :, :-1] = self.img_res * (gt_keypoints[:, :, :-1] + 0.5)
|
||||
#keypoint_matches = [(1, 12), (2, 8), (3, 7), (4, 6), (5, 9), (6, 10), (7, 11), (8, 14), (9, 2), (10, 1), (11, 0), (12, 3), (13, 4), (14, 5)]
|
||||
for i in range(vertices.shape[0]):
|
||||
fl = self.focal_length
|
||||
rend_img = torch.from_numpy(np.transpose(self.__call__(vertices[i], camera_translation[i], images_np[i], focal_length=fl, side_view=False), (2,0,1))).float()
|
||||
rend_img_side = torch.from_numpy(np.transpose(self.__call__(vertices[i], camera_translation[i], images_np[i], focal_length=fl, side_view=True), (2,0,1))).float()
|
||||
hand_keypoints = pred_keypoints[i, :21]
|
||||
#extra_keypoints = pred_keypoints[i, -19:]
|
||||
#for pair in keypoint_matches:
|
||||
# hand_keypoints[pair[0], :] = extra_keypoints[pair[1], :]
|
||||
pred_keypoints_img = render_openpose(255 * images_np[i].copy(), hand_keypoints) / 255
|
||||
hand_keypoints = gt_keypoints[i, :21]
|
||||
#extra_keypoints = gt_keypoints[i, -19:]
|
||||
#for pair in keypoint_matches:
|
||||
# if extra_keypoints[pair[1], -1] > 0 and hand_keypoints[pair[0], -1] == 0:
|
||||
# hand_keypoints[pair[0], :] = extra_keypoints[pair[1], :]
|
||||
gt_keypoints_img = render_openpose(255*images_np[i].copy(), hand_keypoints) / 255
|
||||
rend_imgs.append(torch.from_numpy(images[i]))
|
||||
rend_imgs.append(rend_img)
|
||||
rend_imgs.append(rend_img_side)
|
||||
rend_imgs.append(torch.from_numpy(pred_keypoints_img).permute(2,0,1))
|
||||
rend_imgs.append(torch.from_numpy(gt_keypoints_img).permute(2,0,1))
|
||||
rend_imgs = make_grid(rend_imgs, nrow=nrow, padding=padding)
|
||||
return rend_imgs
|
||||
|
||||
def __call__(self, vertices, camera_translation, image, focal_length=5000, text=None, resize=None, side_view=False, baseColorFactor=(1.0, 1.0, 0.9, 1.0), rot_angle=90):
|
||||
renderer = pyrender.OffscreenRenderer(viewport_width=image.shape[1],
|
||||
viewport_height=image.shape[0],
|
||||
point_size=1.0)
|
||||
material = pyrender.MetallicRoughnessMaterial(
|
||||
metallicFactor=0.0,
|
||||
alphaMode='OPAQUE',
|
||||
baseColorFactor=baseColorFactor)
|
||||
|
||||
camera_translation[0] *= -1.
|
||||
|
||||
mesh = trimesh.Trimesh(vertices.copy(), self.faces.copy())
|
||||
if side_view:
|
||||
rot = trimesh.transformations.rotation_matrix(
|
||||
np.radians(rot_angle), [0, 1, 0])
|
||||
mesh.apply_transform(rot)
|
||||
rot = trimesh.transformations.rotation_matrix(
|
||||
np.radians(180), [1, 0, 0])
|
||||
mesh.apply_transform(rot)
|
||||
mesh = pyrender.Mesh.from_trimesh(mesh, material=material)
|
||||
|
||||
scene = pyrender.Scene(bg_color=[0.0, 0.0, 0.0, 0.0],
|
||||
ambient_light=(0.3, 0.3, 0.3))
|
||||
scene.add(mesh, 'mesh')
|
||||
|
||||
camera_pose = np.eye(4)
|
||||
camera_pose[:3, 3] = camera_translation
|
||||
camera_center = [image.shape[1] / 2., image.shape[0] / 2.]
|
||||
camera = pyrender.IntrinsicsCamera(fx=focal_length, fy=focal_length,
|
||||
cx=camera_center[0], cy=camera_center[1])
|
||||
scene.add(camera, pose=camera_pose)
|
||||
|
||||
|
||||
light_nodes = create_raymond_lights()
|
||||
for node in light_nodes:
|
||||
scene.add_node(node)
|
||||
|
||||
color, rend_depth = renderer.render(scene, flags=pyrender.RenderFlags.RGBA)
|
||||
color = color.astype(np.float32) / 255.0
|
||||
valid_mask = (color[:, :, -1] > 0)[:, :, np.newaxis]
|
||||
if not side_view:
|
||||
output_img = (color[:, :, :3] * valid_mask +
|
||||
(1 - valid_mask) * image)
|
||||
else:
|
||||
output_img = color[:, :, :3]
|
||||
if resize is not None:
|
||||
output_img = cv2.resize(output_img, resize)
|
||||
|
||||
output_img = output_img.astype(np.float32)
|
||||
renderer.delete()
|
||||
return output_img
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
import time
|
||||
import warnings
|
||||
from importlib.util import find_spec
|
||||
from pathlib import Path
|
||||
from typing import Callable, List
|
||||
|
||||
import hydra
|
||||
from omegaconf import DictConfig, OmegaConf
|
||||
from pytorch_lightning import Callback
|
||||
from pytorch_lightning.loggers import Logger
|
||||
from pytorch_lightning.utilities import rank_zero_only
|
||||
|
||||
from . import pylogger, rich_utils
|
||||
|
||||
log = pylogger.get_pylogger(__name__)
|
||||
|
||||
|
||||
def task_wrapper(task_func: Callable) -> Callable:
|
||||
"""Optional decorator that wraps the task function in extra utilities.
|
||||
|
||||
Makes multirun more resistant to failure.
|
||||
|
||||
Utilities:
|
||||
- Calling the `utils.extras()` before the task is started
|
||||
- Calling the `utils.close_loggers()` after the task is finished
|
||||
- Logging the exception if occurs
|
||||
- Logging the task total execution time
|
||||
- Logging the output dir
|
||||
"""
|
||||
|
||||
def wrap(cfg: DictConfig):
|
||||
|
||||
# apply extra utilities
|
||||
extras(cfg)
|
||||
|
||||
# execute the task
|
||||
try:
|
||||
start_time = time.time()
|
||||
ret = task_func(cfg=cfg)
|
||||
except Exception as ex:
|
||||
log.exception("") # save exception to `.log` file
|
||||
raise ex
|
||||
finally:
|
||||
path = Path(cfg.paths.output_dir, "exec_time.log")
|
||||
content = f"'{cfg.task_name}' execution time: {time.time() - start_time} (s)"
|
||||
save_file(path, content) # save task execution time (even if exception occurs)
|
||||
close_loggers() # close loggers (even if exception occurs so multirun won't fail)
|
||||
|
||||
log.info(f"Output dir: {cfg.paths.output_dir}")
|
||||
|
||||
return ret
|
||||
|
||||
return wrap
|
||||
|
||||
|
||||
def extras(cfg: DictConfig) -> None:
|
||||
"""Applies optional utilities before the task is started.
|
||||
|
||||
Utilities:
|
||||
- Ignoring python warnings
|
||||
- Setting tags from command line
|
||||
- Rich config printing
|
||||
"""
|
||||
|
||||
# return if no `extras` config
|
||||
if not cfg.get("extras"):
|
||||
log.warning("Extras config not found! <cfg.extras=null>")
|
||||
return
|
||||
|
||||
# disable python warnings
|
||||
if cfg.extras.get("ignore_warnings"):
|
||||
log.info("Disabling python warnings! <cfg.extras.ignore_warnings=True>")
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
# prompt user to input tags from command line if none are provided in the config
|
||||
if cfg.extras.get("enforce_tags"):
|
||||
log.info("Enforcing tags! <cfg.extras.enforce_tags=True>")
|
||||
rich_utils.enforce_tags(cfg, save_to_file=True)
|
||||
|
||||
# pretty print config tree using Rich library
|
||||
if cfg.extras.get("print_config"):
|
||||
log.info("Printing config tree with Rich! <cfg.extras.print_config=True>")
|
||||
rich_utils.print_config_tree(cfg, resolve=True, save_to_file=True)
|
||||
|
||||
|
||||
@rank_zero_only
|
||||
def save_file(path: str, content: str) -> None:
|
||||
"""Save file in rank zero mode (only on one process in multi-GPU setup)."""
|
||||
with open(path, "w+") as file:
|
||||
file.write(content)
|
||||
|
||||
|
||||
def instantiate_callbacks(callbacks_cfg: DictConfig) -> List[Callback]:
|
||||
"""Instantiates callbacks from config."""
|
||||
callbacks: List[Callback] = []
|
||||
|
||||
if not callbacks_cfg:
|
||||
log.warning("Callbacks config is empty.")
|
||||
return callbacks
|
||||
|
||||
if not isinstance(callbacks_cfg, DictConfig):
|
||||
raise TypeError("Callbacks config must be a DictConfig!")
|
||||
|
||||
for _, cb_conf in callbacks_cfg.items():
|
||||
if isinstance(cb_conf, DictConfig) and "_target_" in cb_conf:
|
||||
log.info(f"Instantiating callback <{cb_conf._target_}>")
|
||||
callbacks.append(hydra.utils.instantiate(cb_conf))
|
||||
|
||||
return callbacks
|
||||
|
||||
|
||||
def instantiate_loggers(logger_cfg: DictConfig) -> List[Logger]:
|
||||
"""Instantiates loggers from config."""
|
||||
logger: List[Logger] = []
|
||||
|
||||
if not logger_cfg:
|
||||
log.warning("Logger config is empty.")
|
||||
return logger
|
||||
|
||||
if not isinstance(logger_cfg, DictConfig):
|
||||
raise TypeError("Logger config must be a DictConfig!")
|
||||
|
||||
for _, lg_conf in logger_cfg.items():
|
||||
if isinstance(lg_conf, DictConfig) and "_target_" in lg_conf:
|
||||
log.info(f"Instantiating logger <{lg_conf._target_}>")
|
||||
logger.append(hydra.utils.instantiate(lg_conf))
|
||||
|
||||
return logger
|
||||
|
||||
|
||||
@rank_zero_only
|
||||
def log_hyperparameters(object_dict: dict) -> None:
|
||||
"""Controls which config parts are saved by lightning loggers.
|
||||
|
||||
Additionally saves:
|
||||
- Number of model parameters
|
||||
"""
|
||||
|
||||
hparams = {}
|
||||
|
||||
cfg = object_dict["cfg"]
|
||||
model = object_dict["model"]
|
||||
trainer = object_dict["trainer"]
|
||||
|
||||
if not trainer.logger:
|
||||
log.warning("Logger not found! Skipping hyperparameter logging...")
|
||||
return
|
||||
|
||||
# save number of model parameters
|
||||
hparams["model/params/total"] = sum(p.numel() for p in model.parameters())
|
||||
hparams["model/params/trainable"] = sum(
|
||||
p.numel() for p in model.parameters() if p.requires_grad
|
||||
)
|
||||
hparams["model/params/non_trainable"] = sum(
|
||||
p.numel() for p in model.parameters() if not p.requires_grad
|
||||
)
|
||||
|
||||
for k in cfg.keys():
|
||||
hparams[k] = cfg.get(k)
|
||||
|
||||
# Resolve all interpolations
|
||||
def _resolve(_cfg):
|
||||
if isinstance(_cfg, DictConfig):
|
||||
_cfg = OmegaConf.to_container(_cfg, resolve=True)
|
||||
return _cfg
|
||||
|
||||
hparams = {k: _resolve(v) for k, v in hparams.items()}
|
||||
|
||||
# send hparams to all loggers
|
||||
trainer.logger.log_hyperparams(hparams)
|
||||
|
||||
|
||||
def get_metric_value(metric_dict: dict, metric_name: str) -> float:
|
||||
"""Safely retrieves value of the metric logged in LightningModule."""
|
||||
|
||||
if not metric_name:
|
||||
log.info("Metric name is None! Skipping metric value retrieval...")
|
||||
return None
|
||||
|
||||
if metric_name not in metric_dict:
|
||||
raise Exception(
|
||||
f"Metric value not found! <metric_name={metric_name}>\n"
|
||||
"Make sure metric name logged in LightningModule is correct!\n"
|
||||
"Make sure `optimized_metric` name in `hparams_search` config is correct!"
|
||||
)
|
||||
|
||||
metric_value = metric_dict[metric_name].item()
|
||||
log.info(f"Retrieved metric value! <{metric_name}={metric_value}>")
|
||||
|
||||
return metric_value
|
||||
|
||||
|
||||
def close_loggers() -> None:
|
||||
"""Makes sure all loggers closed properly (prevents logging failure during multirun)."""
|
||||
|
||||
log.info("Closing loggers...")
|
||||
|
||||
if find_spec("wandb"): # if wandb is installed
|
||||
import wandb
|
||||
|
||||
if wandb.run:
|
||||
log.info("Closing wandb!")
|
||||
wandb.finish()
|
||||
+352
@@ -0,0 +1,352 @@
|
||||
"""
|
||||
Code adapted from: https://github.com/akanazawa/hmr/blob/master/src/benchmark/eval_util.py
|
||||
"""
|
||||
|
||||
import torch
|
||||
import numpy as np
|
||||
from typing import Optional, Dict, List, Tuple
|
||||
|
||||
def compute_similarity_transform(S1: torch.Tensor, S2: torch.Tensor) -> torch.Tensor:
|
||||
"""
|
||||
Computes a similarity transform (sR, t) in a batched way that takes
|
||||
a set of 3D points S1 (B, N, 3) closest to a set of 3D points S2 (B, N, 3),
|
||||
where R is a 3x3 rotation matrix, t 3x1 translation, s scale.
|
||||
i.e. solves the orthogonal Procrutes problem.
|
||||
Args:
|
||||
S1 (torch.Tensor): First set of points of shape (B, N, 3).
|
||||
S2 (torch.Tensor): Second set of points of shape (B, N, 3).
|
||||
Returns:
|
||||
(torch.Tensor): The first set of points after applying the similarity transformation.
|
||||
"""
|
||||
|
||||
batch_size = S1.shape[0]
|
||||
S1 = S1.permute(0, 2, 1)
|
||||
S2 = S2.permute(0, 2, 1)
|
||||
# 1. Remove mean.
|
||||
mu1 = S1.mean(dim=2, keepdim=True)
|
||||
mu2 = S2.mean(dim=2, keepdim=True)
|
||||
X1 = S1 - mu1
|
||||
X2 = S2 - mu2
|
||||
|
||||
# 2. Compute variance of X1 used for scale.
|
||||
var1 = (X1**2).sum(dim=(1,2))
|
||||
|
||||
# 3. The outer product of X1 and X2.
|
||||
K = torch.matmul(X1, X2.permute(0, 2, 1))
|
||||
|
||||
# 4. Solution that Maximizes trace(R'K) is R=U*V', where U, V are singular vectors of K.
|
||||
U, s, V = torch.svd(K)
|
||||
Vh = V.permute(0, 2, 1)
|
||||
|
||||
# Construct Z that fixes the orientation of R to get det(R)=1.
|
||||
Z = torch.eye(U.shape[1], device=U.device).unsqueeze(0).repeat(batch_size, 1, 1)
|
||||
Z[:, -1, -1] *= torch.sign(torch.linalg.det(torch.matmul(U, Vh)))
|
||||
|
||||
# Construct R.
|
||||
R = torch.matmul(torch.matmul(V, Z), U.permute(0, 2, 1))
|
||||
|
||||
# 5. Recover scale.
|
||||
trace = torch.matmul(R, K).diagonal(offset=0, dim1=-1, dim2=-2).sum(dim=-1)
|
||||
scale = (trace / var1).unsqueeze(dim=-1).unsqueeze(dim=-1)
|
||||
|
||||
# 6. Recover translation.
|
||||
t = mu2 - scale*torch.matmul(R, mu1)
|
||||
|
||||
# 7. Error:
|
||||
S1_hat = scale*torch.matmul(R, S1) + t
|
||||
|
||||
return S1_hat.permute(0, 2, 1)
|
||||
|
||||
def reconstruction_error(S1, S2) -> np.array:
|
||||
"""
|
||||
Computes the mean Euclidean distance of 2 set of points S1, S2 after performing Procrustes alignment.
|
||||
Args:
|
||||
S1 (torch.Tensor): First set of points of shape (B, N, 3).
|
||||
S2 (torch.Tensor): Second set of points of shape (B, N, 3).
|
||||
Returns:
|
||||
(np.array): Reconstruction error.
|
||||
"""
|
||||
S1_hat = compute_similarity_transform(S1, S2)
|
||||
re = torch.sqrt( ((S1_hat - S2)** 2).sum(dim=-1)).mean(dim=-1)
|
||||
return re
|
||||
|
||||
def eval_pose(pred_joints, gt_joints) -> Tuple[np.array, np.array]:
|
||||
"""
|
||||
Compute joint errors in mm before and after Procrustes alignment.
|
||||
Args:
|
||||
pred_joints (torch.Tensor): Predicted 3D joints of shape (B, N, 3).
|
||||
gt_joints (torch.Tensor): Ground truth 3D joints of shape (B, N, 3).
|
||||
Returns:
|
||||
Tuple[np.array, np.array]: Joint errors in mm before and after alignment.
|
||||
"""
|
||||
# Absolute error (MPJPE)
|
||||
mpjpe = torch.sqrt(((pred_joints - gt_joints) ** 2).sum(dim=-1)).mean(dim=-1).cpu().numpy()
|
||||
|
||||
# Reconstruction_error
|
||||
r_error = reconstruction_error(pred_joints, gt_joints).cpu().numpy()
|
||||
return 1000 * mpjpe, 1000 * r_error
|
||||
|
||||
class Evaluator:
|
||||
|
||||
def __init__(self,
|
||||
dataset_length: int,
|
||||
dataset: str,
|
||||
keypoint_list: List,
|
||||
pelvis_ind: int,
|
||||
metrics: List = ['mode_mpjpe', 'mode_re', 'min_mpjpe', 'min_re'],
|
||||
preds: List = ['vertices', 'keypoints_3d'],
|
||||
pck_thresholds: Optional[List] = None):
|
||||
"""
|
||||
Class used for evaluating trained models on different 3D pose datasets.
|
||||
Args:
|
||||
dataset_length (int): Total dataset length.
|
||||
keypoint_list [List]: List of keypoints used for evaluation.
|
||||
pelvis_ind (int): Index of pelvis keypoint; used for aligning the predictions and ground truth.
|
||||
metrics [List]: List of evaluation metrics to record.
|
||||
"""
|
||||
self.dataset_length = dataset_length
|
||||
self.dataset = dataset
|
||||
self.keypoint_list = keypoint_list
|
||||
self.pelvis_ind = pelvis_ind
|
||||
self.metrics = metrics
|
||||
self.preds = preds
|
||||
if self.metrics is not None:
|
||||
for metric in self.metrics:
|
||||
setattr(self, metric, np.zeros((dataset_length,)))
|
||||
if self.preds is not None:
|
||||
for pred in self.preds:
|
||||
if pred == 'vertices':
|
||||
self.vertices = np.zeros((dataset_length, 778, 3))
|
||||
if pred == 'keypoints_3d':
|
||||
self.keypoints_3d = np.zeros((dataset_length, 21, 3))
|
||||
self.counter = 0
|
||||
if pck_thresholds is None:
|
||||
self.pck_evaluator = None
|
||||
else:
|
||||
self.pck_evaluator = EvaluatorPCK(pck_thresholds)
|
||||
|
||||
def log(self):
|
||||
"""
|
||||
Print current evaluation metrics
|
||||
"""
|
||||
if self.counter == 0:
|
||||
print('Evaluation has not started')
|
||||
return
|
||||
print(f'{self.counter} / {self.dataset_length} samples')
|
||||
if self.pck_evaluator is not None:
|
||||
self.pck_evaluator.log()
|
||||
if self.metrics is not None:
|
||||
for metric in self.metrics:
|
||||
if metric in ['mode_mpjpe', 'mode_re', 'min_mpjpe', 'min_re']:
|
||||
unit = 'mm'
|
||||
else:
|
||||
unit = ''
|
||||
print(f'{metric}: {getattr(self, metric)[:self.counter].mean()} {unit}')
|
||||
print('***')
|
||||
|
||||
def get_metrics_dict(self) -> Dict:
|
||||
"""
|
||||
Returns:
|
||||
Dict: Dictionary of evaluation metrics.
|
||||
"""
|
||||
d1 = {metric: getattr(self, metric)[:self.counter].mean() for metric in self.metrics}
|
||||
if self.pck_evaluator is not None:
|
||||
d2 = self.pck_evaluator.get_metrics_dict()
|
||||
d1.update(d2)
|
||||
return d1
|
||||
|
||||
def get_preds_dict(self) -> Dict:
|
||||
"""
|
||||
Returns:
|
||||
Dict: Dictionary of evaluation preds.
|
||||
"""
|
||||
d1 = {pred: getattr(self, pred)[:self.counter] for pred in self.preds}
|
||||
return d1
|
||||
|
||||
def __call__(self, output: Dict, batch: Dict, opt_output: Optional[Dict] = None):
|
||||
"""
|
||||
Evaluate current batch.
|
||||
Args:
|
||||
output (Dict): Regression output.
|
||||
batch (Dict): Dictionary containing images and their corresponding annotations.
|
||||
opt_output (Dict): Optimization output.
|
||||
"""
|
||||
if self.pck_evaluator is not None:
|
||||
self.pck_evaluator(output, batch, opt_output)
|
||||
|
||||
pred_keypoints_3d = output['pred_keypoints_3d'].detach()
|
||||
pred_keypoints_3d = pred_keypoints_3d[:,None,:,:]
|
||||
batch_size = pred_keypoints_3d.shape[0]
|
||||
num_samples = pred_keypoints_3d.shape[1]
|
||||
gt_keypoints_3d = batch['keypoints_3d'][:, :, :-1].unsqueeze(1).repeat(1, num_samples, 1, 1)
|
||||
pred_vertices = output['pred_vertices'].detach()
|
||||
|
||||
# Align predictions and ground truth such that the pelvis location is at the origin
|
||||
pred_keypoints_3d -= pred_keypoints_3d[:, :, [self.pelvis_ind]]
|
||||
gt_keypoints_3d -= gt_keypoints_3d[:, :, [self.pelvis_ind]]
|
||||
|
||||
# Compute joint errors
|
||||
mpjpe, re = eval_pose(pred_keypoints_3d.reshape(batch_size * num_samples, -1, 3)[:, self.keypoint_list], gt_keypoints_3d.reshape(batch_size * num_samples, -1 ,3)[:, self.keypoint_list])
|
||||
mpjpe = mpjpe.reshape(batch_size, num_samples)
|
||||
re = re.reshape(batch_size, num_samples)
|
||||
|
||||
# Compute 2d keypoint errors
|
||||
bbox_expand_factor = batch['bbox_expand_factor'][:,None,None,None].detach()
|
||||
pred_keypoints_2d = output['pred_keypoints_2d'].detach()
|
||||
pred_keypoints_2d = pred_keypoints_2d[:,None,:,:]*bbox_expand_factor
|
||||
gt_keypoints_2d = batch['keypoints_2d'][:,None,:,:].repeat(1, num_samples, 1, 1)*bbox_expand_factor
|
||||
conf = gt_keypoints_2d[:, :, :, -1].clone()
|
||||
kp_err = torch.nn.functional.mse_loss(
|
||||
pred_keypoints_2d,
|
||||
gt_keypoints_2d[:, :, :, :-1],
|
||||
reduction='none'
|
||||
).sum(dim=3)
|
||||
kp_l2_loss = (conf * kp_err).mean(dim=2)
|
||||
kp_l2_loss = kp_l2_loss.detach().cpu().numpy()
|
||||
|
||||
# Compute joint errors after optimization, if available.
|
||||
if opt_output is not None:
|
||||
opt_keypoints_3d = opt_output['model_joints']
|
||||
opt_keypoints_3d -= opt_keypoints_3d[:, [self.pelvis_ind]]
|
||||
opt_mpjpe, opt_re = eval_pose(opt_keypoints_3d[:, self.keypoint_list], gt_keypoints_3d[:, 0, self.keypoint_list])
|
||||
|
||||
# The 0-th sample always corresponds to the mode
|
||||
if hasattr(self, 'mode_mpjpe'):
|
||||
mode_mpjpe = mpjpe[:, 0]
|
||||
self.mode_mpjpe[self.counter:self.counter+batch_size] = mode_mpjpe
|
||||
if hasattr(self, 'mode_re'):
|
||||
mode_re = re[:, 0]
|
||||
self.mode_re[self.counter:self.counter+batch_size] = mode_re
|
||||
if hasattr(self, 'mode_kpl2'):
|
||||
mode_kpl2 = kp_l2_loss[:, 0]
|
||||
self.mode_kpl2[self.counter:self.counter+batch_size] = mode_kpl2
|
||||
if hasattr(self, 'min_mpjpe'):
|
||||
min_mpjpe = mpjpe.min(axis=-1)
|
||||
self.min_mpjpe[self.counter:self.counter+batch_size] = min_mpjpe
|
||||
if hasattr(self, 'min_re'):
|
||||
min_re = re.min(axis=-1)
|
||||
self.min_re[self.counter:self.counter+batch_size] = min_re
|
||||
if hasattr(self, 'min_kpl2'):
|
||||
min_kpl2 = kp_l2_loss.min(axis=-1)
|
||||
self.min_kpl2[self.counter:self.counter+batch_size] = min_kpl2
|
||||
if hasattr(self, 'opt_mpjpe'):
|
||||
self.opt_mpjpe[self.counter:self.counter+batch_size] = opt_mpjpe
|
||||
if hasattr(self, 'opt_re'):
|
||||
self.opt_re[self.counter:self.counter+batch_size] = opt_re
|
||||
if hasattr(self, 'vertices'):
|
||||
self.vertices[self.counter:self.counter+batch_size] = pred_vertices.cpu().numpy()
|
||||
if hasattr(self, 'keypoints_3d'):
|
||||
if self.dataset == 'HO3D-VAL':
|
||||
pred_keypoints_3d = pred_keypoints_3d[:,:,[0,5,6,7,9,10,11,17,18,19,13,14,15,1,2,3,4,8,12,16,20]]
|
||||
self.keypoints_3d[self.counter:self.counter+batch_size] = pred_keypoints_3d.squeeze().cpu().numpy()
|
||||
|
||||
self.counter += batch_size
|
||||
|
||||
if hasattr(self, 'mode_mpjpe') and hasattr(self, 'mode_re'):
|
||||
return {
|
||||
'mode_mpjpe': mode_mpjpe,
|
||||
'mode_re': mode_re,
|
||||
}
|
||||
else:
|
||||
return {}
|
||||
|
||||
|
||||
class EvaluatorPCK:
|
||||
|
||||
def __init__(self, thresholds: List = [0.05, 0.1, 0.2, 0.3, 0.4, 0.5],):
|
||||
"""
|
||||
Class used for evaluating trained models on different 3D pose datasets.
|
||||
Args:
|
||||
thresholds [List]: List of PCK thresholds to evaluate.
|
||||
metrics [List]: List of evaluation metrics to record.
|
||||
"""
|
||||
self.thresholds = thresholds
|
||||
self.pred_kp_2d = []
|
||||
self.gt_kp_2d = []
|
||||
self.gt_conf_2d = []
|
||||
self.scale = []
|
||||
self.counter = 0
|
||||
|
||||
def log(self):
|
||||
"""
|
||||
Print current evaluation metrics
|
||||
"""
|
||||
if self.counter == 0:
|
||||
print('Evaluation has not started')
|
||||
return
|
||||
print(f'{self.counter} samples')
|
||||
metrics_dict = self.get_metrics_dict()
|
||||
for metric in metrics_dict:
|
||||
print(f'{metric}: {metrics_dict[metric]}')
|
||||
print('***')
|
||||
|
||||
def get_metrics_dict(self) -> Dict:
|
||||
"""
|
||||
Returns:
|
||||
Dict: Dictionary of evaluation metrics.
|
||||
"""
|
||||
pcks = self.compute_pcks()
|
||||
metrics = {}
|
||||
for thr, (acc,avg_acc,cnt) in zip(self.thresholds, pcks):
|
||||
metrics.update({f'kp{i}_pck_{thr}': float(a) for i, a in enumerate(acc) if a>=0})
|
||||
metrics.update({f'kpAvg_pck_{thr}': float(avg_acc)})
|
||||
return metrics
|
||||
|
||||
def compute_pcks(self):
|
||||
pred_kp_2d = np.concatenate(self.pred_kp_2d, axis=0)
|
||||
gt_kp_2d = np.concatenate(self.gt_kp_2d, axis=0)
|
||||
gt_conf_2d = np.concatenate(self.gt_conf_2d, axis=0)
|
||||
scale = np.concatenate(self.scale, axis=0)
|
||||
assert pred_kp_2d.shape == gt_kp_2d.shape
|
||||
assert pred_kp_2d[..., 0].shape == gt_conf_2d.shape
|
||||
assert pred_kp_2d.shape[1] == 1 # num_samples
|
||||
assert scale.shape[0] == gt_conf_2d.shape[0] # num_samples
|
||||
|
||||
pcks = [
|
||||
self.keypoint_pck_accuracy(
|
||||
pred_kp_2d[:, 0, :, :],
|
||||
gt_kp_2d[:, 0, :, :],
|
||||
gt_conf_2d[:, 0, :]>0.5,
|
||||
thr=thr,
|
||||
scale = scale[:,None]
|
||||
)
|
||||
for thr in self.thresholds
|
||||
]
|
||||
return pcks
|
||||
|
||||
def keypoint_pck_accuracy(self, pred, gt, conf, thr, scale):
|
||||
dist = np.sqrt(np.sum((pred-gt)**2, axis=2))
|
||||
all_joints = conf>0.5
|
||||
correct_joints = np.logical_and(dist<=scale*thr, all_joints)
|
||||
pck = correct_joints.sum(axis=0)/all_joints.sum(axis=0)
|
||||
return pck, pck.mean(), pck.shape[0]
|
||||
|
||||
def __call__(self, output: Dict, batch: Dict, opt_output: Optional[Dict] = None):
|
||||
"""
|
||||
Evaluate current batch.
|
||||
Args:
|
||||
output (Dict): Regression output.
|
||||
batch (Dict): Dictionary containing images and their corresponding annotations.
|
||||
opt_output (Dict): Optimization output.
|
||||
"""
|
||||
pred_keypoints_2d = output['pred_keypoints_2d'].detach()
|
||||
num_samples = 1
|
||||
batch_size = pred_keypoints_2d.shape[0]
|
||||
|
||||
right = batch['right'].detach()
|
||||
pred_keypoints_2d[:,:,0] = (2*right[:,None]-1)*pred_keypoints_2d[:,:,0]
|
||||
box_size = batch['box_size'].detach()
|
||||
box_center = batch['box_center'].detach()
|
||||
bbox_expand_factor = batch['bbox_expand_factor'].detach()
|
||||
scale = box_size/bbox_expand_factor
|
||||
bbox_expand_factor = bbox_expand_factor[:,None,None,None]
|
||||
pred_keypoints_2d = pred_keypoints_2d*box_size[:,None,None]+box_center[:,None]
|
||||
pred_keypoints_2d = pred_keypoints_2d[:,None,:,:]
|
||||
gt_keypoints_2d = batch['orig_keypoints_2d'][:,None,:,:].repeat(1, num_samples, 1, 1)
|
||||
|
||||
self.pred_kp_2d.append(pred_keypoints_2d[:, :, :, :2].detach().cpu().numpy())
|
||||
self.gt_conf_2d.append(gt_keypoints_2d[:, :, :, -1].detach().cpu().numpy())
|
||||
self.gt_kp_2d.append(gt_keypoints_2d[:, :, :, :2].detach().cpu().numpy())
|
||||
self.scale.append(scale.detach().cpu().numpy())
|
||||
|
||||
self.counter += batch_size
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import logging
|
||||
|
||||
from pytorch_lightning.utilities import rank_zero_only
|
||||
|
||||
|
||||
def get_pylogger(name=__name__) -> logging.Logger:
|
||||
"""Initializes multi-GPU-friendly python command line logger."""
|
||||
|
||||
logger = logging.getLogger(name)
|
||||
|
||||
# this ensures all logging levels get marked with the rank zero decorator
|
||||
# otherwise logs would get multiplied for each GPU process in multi-GPU setup
|
||||
logging_levels = ("debug", "info", "warning", "error", "exception", "fatal", "critical")
|
||||
for level in logging_levels:
|
||||
setattr(logger, level, rank_zero_only(getattr(logger, level)))
|
||||
|
||||
return logger
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
"""
|
||||
Render OpenPose keypoints.
|
||||
Code was ported to Python from the official C++ implementation https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/src/openpose/utilities/keypoint.cpp
|
||||
"""
|
||||
import cv2
|
||||
import math
|
||||
import numpy as np
|
||||
from typing import List, Tuple
|
||||
|
||||
def get_keypoints_rectangle(keypoints: np.array, threshold: float) -> Tuple[float, float, float]:
|
||||
"""
|
||||
Compute rectangle enclosing keypoints above the threshold.
|
||||
Args:
|
||||
keypoints (np.array): Keypoint array of shape (N, 3).
|
||||
threshold (float): Confidence visualization threshold.
|
||||
Returns:
|
||||
Tuple[float, float, float]: Rectangle width, height and area.
|
||||
"""
|
||||
valid_ind = keypoints[:, -1] > threshold
|
||||
if valid_ind.sum() > 0:
|
||||
valid_keypoints = keypoints[valid_ind][:, :-1]
|
||||
max_x = valid_keypoints[:,0].max()
|
||||
max_y = valid_keypoints[:,1].max()
|
||||
min_x = valid_keypoints[:,0].min()
|
||||
min_y = valid_keypoints[:,1].min()
|
||||
width = max_x - min_x
|
||||
height = max_y - min_y
|
||||
area = width * height
|
||||
return width, height, area
|
||||
else:
|
||||
return 0,0,0
|
||||
|
||||
def render_keypoints(img: np.array,
|
||||
keypoints: np.array,
|
||||
pairs: List,
|
||||
colors: List,
|
||||
thickness_circle_ratio: float,
|
||||
thickness_line_ratio_wrt_circle: float,
|
||||
pose_scales: List,
|
||||
threshold: float = 0.1,
|
||||
alpha: float = 1.0) -> np.array:
|
||||
"""
|
||||
Render keypoints on input image.
|
||||
Args:
|
||||
img (np.array): Input image of shape (H, W, 3) with pixel values in the [0,255] range.
|
||||
keypoints (np.array): Keypoint array of shape (N, 3).
|
||||
pairs (List): List of keypoint pairs per limb.
|
||||
colors: (List): List of colors per keypoint.
|
||||
thickness_circle_ratio (float): Circle thickness ratio.
|
||||
thickness_line_ratio_wrt_circle (float): Line thickness ratio wrt the circle.
|
||||
pose_scales (List): List of pose scales.
|
||||
threshold (float): Only visualize keypoints with confidence above the threshold.
|
||||
Returns:
|
||||
(np.array): Image of shape (H, W, 3) with keypoints drawn on top of the original image.
|
||||
"""
|
||||
img_orig = img.copy()
|
||||
width, height = img.shape[1], img.shape[2]
|
||||
area = width * height
|
||||
|
||||
lineType = 8
|
||||
shift = 0
|
||||
numberColors = len(colors)
|
||||
thresholdRectangle = 0.1
|
||||
|
||||
person_width, person_height, person_area = get_keypoints_rectangle(keypoints, thresholdRectangle)
|
||||
if person_area > 0:
|
||||
ratioAreas = min(1, max(person_width / width, person_height / height))
|
||||
thicknessRatio = np.maximum(np.round(math.sqrt(area) * thickness_circle_ratio * ratioAreas), 2)
|
||||
thicknessCircle = np.maximum(1, thicknessRatio if ratioAreas > 0.05 else -np.ones_like(thicknessRatio))
|
||||
thicknessLine = np.maximum(1, np.round(thicknessRatio * thickness_line_ratio_wrt_circle))
|
||||
radius = thicknessRatio / 2
|
||||
|
||||
img = np.ascontiguousarray(img.copy())
|
||||
for i, pair in enumerate(pairs):
|
||||
index1, index2 = pair
|
||||
if keypoints[index1, -1] > threshold and keypoints[index2, -1] > threshold:
|
||||
thicknessLineScaled = int(round(min(thicknessLine[index1], thicknessLine[index2]) * pose_scales[0]))
|
||||
colorIndex = index2
|
||||
color = colors[colorIndex % numberColors]
|
||||
keypoint1 = keypoints[index1, :-1].astype(np.int32)
|
||||
keypoint2 = keypoints[index2, :-1].astype(np.int32)
|
||||
cv2.line(img, tuple(keypoint1.tolist()), tuple(keypoint2.tolist()), tuple(color.tolist()), thicknessLineScaled, lineType, shift)
|
||||
for part in range(len(keypoints)):
|
||||
faceIndex = part
|
||||
if keypoints[faceIndex, -1] > threshold:
|
||||
radiusScaled = int(round(radius[faceIndex] * pose_scales[0]))
|
||||
thicknessCircleScaled = int(round(thicknessCircle[faceIndex] * pose_scales[0]))
|
||||
colorIndex = part
|
||||
color = colors[colorIndex % numberColors]
|
||||
center = keypoints[faceIndex, :-1].astype(np.int32)
|
||||
cv2.circle(img, tuple(center.tolist()), radiusScaled, tuple(color.tolist()), thicknessCircleScaled, lineType, shift)
|
||||
return img
|
||||
|
||||
def render_hand_keypoints(img, right_hand_keypoints, threshold=0.1, use_confidence=False, map_fn=lambda x: np.ones_like(x), alpha=1.0):
|
||||
if use_confidence and map_fn is not None:
|
||||
#thicknessCircleRatioLeft = 1./50 * map_fn(left_hand_keypoints[:, -1])
|
||||
thicknessCircleRatioRight = 1./50 * map_fn(right_hand_keypoints[:, -1])
|
||||
else:
|
||||
#thicknessCircleRatioLeft = 1./50 * np.ones(left_hand_keypoints.shape[0])
|
||||
thicknessCircleRatioRight = 1./50 * np.ones(right_hand_keypoints.shape[0])
|
||||
thicknessLineRatioWRTCircle = 0.75
|
||||
pairs = [0,1, 1,2, 2,3, 3,4, 0,5, 5,6, 6,7, 7,8, 0,9, 9,10, 10,11, 11,12, 0,13, 13,14, 14,15, 15,16, 0,17, 17,18, 18,19, 19,20]
|
||||
pairs = np.array(pairs).reshape(-1,2)
|
||||
|
||||
colors = [100., 100., 100.,
|
||||
100., 0., 0.,
|
||||
150., 0., 0.,
|
||||
200., 0., 0.,
|
||||
255., 0., 0.,
|
||||
100., 100., 0.,
|
||||
150., 150., 0.,
|
||||
200., 200., 0.,
|
||||
255., 255., 0.,
|
||||
0., 100., 50.,
|
||||
0., 150., 75.,
|
||||
0., 200., 100.,
|
||||
0., 255., 125.,
|
||||
0., 50., 100.,
|
||||
0., 75., 150.,
|
||||
0., 100., 200.,
|
||||
0., 125., 255.,
|
||||
100., 0., 100.,
|
||||
150., 0., 150.,
|
||||
200., 0., 200.,
|
||||
255., 0., 255.]
|
||||
colors = np.array(colors).reshape(-1,3)
|
||||
#colors = np.zeros_like(colors)
|
||||
poseScales = [1]
|
||||
#img = render_keypoints(img, left_hand_keypoints, pairs, colors, thicknessCircleRatioLeft, thicknessLineRatioWRTCircle, poseScales, threshold, alpha=alpha)
|
||||
img = render_keypoints(img, right_hand_keypoints, pairs, colors, thicknessCircleRatioRight, thicknessLineRatioWRTCircle, poseScales, threshold, alpha=alpha)
|
||||
#img = render_keypoints(img, right_hand_keypoints, pairs, colors, thickness_circle_ratio, thickness_line_ratio_wrt_circle, pose_scales, 0.1)
|
||||
return img
|
||||
|
||||
def render_body_keypoints(img: np.array,
|
||||
body_keypoints: np.array) -> np.array:
|
||||
"""
|
||||
Render OpenPose body keypoints on input image.
|
||||
Args:
|
||||
img (np.array): Input image of shape (H, W, 3) with pixel values in the [0,255] range.
|
||||
body_keypoints (np.array): Keypoint array of shape (N, 3); 3 <====> (x, y, confidence).
|
||||
Returns:
|
||||
(np.array): Image of shape (H, W, 3) with keypoints drawn on top of the original image.
|
||||
"""
|
||||
|
||||
thickness_circle_ratio = 1./75. * np.ones(body_keypoints.shape[0])
|
||||
thickness_line_ratio_wrt_circle = 0.75
|
||||
pairs = []
|
||||
pairs = [1,8,1,2,1,5,2,3,3,4,5,6,6,7,8,9,9,10,10,11,8,12,12,13,13,14,1,0,0,15,15,17,0,16,16,18,14,19,19,20,14,21,11,22,22,23,11,24]
|
||||
pairs = np.array(pairs).reshape(-1,2)
|
||||
colors = [255., 0., 85.,
|
||||
255., 0., 0.,
|
||||
255., 85., 0.,
|
||||
255., 170., 0.,
|
||||
255., 255., 0.,
|
||||
170., 255., 0.,
|
||||
85., 255., 0.,
|
||||
0., 255., 0.,
|
||||
255., 0., 0.,
|
||||
0., 255., 85.,
|
||||
0., 255., 170.,
|
||||
0., 255., 255.,
|
||||
0., 170., 255.,
|
||||
0., 85., 255.,
|
||||
0., 0., 255.,
|
||||
255., 0., 170.,
|
||||
170., 0., 255.,
|
||||
255., 0., 255.,
|
||||
85., 0., 255.,
|
||||
0., 0., 255.,
|
||||
0., 0., 255.,
|
||||
0., 0., 255.,
|
||||
0., 255., 255.,
|
||||
0., 255., 255.,
|
||||
0., 255., 255.]
|
||||
colors = np.array(colors).reshape(-1,3)
|
||||
pose_scales = [1]
|
||||
return render_keypoints(img, body_keypoints, pairs, colors, thickness_circle_ratio, thickness_line_ratio_wrt_circle, pose_scales, 0.1)
|
||||
|
||||
def render_openpose(img: np.array,
|
||||
hand_keypoints: np.array) -> np.array:
|
||||
"""
|
||||
Render keypoints in the OpenPose format on input image.
|
||||
Args:
|
||||
img (np.array): Input image of shape (H, W, 3) with pixel values in the [0,255] range.
|
||||
body_keypoints (np.array): Keypoint array of shape (N, 3); 3 <====> (x, y, confidence).
|
||||
Returns:
|
||||
(np.array): Image of shape (H, W, 3) with keypoints drawn on top of the original image.
|
||||
"""
|
||||
#img = render_body_keypoints(img, body_keypoints)
|
||||
img = render_hand_keypoints(img, hand_keypoints)
|
||||
return img
|
||||
+423
@@ -0,0 +1,423 @@
|
||||
import os
|
||||
if 'PYOPENGL_PLATFORM' not in os.environ:
|
||||
os.environ['PYOPENGL_PLATFORM'] = 'egl'
|
||||
import torch
|
||||
import numpy as np
|
||||
import pyrender
|
||||
import trimesh
|
||||
import cv2
|
||||
from yacs.config import CfgNode
|
||||
from typing import List, Optional
|
||||
|
||||
def cam_crop_to_full(cam_bbox, box_center, box_size, img_size, focal_length=5000.):
|
||||
# Convert cam_bbox to full image
|
||||
img_w, img_h = img_size[:, 0], img_size[:, 1]
|
||||
cx, cy, b = box_center[:, 0], box_center[:, 1], box_size
|
||||
w_2, h_2 = img_w / 2., img_h / 2.
|
||||
bs = b * cam_bbox[:, 0] + 1e-9
|
||||
tz = 2 * focal_length / bs
|
||||
tx = (2 * (cx - w_2) / bs) + cam_bbox[:, 1]
|
||||
ty = (2 * (cy - h_2) / bs) + cam_bbox[:, 2]
|
||||
full_cam = torch.stack([tx, ty, tz], dim=-1)
|
||||
return full_cam
|
||||
|
||||
def get_light_poses(n_lights=5, elevation=np.pi / 3, dist=12):
|
||||
# get lights in a circle around origin at elevation
|
||||
thetas = elevation * np.ones(n_lights)
|
||||
phis = 2 * np.pi * np.arange(n_lights) / n_lights
|
||||
poses = []
|
||||
trans = make_translation(torch.tensor([0, 0, dist]))
|
||||
for phi, theta in zip(phis, thetas):
|
||||
rot = make_rotation(rx=-theta, ry=phi, order="xyz")
|
||||
poses.append((rot @ trans).numpy())
|
||||
return poses
|
||||
|
||||
def make_translation(t):
|
||||
return make_4x4_pose(torch.eye(3), t)
|
||||
|
||||
def make_rotation(rx=0, ry=0, rz=0, order="xyz"):
|
||||
Rx = rotx(rx)
|
||||
Ry = roty(ry)
|
||||
Rz = rotz(rz)
|
||||
if order == "xyz":
|
||||
R = Rz @ Ry @ Rx
|
||||
elif order == "xzy":
|
||||
R = Ry @ Rz @ Rx
|
||||
elif order == "yxz":
|
||||
R = Rz @ Rx @ Ry
|
||||
elif order == "yzx":
|
||||
R = Rx @ Rz @ Ry
|
||||
elif order == "zyx":
|
||||
R = Rx @ Ry @ Rz
|
||||
elif order == "zxy":
|
||||
R = Ry @ Rx @ Rz
|
||||
return make_4x4_pose(R, torch.zeros(3))
|
||||
|
||||
def make_4x4_pose(R, t):
|
||||
"""
|
||||
:param R (*, 3, 3)
|
||||
:param t (*, 3)
|
||||
return (*, 4, 4)
|
||||
"""
|
||||
dims = R.shape[:-2]
|
||||
pose_3x4 = torch.cat([R, t.view(*dims, 3, 1)], dim=-1)
|
||||
bottom = (
|
||||
torch.tensor([0, 0, 0, 1], device=R.device)
|
||||
.reshape(*(1,) * len(dims), 1, 4)
|
||||
.expand(*dims, 1, 4)
|
||||
)
|
||||
return torch.cat([pose_3x4, bottom], dim=-2)
|
||||
|
||||
|
||||
def rotx(theta):
|
||||
return torch.tensor(
|
||||
[
|
||||
[1, 0, 0],
|
||||
[0, np.cos(theta), -np.sin(theta)],
|
||||
[0, np.sin(theta), np.cos(theta)],
|
||||
],
|
||||
dtype=torch.float32,
|
||||
)
|
||||
|
||||
|
||||
def roty(theta):
|
||||
return torch.tensor(
|
||||
[
|
||||
[np.cos(theta), 0, np.sin(theta)],
|
||||
[0, 1, 0],
|
||||
[-np.sin(theta), 0, np.cos(theta)],
|
||||
],
|
||||
dtype=torch.float32,
|
||||
)
|
||||
|
||||
|
||||
def rotz(theta):
|
||||
return torch.tensor(
|
||||
[
|
||||
[np.cos(theta), -np.sin(theta), 0],
|
||||
[np.sin(theta), np.cos(theta), 0],
|
||||
[0, 0, 1],
|
||||
],
|
||||
dtype=torch.float32,
|
||||
)
|
||||
|
||||
|
||||
def create_raymond_lights() -> List[pyrender.Node]:
|
||||
"""
|
||||
Return raymond light nodes for the scene.
|
||||
"""
|
||||
thetas = np.pi * np.array([1.0 / 6.0, 1.0 / 6.0, 1.0 / 6.0])
|
||||
phis = np.pi * np.array([0.0, 2.0 / 3.0, 4.0 / 3.0])
|
||||
|
||||
nodes = []
|
||||
|
||||
for phi, theta in zip(phis, thetas):
|
||||
xp = np.sin(theta) * np.cos(phi)
|
||||
yp = np.sin(theta) * np.sin(phi)
|
||||
zp = np.cos(theta)
|
||||
|
||||
z = np.array([xp, yp, zp])
|
||||
z = z / np.linalg.norm(z)
|
||||
x = np.array([-z[1], z[0], 0.0])
|
||||
if np.linalg.norm(x) == 0:
|
||||
x = np.array([1.0, 0.0, 0.0])
|
||||
x = x / np.linalg.norm(x)
|
||||
y = np.cross(z, x)
|
||||
|
||||
matrix = np.eye(4)
|
||||
matrix[:3,:3] = np.c_[x,y,z]
|
||||
nodes.append(pyrender.Node(
|
||||
light=pyrender.DirectionalLight(color=np.ones(3), intensity=1.0),
|
||||
matrix=matrix
|
||||
))
|
||||
|
||||
return nodes
|
||||
|
||||
class Renderer:
|
||||
|
||||
def __init__(self, cfg: CfgNode, faces: np.array):
|
||||
"""
|
||||
Wrapper around the pyrender renderer to render MANO meshes.
|
||||
Args:
|
||||
cfg (CfgNode): Model config file.
|
||||
faces (np.array): Array of shape (F, 3) containing the mesh faces.
|
||||
"""
|
||||
self.cfg = cfg
|
||||
self.focal_length = cfg.EXTRA.FOCAL_LENGTH
|
||||
self.img_res = cfg.MODEL.IMAGE_SIZE
|
||||
|
||||
# add faces that make the hand mesh watertight
|
||||
faces_new = np.array([[92, 38, 234],
|
||||
[234, 38, 239],
|
||||
[38, 122, 239],
|
||||
[239, 122, 279],
|
||||
[122, 118, 279],
|
||||
[279, 118, 215],
|
||||
[118, 117, 215],
|
||||
[215, 117, 214],
|
||||
[117, 119, 214],
|
||||
[214, 119, 121],
|
||||
[119, 120, 121],
|
||||
[121, 120, 78],
|
||||
[120, 108, 78],
|
||||
[78, 108, 79]])
|
||||
faces = np.concatenate([faces, faces_new], axis=0)
|
||||
|
||||
self.camera_center = [self.img_res // 2, self.img_res // 2]
|
||||
self.faces = faces
|
||||
self.faces_left = self.faces[:,[0,2,1]]
|
||||
|
||||
def __call__(self,
|
||||
vertices: np.array,
|
||||
camera_translation: np.array,
|
||||
image: torch.Tensor,
|
||||
full_frame: bool = False,
|
||||
imgname: Optional[str] = None,
|
||||
side_view=False, rot_angle=90,
|
||||
mesh_base_color=(1.0, 1.0, 0.9),
|
||||
scene_bg_color=(0,0,0),
|
||||
return_rgba=False,
|
||||
) -> np.array:
|
||||
"""
|
||||
Render meshes on input image
|
||||
Args:
|
||||
vertices (np.array): Array of shape (V, 3) containing the mesh vertices.
|
||||
camera_translation (np.array): Array of shape (3,) with the camera translation.
|
||||
image (torch.Tensor): Tensor of shape (3, H, W) containing the image crop with normalized pixel values.
|
||||
full_frame (bool): If True, then render on the full image.
|
||||
imgname (Optional[str]): Contains the original image filenamee. Used only if full_frame == True.
|
||||
"""
|
||||
|
||||
if full_frame:
|
||||
image = cv2.imread(imgname).astype(np.float32)[:, :, ::-1] / 255.
|
||||
else:
|
||||
image = image.clone() * torch.tensor(self.cfg.MODEL.IMAGE_STD, device=image.device).reshape(3,1,1)
|
||||
image = image + torch.tensor(self.cfg.MODEL.IMAGE_MEAN, device=image.device).reshape(3,1,1)
|
||||
image = image.permute(1, 2, 0).cpu().numpy()
|
||||
|
||||
renderer = pyrender.OffscreenRenderer(viewport_width=image.shape[1],
|
||||
viewport_height=image.shape[0],
|
||||
point_size=1.0)
|
||||
material = pyrender.MetallicRoughnessMaterial(
|
||||
metallicFactor=0.0,
|
||||
alphaMode='OPAQUE',
|
||||
baseColorFactor=(*mesh_base_color, 1.0))
|
||||
|
||||
camera_translation[0] *= -1.
|
||||
|
||||
mesh = trimesh.Trimesh(vertices.copy(), self.faces.copy())
|
||||
if side_view:
|
||||
rot = trimesh.transformations.rotation_matrix(
|
||||
np.radians(rot_angle), [0, 1, 0])
|
||||
mesh.apply_transform(rot)
|
||||
rot = trimesh.transformations.rotation_matrix(
|
||||
np.radians(180), [1, 0, 0])
|
||||
mesh.apply_transform(rot)
|
||||
mesh = pyrender.Mesh.from_trimesh(mesh, material=material)
|
||||
|
||||
scene = pyrender.Scene(bg_color=[*scene_bg_color, 0.0],
|
||||
ambient_light=(0.3, 0.3, 0.3))
|
||||
scene.add(mesh, 'mesh')
|
||||
|
||||
camera_pose = np.eye(4)
|
||||
camera_pose[:3, 3] = camera_translation
|
||||
camera_center = [image.shape[1] / 2., image.shape[0] / 2.]
|
||||
camera = pyrender.IntrinsicsCamera(fx=self.focal_length, fy=self.focal_length,
|
||||
cx=camera_center[0], cy=camera_center[1], zfar=1e12)
|
||||
scene.add(camera, pose=camera_pose)
|
||||
|
||||
|
||||
light_nodes = create_raymond_lights()
|
||||
for node in light_nodes:
|
||||
scene.add_node(node)
|
||||
|
||||
color, rend_depth = renderer.render(scene, flags=pyrender.RenderFlags.RGBA)
|
||||
color = color.astype(np.float32) / 255.0
|
||||
renderer.delete()
|
||||
|
||||
if return_rgba:
|
||||
return color
|
||||
|
||||
valid_mask = (color[:, :, -1])[:, :, np.newaxis]
|
||||
if not side_view:
|
||||
output_img = (color[:, :, :3] * valid_mask + (1 - valid_mask) * image)
|
||||
else:
|
||||
output_img = color[:, :, :3]
|
||||
|
||||
output_img = output_img.astype(np.float32)
|
||||
return output_img
|
||||
|
||||
def vertices_to_trimesh(self, vertices, camera_translation, mesh_base_color=(1.0, 1.0, 0.9),
|
||||
rot_axis=[1,0,0], rot_angle=0, is_right=1):
|
||||
# material = pyrender.MetallicRoughnessMaterial(
|
||||
# metallicFactor=0.0,
|
||||
# alphaMode='OPAQUE',
|
||||
# baseColorFactor=(*mesh_base_color, 1.0))
|
||||
vertex_colors = np.array([(*mesh_base_color, 1.0)] * vertices.shape[0])
|
||||
if is_right:
|
||||
mesh = trimesh.Trimesh(vertices.copy() + camera_translation, self.faces.copy(), vertex_colors=vertex_colors)
|
||||
else:
|
||||
mesh = trimesh.Trimesh(vertices.copy() + camera_translation, self.faces_left.copy(), vertex_colors=vertex_colors)
|
||||
# mesh = trimesh.Trimesh(vertices.copy(), self.faces.copy())
|
||||
|
||||
rot = trimesh.transformations.rotation_matrix(
|
||||
np.radians(rot_angle), rot_axis)
|
||||
mesh.apply_transform(rot)
|
||||
|
||||
rot = trimesh.transformations.rotation_matrix(
|
||||
np.radians(180), [1, 0, 0])
|
||||
mesh.apply_transform(rot)
|
||||
return mesh
|
||||
|
||||
def render_rgba(
|
||||
self,
|
||||
vertices: np.array,
|
||||
cam_t = None,
|
||||
rot=None,
|
||||
rot_axis=[1,0,0],
|
||||
rot_angle=0,
|
||||
camera_z=3,
|
||||
# camera_translation: np.array,
|
||||
mesh_base_color=(1.0, 1.0, 0.9),
|
||||
scene_bg_color=(0,0,0),
|
||||
render_res=[256, 256],
|
||||
focal_length=None,
|
||||
is_right=None,
|
||||
):
|
||||
|
||||
renderer = pyrender.OffscreenRenderer(viewport_width=render_res[0],
|
||||
viewport_height=render_res[1],
|
||||
point_size=1.0)
|
||||
# material = pyrender.MetallicRoughnessMaterial(
|
||||
# metallicFactor=0.0,
|
||||
# alphaMode='OPAQUE',
|
||||
# baseColorFactor=(*mesh_base_color, 1.0))
|
||||
|
||||
focal_length = focal_length if focal_length is not None else self.focal_length
|
||||
|
||||
if cam_t is not None:
|
||||
camera_translation = cam_t.copy()
|
||||
camera_translation[0] *= -1.
|
||||
else:
|
||||
camera_translation = np.array([0, 0, camera_z * focal_length/render_res[1]])
|
||||
|
||||
mesh = self.vertices_to_trimesh(vertices, np.array([0, 0, 0]), mesh_base_color, rot_axis, rot_angle, is_right=is_right)
|
||||
mesh = pyrender.Mesh.from_trimesh(mesh)
|
||||
# mesh = pyrender.Mesh.from_trimesh(mesh, material=material)
|
||||
|
||||
scene = pyrender.Scene(bg_color=[*scene_bg_color, 0.0],
|
||||
ambient_light=(0.3, 0.3, 0.3))
|
||||
scene.add(mesh, 'mesh')
|
||||
|
||||
camera_pose = np.eye(4)
|
||||
camera_pose[:3, 3] = camera_translation
|
||||
camera_center = [render_res[0] / 2., render_res[1] / 2.]
|
||||
camera = pyrender.IntrinsicsCamera(fx=focal_length, fy=focal_length,
|
||||
cx=camera_center[0], cy=camera_center[1], zfar=1e12)
|
||||
|
||||
# Create camera node and add it to pyRender scene
|
||||
camera_node = pyrender.Node(camera=camera, matrix=camera_pose)
|
||||
scene.add_node(camera_node)
|
||||
self.add_point_lighting(scene, camera_node)
|
||||
self.add_lighting(scene, camera_node)
|
||||
|
||||
light_nodes = create_raymond_lights()
|
||||
for node in light_nodes:
|
||||
scene.add_node(node)
|
||||
|
||||
color, rend_depth = renderer.render(scene, flags=pyrender.RenderFlags.RGBA)
|
||||
color = color.astype(np.float32) / 255.0
|
||||
renderer.delete()
|
||||
|
||||
return color
|
||||
|
||||
def render_rgba_multiple(
|
||||
self,
|
||||
vertices: List[np.array],
|
||||
cam_t: List[np.array],
|
||||
rot_axis=[1,0,0],
|
||||
rot_angle=0,
|
||||
mesh_base_color=(1.0, 1.0, 0.9),
|
||||
scene_bg_color=(0,0,0),
|
||||
render_res=[256, 256],
|
||||
focal_length=None,
|
||||
is_right=None,
|
||||
):
|
||||
|
||||
renderer = pyrender.OffscreenRenderer(viewport_width=render_res[0],
|
||||
viewport_height=render_res[1],
|
||||
point_size=1.0)
|
||||
# material = pyrender.MetallicRoughnessMaterial(
|
||||
# metallicFactor=0.0,
|
||||
# alphaMode='OPAQUE',
|
||||
# baseColorFactor=(*mesh_base_color, 1.0))
|
||||
|
||||
if is_right is None:
|
||||
is_right = [1 for _ in range(len(vertices))]
|
||||
|
||||
mesh_list = [pyrender.Mesh.from_trimesh(self.vertices_to_trimesh(vvv, ttt.copy(), mesh_base_color, rot_axis, rot_angle, is_right=sss)) for vvv,ttt,sss in zip(vertices, cam_t, is_right)]
|
||||
|
||||
scene = pyrender.Scene(bg_color=[*scene_bg_color, 0.0],
|
||||
ambient_light=(0.3, 0.3, 0.3))
|
||||
for i,mesh in enumerate(mesh_list):
|
||||
scene.add(mesh, f'mesh_{i}')
|
||||
|
||||
camera_pose = np.eye(4)
|
||||
# camera_pose[:3, 3] = camera_translation
|
||||
camera_center = [render_res[0] / 2., render_res[1] / 2.]
|
||||
focal_length = focal_length if focal_length is not None else self.focal_length
|
||||
camera = pyrender.IntrinsicsCamera(fx=focal_length, fy=focal_length,
|
||||
cx=camera_center[0], cy=camera_center[1], zfar=1e12)
|
||||
|
||||
# Create camera node and add it to pyRender scene
|
||||
camera_node = pyrender.Node(camera=camera, matrix=camera_pose)
|
||||
scene.add_node(camera_node)
|
||||
self.add_point_lighting(scene, camera_node)
|
||||
self.add_lighting(scene, camera_node)
|
||||
|
||||
light_nodes = create_raymond_lights()
|
||||
for node in light_nodes:
|
||||
scene.add_node(node)
|
||||
|
||||
color, rend_depth = renderer.render(scene, flags=pyrender.RenderFlags.RGBA)
|
||||
color = color.astype(np.float32) / 255.0
|
||||
renderer.delete()
|
||||
|
||||
return color
|
||||
|
||||
def add_lighting(self, scene, cam_node, color=np.ones(3), intensity=1.0):
|
||||
# from phalp.visualize.py_renderer import get_light_poses
|
||||
light_poses = get_light_poses()
|
||||
light_poses.append(np.eye(4))
|
||||
cam_pose = scene.get_pose(cam_node)
|
||||
for i, pose in enumerate(light_poses):
|
||||
matrix = cam_pose @ pose
|
||||
node = pyrender.Node(
|
||||
name=f"light-{i:02d}",
|
||||
light=pyrender.DirectionalLight(color=color, intensity=intensity),
|
||||
matrix=matrix,
|
||||
)
|
||||
if scene.has_node(node):
|
||||
continue
|
||||
scene.add_node(node)
|
||||
|
||||
def add_point_lighting(self, scene, cam_node, color=np.ones(3), intensity=1.0):
|
||||
# from phalp.visualize.py_renderer import get_light_poses
|
||||
light_poses = get_light_poses(dist=0.5)
|
||||
light_poses.append(np.eye(4))
|
||||
cam_pose = scene.get_pose(cam_node)
|
||||
for i, pose in enumerate(light_poses):
|
||||
matrix = cam_pose @ pose
|
||||
# node = pyrender.Node(
|
||||
# name=f"light-{i:02d}",
|
||||
# light=pyrender.DirectionalLight(color=color, intensity=intensity),
|
||||
# matrix=matrix,
|
||||
# )
|
||||
node = pyrender.Node(
|
||||
name=f"plight-{i:02d}",
|
||||
light=pyrender.PointLight(color=color, intensity=intensity),
|
||||
matrix=matrix,
|
||||
)
|
||||
if scene.has_node(node):
|
||||
continue
|
||||
scene.add_node(node)
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
from pathlib import Path
|
||||
from typing import Sequence
|
||||
|
||||
import rich
|
||||
import rich.syntax
|
||||
import rich.tree
|
||||
from hydra.core.hydra_config import HydraConfig
|
||||
from omegaconf import DictConfig, OmegaConf, open_dict
|
||||
from pytorch_lightning.utilities import rank_zero_only
|
||||
from rich.prompt import Prompt
|
||||
|
||||
from . import pylogger
|
||||
|
||||
log = pylogger.get_pylogger(__name__)
|
||||
|
||||
|
||||
@rank_zero_only
|
||||
def print_config_tree(
|
||||
cfg: DictConfig,
|
||||
print_order: Sequence[str] = (
|
||||
"datamodule",
|
||||
"model",
|
||||
"callbacks",
|
||||
"logger",
|
||||
"trainer",
|
||||
"paths",
|
||||
"extras",
|
||||
),
|
||||
resolve: bool = False,
|
||||
save_to_file: bool = False,
|
||||
) -> None:
|
||||
"""Prints content of DictConfig using Rich library and its tree structure.
|
||||
|
||||
Args:
|
||||
cfg (DictConfig): Configuration composed by Hydra.
|
||||
print_order (Sequence[str], optional): Determines in what order config components are printed.
|
||||
resolve (bool, optional): Whether to resolve reference fields of DictConfig.
|
||||
save_to_file (bool, optional): Whether to export config to the hydra output folder.
|
||||
"""
|
||||
|
||||
style = "dim"
|
||||
tree = rich.tree.Tree("CONFIG", style=style, guide_style=style)
|
||||
|
||||
queue = []
|
||||
|
||||
# add fields from `print_order` to queue
|
||||
for field in print_order:
|
||||
queue.append(field) if field in cfg else log.warning(
|
||||
f"Field '{field}' not found in config. Skipping '{field}' config printing..."
|
||||
)
|
||||
|
||||
# add all the other fields to queue (not specified in `print_order`)
|
||||
for field in cfg:
|
||||
if field not in queue:
|
||||
queue.append(field)
|
||||
|
||||
# generate config tree from queue
|
||||
for field in queue:
|
||||
branch = tree.add(field, style=style, guide_style=style)
|
||||
|
||||
config_group = cfg[field]
|
||||
if isinstance(config_group, DictConfig):
|
||||
branch_content = OmegaConf.to_yaml(config_group, resolve=resolve)
|
||||
else:
|
||||
branch_content = str(config_group)
|
||||
|
||||
branch.add(rich.syntax.Syntax(branch_content, "yaml"))
|
||||
|
||||
# print config tree
|
||||
rich.print(tree)
|
||||
|
||||
# save config tree to file
|
||||
if save_to_file:
|
||||
with open(Path(cfg.paths.output_dir, "config_tree.log"), "w") as file:
|
||||
rich.print(tree, file=file)
|
||||
|
||||
|
||||
@rank_zero_only
|
||||
def enforce_tags(cfg: DictConfig, save_to_file: bool = False) -> None:
|
||||
"""Prompts user to input tags from command line if no tags are provided in config."""
|
||||
|
||||
if not cfg.get("tags"):
|
||||
if "id" in HydraConfig().cfg.hydra.job:
|
||||
raise ValueError("Specify tags before launching a multirun!")
|
||||
|
||||
log.warning("No tags provided in config. Prompting user to input tags...")
|
||||
tags = Prompt.ask("Enter a list of comma separated tags", default="dev")
|
||||
tags = [t.strip() for t in tags.split(",") if t != ""]
|
||||
|
||||
with open_dict(cfg):
|
||||
cfg.tags = tags
|
||||
|
||||
log.info(f"Tags: {cfg.tags}")
|
||||
|
||||
if save_to_file:
|
||||
with open(Path(cfg.paths.output_dir, "tags.log"), "w") as file:
|
||||
rich.print(cfg.tags, file=file)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from hydra import compose, initialize
|
||||
|
||||
with initialize(version_base="1.2", config_path="../../configs"):
|
||||
cfg = compose(config_name="train.yaml", return_hydra_config=False, overrides=[])
|
||||
print_config_tree(cfg, resolve=False, save_to_file=False)
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
import torch
|
||||
import numpy as np
|
||||
import trimesh
|
||||
from typing import Optional
|
||||
from yacs.config import CfgNode
|
||||
|
||||
from .geometry import perspective_projection
|
||||
from .render_openpose import render_openpose
|
||||
|
||||
class SkeletonRenderer:
|
||||
|
||||
def __init__(self, cfg: CfgNode):
|
||||
"""
|
||||
Object used to render 3D keypoints. Faster for use during training.
|
||||
Args:
|
||||
cfg (CfgNode): Model config file.
|
||||
"""
|
||||
self.cfg = cfg
|
||||
|
||||
def __call__(self,
|
||||
pred_keypoints_3d: torch.Tensor,
|
||||
gt_keypoints_3d: torch.Tensor,
|
||||
gt_keypoints_2d: torch.Tensor,
|
||||
images: Optional[np.array] = None,
|
||||
camera_translation: Optional[torch.Tensor] = None) -> np.array:
|
||||
"""
|
||||
Render batch of 3D keypoints.
|
||||
Args:
|
||||
pred_keypoints_3d (torch.Tensor): Tensor of shape (B, S, N, 3) containing a batch of predicted 3D keypoints, with S samples per image.
|
||||
gt_keypoints_3d (torch.Tensor): Tensor of shape (B, N, 4) containing corresponding ground truth 3D keypoints; last value is the confidence.
|
||||
gt_keypoints_2d (torch.Tensor): Tensor of shape (B, N, 3) containing corresponding ground truth 2D keypoints.
|
||||
images (torch.Tensor): Tensor of shape (B, H, W, 3) containing images with values in the [0,255] range.
|
||||
camera_translation (torch.Tensor): Tensor of shape (B, 3) containing the camera translation.
|
||||
Returns:
|
||||
np.array : Image with the following layout. Each row contains the a) input image,
|
||||
b) image with gt 2D keypoints,
|
||||
c) image with projected gt 3D keypoints,
|
||||
d_1, ... , d_S) image with projected predicted 3D keypoints,
|
||||
e) gt 3D keypoints rendered from a side view,
|
||||
f_1, ... , f_S) predicted 3D keypoints frorm a side view
|
||||
"""
|
||||
batch_size = pred_keypoints_3d.shape[0]
|
||||
# num_samples = pred_keypoints_3d.shape[1]
|
||||
pred_keypoints_3d = pred_keypoints_3d.clone().cpu().float()
|
||||
gt_keypoints_3d = gt_keypoints_3d.clone().cpu().float()
|
||||
gt_keypoints_3d[:, :, :-1] = gt_keypoints_3d[:, :, :-1] - gt_keypoints_3d[:, [0], :-1] + pred_keypoints_3d[:, [0]]
|
||||
gt_keypoints_2d = gt_keypoints_2d.clone().cpu().float().numpy()
|
||||
gt_keypoints_2d[:, :, :-1] = self.cfg.MODEL.IMAGE_SIZE * (gt_keypoints_2d[:, :, :-1] + 1.0) / 2.0
|
||||
|
||||
#openpose_indices = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
|
||||
#gt_indices = [12, 8, 7, 6, 9, 10, 11, 14, 2, 1, 0, 3, 4, 5]
|
||||
#gt_indices = [25 + i for i in gt_indices]
|
||||
openpose_indices = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||
gt_indices = openpose_indices
|
||||
keypoints_to_render = torch.ones(batch_size, gt_keypoints_3d.shape[1], 1)
|
||||
rotation = torch.eye(3).unsqueeze(0)
|
||||
if camera_translation is None:
|
||||
camera_translation = torch.tensor([0.0, 0.0, 2 * self.cfg.EXTRA.FOCAL_LENGTH / (0.8 * self.cfg.MODEL.IMAGE_SIZE)]).unsqueeze(0).repeat(batch_size, 1)
|
||||
else:
|
||||
camera_translation = camera_translation.cpu()
|
||||
|
||||
if images is None:
|
||||
images = np.zeros((batch_size, self.cfg.MODEL.IMAGE_SIZE, self.cfg.MODEL.IMAGE_SIZE, 3))
|
||||
focal_length = torch.tensor([self.cfg.EXTRA.FOCAL_LENGTH, self.cfg.EXTRA.FOCAL_LENGTH]).reshape(1, 2)
|
||||
camera_center = torch.tensor([self.cfg.MODEL.IMAGE_SIZE, self.cfg.MODEL.IMAGE_SIZE], dtype=torch.float).reshape(1, 2) / 2.
|
||||
gt_keypoints_3d_proj = perspective_projection(gt_keypoints_3d[:, :, :-1], rotation=rotation.repeat(batch_size, 1, 1), translation=camera_translation[:, :], focal_length=focal_length.repeat(batch_size, 1), camera_center=camera_center.repeat(batch_size, 1))
|
||||
pred_keypoints_3d_proj = perspective_projection(pred_keypoints_3d.reshape(batch_size, -1, 3), rotation=rotation.repeat(batch_size, 1, 1), translation=camera_translation.reshape(batch_size, -1), focal_length=focal_length.repeat(batch_size, 1), camera_center=camera_center.repeat(batch_size, 1)).reshape(batch_size, -1, 2)
|
||||
gt_keypoints_3d_proj = torch.cat([gt_keypoints_3d_proj, gt_keypoints_3d[:, :, [-1]]], dim=-1).cpu().numpy()
|
||||
pred_keypoints_3d_proj = torch.cat([pred_keypoints_3d_proj, keypoints_to_render.reshape(batch_size, -1, 1)], dim=-1).cpu().numpy()
|
||||
rows = []
|
||||
# Rotate keypoints to visualize side view
|
||||
R = torch.tensor(trimesh.transformations.rotation_matrix(np.radians(90), [0, 1, 0])[:3, :3]).float()
|
||||
gt_keypoints_3d_side = gt_keypoints_3d.clone()
|
||||
gt_keypoints_3d_side[:, :, :-1] = torch.einsum('bni,ij->bnj', gt_keypoints_3d_side[:, :, :-1], R)
|
||||
pred_keypoints_3d_side = pred_keypoints_3d.clone()
|
||||
pred_keypoints_3d_side = torch.einsum('bni,ij->bnj', pred_keypoints_3d_side, R)
|
||||
gt_keypoints_3d_proj_side = perspective_projection(gt_keypoints_3d_side[:, :, :-1], rotation=rotation.repeat(batch_size, 1, 1), translation=camera_translation[:, :], focal_length=focal_length.repeat(batch_size, 1), camera_center=camera_center.repeat(batch_size, 1))
|
||||
pred_keypoints_3d_proj_side = perspective_projection(pred_keypoints_3d_side.reshape(batch_size, -1, 3), rotation=rotation.repeat(batch_size, 1, 1), translation=camera_translation.reshape(batch_size, -1), focal_length=focal_length.repeat(batch_size, 1), camera_center=camera_center.repeat(batch_size, 1)).reshape(batch_size, -1, 2)
|
||||
gt_keypoints_3d_proj_side = torch.cat([gt_keypoints_3d_proj_side, gt_keypoints_3d_side[:, :, [-1]]], dim=-1).cpu().numpy()
|
||||
pred_keypoints_3d_proj_side = torch.cat([pred_keypoints_3d_proj_side, keypoints_to_render.reshape(batch_size, -1, 1)], dim=-1).cpu().numpy()
|
||||
for i in range(batch_size):
|
||||
img = images[i]
|
||||
side_img = np.zeros((self.cfg.MODEL.IMAGE_SIZE, self.cfg.MODEL.IMAGE_SIZE, 3))
|
||||
# gt 2D keypoints
|
||||
body_keypoints_2d = gt_keypoints_2d[i, :21].copy()
|
||||
for op, gt in zip(openpose_indices, gt_indices):
|
||||
if gt_keypoints_2d[i, gt, -1] > body_keypoints_2d[op, -1]:
|
||||
body_keypoints_2d[op] = gt_keypoints_2d[i, gt]
|
||||
gt_keypoints_img = render_openpose(img, body_keypoints_2d) / 255.
|
||||
# gt 3D keypoints
|
||||
body_keypoints_3d_proj = gt_keypoints_3d_proj[i, :21].copy()
|
||||
for op, gt in zip(openpose_indices, gt_indices):
|
||||
if gt_keypoints_3d_proj[i, gt, -1] > body_keypoints_3d_proj[op, -1]:
|
||||
body_keypoints_3d_proj[op] = gt_keypoints_3d_proj[i, gt]
|
||||
gt_keypoints_3d_proj_img = render_openpose(img, body_keypoints_3d_proj) / 255.
|
||||
# gt 3D keypoints from the side
|
||||
body_keypoints_3d_proj = gt_keypoints_3d_proj_side[i, :21].copy()
|
||||
for op, gt in zip(openpose_indices, gt_indices):
|
||||
if gt_keypoints_3d_proj_side[i, gt, -1] > body_keypoints_3d_proj[op, -1]:
|
||||
body_keypoints_3d_proj[op] = gt_keypoints_3d_proj_side[i, gt]
|
||||
gt_keypoints_3d_proj_img_side = render_openpose(side_img, body_keypoints_3d_proj) / 255.
|
||||
# pred 3D keypoints
|
||||
pred_keypoints_3d_proj_imgs = []
|
||||
body_keypoints_3d_proj = pred_keypoints_3d_proj[i, :21].copy()
|
||||
for op, gt in zip(openpose_indices, gt_indices):
|
||||
if pred_keypoints_3d_proj[i, gt, -1] >= body_keypoints_3d_proj[op, -1]:
|
||||
body_keypoints_3d_proj[op] = pred_keypoints_3d_proj[i, gt]
|
||||
pred_keypoints_3d_proj_imgs.append(render_openpose(img, body_keypoints_3d_proj) / 255.)
|
||||
pred_keypoints_3d_proj_img = np.concatenate(pred_keypoints_3d_proj_imgs, axis=1)
|
||||
# gt 3D keypoints from the side
|
||||
pred_keypoints_3d_proj_imgs_side = []
|
||||
body_keypoints_3d_proj = pred_keypoints_3d_proj_side[i, :21].copy()
|
||||
for op, gt in zip(openpose_indices, gt_indices):
|
||||
if pred_keypoints_3d_proj_side[i, gt, -1] >= body_keypoints_3d_proj[op, -1]:
|
||||
body_keypoints_3d_proj[op] = pred_keypoints_3d_proj_side[i, gt]
|
||||
pred_keypoints_3d_proj_imgs_side.append(render_openpose(side_img, body_keypoints_3d_proj) / 255.)
|
||||
pred_keypoints_3d_proj_img_side = np.concatenate(pred_keypoints_3d_proj_imgs_side, axis=1)
|
||||
rows.append(np.concatenate((gt_keypoints_img, gt_keypoints_3d_proj_img, pred_keypoints_3d_proj_img, gt_keypoints_3d_proj_img_side, pred_keypoints_3d_proj_img_side), axis=1))
|
||||
# Concatenate images
|
||||
img = np.concatenate(rows, axis=0)
|
||||
img[:, ::self.cfg.MODEL.IMAGE_SIZE, :] = 1.0
|
||||
img[::self.cfg.MODEL.IMAGE_SIZE, :, :] = 1.0
|
||||
img[:, (1+1+1)*self.cfg.MODEL.IMAGE_SIZE, :] = 0.5
|
||||
return img
|
||||
@@ -0,0 +1,93 @@
|
||||
import detectron2.data.transforms as T
|
||||
import torch
|
||||
from detectron2.checkpoint import DetectionCheckpointer
|
||||
from detectron2.config import CfgNode, instantiate
|
||||
from detectron2.data import MetadataCatalog
|
||||
from omegaconf import OmegaConf
|
||||
|
||||
|
||||
class DefaultPredictor_Lazy:
|
||||
"""Create a simple end-to-end predictor with the given config that runs on single device for a
|
||||
single input image.
|
||||
|
||||
Compared to using the model directly, this class does the following additions:
|
||||
|
||||
1. Load checkpoint from the weights specified in config (cfg.MODEL.WEIGHTS).
|
||||
2. Always take BGR image as the input and apply format conversion internally.
|
||||
3. Apply resizing defined by the config (`cfg.INPUT.{MIN,MAX}_SIZE_TEST`).
|
||||
4. Take one input image and produce a single output, instead of a batch.
|
||||
|
||||
This is meant for simple demo purposes, so it does the above steps automatically.
|
||||
This is not meant for benchmarks or running complicated inference logic.
|
||||
If you'd like to do anything more complicated, please refer to its source code as
|
||||
examples to build and use the model manually.
|
||||
|
||||
Attributes:
|
||||
metadata (Metadata): the metadata of the underlying dataset, obtained from
|
||||
test dataset name in the config.
|
||||
|
||||
|
||||
Examples:
|
||||
::
|
||||
pred = DefaultPredictor(cfg)
|
||||
inputs = cv2.imread("input.jpg")
|
||||
outputs = pred(inputs)
|
||||
"""
|
||||
|
||||
def __init__(self, cfg):
|
||||
"""
|
||||
Args:
|
||||
cfg: a yacs CfgNode or a omegaconf dict object.
|
||||
"""
|
||||
if isinstance(cfg, CfgNode):
|
||||
self.cfg = cfg.clone() # cfg can be modified by model
|
||||
self.model = build_model(self.cfg) # noqa: F821
|
||||
if len(cfg.DATASETS.TEST):
|
||||
test_dataset = cfg.DATASETS.TEST[0]
|
||||
|
||||
checkpointer = DetectionCheckpointer(self.model)
|
||||
checkpointer.load(cfg.MODEL.WEIGHTS)
|
||||
|
||||
self.aug = T.ResizeShortestEdge(
|
||||
[cfg.INPUT.MIN_SIZE_TEST, cfg.INPUT.MIN_SIZE_TEST], cfg.INPUT.MAX_SIZE_TEST
|
||||
)
|
||||
|
||||
self.input_format = cfg.INPUT.FORMAT
|
||||
else: # new LazyConfig
|
||||
self.cfg = cfg
|
||||
self.model = instantiate(cfg.model)
|
||||
test_dataset = OmegaConf.select(cfg, "dataloader.test.dataset.names", default=None)
|
||||
if isinstance(test_dataset, (list, tuple)):
|
||||
test_dataset = test_dataset[0]
|
||||
|
||||
checkpointer = DetectionCheckpointer(self.model)
|
||||
checkpointer.load(OmegaConf.select(cfg, "train.init_checkpoint", default=""))
|
||||
|
||||
mapper = instantiate(cfg.dataloader.test.mapper)
|
||||
self.aug = mapper.augmentations
|
||||
self.input_format = mapper.image_format
|
||||
|
||||
self.model.eval().cuda()
|
||||
if test_dataset:
|
||||
self.metadata = MetadataCatalog.get(test_dataset)
|
||||
assert self.input_format in ["RGB", "BGR"], self.input_format
|
||||
|
||||
def __call__(self, original_image):
|
||||
"""
|
||||
Args:
|
||||
original_image (np.ndarray): an image of shape (H, W, C) (in BGR order).
|
||||
|
||||
Returns:
|
||||
predictions (dict):
|
||||
the output of the model for one image only.
|
||||
See :doc:`/tutorials/models` for details about the format.
|
||||
"""
|
||||
with torch.no_grad():
|
||||
if self.input_format == "RGB":
|
||||
original_image = original_image[:, :, ::-1]
|
||||
height, width = original_image.shape[:2]
|
||||
image = self.aug(T.AugInput(original_image)).apply_image(original_image)
|
||||
image = torch.as_tensor(image.astype("float32").transpose(2, 0, 1))
|
||||
inputs = {"image": image, "height": height, "width": width}
|
||||
predictions = self.model([inputs])[0]
|
||||
return predictions
|
||||
Vendored
+37
@@ -0,0 +1,37 @@
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
print('Found packages:', find_packages())
|
||||
setup(
|
||||
description='HaMeR as a package',
|
||||
name='hamer',
|
||||
packages=find_packages(),
|
||||
install_requires=[
|
||||
'gdown',
|
||||
'numpy',
|
||||
'opencv-python',
|
||||
'pyrender',
|
||||
'pytorch-lightning',
|
||||
'scikit-image',
|
||||
'smplx==0.1.28',
|
||||
'torch',
|
||||
'torchvision',
|
||||
'yacs',
|
||||
'detectron2 @ git+https://github.com/facebookresearch/detectron2',
|
||||
'chumpy @ git+https://github.com/mattloper/chumpy',
|
||||
'mmcv==1.3.9',
|
||||
'timm',
|
||||
'einops',
|
||||
'xtcocotools',
|
||||
'pandas',
|
||||
],
|
||||
extras_require={
|
||||
'all': [
|
||||
'hydra-core',
|
||||
'hydra-submitit-launcher',
|
||||
'hydra-colorlog',
|
||||
'pyrootutils',
|
||||
'rich',
|
||||
'webdataset',
|
||||
],
|
||||
},
|
||||
)
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
Copyright 2018-2020 Open-MMLab. All rights reserved.
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2018-2020 Open-MMLab.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,5 @@
|
||||
include requirements/*.txt
|
||||
include mmpose/.mim/model-index.yml
|
||||
recursive-include mmpose/.mim/configs *.py *.yml
|
||||
recursive-include mmpose/.mim/tools *.py *.sh
|
||||
recursive-include mmpose/.mim/demo *.py
|
||||
+293
@@ -0,0 +1,293 @@
|
||||
<h1 align="left">ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation<a href="https://arxiv.org/abs/2204.12484"><img src="https://img.shields.io/badge/arXiv-Paper-<COLOR>.svg" ></a> </h1>
|
||||
|
||||
[](https://paperswithcode.com/sota/pose-estimation-on-coco-test-dev?p=vitpose-simple-vision-transformer-baselines)
|
||||
[](https://paperswithcode.com/sota/pose-estimation-on-aic?p=vitpose-simple-vision-transformer-baselines)
|
||||
[](https://paperswithcode.com/sota/pose-estimation-on-crowdpose?p=vitpose-simple-vision-transformer-baselines)
|
||||
[](https://paperswithcode.com/sota/pose-estimation-on-ochuman?p=vitpose-simple-vision-transformer-baselines)
|
||||
|
||||
<p align="center">
|
||||
<a href="#Results">Results</a> |
|
||||
<a href="#Updates">Updates</a> |
|
||||
<a href="#Usage">Usage</a> |
|
||||
<a href='#Todo'>Todo</a> |
|
||||
<a href="#Acknowledge">Acknowledge</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://giphy.com/gifs/UfPQB1qKir7Vqem6sL/fullscreen"><img src="https://media.giphy.com/media/ZewXwZuixYKS2lZmNL/giphy.gif"></a> <a href="https://giphy.com/gifs/DCvf1DrWZgbwPa8bWZ/fullscreen"><img src="https://media.giphy.com/media/2AEeuicbIjwqp2mbug/giphy.gif"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://giphy.com/gifs/r3GaZz7H1H6zpuIvPI/fullscreen"><img src="https://media.giphy.com/media/13oe6zo6b2B7CdsOac/giphy.gif"></a> <a href="https://giphy.com/gifs/FjzrGJxsOzZAXaW7Vi/fullscreen"><img src="https://media.giphy.com/media/4JLERHxOEgH0tt5DZO/giphy.gif"></a>
|
||||
</p>
|
||||
|
||||
This branch contains the pytorch implementation of <a href="https://arxiv.org/abs/2204.12484">ViTPose: Simple Vision Transformer Baselines for Human Pose Estimation</a> and <a href="https://arxiv.org/abs/2212.04246">ViTPose+: Vision Transformer Foundation Model for Generic Body Pose Estimation</a>. It obtains 81.1 AP on MS COCO Keypoint test-dev set.
|
||||
|
||||
<img src="figures/Throughput.png" class="left" width='80%'>
|
||||
|
||||
## Web Demo
|
||||
|
||||
- Integrated into [Huggingface Spaces 🤗](https://huggingface.co/spaces) using [Gradio](https://github.com/gradio-app/gradio). Try out the Web Demo for video: [](https://huggingface.co/spaces/hysts/ViTPose_video) and images [](https://huggingface.co/spaces/Gradio-Blocks/ViTPose)
|
||||
|
||||
## MAE Pre-trained model
|
||||
|
||||
- The small size MAE pre-trained model can be found in [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccZeiFjh4DJ7gjYyg?e=iTMdMq).
|
||||
- The base, large, and huge pre-trained models using MAE can be found in the [MAE official repo](https://github.com/facebookresearch/mae).
|
||||
|
||||
## Results from this repo on MS COCO val set (single-task training)
|
||||
|
||||
Using detection results from a detector that obtains 56 mAP on person. The configs here are for both training and test.
|
||||
|
||||
> With classic decoder
|
||||
|
||||
| Model | Pretrain | Resolution | AP | AR | config | log | weight |
|
||||
| :----: | :----: | :----: | :----: | :----: | :----: | :----: | :----: |
|
||||
| ViTPose-S | MAE | 256x192 | 73.8 | 79.2 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/ViTPose_small_coco_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgcchdNXBAh7ClS14pA?e=dKXmJ6) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccifT1XlGRatxg3vw?e=9wz7BY) |
|
||||
| ViTPose-B | MAE | 256x192 | 75.8 | 81.1 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/ViTPose_base_coco_256x192.py) | [log](logs/vitpose-b.log.json) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgSMjp1_NrV3VRSmK?e=Q1uZKs) |
|
||||
| ViTPose-L | MAE | 256x192 | 78.3 | 83.5 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/ViTPose_large_coco_256x192.py) | [log](logs/vitpose-l.log.json) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgSd9k_kuktPtiP4F?e=K7DGYT) |
|
||||
| ViTPose-H | MAE | 256x192 | 79.1 | 84.1 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/ViTPose_huge_coco_256x192.py) | [log](logs/vitpose-h.log.json) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgShLMI-kkmvNfF_h?e=dEhGHe) |
|
||||
|
||||
> With simple decoder
|
||||
|
||||
| Model | Pretrain | Resolution | AP | AR | config | log | weight |
|
||||
| :----: | :----: | :----: | :----: | :----: | :----: | :----: | :----: |
|
||||
| ViTPose-S | MAE | 256x192 | 73.5 | 78.9 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/ViTPose_small_simple_coco_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccfkqELJqE67kpRtw?e=InSjJP) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccgb_50jIgiYkHvdw?e=D7RbH2) |
|
||||
| ViTPose-B | MAE | 256x192 | 75.5 | 80.9 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/ViTPose_base_simple_coco_256x192.py) | [log](logs/vitpose-b-simple.log.json) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgSRPKrD5PmDRiv0R?e=jifvOe) |
|
||||
| ViTPose-L | MAE | 256x192 | 78.2 | 83.4 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/ViTPose_large_simple_coco_256x192.py) | [log](logs/vitpose-l-simple.log.json) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgSVS6DP2LmKwZ3sm?e=MmCvDT) |
|
||||
| ViTPose-H | MAE | 256x192 | 78.9 | 84.0 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/ViTPose_huge_simple_coco_256x192.py) | [log](logs/vitpose-h-simple.log.json) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgSbHyN2mjh2n2LyG?e=y0FgMK) |
|
||||
|
||||
|
||||
## Results with multi-task training
|
||||
|
||||
**Note** \* There may exist duplicate images in the crowdpose training set and the validation images in other datasets, as discussed in [issue #24](https://github.com/ViTAE-Transformer/ViTPose/issues/24). Please be careful when using these models for evaluation. We provide the results without the crowpose dataset for reference.
|
||||
|
||||
### Human datasets (MS COCO, AIC, MPII, CrowdPose)
|
||||
> Results on MS COCO val set
|
||||
|
||||
Using detection results from a detector that obtains 56 mAP on person. Note the configs here are only for evaluation.
|
||||
|
||||
| Model | Dataset | Resolution | AP | AR | config | weight |
|
||||
| :----: | :----: | :----: | :----: | :----: | :----: | :----: |
|
||||
| ViTPose-B | COCO+AIC+MPII | 256x192 | 77.1 | 82.2 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/ViTPose_base_coco_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgcccwaTZ8xCFFM3Sjg?e=chmiK5) |
|
||||
| ViTPose-L | COCO+AIC+MPII | 256x192 | 78.7 | 83.8 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/ViTPose_large_coco_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccdOLQqSo6E87GfMw?e=TEurgW) |
|
||||
| ViTPose-H | COCO+AIC+MPII | 256x192 | 79.5 | 84.5 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/ViTPose_huge_coco_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccmHofkmfJDQDukVw?e=gRK224) |
|
||||
| ViTPose-G | COCO+AIC+MPII | 576x432 | 81.0 | 85.6 | | |
|
||||
| ViTPose-B* | COCO+AIC+MPII+CrowdPose | 256x192 | 77.5 | 82.6 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/ViTPose_base_coco_256x192.py) |[Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgSrlMB093JzJtqq-?e=Jr5S3R) |
|
||||
| ViTPose-L* | COCO+AIC+MPII+CrowdPose | 256x192 | 79.1 | 84.1 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/ViTPose_large_coco_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgTBm3dCVmBUbHYT6?e=fHUrTq) |
|
||||
| ViTPose-H* | COCO+AIC+MPII+CrowdPose | 256x192 | 79.8 | 84.8 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/ViTPose_huge_coco_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgS5rLeRAJiWobCdh?e=41GsDd) |
|
||||
| **ViTPose+-S** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 75.8 | 82.6 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/vitPose+_small_coco+aic+mpii+ap10k+apt36k+wholebody_256x192_udp.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccqO1JBHtBjNaeCbQ?e=ZN5NSz) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccrwORr61gT9E4n8g?e=kz9sz5) |
|
||||
| **ViTPose+-B** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 77.0 | 82.6 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/vitPose+_base_coco+aic+mpii+ap10k+apt36k+wholebody_256x192_udp.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccjj9lgPTlkGT1HTw?e=OlS5zv) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgcckRZk1bIAuRa_E1w?e=ylDB2G) |
|
||||
| **ViTPose+-L** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 78.6 | 84.1 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/vitPose+_large_coco+aic+mpii+ap10k+apt36k+wholebody_256x192_udp.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccp7HJf4QMeQQpeyA?e=JagPNt) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccs1SNFUGSTsmRJ8w?e=a9zKwZ) |
|
||||
| **ViTPose+-H** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 79.4 | 84.8 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/coco/vitPose+_huge_coco+aic+mpii+ap10k+apt36k+wholebody_256x192_udp.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgcclxZOlwRJdqpIIjA?e=nFQgVC) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccoXv8rCUgVe7oD9Q?e=ZBw6gR) |
|
||||
|
||||
|
||||
> Results on OCHuman test set
|
||||
|
||||
Using groundtruth bounding boxes. Note the configs here are only for evaluation.
|
||||
|
||||
| Model | Dataset | Resolution | AP | AR | config | weight |
|
||||
| :----: | :----: | :----: | :----: | :----: | :----: | :----: |
|
||||
| ViTPose-B | COCO+AIC+MPII | 256x192 | 88.0 | 89.6 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/ochuman/ViTPose_base_ochuman_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgcccwaTZ8xCFFM3Sjg?e=chmiK5) |
|
||||
| ViTPose-L | COCO+AIC+MPII | 256x192 | 90.9 | 92.2 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/ochuman/ViTPose_large_ochuman_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccdOLQqSo6E87GfMw?e=TEurgW) |
|
||||
| ViTPose-H | COCO+AIC+MPII | 256x192 | 90.9 | 92.3 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/ochuman/ViTPose_huge_ochuman_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccmHofkmfJDQDukVw?e=gRK224) |
|
||||
| ViTPose-G | COCO+AIC+MPII | 576x432 | 93.3 | 94.3 | | |
|
||||
| ViTPose-B* | COCO+AIC+MPII+CrowdPose | 256x192 | 88.2 | 90.0 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/ochuman/ViTPose_base_ochuman_256x192.py) |[Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgSrlMB093JzJtqq-?e=Jr5S3R) |
|
||||
| ViTPose-L* | COCO+AIC+MPII+CrowdPose | 256x192 | 91.5 | 92.8 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/ochuman/ViTPose_large_ochuman_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgTBm3dCVmBUbHYT6?e=fHUrTq) |
|
||||
| ViTPose-H* | COCO+AIC+MPII+CrowdPose | 256x192 | 91.6 | 92.8 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/ochuman/ViTPose_huge_ochuman_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgS5rLeRAJiWobCdh?e=41GsDd) |
|
||||
| **ViTPose+-S** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 78.4 | 80.6 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/ochuman/ViTPose_small_ochuman_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccqO1JBHtBjNaeCbQ?e=ZN5NSz) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccrwORr61gT9E4n8g?e=kz9sz5) |
|
||||
| **ViTPose+-B** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 82.6 | 84.8 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/ochuman/ViTPose_base_ochuman_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccjj9lgPTlkGT1HTw?e=OlS5zv) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgcckRZk1bIAuRa_E1w?e=ylDB2G) |
|
||||
| **ViTPose+-L** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 85.7 | 87.5 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/ochuman/ViTPose_large_ochuman_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccp7HJf4QMeQQpeyA?e=JagPNt) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccs1SNFUGSTsmRJ8w?e=a9zKwZ) |
|
||||
| **ViTPose+-H** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 85.7 | 87.4 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/ochuman/ViTPose_huge_ochuman_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgcclxZOlwRJdqpIIjA?e=nFQgVC) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccoXv8rCUgVe7oD9Q?e=ZBw6gR) |
|
||||
|
||||
> Results on MPII val set
|
||||
|
||||
Using groundtruth bounding boxes. Note the configs here are only for evaluation. The metric is PCKh.
|
||||
|
||||
| Model | Dataset | Resolution | Mean | config | weight |
|
||||
| :----: | :----: | :----: | :----: | :----: | :----: |
|
||||
| ViTPose-B | COCO+AIC+MPII | 256x192 | 93.3 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/mpii/ViTPose_base_mpii_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgcccwaTZ8xCFFM3Sjg?e=chmiK5) |
|
||||
| ViTPose-L | COCO+AIC+MPII | 256x192 | 94.0 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/mpii/ViTPose_large_mpii_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccdOLQqSo6E87GfMw?e=TEurgW) |
|
||||
| ViTPose-H | COCO+AIC+MPII | 256x192 | 94.1 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/mpii/ViTPose_huge_mpii_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccmHofkmfJDQDukVw?e=gRK224) |
|
||||
| ViTPose-G | COCO+AIC+MPII | 576x432 | 94.3 | | |
|
||||
| ViTPose-B* | COCO+AIC+MPII+CrowdPose | 256x192 | 93.4 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/mpii/ViTPose_base_mpii_256x192.py) |[Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgSy_OSEm906wd2LB?e=GOSg14) |
|
||||
| ViTPose-L* | COCO+AIC+MPII+CrowdPose | 256x192 | 93.9 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/mpii/ViTPose_large_mpii_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgTM32I6Kpjr-esl6?e=qvh0Yl) |
|
||||
| ViTPose-H* | COCO+AIC+MPII+CrowdPose | 256x192 | 94.1 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/mpii/ViTPose_huge_mpii_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgTT90XEQBKy-scIH?e=D2WhTS) |
|
||||
| **ViTPose+-S** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 92.7 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/mpii/ViTPose_small_mpii_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccqO1JBHtBjNaeCbQ?e=ZN5NSz) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccrwORr61gT9E4n8g?e=kz9sz5) |
|
||||
| **ViTPose+-B** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 92.8 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/mpii/ViTPose_base_mpii_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccjj9lgPTlkGT1HTw?e=OlS5zv) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgcckRZk1bIAuRa_E1w?e=ylDB2G) |
|
||||
| **ViTPose+-L** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 94.0 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/mpii/ViTPose_large_mpii_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccp7HJf4QMeQQpeyA?e=JagPNt) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccs1SNFUGSTsmRJ8w?e=a9zKwZ) |
|
||||
| **ViTPose+-H** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 94.2 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/mpii/ViTPose_huge_mpii_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgcclxZOlwRJdqpIIjA?e=nFQgVC) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccoXv8rCUgVe7oD9Q?e=ZBw6gR) |
|
||||
|
||||
|
||||
> Results on AI Challenger test set
|
||||
|
||||
Using groundtruth bounding boxes. Note the configs here are only for evaluation.
|
||||
|
||||
| Model | Dataset | Resolution | AP | AR | config | weight |
|
||||
| :----: | :----: | :----: | :----: | :----: | :----: | :----: |
|
||||
| ViTPose-B | COCO+AIC+MPII | 256x192 | 32.0 | 36.3 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/aic/ViTPose_base_aic_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgcccwaTZ8xCFFM3Sjg?e=chmiK5) |
|
||||
| ViTPose-L | COCO+AIC+MPII | 256x192 | 34.5 | 39.0 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/aic/ViTPose_large_aic_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccdOLQqSo6E87GfMw?e=TEurgW) |
|
||||
| ViTPose-H | COCO+AIC+MPII | 256x192 | 35.4 | 39.9 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/aic/ViTPose_huge_aic_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccmHofkmfJDQDukVw?e=gRK224) |
|
||||
| ViTPose-G | COCO+AIC+MPII | 576x432 | 43.2 | 47.1 | | |
|
||||
| ViTPose-B* | COCO+AIC+MPII+CrowdPose | 256x192 | 31.9 | 36.3 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/aic/ViTPose_base_aic_256x192.py) |[Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgSlvdVaXTC92SHYH?e=j7iqcp) |
|
||||
| ViTPose-L* | COCO+AIC+MPII+CrowdPose | 256x192 | 34.6 | 39.0 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/aic/ViTPose_large_aic_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgTF06FX3FSAm0MOH?e=rYts9F) |
|
||||
| ViTPose-H* | COCO+AIC+MPII+CrowdPose | 256x192 | 35.3 | 39.8 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/aic/ViTPose_huge_aic_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgS1MRmb2mcow_K04?e=q9jPab) |
|
||||
| **ViTPose+-S** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 29.7 | 34.3 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/ochuman/ViTPose_small_ochuman_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccqO1JBHtBjNaeCbQ?e=ZN5NSz) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccrwORr61gT9E4n8g?e=kz9sz5) |
|
||||
| **ViTPose+-B** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 31.8 | 36.3 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/ochuman/ViTPose_base_ochuman_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccjj9lgPTlkGT1HTw?e=OlS5zv) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgcckRZk1bIAuRa_E1w?e=ylDB2G) |
|
||||
| **ViTPose+-L** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 34.3 | 38.9 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/ochuman/ViTPose_large_ochuman_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccp7HJf4QMeQQpeyA?e=JagPNt) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccs1SNFUGSTsmRJ8w?e=a9zKwZ) |
|
||||
| **ViTPose+-H** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 34.8 | 39.1 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/ochuman/ViTPose_huge_ochuman_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgcclxZOlwRJdqpIIjA?e=nFQgVC) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccoXv8rCUgVe7oD9Q?e=ZBw6gR) |
|
||||
|
||||
> Results on CrowdPose test set
|
||||
|
||||
Using YOLOv3 human detector. Note the configs here are only for evaluation.
|
||||
|
||||
| Model | Dataset | Resolution | AP | AP(H) | config | weight |
|
||||
| :----: | :----: | :----: | :----: | :----: | :----: | :----: |
|
||||
| ViTPose-B* | COCO+AIC+MPII+CrowdPose | 256x192 | 74.7 | 63.3 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/crowdpose/ViTPose_base_crowdpose_256x192.py) |[Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgStrrCb91cPlaxJx?e=6Xobo6) |
|
||||
| ViTPose-L* | COCO+AIC+MPII+CrowdPose | 256x192 | 76.6 | 65.9 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/crowdpose/ViTPose_large_crowdpose_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgTK3dug-r7c6GFyu?e=1ZBpEG) |
|
||||
| ViTPose-H* | COCO+AIC+MPII+CrowdPose | 256x192 | 76.3 | 65.6 | [config](configs/body/2d_kpt_sview_rgb_img/topdown_heatmap/crowdpose/ViTPose_huge_crowdpose_256x192.py) | [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgS-oAvEV4MTD--Xr?e=EeW2Fu) |
|
||||
|
||||
### Animal datasets (AP10K, APT36K)
|
||||
|
||||
> Results on AP-10K test set
|
||||
|
||||
| Model | Dataset | Resolution | AP | config | weight |
|
||||
| :----: | :----: | :----: | :----: | :----: | :----: |
|
||||
| **ViTPose+-S** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 71.4 | [config](configs/animal/2d_kpt_sview_rgb_img/topdown_heatmap/ap10k/ViTPose_small_ap10k_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccqO1JBHtBjNaeCbQ?e=ZN5NSz) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccrwORr61gT9E4n8g?e=kz9sz5) |
|
||||
| **ViTPose+-B** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 74.5 | [config](configs/animal/2d_kpt_sview_rgb_img/topdown_heatmap/ap10k/ViTPose_base_ap10k_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccjj9lgPTlkGT1HTw?e=OlS5zv) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgcckRZk1bIAuRa_E1w?e=ylDB2G) |
|
||||
| **ViTPose+-L** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 80.4 | [config](configs/animal/2d_kpt_sview_rgb_img/topdown_heatmap/ap10k/ViTPose_large_ap10k_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccp7HJf4QMeQQpeyA?e=JagPNt) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccs1SNFUGSTsmRJ8w?e=a9zKwZ) |
|
||||
| **ViTPose+-H** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 82.4 | [config](configs/animal/2d_kpt_sview_rgb_img/topdown_heatmap/ap10k/ViTPose_huge_ap10k_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgcclxZOlwRJdqpIIjA?e=nFQgVC) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccoXv8rCUgVe7oD9Q?e=ZBw6gR) |
|
||||
|
||||
> Results on APT-36K val set
|
||||
|
||||
| Model | Dataset | Resolution | AP | config | weight |
|
||||
| :----: | :----: | :----: | :----: | :----: | :----: |
|
||||
| **ViTPose+-S** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 74.2 | [config](configs/animal/2d_kpt_sview_rgb_img/topdown_heatmap/apt36k/ViTPose_small_apt36k_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccqO1JBHtBjNaeCbQ?e=ZN5NSz) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccrwORr61gT9E4n8g?e=kz9sz5) |
|
||||
| **ViTPose+-B** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 75.9 | [config](configs/animal/2d_kpt_sview_rgb_img/topdown_heatmap/apt36k/ViTPose_base_apt36k_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccjj9lgPTlkGT1HTw?e=OlS5zv) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgcckRZk1bIAuRa_E1w?e=ylDB2G) |
|
||||
| **ViTPose+-L** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 80.8 | [config](configs/animal/2d_kpt_sview_rgb_img/topdown_heatmap/apt36k/ViTPose_large_apt36k_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccp7HJf4QMeQQpeyA?e=JagPNt) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccs1SNFUGSTsmRJ8w?e=a9zKwZ) |
|
||||
| **ViTPose+-H** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 82.3 | [config](configs/animal/2d_kpt_sview_rgb_img/topdown_heatmap/apt36k/ViTPose_huge_apt36k_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgcclxZOlwRJdqpIIjA?e=nFQgVC) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccoXv8rCUgVe7oD9Q?e=ZBw6gR) |
|
||||
|
||||
### WholeBody dataset
|
||||
|
||||
| Model | Dataset | Resolution | AP | config | weight |
|
||||
| :----: | :----: | :----: | :----: | :----: | :----: |
|
||||
| **ViTPose+-S** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 54.4 | [config](configs/wholebody/2d_kpt_sview_rgb_img/topdown_heatmap/coco-wholebody/ViTPose_small_wholebody_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccqO1JBHtBjNaeCbQ?e=ZN5NSz) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccrwORr61gT9E4n8g?e=kz9sz5) |
|
||||
| **ViTPose+-B** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 57.4 | [config](cconfigs/wholebody/2d_kpt_sview_rgb_img/topdown_heatmap/coco-wholebody/ViTPose_base_wholebody_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccjj9lgPTlkGT1HTw?e=OlS5zv) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgcckRZk1bIAuRa_E1w?e=ylDB2G) |
|
||||
| **ViTPose+-L** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 60.6 | [config](configs/wholebody/2d_kpt_sview_rgb_img/topdown_heatmap/coco-wholebody/ViTPose_large_wholebody_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgccp7HJf4QMeQQpeyA?e=JagPNt) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccs1SNFUGSTsmRJ8w?e=a9zKwZ) |
|
||||
| **ViTPose+-H** | COCO+AIC+MPII+AP10K+APT36K+WholeBody | 256x192 | 61.2 | [config](configs/wholebody/2d_kpt_sview_rgb_img/topdown_heatmap/coco-wholebody/ViTPose_huge_wholebody_256x192.py) | [log](https://1drv.ms/u/s!AimBgYV7JjTlgcclxZOlwRJdqpIIjA?e=nFQgVC) \| [Onedrive](https://1drv.ms/u/s!AimBgYV7JjTlgccoXv8rCUgVe7oD9Q?e=ZBw6gR) |
|
||||
|
||||
### Transfer results on the hand dataset (InterHand2.6M)
|
||||
|
||||
| Model | Dataset | Resolution | AUC | config | weight |
|
||||
| :----: | :----: | :----: | :----: | :----: | :----: |
|
||||
| **ViTPose+-S** | COCO+AIC+MPII+WholeBody | 256x192 | 86.5 | [config](configs/hand/2d_kpt_sview_rgb_img/topdown_heatmap/interhand2d/ViTPose_small_interhand2d_all_256x192.py) | Coming Soon |
|
||||
| **ViTPose+-B** | COCO+AIC+MPII+WholeBody | 256x192 | 87.0 | [config](configs/hand/2d_kpt_sview_rgb_img/topdown_heatmap/interhand2d/ViTPose_base_interhand2d_all_256x192.py) | Coming Soon |
|
||||
| **ViTPose+-L** | COCO+AIC+MPII+WholeBody | 256x192 | 87.5 | [config](configs/hand/2d_kpt_sview_rgb_img/topdown_heatmap/interhand2d/ViTPose_large_interhand2d_all_256x192.py) | Coming Soon |
|
||||
| **ViTPose+-H** | COCO+AIC+MPII+WholeBody | 256x192 | 87.6 | [config](configs/hand/2d_kpt_sview_rgb_img/topdown_heatmap/interhand2d/ViTPose_huge_interhand2d_all_256x192.py) | Coming Soon |
|
||||
|
||||
## Updates
|
||||
|
||||
> [2023-01-10] Update ViTPose+! It uses MoE strategies to jointly deal with human, animal, and wholebody pose estimation tasks.
|
||||
|
||||
> [2022-05-24] Upload the single-task training code, single-task pre-trained models, and multi-task pretrained models.
|
||||
|
||||
> [2022-05-06] Upload the logs for the base, large, and huge models!
|
||||
|
||||
> [2022-04-27] Our ViTPose with ViTAE-G obtains 81.1 AP on COCO test-dev set!
|
||||
|
||||
> Applications of ViTAE Transformer include: [image classification](https://github.com/ViTAE-Transformer/ViTAE-Transformer/tree/main/Image-Classification) | [object detection](https://github.com/ViTAE-Transformer/ViTAE-Transformer/tree/main/Object-Detection) | [semantic segmentation](https://github.com/ViTAE-Transformer/ViTAE-Transformer/tree/main/Semantic-Segmentation) | [animal pose segmentation](https://github.com/ViTAE-Transformer/ViTAE-Transformer/tree/main/Animal-Pose-Estimation) | [remote sensing](https://github.com/ViTAE-Transformer/ViTAE-Transformer-Remote-Sensing) | [matting](https://github.com/ViTAE-Transformer/ViTAE-Transformer-Matting) | [VSA](https://github.com/ViTAE-Transformer/ViTAE-VSA) | [ViTDet](https://github.com/ViTAE-Transformer/ViTDet)
|
||||
|
||||
## Usage
|
||||
|
||||
We use PyTorch 1.9.0 or NGC docker 21.06, and mmcv 1.3.9 for the experiments.
|
||||
```bash
|
||||
git clone https://github.com/open-mmlab/mmcv.git
|
||||
cd mmcv
|
||||
git checkout v1.3.9
|
||||
MMCV_WITH_OPS=1 pip install -e .
|
||||
cd ..
|
||||
git clone https://github.com/ViTAE-Transformer/ViTPose.git
|
||||
cd ViTPose
|
||||
pip install -v -e .
|
||||
```
|
||||
|
||||
After install the two repos, install timm and einops, i.e.,
|
||||
```bash
|
||||
pip install timm==0.4.9 einops
|
||||
```
|
||||
|
||||
After downloading the pretrained models, please conduct the experiments by running
|
||||
|
||||
```bash
|
||||
# for single machine
|
||||
bash tools/dist_train.sh <Config PATH> <NUM GPUs> --cfg-options model.pretrained=<Pretrained PATH> --seed 0
|
||||
|
||||
# for multiple machines
|
||||
python -m torch.distributed.launch --nnodes <Num Machines> --node_rank <Rank of Machine> --nproc_per_node <GPUs Per Machine> --master_addr <Master Addr> --master_port <Master Port> tools/train.py <Config PATH> --cfg-options model.pretrained=<Pretrained PATH> --launcher pytorch --seed 0
|
||||
```
|
||||
|
||||
To test the pretrained models performance, please run
|
||||
|
||||
```bash
|
||||
bash tools/dist_test.sh <Config PATH> <Checkpoint PATH> <NUM GPUs>
|
||||
```
|
||||
|
||||
For ViTPose+ pre-trained models, please first re-organize the pre-trained weights using
|
||||
|
||||
```bash
|
||||
python tools/model_split.py --source <Pretrained PATH>
|
||||
```
|
||||
|
||||
## Todo
|
||||
|
||||
This repo current contains modifications including:
|
||||
|
||||
- [x] Upload configs and pretrained models
|
||||
|
||||
- [x] More models with SOTA results
|
||||
|
||||
- [x] Upload multi-task training config
|
||||
|
||||
## Acknowledge
|
||||
We acknowledge the excellent implementation from [mmpose](https://github.com/open-mmlab/mmdetection) and [MAE](https://github.com/facebookresearch/mae).
|
||||
|
||||
## Citing ViTPose
|
||||
|
||||
For ViTPose
|
||||
|
||||
```
|
||||
@inproceedings{
|
||||
xu2022vitpose,
|
||||
title={Vi{TP}ose: Simple Vision Transformer Baselines for Human Pose Estimation},
|
||||
author={Yufei Xu and Jing Zhang and Qiming Zhang and Dacheng Tao},
|
||||
booktitle={Advances in Neural Information Processing Systems},
|
||||
year={2022},
|
||||
}
|
||||
```
|
||||
|
||||
For ViTPose+
|
||||
|
||||
```
|
||||
@article{xu2022vitpose+,
|
||||
title={ViTPose+: Vision Transformer Foundation Model for Generic Body Pose Estimation},
|
||||
author={Xu, Yufei and Zhang, Jing and Zhang, Qiming and Tao, Dacheng},
|
||||
journal={arXiv preprint arXiv:2212.04246},
|
||||
year={2022}
|
||||
}
|
||||
```
|
||||
|
||||
For ViTAE and ViTAEv2, please refer to:
|
||||
```
|
||||
@article{xu2021vitae,
|
||||
title={Vitae: Vision transformer advanced by exploring intrinsic inductive bias},
|
||||
author={Xu, Yufei and Zhang, Qiming and Zhang, Jing and Tao, Dacheng},
|
||||
journal={Advances in Neural Information Processing Systems},
|
||||
volume={34},
|
||||
year={2021}
|
||||
}
|
||||
|
||||
@article{zhang2022vitaev2,
|
||||
title={ViTAEv2: Vision Transformer Advanced by Exploring Inductive Bias for Image Recognition and Beyond},
|
||||
author={Zhang, Qiming and Xu, Yufei and Zhang, Jing and Tao, Dacheng},
|
||||
journal={arXiv preprint arXiv:2202.10108},
|
||||
year={2022}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,384 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='300w',
|
||||
paper_info=dict(
|
||||
author='Sagonas, Christos and Antonakos, Epameinondas '
|
||||
'and Tzimiropoulos, Georgios and Zafeiriou, Stefanos '
|
||||
'and Pantic, Maja',
|
||||
title='300 faces in-the-wild challenge: '
|
||||
'Database and results',
|
||||
container='Image and vision computing',
|
||||
year='2016',
|
||||
homepage='https://ibug.doc.ic.ac.uk/resources/300-W/',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='kpt-0', id=0, color=[255, 255, 255], type='', swap='kpt-16'),
|
||||
1:
|
||||
dict(
|
||||
name='kpt-1', id=1, color=[255, 255, 255], type='', swap='kpt-15'),
|
||||
2:
|
||||
dict(
|
||||
name='kpt-2', id=2, color=[255, 255, 255], type='', swap='kpt-14'),
|
||||
3:
|
||||
dict(
|
||||
name='kpt-3', id=3, color=[255, 255, 255], type='', swap='kpt-13'),
|
||||
4:
|
||||
dict(
|
||||
name='kpt-4', id=4, color=[255, 255, 255], type='', swap='kpt-12'),
|
||||
5:
|
||||
dict(
|
||||
name='kpt-5', id=5, color=[255, 255, 255], type='', swap='kpt-11'),
|
||||
6:
|
||||
dict(
|
||||
name='kpt-6', id=6, color=[255, 255, 255], type='', swap='kpt-10'),
|
||||
7:
|
||||
dict(name='kpt-7', id=7, color=[255, 255, 255], type='', swap='kpt-9'),
|
||||
8:
|
||||
dict(name='kpt-8', id=8, color=[255, 255, 255], type='', swap=''),
|
||||
9:
|
||||
dict(name='kpt-9', id=9, color=[255, 255, 255], type='', swap='kpt-7'),
|
||||
10:
|
||||
dict(
|
||||
name='kpt-10', id=10, color=[255, 255, 255], type='',
|
||||
swap='kpt-6'),
|
||||
11:
|
||||
dict(
|
||||
name='kpt-11', id=11, color=[255, 255, 255], type='',
|
||||
swap='kpt-5'),
|
||||
12:
|
||||
dict(
|
||||
name='kpt-12', id=12, color=[255, 255, 255], type='',
|
||||
swap='kpt-4'),
|
||||
13:
|
||||
dict(
|
||||
name='kpt-13', id=13, color=[255, 255, 255], type='',
|
||||
swap='kpt-3'),
|
||||
14:
|
||||
dict(
|
||||
name='kpt-14', id=14, color=[255, 255, 255], type='',
|
||||
swap='kpt-2'),
|
||||
15:
|
||||
dict(
|
||||
name='kpt-15', id=15, color=[255, 255, 255], type='',
|
||||
swap='kpt-1'),
|
||||
16:
|
||||
dict(
|
||||
name='kpt-16', id=16, color=[255, 255, 255], type='',
|
||||
swap='kpt-0'),
|
||||
17:
|
||||
dict(
|
||||
name='kpt-17',
|
||||
id=17,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-26'),
|
||||
18:
|
||||
dict(
|
||||
name='kpt-18',
|
||||
id=18,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-25'),
|
||||
19:
|
||||
dict(
|
||||
name='kpt-19',
|
||||
id=19,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-24'),
|
||||
20:
|
||||
dict(
|
||||
name='kpt-20',
|
||||
id=20,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-23'),
|
||||
21:
|
||||
dict(
|
||||
name='kpt-21',
|
||||
id=21,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-22'),
|
||||
22:
|
||||
dict(
|
||||
name='kpt-22',
|
||||
id=22,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-21'),
|
||||
23:
|
||||
dict(
|
||||
name='kpt-23',
|
||||
id=23,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-20'),
|
||||
24:
|
||||
dict(
|
||||
name='kpt-24',
|
||||
id=24,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-19'),
|
||||
25:
|
||||
dict(
|
||||
name='kpt-25',
|
||||
id=25,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-18'),
|
||||
26:
|
||||
dict(
|
||||
name='kpt-26',
|
||||
id=26,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-17'),
|
||||
27:
|
||||
dict(name='kpt-27', id=27, color=[255, 255, 255], type='', swap=''),
|
||||
28:
|
||||
dict(name='kpt-28', id=28, color=[255, 255, 255], type='', swap=''),
|
||||
29:
|
||||
dict(name='kpt-29', id=29, color=[255, 255, 255], type='', swap=''),
|
||||
30:
|
||||
dict(name='kpt-30', id=30, color=[255, 255, 255], type='', swap=''),
|
||||
31:
|
||||
dict(
|
||||
name='kpt-31',
|
||||
id=31,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-35'),
|
||||
32:
|
||||
dict(
|
||||
name='kpt-32',
|
||||
id=32,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-34'),
|
||||
33:
|
||||
dict(name='kpt-33', id=33, color=[255, 255, 255], type='', swap=''),
|
||||
34:
|
||||
dict(
|
||||
name='kpt-34',
|
||||
id=34,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-32'),
|
||||
35:
|
||||
dict(
|
||||
name='kpt-35',
|
||||
id=35,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-31'),
|
||||
36:
|
||||
dict(
|
||||
name='kpt-36',
|
||||
id=36,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-45'),
|
||||
37:
|
||||
dict(
|
||||
name='kpt-37',
|
||||
id=37,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-44'),
|
||||
38:
|
||||
dict(
|
||||
name='kpt-38',
|
||||
id=38,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-43'),
|
||||
39:
|
||||
dict(
|
||||
name='kpt-39',
|
||||
id=39,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-42'),
|
||||
40:
|
||||
dict(
|
||||
name='kpt-40',
|
||||
id=40,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-47'),
|
||||
41:
|
||||
dict(
|
||||
name='kpt-41',
|
||||
id=41,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-46'),
|
||||
42:
|
||||
dict(
|
||||
name='kpt-42',
|
||||
id=42,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-39'),
|
||||
43:
|
||||
dict(
|
||||
name='kpt-43',
|
||||
id=43,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-38'),
|
||||
44:
|
||||
dict(
|
||||
name='kpt-44',
|
||||
id=44,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-37'),
|
||||
45:
|
||||
dict(
|
||||
name='kpt-45',
|
||||
id=45,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-36'),
|
||||
46:
|
||||
dict(
|
||||
name='kpt-46',
|
||||
id=46,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-41'),
|
||||
47:
|
||||
dict(
|
||||
name='kpt-47',
|
||||
id=47,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-40'),
|
||||
48:
|
||||
dict(
|
||||
name='kpt-48',
|
||||
id=48,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-54'),
|
||||
49:
|
||||
dict(
|
||||
name='kpt-49',
|
||||
id=49,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-53'),
|
||||
50:
|
||||
dict(
|
||||
name='kpt-50',
|
||||
id=50,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-52'),
|
||||
51:
|
||||
dict(name='kpt-51', id=51, color=[255, 255, 255], type='', swap=''),
|
||||
52:
|
||||
dict(
|
||||
name='kpt-52',
|
||||
id=52,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-50'),
|
||||
53:
|
||||
dict(
|
||||
name='kpt-53',
|
||||
id=53,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-49'),
|
||||
54:
|
||||
dict(
|
||||
name='kpt-54',
|
||||
id=54,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-48'),
|
||||
55:
|
||||
dict(
|
||||
name='kpt-55',
|
||||
id=55,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-59'),
|
||||
56:
|
||||
dict(
|
||||
name='kpt-56',
|
||||
id=56,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-58'),
|
||||
57:
|
||||
dict(name='kpt-57', id=57, color=[255, 255, 255], type='', swap=''),
|
||||
58:
|
||||
dict(
|
||||
name='kpt-58',
|
||||
id=58,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-56'),
|
||||
59:
|
||||
dict(
|
||||
name='kpt-59',
|
||||
id=59,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-55'),
|
||||
60:
|
||||
dict(
|
||||
name='kpt-60',
|
||||
id=60,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-64'),
|
||||
61:
|
||||
dict(
|
||||
name='kpt-61',
|
||||
id=61,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-63'),
|
||||
62:
|
||||
dict(name='kpt-62', id=62, color=[255, 255, 255], type='', swap=''),
|
||||
63:
|
||||
dict(
|
||||
name='kpt-63',
|
||||
id=63,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-61'),
|
||||
64:
|
||||
dict(
|
||||
name='kpt-64',
|
||||
id=64,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-60'),
|
||||
65:
|
||||
dict(
|
||||
name='kpt-65',
|
||||
id=65,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-67'),
|
||||
66:
|
||||
dict(name='kpt-66', id=66, color=[255, 255, 255], type='', swap=''),
|
||||
67:
|
||||
dict(
|
||||
name='kpt-67',
|
||||
id=67,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-65'),
|
||||
},
|
||||
skeleton_info={},
|
||||
joint_weights=[1.] * 68,
|
||||
sigmas=[])
|
||||
@@ -0,0 +1,83 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='aflw',
|
||||
paper_info=dict(
|
||||
author='Koestinger, Martin and Wohlhart, Paul and '
|
||||
'Roth, Peter M and Bischof, Horst',
|
||||
title='Annotated facial landmarks in the wild: '
|
||||
'A large-scale, real-world database for facial '
|
||||
'landmark localization',
|
||||
container='2011 IEEE international conference on computer '
|
||||
'vision workshops (ICCV workshops)',
|
||||
year='2011',
|
||||
homepage='https://www.tugraz.at/institute/icg/research/'
|
||||
'team-bischof/lrs/downloads/aflw/',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(name='kpt-0', id=0, color=[255, 255, 255], type='', swap='kpt-5'),
|
||||
1:
|
||||
dict(name='kpt-1', id=1, color=[255, 255, 255], type='', swap='kpt-4'),
|
||||
2:
|
||||
dict(name='kpt-2', id=2, color=[255, 255, 255], type='', swap='kpt-3'),
|
||||
3:
|
||||
dict(name='kpt-3', id=3, color=[255, 255, 255], type='', swap='kpt-2'),
|
||||
4:
|
||||
dict(name='kpt-4', id=4, color=[255, 255, 255], type='', swap='kpt-1'),
|
||||
5:
|
||||
dict(name='kpt-5', id=5, color=[255, 255, 255], type='', swap='kpt-0'),
|
||||
6:
|
||||
dict(
|
||||
name='kpt-6', id=6, color=[255, 255, 255], type='', swap='kpt-11'),
|
||||
7:
|
||||
dict(
|
||||
name='kpt-7', id=7, color=[255, 255, 255], type='', swap='kpt-10'),
|
||||
8:
|
||||
dict(name='kpt-8', id=8, color=[255, 255, 255], type='', swap='kpt-9'),
|
||||
9:
|
||||
dict(name='kpt-9', id=9, color=[255, 255, 255], type='', swap='kpt-8'),
|
||||
10:
|
||||
dict(
|
||||
name='kpt-10', id=10, color=[255, 255, 255], type='',
|
||||
swap='kpt-7'),
|
||||
11:
|
||||
dict(
|
||||
name='kpt-11', id=11, color=[255, 255, 255], type='',
|
||||
swap='kpt-6'),
|
||||
12:
|
||||
dict(
|
||||
name='kpt-12',
|
||||
id=12,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-14'),
|
||||
13:
|
||||
dict(name='kpt-13', id=13, color=[255, 255, 255], type='', swap=''),
|
||||
14:
|
||||
dict(
|
||||
name='kpt-14',
|
||||
id=14,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-12'),
|
||||
15:
|
||||
dict(
|
||||
name='kpt-15',
|
||||
id=15,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-17'),
|
||||
16:
|
||||
dict(name='kpt-16', id=16, color=[255, 255, 255], type='', swap=''),
|
||||
17:
|
||||
dict(
|
||||
name='kpt-17',
|
||||
id=17,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-15'),
|
||||
18:
|
||||
dict(name='kpt-18', id=18, color=[255, 255, 255], type='', swap='')
|
||||
},
|
||||
skeleton_info={},
|
||||
joint_weights=[1.] * 19,
|
||||
sigmas=[])
|
||||
@@ -0,0 +1,140 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='aic',
|
||||
paper_info=dict(
|
||||
author='Wu, Jiahong and Zheng, He and Zhao, Bo and '
|
||||
'Li, Yixin and Yan, Baoming and Liang, Rui and '
|
||||
'Wang, Wenjia and Zhou, Shipei and Lin, Guosen and '
|
||||
'Fu, Yanwei and others',
|
||||
title='Ai challenger: A large-scale dataset for going '
|
||||
'deeper in image understanding',
|
||||
container='arXiv',
|
||||
year='2017',
|
||||
homepage='https://github.com/AIChallenger/AI_Challenger_2017',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='right_shoulder',
|
||||
id=0,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_shoulder'),
|
||||
1:
|
||||
dict(
|
||||
name='right_elbow',
|
||||
id=1,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_elbow'),
|
||||
2:
|
||||
dict(
|
||||
name='right_wrist',
|
||||
id=2,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_wrist'),
|
||||
3:
|
||||
dict(
|
||||
name='left_shoulder',
|
||||
id=3,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_shoulder'),
|
||||
4:
|
||||
dict(
|
||||
name='left_elbow',
|
||||
id=4,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_elbow'),
|
||||
5:
|
||||
dict(
|
||||
name='left_wrist',
|
||||
id=5,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_wrist'),
|
||||
6:
|
||||
dict(
|
||||
name='right_hip',
|
||||
id=6,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_hip'),
|
||||
7:
|
||||
dict(
|
||||
name='right_knee',
|
||||
id=7,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_knee'),
|
||||
8:
|
||||
dict(
|
||||
name='right_ankle',
|
||||
id=8,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_ankle'),
|
||||
9:
|
||||
dict(
|
||||
name='left_hip',
|
||||
id=9,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_hip'),
|
||||
10:
|
||||
dict(
|
||||
name='left_knee',
|
||||
id=10,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_knee'),
|
||||
11:
|
||||
dict(
|
||||
name='left_ankle',
|
||||
id=11,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_ankle'),
|
||||
12:
|
||||
dict(
|
||||
name='head_top',
|
||||
id=12,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap=''),
|
||||
13:
|
||||
dict(name='neck', id=13, color=[51, 153, 255], type='upper', swap='')
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('right_wrist', 'right_elbow'), id=0, color=[255, 128, 0]),
|
||||
1: dict(
|
||||
link=('right_elbow', 'right_shoulder'), id=1, color=[255, 128, 0]),
|
||||
2: dict(link=('right_shoulder', 'neck'), id=2, color=[51, 153, 255]),
|
||||
3: dict(link=('neck', 'left_shoulder'), id=3, color=[51, 153, 255]),
|
||||
4: dict(link=('left_shoulder', 'left_elbow'), id=4, color=[0, 255, 0]),
|
||||
5: dict(link=('left_elbow', 'left_wrist'), id=5, color=[0, 255, 0]),
|
||||
6: dict(link=('right_ankle', 'right_knee'), id=6, color=[255, 128, 0]),
|
||||
7: dict(link=('right_knee', 'right_hip'), id=7, color=[255, 128, 0]),
|
||||
8: dict(link=('right_hip', 'left_hip'), id=8, color=[51, 153, 255]),
|
||||
9: dict(link=('left_hip', 'left_knee'), id=9, color=[0, 255, 0]),
|
||||
10: dict(link=('left_knee', 'left_ankle'), id=10, color=[0, 255, 0]),
|
||||
11: dict(link=('head_top', 'neck'), id=11, color=[51, 153, 255]),
|
||||
12: dict(
|
||||
link=('right_shoulder', 'right_hip'), id=12, color=[51, 153, 255]),
|
||||
13:
|
||||
dict(link=('left_shoulder', 'left_hip'), id=13, color=[51, 153, 255])
|
||||
},
|
||||
joint_weights=[
|
||||
1., 1.2, 1.5, 1., 1.2, 1.5, 1., 1.2, 1.5, 1., 1.2, 1.5, 1., 1.
|
||||
],
|
||||
|
||||
# 'https://github.com/AIChallenger/AI_Challenger_2017/blob/master/'
|
||||
# 'Evaluation/keypoint_eval/keypoint_eval.py#L50'
|
||||
# delta = 2 x sigma
|
||||
sigmas=[
|
||||
0.01388152, 0.01515228, 0.01057665, 0.01417709, 0.01497891, 0.01402144,
|
||||
0.03909642, 0.03686941, 0.01981803, 0.03843971, 0.03412318, 0.02415081,
|
||||
0.01291456, 0.01236173
|
||||
])
|
||||
@@ -0,0 +1,140 @@
|
||||
aic_info = dict(
|
||||
dataset_name='aic',
|
||||
paper_info=dict(
|
||||
author='Wu, Jiahong and Zheng, He and Zhao, Bo and '
|
||||
'Li, Yixin and Yan, Baoming and Liang, Rui and '
|
||||
'Wang, Wenjia and Zhou, Shipei and Lin, Guosen and '
|
||||
'Fu, Yanwei and others',
|
||||
title='Ai challenger: A large-scale dataset for going '
|
||||
'deeper in image understanding',
|
||||
container='arXiv',
|
||||
year='2017',
|
||||
homepage='https://github.com/AIChallenger/AI_Challenger_2017',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='right_shoulder',
|
||||
id=0,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_shoulder'),
|
||||
1:
|
||||
dict(
|
||||
name='right_elbow',
|
||||
id=1,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_elbow'),
|
||||
2:
|
||||
dict(
|
||||
name='right_wrist',
|
||||
id=2,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_wrist'),
|
||||
3:
|
||||
dict(
|
||||
name='left_shoulder',
|
||||
id=3,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_shoulder'),
|
||||
4:
|
||||
dict(
|
||||
name='left_elbow',
|
||||
id=4,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_elbow'),
|
||||
5:
|
||||
dict(
|
||||
name='left_wrist',
|
||||
id=5,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_wrist'),
|
||||
6:
|
||||
dict(
|
||||
name='right_hip',
|
||||
id=6,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_hip'),
|
||||
7:
|
||||
dict(
|
||||
name='right_knee',
|
||||
id=7,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_knee'),
|
||||
8:
|
||||
dict(
|
||||
name='right_ankle',
|
||||
id=8,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_ankle'),
|
||||
9:
|
||||
dict(
|
||||
name='left_hip',
|
||||
id=9,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_hip'),
|
||||
10:
|
||||
dict(
|
||||
name='left_knee',
|
||||
id=10,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_knee'),
|
||||
11:
|
||||
dict(
|
||||
name='left_ankle',
|
||||
id=11,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_ankle'),
|
||||
12:
|
||||
dict(
|
||||
name='head_top',
|
||||
id=12,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap=''),
|
||||
13:
|
||||
dict(name='neck', id=13, color=[51, 153, 255], type='upper', swap='')
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('right_wrist', 'right_elbow'), id=0, color=[255, 128, 0]),
|
||||
1: dict(
|
||||
link=('right_elbow', 'right_shoulder'), id=1, color=[255, 128, 0]),
|
||||
2: dict(link=('right_shoulder', 'neck'), id=2, color=[51, 153, 255]),
|
||||
3: dict(link=('neck', 'left_shoulder'), id=3, color=[51, 153, 255]),
|
||||
4: dict(link=('left_shoulder', 'left_elbow'), id=4, color=[0, 255, 0]),
|
||||
5: dict(link=('left_elbow', 'left_wrist'), id=5, color=[0, 255, 0]),
|
||||
6: dict(link=('right_ankle', 'right_knee'), id=6, color=[255, 128, 0]),
|
||||
7: dict(link=('right_knee', 'right_hip'), id=7, color=[255, 128, 0]),
|
||||
8: dict(link=('right_hip', 'left_hip'), id=8, color=[51, 153, 255]),
|
||||
9: dict(link=('left_hip', 'left_knee'), id=9, color=[0, 255, 0]),
|
||||
10: dict(link=('left_knee', 'left_ankle'), id=10, color=[0, 255, 0]),
|
||||
11: dict(link=('head_top', 'neck'), id=11, color=[51, 153, 255]),
|
||||
12: dict(
|
||||
link=('right_shoulder', 'right_hip'), id=12, color=[51, 153, 255]),
|
||||
13:
|
||||
dict(link=('left_shoulder', 'left_hip'), id=13, color=[51, 153, 255])
|
||||
},
|
||||
joint_weights=[
|
||||
1., 1.2, 1.5, 1., 1.2, 1.5, 1., 1.2, 1.5, 1., 1.2, 1.5, 1., 1.
|
||||
],
|
||||
|
||||
# 'https://github.com/AIChallenger/AI_Challenger_2017/blob/master/'
|
||||
# 'Evaluation/keypoint_eval/keypoint_eval.py#L50'
|
||||
# delta = 2 x sigma
|
||||
sigmas=[
|
||||
0.01388152, 0.01515228, 0.01057665, 0.01417709, 0.01497891, 0.01402144,
|
||||
0.03909642, 0.03686941, 0.01981803, 0.03843971, 0.03412318, 0.02415081,
|
||||
0.01291456, 0.01236173
|
||||
])
|
||||
@@ -0,0 +1,166 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='animalpose',
|
||||
paper_info=dict(
|
||||
author='Cao, Jinkun and Tang, Hongyang and Fang, Hao-Shu and '
|
||||
'Shen, Xiaoyong and Lu, Cewu and Tai, Yu-Wing',
|
||||
title='Cross-Domain Adaptation for Animal Pose Estimation',
|
||||
container='The IEEE International Conference on '
|
||||
'Computer Vision (ICCV)',
|
||||
year='2019',
|
||||
homepage='https://sites.google.com/view/animal-pose/',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='L_Eye', id=0, color=[0, 255, 0], type='upper', swap='R_Eye'),
|
||||
1:
|
||||
dict(
|
||||
name='R_Eye',
|
||||
id=1,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='L_Eye'),
|
||||
2:
|
||||
dict(
|
||||
name='L_EarBase',
|
||||
id=2,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='R_EarBase'),
|
||||
3:
|
||||
dict(
|
||||
name='R_EarBase',
|
||||
id=3,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='L_EarBase'),
|
||||
4:
|
||||
dict(name='Nose', id=4, color=[51, 153, 255], type='upper', swap=''),
|
||||
5:
|
||||
dict(name='Throat', id=5, color=[51, 153, 255], type='upper', swap=''),
|
||||
6:
|
||||
dict(
|
||||
name='TailBase', id=6, color=[51, 153, 255], type='lower',
|
||||
swap=''),
|
||||
7:
|
||||
dict(
|
||||
name='Withers', id=7, color=[51, 153, 255], type='upper', swap=''),
|
||||
8:
|
||||
dict(
|
||||
name='L_F_Elbow',
|
||||
id=8,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='R_F_Elbow'),
|
||||
9:
|
||||
dict(
|
||||
name='R_F_Elbow',
|
||||
id=9,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='L_F_Elbow'),
|
||||
10:
|
||||
dict(
|
||||
name='L_B_Elbow',
|
||||
id=10,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='R_B_Elbow'),
|
||||
11:
|
||||
dict(
|
||||
name='R_B_Elbow',
|
||||
id=11,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='L_B_Elbow'),
|
||||
12:
|
||||
dict(
|
||||
name='L_F_Knee',
|
||||
id=12,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='R_F_Knee'),
|
||||
13:
|
||||
dict(
|
||||
name='R_F_Knee',
|
||||
id=13,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='L_F_Knee'),
|
||||
14:
|
||||
dict(
|
||||
name='L_B_Knee',
|
||||
id=14,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='R_B_Knee'),
|
||||
15:
|
||||
dict(
|
||||
name='R_B_Knee',
|
||||
id=15,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='L_B_Knee'),
|
||||
16:
|
||||
dict(
|
||||
name='L_F_Paw',
|
||||
id=16,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='R_F_Paw'),
|
||||
17:
|
||||
dict(
|
||||
name='R_F_Paw',
|
||||
id=17,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='L_F_Paw'),
|
||||
18:
|
||||
dict(
|
||||
name='L_B_Paw',
|
||||
id=18,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='R_B_Paw'),
|
||||
19:
|
||||
dict(
|
||||
name='R_B_Paw',
|
||||
id=19,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='L_B_Paw')
|
||||
},
|
||||
skeleton_info={
|
||||
0: dict(link=('L_Eye', 'R_Eye'), id=0, color=[51, 153, 255]),
|
||||
1: dict(link=('L_Eye', 'L_EarBase'), id=1, color=[0, 255, 0]),
|
||||
2: dict(link=('R_Eye', 'R_EarBase'), id=2, color=[255, 128, 0]),
|
||||
3: dict(link=('L_Eye', 'Nose'), id=3, color=[0, 255, 0]),
|
||||
4: dict(link=('R_Eye', 'Nose'), id=4, color=[255, 128, 0]),
|
||||
5: dict(link=('Nose', 'Throat'), id=5, color=[51, 153, 255]),
|
||||
6: dict(link=('Throat', 'Withers'), id=6, color=[51, 153, 255]),
|
||||
7: dict(link=('TailBase', 'Withers'), id=7, color=[51, 153, 255]),
|
||||
8: dict(link=('Throat', 'L_F_Elbow'), id=8, color=[0, 255, 0]),
|
||||
9: dict(link=('L_F_Elbow', 'L_F_Knee'), id=9, color=[0, 255, 0]),
|
||||
10: dict(link=('L_F_Knee', 'L_F_Paw'), id=10, color=[0, 255, 0]),
|
||||
11: dict(link=('Throat', 'R_F_Elbow'), id=11, color=[255, 128, 0]),
|
||||
12: dict(link=('R_F_Elbow', 'R_F_Knee'), id=12, color=[255, 128, 0]),
|
||||
13: dict(link=('R_F_Knee', 'R_F_Paw'), id=13, color=[255, 128, 0]),
|
||||
14: dict(link=('TailBase', 'L_B_Elbow'), id=14, color=[0, 255, 0]),
|
||||
15: dict(link=('L_B_Elbow', 'L_B_Knee'), id=15, color=[0, 255, 0]),
|
||||
16: dict(link=('L_B_Knee', 'L_B_Paw'), id=16, color=[0, 255, 0]),
|
||||
17: dict(link=('TailBase', 'R_B_Elbow'), id=17, color=[255, 128, 0]),
|
||||
18: dict(link=('R_B_Elbow', 'R_B_Knee'), id=18, color=[255, 128, 0]),
|
||||
19: dict(link=('R_B_Knee', 'R_B_Paw'), id=19, color=[255, 128, 0])
|
||||
},
|
||||
joint_weights=[
|
||||
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.2, 1.2, 1.2, 1.2,
|
||||
1.5, 1.5, 1.5, 1.5
|
||||
],
|
||||
|
||||
# Note: The original paper did not provide enough information about
|
||||
# the sigmas. We modified from 'https://github.com/cocodataset/'
|
||||
# 'cocoapi/blob/master/PythonAPI/pycocotools/cocoeval.py#L523'
|
||||
sigmas=[
|
||||
0.025, 0.025, 0.026, 0.035, 0.035, 0.10, 0.10, 0.10, 0.107, 0.107,
|
||||
0.107, 0.107, 0.087, 0.087, 0.087, 0.087, 0.089, 0.089, 0.089, 0.089
|
||||
])
|
||||
@@ -0,0 +1,142 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='ap10k',
|
||||
paper_info=dict(
|
||||
author='Yu, Hang and Xu, Yufei and Zhang, Jing and '
|
||||
'Zhao, Wei and Guan, Ziyu and Tao, Dacheng',
|
||||
title='AP-10K: A Benchmark for Animal Pose Estimation in the Wild',
|
||||
container='35th Conference on Neural Information Processing Systems '
|
||||
'(NeurIPS 2021) Track on Datasets and Bench-marks.',
|
||||
year='2021',
|
||||
homepage='https://github.com/AlexTheBad/AP-10K',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='L_Eye', id=0, color=[0, 255, 0], type='upper', swap='R_Eye'),
|
||||
1:
|
||||
dict(
|
||||
name='R_Eye',
|
||||
id=1,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='L_Eye'),
|
||||
2:
|
||||
dict(name='Nose', id=2, color=[51, 153, 255], type='upper', swap=''),
|
||||
3:
|
||||
dict(name='Neck', id=3, color=[51, 153, 255], type='upper', swap=''),
|
||||
4:
|
||||
dict(
|
||||
name='Root of tail',
|
||||
id=4,
|
||||
color=[51, 153, 255],
|
||||
type='lower',
|
||||
swap=''),
|
||||
5:
|
||||
dict(
|
||||
name='L_Shoulder',
|
||||
id=5,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='R_Shoulder'),
|
||||
6:
|
||||
dict(
|
||||
name='L_Elbow',
|
||||
id=6,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='R_Elbow'),
|
||||
7:
|
||||
dict(
|
||||
name='L_F_Paw',
|
||||
id=7,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='R_F_Paw'),
|
||||
8:
|
||||
dict(
|
||||
name='R_Shoulder',
|
||||
id=8,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='L_Shoulder'),
|
||||
9:
|
||||
dict(
|
||||
name='R_Elbow',
|
||||
id=9,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='L_Elbow'),
|
||||
10:
|
||||
dict(
|
||||
name='R_F_Paw',
|
||||
id=10,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='L_F_Paw'),
|
||||
11:
|
||||
dict(
|
||||
name='L_Hip',
|
||||
id=11,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='R_Hip'),
|
||||
12:
|
||||
dict(
|
||||
name='L_Knee',
|
||||
id=12,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='R_Knee'),
|
||||
13:
|
||||
dict(
|
||||
name='L_B_Paw',
|
||||
id=13,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='R_B_Paw'),
|
||||
14:
|
||||
dict(
|
||||
name='R_Hip', id=14, color=[0, 255, 0], type='lower',
|
||||
swap='L_Hip'),
|
||||
15:
|
||||
dict(
|
||||
name='R_Knee',
|
||||
id=15,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='L_Knee'),
|
||||
16:
|
||||
dict(
|
||||
name='R_B_Paw',
|
||||
id=16,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='L_B_Paw'),
|
||||
},
|
||||
skeleton_info={
|
||||
0: dict(link=('L_Eye', 'R_Eye'), id=0, color=[0, 0, 255]),
|
||||
1: dict(link=('L_Eye', 'Nose'), id=1, color=[0, 0, 255]),
|
||||
2: dict(link=('R_Eye', 'Nose'), id=2, color=[0, 0, 255]),
|
||||
3: dict(link=('Nose', 'Neck'), id=3, color=[0, 255, 0]),
|
||||
4: dict(link=('Neck', 'Root of tail'), id=4, color=[0, 255, 0]),
|
||||
5: dict(link=('Neck', 'L_Shoulder'), id=5, color=[0, 255, 255]),
|
||||
6: dict(link=('L_Shoulder', 'L_Elbow'), id=6, color=[0, 255, 255]),
|
||||
7: dict(link=('L_Elbow', 'L_F_Paw'), id=6, color=[0, 255, 255]),
|
||||
8: dict(link=('Neck', 'R_Shoulder'), id=7, color=[6, 156, 250]),
|
||||
9: dict(link=('R_Shoulder', 'R_Elbow'), id=8, color=[6, 156, 250]),
|
||||
10: dict(link=('R_Elbow', 'R_F_Paw'), id=9, color=[6, 156, 250]),
|
||||
11: dict(link=('Root of tail', 'L_Hip'), id=10, color=[0, 255, 255]),
|
||||
12: dict(link=('L_Hip', 'L_Knee'), id=11, color=[0, 255, 255]),
|
||||
13: dict(link=('L_Knee', 'L_B_Paw'), id=12, color=[0, 255, 255]),
|
||||
14: dict(link=('Root of tail', 'R_Hip'), id=13, color=[6, 156, 250]),
|
||||
15: dict(link=('R_Hip', 'R_Knee'), id=14, color=[6, 156, 250]),
|
||||
16: dict(link=('R_Knee', 'R_B_Paw'), id=15, color=[6, 156, 250]),
|
||||
},
|
||||
joint_weights=[
|
||||
1., 1., 1., 1., 1., 1., 1., 1.2, 1.2, 1.5, 1.5, 1., 1., 1.2, 1.2, 1.5,
|
||||
1.5
|
||||
],
|
||||
sigmas=[
|
||||
0.025, 0.025, 0.026, 0.035, 0.035, 0.079, 0.072, 0.062, 0.079, 0.072,
|
||||
0.062, 0.107, 0.087, 0.089, 0.107, 0.087, 0.089
|
||||
])
|
||||
@@ -0,0 +1,142 @@
|
||||
ap10k_info = dict(
|
||||
dataset_name='ap10k',
|
||||
paper_info=dict(
|
||||
author='Yu, Hang and Xu, Yufei and Zhang, Jing and '
|
||||
'Zhao, Wei and Guan, Ziyu and Tao, Dacheng',
|
||||
title='AP-10K: A Benchmark for Animal Pose Estimation in the Wild',
|
||||
container='35th Conference on Neural Information Processing Systems '
|
||||
'(NeurIPS 2021) Track on Datasets and Bench-marks.',
|
||||
year='2021',
|
||||
homepage='https://github.com/AlexTheBad/AP-10K',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='L_Eye', id=0, color=[0, 255, 0], type='upper', swap='R_Eye'),
|
||||
1:
|
||||
dict(
|
||||
name='R_Eye',
|
||||
id=1,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='L_Eye'),
|
||||
2:
|
||||
dict(name='Nose', id=2, color=[51, 153, 255], type='upper', swap=''),
|
||||
3:
|
||||
dict(name='Neck', id=3, color=[51, 153, 255], type='upper', swap=''),
|
||||
4:
|
||||
dict(
|
||||
name='Root of tail',
|
||||
id=4,
|
||||
color=[51, 153, 255],
|
||||
type='lower',
|
||||
swap=''),
|
||||
5:
|
||||
dict(
|
||||
name='L_Shoulder',
|
||||
id=5,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='R_Shoulder'),
|
||||
6:
|
||||
dict(
|
||||
name='L_Elbow',
|
||||
id=6,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='R_Elbow'),
|
||||
7:
|
||||
dict(
|
||||
name='L_F_Paw',
|
||||
id=7,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='R_F_Paw'),
|
||||
8:
|
||||
dict(
|
||||
name='R_Shoulder',
|
||||
id=8,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='L_Shoulder'),
|
||||
9:
|
||||
dict(
|
||||
name='R_Elbow',
|
||||
id=9,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='L_Elbow'),
|
||||
10:
|
||||
dict(
|
||||
name='R_F_Paw',
|
||||
id=10,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='L_F_Paw'),
|
||||
11:
|
||||
dict(
|
||||
name='L_Hip',
|
||||
id=11,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='R_Hip'),
|
||||
12:
|
||||
dict(
|
||||
name='L_Knee',
|
||||
id=12,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='R_Knee'),
|
||||
13:
|
||||
dict(
|
||||
name='L_B_Paw',
|
||||
id=13,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='R_B_Paw'),
|
||||
14:
|
||||
dict(
|
||||
name='R_Hip', id=14, color=[0, 255, 0], type='lower',
|
||||
swap='L_Hip'),
|
||||
15:
|
||||
dict(
|
||||
name='R_Knee',
|
||||
id=15,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='L_Knee'),
|
||||
16:
|
||||
dict(
|
||||
name='R_B_Paw',
|
||||
id=16,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='L_B_Paw'),
|
||||
},
|
||||
skeleton_info={
|
||||
0: dict(link=('L_Eye', 'R_Eye'), id=0, color=[0, 0, 255]),
|
||||
1: dict(link=('L_Eye', 'Nose'), id=1, color=[0, 0, 255]),
|
||||
2: dict(link=('R_Eye', 'Nose'), id=2, color=[0, 0, 255]),
|
||||
3: dict(link=('Nose', 'Neck'), id=3, color=[0, 255, 0]),
|
||||
4: dict(link=('Neck', 'Root of tail'), id=4, color=[0, 255, 0]),
|
||||
5: dict(link=('Neck', 'L_Shoulder'), id=5, color=[0, 255, 255]),
|
||||
6: dict(link=('L_Shoulder', 'L_Elbow'), id=6, color=[0, 255, 255]),
|
||||
7: dict(link=('L_Elbow', 'L_F_Paw'), id=6, color=[0, 255, 255]),
|
||||
8: dict(link=('Neck', 'R_Shoulder'), id=7, color=[6, 156, 250]),
|
||||
9: dict(link=('R_Shoulder', 'R_Elbow'), id=8, color=[6, 156, 250]),
|
||||
10: dict(link=('R_Elbow', 'R_F_Paw'), id=9, color=[6, 156, 250]),
|
||||
11: dict(link=('Root of tail', 'L_Hip'), id=10, color=[0, 255, 255]),
|
||||
12: dict(link=('L_Hip', 'L_Knee'), id=11, color=[0, 255, 255]),
|
||||
13: dict(link=('L_Knee', 'L_B_Paw'), id=12, color=[0, 255, 255]),
|
||||
14: dict(link=('Root of tail', 'R_Hip'), id=13, color=[6, 156, 250]),
|
||||
15: dict(link=('R_Hip', 'R_Knee'), id=14, color=[6, 156, 250]),
|
||||
16: dict(link=('R_Knee', 'R_B_Paw'), id=15, color=[6, 156, 250]),
|
||||
},
|
||||
joint_weights=[
|
||||
1., 1., 1., 1., 1., 1., 1., 1.2, 1.2, 1.5, 1.5, 1., 1., 1.2, 1.2, 1.5,
|
||||
1.5
|
||||
],
|
||||
sigmas=[
|
||||
0.025, 0.025, 0.026, 0.035, 0.035, 0.079, 0.072, 0.062, 0.079, 0.072,
|
||||
0.062, 0.107, 0.087, 0.089, 0.107, 0.087, 0.089
|
||||
])
|
||||
@@ -0,0 +1,144 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='atrw',
|
||||
paper_info=dict(
|
||||
author='Li, Shuyuan and Li, Jianguo and Tang, Hanlin '
|
||||
'and Qian, Rui and Lin, Weiyao',
|
||||
title='ATRW: A Benchmark for Amur Tiger '
|
||||
'Re-identification in the Wild',
|
||||
container='Proceedings of the 28th ACM '
|
||||
'International Conference on Multimedia',
|
||||
year='2020',
|
||||
homepage='https://cvwc2019.github.io/challenge.html',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='left_ear',
|
||||
id=0,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='right_ear'),
|
||||
1:
|
||||
dict(
|
||||
name='right_ear',
|
||||
id=1,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='left_ear'),
|
||||
2:
|
||||
dict(name='nose', id=2, color=[51, 153, 255], type='upper', swap=''),
|
||||
3:
|
||||
dict(
|
||||
name='right_shoulder',
|
||||
id=3,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_shoulder'),
|
||||
4:
|
||||
dict(
|
||||
name='right_front_paw',
|
||||
id=4,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_front_paw'),
|
||||
5:
|
||||
dict(
|
||||
name='left_shoulder',
|
||||
id=5,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_shoulder'),
|
||||
6:
|
||||
dict(
|
||||
name='left_front_paw',
|
||||
id=6,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_front_paw'),
|
||||
7:
|
||||
dict(
|
||||
name='right_hip',
|
||||
id=7,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_hip'),
|
||||
8:
|
||||
dict(
|
||||
name='right_knee',
|
||||
id=8,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_knee'),
|
||||
9:
|
||||
dict(
|
||||
name='right_back_paw',
|
||||
id=9,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_back_paw'),
|
||||
10:
|
||||
dict(
|
||||
name='left_hip',
|
||||
id=10,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_hip'),
|
||||
11:
|
||||
dict(
|
||||
name='left_knee',
|
||||
id=11,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_knee'),
|
||||
12:
|
||||
dict(
|
||||
name='left_back_paw',
|
||||
id=12,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_back_paw'),
|
||||
13:
|
||||
dict(name='tail', id=13, color=[51, 153, 255], type='lower', swap=''),
|
||||
14:
|
||||
dict(
|
||||
name='center', id=14, color=[51, 153, 255], type='lower', swap=''),
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('left_ear', 'nose'), id=0, color=[51, 153, 255]),
|
||||
1:
|
||||
dict(link=('right_ear', 'nose'), id=1, color=[51, 153, 255]),
|
||||
2:
|
||||
dict(link=('nose', 'center'), id=2, color=[51, 153, 255]),
|
||||
3:
|
||||
dict(
|
||||
link=('left_shoulder', 'left_front_paw'), id=3, color=[0, 255, 0]),
|
||||
4:
|
||||
dict(link=('left_shoulder', 'center'), id=4, color=[0, 255, 0]),
|
||||
5:
|
||||
dict(
|
||||
link=('right_shoulder', 'right_front_paw'),
|
||||
id=5,
|
||||
color=[255, 128, 0]),
|
||||
6:
|
||||
dict(link=('right_shoulder', 'center'), id=6, color=[255, 128, 0]),
|
||||
7:
|
||||
dict(link=('tail', 'center'), id=7, color=[51, 153, 255]),
|
||||
8:
|
||||
dict(link=('right_back_paw', 'right_knee'), id=8, color=[255, 128, 0]),
|
||||
9:
|
||||
dict(link=('right_knee', 'right_hip'), id=9, color=[255, 128, 0]),
|
||||
10:
|
||||
dict(link=('right_hip', 'tail'), id=10, color=[255, 128, 0]),
|
||||
11:
|
||||
dict(link=('left_back_paw', 'left_knee'), id=11, color=[0, 255, 0]),
|
||||
12:
|
||||
dict(link=('left_knee', 'left_hip'), id=12, color=[0, 255, 0]),
|
||||
13:
|
||||
dict(link=('left_hip', 'tail'), id=13, color=[0, 255, 0]),
|
||||
},
|
||||
joint_weights=[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
|
||||
sigmas=[
|
||||
0.0277, 0.0823, 0.0831, 0.0202, 0.0716, 0.0263, 0.0646, 0.0302, 0.0440,
|
||||
0.0316, 0.0333, 0.0547, 0.0263, 0.0683, 0.0539
|
||||
])
|
||||
@@ -0,0 +1,181 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='coco',
|
||||
paper_info=dict(
|
||||
author='Lin, Tsung-Yi and Maire, Michael and '
|
||||
'Belongie, Serge and Hays, James and '
|
||||
'Perona, Pietro and Ramanan, Deva and '
|
||||
r'Doll{\'a}r, Piotr and Zitnick, C Lawrence',
|
||||
title='Microsoft coco: Common objects in context',
|
||||
container='European conference on computer vision',
|
||||
year='2014',
|
||||
homepage='http://cocodataset.org/',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(name='nose', id=0, color=[51, 153, 255], type='upper', swap=''),
|
||||
1:
|
||||
dict(
|
||||
name='left_eye',
|
||||
id=1,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='right_eye'),
|
||||
2:
|
||||
dict(
|
||||
name='right_eye',
|
||||
id=2,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='left_eye'),
|
||||
3:
|
||||
dict(
|
||||
name='left_ear',
|
||||
id=3,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='right_ear'),
|
||||
4:
|
||||
dict(
|
||||
name='right_ear',
|
||||
id=4,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='left_ear'),
|
||||
5:
|
||||
dict(
|
||||
name='left_shoulder',
|
||||
id=5,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_shoulder'),
|
||||
6:
|
||||
dict(
|
||||
name='right_shoulder',
|
||||
id=6,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_shoulder'),
|
||||
7:
|
||||
dict(
|
||||
name='left_elbow',
|
||||
id=7,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_elbow'),
|
||||
8:
|
||||
dict(
|
||||
name='right_elbow',
|
||||
id=8,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_elbow'),
|
||||
9:
|
||||
dict(
|
||||
name='left_wrist',
|
||||
id=9,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_wrist'),
|
||||
10:
|
||||
dict(
|
||||
name='right_wrist',
|
||||
id=10,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_wrist'),
|
||||
11:
|
||||
dict(
|
||||
name='left_hip',
|
||||
id=11,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_hip'),
|
||||
12:
|
||||
dict(
|
||||
name='right_hip',
|
||||
id=12,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_hip'),
|
||||
13:
|
||||
dict(
|
||||
name='left_knee',
|
||||
id=13,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_knee'),
|
||||
14:
|
||||
dict(
|
||||
name='right_knee',
|
||||
id=14,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_knee'),
|
||||
15:
|
||||
dict(
|
||||
name='left_ankle',
|
||||
id=15,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_ankle'),
|
||||
16:
|
||||
dict(
|
||||
name='right_ankle',
|
||||
id=16,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_ankle')
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('left_ankle', 'left_knee'), id=0, color=[0, 255, 0]),
|
||||
1:
|
||||
dict(link=('left_knee', 'left_hip'), id=1, color=[0, 255, 0]),
|
||||
2:
|
||||
dict(link=('right_ankle', 'right_knee'), id=2, color=[255, 128, 0]),
|
||||
3:
|
||||
dict(link=('right_knee', 'right_hip'), id=3, color=[255, 128, 0]),
|
||||
4:
|
||||
dict(link=('left_hip', 'right_hip'), id=4, color=[51, 153, 255]),
|
||||
5:
|
||||
dict(link=('left_shoulder', 'left_hip'), id=5, color=[51, 153, 255]),
|
||||
6:
|
||||
dict(link=('right_shoulder', 'right_hip'), id=6, color=[51, 153, 255]),
|
||||
7:
|
||||
dict(
|
||||
link=('left_shoulder', 'right_shoulder'),
|
||||
id=7,
|
||||
color=[51, 153, 255]),
|
||||
8:
|
||||
dict(link=('left_shoulder', 'left_elbow'), id=8, color=[0, 255, 0]),
|
||||
9:
|
||||
dict(
|
||||
link=('right_shoulder', 'right_elbow'), id=9, color=[255, 128, 0]),
|
||||
10:
|
||||
dict(link=('left_elbow', 'left_wrist'), id=10, color=[0, 255, 0]),
|
||||
11:
|
||||
dict(link=('right_elbow', 'right_wrist'), id=11, color=[255, 128, 0]),
|
||||
12:
|
||||
dict(link=('left_eye', 'right_eye'), id=12, color=[51, 153, 255]),
|
||||
13:
|
||||
dict(link=('nose', 'left_eye'), id=13, color=[51, 153, 255]),
|
||||
14:
|
||||
dict(link=('nose', 'right_eye'), id=14, color=[51, 153, 255]),
|
||||
15:
|
||||
dict(link=('left_eye', 'left_ear'), id=15, color=[51, 153, 255]),
|
||||
16:
|
||||
dict(link=('right_eye', 'right_ear'), id=16, color=[51, 153, 255]),
|
||||
17:
|
||||
dict(link=('left_ear', 'left_shoulder'), id=17, color=[51, 153, 255]),
|
||||
18:
|
||||
dict(
|
||||
link=('right_ear', 'right_shoulder'), id=18, color=[51, 153, 255])
|
||||
},
|
||||
joint_weights=[
|
||||
1., 1., 1., 1., 1., 1., 1., 1.2, 1.2, 1.5, 1.5, 1., 1., 1.2, 1.2, 1.5,
|
||||
1.5
|
||||
],
|
||||
sigmas=[
|
||||
0.026, 0.025, 0.025, 0.035, 0.035, 0.079, 0.079, 0.072, 0.072, 0.062,
|
||||
0.062, 0.107, 0.107, 0.087, 0.087, 0.089, 0.089
|
||||
])
|
||||
+1154
File diff suppressed because it is too large
Load Diff
+448
@@ -0,0 +1,448 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='coco_wholebody_face',
|
||||
paper_info=dict(
|
||||
author='Jin, Sheng and Xu, Lumin and Xu, Jin and '
|
||||
'Wang, Can and Liu, Wentao and '
|
||||
'Qian, Chen and Ouyang, Wanli and Luo, Ping',
|
||||
title='Whole-Body Human Pose Estimation in the Wild',
|
||||
container='Proceedings of the European '
|
||||
'Conference on Computer Vision (ECCV)',
|
||||
year='2020',
|
||||
homepage='https://github.com/jin-s13/COCO-WholeBody/',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='face-0',
|
||||
id=0,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-16'),
|
||||
1:
|
||||
dict(
|
||||
name='face-1',
|
||||
id=1,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-15'),
|
||||
2:
|
||||
dict(
|
||||
name='face-2',
|
||||
id=2,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-14'),
|
||||
3:
|
||||
dict(
|
||||
name='face-3',
|
||||
id=3,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-13'),
|
||||
4:
|
||||
dict(
|
||||
name='face-4',
|
||||
id=4,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-12'),
|
||||
5:
|
||||
dict(
|
||||
name='face-5',
|
||||
id=5,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-11'),
|
||||
6:
|
||||
dict(
|
||||
name='face-6',
|
||||
id=6,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-10'),
|
||||
7:
|
||||
dict(
|
||||
name='face-7', id=7, color=[255, 255, 255], type='',
|
||||
swap='face-9'),
|
||||
8:
|
||||
dict(name='face-8', id=8, color=[255, 255, 255], type='', swap=''),
|
||||
9:
|
||||
dict(
|
||||
name='face-9', id=9, color=[255, 255, 255], type='',
|
||||
swap='face-7'),
|
||||
10:
|
||||
dict(
|
||||
name='face-10',
|
||||
id=10,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-6'),
|
||||
11:
|
||||
dict(
|
||||
name='face-11',
|
||||
id=11,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-5'),
|
||||
12:
|
||||
dict(
|
||||
name='face-12',
|
||||
id=12,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-4'),
|
||||
13:
|
||||
dict(
|
||||
name='face-13',
|
||||
id=13,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-3'),
|
||||
14:
|
||||
dict(
|
||||
name='face-14',
|
||||
id=14,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-2'),
|
||||
15:
|
||||
dict(
|
||||
name='face-15',
|
||||
id=15,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-1'),
|
||||
16:
|
||||
dict(
|
||||
name='face-16',
|
||||
id=16,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-0'),
|
||||
17:
|
||||
dict(
|
||||
name='face-17',
|
||||
id=17,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-26'),
|
||||
18:
|
||||
dict(
|
||||
name='face-18',
|
||||
id=18,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-25'),
|
||||
19:
|
||||
dict(
|
||||
name='face-19',
|
||||
id=19,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-24'),
|
||||
20:
|
||||
dict(
|
||||
name='face-20',
|
||||
id=20,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-23'),
|
||||
21:
|
||||
dict(
|
||||
name='face-21',
|
||||
id=21,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-22'),
|
||||
22:
|
||||
dict(
|
||||
name='face-22',
|
||||
id=22,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-21'),
|
||||
23:
|
||||
dict(
|
||||
name='face-23',
|
||||
id=23,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-20'),
|
||||
24:
|
||||
dict(
|
||||
name='face-24',
|
||||
id=24,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-19'),
|
||||
25:
|
||||
dict(
|
||||
name='face-25',
|
||||
id=25,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-18'),
|
||||
26:
|
||||
dict(
|
||||
name='face-26',
|
||||
id=26,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-17'),
|
||||
27:
|
||||
dict(name='face-27', id=27, color=[255, 255, 255], type='', swap=''),
|
||||
28:
|
||||
dict(name='face-28', id=28, color=[255, 255, 255], type='', swap=''),
|
||||
29:
|
||||
dict(name='face-29', id=29, color=[255, 255, 255], type='', swap=''),
|
||||
30:
|
||||
dict(name='face-30', id=30, color=[255, 255, 255], type='', swap=''),
|
||||
31:
|
||||
dict(
|
||||
name='face-31',
|
||||
id=31,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-35'),
|
||||
32:
|
||||
dict(
|
||||
name='face-32',
|
||||
id=32,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-34'),
|
||||
33:
|
||||
dict(name='face-33', id=33, color=[255, 255, 255], type='', swap=''),
|
||||
34:
|
||||
dict(
|
||||
name='face-34',
|
||||
id=34,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-32'),
|
||||
35:
|
||||
dict(
|
||||
name='face-35',
|
||||
id=35,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-31'),
|
||||
36:
|
||||
dict(
|
||||
name='face-36',
|
||||
id=36,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-45'),
|
||||
37:
|
||||
dict(
|
||||
name='face-37',
|
||||
id=37,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-44'),
|
||||
38:
|
||||
dict(
|
||||
name='face-38',
|
||||
id=38,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-43'),
|
||||
39:
|
||||
dict(
|
||||
name='face-39',
|
||||
id=39,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-42'),
|
||||
40:
|
||||
dict(
|
||||
name='face-40',
|
||||
id=40,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-47'),
|
||||
41:
|
||||
dict(
|
||||
name='face-41',
|
||||
id=41,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-46'),
|
||||
42:
|
||||
dict(
|
||||
name='face-42',
|
||||
id=42,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-39'),
|
||||
43:
|
||||
dict(
|
||||
name='face-43',
|
||||
id=43,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-38'),
|
||||
44:
|
||||
dict(
|
||||
name='face-44',
|
||||
id=44,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-37'),
|
||||
45:
|
||||
dict(
|
||||
name='face-45',
|
||||
id=45,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-36'),
|
||||
46:
|
||||
dict(
|
||||
name='face-46',
|
||||
id=46,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-41'),
|
||||
47:
|
||||
dict(
|
||||
name='face-47',
|
||||
id=47,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-40'),
|
||||
48:
|
||||
dict(
|
||||
name='face-48',
|
||||
id=48,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-54'),
|
||||
49:
|
||||
dict(
|
||||
name='face-49',
|
||||
id=49,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-53'),
|
||||
50:
|
||||
dict(
|
||||
name='face-50',
|
||||
id=50,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-52'),
|
||||
51:
|
||||
dict(name='face-51', id=52, color=[255, 255, 255], type='', swap=''),
|
||||
52:
|
||||
dict(
|
||||
name='face-52',
|
||||
id=52,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-50'),
|
||||
53:
|
||||
dict(
|
||||
name='face-53',
|
||||
id=53,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-49'),
|
||||
54:
|
||||
dict(
|
||||
name='face-54',
|
||||
id=54,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-48'),
|
||||
55:
|
||||
dict(
|
||||
name='face-55',
|
||||
id=55,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-59'),
|
||||
56:
|
||||
dict(
|
||||
name='face-56',
|
||||
id=56,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-58'),
|
||||
57:
|
||||
dict(name='face-57', id=57, color=[255, 255, 255], type='', swap=''),
|
||||
58:
|
||||
dict(
|
||||
name='face-58',
|
||||
id=58,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-56'),
|
||||
59:
|
||||
dict(
|
||||
name='face-59',
|
||||
id=59,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-55'),
|
||||
60:
|
||||
dict(
|
||||
name='face-60',
|
||||
id=60,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-64'),
|
||||
61:
|
||||
dict(
|
||||
name='face-61',
|
||||
id=61,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-63'),
|
||||
62:
|
||||
dict(name='face-62', id=62, color=[255, 255, 255], type='', swap=''),
|
||||
63:
|
||||
dict(
|
||||
name='face-63',
|
||||
id=63,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-61'),
|
||||
64:
|
||||
dict(
|
||||
name='face-64',
|
||||
id=64,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-60'),
|
||||
65:
|
||||
dict(
|
||||
name='face-65',
|
||||
id=65,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-67'),
|
||||
66:
|
||||
dict(name='face-66', id=66, color=[255, 255, 255], type='', swap=''),
|
||||
67:
|
||||
dict(
|
||||
name='face-67',
|
||||
id=67,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='face-65')
|
||||
},
|
||||
skeleton_info={},
|
||||
joint_weights=[1.] * 68,
|
||||
|
||||
# 'https://github.com/jin-s13/COCO-WholeBody/blob/master/'
|
||||
# 'evaluation/myeval_wholebody.py#L177'
|
||||
sigmas=[
|
||||
0.042, 0.043, 0.044, 0.043, 0.040, 0.035, 0.031, 0.025, 0.020, 0.023,
|
||||
0.029, 0.032, 0.037, 0.038, 0.043, 0.041, 0.045, 0.013, 0.012, 0.011,
|
||||
0.011, 0.012, 0.012, 0.011, 0.011, 0.013, 0.015, 0.009, 0.007, 0.007,
|
||||
0.007, 0.012, 0.009, 0.008, 0.016, 0.010, 0.017, 0.011, 0.009, 0.011,
|
||||
0.009, 0.007, 0.013, 0.008, 0.011, 0.012, 0.010, 0.034, 0.008, 0.008,
|
||||
0.009, 0.008, 0.008, 0.007, 0.010, 0.008, 0.009, 0.009, 0.009, 0.007,
|
||||
0.007, 0.008, 0.011, 0.008, 0.008, 0.008, 0.01, 0.008
|
||||
])
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='coco_wholebody_hand',
|
||||
paper_info=dict(
|
||||
author='Jin, Sheng and Xu, Lumin and Xu, Jin and '
|
||||
'Wang, Can and Liu, Wentao and '
|
||||
'Qian, Chen and Ouyang, Wanli and Luo, Ping',
|
||||
title='Whole-Body Human Pose Estimation in the Wild',
|
||||
container='Proceedings of the European '
|
||||
'Conference on Computer Vision (ECCV)',
|
||||
year='2020',
|
||||
homepage='https://github.com/jin-s13/COCO-WholeBody/',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(name='wrist', id=0, color=[255, 255, 255], type='', swap=''),
|
||||
1:
|
||||
dict(name='thumb1', id=1, color=[255, 128, 0], type='', swap=''),
|
||||
2:
|
||||
dict(name='thumb2', id=2, color=[255, 128, 0], type='', swap=''),
|
||||
3:
|
||||
dict(name='thumb3', id=3, color=[255, 128, 0], type='', swap=''),
|
||||
4:
|
||||
dict(name='thumb4', id=4, color=[255, 128, 0], type='', swap=''),
|
||||
5:
|
||||
dict(
|
||||
name='forefinger1', id=5, color=[255, 153, 255], type='', swap=''),
|
||||
6:
|
||||
dict(
|
||||
name='forefinger2', id=6, color=[255, 153, 255], type='', swap=''),
|
||||
7:
|
||||
dict(
|
||||
name='forefinger3', id=7, color=[255, 153, 255], type='', swap=''),
|
||||
8:
|
||||
dict(
|
||||
name='forefinger4', id=8, color=[255, 153, 255], type='', swap=''),
|
||||
9:
|
||||
dict(
|
||||
name='middle_finger1',
|
||||
id=9,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
10:
|
||||
dict(
|
||||
name='middle_finger2',
|
||||
id=10,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
11:
|
||||
dict(
|
||||
name='middle_finger3',
|
||||
id=11,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
12:
|
||||
dict(
|
||||
name='middle_finger4',
|
||||
id=12,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
13:
|
||||
dict(
|
||||
name='ring_finger1', id=13, color=[255, 51, 51], type='', swap=''),
|
||||
14:
|
||||
dict(
|
||||
name='ring_finger2', id=14, color=[255, 51, 51], type='', swap=''),
|
||||
15:
|
||||
dict(
|
||||
name='ring_finger3', id=15, color=[255, 51, 51], type='', swap=''),
|
||||
16:
|
||||
dict(
|
||||
name='ring_finger4', id=16, color=[255, 51, 51], type='', swap=''),
|
||||
17:
|
||||
dict(name='pinky_finger1', id=17, color=[0, 255, 0], type='', swap=''),
|
||||
18:
|
||||
dict(name='pinky_finger2', id=18, color=[0, 255, 0], type='', swap=''),
|
||||
19:
|
||||
dict(name='pinky_finger3', id=19, color=[0, 255, 0], type='', swap=''),
|
||||
20:
|
||||
dict(name='pinky_finger4', id=20, color=[0, 255, 0], type='', swap='')
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('wrist', 'thumb1'), id=0, color=[255, 128, 0]),
|
||||
1:
|
||||
dict(link=('thumb1', 'thumb2'), id=1, color=[255, 128, 0]),
|
||||
2:
|
||||
dict(link=('thumb2', 'thumb3'), id=2, color=[255, 128, 0]),
|
||||
3:
|
||||
dict(link=('thumb3', 'thumb4'), id=3, color=[255, 128, 0]),
|
||||
4:
|
||||
dict(link=('wrist', 'forefinger1'), id=4, color=[255, 153, 255]),
|
||||
5:
|
||||
dict(link=('forefinger1', 'forefinger2'), id=5, color=[255, 153, 255]),
|
||||
6:
|
||||
dict(link=('forefinger2', 'forefinger3'), id=6, color=[255, 153, 255]),
|
||||
7:
|
||||
dict(link=('forefinger3', 'forefinger4'), id=7, color=[255, 153, 255]),
|
||||
8:
|
||||
dict(link=('wrist', 'middle_finger1'), id=8, color=[102, 178, 255]),
|
||||
9:
|
||||
dict(
|
||||
link=('middle_finger1', 'middle_finger2'),
|
||||
id=9,
|
||||
color=[102, 178, 255]),
|
||||
10:
|
||||
dict(
|
||||
link=('middle_finger2', 'middle_finger3'),
|
||||
id=10,
|
||||
color=[102, 178, 255]),
|
||||
11:
|
||||
dict(
|
||||
link=('middle_finger3', 'middle_finger4'),
|
||||
id=11,
|
||||
color=[102, 178, 255]),
|
||||
12:
|
||||
dict(link=('wrist', 'ring_finger1'), id=12, color=[255, 51, 51]),
|
||||
13:
|
||||
dict(
|
||||
link=('ring_finger1', 'ring_finger2'), id=13, color=[255, 51, 51]),
|
||||
14:
|
||||
dict(
|
||||
link=('ring_finger2', 'ring_finger3'), id=14, color=[255, 51, 51]),
|
||||
15:
|
||||
dict(
|
||||
link=('ring_finger3', 'ring_finger4'), id=15, color=[255, 51, 51]),
|
||||
16:
|
||||
dict(link=('wrist', 'pinky_finger1'), id=16, color=[0, 255, 0]),
|
||||
17:
|
||||
dict(
|
||||
link=('pinky_finger1', 'pinky_finger2'), id=17, color=[0, 255, 0]),
|
||||
18:
|
||||
dict(
|
||||
link=('pinky_finger2', 'pinky_finger3'), id=18, color=[0, 255, 0]),
|
||||
19:
|
||||
dict(
|
||||
link=('pinky_finger3', 'pinky_finger4'), id=19, color=[0, 255, 0])
|
||||
},
|
||||
joint_weights=[1.] * 21,
|
||||
sigmas=[
|
||||
0.029, 0.022, 0.035, 0.037, 0.047, 0.026, 0.025, 0.024, 0.035, 0.018,
|
||||
0.024, 0.022, 0.026, 0.017, 0.021, 0.021, 0.032, 0.02, 0.019, 0.022,
|
||||
0.031
|
||||
])
|
||||
+1154
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,134 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='cofw',
|
||||
paper_info=dict(
|
||||
author='Burgos-Artizzu, Xavier P and Perona, '
|
||||
r'Pietro and Doll{\'a}r, Piotr',
|
||||
title='Robust face landmark estimation under occlusion',
|
||||
container='Proceedings of the IEEE international '
|
||||
'conference on computer vision',
|
||||
year='2013',
|
||||
homepage='http://www.vision.caltech.edu/xpburgos/ICCV13/',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(name='kpt-0', id=0, color=[255, 255, 255], type='', swap='kpt-1'),
|
||||
1:
|
||||
dict(name='kpt-1', id=1, color=[255, 255, 255], type='', swap='kpt-0'),
|
||||
2:
|
||||
dict(name='kpt-2', id=2, color=[255, 255, 255], type='', swap='kpt-3'),
|
||||
3:
|
||||
dict(name='kpt-3', id=3, color=[255, 255, 255], type='', swap='kpt-2'),
|
||||
4:
|
||||
dict(name='kpt-4', id=4, color=[255, 255, 255], type='', swap='kpt-6'),
|
||||
5:
|
||||
dict(name='kpt-5', id=5, color=[255, 255, 255], type='', swap='kpt-7'),
|
||||
6:
|
||||
dict(name='kpt-6', id=6, color=[255, 255, 255], type='', swap='kpt-4'),
|
||||
7:
|
||||
dict(name='kpt-7', id=7, color=[255, 255, 255], type='', swap='kpt-5'),
|
||||
8:
|
||||
dict(name='kpt-8', id=8, color=[255, 255, 255], type='', swap='kpt-9'),
|
||||
9:
|
||||
dict(name='kpt-9', id=9, color=[255, 255, 255], type='', swap='kpt-8'),
|
||||
10:
|
||||
dict(
|
||||
name='kpt-10',
|
||||
id=10,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-11'),
|
||||
11:
|
||||
dict(
|
||||
name='kpt-11',
|
||||
id=11,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-10'),
|
||||
12:
|
||||
dict(
|
||||
name='kpt-12',
|
||||
id=12,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-14'),
|
||||
13:
|
||||
dict(
|
||||
name='kpt-13',
|
||||
id=13,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-15'),
|
||||
14:
|
||||
dict(
|
||||
name='kpt-14',
|
||||
id=14,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-12'),
|
||||
15:
|
||||
dict(
|
||||
name='kpt-15',
|
||||
id=15,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-13'),
|
||||
16:
|
||||
dict(
|
||||
name='kpt-16',
|
||||
id=16,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-17'),
|
||||
17:
|
||||
dict(
|
||||
name='kpt-17',
|
||||
id=17,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-16'),
|
||||
18:
|
||||
dict(
|
||||
name='kpt-18',
|
||||
id=18,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-19'),
|
||||
19:
|
||||
dict(
|
||||
name='kpt-19',
|
||||
id=19,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-18'),
|
||||
20:
|
||||
dict(name='kpt-20', id=20, color=[255, 255, 255], type='', swap=''),
|
||||
21:
|
||||
dict(name='kpt-21', id=21, color=[255, 255, 255], type='', swap=''),
|
||||
22:
|
||||
dict(
|
||||
name='kpt-22',
|
||||
id=22,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-23'),
|
||||
23:
|
||||
dict(
|
||||
name='kpt-23',
|
||||
id=23,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='kpt-22'),
|
||||
24:
|
||||
dict(name='kpt-24', id=24, color=[255, 255, 255], type='', swap=''),
|
||||
25:
|
||||
dict(name='kpt-25', id=25, color=[255, 255, 255], type='', swap=''),
|
||||
26:
|
||||
dict(name='kpt-26', id=26, color=[255, 255, 255], type='', swap=''),
|
||||
27:
|
||||
dict(name='kpt-27', id=27, color=[255, 255, 255], type='', swap=''),
|
||||
28:
|
||||
dict(name='kpt-28', id=28, color=[255, 255, 255], type='', swap='')
|
||||
},
|
||||
skeleton_info={},
|
||||
joint_weights=[1.] * 29,
|
||||
sigmas=[])
|
||||
@@ -0,0 +1,147 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='crowdpose',
|
||||
paper_info=dict(
|
||||
author='Li, Jiefeng and Wang, Can and Zhu, Hao and '
|
||||
'Mao, Yihuan and Fang, Hao-Shu and Lu, Cewu',
|
||||
title='CrowdPose: Efficient Crowded Scenes Pose Estimation '
|
||||
'and A New Benchmark',
|
||||
container='Proceedings of IEEE Conference on Computer '
|
||||
'Vision and Pattern Recognition (CVPR)',
|
||||
year='2019',
|
||||
homepage='https://github.com/Jeff-sjtu/CrowdPose',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='left_shoulder',
|
||||
id=0,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='right_shoulder'),
|
||||
1:
|
||||
dict(
|
||||
name='right_shoulder',
|
||||
id=1,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='left_shoulder'),
|
||||
2:
|
||||
dict(
|
||||
name='left_elbow',
|
||||
id=2,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='right_elbow'),
|
||||
3:
|
||||
dict(
|
||||
name='right_elbow',
|
||||
id=3,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='left_elbow'),
|
||||
4:
|
||||
dict(
|
||||
name='left_wrist',
|
||||
id=4,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='right_wrist'),
|
||||
5:
|
||||
dict(
|
||||
name='right_wrist',
|
||||
id=5,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='left_wrist'),
|
||||
6:
|
||||
dict(
|
||||
name='left_hip',
|
||||
id=6,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='right_hip'),
|
||||
7:
|
||||
dict(
|
||||
name='right_hip',
|
||||
id=7,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='left_hip'),
|
||||
8:
|
||||
dict(
|
||||
name='left_knee',
|
||||
id=8,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='right_knee'),
|
||||
9:
|
||||
dict(
|
||||
name='right_knee',
|
||||
id=9,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='left_knee'),
|
||||
10:
|
||||
dict(
|
||||
name='left_ankle',
|
||||
id=10,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='right_ankle'),
|
||||
11:
|
||||
dict(
|
||||
name='right_ankle',
|
||||
id=11,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='left_ankle'),
|
||||
12:
|
||||
dict(
|
||||
name='top_head', id=12, color=[255, 128, 0], type='upper',
|
||||
swap=''),
|
||||
13:
|
||||
dict(name='neck', id=13, color=[0, 255, 0], type='upper', swap='')
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('left_ankle', 'left_knee'), id=0, color=[0, 255, 0]),
|
||||
1:
|
||||
dict(link=('left_knee', 'left_hip'), id=1, color=[0, 255, 0]),
|
||||
2:
|
||||
dict(link=('right_ankle', 'right_knee'), id=2, color=[255, 128, 0]),
|
||||
3:
|
||||
dict(link=('right_knee', 'right_hip'), id=3, color=[255, 128, 0]),
|
||||
4:
|
||||
dict(link=('left_hip', 'right_hip'), id=4, color=[51, 153, 255]),
|
||||
5:
|
||||
dict(link=('left_shoulder', 'left_hip'), id=5, color=[51, 153, 255]),
|
||||
6:
|
||||
dict(link=('right_shoulder', 'right_hip'), id=6, color=[51, 153, 255]),
|
||||
7:
|
||||
dict(
|
||||
link=('left_shoulder', 'right_shoulder'),
|
||||
id=7,
|
||||
color=[51, 153, 255]),
|
||||
8:
|
||||
dict(link=('left_shoulder', 'left_elbow'), id=8, color=[0, 255, 0]),
|
||||
9:
|
||||
dict(
|
||||
link=('right_shoulder', 'right_elbow'), id=9, color=[255, 128, 0]),
|
||||
10:
|
||||
dict(link=('left_elbow', 'left_wrist'), id=10, color=[0, 255, 0]),
|
||||
11:
|
||||
dict(link=('right_elbow', 'right_wrist'), id=11, color=[255, 128, 0]),
|
||||
12:
|
||||
dict(link=('top_head', 'neck'), id=12, color=[51, 153, 255]),
|
||||
13:
|
||||
dict(link=('right_shoulder', 'neck'), id=13, color=[51, 153, 255]),
|
||||
14:
|
||||
dict(link=('left_shoulder', 'neck'), id=14, color=[51, 153, 255])
|
||||
},
|
||||
joint_weights=[
|
||||
0.2, 0.2, 0.2, 1.3, 1.5, 0.2, 1.3, 1.5, 0.2, 0.2, 0.5, 0.2, 0.2, 0.5
|
||||
],
|
||||
sigmas=[
|
||||
0.079, 0.079, 0.072, 0.072, 0.062, 0.062, 0.107, 0.107, 0.087, 0.087,
|
||||
0.089, 0.089, 0.079, 0.079
|
||||
])
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='deepfashion_full',
|
||||
paper_info=dict(
|
||||
author='Liu, Ziwei and Luo, Ping and Qiu, Shi '
|
||||
'and Wang, Xiaogang and Tang, Xiaoou',
|
||||
title='DeepFashion: Powering Robust Clothes Recognition '
|
||||
'and Retrieval with Rich Annotations',
|
||||
container='Proceedings of IEEE Conference on Computer '
|
||||
'Vision and Pattern Recognition (CVPR)',
|
||||
year='2016',
|
||||
homepage='http://mmlab.ie.cuhk.edu.hk/projects/'
|
||||
'DeepFashion/LandmarkDetection.html',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='left collar',
|
||||
id=0,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='right collar'),
|
||||
1:
|
||||
dict(
|
||||
name='right collar',
|
||||
id=1,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='left collar'),
|
||||
2:
|
||||
dict(
|
||||
name='left sleeve',
|
||||
id=2,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='right sleeve'),
|
||||
3:
|
||||
dict(
|
||||
name='right sleeve',
|
||||
id=3,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='left sleeve'),
|
||||
4:
|
||||
dict(
|
||||
name='left waistline',
|
||||
id=0,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='right waistline'),
|
||||
5:
|
||||
dict(
|
||||
name='right waistline',
|
||||
id=1,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='left waistline'),
|
||||
6:
|
||||
dict(
|
||||
name='left hem',
|
||||
id=2,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='right hem'),
|
||||
7:
|
||||
dict(
|
||||
name='right hem',
|
||||
id=3,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='left hem'),
|
||||
},
|
||||
skeleton_info={},
|
||||
joint_weights=[1.] * 8,
|
||||
sigmas=[])
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='deepfashion_lower',
|
||||
paper_info=dict(
|
||||
author='Liu, Ziwei and Luo, Ping and Qiu, Shi '
|
||||
'and Wang, Xiaogang and Tang, Xiaoou',
|
||||
title='DeepFashion: Powering Robust Clothes Recognition '
|
||||
'and Retrieval with Rich Annotations',
|
||||
container='Proceedings of IEEE Conference on Computer '
|
||||
'Vision and Pattern Recognition (CVPR)',
|
||||
year='2016',
|
||||
homepage='http://mmlab.ie.cuhk.edu.hk/projects/'
|
||||
'DeepFashion/LandmarkDetection.html',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='left waistline',
|
||||
id=0,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='right waistline'),
|
||||
1:
|
||||
dict(
|
||||
name='right waistline',
|
||||
id=1,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='left waistline'),
|
||||
2:
|
||||
dict(
|
||||
name='left hem',
|
||||
id=2,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='right hem'),
|
||||
3:
|
||||
dict(
|
||||
name='right hem',
|
||||
id=3,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='left hem'),
|
||||
},
|
||||
skeleton_info={},
|
||||
joint_weights=[1.] * 4,
|
||||
sigmas=[])
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='deepfashion_upper',
|
||||
paper_info=dict(
|
||||
author='Liu, Ziwei and Luo, Ping and Qiu, Shi '
|
||||
'and Wang, Xiaogang and Tang, Xiaoou',
|
||||
title='DeepFashion: Powering Robust Clothes Recognition '
|
||||
'and Retrieval with Rich Annotations',
|
||||
container='Proceedings of IEEE Conference on Computer '
|
||||
'Vision and Pattern Recognition (CVPR)',
|
||||
year='2016',
|
||||
homepage='http://mmlab.ie.cuhk.edu.hk/projects/'
|
||||
'DeepFashion/LandmarkDetection.html',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='left collar',
|
||||
id=0,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='right collar'),
|
||||
1:
|
||||
dict(
|
||||
name='right collar',
|
||||
id=1,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='left collar'),
|
||||
2:
|
||||
dict(
|
||||
name='left sleeve',
|
||||
id=2,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='right sleeve'),
|
||||
3:
|
||||
dict(
|
||||
name='right sleeve',
|
||||
id=3,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='left sleeve'),
|
||||
4:
|
||||
dict(
|
||||
name='left hem',
|
||||
id=4,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='right hem'),
|
||||
5:
|
||||
dict(
|
||||
name='right hem',
|
||||
id=5,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='left hem'),
|
||||
},
|
||||
skeleton_info={},
|
||||
joint_weights=[1.] * 6,
|
||||
sigmas=[])
|
||||
@@ -0,0 +1,237 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='fly',
|
||||
paper_info=dict(
|
||||
author='Pereira, Talmo D and Aldarondo, Diego E and '
|
||||
'Willmore, Lindsay and Kislin, Mikhail and '
|
||||
'Wang, Samuel S-H and Murthy, Mala and Shaevitz, Joshua W',
|
||||
title='Fast animal pose estimation using deep neural networks',
|
||||
container='Nature methods',
|
||||
year='2019',
|
||||
homepage='https://github.com/jgraving/DeepPoseKit-Data',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(name='head', id=0, color=[255, 255, 255], type='', swap=''),
|
||||
1:
|
||||
dict(name='eyeL', id=1, color=[255, 255, 255], type='', swap='eyeR'),
|
||||
2:
|
||||
dict(name='eyeR', id=2, color=[255, 255, 255], type='', swap='eyeL'),
|
||||
3:
|
||||
dict(name='neck', id=3, color=[255, 255, 255], type='', swap=''),
|
||||
4:
|
||||
dict(name='thorax', id=4, color=[255, 255, 255], type='', swap=''),
|
||||
5:
|
||||
dict(name='abdomen', id=5, color=[255, 255, 255], type='', swap=''),
|
||||
6:
|
||||
dict(
|
||||
name='forelegR1',
|
||||
id=6,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='forelegL1'),
|
||||
7:
|
||||
dict(
|
||||
name='forelegR2',
|
||||
id=7,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='forelegL2'),
|
||||
8:
|
||||
dict(
|
||||
name='forelegR3',
|
||||
id=8,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='forelegL3'),
|
||||
9:
|
||||
dict(
|
||||
name='forelegR4',
|
||||
id=9,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='forelegL4'),
|
||||
10:
|
||||
dict(
|
||||
name='midlegR1',
|
||||
id=10,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='midlegL1'),
|
||||
11:
|
||||
dict(
|
||||
name='midlegR2',
|
||||
id=11,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='midlegL2'),
|
||||
12:
|
||||
dict(
|
||||
name='midlegR3',
|
||||
id=12,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='midlegL3'),
|
||||
13:
|
||||
dict(
|
||||
name='midlegR4',
|
||||
id=13,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='midlegL4'),
|
||||
14:
|
||||
dict(
|
||||
name='hindlegR1',
|
||||
id=14,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='hindlegL1'),
|
||||
15:
|
||||
dict(
|
||||
name='hindlegR2',
|
||||
id=15,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='hindlegL2'),
|
||||
16:
|
||||
dict(
|
||||
name='hindlegR3',
|
||||
id=16,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='hindlegL3'),
|
||||
17:
|
||||
dict(
|
||||
name='hindlegR4',
|
||||
id=17,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='hindlegL4'),
|
||||
18:
|
||||
dict(
|
||||
name='forelegL1',
|
||||
id=18,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='forelegR1'),
|
||||
19:
|
||||
dict(
|
||||
name='forelegL2',
|
||||
id=19,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='forelegR2'),
|
||||
20:
|
||||
dict(
|
||||
name='forelegL3',
|
||||
id=20,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='forelegR3'),
|
||||
21:
|
||||
dict(
|
||||
name='forelegL4',
|
||||
id=21,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='forelegR4'),
|
||||
22:
|
||||
dict(
|
||||
name='midlegL1',
|
||||
id=22,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='midlegR1'),
|
||||
23:
|
||||
dict(
|
||||
name='midlegL2',
|
||||
id=23,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='midlegR2'),
|
||||
24:
|
||||
dict(
|
||||
name='midlegL3',
|
||||
id=24,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='midlegR3'),
|
||||
25:
|
||||
dict(
|
||||
name='midlegL4',
|
||||
id=25,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='midlegR4'),
|
||||
26:
|
||||
dict(
|
||||
name='hindlegL1',
|
||||
id=26,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='hindlegR1'),
|
||||
27:
|
||||
dict(
|
||||
name='hindlegL2',
|
||||
id=27,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='hindlegR2'),
|
||||
28:
|
||||
dict(
|
||||
name='hindlegL3',
|
||||
id=28,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='hindlegR3'),
|
||||
29:
|
||||
dict(
|
||||
name='hindlegL4',
|
||||
id=29,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='hindlegR4'),
|
||||
30:
|
||||
dict(
|
||||
name='wingL', id=30, color=[255, 255, 255], type='', swap='wingR'),
|
||||
31:
|
||||
dict(
|
||||
name='wingR', id=31, color=[255, 255, 255], type='', swap='wingL'),
|
||||
},
|
||||
skeleton_info={
|
||||
0: dict(link=('eyeL', 'head'), id=0, color=[255, 255, 255]),
|
||||
1: dict(link=('eyeR', 'head'), id=1, color=[255, 255, 255]),
|
||||
2: dict(link=('neck', 'head'), id=2, color=[255, 255, 255]),
|
||||
3: dict(link=('thorax', 'neck'), id=3, color=[255, 255, 255]),
|
||||
4: dict(link=('abdomen', 'thorax'), id=4, color=[255, 255, 255]),
|
||||
5: dict(link=('forelegR2', 'forelegR1'), id=5, color=[255, 255, 255]),
|
||||
6: dict(link=('forelegR3', 'forelegR2'), id=6, color=[255, 255, 255]),
|
||||
7: dict(link=('forelegR4', 'forelegR3'), id=7, color=[255, 255, 255]),
|
||||
8: dict(link=('midlegR2', 'midlegR1'), id=8, color=[255, 255, 255]),
|
||||
9: dict(link=('midlegR3', 'midlegR2'), id=9, color=[255, 255, 255]),
|
||||
10: dict(link=('midlegR4', 'midlegR3'), id=10, color=[255, 255, 255]),
|
||||
11:
|
||||
dict(link=('hindlegR2', 'hindlegR1'), id=11, color=[255, 255, 255]),
|
||||
12:
|
||||
dict(link=('hindlegR3', 'hindlegR2'), id=12, color=[255, 255, 255]),
|
||||
13:
|
||||
dict(link=('hindlegR4', 'hindlegR3'), id=13, color=[255, 255, 255]),
|
||||
14:
|
||||
dict(link=('forelegL2', 'forelegL1'), id=14, color=[255, 255, 255]),
|
||||
15:
|
||||
dict(link=('forelegL3', 'forelegL2'), id=15, color=[255, 255, 255]),
|
||||
16:
|
||||
dict(link=('forelegL4', 'forelegL3'), id=16, color=[255, 255, 255]),
|
||||
17: dict(link=('midlegL2', 'midlegL1'), id=17, color=[255, 255, 255]),
|
||||
18: dict(link=('midlegL3', 'midlegL2'), id=18, color=[255, 255, 255]),
|
||||
19: dict(link=('midlegL4', 'midlegL3'), id=19, color=[255, 255, 255]),
|
||||
20:
|
||||
dict(link=('hindlegL2', 'hindlegL1'), id=20, color=[255, 255, 255]),
|
||||
21:
|
||||
dict(link=('hindlegL3', 'hindlegL2'), id=21, color=[255, 255, 255]),
|
||||
22:
|
||||
dict(link=('hindlegL4', 'hindlegL3'), id=22, color=[255, 255, 255]),
|
||||
23: dict(link=('wingL', 'neck'), id=23, color=[255, 255, 255]),
|
||||
24: dict(link=('wingR', 'neck'), id=24, color=[255, 255, 255])
|
||||
},
|
||||
joint_weights=[1.] * 32,
|
||||
sigmas=[])
|
||||
@@ -0,0 +1,144 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='freihand',
|
||||
paper_info=dict(
|
||||
author='Zimmermann, Christian and Ceylan, Duygu and '
|
||||
'Yang, Jimei and Russell, Bryan and '
|
||||
'Argus, Max and Brox, Thomas',
|
||||
title='Freihand: A dataset for markerless capture of hand pose '
|
||||
'and shape from single rgb images',
|
||||
container='Proceedings of the IEEE International '
|
||||
'Conference on Computer Vision',
|
||||
year='2019',
|
||||
homepage='https://lmb.informatik.uni-freiburg.de/projects/freihand/',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(name='wrist', id=0, color=[255, 255, 255], type='', swap=''),
|
||||
1:
|
||||
dict(name='thumb1', id=1, color=[255, 128, 0], type='', swap=''),
|
||||
2:
|
||||
dict(name='thumb2', id=2, color=[255, 128, 0], type='', swap=''),
|
||||
3:
|
||||
dict(name='thumb3', id=3, color=[255, 128, 0], type='', swap=''),
|
||||
4:
|
||||
dict(name='thumb4', id=4, color=[255, 128, 0], type='', swap=''),
|
||||
5:
|
||||
dict(
|
||||
name='forefinger1', id=5, color=[255, 153, 255], type='', swap=''),
|
||||
6:
|
||||
dict(
|
||||
name='forefinger2', id=6, color=[255, 153, 255], type='', swap=''),
|
||||
7:
|
||||
dict(
|
||||
name='forefinger3', id=7, color=[255, 153, 255], type='', swap=''),
|
||||
8:
|
||||
dict(
|
||||
name='forefinger4', id=8, color=[255, 153, 255], type='', swap=''),
|
||||
9:
|
||||
dict(
|
||||
name='middle_finger1',
|
||||
id=9,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
10:
|
||||
dict(
|
||||
name='middle_finger2',
|
||||
id=10,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
11:
|
||||
dict(
|
||||
name='middle_finger3',
|
||||
id=11,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
12:
|
||||
dict(
|
||||
name='middle_finger4',
|
||||
id=12,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
13:
|
||||
dict(
|
||||
name='ring_finger1', id=13, color=[255, 51, 51], type='', swap=''),
|
||||
14:
|
||||
dict(
|
||||
name='ring_finger2', id=14, color=[255, 51, 51], type='', swap=''),
|
||||
15:
|
||||
dict(
|
||||
name='ring_finger3', id=15, color=[255, 51, 51], type='', swap=''),
|
||||
16:
|
||||
dict(
|
||||
name='ring_finger4', id=16, color=[255, 51, 51], type='', swap=''),
|
||||
17:
|
||||
dict(name='pinky_finger1', id=17, color=[0, 255, 0], type='', swap=''),
|
||||
18:
|
||||
dict(name='pinky_finger2', id=18, color=[0, 255, 0], type='', swap=''),
|
||||
19:
|
||||
dict(name='pinky_finger3', id=19, color=[0, 255, 0], type='', swap=''),
|
||||
20:
|
||||
dict(name='pinky_finger4', id=20, color=[0, 255, 0], type='', swap='')
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('wrist', 'thumb1'), id=0, color=[255, 128, 0]),
|
||||
1:
|
||||
dict(link=('thumb1', 'thumb2'), id=1, color=[255, 128, 0]),
|
||||
2:
|
||||
dict(link=('thumb2', 'thumb3'), id=2, color=[255, 128, 0]),
|
||||
3:
|
||||
dict(link=('thumb3', 'thumb4'), id=3, color=[255, 128, 0]),
|
||||
4:
|
||||
dict(link=('wrist', 'forefinger1'), id=4, color=[255, 153, 255]),
|
||||
5:
|
||||
dict(link=('forefinger1', 'forefinger2'), id=5, color=[255, 153, 255]),
|
||||
6:
|
||||
dict(link=('forefinger2', 'forefinger3'), id=6, color=[255, 153, 255]),
|
||||
7:
|
||||
dict(link=('forefinger3', 'forefinger4'), id=7, color=[255, 153, 255]),
|
||||
8:
|
||||
dict(link=('wrist', 'middle_finger1'), id=8, color=[102, 178, 255]),
|
||||
9:
|
||||
dict(
|
||||
link=('middle_finger1', 'middle_finger2'),
|
||||
id=9,
|
||||
color=[102, 178, 255]),
|
||||
10:
|
||||
dict(
|
||||
link=('middle_finger2', 'middle_finger3'),
|
||||
id=10,
|
||||
color=[102, 178, 255]),
|
||||
11:
|
||||
dict(
|
||||
link=('middle_finger3', 'middle_finger4'),
|
||||
id=11,
|
||||
color=[102, 178, 255]),
|
||||
12:
|
||||
dict(link=('wrist', 'ring_finger1'), id=12, color=[255, 51, 51]),
|
||||
13:
|
||||
dict(
|
||||
link=('ring_finger1', 'ring_finger2'), id=13, color=[255, 51, 51]),
|
||||
14:
|
||||
dict(
|
||||
link=('ring_finger2', 'ring_finger3'), id=14, color=[255, 51, 51]),
|
||||
15:
|
||||
dict(
|
||||
link=('ring_finger3', 'ring_finger4'), id=15, color=[255, 51, 51]),
|
||||
16:
|
||||
dict(link=('wrist', 'pinky_finger1'), id=16, color=[0, 255, 0]),
|
||||
17:
|
||||
dict(
|
||||
link=('pinky_finger1', 'pinky_finger2'), id=17, color=[0, 255, 0]),
|
||||
18:
|
||||
dict(
|
||||
link=('pinky_finger2', 'pinky_finger3'), id=18, color=[0, 255, 0]),
|
||||
19:
|
||||
dict(
|
||||
link=('pinky_finger3', 'pinky_finger4'), id=19, color=[0, 255, 0])
|
||||
},
|
||||
joint_weights=[1.] * 21,
|
||||
sigmas=[])
|
||||
@@ -0,0 +1,152 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='h36m',
|
||||
paper_info=dict(
|
||||
author='Ionescu, Catalin and Papava, Dragos and '
|
||||
'Olaru, Vlad and Sminchisescu, Cristian',
|
||||
title='Human3.6M: Large Scale Datasets and Predictive '
|
||||
'Methods for 3D Human Sensing in Natural Environments',
|
||||
container='IEEE Transactions on Pattern Analysis and '
|
||||
'Machine Intelligence',
|
||||
year='2014',
|
||||
homepage='http://vision.imar.ro/human3.6m/description.php',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(name='root', id=0, color=[51, 153, 255], type='lower', swap=''),
|
||||
1:
|
||||
dict(
|
||||
name='right_hip',
|
||||
id=1,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_hip'),
|
||||
2:
|
||||
dict(
|
||||
name='right_knee',
|
||||
id=2,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_knee'),
|
||||
3:
|
||||
dict(
|
||||
name='right_foot',
|
||||
id=3,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_foot'),
|
||||
4:
|
||||
dict(
|
||||
name='left_hip',
|
||||
id=4,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_hip'),
|
||||
5:
|
||||
dict(
|
||||
name='left_knee',
|
||||
id=5,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_knee'),
|
||||
6:
|
||||
dict(
|
||||
name='left_foot',
|
||||
id=6,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_foot'),
|
||||
7:
|
||||
dict(name='spine', id=7, color=[51, 153, 255], type='upper', swap=''),
|
||||
8:
|
||||
dict(name='thorax', id=8, color=[51, 153, 255], type='upper', swap=''),
|
||||
9:
|
||||
dict(
|
||||
name='neck_base',
|
||||
id=9,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap=''),
|
||||
10:
|
||||
dict(name='head', id=10, color=[51, 153, 255], type='upper', swap=''),
|
||||
11:
|
||||
dict(
|
||||
name='left_shoulder',
|
||||
id=11,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_shoulder'),
|
||||
12:
|
||||
dict(
|
||||
name='left_elbow',
|
||||
id=12,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_elbow'),
|
||||
13:
|
||||
dict(
|
||||
name='left_wrist',
|
||||
id=13,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_wrist'),
|
||||
14:
|
||||
dict(
|
||||
name='right_shoulder',
|
||||
id=14,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_shoulder'),
|
||||
15:
|
||||
dict(
|
||||
name='right_elbow',
|
||||
id=15,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_elbow'),
|
||||
16:
|
||||
dict(
|
||||
name='right_wrist',
|
||||
id=16,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_wrist')
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('root', 'left_hip'), id=0, color=[0, 255, 0]),
|
||||
1:
|
||||
dict(link=('left_hip', 'left_knee'), id=1, color=[0, 255, 0]),
|
||||
2:
|
||||
dict(link=('left_knee', 'left_foot'), id=2, color=[0, 255, 0]),
|
||||
3:
|
||||
dict(link=('root', 'right_hip'), id=3, color=[255, 128, 0]),
|
||||
4:
|
||||
dict(link=('right_hip', 'right_knee'), id=4, color=[255, 128, 0]),
|
||||
5:
|
||||
dict(link=('right_knee', 'right_foot'), id=5, color=[255, 128, 0]),
|
||||
6:
|
||||
dict(link=('root', 'spine'), id=6, color=[51, 153, 255]),
|
||||
7:
|
||||
dict(link=('spine', 'thorax'), id=7, color=[51, 153, 255]),
|
||||
8:
|
||||
dict(link=('thorax', 'neck_base'), id=8, color=[51, 153, 255]),
|
||||
9:
|
||||
dict(link=('neck_base', 'head'), id=9, color=[51, 153, 255]),
|
||||
10:
|
||||
dict(link=('thorax', 'left_shoulder'), id=10, color=[0, 255, 0]),
|
||||
11:
|
||||
dict(link=('left_shoulder', 'left_elbow'), id=11, color=[0, 255, 0]),
|
||||
12:
|
||||
dict(link=('left_elbow', 'left_wrist'), id=12, color=[0, 255, 0]),
|
||||
13:
|
||||
dict(link=('thorax', 'right_shoulder'), id=13, color=[255, 128, 0]),
|
||||
14:
|
||||
dict(
|
||||
link=('right_shoulder', 'right_elbow'), id=14, color=[255, 128,
|
||||
0]),
|
||||
15:
|
||||
dict(link=('right_elbow', 'right_wrist'), id=15, color=[255, 128, 0])
|
||||
},
|
||||
joint_weights=[1.] * 17,
|
||||
sigmas=[],
|
||||
stats_info=dict(bbox_center=(528., 427.), bbox_scale=400.))
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,201 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='horse10',
|
||||
paper_info=dict(
|
||||
author='Mathis, Alexander and Biasi, Thomas and '
|
||||
'Schneider, Steffen and '
|
||||
'Yuksekgonul, Mert and Rogers, Byron and '
|
||||
'Bethge, Matthias and '
|
||||
'Mathis, Mackenzie W',
|
||||
title='Pretraining boosts out-of-domain robustness '
|
||||
'for pose estimation',
|
||||
container='Proceedings of the IEEE/CVF Winter Conference on '
|
||||
'Applications of Computer Vision',
|
||||
year='2021',
|
||||
homepage='http://www.mackenziemathislab.org/horse10',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(name='Nose', id=0, color=[255, 153, 255], type='upper', swap=''),
|
||||
1:
|
||||
dict(name='Eye', id=1, color=[255, 153, 255], type='upper', swap=''),
|
||||
2:
|
||||
dict(
|
||||
name='Nearknee',
|
||||
id=2,
|
||||
color=[255, 102, 255],
|
||||
type='upper',
|
||||
swap=''),
|
||||
3:
|
||||
dict(
|
||||
name='Nearfrontfetlock',
|
||||
id=3,
|
||||
color=[255, 102, 255],
|
||||
type='upper',
|
||||
swap=''),
|
||||
4:
|
||||
dict(
|
||||
name='Nearfrontfoot',
|
||||
id=4,
|
||||
color=[255, 102, 255],
|
||||
type='upper',
|
||||
swap=''),
|
||||
5:
|
||||
dict(
|
||||
name='Offknee', id=5, color=[255, 102, 255], type='upper',
|
||||
swap=''),
|
||||
6:
|
||||
dict(
|
||||
name='Offfrontfetlock',
|
||||
id=6,
|
||||
color=[255, 102, 255],
|
||||
type='upper',
|
||||
swap=''),
|
||||
7:
|
||||
dict(
|
||||
name='Offfrontfoot',
|
||||
id=7,
|
||||
color=[255, 102, 255],
|
||||
type='upper',
|
||||
swap=''),
|
||||
8:
|
||||
dict(
|
||||
name='Shoulder',
|
||||
id=8,
|
||||
color=[255, 153, 255],
|
||||
type='upper',
|
||||
swap=''),
|
||||
9:
|
||||
dict(
|
||||
name='Midshoulder',
|
||||
id=9,
|
||||
color=[255, 153, 255],
|
||||
type='upper',
|
||||
swap=''),
|
||||
10:
|
||||
dict(
|
||||
name='Elbow', id=10, color=[255, 153, 255], type='upper', swap=''),
|
||||
11:
|
||||
dict(
|
||||
name='Girth', id=11, color=[255, 153, 255], type='upper', swap=''),
|
||||
12:
|
||||
dict(
|
||||
name='Wither', id=12, color=[255, 153, 255], type='upper',
|
||||
swap=''),
|
||||
13:
|
||||
dict(
|
||||
name='Nearhindhock',
|
||||
id=13,
|
||||
color=[255, 51, 255],
|
||||
type='lower',
|
||||
swap=''),
|
||||
14:
|
||||
dict(
|
||||
name='Nearhindfetlock',
|
||||
id=14,
|
||||
color=[255, 51, 255],
|
||||
type='lower',
|
||||
swap=''),
|
||||
15:
|
||||
dict(
|
||||
name='Nearhindfoot',
|
||||
id=15,
|
||||
color=[255, 51, 255],
|
||||
type='lower',
|
||||
swap=''),
|
||||
16:
|
||||
dict(name='Hip', id=16, color=[255, 153, 255], type='lower', swap=''),
|
||||
17:
|
||||
dict(
|
||||
name='Stifle', id=17, color=[255, 153, 255], type='lower',
|
||||
swap=''),
|
||||
18:
|
||||
dict(
|
||||
name='Offhindhock',
|
||||
id=18,
|
||||
color=[255, 51, 255],
|
||||
type='lower',
|
||||
swap=''),
|
||||
19:
|
||||
dict(
|
||||
name='Offhindfetlock',
|
||||
id=19,
|
||||
color=[255, 51, 255],
|
||||
type='lower',
|
||||
swap=''),
|
||||
20:
|
||||
dict(
|
||||
name='Offhindfoot',
|
||||
id=20,
|
||||
color=[255, 51, 255],
|
||||
type='lower',
|
||||
swap=''),
|
||||
21:
|
||||
dict(
|
||||
name='Ischium',
|
||||
id=21,
|
||||
color=[255, 153, 255],
|
||||
type='lower',
|
||||
swap='')
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('Nose', 'Eye'), id=0, color=[255, 153, 255]),
|
||||
1:
|
||||
dict(link=('Eye', 'Wither'), id=1, color=[255, 153, 255]),
|
||||
2:
|
||||
dict(link=('Wither', 'Hip'), id=2, color=[255, 153, 255]),
|
||||
3:
|
||||
dict(link=('Hip', 'Ischium'), id=3, color=[255, 153, 255]),
|
||||
4:
|
||||
dict(link=('Ischium', 'Stifle'), id=4, color=[255, 153, 255]),
|
||||
5:
|
||||
dict(link=('Stifle', 'Girth'), id=5, color=[255, 153, 255]),
|
||||
6:
|
||||
dict(link=('Girth', 'Elbow'), id=6, color=[255, 153, 255]),
|
||||
7:
|
||||
dict(link=('Elbow', 'Shoulder'), id=7, color=[255, 153, 255]),
|
||||
8:
|
||||
dict(link=('Shoulder', 'Midshoulder'), id=8, color=[255, 153, 255]),
|
||||
9:
|
||||
dict(link=('Midshoulder', 'Wither'), id=9, color=[255, 153, 255]),
|
||||
10:
|
||||
dict(
|
||||
link=('Nearknee', 'Nearfrontfetlock'),
|
||||
id=10,
|
||||
color=[255, 102, 255]),
|
||||
11:
|
||||
dict(
|
||||
link=('Nearfrontfetlock', 'Nearfrontfoot'),
|
||||
id=11,
|
||||
color=[255, 102, 255]),
|
||||
12:
|
||||
dict(
|
||||
link=('Offknee', 'Offfrontfetlock'), id=12, color=[255, 102, 255]),
|
||||
13:
|
||||
dict(
|
||||
link=('Offfrontfetlock', 'Offfrontfoot'),
|
||||
id=13,
|
||||
color=[255, 102, 255]),
|
||||
14:
|
||||
dict(
|
||||
link=('Nearhindhock', 'Nearhindfetlock'),
|
||||
id=14,
|
||||
color=[255, 51, 255]),
|
||||
15:
|
||||
dict(
|
||||
link=('Nearhindfetlock', 'Nearhindfoot'),
|
||||
id=15,
|
||||
color=[255, 51, 255]),
|
||||
16:
|
||||
dict(
|
||||
link=('Offhindhock', 'Offhindfetlock'),
|
||||
id=16,
|
||||
color=[255, 51, 255]),
|
||||
17:
|
||||
dict(
|
||||
link=('Offhindfetlock', 'Offhindfoot'),
|
||||
id=17,
|
||||
color=[255, 51, 255])
|
||||
},
|
||||
joint_weights=[1.] * 22,
|
||||
sigmas=[])
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='interhand2d',
|
||||
paper_info=dict(
|
||||
author='Moon, Gyeongsik and Yu, Shoou-I and Wen, He and '
|
||||
'Shiratori, Takaaki and Lee, Kyoung Mu',
|
||||
title='InterHand2.6M: A dataset and baseline for 3D '
|
||||
'interacting hand pose estimation from a single RGB image',
|
||||
container='arXiv',
|
||||
year='2020',
|
||||
homepage='https://mks0601.github.io/InterHand2.6M/',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(name='thumb4', id=0, color=[255, 128, 0], type='', swap=''),
|
||||
1:
|
||||
dict(name='thumb3', id=1, color=[255, 128, 0], type='', swap=''),
|
||||
2:
|
||||
dict(name='thumb2', id=2, color=[255, 128, 0], type='', swap=''),
|
||||
3:
|
||||
dict(name='thumb1', id=3, color=[255, 128, 0], type='', swap=''),
|
||||
4:
|
||||
dict(
|
||||
name='forefinger4', id=4, color=[255, 153, 255], type='', swap=''),
|
||||
5:
|
||||
dict(
|
||||
name='forefinger3', id=5, color=[255, 153, 255], type='', swap=''),
|
||||
6:
|
||||
dict(
|
||||
name='forefinger2', id=6, color=[255, 153, 255], type='', swap=''),
|
||||
7:
|
||||
dict(
|
||||
name='forefinger1', id=7, color=[255, 153, 255], type='', swap=''),
|
||||
8:
|
||||
dict(
|
||||
name='middle_finger4',
|
||||
id=8,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
9:
|
||||
dict(
|
||||
name='middle_finger3',
|
||||
id=9,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
10:
|
||||
dict(
|
||||
name='middle_finger2',
|
||||
id=10,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
11:
|
||||
dict(
|
||||
name='middle_finger1',
|
||||
id=11,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
12:
|
||||
dict(
|
||||
name='ring_finger4', id=12, color=[255, 51, 51], type='', swap=''),
|
||||
13:
|
||||
dict(
|
||||
name='ring_finger3', id=13, color=[255, 51, 51], type='', swap=''),
|
||||
14:
|
||||
dict(
|
||||
name='ring_finger2', id=14, color=[255, 51, 51], type='', swap=''),
|
||||
15:
|
||||
dict(
|
||||
name='ring_finger1', id=15, color=[255, 51, 51], type='', swap=''),
|
||||
16:
|
||||
dict(name='pinky_finger4', id=16, color=[0, 255, 0], type='', swap=''),
|
||||
17:
|
||||
dict(name='pinky_finger3', id=17, color=[0, 255, 0], type='', swap=''),
|
||||
18:
|
||||
dict(name='pinky_finger2', id=18, color=[0, 255, 0], type='', swap=''),
|
||||
19:
|
||||
dict(name='pinky_finger1', id=19, color=[0, 255, 0], type='', swap=''),
|
||||
20:
|
||||
dict(name='wrist', id=20, color=[255, 255, 255], type='', swap='')
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('wrist', 'thumb1'), id=0, color=[255, 128, 0]),
|
||||
1:
|
||||
dict(link=('thumb1', 'thumb2'), id=1, color=[255, 128, 0]),
|
||||
2:
|
||||
dict(link=('thumb2', 'thumb3'), id=2, color=[255, 128, 0]),
|
||||
3:
|
||||
dict(link=('thumb3', 'thumb4'), id=3, color=[255, 128, 0]),
|
||||
4:
|
||||
dict(link=('wrist', 'forefinger1'), id=4, color=[255, 153, 255]),
|
||||
5:
|
||||
dict(link=('forefinger1', 'forefinger2'), id=5, color=[255, 153, 255]),
|
||||
6:
|
||||
dict(link=('forefinger2', 'forefinger3'), id=6, color=[255, 153, 255]),
|
||||
7:
|
||||
dict(link=('forefinger3', 'forefinger4'), id=7, color=[255, 153, 255]),
|
||||
8:
|
||||
dict(link=('wrist', 'middle_finger1'), id=8, color=[102, 178, 255]),
|
||||
9:
|
||||
dict(
|
||||
link=('middle_finger1', 'middle_finger2'),
|
||||
id=9,
|
||||
color=[102, 178, 255]),
|
||||
10:
|
||||
dict(
|
||||
link=('middle_finger2', 'middle_finger3'),
|
||||
id=10,
|
||||
color=[102, 178, 255]),
|
||||
11:
|
||||
dict(
|
||||
link=('middle_finger3', 'middle_finger4'),
|
||||
id=11,
|
||||
color=[102, 178, 255]),
|
||||
12:
|
||||
dict(link=('wrist', 'ring_finger1'), id=12, color=[255, 51, 51]),
|
||||
13:
|
||||
dict(
|
||||
link=('ring_finger1', 'ring_finger2'), id=13, color=[255, 51, 51]),
|
||||
14:
|
||||
dict(
|
||||
link=('ring_finger2', 'ring_finger3'), id=14, color=[255, 51, 51]),
|
||||
15:
|
||||
dict(
|
||||
link=('ring_finger3', 'ring_finger4'), id=15, color=[255, 51, 51]),
|
||||
16:
|
||||
dict(link=('wrist', 'pinky_finger1'), id=16, color=[0, 255, 0]),
|
||||
17:
|
||||
dict(
|
||||
link=('pinky_finger1', 'pinky_finger2'), id=17, color=[0, 255, 0]),
|
||||
18:
|
||||
dict(
|
||||
link=('pinky_finger2', 'pinky_finger3'), id=18, color=[0, 255, 0]),
|
||||
19:
|
||||
dict(
|
||||
link=('pinky_finger3', 'pinky_finger4'), id=19, color=[0, 255, 0])
|
||||
},
|
||||
joint_weights=[1.] * 21,
|
||||
sigmas=[])
|
||||
+487
@@ -0,0 +1,487 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='interhand3d',
|
||||
paper_info=dict(
|
||||
author='Moon, Gyeongsik and Yu, Shoou-I and Wen, He and '
|
||||
'Shiratori, Takaaki and Lee, Kyoung Mu',
|
||||
title='InterHand2.6M: A dataset and baseline for 3D '
|
||||
'interacting hand pose estimation from a single RGB image',
|
||||
container='arXiv',
|
||||
year='2020',
|
||||
homepage='https://mks0601.github.io/InterHand2.6M/',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='right_thumb4',
|
||||
id=0,
|
||||
color=[255, 128, 0],
|
||||
type='',
|
||||
swap='left_thumb4'),
|
||||
1:
|
||||
dict(
|
||||
name='right_thumb3',
|
||||
id=1,
|
||||
color=[255, 128, 0],
|
||||
type='',
|
||||
swap='left_thumb3'),
|
||||
2:
|
||||
dict(
|
||||
name='right_thumb2',
|
||||
id=2,
|
||||
color=[255, 128, 0],
|
||||
type='',
|
||||
swap='left_thumb2'),
|
||||
3:
|
||||
dict(
|
||||
name='right_thumb1',
|
||||
id=3,
|
||||
color=[255, 128, 0],
|
||||
type='',
|
||||
swap='left_thumb1'),
|
||||
4:
|
||||
dict(
|
||||
name='right_forefinger4',
|
||||
id=4,
|
||||
color=[255, 153, 255],
|
||||
type='',
|
||||
swap='left_forefinger4'),
|
||||
5:
|
||||
dict(
|
||||
name='right_forefinger3',
|
||||
id=5,
|
||||
color=[255, 153, 255],
|
||||
type='',
|
||||
swap='left_forefinger3'),
|
||||
6:
|
||||
dict(
|
||||
name='right_forefinger2',
|
||||
id=6,
|
||||
color=[255, 153, 255],
|
||||
type='',
|
||||
swap='left_forefinger2'),
|
||||
7:
|
||||
dict(
|
||||
name='right_forefinger1',
|
||||
id=7,
|
||||
color=[255, 153, 255],
|
||||
type='',
|
||||
swap='left_forefinger1'),
|
||||
8:
|
||||
dict(
|
||||
name='right_middle_finger4',
|
||||
id=8,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap='left_middle_finger4'),
|
||||
9:
|
||||
dict(
|
||||
name='right_middle_finger3',
|
||||
id=9,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap='left_middle_finger3'),
|
||||
10:
|
||||
dict(
|
||||
name='right_middle_finger2',
|
||||
id=10,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap='left_middle_finger2'),
|
||||
11:
|
||||
dict(
|
||||
name='right_middle_finger1',
|
||||
id=11,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap='left_middle_finger1'),
|
||||
12:
|
||||
dict(
|
||||
name='right_ring_finger4',
|
||||
id=12,
|
||||
color=[255, 51, 51],
|
||||
type='',
|
||||
swap='left_ring_finger4'),
|
||||
13:
|
||||
dict(
|
||||
name='right_ring_finger3',
|
||||
id=13,
|
||||
color=[255, 51, 51],
|
||||
type='',
|
||||
swap='left_ring_finger3'),
|
||||
14:
|
||||
dict(
|
||||
name='right_ring_finger2',
|
||||
id=14,
|
||||
color=[255, 51, 51],
|
||||
type='',
|
||||
swap='left_ring_finger2'),
|
||||
15:
|
||||
dict(
|
||||
name='right_ring_finger1',
|
||||
id=15,
|
||||
color=[255, 51, 51],
|
||||
type='',
|
||||
swap='left_ring_finger1'),
|
||||
16:
|
||||
dict(
|
||||
name='right_pinky_finger4',
|
||||
id=16,
|
||||
color=[0, 255, 0],
|
||||
type='',
|
||||
swap='left_pinky_finger4'),
|
||||
17:
|
||||
dict(
|
||||
name='right_pinky_finger3',
|
||||
id=17,
|
||||
color=[0, 255, 0],
|
||||
type='',
|
||||
swap='left_pinky_finger3'),
|
||||
18:
|
||||
dict(
|
||||
name='right_pinky_finger2',
|
||||
id=18,
|
||||
color=[0, 255, 0],
|
||||
type='',
|
||||
swap='left_pinky_finger2'),
|
||||
19:
|
||||
dict(
|
||||
name='right_pinky_finger1',
|
||||
id=19,
|
||||
color=[0, 255, 0],
|
||||
type='',
|
||||
swap='left_pinky_finger1'),
|
||||
20:
|
||||
dict(
|
||||
name='right_wrist',
|
||||
id=20,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='left_wrist'),
|
||||
21:
|
||||
dict(
|
||||
name='left_thumb4',
|
||||
id=21,
|
||||
color=[255, 128, 0],
|
||||
type='',
|
||||
swap='right_thumb4'),
|
||||
22:
|
||||
dict(
|
||||
name='left_thumb3',
|
||||
id=22,
|
||||
color=[255, 128, 0],
|
||||
type='',
|
||||
swap='right_thumb3'),
|
||||
23:
|
||||
dict(
|
||||
name='left_thumb2',
|
||||
id=23,
|
||||
color=[255, 128, 0],
|
||||
type='',
|
||||
swap='right_thumb2'),
|
||||
24:
|
||||
dict(
|
||||
name='left_thumb1',
|
||||
id=24,
|
||||
color=[255, 128, 0],
|
||||
type='',
|
||||
swap='right_thumb1'),
|
||||
25:
|
||||
dict(
|
||||
name='left_forefinger4',
|
||||
id=25,
|
||||
color=[255, 153, 255],
|
||||
type='',
|
||||
swap='right_forefinger4'),
|
||||
26:
|
||||
dict(
|
||||
name='left_forefinger3',
|
||||
id=26,
|
||||
color=[255, 153, 255],
|
||||
type='',
|
||||
swap='right_forefinger3'),
|
||||
27:
|
||||
dict(
|
||||
name='left_forefinger2',
|
||||
id=27,
|
||||
color=[255, 153, 255],
|
||||
type='',
|
||||
swap='right_forefinger2'),
|
||||
28:
|
||||
dict(
|
||||
name='left_forefinger1',
|
||||
id=28,
|
||||
color=[255, 153, 255],
|
||||
type='',
|
||||
swap='right_forefinger1'),
|
||||
29:
|
||||
dict(
|
||||
name='left_middle_finger4',
|
||||
id=29,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap='right_middle_finger4'),
|
||||
30:
|
||||
dict(
|
||||
name='left_middle_finger3',
|
||||
id=30,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap='right_middle_finger3'),
|
||||
31:
|
||||
dict(
|
||||
name='left_middle_finger2',
|
||||
id=31,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap='right_middle_finger2'),
|
||||
32:
|
||||
dict(
|
||||
name='left_middle_finger1',
|
||||
id=32,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap='right_middle_finger1'),
|
||||
33:
|
||||
dict(
|
||||
name='left_ring_finger4',
|
||||
id=33,
|
||||
color=[255, 51, 51],
|
||||
type='',
|
||||
swap='right_ring_finger4'),
|
||||
34:
|
||||
dict(
|
||||
name='left_ring_finger3',
|
||||
id=34,
|
||||
color=[255, 51, 51],
|
||||
type='',
|
||||
swap='right_ring_finger3'),
|
||||
35:
|
||||
dict(
|
||||
name='left_ring_finger2',
|
||||
id=35,
|
||||
color=[255, 51, 51],
|
||||
type='',
|
||||
swap='right_ring_finger2'),
|
||||
36:
|
||||
dict(
|
||||
name='left_ring_finger1',
|
||||
id=36,
|
||||
color=[255, 51, 51],
|
||||
type='',
|
||||
swap='right_ring_finger1'),
|
||||
37:
|
||||
dict(
|
||||
name='left_pinky_finger4',
|
||||
id=37,
|
||||
color=[0, 255, 0],
|
||||
type='',
|
||||
swap='right_pinky_finger4'),
|
||||
38:
|
||||
dict(
|
||||
name='left_pinky_finger3',
|
||||
id=38,
|
||||
color=[0, 255, 0],
|
||||
type='',
|
||||
swap='right_pinky_finger3'),
|
||||
39:
|
||||
dict(
|
||||
name='left_pinky_finger2',
|
||||
id=39,
|
||||
color=[0, 255, 0],
|
||||
type='',
|
||||
swap='right_pinky_finger2'),
|
||||
40:
|
||||
dict(
|
||||
name='left_pinky_finger1',
|
||||
id=40,
|
||||
color=[0, 255, 0],
|
||||
type='',
|
||||
swap='right_pinky_finger1'),
|
||||
41:
|
||||
dict(
|
||||
name='left_wrist',
|
||||
id=41,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='right_wrist'),
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('right_wrist', 'right_thumb1'), id=0, color=[255, 128, 0]),
|
||||
1:
|
||||
dict(link=('right_thumb1', 'right_thumb2'), id=1, color=[255, 128, 0]),
|
||||
2:
|
||||
dict(link=('right_thumb2', 'right_thumb3'), id=2, color=[255, 128, 0]),
|
||||
3:
|
||||
dict(link=('right_thumb3', 'right_thumb4'), id=3, color=[255, 128, 0]),
|
||||
4:
|
||||
dict(
|
||||
link=('right_wrist', 'right_forefinger1'),
|
||||
id=4,
|
||||
color=[255, 153, 255]),
|
||||
5:
|
||||
dict(
|
||||
link=('right_forefinger1', 'right_forefinger2'),
|
||||
id=5,
|
||||
color=[255, 153, 255]),
|
||||
6:
|
||||
dict(
|
||||
link=('right_forefinger2', 'right_forefinger3'),
|
||||
id=6,
|
||||
color=[255, 153, 255]),
|
||||
7:
|
||||
dict(
|
||||
link=('right_forefinger3', 'right_forefinger4'),
|
||||
id=7,
|
||||
color=[255, 153, 255]),
|
||||
8:
|
||||
dict(
|
||||
link=('right_wrist', 'right_middle_finger1'),
|
||||
id=8,
|
||||
color=[102, 178, 255]),
|
||||
9:
|
||||
dict(
|
||||
link=('right_middle_finger1', 'right_middle_finger2'),
|
||||
id=9,
|
||||
color=[102, 178, 255]),
|
||||
10:
|
||||
dict(
|
||||
link=('right_middle_finger2', 'right_middle_finger3'),
|
||||
id=10,
|
||||
color=[102, 178, 255]),
|
||||
11:
|
||||
dict(
|
||||
link=('right_middle_finger3', 'right_middle_finger4'),
|
||||
id=11,
|
||||
color=[102, 178, 255]),
|
||||
12:
|
||||
dict(
|
||||
link=('right_wrist', 'right_ring_finger1'),
|
||||
id=12,
|
||||
color=[255, 51, 51]),
|
||||
13:
|
||||
dict(
|
||||
link=('right_ring_finger1', 'right_ring_finger2'),
|
||||
id=13,
|
||||
color=[255, 51, 51]),
|
||||
14:
|
||||
dict(
|
||||
link=('right_ring_finger2', 'right_ring_finger3'),
|
||||
id=14,
|
||||
color=[255, 51, 51]),
|
||||
15:
|
||||
dict(
|
||||
link=('right_ring_finger3', 'right_ring_finger4'),
|
||||
id=15,
|
||||
color=[255, 51, 51]),
|
||||
16:
|
||||
dict(
|
||||
link=('right_wrist', 'right_pinky_finger1'),
|
||||
id=16,
|
||||
color=[0, 255, 0]),
|
||||
17:
|
||||
dict(
|
||||
link=('right_pinky_finger1', 'right_pinky_finger2'),
|
||||
id=17,
|
||||
color=[0, 255, 0]),
|
||||
18:
|
||||
dict(
|
||||
link=('right_pinky_finger2', 'right_pinky_finger3'),
|
||||
id=18,
|
||||
color=[0, 255, 0]),
|
||||
19:
|
||||
dict(
|
||||
link=('right_pinky_finger3', 'right_pinky_finger4'),
|
||||
id=19,
|
||||
color=[0, 255, 0]),
|
||||
20:
|
||||
dict(link=('left_wrist', 'left_thumb1'), id=20, color=[255, 128, 0]),
|
||||
21:
|
||||
dict(link=('left_thumb1', 'left_thumb2'), id=21, color=[255, 128, 0]),
|
||||
22:
|
||||
dict(link=('left_thumb2', 'left_thumb3'), id=22, color=[255, 128, 0]),
|
||||
23:
|
||||
dict(link=('left_thumb3', 'left_thumb4'), id=23, color=[255, 128, 0]),
|
||||
24:
|
||||
dict(
|
||||
link=('left_wrist', 'left_forefinger1'),
|
||||
id=24,
|
||||
color=[255, 153, 255]),
|
||||
25:
|
||||
dict(
|
||||
link=('left_forefinger1', 'left_forefinger2'),
|
||||
id=25,
|
||||
color=[255, 153, 255]),
|
||||
26:
|
||||
dict(
|
||||
link=('left_forefinger2', 'left_forefinger3'),
|
||||
id=26,
|
||||
color=[255, 153, 255]),
|
||||
27:
|
||||
dict(
|
||||
link=('left_forefinger3', 'left_forefinger4'),
|
||||
id=27,
|
||||
color=[255, 153, 255]),
|
||||
28:
|
||||
dict(
|
||||
link=('left_wrist', 'left_middle_finger1'),
|
||||
id=28,
|
||||
color=[102, 178, 255]),
|
||||
29:
|
||||
dict(
|
||||
link=('left_middle_finger1', 'left_middle_finger2'),
|
||||
id=29,
|
||||
color=[102, 178, 255]),
|
||||
30:
|
||||
dict(
|
||||
link=('left_middle_finger2', 'left_middle_finger3'),
|
||||
id=30,
|
||||
color=[102, 178, 255]),
|
||||
31:
|
||||
dict(
|
||||
link=('left_middle_finger3', 'left_middle_finger4'),
|
||||
id=31,
|
||||
color=[102, 178, 255]),
|
||||
32:
|
||||
dict(
|
||||
link=('left_wrist', 'left_ring_finger1'),
|
||||
id=32,
|
||||
color=[255, 51, 51]),
|
||||
33:
|
||||
dict(
|
||||
link=('left_ring_finger1', 'left_ring_finger2'),
|
||||
id=33,
|
||||
color=[255, 51, 51]),
|
||||
34:
|
||||
dict(
|
||||
link=('left_ring_finger2', 'left_ring_finger3'),
|
||||
id=34,
|
||||
color=[255, 51, 51]),
|
||||
35:
|
||||
dict(
|
||||
link=('left_ring_finger3', 'left_ring_finger4'),
|
||||
id=35,
|
||||
color=[255, 51, 51]),
|
||||
36:
|
||||
dict(
|
||||
link=('left_wrist', 'left_pinky_finger1'),
|
||||
id=36,
|
||||
color=[0, 255, 0]),
|
||||
37:
|
||||
dict(
|
||||
link=('left_pinky_finger1', 'left_pinky_finger2'),
|
||||
id=37,
|
||||
color=[0, 255, 0]),
|
||||
38:
|
||||
dict(
|
||||
link=('left_pinky_finger2', 'left_pinky_finger3'),
|
||||
id=38,
|
||||
color=[0, 255, 0]),
|
||||
39:
|
||||
dict(
|
||||
link=('left_pinky_finger3', 'left_pinky_finger4'),
|
||||
id=39,
|
||||
color=[0, 255, 0]),
|
||||
},
|
||||
joint_weights=[1.] * 42,
|
||||
sigmas=[])
|
||||
@@ -0,0 +1,129 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='jhmdb',
|
||||
paper_info=dict(
|
||||
author='H. Jhuang and J. Gall and S. Zuffi and '
|
||||
'C. Schmid and M. J. Black',
|
||||
title='Towards understanding action recognition',
|
||||
container='International Conf. on Computer Vision (ICCV)',
|
||||
year='2013',
|
||||
homepage='http://jhmdb.is.tue.mpg.de/dataset',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(name='neck', id=0, color=[255, 128, 0], type='upper', swap=''),
|
||||
1:
|
||||
dict(name='belly', id=1, color=[255, 128, 0], type='upper', swap=''),
|
||||
2:
|
||||
dict(name='head', id=2, color=[255, 128, 0], type='upper', swap=''),
|
||||
3:
|
||||
dict(
|
||||
name='right_shoulder',
|
||||
id=3,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='left_shoulder'),
|
||||
4:
|
||||
dict(
|
||||
name='left_shoulder',
|
||||
id=4,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_shoulder'),
|
||||
5:
|
||||
dict(
|
||||
name='right_hip',
|
||||
id=5,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='left_hip'),
|
||||
6:
|
||||
dict(
|
||||
name='left_hip',
|
||||
id=6,
|
||||
color=[51, 153, 255],
|
||||
type='lower',
|
||||
swap='right_hip'),
|
||||
7:
|
||||
dict(
|
||||
name='right_elbow',
|
||||
id=7,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='left_elbow'),
|
||||
8:
|
||||
dict(
|
||||
name='left_elbow',
|
||||
id=8,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='right_elbow'),
|
||||
9:
|
||||
dict(
|
||||
name='right_knee',
|
||||
id=9,
|
||||
color=[51, 153, 255],
|
||||
type='lower',
|
||||
swap='left_knee'),
|
||||
10:
|
||||
dict(
|
||||
name='left_knee',
|
||||
id=10,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='right_knee'),
|
||||
11:
|
||||
dict(
|
||||
name='right_wrist',
|
||||
id=11,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_wrist'),
|
||||
12:
|
||||
dict(
|
||||
name='left_wrist',
|
||||
id=12,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='right_wrist'),
|
||||
13:
|
||||
dict(
|
||||
name='right_ankle',
|
||||
id=13,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='left_ankle'),
|
||||
14:
|
||||
dict(
|
||||
name='left_ankle',
|
||||
id=14,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_ankle')
|
||||
},
|
||||
skeleton_info={
|
||||
0: dict(link=('right_ankle', 'right_knee'), id=0, color=[255, 128, 0]),
|
||||
1: dict(link=('right_knee', 'right_hip'), id=1, color=[255, 128, 0]),
|
||||
2: dict(link=('right_hip', 'belly'), id=2, color=[255, 128, 0]),
|
||||
3: dict(link=('belly', 'left_hip'), id=3, color=[0, 255, 0]),
|
||||
4: dict(link=('left_hip', 'left_knee'), id=4, color=[0, 255, 0]),
|
||||
5: dict(link=('left_knee', 'left_ankle'), id=5, color=[0, 255, 0]),
|
||||
6: dict(link=('belly', 'neck'), id=6, color=[51, 153, 255]),
|
||||
7: dict(link=('neck', 'head'), id=7, color=[51, 153, 255]),
|
||||
8: dict(link=('neck', 'right_shoulder'), id=8, color=[255, 128, 0]),
|
||||
9: dict(
|
||||
link=('right_shoulder', 'right_elbow'), id=9, color=[255, 128, 0]),
|
||||
10:
|
||||
dict(link=('right_elbow', 'right_wrist'), id=10, color=[255, 128, 0]),
|
||||
11: dict(link=('neck', 'left_shoulder'), id=11, color=[0, 255, 0]),
|
||||
12:
|
||||
dict(link=('left_shoulder', 'left_elbow'), id=12, color=[0, 255, 0]),
|
||||
13: dict(link=('left_elbow', 'left_wrist'), id=13, color=[0, 255, 0])
|
||||
},
|
||||
joint_weights=[
|
||||
1., 1., 1., 1., 1., 1., 1., 1.2, 1.2, 1.2, 1.2, 1.5, 1.5, 1.5, 1.5
|
||||
],
|
||||
# Adapted from COCO dataset.
|
||||
sigmas=[
|
||||
0.025, 0.107, 0.025, 0.079, 0.079, 0.107, 0.107, 0.072, 0.072, 0.087,
|
||||
0.087, 0.062, 0.062, 0.089, 0.089
|
||||
])
|
||||
@@ -0,0 +1,263 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='locust',
|
||||
paper_info=dict(
|
||||
author='Graving, Jacob M and Chae, Daniel and Naik, Hemal and '
|
||||
'Li, Liang and Koger, Benjamin and Costelloe, Blair R and '
|
||||
'Couzin, Iain D',
|
||||
title='DeepPoseKit, a software toolkit for fast and robust '
|
||||
'animal pose estimation using deep learning',
|
||||
container='Elife',
|
||||
year='2019',
|
||||
homepage='https://github.com/jgraving/DeepPoseKit-Data',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(name='head', id=0, color=[255, 255, 255], type='', swap=''),
|
||||
1:
|
||||
dict(name='neck', id=1, color=[255, 255, 255], type='', swap=''),
|
||||
2:
|
||||
dict(name='thorax', id=2, color=[255, 255, 255], type='', swap=''),
|
||||
3:
|
||||
dict(name='abdomen1', id=3, color=[255, 255, 255], type='', swap=''),
|
||||
4:
|
||||
dict(name='abdomen2', id=4, color=[255, 255, 255], type='', swap=''),
|
||||
5:
|
||||
dict(
|
||||
name='anttipL',
|
||||
id=5,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='anttipR'),
|
||||
6:
|
||||
dict(
|
||||
name='antbaseL',
|
||||
id=6,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='antbaseR'),
|
||||
7:
|
||||
dict(name='eyeL', id=7, color=[255, 255, 255], type='', swap='eyeR'),
|
||||
8:
|
||||
dict(
|
||||
name='forelegL1',
|
||||
id=8,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='forelegR1'),
|
||||
9:
|
||||
dict(
|
||||
name='forelegL2',
|
||||
id=9,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='forelegR2'),
|
||||
10:
|
||||
dict(
|
||||
name='forelegL3',
|
||||
id=10,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='forelegR3'),
|
||||
11:
|
||||
dict(
|
||||
name='forelegL4',
|
||||
id=11,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='forelegR4'),
|
||||
12:
|
||||
dict(
|
||||
name='midlegL1',
|
||||
id=12,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='midlegR1'),
|
||||
13:
|
||||
dict(
|
||||
name='midlegL2',
|
||||
id=13,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='midlegR2'),
|
||||
14:
|
||||
dict(
|
||||
name='midlegL3',
|
||||
id=14,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='midlegR3'),
|
||||
15:
|
||||
dict(
|
||||
name='midlegL4',
|
||||
id=15,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='midlegR4'),
|
||||
16:
|
||||
dict(
|
||||
name='hindlegL1',
|
||||
id=16,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='hindlegR1'),
|
||||
17:
|
||||
dict(
|
||||
name='hindlegL2',
|
||||
id=17,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='hindlegR2'),
|
||||
18:
|
||||
dict(
|
||||
name='hindlegL3',
|
||||
id=18,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='hindlegR3'),
|
||||
19:
|
||||
dict(
|
||||
name='hindlegL4',
|
||||
id=19,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='hindlegR4'),
|
||||
20:
|
||||
dict(
|
||||
name='anttipR',
|
||||
id=20,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='anttipL'),
|
||||
21:
|
||||
dict(
|
||||
name='antbaseR',
|
||||
id=21,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='antbaseL'),
|
||||
22:
|
||||
dict(name='eyeR', id=22, color=[255, 255, 255], type='', swap='eyeL'),
|
||||
23:
|
||||
dict(
|
||||
name='forelegR1',
|
||||
id=23,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='forelegL1'),
|
||||
24:
|
||||
dict(
|
||||
name='forelegR2',
|
||||
id=24,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='forelegL2'),
|
||||
25:
|
||||
dict(
|
||||
name='forelegR3',
|
||||
id=25,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='forelegL3'),
|
||||
26:
|
||||
dict(
|
||||
name='forelegR4',
|
||||
id=26,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='forelegL4'),
|
||||
27:
|
||||
dict(
|
||||
name='midlegR1',
|
||||
id=27,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='midlegL1'),
|
||||
28:
|
||||
dict(
|
||||
name='midlegR2',
|
||||
id=28,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='midlegL2'),
|
||||
29:
|
||||
dict(
|
||||
name='midlegR3',
|
||||
id=29,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='midlegL3'),
|
||||
30:
|
||||
dict(
|
||||
name='midlegR4',
|
||||
id=30,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='midlegL4'),
|
||||
31:
|
||||
dict(
|
||||
name='hindlegR1',
|
||||
id=31,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='hindlegL1'),
|
||||
32:
|
||||
dict(
|
||||
name='hindlegR2',
|
||||
id=32,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='hindlegL2'),
|
||||
33:
|
||||
dict(
|
||||
name='hindlegR3',
|
||||
id=33,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='hindlegL3'),
|
||||
34:
|
||||
dict(
|
||||
name='hindlegR4',
|
||||
id=34,
|
||||
color=[255, 255, 255],
|
||||
type='',
|
||||
swap='hindlegL4')
|
||||
},
|
||||
skeleton_info={
|
||||
0: dict(link=('neck', 'head'), id=0, color=[255, 255, 255]),
|
||||
1: dict(link=('thorax', 'neck'), id=1, color=[255, 255, 255]),
|
||||
2: dict(link=('abdomen1', 'thorax'), id=2, color=[255, 255, 255]),
|
||||
3: dict(link=('abdomen2', 'abdomen1'), id=3, color=[255, 255, 255]),
|
||||
4: dict(link=('antbaseL', 'anttipL'), id=4, color=[255, 255, 255]),
|
||||
5: dict(link=('eyeL', 'antbaseL'), id=5, color=[255, 255, 255]),
|
||||
6: dict(link=('forelegL2', 'forelegL1'), id=6, color=[255, 255, 255]),
|
||||
7: dict(link=('forelegL3', 'forelegL2'), id=7, color=[255, 255, 255]),
|
||||
8: dict(link=('forelegL4', 'forelegL3'), id=8, color=[255, 255, 255]),
|
||||
9: dict(link=('midlegL2', 'midlegL1'), id=9, color=[255, 255, 255]),
|
||||
10: dict(link=('midlegL3', 'midlegL2'), id=10, color=[255, 255, 255]),
|
||||
11: dict(link=('midlegL4', 'midlegL3'), id=11, color=[255, 255, 255]),
|
||||
12:
|
||||
dict(link=('hindlegL2', 'hindlegL1'), id=12, color=[255, 255, 255]),
|
||||
13:
|
||||
dict(link=('hindlegL3', 'hindlegL2'), id=13, color=[255, 255, 255]),
|
||||
14:
|
||||
dict(link=('hindlegL4', 'hindlegL3'), id=14, color=[255, 255, 255]),
|
||||
15: dict(link=('antbaseR', 'anttipR'), id=15, color=[255, 255, 255]),
|
||||
16: dict(link=('eyeR', 'antbaseR'), id=16, color=[255, 255, 255]),
|
||||
17:
|
||||
dict(link=('forelegR2', 'forelegR1'), id=17, color=[255, 255, 255]),
|
||||
18:
|
||||
dict(link=('forelegR3', 'forelegR2'), id=18, color=[255, 255, 255]),
|
||||
19:
|
||||
dict(link=('forelegR4', 'forelegR3'), id=19, color=[255, 255, 255]),
|
||||
20: dict(link=('midlegR2', 'midlegR1'), id=20, color=[255, 255, 255]),
|
||||
21: dict(link=('midlegR3', 'midlegR2'), id=21, color=[255, 255, 255]),
|
||||
22: dict(link=('midlegR4', 'midlegR3'), id=22, color=[255, 255, 255]),
|
||||
23:
|
||||
dict(link=('hindlegR2', 'hindlegR1'), id=23, color=[255, 255, 255]),
|
||||
24:
|
||||
dict(link=('hindlegR3', 'hindlegR2'), id=24, color=[255, 255, 255]),
|
||||
25:
|
||||
dict(link=('hindlegR4', 'hindlegR3'), id=25, color=[255, 255, 255])
|
||||
},
|
||||
joint_weights=[1.] * 35,
|
||||
sigmas=[])
|
||||
@@ -0,0 +1,183 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='macaque',
|
||||
paper_info=dict(
|
||||
author='Labuguen, Rollyn and Matsumoto, Jumpei and '
|
||||
'Negrete, Salvador and Nishimaru, Hiroshi and '
|
||||
'Nishijo, Hisao and Takada, Masahiko and '
|
||||
'Go, Yasuhiro and Inoue, Ken-ichi and Shibata, Tomohiro',
|
||||
title='MacaquePose: A novel "in the wild" macaque monkey pose dataset '
|
||||
'for markerless motion capture',
|
||||
container='bioRxiv',
|
||||
year='2020',
|
||||
homepage='http://www.pri.kyoto-u.ac.jp/datasets/'
|
||||
'macaquepose/index.html',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(name='nose', id=0, color=[51, 153, 255], type='upper', swap=''),
|
||||
1:
|
||||
dict(
|
||||
name='left_eye',
|
||||
id=1,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='right_eye'),
|
||||
2:
|
||||
dict(
|
||||
name='right_eye',
|
||||
id=2,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='left_eye'),
|
||||
3:
|
||||
dict(
|
||||
name='left_ear',
|
||||
id=3,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='right_ear'),
|
||||
4:
|
||||
dict(
|
||||
name='right_ear',
|
||||
id=4,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='left_ear'),
|
||||
5:
|
||||
dict(
|
||||
name='left_shoulder',
|
||||
id=5,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_shoulder'),
|
||||
6:
|
||||
dict(
|
||||
name='right_shoulder',
|
||||
id=6,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_shoulder'),
|
||||
7:
|
||||
dict(
|
||||
name='left_elbow',
|
||||
id=7,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_elbow'),
|
||||
8:
|
||||
dict(
|
||||
name='right_elbow',
|
||||
id=8,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_elbow'),
|
||||
9:
|
||||
dict(
|
||||
name='left_wrist',
|
||||
id=9,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_wrist'),
|
||||
10:
|
||||
dict(
|
||||
name='right_wrist',
|
||||
id=10,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_wrist'),
|
||||
11:
|
||||
dict(
|
||||
name='left_hip',
|
||||
id=11,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_hip'),
|
||||
12:
|
||||
dict(
|
||||
name='right_hip',
|
||||
id=12,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_hip'),
|
||||
13:
|
||||
dict(
|
||||
name='left_knee',
|
||||
id=13,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_knee'),
|
||||
14:
|
||||
dict(
|
||||
name='right_knee',
|
||||
id=14,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_knee'),
|
||||
15:
|
||||
dict(
|
||||
name='left_ankle',
|
||||
id=15,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_ankle'),
|
||||
16:
|
||||
dict(
|
||||
name='right_ankle',
|
||||
id=16,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_ankle')
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('left_ankle', 'left_knee'), id=0, color=[0, 255, 0]),
|
||||
1:
|
||||
dict(link=('left_knee', 'left_hip'), id=1, color=[0, 255, 0]),
|
||||
2:
|
||||
dict(link=('right_ankle', 'right_knee'), id=2, color=[255, 128, 0]),
|
||||
3:
|
||||
dict(link=('right_knee', 'right_hip'), id=3, color=[255, 128, 0]),
|
||||
4:
|
||||
dict(link=('left_hip', 'right_hip'), id=4, color=[51, 153, 255]),
|
||||
5:
|
||||
dict(link=('left_shoulder', 'left_hip'), id=5, color=[51, 153, 255]),
|
||||
6:
|
||||
dict(link=('right_shoulder', 'right_hip'), id=6, color=[51, 153, 255]),
|
||||
7:
|
||||
dict(
|
||||
link=('left_shoulder', 'right_shoulder'),
|
||||
id=7,
|
||||
color=[51, 153, 255]),
|
||||
8:
|
||||
dict(link=('left_shoulder', 'left_elbow'), id=8, color=[0, 255, 0]),
|
||||
9:
|
||||
dict(
|
||||
link=('right_shoulder', 'right_elbow'), id=9, color=[255, 128, 0]),
|
||||
10:
|
||||
dict(link=('left_elbow', 'left_wrist'), id=10, color=[0, 255, 0]),
|
||||
11:
|
||||
dict(link=('right_elbow', 'right_wrist'), id=11, color=[255, 128, 0]),
|
||||
12:
|
||||
dict(link=('left_eye', 'right_eye'), id=12, color=[51, 153, 255]),
|
||||
13:
|
||||
dict(link=('nose', 'left_eye'), id=13, color=[51, 153, 255]),
|
||||
14:
|
||||
dict(link=('nose', 'right_eye'), id=14, color=[51, 153, 255]),
|
||||
15:
|
||||
dict(link=('left_eye', 'left_ear'), id=15, color=[51, 153, 255]),
|
||||
16:
|
||||
dict(link=('right_eye', 'right_ear'), id=16, color=[51, 153, 255]),
|
||||
17:
|
||||
dict(link=('left_ear', 'left_shoulder'), id=17, color=[51, 153, 255]),
|
||||
18:
|
||||
dict(
|
||||
link=('right_ear', 'right_shoulder'), id=18, color=[51, 153, 255])
|
||||
},
|
||||
joint_weights=[
|
||||
1., 1., 1., 1., 1., 1., 1., 1.2, 1.2, 1.5, 1.5, 1., 1., 1.2, 1.2, 1.5,
|
||||
1.5
|
||||
],
|
||||
sigmas=[
|
||||
0.026, 0.025, 0.025, 0.035, 0.035, 0.079, 0.079, 0.072, 0.072, 0.062,
|
||||
0.062, 0.107, 0.107, 0.087, 0.087, 0.089, 0.089
|
||||
])
|
||||
@@ -0,0 +1,156 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='mhp',
|
||||
paper_info=dict(
|
||||
author='Zhao, Jian and Li, Jianshu and Cheng, Yu and '
|
||||
'Sim, Terence and Yan, Shuicheng and Feng, Jiashi',
|
||||
title='Understanding humans in crowded scenes: '
|
||||
'Deep nested adversarial learning and a '
|
||||
'new benchmark for multi-human parsing',
|
||||
container='Proceedings of the 26th ACM '
|
||||
'international conference on Multimedia',
|
||||
year='2018',
|
||||
homepage='https://lv-mhp.github.io/dataset',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='right_ankle',
|
||||
id=0,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_ankle'),
|
||||
1:
|
||||
dict(
|
||||
name='right_knee',
|
||||
id=1,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_knee'),
|
||||
2:
|
||||
dict(
|
||||
name='right_hip',
|
||||
id=2,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_hip'),
|
||||
3:
|
||||
dict(
|
||||
name='left_hip',
|
||||
id=3,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_hip'),
|
||||
4:
|
||||
dict(
|
||||
name='left_knee',
|
||||
id=4,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_knee'),
|
||||
5:
|
||||
dict(
|
||||
name='left_ankle',
|
||||
id=5,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_ankle'),
|
||||
6:
|
||||
dict(name='pelvis', id=6, color=[51, 153, 255], type='lower', swap=''),
|
||||
7:
|
||||
dict(name='thorax', id=7, color=[51, 153, 255], type='upper', swap=''),
|
||||
8:
|
||||
dict(
|
||||
name='upper_neck',
|
||||
id=8,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap=''),
|
||||
9:
|
||||
dict(
|
||||
name='head_top', id=9, color=[51, 153, 255], type='upper',
|
||||
swap=''),
|
||||
10:
|
||||
dict(
|
||||
name='right_wrist',
|
||||
id=10,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_wrist'),
|
||||
11:
|
||||
dict(
|
||||
name='right_elbow',
|
||||
id=11,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_elbow'),
|
||||
12:
|
||||
dict(
|
||||
name='right_shoulder',
|
||||
id=12,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_shoulder'),
|
||||
13:
|
||||
dict(
|
||||
name='left_shoulder',
|
||||
id=13,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_shoulder'),
|
||||
14:
|
||||
dict(
|
||||
name='left_elbow',
|
||||
id=14,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_elbow'),
|
||||
15:
|
||||
dict(
|
||||
name='left_wrist',
|
||||
id=15,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_wrist')
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('right_ankle', 'right_knee'), id=0, color=[255, 128, 0]),
|
||||
1:
|
||||
dict(link=('right_knee', 'right_hip'), id=1, color=[255, 128, 0]),
|
||||
2:
|
||||
dict(link=('right_hip', 'pelvis'), id=2, color=[255, 128, 0]),
|
||||
3:
|
||||
dict(link=('pelvis', 'left_hip'), id=3, color=[0, 255, 0]),
|
||||
4:
|
||||
dict(link=('left_hip', 'left_knee'), id=4, color=[0, 255, 0]),
|
||||
5:
|
||||
dict(link=('left_knee', 'left_ankle'), id=5, color=[0, 255, 0]),
|
||||
6:
|
||||
dict(link=('pelvis', 'thorax'), id=6, color=[51, 153, 255]),
|
||||
7:
|
||||
dict(link=('thorax', 'upper_neck'), id=7, color=[51, 153, 255]),
|
||||
8:
|
||||
dict(link=('upper_neck', 'head_top'), id=8, color=[51, 153, 255]),
|
||||
9:
|
||||
dict(link=('upper_neck', 'right_shoulder'), id=9, color=[255, 128, 0]),
|
||||
10:
|
||||
dict(
|
||||
link=('right_shoulder', 'right_elbow'), id=10, color=[255, 128,
|
||||
0]),
|
||||
11:
|
||||
dict(link=('right_elbow', 'right_wrist'), id=11, color=[255, 128, 0]),
|
||||
12:
|
||||
dict(link=('upper_neck', 'left_shoulder'), id=12, color=[0, 255, 0]),
|
||||
13:
|
||||
dict(link=('left_shoulder', 'left_elbow'), id=13, color=[0, 255, 0]),
|
||||
14:
|
||||
dict(link=('left_elbow', 'left_wrist'), id=14, color=[0, 255, 0])
|
||||
},
|
||||
joint_weights=[
|
||||
1.5, 1.2, 1., 1., 1.2, 1.5, 1., 1., 1., 1., 1.5, 1.2, 1., 1., 1.2, 1.5
|
||||
],
|
||||
# Adapted from COCO dataset.
|
||||
sigmas=[
|
||||
0.089, 0.083, 0.107, 0.107, 0.083, 0.089, 0.026, 0.026, 0.026, 0.026,
|
||||
0.062, 0.072, 0.179, 0.179, 0.072, 0.062
|
||||
])
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='mpi_inf_3dhp',
|
||||
paper_info=dict(
|
||||
author='ehta, Dushyant and Rhodin, Helge and Casas, Dan and '
|
||||
'Fua, Pascal and Sotnychenko, Oleksandr and Xu, Weipeng and '
|
||||
'Theobalt, Christian',
|
||||
title='Monocular 3D Human Pose Estimation In The Wild Using Improved '
|
||||
'CNN Supervision',
|
||||
container='2017 international conference on 3D vision (3DV)',
|
||||
year='2017',
|
||||
homepage='http://gvv.mpi-inf.mpg.de/3dhp-dataset',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='head_top', id=0, color=[51, 153, 255], type='upper',
|
||||
swap=''),
|
||||
1:
|
||||
dict(name='neck', id=1, color=[51, 153, 255], type='upper', swap=''),
|
||||
2:
|
||||
dict(
|
||||
name='right_shoulder',
|
||||
id=2,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_shoulder'),
|
||||
3:
|
||||
dict(
|
||||
name='right_elbow',
|
||||
id=3,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_elbow'),
|
||||
4:
|
||||
dict(
|
||||
name='right_wrist',
|
||||
id=4,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_wrist'),
|
||||
5:
|
||||
dict(
|
||||
name='left_shoulder',
|
||||
id=5,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_shoulder'),
|
||||
6:
|
||||
dict(
|
||||
name='left_elbow',
|
||||
id=6,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_elbow'),
|
||||
7:
|
||||
dict(
|
||||
name='left_wrist',
|
||||
id=7,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_wrist'),
|
||||
8:
|
||||
dict(
|
||||
name='right_hip',
|
||||
id=8,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_hip'),
|
||||
9:
|
||||
dict(
|
||||
name='right_knee',
|
||||
id=9,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_knee'),
|
||||
10:
|
||||
dict(
|
||||
name='right_ankle',
|
||||
id=10,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_ankle'),
|
||||
11:
|
||||
dict(
|
||||
name='left_hip',
|
||||
id=11,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_hip'),
|
||||
12:
|
||||
dict(
|
||||
name='left_knee',
|
||||
id=12,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_knee'),
|
||||
13:
|
||||
dict(
|
||||
name='left_ankle',
|
||||
id=13,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_ankle'),
|
||||
14:
|
||||
dict(name='root', id=14, color=[51, 153, 255], type='lower', swap=''),
|
||||
15:
|
||||
dict(name='spine', id=15, color=[51, 153, 255], type='upper', swap=''),
|
||||
16:
|
||||
dict(name='head', id=16, color=[51, 153, 255], type='upper', swap='')
|
||||
},
|
||||
skeleton_info={
|
||||
0: dict(link=('neck', 'right_shoulder'), id=0, color=[255, 128, 0]),
|
||||
1: dict(
|
||||
link=('right_shoulder', 'right_elbow'), id=1, color=[255, 128, 0]),
|
||||
2:
|
||||
dict(link=('right_elbow', 'right_wrist'), id=2, color=[255, 128, 0]),
|
||||
3: dict(link=('neck', 'left_shoulder'), id=3, color=[0, 255, 0]),
|
||||
4: dict(link=('left_shoulder', 'left_elbow'), id=4, color=[0, 255, 0]),
|
||||
5: dict(link=('left_elbow', 'left_wrist'), id=5, color=[0, 255, 0]),
|
||||
6: dict(link=('root', 'right_hip'), id=6, color=[255, 128, 0]),
|
||||
7: dict(link=('right_hip', 'right_knee'), id=7, color=[255, 128, 0]),
|
||||
8: dict(link=('right_knee', 'right_ankle'), id=8, color=[255, 128, 0]),
|
||||
9: dict(link=('root', 'left_hip'), id=9, color=[0, 255, 0]),
|
||||
10: dict(link=('left_hip', 'left_knee'), id=10, color=[0, 255, 0]),
|
||||
11: dict(link=('left_knee', 'left_ankle'), id=11, color=[0, 255, 0]),
|
||||
12: dict(link=('head_top', 'head'), id=12, color=[51, 153, 255]),
|
||||
13: dict(link=('head', 'neck'), id=13, color=[51, 153, 255]),
|
||||
14: dict(link=('neck', 'spine'), id=14, color=[51, 153, 255]),
|
||||
15: dict(link=('spine', 'root'), id=15, color=[51, 153, 255])
|
||||
},
|
||||
joint_weights=[1.] * 17,
|
||||
sigmas=[])
|
||||
@@ -0,0 +1,155 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='mpii',
|
||||
paper_info=dict(
|
||||
author='Mykhaylo Andriluka and Leonid Pishchulin and '
|
||||
'Peter Gehler and Schiele, Bernt',
|
||||
title='2D Human Pose Estimation: New Benchmark and '
|
||||
'State of the Art Analysis',
|
||||
container='IEEE Conference on Computer Vision and '
|
||||
'Pattern Recognition (CVPR)',
|
||||
year='2014',
|
||||
homepage='http://human-pose.mpi-inf.mpg.de/',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='right_ankle',
|
||||
id=0,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_ankle'),
|
||||
1:
|
||||
dict(
|
||||
name='right_knee',
|
||||
id=1,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_knee'),
|
||||
2:
|
||||
dict(
|
||||
name='right_hip',
|
||||
id=2,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_hip'),
|
||||
3:
|
||||
dict(
|
||||
name='left_hip',
|
||||
id=3,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_hip'),
|
||||
4:
|
||||
dict(
|
||||
name='left_knee',
|
||||
id=4,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_knee'),
|
||||
5:
|
||||
dict(
|
||||
name='left_ankle',
|
||||
id=5,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_ankle'),
|
||||
6:
|
||||
dict(name='pelvis', id=6, color=[51, 153, 255], type='lower', swap=''),
|
||||
7:
|
||||
dict(name='thorax', id=7, color=[51, 153, 255], type='upper', swap=''),
|
||||
8:
|
||||
dict(
|
||||
name='upper_neck',
|
||||
id=8,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap=''),
|
||||
9:
|
||||
dict(
|
||||
name='head_top', id=9, color=[51, 153, 255], type='upper',
|
||||
swap=''),
|
||||
10:
|
||||
dict(
|
||||
name='right_wrist',
|
||||
id=10,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_wrist'),
|
||||
11:
|
||||
dict(
|
||||
name='right_elbow',
|
||||
id=11,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_elbow'),
|
||||
12:
|
||||
dict(
|
||||
name='right_shoulder',
|
||||
id=12,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_shoulder'),
|
||||
13:
|
||||
dict(
|
||||
name='left_shoulder',
|
||||
id=13,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_shoulder'),
|
||||
14:
|
||||
dict(
|
||||
name='left_elbow',
|
||||
id=14,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_elbow'),
|
||||
15:
|
||||
dict(
|
||||
name='left_wrist',
|
||||
id=15,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_wrist')
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('right_ankle', 'right_knee'), id=0, color=[255, 128, 0]),
|
||||
1:
|
||||
dict(link=('right_knee', 'right_hip'), id=1, color=[255, 128, 0]),
|
||||
2:
|
||||
dict(link=('right_hip', 'pelvis'), id=2, color=[255, 128, 0]),
|
||||
3:
|
||||
dict(link=('pelvis', 'left_hip'), id=3, color=[0, 255, 0]),
|
||||
4:
|
||||
dict(link=('left_hip', 'left_knee'), id=4, color=[0, 255, 0]),
|
||||
5:
|
||||
dict(link=('left_knee', 'left_ankle'), id=5, color=[0, 255, 0]),
|
||||
6:
|
||||
dict(link=('pelvis', 'thorax'), id=6, color=[51, 153, 255]),
|
||||
7:
|
||||
dict(link=('thorax', 'upper_neck'), id=7, color=[51, 153, 255]),
|
||||
8:
|
||||
dict(link=('upper_neck', 'head_top'), id=8, color=[51, 153, 255]),
|
||||
9:
|
||||
dict(link=('upper_neck', 'right_shoulder'), id=9, color=[255, 128, 0]),
|
||||
10:
|
||||
dict(
|
||||
link=('right_shoulder', 'right_elbow'), id=10, color=[255, 128,
|
||||
0]),
|
||||
11:
|
||||
dict(link=('right_elbow', 'right_wrist'), id=11, color=[255, 128, 0]),
|
||||
12:
|
||||
dict(link=('upper_neck', 'left_shoulder'), id=12, color=[0, 255, 0]),
|
||||
13:
|
||||
dict(link=('left_shoulder', 'left_elbow'), id=13, color=[0, 255, 0]),
|
||||
14:
|
||||
dict(link=('left_elbow', 'left_wrist'), id=14, color=[0, 255, 0])
|
||||
},
|
||||
joint_weights=[
|
||||
1.5, 1.2, 1., 1., 1.2, 1.5, 1., 1., 1., 1., 1.5, 1.2, 1., 1., 1.2, 1.5
|
||||
],
|
||||
# Adapted from COCO dataset.
|
||||
sigmas=[
|
||||
0.089, 0.083, 0.107, 0.107, 0.083, 0.089, 0.026, 0.026, 0.026, 0.026,
|
||||
0.062, 0.072, 0.179, 0.179, 0.072, 0.062
|
||||
])
|
||||
@@ -0,0 +1,155 @@
|
||||
mpii_info = dict(
|
||||
dataset_name='mpii',
|
||||
paper_info=dict(
|
||||
author='Mykhaylo Andriluka and Leonid Pishchulin and '
|
||||
'Peter Gehler and Schiele, Bernt',
|
||||
title='2D Human Pose Estimation: New Benchmark and '
|
||||
'State of the Art Analysis',
|
||||
container='IEEE Conference on Computer Vision and '
|
||||
'Pattern Recognition (CVPR)',
|
||||
year='2014',
|
||||
homepage='http://human-pose.mpi-inf.mpg.de/',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='right_ankle',
|
||||
id=0,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_ankle'),
|
||||
1:
|
||||
dict(
|
||||
name='right_knee',
|
||||
id=1,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_knee'),
|
||||
2:
|
||||
dict(
|
||||
name='right_hip',
|
||||
id=2,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_hip'),
|
||||
3:
|
||||
dict(
|
||||
name='left_hip',
|
||||
id=3,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_hip'),
|
||||
4:
|
||||
dict(
|
||||
name='left_knee',
|
||||
id=4,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_knee'),
|
||||
5:
|
||||
dict(
|
||||
name='left_ankle',
|
||||
id=5,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_ankle'),
|
||||
6:
|
||||
dict(name='pelvis', id=6, color=[51, 153, 255], type='lower', swap=''),
|
||||
7:
|
||||
dict(name='thorax', id=7, color=[51, 153, 255], type='upper', swap=''),
|
||||
8:
|
||||
dict(
|
||||
name='upper_neck',
|
||||
id=8,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap=''),
|
||||
9:
|
||||
dict(
|
||||
name='head_top', id=9, color=[51, 153, 255], type='upper',
|
||||
swap=''),
|
||||
10:
|
||||
dict(
|
||||
name='right_wrist',
|
||||
id=10,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_wrist'),
|
||||
11:
|
||||
dict(
|
||||
name='right_elbow',
|
||||
id=11,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_elbow'),
|
||||
12:
|
||||
dict(
|
||||
name='right_shoulder',
|
||||
id=12,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_shoulder'),
|
||||
13:
|
||||
dict(
|
||||
name='left_shoulder',
|
||||
id=13,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_shoulder'),
|
||||
14:
|
||||
dict(
|
||||
name='left_elbow',
|
||||
id=14,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_elbow'),
|
||||
15:
|
||||
dict(
|
||||
name='left_wrist',
|
||||
id=15,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_wrist')
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('right_ankle', 'right_knee'), id=0, color=[255, 128, 0]),
|
||||
1:
|
||||
dict(link=('right_knee', 'right_hip'), id=1, color=[255, 128, 0]),
|
||||
2:
|
||||
dict(link=('right_hip', 'pelvis'), id=2, color=[255, 128, 0]),
|
||||
3:
|
||||
dict(link=('pelvis', 'left_hip'), id=3, color=[0, 255, 0]),
|
||||
4:
|
||||
dict(link=('left_hip', 'left_knee'), id=4, color=[0, 255, 0]),
|
||||
5:
|
||||
dict(link=('left_knee', 'left_ankle'), id=5, color=[0, 255, 0]),
|
||||
6:
|
||||
dict(link=('pelvis', 'thorax'), id=6, color=[51, 153, 255]),
|
||||
7:
|
||||
dict(link=('thorax', 'upper_neck'), id=7, color=[51, 153, 255]),
|
||||
8:
|
||||
dict(link=('upper_neck', 'head_top'), id=8, color=[51, 153, 255]),
|
||||
9:
|
||||
dict(link=('upper_neck', 'right_shoulder'), id=9, color=[255, 128, 0]),
|
||||
10:
|
||||
dict(
|
||||
link=('right_shoulder', 'right_elbow'), id=10, color=[255, 128,
|
||||
0]),
|
||||
11:
|
||||
dict(link=('right_elbow', 'right_wrist'), id=11, color=[255, 128, 0]),
|
||||
12:
|
||||
dict(link=('upper_neck', 'left_shoulder'), id=12, color=[0, 255, 0]),
|
||||
13:
|
||||
dict(link=('left_shoulder', 'left_elbow'), id=13, color=[0, 255, 0]),
|
||||
14:
|
||||
dict(link=('left_elbow', 'left_wrist'), id=14, color=[0, 255, 0])
|
||||
},
|
||||
joint_weights=[
|
||||
1.5, 1.2, 1., 1., 1.2, 1.5, 1., 1., 1., 1., 1.5, 1.2, 1., 1., 1.2, 1.5
|
||||
],
|
||||
# Adapted from COCO dataset.
|
||||
sigmas=[
|
||||
0.089, 0.083, 0.107, 0.107, 0.083, 0.089, 0.026, 0.026, 0.026, 0.026,
|
||||
0.062, 0.072, 0.179, 0.179, 0.072, 0.062
|
||||
])
|
||||
@@ -0,0 +1,380 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='mpii_trb',
|
||||
paper_info=dict(
|
||||
author='Duan, Haodong and Lin, Kwan-Yee and Jin, Sheng and '
|
||||
'Liu, Wentao and Qian, Chen and Ouyang, Wanli',
|
||||
title='TRB: A Novel Triplet Representation for '
|
||||
'Understanding 2D Human Body',
|
||||
container='Proceedings of the IEEE International '
|
||||
'Conference on Computer Vision',
|
||||
year='2019',
|
||||
homepage='https://github.com/kennymckormick/'
|
||||
'Triplet-Representation-of-human-Body',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(
|
||||
name='left_shoulder',
|
||||
id=0,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_shoulder'),
|
||||
1:
|
||||
dict(
|
||||
name='right_shoulder',
|
||||
id=1,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_shoulder'),
|
||||
2:
|
||||
dict(
|
||||
name='left_elbow',
|
||||
id=2,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_elbow'),
|
||||
3:
|
||||
dict(
|
||||
name='right_elbow',
|
||||
id=3,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_elbow'),
|
||||
4:
|
||||
dict(
|
||||
name='left_wrist',
|
||||
id=4,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_wrist'),
|
||||
5:
|
||||
dict(
|
||||
name='right_wrist',
|
||||
id=5,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_wrist'),
|
||||
6:
|
||||
dict(
|
||||
name='left_hip',
|
||||
id=6,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_hip'),
|
||||
7:
|
||||
dict(
|
||||
name='right_hip',
|
||||
id=7,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_hip'),
|
||||
8:
|
||||
dict(
|
||||
name='left_knee',
|
||||
id=8,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_knee'),
|
||||
9:
|
||||
dict(
|
||||
name='right_knee',
|
||||
id=9,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_knee'),
|
||||
10:
|
||||
dict(
|
||||
name='left_ankle',
|
||||
id=10,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_ankle'),
|
||||
11:
|
||||
dict(
|
||||
name='right_ankle',
|
||||
id=11,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_ankle'),
|
||||
12:
|
||||
dict(name='head', id=12, color=[51, 153, 255], type='upper', swap=''),
|
||||
13:
|
||||
dict(name='neck', id=13, color=[51, 153, 255], type='upper', swap=''),
|
||||
14:
|
||||
dict(
|
||||
name='right_neck',
|
||||
id=14,
|
||||
color=[255, 255, 255],
|
||||
type='upper',
|
||||
swap='left_neck'),
|
||||
15:
|
||||
dict(
|
||||
name='left_neck',
|
||||
id=15,
|
||||
color=[255, 255, 255],
|
||||
type='upper',
|
||||
swap='right_neck'),
|
||||
16:
|
||||
dict(
|
||||
name='medial_right_shoulder',
|
||||
id=16,
|
||||
color=[255, 255, 255],
|
||||
type='upper',
|
||||
swap='medial_left_shoulder'),
|
||||
17:
|
||||
dict(
|
||||
name='lateral_right_shoulder',
|
||||
id=17,
|
||||
color=[255, 255, 255],
|
||||
type='upper',
|
||||
swap='lateral_left_shoulder'),
|
||||
18:
|
||||
dict(
|
||||
name='medial_right_bow',
|
||||
id=18,
|
||||
color=[255, 255, 255],
|
||||
type='upper',
|
||||
swap='medial_left_bow'),
|
||||
19:
|
||||
dict(
|
||||
name='lateral_right_bow',
|
||||
id=19,
|
||||
color=[255, 255, 255],
|
||||
type='upper',
|
||||
swap='lateral_left_bow'),
|
||||
20:
|
||||
dict(
|
||||
name='medial_right_wrist',
|
||||
id=20,
|
||||
color=[255, 255, 255],
|
||||
type='upper',
|
||||
swap='medial_left_wrist'),
|
||||
21:
|
||||
dict(
|
||||
name='lateral_right_wrist',
|
||||
id=21,
|
||||
color=[255, 255, 255],
|
||||
type='upper',
|
||||
swap='lateral_left_wrist'),
|
||||
22:
|
||||
dict(
|
||||
name='medial_left_shoulder',
|
||||
id=22,
|
||||
color=[255, 255, 255],
|
||||
type='upper',
|
||||
swap='medial_right_shoulder'),
|
||||
23:
|
||||
dict(
|
||||
name='lateral_left_shoulder',
|
||||
id=23,
|
||||
color=[255, 255, 255],
|
||||
type='upper',
|
||||
swap='lateral_right_shoulder'),
|
||||
24:
|
||||
dict(
|
||||
name='medial_left_bow',
|
||||
id=24,
|
||||
color=[255, 255, 255],
|
||||
type='upper',
|
||||
swap='medial_right_bow'),
|
||||
25:
|
||||
dict(
|
||||
name='lateral_left_bow',
|
||||
id=25,
|
||||
color=[255, 255, 255],
|
||||
type='upper',
|
||||
swap='lateral_right_bow'),
|
||||
26:
|
||||
dict(
|
||||
name='medial_left_wrist',
|
||||
id=26,
|
||||
color=[255, 255, 255],
|
||||
type='upper',
|
||||
swap='medial_right_wrist'),
|
||||
27:
|
||||
dict(
|
||||
name='lateral_left_wrist',
|
||||
id=27,
|
||||
color=[255, 255, 255],
|
||||
type='upper',
|
||||
swap='lateral_right_wrist'),
|
||||
28:
|
||||
dict(
|
||||
name='medial_right_hip',
|
||||
id=28,
|
||||
color=[255, 255, 255],
|
||||
type='lower',
|
||||
swap='medial_left_hip'),
|
||||
29:
|
||||
dict(
|
||||
name='lateral_right_hip',
|
||||
id=29,
|
||||
color=[255, 255, 255],
|
||||
type='lower',
|
||||
swap='lateral_left_hip'),
|
||||
30:
|
||||
dict(
|
||||
name='medial_right_knee',
|
||||
id=30,
|
||||
color=[255, 255, 255],
|
||||
type='lower',
|
||||
swap='medial_left_knee'),
|
||||
31:
|
||||
dict(
|
||||
name='lateral_right_knee',
|
||||
id=31,
|
||||
color=[255, 255, 255],
|
||||
type='lower',
|
||||
swap='lateral_left_knee'),
|
||||
32:
|
||||
dict(
|
||||
name='medial_right_ankle',
|
||||
id=32,
|
||||
color=[255, 255, 255],
|
||||
type='lower',
|
||||
swap='medial_left_ankle'),
|
||||
33:
|
||||
dict(
|
||||
name='lateral_right_ankle',
|
||||
id=33,
|
||||
color=[255, 255, 255],
|
||||
type='lower',
|
||||
swap='lateral_left_ankle'),
|
||||
34:
|
||||
dict(
|
||||
name='medial_left_hip',
|
||||
id=34,
|
||||
color=[255, 255, 255],
|
||||
type='lower',
|
||||
swap='medial_right_hip'),
|
||||
35:
|
||||
dict(
|
||||
name='lateral_left_hip',
|
||||
id=35,
|
||||
color=[255, 255, 255],
|
||||
type='lower',
|
||||
swap='lateral_right_hip'),
|
||||
36:
|
||||
dict(
|
||||
name='medial_left_knee',
|
||||
id=36,
|
||||
color=[255, 255, 255],
|
||||
type='lower',
|
||||
swap='medial_right_knee'),
|
||||
37:
|
||||
dict(
|
||||
name='lateral_left_knee',
|
||||
id=37,
|
||||
color=[255, 255, 255],
|
||||
type='lower',
|
||||
swap='lateral_right_knee'),
|
||||
38:
|
||||
dict(
|
||||
name='medial_left_ankle',
|
||||
id=38,
|
||||
color=[255, 255, 255],
|
||||
type='lower',
|
||||
swap='medial_right_ankle'),
|
||||
39:
|
||||
dict(
|
||||
name='lateral_left_ankle',
|
||||
id=39,
|
||||
color=[255, 255, 255],
|
||||
type='lower',
|
||||
swap='lateral_right_ankle'),
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('head', 'neck'), id=0, color=[51, 153, 255]),
|
||||
1:
|
||||
dict(link=('neck', 'left_shoulder'), id=1, color=[51, 153, 255]),
|
||||
2:
|
||||
dict(link=('neck', 'right_shoulder'), id=2, color=[51, 153, 255]),
|
||||
3:
|
||||
dict(link=('left_shoulder', 'left_elbow'), id=3, color=[0, 255, 0]),
|
||||
4:
|
||||
dict(
|
||||
link=('right_shoulder', 'right_elbow'), id=4, color=[255, 128, 0]),
|
||||
5:
|
||||
dict(link=('left_elbow', 'left_wrist'), id=5, color=[0, 255, 0]),
|
||||
6:
|
||||
dict(link=('right_elbow', 'right_wrist'), id=6, color=[255, 128, 0]),
|
||||
7:
|
||||
dict(link=('left_shoulder', 'left_hip'), id=7, color=[51, 153, 255]),
|
||||
8:
|
||||
dict(link=('right_shoulder', 'right_hip'), id=8, color=[51, 153, 255]),
|
||||
9:
|
||||
dict(link=('left_hip', 'right_hip'), id=9, color=[51, 153, 255]),
|
||||
10:
|
||||
dict(link=('left_hip', 'left_knee'), id=10, color=[0, 255, 0]),
|
||||
11:
|
||||
dict(link=('right_hip', 'right_knee'), id=11, color=[255, 128, 0]),
|
||||
12:
|
||||
dict(link=('left_knee', 'left_ankle'), id=12, color=[0, 255, 0]),
|
||||
13:
|
||||
dict(link=('right_knee', 'right_ankle'), id=13, color=[255, 128, 0]),
|
||||
14:
|
||||
dict(link=('right_neck', 'left_neck'), id=14, color=[255, 255, 255]),
|
||||
15:
|
||||
dict(
|
||||
link=('medial_right_shoulder', 'lateral_right_shoulder'),
|
||||
id=15,
|
||||
color=[255, 255, 255]),
|
||||
16:
|
||||
dict(
|
||||
link=('medial_right_bow', 'lateral_right_bow'),
|
||||
id=16,
|
||||
color=[255, 255, 255]),
|
||||
17:
|
||||
dict(
|
||||
link=('medial_right_wrist', 'lateral_right_wrist'),
|
||||
id=17,
|
||||
color=[255, 255, 255]),
|
||||
18:
|
||||
dict(
|
||||
link=('medial_left_shoulder', 'lateral_left_shoulder'),
|
||||
id=18,
|
||||
color=[255, 255, 255]),
|
||||
19:
|
||||
dict(
|
||||
link=('medial_left_bow', 'lateral_left_bow'),
|
||||
id=19,
|
||||
color=[255, 255, 255]),
|
||||
20:
|
||||
dict(
|
||||
link=('medial_left_wrist', 'lateral_left_wrist'),
|
||||
id=20,
|
||||
color=[255, 255, 255]),
|
||||
21:
|
||||
dict(
|
||||
link=('medial_right_hip', 'lateral_right_hip'),
|
||||
id=21,
|
||||
color=[255, 255, 255]),
|
||||
22:
|
||||
dict(
|
||||
link=('medial_right_knee', 'lateral_right_knee'),
|
||||
id=22,
|
||||
color=[255, 255, 255]),
|
||||
23:
|
||||
dict(
|
||||
link=('medial_right_ankle', 'lateral_right_ankle'),
|
||||
id=23,
|
||||
color=[255, 255, 255]),
|
||||
24:
|
||||
dict(
|
||||
link=('medial_left_hip', 'lateral_left_hip'),
|
||||
id=24,
|
||||
color=[255, 255, 255]),
|
||||
25:
|
||||
dict(
|
||||
link=('medial_left_knee', 'lateral_left_knee'),
|
||||
id=25,
|
||||
color=[255, 255, 255]),
|
||||
26:
|
||||
dict(
|
||||
link=('medial_left_ankle', 'lateral_left_ankle'),
|
||||
id=26,
|
||||
color=[255, 255, 255])
|
||||
},
|
||||
joint_weights=[1.] * 40,
|
||||
sigmas=[])
|
||||
@@ -0,0 +1,181 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='ochuman',
|
||||
paper_info=dict(
|
||||
author='Zhang, Song-Hai and Li, Ruilong and Dong, Xin and '
|
||||
'Rosin, Paul and Cai, Zixi and Han, Xi and '
|
||||
'Yang, Dingcheng and Huang, Haozhi and Hu, Shi-Min',
|
||||
title='Pose2seg: Detection free human instance segmentation',
|
||||
container='Proceedings of the IEEE conference on computer '
|
||||
'vision and pattern recognition',
|
||||
year='2019',
|
||||
homepage='https://github.com/liruilong940607/OCHumanApi',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(name='nose', id=0, color=[51, 153, 255], type='upper', swap=''),
|
||||
1:
|
||||
dict(
|
||||
name='left_eye',
|
||||
id=1,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='right_eye'),
|
||||
2:
|
||||
dict(
|
||||
name='right_eye',
|
||||
id=2,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='left_eye'),
|
||||
3:
|
||||
dict(
|
||||
name='left_ear',
|
||||
id=3,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='right_ear'),
|
||||
4:
|
||||
dict(
|
||||
name='right_ear',
|
||||
id=4,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='left_ear'),
|
||||
5:
|
||||
dict(
|
||||
name='left_shoulder',
|
||||
id=5,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_shoulder'),
|
||||
6:
|
||||
dict(
|
||||
name='right_shoulder',
|
||||
id=6,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_shoulder'),
|
||||
7:
|
||||
dict(
|
||||
name='left_elbow',
|
||||
id=7,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_elbow'),
|
||||
8:
|
||||
dict(
|
||||
name='right_elbow',
|
||||
id=8,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_elbow'),
|
||||
9:
|
||||
dict(
|
||||
name='left_wrist',
|
||||
id=9,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_wrist'),
|
||||
10:
|
||||
dict(
|
||||
name='right_wrist',
|
||||
id=10,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_wrist'),
|
||||
11:
|
||||
dict(
|
||||
name='left_hip',
|
||||
id=11,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_hip'),
|
||||
12:
|
||||
dict(
|
||||
name='right_hip',
|
||||
id=12,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_hip'),
|
||||
13:
|
||||
dict(
|
||||
name='left_knee',
|
||||
id=13,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_knee'),
|
||||
14:
|
||||
dict(
|
||||
name='right_knee',
|
||||
id=14,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_knee'),
|
||||
15:
|
||||
dict(
|
||||
name='left_ankle',
|
||||
id=15,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_ankle'),
|
||||
16:
|
||||
dict(
|
||||
name='right_ankle',
|
||||
id=16,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_ankle')
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('left_ankle', 'left_knee'), id=0, color=[0, 255, 0]),
|
||||
1:
|
||||
dict(link=('left_knee', 'left_hip'), id=1, color=[0, 255, 0]),
|
||||
2:
|
||||
dict(link=('right_ankle', 'right_knee'), id=2, color=[255, 128, 0]),
|
||||
3:
|
||||
dict(link=('right_knee', 'right_hip'), id=3, color=[255, 128, 0]),
|
||||
4:
|
||||
dict(link=('left_hip', 'right_hip'), id=4, color=[51, 153, 255]),
|
||||
5:
|
||||
dict(link=('left_shoulder', 'left_hip'), id=5, color=[51, 153, 255]),
|
||||
6:
|
||||
dict(link=('right_shoulder', 'right_hip'), id=6, color=[51, 153, 255]),
|
||||
7:
|
||||
dict(
|
||||
link=('left_shoulder', 'right_shoulder'),
|
||||
id=7,
|
||||
color=[51, 153, 255]),
|
||||
8:
|
||||
dict(link=('left_shoulder', 'left_elbow'), id=8, color=[0, 255, 0]),
|
||||
9:
|
||||
dict(
|
||||
link=('right_shoulder', 'right_elbow'), id=9, color=[255, 128, 0]),
|
||||
10:
|
||||
dict(link=('left_elbow', 'left_wrist'), id=10, color=[0, 255, 0]),
|
||||
11:
|
||||
dict(link=('right_elbow', 'right_wrist'), id=11, color=[255, 128, 0]),
|
||||
12:
|
||||
dict(link=('left_eye', 'right_eye'), id=12, color=[51, 153, 255]),
|
||||
13:
|
||||
dict(link=('nose', 'left_eye'), id=13, color=[51, 153, 255]),
|
||||
14:
|
||||
dict(link=('nose', 'right_eye'), id=14, color=[51, 153, 255]),
|
||||
15:
|
||||
dict(link=('left_eye', 'left_ear'), id=15, color=[51, 153, 255]),
|
||||
16:
|
||||
dict(link=('right_eye', 'right_ear'), id=16, color=[51, 153, 255]),
|
||||
17:
|
||||
dict(link=('left_ear', 'left_shoulder'), id=17, color=[51, 153, 255]),
|
||||
18:
|
||||
dict(
|
||||
link=('right_ear', 'right_shoulder'), id=18, color=[51, 153, 255])
|
||||
},
|
||||
joint_weights=[
|
||||
1., 1., 1., 1., 1., 1., 1., 1.2, 1.2, 1.5, 1.5, 1., 1., 1.2, 1.2, 1.5,
|
||||
1.5
|
||||
],
|
||||
sigmas=[
|
||||
0.026, 0.025, 0.025, 0.035, 0.035, 0.079, 0.079, 0.072, 0.072, 0.062,
|
||||
0.062, 0.107, 0.107, 0.087, 0.087, 0.089, 0.089
|
||||
])
|
||||
@@ -0,0 +1,142 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='onehand10k',
|
||||
paper_info=dict(
|
||||
author='Wang, Yangang and Peng, Cong and Liu, Yebin',
|
||||
title='Mask-pose cascaded cnn for 2d hand pose estimation '
|
||||
'from single color image',
|
||||
container='IEEE Transactions on Circuits and Systems '
|
||||
'for Video Technology',
|
||||
year='2018',
|
||||
homepage='https://www.yangangwang.com/papers/WANG-MCC-2018-10.html',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(name='wrist', id=0, color=[255, 255, 255], type='', swap=''),
|
||||
1:
|
||||
dict(name='thumb1', id=1, color=[255, 128, 0], type='', swap=''),
|
||||
2:
|
||||
dict(name='thumb2', id=2, color=[255, 128, 0], type='', swap=''),
|
||||
3:
|
||||
dict(name='thumb3', id=3, color=[255, 128, 0], type='', swap=''),
|
||||
4:
|
||||
dict(name='thumb4', id=4, color=[255, 128, 0], type='', swap=''),
|
||||
5:
|
||||
dict(
|
||||
name='forefinger1', id=5, color=[255, 153, 255], type='', swap=''),
|
||||
6:
|
||||
dict(
|
||||
name='forefinger2', id=6, color=[255, 153, 255], type='', swap=''),
|
||||
7:
|
||||
dict(
|
||||
name='forefinger3', id=7, color=[255, 153, 255], type='', swap=''),
|
||||
8:
|
||||
dict(
|
||||
name='forefinger4', id=8, color=[255, 153, 255], type='', swap=''),
|
||||
9:
|
||||
dict(
|
||||
name='middle_finger1',
|
||||
id=9,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
10:
|
||||
dict(
|
||||
name='middle_finger2',
|
||||
id=10,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
11:
|
||||
dict(
|
||||
name='middle_finger3',
|
||||
id=11,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
12:
|
||||
dict(
|
||||
name='middle_finger4',
|
||||
id=12,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
13:
|
||||
dict(
|
||||
name='ring_finger1', id=13, color=[255, 51, 51], type='', swap=''),
|
||||
14:
|
||||
dict(
|
||||
name='ring_finger2', id=14, color=[255, 51, 51], type='', swap=''),
|
||||
15:
|
||||
dict(
|
||||
name='ring_finger3', id=15, color=[255, 51, 51], type='', swap=''),
|
||||
16:
|
||||
dict(
|
||||
name='ring_finger4', id=16, color=[255, 51, 51], type='', swap=''),
|
||||
17:
|
||||
dict(name='pinky_finger1', id=17, color=[0, 255, 0], type='', swap=''),
|
||||
18:
|
||||
dict(name='pinky_finger2', id=18, color=[0, 255, 0], type='', swap=''),
|
||||
19:
|
||||
dict(name='pinky_finger3', id=19, color=[0, 255, 0], type='', swap=''),
|
||||
20:
|
||||
dict(name='pinky_finger4', id=20, color=[0, 255, 0], type='', swap='')
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('wrist', 'thumb1'), id=0, color=[255, 128, 0]),
|
||||
1:
|
||||
dict(link=('thumb1', 'thumb2'), id=1, color=[255, 128, 0]),
|
||||
2:
|
||||
dict(link=('thumb2', 'thumb3'), id=2, color=[255, 128, 0]),
|
||||
3:
|
||||
dict(link=('thumb3', 'thumb4'), id=3, color=[255, 128, 0]),
|
||||
4:
|
||||
dict(link=('wrist', 'forefinger1'), id=4, color=[255, 153, 255]),
|
||||
5:
|
||||
dict(link=('forefinger1', 'forefinger2'), id=5, color=[255, 153, 255]),
|
||||
6:
|
||||
dict(link=('forefinger2', 'forefinger3'), id=6, color=[255, 153, 255]),
|
||||
7:
|
||||
dict(link=('forefinger3', 'forefinger4'), id=7, color=[255, 153, 255]),
|
||||
8:
|
||||
dict(link=('wrist', 'middle_finger1'), id=8, color=[102, 178, 255]),
|
||||
9:
|
||||
dict(
|
||||
link=('middle_finger1', 'middle_finger2'),
|
||||
id=9,
|
||||
color=[102, 178, 255]),
|
||||
10:
|
||||
dict(
|
||||
link=('middle_finger2', 'middle_finger3'),
|
||||
id=10,
|
||||
color=[102, 178, 255]),
|
||||
11:
|
||||
dict(
|
||||
link=('middle_finger3', 'middle_finger4'),
|
||||
id=11,
|
||||
color=[102, 178, 255]),
|
||||
12:
|
||||
dict(link=('wrist', 'ring_finger1'), id=12, color=[255, 51, 51]),
|
||||
13:
|
||||
dict(
|
||||
link=('ring_finger1', 'ring_finger2'), id=13, color=[255, 51, 51]),
|
||||
14:
|
||||
dict(
|
||||
link=('ring_finger2', 'ring_finger3'), id=14, color=[255, 51, 51]),
|
||||
15:
|
||||
dict(
|
||||
link=('ring_finger3', 'ring_finger4'), id=15, color=[255, 51, 51]),
|
||||
16:
|
||||
dict(link=('wrist', 'pinky_finger1'), id=16, color=[0, 255, 0]),
|
||||
17:
|
||||
dict(
|
||||
link=('pinky_finger1', 'pinky_finger2'), id=17, color=[0, 255, 0]),
|
||||
18:
|
||||
dict(
|
||||
link=('pinky_finger2', 'pinky_finger3'), id=18, color=[0, 255, 0]),
|
||||
19:
|
||||
dict(
|
||||
link=('pinky_finger3', 'pinky_finger4'), id=19, color=[0, 255, 0])
|
||||
},
|
||||
joint_weights=[1.] * 21,
|
||||
sigmas=[])
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='panoptic_pose_3d',
|
||||
paper_info=dict(
|
||||
author='Joo, Hanbyul and Simon, Tomas and Li, Xulong'
|
||||
'and Liu, Hao and Tan, Lei and Gui, Lin and Banerjee, Sean'
|
||||
'and Godisart, Timothy and Nabbe, Bart and Matthews, Iain'
|
||||
'and Kanade, Takeo and Nobuhara, Shohei and Sheikh, Yaser',
|
||||
title='Panoptic Studio: A Massively Multiview System '
|
||||
'for Interaction Motion Capture',
|
||||
container='IEEE Transactions on Pattern Analysis'
|
||||
' and Machine Intelligence',
|
||||
year='2017',
|
||||
homepage='http://domedb.perception.cs.cmu.edu',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(name='neck', id=0, color=[51, 153, 255], type='upper', swap=''),
|
||||
1:
|
||||
dict(name='nose', id=1, color=[51, 153, 255], type='upper', swap=''),
|
||||
2:
|
||||
dict(name='mid_hip', id=2, color=[0, 255, 0], type='lower', swap=''),
|
||||
3:
|
||||
dict(
|
||||
name='left_shoulder',
|
||||
id=3,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_shoulder'),
|
||||
4:
|
||||
dict(
|
||||
name='left_elbow',
|
||||
id=4,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_elbow'),
|
||||
5:
|
||||
dict(
|
||||
name='left_wrist',
|
||||
id=5,
|
||||
color=[0, 255, 0],
|
||||
type='upper',
|
||||
swap='right_wrist'),
|
||||
6:
|
||||
dict(
|
||||
name='left_hip',
|
||||
id=6,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_hip'),
|
||||
7:
|
||||
dict(
|
||||
name='left_knee',
|
||||
id=7,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_knee'),
|
||||
8:
|
||||
dict(
|
||||
name='left_ankle',
|
||||
id=8,
|
||||
color=[0, 255, 0],
|
||||
type='lower',
|
||||
swap='right_ankle'),
|
||||
9:
|
||||
dict(
|
||||
name='right_shoulder',
|
||||
id=9,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_shoulder'),
|
||||
10:
|
||||
dict(
|
||||
name='right_elbow',
|
||||
id=10,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_elbow'),
|
||||
11:
|
||||
dict(
|
||||
name='right_wrist',
|
||||
id=11,
|
||||
color=[255, 128, 0],
|
||||
type='upper',
|
||||
swap='left_wrist'),
|
||||
12:
|
||||
dict(
|
||||
name='right_hip',
|
||||
id=12,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_hip'),
|
||||
13:
|
||||
dict(
|
||||
name='right_knee',
|
||||
id=13,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_knee'),
|
||||
14:
|
||||
dict(
|
||||
name='right_ankle',
|
||||
id=14,
|
||||
color=[255, 128, 0],
|
||||
type='lower',
|
||||
swap='left_ankle'),
|
||||
15:
|
||||
dict(
|
||||
name='left_eye',
|
||||
id=15,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='right_eye'),
|
||||
16:
|
||||
dict(
|
||||
name='left_ear',
|
||||
id=16,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='right_ear'),
|
||||
17:
|
||||
dict(
|
||||
name='right_eye',
|
||||
id=17,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='left_eye'),
|
||||
18:
|
||||
dict(
|
||||
name='right_ear',
|
||||
id=18,
|
||||
color=[51, 153, 255],
|
||||
type='upper',
|
||||
swap='left_ear')
|
||||
},
|
||||
skeleton_info={
|
||||
0: dict(link=('nose', 'neck'), id=0, color=[51, 153, 255]),
|
||||
1: dict(link=('neck', 'left_shoulder'), id=1, color=[0, 255, 0]),
|
||||
2: dict(link=('neck', 'right_shoulder'), id=2, color=[255, 128, 0]),
|
||||
3: dict(link=('left_shoulder', 'left_elbow'), id=3, color=[0, 255, 0]),
|
||||
4: dict(
|
||||
link=('right_shoulder', 'right_elbow'), id=4, color=[255, 128, 0]),
|
||||
5: dict(link=('left_elbow', 'left_wrist'), id=5, color=[0, 255, 0]),
|
||||
6:
|
||||
dict(link=('right_elbow', 'right_wrist'), id=6, color=[255, 128, 0]),
|
||||
7: dict(link=('left_ankle', 'left_knee'), id=7, color=[0, 255, 0]),
|
||||
8: dict(link=('left_knee', 'left_hip'), id=8, color=[0, 255, 0]),
|
||||
9: dict(link=('right_ankle', 'right_knee'), id=9, color=[255, 128, 0]),
|
||||
10: dict(link=('right_knee', 'right_hip'), id=10, color=[255, 128, 0]),
|
||||
11: dict(link=('mid_hip', 'left_hip'), id=11, color=[0, 255, 0]),
|
||||
12: dict(link=('mid_hip', 'right_hip'), id=12, color=[255, 128, 0]),
|
||||
13: dict(link=('mid_hip', 'neck'), id=13, color=[51, 153, 255]),
|
||||
},
|
||||
joint_weights=[
|
||||
1.0, 1.0, 1.0, 1.0, 1.2, 1.5, 1.0, 1.2, 1.5, 1.0, 1.2, 1.5, 1.0, 1.2,
|
||||
1.5, 1.0, 1.0, 1.0, 1.0
|
||||
],
|
||||
sigmas=[
|
||||
0.026, 0.026, 0.107, 0.079, 0.072, 0.062, 0.107, 0.087, 0.089, 0.079,
|
||||
0.072, 0.062, 0.107, 0.087, 0.089, 0.025, 0.035, 0.025, 0.035
|
||||
])
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
dataset_info = dict(
|
||||
dataset_name='panoptic_hand2d',
|
||||
paper_info=dict(
|
||||
author='Simon, Tomas and Joo, Hanbyul and '
|
||||
'Matthews, Iain and Sheikh, Yaser',
|
||||
title='Hand keypoint detection in single images using '
|
||||
'multiview bootstrapping',
|
||||
container='Proceedings of the IEEE conference on '
|
||||
'Computer Vision and Pattern Recognition',
|
||||
year='2017',
|
||||
homepage='http://domedb.perception.cs.cmu.edu/handdb.html',
|
||||
),
|
||||
keypoint_info={
|
||||
0:
|
||||
dict(name='wrist', id=0, color=[255, 255, 255], type='', swap=''),
|
||||
1:
|
||||
dict(name='thumb1', id=1, color=[255, 128, 0], type='', swap=''),
|
||||
2:
|
||||
dict(name='thumb2', id=2, color=[255, 128, 0], type='', swap=''),
|
||||
3:
|
||||
dict(name='thumb3', id=3, color=[255, 128, 0], type='', swap=''),
|
||||
4:
|
||||
dict(name='thumb4', id=4, color=[255, 128, 0], type='', swap=''),
|
||||
5:
|
||||
dict(
|
||||
name='forefinger1', id=5, color=[255, 153, 255], type='', swap=''),
|
||||
6:
|
||||
dict(
|
||||
name='forefinger2', id=6, color=[255, 153, 255], type='', swap=''),
|
||||
7:
|
||||
dict(
|
||||
name='forefinger3', id=7, color=[255, 153, 255], type='', swap=''),
|
||||
8:
|
||||
dict(
|
||||
name='forefinger4', id=8, color=[255, 153, 255], type='', swap=''),
|
||||
9:
|
||||
dict(
|
||||
name='middle_finger1',
|
||||
id=9,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
10:
|
||||
dict(
|
||||
name='middle_finger2',
|
||||
id=10,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
11:
|
||||
dict(
|
||||
name='middle_finger3',
|
||||
id=11,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
12:
|
||||
dict(
|
||||
name='middle_finger4',
|
||||
id=12,
|
||||
color=[102, 178, 255],
|
||||
type='',
|
||||
swap=''),
|
||||
13:
|
||||
dict(
|
||||
name='ring_finger1', id=13, color=[255, 51, 51], type='', swap=''),
|
||||
14:
|
||||
dict(
|
||||
name='ring_finger2', id=14, color=[255, 51, 51], type='', swap=''),
|
||||
15:
|
||||
dict(
|
||||
name='ring_finger3', id=15, color=[255, 51, 51], type='', swap=''),
|
||||
16:
|
||||
dict(
|
||||
name='ring_finger4', id=16, color=[255, 51, 51], type='', swap=''),
|
||||
17:
|
||||
dict(name='pinky_finger1', id=17, color=[0, 255, 0], type='', swap=''),
|
||||
18:
|
||||
dict(name='pinky_finger2', id=18, color=[0, 255, 0], type='', swap=''),
|
||||
19:
|
||||
dict(name='pinky_finger3', id=19, color=[0, 255, 0], type='', swap=''),
|
||||
20:
|
||||
dict(name='pinky_finger4', id=20, color=[0, 255, 0], type='', swap='')
|
||||
},
|
||||
skeleton_info={
|
||||
0:
|
||||
dict(link=('wrist', 'thumb1'), id=0, color=[255, 128, 0]),
|
||||
1:
|
||||
dict(link=('thumb1', 'thumb2'), id=1, color=[255, 128, 0]),
|
||||
2:
|
||||
dict(link=('thumb2', 'thumb3'), id=2, color=[255, 128, 0]),
|
||||
3:
|
||||
dict(link=('thumb3', 'thumb4'), id=3, color=[255, 128, 0]),
|
||||
4:
|
||||
dict(link=('wrist', 'forefinger1'), id=4, color=[255, 153, 255]),
|
||||
5:
|
||||
dict(link=('forefinger1', 'forefinger2'), id=5, color=[255, 153, 255]),
|
||||
6:
|
||||
dict(link=('forefinger2', 'forefinger3'), id=6, color=[255, 153, 255]),
|
||||
7:
|
||||
dict(link=('forefinger3', 'forefinger4'), id=7, color=[255, 153, 255]),
|
||||
8:
|
||||
dict(link=('wrist', 'middle_finger1'), id=8, color=[102, 178, 255]),
|
||||
9:
|
||||
dict(
|
||||
link=('middle_finger1', 'middle_finger2'),
|
||||
id=9,
|
||||
color=[102, 178, 255]),
|
||||
10:
|
||||
dict(
|
||||
link=('middle_finger2', 'middle_finger3'),
|
||||
id=10,
|
||||
color=[102, 178, 255]),
|
||||
11:
|
||||
dict(
|
||||
link=('middle_finger3', 'middle_finger4'),
|
||||
id=11,
|
||||
color=[102, 178, 255]),
|
||||
12:
|
||||
dict(link=('wrist', 'ring_finger1'), id=12, color=[255, 51, 51]),
|
||||
13:
|
||||
dict(
|
||||
link=('ring_finger1', 'ring_finger2'), id=13, color=[255, 51, 51]),
|
||||
14:
|
||||
dict(
|
||||
link=('ring_finger2', 'ring_finger3'), id=14, color=[255, 51, 51]),
|
||||
15:
|
||||
dict(
|
||||
link=('ring_finger3', 'ring_finger4'), id=15, color=[255, 51, 51]),
|
||||
16:
|
||||
dict(link=('wrist', 'pinky_finger1'), id=16, color=[0, 255, 0]),
|
||||
17:
|
||||
dict(
|
||||
link=('pinky_finger1', 'pinky_finger2'), id=17, color=[0, 255, 0]),
|
||||
18:
|
||||
dict(
|
||||
link=('pinky_finger2', 'pinky_finger3'), id=18, color=[0, 255, 0]),
|
||||
19:
|
||||
dict(
|
||||
link=('pinky_finger3', 'pinky_finger4'), id=19, color=[0, 255, 0])
|
||||
},
|
||||
joint_weights=[1.] * 21,
|
||||
sigmas=[])
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user