mambazjp commited on
Commit
ef6a8c6
1 Parent(s): f512d8d

Upload 11 files

Browse files
REC-MV_preprocess.md ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This is the tutorial of data processing of REC-MV.
2
+
3
+ The data pre-processing part includes img, mask, normal, parsing (garment segmentation), camera, smpl parameters (beta & theta), featurelines, skinning weight.
4
+ ## Step0
5
+ set up the environment (or you can directly use REC-MV environment)
6
+ ```
7
+ pip install -r requirements.txt
8
+ ```
9
+
10
+
11
+ ## Step1
12
+ You should make directory to save all processed data, named, to say, xiaoming.
13
+ And you turn the video into images:
14
+ ```
15
+ encodepngffmpeg()
16
+ {
17
+ # $1: target folder
18
+ # $2: save video name
19
+ ffmpeg -r ${1} -pattern_type glob -i '*.png' -vcodec libx264 -crf 18 -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2" -pix_fmt yuv420p ${2}
20
+ }
21
+
22
+
23
+ encodepngffmpeg 30 ./xiaoming.mp4
24
+ ```
25
+ Then, your data directory:
26
+ ```
27
+ xiaoming/
28
+ └── imgs
29
+ ```
30
+ ## Step2 Normal, Parsing, and Mask
31
+ Get the normal map, parsing mask, masks.
32
+ ```
33
+ python prcess_data_all.py --gid <gpu_id> --root <Your data root> --gender <data gender>
34
+ # example
35
+ python prcess_data_all.py --gid 0 --root /data/xiaoming --gender male
36
+ ```
37
+ Your data directory:
38
+ ```
39
+ xiaoming/
40
+ ├── imgs
41
+ ├── masks
42
+ ├── normals
43
+ └── parsing_SCH_ATR
44
+ ```
45
+
46
+ ## Step3 SMPL & Camera
47
+ To get smpl paramaters (pose and shape), here we use [videoavatar](https://github.com/thmoa/videoavatars):
48
+ - Set up the env (**Note it use python2**)
49
+ - Prepare keypoints files for each frame in the video and put them under `xiaoming/openpose`, which I use [Openpose](https://github.com/CMU-Perceptual-Computing-Lab/openpose).
50
+ - Run three python files in videoavatars/prepare_data, you'll get `keypoints.hdf5, masks.hdf5, camera.hdf5.` Or you can just use my script: ```cd videoavatars; python get_reconstructed_poses.py --root xiaoming --out xiaoming --gender male```
51
+ - `bash run_step1.sh`
52
+
53
+ After you run through videoavatar, you will get `camera.pkl, reconstructed_poses.hdf5`. Put it also under the root(xiaoming).
54
+
55
+ You can get `smpl_rec.npz, camera.npz` by running:
56
+ ```
57
+ python get_smpl_rec_camera.py --root xiaoming --save_root xiaoming --gender male
58
+ ```
59
+
60
+ **Note: You can use any other smpl estimation algorithm, but you should follow the way how smpl_rec.npz save pose, shape, and trans.**
61
+
62
+ ## Step4 Skining Weight
63
+ We follow [fite](https://github.com/jsnln/fite) to get the lbs skinning weight to prevent artifacts.
64
+
65
+ In fite's readme, you'll get a skining weight cube after finishing 3.Diffused Skinning. Name it `diffused_skinning_weights.npy` and put it under xiaoming.
66
+
67
+
68
+
depth2normal.py ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ from cv2 import imread
3
+ import numpy as np
4
+ from numpy import unique, load
5
+ import argparse
6
+ import os, os.path as osp
7
+ import tqdm
8
+ import pdb
9
+
10
+ def parse_args():
11
+ parser = argparse.ArgumentParser()
12
+ parser.add_argument('--root', type=str, required=True, help='root dir of one identity')
13
+ parser.add_argument('--cam_file', type=str, default='camera.npz')
14
+
15
+ parser.add_argument('--depth_dir', help='depth map path', default='depth', type=str)
16
+ parser.add_argument('--out_dir', '-n', help='outputnormal path', default='normal_depth', type=str)
17
+ parser.add_argument('--mask_dir', help='mask path', default='masks', type=str)
18
+ parser.add_argument('--mask_total_dir', help='total mask path', default='masks_total', type=str)
19
+ args = parser.parse_args()
20
+ return args
21
+
22
+ def get_surface_normal_by_depth(depth, fx, fy):
23
+ """
24
+ depth: (h, w) of float, the unit of depth is meter
25
+ K: (3, 3) of float, the depth camere's intrinsic
26
+ """
27
+
28
+ dz_dv, dz_du = np.gradient(depth) # u, v mean the pixel coordinate in the image
29
+ # u*depth = fx*x + cx --> du/dx = fx / dept
30
+ # smooth
31
+ # dz_du = cv2.Sobel(depth, cv2.CV_64F, 1, 0, ksize=5)
32
+ # dz_dv = cv2.Sobel(depth, cv2.CV_64F, 0, 1, ksize=5)
33
+ du_dx = fx / depth # x is xyz of camera coordinate
34
+ dv_dy = fy / depth
35
+
36
+ dz_dx = dz_du * du_dx
37
+ dz_dy = dz_dv * dv_dy
38
+ # cross-product (1,0,dz_dx)X(0,1,dz_dy) = (-dz_dx, -dz_dy, 1)
39
+ normal_cross = np.dstack((-dz_dx, -dz_dy, np.ones_like(depth)))
40
+ # normalize to unit vector
41
+ normal_unit = normal_cross / np.linalg.norm(normal_cross, axis=2, keepdims=True)
42
+ # set default normal to [0, 0, 1]
43
+ # pdb.set_trace()
44
+ nan_mask = np.isfinite(normal_unit).all(2)
45
+ normal_unit[~np.isfinite(normal_unit).all(2)] = [-1, -1, -1]
46
+ return normal_unit, nan_mask
47
+
48
+ # def delete_holes(img):
49
+ # im = img.copy()
50
+ # h, w = im.shape[:2]
51
+ # mask = np.zeros((h+2, w+2), dtype=np.uint8)
52
+ # holes = cv2.floodFill(im.copy(), mask, (0, 0), 255)[1]
53
+ # holes = ~holes
54
+ # im[holes == 255] = 255
55
+ # return im
56
+ def denoise(img):
57
+
58
+ kernel = np.ones((11, 11), np.uint8)
59
+ img= cv2.erode(img, kernel, iterations=2)
60
+ img= cv2.dilate(img, kernel, iterations=2)
61
+
62
+ return img
63
+
64
+ def main():
65
+ args = parse_args()
66
+ root = args.root
67
+ cam_file = osp.join(root, args.cam_file)
68
+ depth_dir = osp.join(root, args.depth_dir)
69
+ out_dir = osp.join(root, args.out_dir)
70
+ os.makedirs(out_dir, exist_ok=True)
71
+ mask_dir = osp.join(root, args.mask_dir)
72
+ mask_total_dir = osp.join(root, args.mask_total_dir)
73
+ os.makedirs(mask_total_dir, exist_ok=True)
74
+
75
+ cam = np.load(cam_file)
76
+ fx, fy = cam['fx'], cam['fy']
77
+
78
+ assert osp.exists(depth_dir), 'depth dir not exists'
79
+
80
+ depth_paths = sorted([
81
+ osp.join(depth_dir, f) for f in os.listdir(depth_dir)])
82
+ mask_paths = sorted([osp.join(mask_dir, f) for f in os.listdir(mask_dir)])
83
+
84
+
85
+ assert depth_paths[0].endswith('.npy'), 'depth dir must be .npy'
86
+
87
+ # [-1,1] -> [0, 2]/2 -> [0,1]*255 -> [0,255]
88
+ vis_normal = lambda normal: np.uint8((normal + 1) / 2 * 255)[..., ::-1]
89
+ for idx, depth_p in enumerate(depth_paths):
90
+
91
+ # mask is [0, 1]
92
+ mask = cv2.imread(mask_paths[idx], -1)[..., 0] / 255
93
+ assert len(mask.shape) == 2, 'dims of mask are not 2'
94
+
95
+ depth = np.load(depth_p) # the unit of depth is meter
96
+ # the val of normal is between [-1, 1]
97
+ normal, nan_mask = get_surface_normal_by_depth(depth, fx, fy)
98
+ mask_total = nan_mask * mask
99
+ #mask_total = denoise(mask_total)
100
+ # normal should be filtered by mask and nan_mask
101
+ normal = vis_normal(normal) * mask_total[..., None]
102
+
103
+ cv2.imwrite(osp.join(out_dir, f'{idx:05d}.png'), normal)
104
+ cv2.imwrite(osp.join(mask_total_dir, f'{idx:05d}.png'), mask_total.astype(np.uint8) * 255)
105
+ #cv2.imwrite(osp.join(root, 'nan_mask.png'), nan_mask.astype(np.uint8))
106
+ #xxx
107
+
108
+
109
+
110
+ if __name__ == '__main__':
111
+ #os.makedirs(args.normalPath, exist_ok = True)
112
+ main()
113
+ ''' if args.totalmaskPath:
114
+ os.makedirs(args.totalmaskPath, exist_ok = True)
115
+ for img_name in tqdm.tqdm(sorted(os.listdir(args.depthPath))):
116
+ img_path = os.path.join(args.depthPath, img_name)
117
+ depth = cv2.imread(img_path, -1) / 1000.0
118
+ normal, nan_mask = get_surface_normal_by_depth(depth)
119
+
120
+ vis_normal = lambda normal: np.uint8((normal + 1) / 2 * 255)[..., ::-1]
121
+ normal = vis_normal(normal)
122
+ if args.maskPath:
123
+ mask_path = os.path.join(args.maskPath, img_name[:-4] + '_mask' + img_name[-4:])
124
+ mask = cv2.imread(mask_path)
125
+ mask = cv2.rotate(mask, cv2.ROTATE_90_CLOCKWISE)
126
+ total_mask = mask[..., 0] * nan_mask
127
+ # cv2.imwrite(os.path.join(args.totalmaskPath, img_name), np.uint8(nan_mask*255))
128
+ # cv2.imwrite(os.path.join(args.totalmaskPath, img_name), total_mask)
129
+ kernel = np.ones((11, 11), np.uint8)
130
+ total_mask = cv2.erode(total_mask, kernel, iterations=1)
131
+ total_mask = cv2.dilate(total_mask, kernel, iterations=1)
132
+ # pdb.set_trace()
133
+ normal = np.uint8(total_mask[..., None]/255) * normal
134
+
135
+ if args.totalmaskPath:
136
+ # cv2.imwrite(os.path.join(args.totalmaskPath, img_name), delete_holes(total_mask))
137
+ total_mask = cv2.rotate(total_mask, cv2.ROTATE_90_COUNTERCLOCKWISE)
138
+ cv2.imwrite(os.path.join(args.totalmaskPath, img_name), total_mask)
139
+ # pdb.set_trace()
140
+
141
+ normal_path = os.path.join(args.normalPath, img_name)
142
+ normal = cv2.rotate(normal, cv2.ROTATE_90_COUNTERCLOCKWISE)
143
+ cv2.imwrite(normal_path, normal)
144
+
145
+ '''
146
+
get_smpl_rec_camera.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''
2
+ @Desc: From camera.pkl and reconstructed_poses.hdf5, get the camera.npz and smpl_rec.npz
3
+ Example: python xxx.py --root /home/zjp/DeepDynamicFashion/Data_depth/xinyu_a --save_root /home/zjp/DeepDynamicFashion/Data_depth/xinyu_a --gender female
4
+ '''
5
+ import h5py
6
+ import pickle
7
+ import numpy as np
8
+ import torch
9
+ import os
10
+ import os.path as osp
11
+ import cv2
12
+ from tqdm import tqdm
13
+ from glob import glob
14
+ import shutil
15
+ import argparse
16
+ parser = argparse.ArgumentParser(description='neu video body rec')
17
+ parser.add_argument('--root',default=None,metavar='M',
18
+ help='data root')
19
+ parser.add_argument('--sid',default=0,type=int,metavar='IDs',
20
+ help='start frame index')
21
+ parser.add_argument('--save_root',default=None,metavar='M',
22
+ help='save data root')
23
+ parser.add_argument('--gender', type=str, default='female')
24
+ args = parser.parse_args()
25
+
26
+ root=args.root
27
+ sid=args.sid
28
+ gender=args.gender
29
+ save_root=args.save_root
30
+ os.makedirs(save_root,exist_ok=True)
31
+
32
+ #rgb_root=osp.join(save_root,'imgs')
33
+ #if not osp.isdir(rgb_root):
34
+ # os.makedirs(rgb_root)
35
+ #
36
+ img_files = sorted(glob(os.path.join(root,'imgs/*.jpg')))
37
+ frame_num = len(img_files)
38
+
39
+ #for ind in tqdm(range(len(img_files)),desc='rgbs'):
40
+ # src_img = img_files[ind]
41
+ # target_img = osp.join(rgb_root,'%06d.jpg'%(ind-sid))
42
+ # shutil.copy2(src_img, target_img)
43
+
44
+
45
+ with h5py.File(osp.join(root,'reconstructed_poses.hdf5'),'r') as ff:
46
+ shape=ff['betas'][:].reshape(10)
47
+ poses=ff['pose'][:].reshape(-1,24,3)[sid:,:,:]
48
+ trans=ff['trans'][:].reshape(-1,3)[sid:,:]
49
+ assert(poses.shape[0]>=frame_num-sid and trans.shape[0]>=frame_num-sid)
50
+ np.savez(osp.join(save_root,'smpl_rec.npz'),poses=poses,shape=shape,trans=trans,gender=gender)
51
+
52
+ #with h5py.File(osp.join(root,'masks.hdf5'),'r') as ff:
53
+ # fnum=ff['masks'].shape[0]
54
+ # assert fnum>sid
55
+ # mask_root=osp.join(save_root,'masks')
56
+ # os.makedirs(mask_root,exist_ok=True)
57
+ # for ind in tqdm(range(sid,fnum),desc='masks'):
58
+ # cv2.imwrite(osp.join(mask_root,'%06d.png'%(ind-sid)),ff['masks'][ind]*255)
59
+
60
+
61
+ with open(osp.join(root,'camera.pkl'),'rb') as ff:
62
+ cam_data=pickle.load(ff,encoding='latin1')
63
+ ps=cam_data['camera_c']
64
+ fs=cam_data['camera_f']
65
+ trans=cam_data['camera_t']
66
+ rt=cam_data['camera_rt']
67
+ assert(np.linalg.norm(rt)<0.0001) # The cameras of snapshot dataset seems no rotation and translation
68
+ H=cam_data['height']
69
+ W=cam_data['width']
70
+
71
+ quat=np.array([np.cos(np.pi/2.),0.,0.,np.sin(np.pi/2.)])
72
+ T=trans
73
+ fx=fs[0]
74
+ fy=fs[1]
75
+ cx=ps[0]
76
+ cy=ps[1]
77
+ print(fx,fy,cx,cy,quat,T)
78
+
79
+ np.savez(osp.join(save_root,'camera.npz'),fx=fx,fy=fy,cx=cx,cy=cy,quat=quat,T=T)
80
+
81
+
82
+
83
+
84
+
inference.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''
2
+ This file is written to finish the preprocess of REC-MV:
3
+ - mask
4
+ - normal
5
+ - smpl params
6
+ - parse masks
7
+ '''
8
+
9
+ import json, os, os.path as osp, sys, shutil, glob, pdb, argparse
10
+
11
+ def parse_args():
12
+ parser = argparse.ArgumentParser()
13
+ parser.add_argument('--root', type=str)
14
+ parser.add_argument('--avatar_dir', type=str)
15
+ args = parser.parse_args()
16
+ return args
17
+
18
+ def main():
19
+ args = parse_args()
20
+ root = args.root
21
+ # TODO: get mask
22
+
23
+ # TODO: get normal
24
+ os.system('cd ./pifuhd && python generate_normals.py --imgpath {}'.format(osp.join(root, 'imgs')))
25
+ # get smpl_rec.npz
26
+ avatar_dir = osp.join(args.root, args.avatar_dir)
27
+ os.system('cd ./videoavatars && python get_reconstructed_poses.py --root {} --out {}'.format(args.root, avatar_dir))
28
+ os.system('cd ../ && python get_smpl_rec_camera.py --root {} --save-root {}'.format(args.root, args.root))
29
+
30
+ if __name__ == '__main__':
31
+ main()
mv_featurelines.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''
2
+ @File : mv_featurelines.py
3
+ @Author : Jiapeng Zhou
4
+ @Desc : move part of featurelines to another annotation labelme json files (bottom_curve are good, but left_cuff arenot)
5
+ '''
6
+
7
+ import os, os.path as osp, sys, pdb, json, shutil, argparse
8
+
9
+ def parse_args():
10
+ parser = argparse.ArgumentParser()
11
+ parser.add_argument('--src-dir', type=str)
12
+ parser.add_argument('--dst-dir', type=str)
13
+ args = parser.parse_args()
14
+ return args
15
+
16
+ def main():
17
+ args = parse_args()
18
+ src_dir = args.src_dir
19
+ dst_dir = args.dst_dir
20
+ src_files = sorted([osp.join(src_dir, f) for f in os.listdir(src_dir) if f.endswith('.json')])
21
+ dst_files = sorted([osp.join(dst_dir, f) for f in os.listdir(dst_dir) if f.endswith('.json')])
22
+ assert len(src_files) == len(dst_files), 'src_files and dst_files should have same length'
23
+ for idx, (src_file, dst_file) in enumerate(zip(src_files, dst_files)):
24
+ with open(src_file) as fp:
25
+ src_json = json.load(fp)
26
+ with open(dst_file) as fp:
27
+ dst_json = json.load(fp)
28
+ src_shapes = src_json['shapes']
29
+ dst_shapes = dst_json['shapes']
30
+
31
+ for src_shape in src_shapes:
32
+ if src_shape['label'] == 'bottom_curve':
33
+ dst_shapes.append(src_shape)
34
+ dst_json['shapes'] = dst_shapes
35
+
36
+ with open(dst_file, 'w') as fp:
37
+ json.dump(dst_json, fp)
38
+ print('finish {}/{}'.format(idx+1, len(src_files)))
39
+
40
+
41
+ if __name__ == '__main__':
42
+ main()
normal_test.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''
2
+ @Description: The script is to transfer the normal map from world coordinate to camera coordinate
3
+ '''
4
+ import os, os.path as osp, numpy as np, cv2, argparse, tqdm, pdb
5
+
6
+ def parse_args():
7
+ parser = argparse.ArgumentParser()
8
+ parser.add_argument('--root', type=str)
9
+ parser.add_argument('--out_dir', type=str, default='normal_test')
10
+ return parser.parse_args()
11
+
12
+ def convert_normal_map():
13
+ args = parse_args()
14
+ normal_dir = osp.join(args.root, 'normals')
15
+ normal_paths = sorted([osp.join(normal_dir, name) for name in os.listdir(normal_dir)])
16
+ out_dir = osp.join(args.root, args.out_dir)
17
+ os.makedirs(out_dir, exist_ok=True)
18
+
19
+ for idx, norm_f in enumerate(normal_paths):
20
+ normals = cv2.imread(norm_f)[:, :, ::-1]
21
+ normals = 2.* normals.astype(np.float32)/255. - 1. # [0, 255] -> [-1, 1]
22
+ normals =
23
+ cv2.imwrite(osp.join(out_dir, f'{idx:05d}.png'), normals)
24
+ pdb.set_trace()
25
+
26
+
27
+
28
+
29
+
30
+ def main():
31
+ convert_normal_map()
32
+
33
+ if __name__ == '__main__':
34
+ main()
parsing_mask_to_fl.py ADDED
@@ -0,0 +1,388 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ @File: parsing_mask_to_fl.py
3
+ @Author: Lingteng Qiu
4
+ @Email: qiulingteng@link.cuhk.edu.cn
5
+ @Date: 2022-10-19
6
+ @Desc: parsing mask to polygons, given a series of mask infos
7
+ """
8
+ import sys
9
+ sys.path.extend('./')
10
+ import argparse
11
+ import os
12
+ import glob
13
+ import os.path as osp
14
+ import numpy as np
15
+ import cv2
16
+ import pdb
17
+ import cv2
18
+ import json
19
+ from pytorch3d.ops.knn import knn_points
20
+ import torch
21
+ from utils.constant import FL_EXTRACT, TEMPLATE_GARMENT
22
+ '''
23
+ 关于如何从parsing_mask提取featureline:
24
+ 需要 parse_mask,标的两个点的json文件,但是如果出现了手遮挡住腰间的情况(或者头发遮挡neck),那么就要标注六个点绕过去
25
+ '''
26
+
27
+ FL_COLOR = {
28
+ 'neck':(0, 0, 255),
29
+ 'right_cuff': (0, 255, 0),
30
+ 'left_cuff':(255, 0, 0),
31
+ 'left_pant': (127, 127, 0),
32
+ 'right_pant':(0, 127, 127),
33
+ 'upper_bottom': (127, 0, 127),
34
+ 'bottom_curve':(0, 127, 127),
35
+ }
36
+
37
+ def draw_lines(pts, color, img=None):
38
+ #pdb.set_trace()
39
+ if img is None:
40
+ img = np.zeros((1080, 1080, 3), np.uint8)
41
+ for i in range(len(pts)-1):
42
+ cv2.line(img, (int(pts[i][0]), int(pts[i][1])), (int(pts[i+1][0]), int(pts[i+1][1])), color, 2)
43
+ return img
44
+
45
+ def draw_pts(pts, color, img=None):
46
+ #pdb.set_trace()
47
+ if img is None:
48
+ img = np.zeros((1080, 1080, 3), np.uint8)
49
+ for i, pt in enumerate(pts):
50
+ cv2.circle(img, (int(pt[0]), int(pt[1])), 2, color, -1)
51
+ return img
52
+
53
+
54
+ class PolyMask(object):
55
+ def __init__(self, mask):
56
+ self.mask = mask
57
+
58
+ def query(self,query_sets ,labels, garment_key):
59
+ '''
60
+ query_sets 必须要偶数个 why?
61
+ 1、计算featureline和mask的交点
62
+ 2、如果交点数 > 2,找到一个交点对(两个交点),线段在特征线上并且在mask中的部分最长
63
+ 3、通过这个交点对来获得featureline: 交点对 + 两点之间的mask边界
64
+ Args:
65
+ labels: only cloth?
66
+ '''
67
+
68
+ mask = np.zeros_like(self.mask, dtype= np.bool)
69
+ #pdb.set_trace()
70
+
71
+ for label in labels:
72
+ label_mask = np.zeros_like(self.mask, dtype =np.bool)
73
+ #pdb.set_trace()
74
+ i,j = np.where(self.mask == label)
75
+ label_mask[i,j] = True
76
+
77
+ mask |= label_mask
78
+
79
+ # [0, 255]
80
+ mask = mask.astype(np.uint8)*255
81
+ mask = self.smooth_noise(mask)
82
+
83
+ mask_polygons, mask_area = self.mask2polygon(mask)
84
+ # img_org = cv2.imread('./debug/多边形.png', -1)
85
+ # img=draw_lines(query_sets['neck'], (0, 255, 0), img_org)
86
+ length_dp = []
87
+ for mask_polygon in mask_polygons:
88
+ #pdb.set_trace()
89
+ dis = [0]
90
+ dis.extend([abs(mask_polygon[p_i][0]- mask_polygon[p_i+1][0]) + abs(mask_polygon[p_i][1]- mask_polygon[p_i+1][1]) for p_i in range(mask_polygon.shape[0]-1)])
91
+ dis.append(abs(mask_polygon[0][0]- mask_polygon[-1][0]) + abs(mask_polygon[0][1]- mask_polygon[-1][1]))
92
+ # 累计距离
93
+ dp = np.cumsum(dis)
94
+ length_dp.append(dp)
95
+ new_query_sets = {}
96
+ reply_pts = np.concatenate(mask_polygons, axis=0)
97
+ reply_pts = torch.from_numpy(reply_pts).float().cuda()
98
+
99
+ #pdb.set_trace()
100
+
101
+ for key in query_sets.keys():
102
+ polygon = query_sets[key]
103
+ # len(featureline points) % 2 == 0
104
+ assert polygon.shape[0] % 2 == 0
105
+ # 两两组合
106
+ polygons = polygon.reshape(-1, 2, 2)
107
+
108
+ group = []
109
+ for group_id, mask_polygon in enumerate(mask_polygons):
110
+ group.extend([group_id for i in range(mask_polygon.shape[0])])
111
+ group = torch.tensor(group).long()
112
+ new_polygons=[]
113
+ pre_polygon = None
114
+ # 循环每个顶点对
115
+ for polygon in polygons:
116
+
117
+ polygon = torch.from_numpy(polygon).float().cuda()
118
+ if pre_polygon is not None:
119
+ dis = torch.sqrt(((polygon[0] - pre_polygon[-1]) **2).sum())
120
+ # if two pts are close, directly add the polygon the new_polygons, avoid the situation that the hands or hair block the mask
121
+ if dis < 10:
122
+ new_polygons.append(polygon.detach().cpu().numpy())
123
+ pre_polygon = None
124
+ continue
125
+ pre_polygon = polygon.detach().clone()
126
+
127
+ # find the nearest edge in mask of the featureline
128
+ dist = knn_points(polygon[None], reply_pts[None])
129
+ idx = dist.idx[0, ...,0]
130
+ group_id = group[idx]
131
+
132
+ if dist.dists.max()>1000:
133
+ new_polygons.append(polygon.detach().cpu().numpy())
134
+ continue
135
+
136
+
137
+ # pick the id which is in a larger mask area => pick which the mask area
138
+ prefer_id = group_id[0] if mask_area[group_id[0]] > mask_area[group_id[1]] else group_id[1]
139
+ prefer_pts = torch.from_numpy(mask_polygons[prefer_id]).float().cuda()
140
+ # find the nearest edge in mask of the featureline two points
141
+ dist = knn_points(polygon[None], prefer_pts[None])
142
+ idx = dist.idx[0, ...,0].sort()
143
+ polygon= polygon[idx.indices]
144
+ idx=idx.values
145
+
146
+ reverse_flag = (not idx[0] == dist.idx[0, 0, 0])
147
+
148
+
149
+ # obtain slice_curve
150
+
151
+ dp = length_dp[prefer_id]
152
+ # compute the length of the two points in mask edge
153
+ # find the shortest path
154
+ slice_a = dp[idx[1]] - dp[idx[0]]
155
+ slice_b = dp[-1] - slice_a
156
+
157
+ #obtain slice_b
158
+ if slice_a>slice_b:
159
+ # 找最短的路径,当前这个edge的后一个点
160
+ segment = torch.cat([polygon[1:],prefer_pts[idx[1]:], prefer_pts[:idx[0]+1], polygon[0:1]], dim = 0)
161
+ reverse_flag = (not reverse_flag)
162
+
163
+ else:
164
+ segment = torch.cat([polygon[0:1], prefer_pts[idx[0]:idx[1]+1], polygon[1:]], dim=0)
165
+
166
+ segment = segment.detach().cpu().numpy()
167
+ if reverse_flag:
168
+ segment = segment[::-1]
169
+
170
+ new_polygons.append(segment)
171
+
172
+
173
+ new_polygons = np.concatenate(new_polygons, axis = 0)
174
+ new_query_sets[key] = new_polygons
175
+ #pdb.set_trace()
176
+ return new_query_sets, mask
177
+
178
+ def smooth_noise(self, mask):
179
+ kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5, 5))
180
+ mask = cv2.erode(mask, kernel, iterations=2)
181
+ mask = cv2.dilate(mask, kernel, iterations=2)
182
+
183
+ return mask
184
+
185
+ def mask2polygon(self, mask):
186
+ contours, hierarchy = cv2.findContours((mask).astype(np.uint8), cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
187
+ # mask_new, contours, hierarchy = cv2.findContours((mask).astype(np.uint8), cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
188
+ segmentation = []
189
+ polygon_size = []
190
+ for contour in contours:
191
+ contour_list = contour.flatten().tolist()
192
+ if len(contour_list) > 4:# and cv2.contourArea(contour)>10000
193
+
194
+ area = self.polygons_to_mask(mask.shape, contour_list).sum()
195
+ polygon_size.append(area)
196
+
197
+ contour_numpy = np.asarray(contour_list).reshape(-1, 2)
198
+ segmentation.append(contour_numpy)
199
+
200
+
201
+ return segmentation, polygon_size
202
+
203
+ def polygons_to_mask(self, img_shape, polygons):
204
+ mask = np.zeros(img_shape, dtype=np.uint8)
205
+
206
+ polygons = np.asarray(polygons, np.int32) # 这里必须是int32,其他类型使用fillPoly会报错
207
+ shape=polygons.shape
208
+
209
+ polygons=polygons.reshape(-1,2)
210
+ cv2.fillPoly(mask, [polygons],color=1) # 非int32 会报错
211
+ return mask
212
+
213
+
214
+
215
+ def get_upper_bttom_type(parsing_type, key):
216
+
217
+ # 'ATR': ['Background', 'Hat', 'Hair', 'Sunglasses', 'Upper-clothes', 'Skirt', 'Pants', 'Dress', 'Belt',
218
+ # 'Left-shoe', 'Right-shoe', 'Face', 'Left-leg', 'Right-leg', 'Left-arm', 'Right-arm', 'Bag', 'Scarf'],
219
+ ATR_PARSING = {
220
+ 'upper':[4, 16, 17], # 4: upper-clothes, 16: Bag, 17: Scarf
221
+ #'upper':[4], # 4: upper-clothes, 16: Bag, 17: Scarf
222
+ #without head
223
+ # 'upper':[1, 2, 3, 4, 11, 16, 17],
224
+ 'bottom':[5, 6, 8],
225
+ #'bottom':[5, 6 ], # 5: skirt, 6: pants, 8: belt
226
+ # with head and hand
227
+ #'upper_bottom':[4, 5, 6, 7 ]
228
+ 'upper_bottom':[4, 5, 6, 7, 8, 16, 17]
229
+ }
230
+ CLO_PARSING = {
231
+ # with head and hand
232
+ 'upper':[1,2,3],
233
+ #without head
234
+ # 'upper':[1, 2, 3, 4, 11, 16, 17],
235
+ 'bottom':[1,2,3],
236
+ # with head and hand
237
+ 'upper_bottom':[1,2,3]
238
+ # w/o hand
239
+ # 'upper_bottom':[4, 5, 7, 16, 17]
240
+ }
241
+
242
+ if parsing_type =='ATR':
243
+ return ATR_PARSING[key]
244
+ else:
245
+ return CLO_PARSING[key]
246
+
247
+
248
+ def get_parsing_label(parsing_type):
249
+ parsing_table ={
250
+ 'ATR': ['Background', 'Hat', 'Hair', 'Sunglasses', 'Upper-clothes', 'Skirt', 'Pants', 'Dress', 'Belt',
251
+ 'Left-shoe', 'Right-shoe', 'Face', 'Left-leg', 'Right-leg', 'Left-arm', 'Right-arm', 'Bag', 'Scarf'],
252
+ 'CLO':['background', 'upper', 'bottom', 'upper-bottom']
253
+ }
254
+
255
+ return parsing_table[parsing_type]
256
+
257
+ def get_parse():
258
+ parser = argparse.ArgumentParser(description='')
259
+ parser.add_argument('--parsing_type', default='ATR', help='garment_parsing type', choices=['ATR', 'CLO'])
260
+ parser.add_argument('--input_path', default='', help='select model')
261
+ parser.add_argument('--output_path', default='', help='polygons output')
262
+
263
+ args = parser.parse_args()
264
+ return args
265
+
266
+ def parsing_curve(query_file, parsing_file, parsing_type, class_type, debug_path, name):
267
+
268
+ query_sets = {}
269
+ with open(query_file) as reader:
270
+ fl_infos = json.load(reader)
271
+ shapes = fl_infos['shapes']
272
+ for fl in shapes:
273
+ query_sets[fl['label']] = np.asarray(fl['points']).astype(np.float32)
274
+
275
+ class_table = dict(
276
+ female_outfit3=['upper_bottom'],
277
+ female_outfit1=['upper_bottom'],
278
+ anran_run = ['short_sleeve_upper', 'skirt'],
279
+ anran_tic = ['short_sleeve_upper', 'skirt'],
280
+ leyang_jump = ['dress'],
281
+ leyang_steps = ['dress'],
282
+ )
283
+
284
+ garment_table = dict(
285
+ short_sleeve_upper='upper',
286
+ skirt='bottom',
287
+ dress='upper_bottom',
288
+ long_sleeve_upper='upper',
289
+ long_pants='bottom',
290
+ short_pants='bottom',
291
+ )
292
+
293
+ masks = np.load(parsing_file, allow_pickle= True) # [H, W]
294
+ parsing_name = parsing_file.split('/')[-1]
295
+
296
+ poly_mask = PolyMask(masks)
297
+ new_query_sets = {}
298
+
299
+ for garment_key in TEMPLATE_GARMENT[class_type]:
300
+ pdb.set_trace()
301
+ garment_class = get_upper_bttom_type(parsing_type, garment_table[garment_key])
302
+ fl_names = 'bottom_curve' #FL_EXTRACT[garment_key]
303
+ fl_query_sets = {}
304
+
305
+ for fl_name in fl_names:
306
+ if fl_name in query_sets.keys():
307
+ fl_query_sets[fl_name] = query_sets[fl_name]
308
+
309
+ #pdb.set_trace()
310
+ new_fl_query_sets, mask = poly_mask.query(fl_query_sets, garment_class, garment_key)
311
+ new_query_sets.update(new_fl_query_sets)
312
+
313
+ cv2.imwrite(osp.join(debug_path, 'mask_{}_'.format(garment_key)+name), mask)
314
+
315
+ return new_query_sets, mask
316
+
317
+
318
+ def main(args):
319
+ # ATR, CLO
320
+ parsing_type = args.parsing_type
321
+ parsing_label = get_parsing_label(parsing_type)
322
+ parsing_dir = osp.join(args.input_path, 'parsing_SCH_{}'.format(parsing_type))
323
+ img_dir = osp.join(args.input_path, 'imgs/')
324
+ #json_files = sorted(glob.glob(osp.join(args.input_path, 'featurelines/*.json')))
325
+ json_files = sorted(glob.glob(osp.join(args.input_path, 'json_hand_label_no_bottom_curve/*.json')))
326
+ img_files = sorted(glob.glob(osp.join(img_dir, '*.jpg')))
327
+ img_files += sorted(glob.glob(osp.join(img_dir, '*.png')))
328
+ # get the id: 000342
329
+ json_key = [json_file.split('/')[-1][:-5] for json_file in json_files]
330
+
331
+ parsing_files = sorted(glob.glob(osp.join(parsing_dir,'*.npy')))
332
+ # given the small json files (less than no.imgs), find the corresponding parsing files and img files
333
+ filter_parsing_files = list(filter(lambda x: x.split('/')[-1].split('_')[-1][:-4] in json_key, parsing_files))
334
+ filter_img_files = list(filter(lambda x: x.split('/')[-1][:-4] in json_key, img_files))
335
+
336
+ if args.input_path[-1] =='/':
337
+ input_path = args.input_path[:-1]
338
+ else:
339
+ input_path = args.input_path
340
+
341
+ class_type = input_path.split('/')[-1]
342
+ debug_path = osp.join('./debug/{}/polymask'.format(class_type))
343
+ output_path = args.output_path
344
+ os.makedirs(output_path, exist_ok = True)
345
+ os.makedirs(debug_path, exist_ok= True)
346
+
347
+ for idx, (parsing_file, json_file, filter_img_file) in enumerate(zip(filter_parsing_files, json_files, filter_img_files)):
348
+ pdb.set_trace()
349
+ print('processing: {}'.format(filter_img_file))
350
+ img = cv2.imread(filter_img_file)
351
+ name = filter_img_file.split('/')[-1]
352
+ # if idx == 5:
353
+ # pdb.set_trace()
354
+
355
+ new_query_sets, mask = parsing_curve(json_file, parsing_file, args.parsing_type, class_type, debug_path, name)
356
+
357
+ with open(json_file) as reader:
358
+ fl_infos = json.load(reader)
359
+ shapes = fl_infos['shapes']
360
+ for fl in shapes:
361
+ # query_sets[fl['label']] = np.asarray(fl['points']).astype(np.float32)
362
+ fl['points']= new_query_sets[fl['label']].tolist()
363
+
364
+
365
+ json_name = json_file.split('/')[-1]
366
+ new_json_file = os.path.join(output_path, json_name)
367
+ with open(new_json_file, 'w') as writer:
368
+ json.dump(fl_infos, writer)
369
+
370
+
371
+ for key in new_query_sets.keys():
372
+ color = FL_COLOR[key]
373
+ pt_list = new_query_sets[key].astype(np.int)
374
+ for pt in new_query_sets[key].astype(np.int):
375
+ img = cv2.circle(img, (pt[0], pt[1]),2, color,2)
376
+
377
+ for pt_idx in range(pt_list.shape[0]-1):
378
+ img = cv2.line(img, (pt_list[pt_idx][0],pt_list[pt_idx][1]), (pt_list[pt_idx+1][0],pt_list[pt_idx+1][1]), color, 2)
379
+
380
+
381
+ cv2.imwrite(osp.join(debug_path, name), img)
382
+
383
+ if __name__ == '__main__':
384
+
385
+ args = get_parse()
386
+ main(args)
387
+
388
+
process_data_all.py ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''
2
+ @Author: Jiapeng Zhou
3
+ @Email: jiapengzhou@link.cuhk.edu.cn
4
+ @Desc: script to process all data of RECMV.
5
+ Before run this bash, what you only need to do is :
6
+ - run openpose to get keypoints.json file in the dir: (self.root, openpose)
7
+ - have a conda environment of videoavatar, named: "videoavatar"
8
+ Usage: python process_data_all.py --root ~/DeepDxxx/xinyu_a/ --gid 0 --gender female
9
+ '''
10
+
11
+ import pdb, os, os.path as osp, sys, argparse
12
+ from typing import Any
13
+ import numpy as np, cv2
14
+
15
+ class RECMVDataProcessor():
16
+ def __init__(self, args) -> None:
17
+ self.args = args
18
+ self.gender = args.gender
19
+
20
+ self.root = args.root
21
+ #out = osp.join(self.root, args.out)
22
+ #os.makedirs(out, exist_ok=True)
23
+ self.img_dir = osp.join(self.root, 'imgs')
24
+ assert osp.exists(self.img_dir) and len(os.listdir(self.img_dir)) > 0, 'img file does not exist'
25
+ self.gid = args.gid
26
+
27
+ def __len__(self):
28
+ return len(os.listdir(self.img_dir))
29
+
30
+ def __call__(self):
31
+ '''get normals, ATR-parsing, masks, camera, smpl_params, depth, featurelines'''
32
+
33
+ # get ATR_parsing
34
+ self.get_ATR_parsing()
35
+
36
+ # get masks
37
+ self.get_masks()
38
+
39
+ # get normal from pifuhd
40
+ self.get_normals()
41
+
42
+ '''cannot directly ca videoavatar
43
+ # get reconstructed_poses.hdf5 from videoavatar
44
+ self.get_poses()
45
+
46
+ # get camera.npz and smpl_rec.npz
47
+ self.get_camera_smpl_rec()
48
+
49
+ '''
50
+
51
+ # get depth
52
+ #self.get_depth()
53
+
54
+ # get featurelines
55
+ #self.get_featurelines()
56
+
57
+ def get_featurelines(self):
58
+ fl_dir = osp.join(self.root, 'featurelines')
59
+ if osp.exists(fl_dir) and len(os.listdir(fl_dir)) >= self.__len__():
60
+ print('featurelines files exists')
61
+ else:
62
+ print('featurelines file does not exist')
63
+
64
+ def get_depth(self):
65
+ depth_dir = osp.join(self.root, 'depth')
66
+ if osp.exists(depth_dir) and len(os.listdir(depth_dir)) >= self.__len__():
67
+ print('depth files exists')
68
+ else:
69
+ print('depth file does not exist')
70
+
71
+ def get_masks(self):
72
+ mask_dir = osp.join(self.root, 'masks')
73
+ if osp.exists(mask_dir) and len(os.listdir(mask_dir)) >= self.__len__():
74
+ print('mask files exists')
75
+ return
76
+ os.makedirs(mask_dir, exist_ok=True)
77
+ # mask是否需要按照单通道保存?
78
+ print('\n-----------------Getting Masks-------------------------')
79
+ os.system(f'cd ./RobustVideoMatting && python inference_itw_rotate.py \
80
+ --input_pth {self.img_dir} --output_pth {mask_dir} --device {self.gid}')
81
+
82
+
83
+ def get_normals(self):
84
+ normal_dir = osp.join(self.root, 'normals')
85
+ if osp.exists(normal_dir) and len(os.listdir(normal_dir)) >= self.__len__():
86
+ print('normal files exists')
87
+ return
88
+
89
+ print('\n-------------------Getting Normals----------------------')
90
+ os.makedirs(normal_dir, exist_ok=True)
91
+ os.system('cd ./pifuhd && python ./generate_normals.py --gid {} --imgpath {}'.format(self.gid, self.img_dir))
92
+
93
+ def get_ATR_parsing(self):
94
+ input_dir = osp.join(self.root, 'imgs')
95
+ output_dir = osp.join(self.root, 'parsing_SCH_ATR')
96
+ if osp.exists(output_dir) and len(os.listdir(output_dir)) >= self.__len__():
97
+ print('ATR parsing files exists')
98
+ return
99
+ print('\n--------------------Getting ATR_Parsing------------------')
100
+ os.makedirs(output_dir, exist_ok=True)
101
+
102
+ os.system(f'cd ./Self-Correction-Human-Parsing && python simple_extractor.py \
103
+ --dataset atr --model-restore exp-schp-201908301523-atr.pth --gpu {self.gid} \
104
+ --input-dir {self.img_dir} --output-dir {output_dir} --logits')
105
+
106
+
107
+ def get_poses(self):
108
+ openpose_p = osp.join(self.root, 'openpose')
109
+ assert osp.exists(openpose_p) and len(os.listdir(openpose_p)) >= self.__len__(), 'openpose keypoint folder doesnot exist or it is emtpy'
110
+
111
+ output_dir = osp.join(self.root, 'videoavatars')
112
+ if osp.exists(output_dir) and osp.exists(osp.join(output_dir, 'reconstructed_poses.hdf5')):
113
+ print('reconstructed_poses.hdf5 files exists')
114
+ return
115
+
116
+ print('\n------------------Getting Poses---------------------------')
117
+ os.makedirs(output_dir, exist_ok=True)
118
+ # Note: Here needs to conda actiavte the environment of videoavatar
119
+ os.system(f'cd ./videoavatars && bash get_reconstructed_poses.sh {self.root} {output_dir} {self.gender}')
120
+
121
+
122
+ def get_camera_smpl_rec(self):
123
+ if osp.exists(osp.join(self.root, 'camera.npz')) and osp.exists(osp.join(self.root, 'smpl_rec.npz')):
124
+ print('camera.npz and smpl_rec.npz files exists')
125
+ return
126
+
127
+ print('\n---------------------Getting camera and smpl_rec--------------------')
128
+ os.system(' python get_smpl_rec_camera.py --root {} --save_root {} --gender {}'.\
129
+ format(osp.join(self.root, 'videoavatars'), self.root, self.gender))
130
+
131
+
132
+
133
+
134
+ def parse_args():
135
+ parser = argparse.ArgumentParser()
136
+ parser.add_argument('--gid', type=int, default=0)
137
+ parser.add_argument('--root', type=str, required=True)
138
+ parser.add_argument('--gender', type=str, choices=['male', 'female'], required=True)
139
+ args = parser.parse_args()
140
+ return args
141
+
142
+ def main():
143
+ args = parse_args()
144
+ processor = RECMVDataProcessor(args)
145
+ processor()
146
+
147
+ if __name__ == '__main__':
148
+ main()
149
+
rename.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, os.path as osp, sys, shutil, argparse, re, glob, time, argparse, pdb
2
+
3
+ def rename(dir):
4
+ for root, dirs, files in os.walk(dir):
5
+ pdb.set_trace()
6
+ for file in files:
7
+ if file.endswith('.npy'):
8
+ new_name = file.split('_')[-1]
9
+ new_name = osp.join(root, new_name)
10
+
11
+ old_name = os.path.join(root, file)
12
+ os.rename(old_name, new_name)
13
+ print('Renamed {} to {}'.format(old_name, new_name))
14
+
15
+
16
+ if __name__ == '__main__':
17
+ dir = '/home/zjp/DeepDynamicFashion/REC-MV/data/yanzhi_a/parsing'
18
+ rename(dir)
requirements.txt ADDED
@@ -0,0 +1,266 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ absl-py==1.4.0
2
+ addict==2.4.0
3
+ aiohttp==3.8.1
4
+ aioice==0.7.6
5
+ aiortc==1.3.2
6
+ aiosignal==1.3.1
7
+ alabaster==0.7.13
8
+ anyio==3.6.2
9
+ appdirs==1.4.4
10
+ argon2-cffi==21.3.0
11
+ argon2-cffi-bindings==21.2.0
12
+ asttokens==2.2.1
13
+ async-timeout==4.0.2
14
+ attrs==22.2.0
15
+ aux==0.0.2
16
+ av==8.0.3
17
+ Babel==2.11.0
18
+ backcall==0.2.0
19
+ bcrypt==4.0.1
20
+ beautifulsoup4==4.11.2
21
+ bidict==0.22.1
22
+ bleach==6.0.0
23
+ blessed==1.20.0
24
+ cachetools==5.3.0
25
+ certifi==2022.12.7
26
+ cffi==1.15.1
27
+ chardet==4.0.0
28
+ charset-normalizer==2.0.12
29
+ chumpy==0.70
30
+ click==8.1.3
31
+ colorama==0.4.6
32
+ comm==0.1.2
33
+ commonmark==0.9.1
34
+ ConfigArgParse==1.5.3
35
+ cppcuda-tutorial @ file:///home/zjp/Learning/pytorch_cppcuda_tutorial
36
+ cryptography==39.0.0
37
+ cycler==0.11.0
38
+ d2l==0.17.6
39
+ dash==2.8.1
40
+ dash-core-components==2.0.0
41
+ dash-html-components==2.0.0
42
+ dash-table==5.0.0
43
+ datasets==2.12.0
44
+ debugpy==1.6.6
45
+ decorator==5.1.1
46
+ defusedxml==0.7.1
47
+ descartes==1.1.0
48
+ dill==0.3.6
49
+ dnspython==2.3.0
50
+ docker-pycreds==0.4.0
51
+ docstring-parser==0.14.1
52
+ docutils==0.19
53
+ einops==0.6.0
54
+ exceptiongroup==1.1.1
55
+ executing==1.2.0
56
+ fabric==3.0.0
57
+ fastjsonschema==2.16.2
58
+ FastMinv==0.0.0
59
+ filelock==3.9.0
60
+ filterpy==1.4.5
61
+ fire==0.5.0
62
+ Flask==2.2.2
63
+ fonttools==4.38.0
64
+ freetype-py==2.3.0
65
+ frozendict==2.3.4
66
+ frozenlist==1.3.3
67
+ fsspec==2023.5.0
68
+ fvcore==0.1.5.post20221221
69
+ gdown==4.5.1
70
+ gitdb==4.0.10
71
+ GitPython==3.1.30
72
+ google-auth==2.16.0
73
+ google-auth-oauthlib==1.0.0
74
+ google-crc32c==1.5.0
75
+ gpustat==1.0.0
76
+ grpcio==1.51.1
77
+ h5py==3.8.0
78
+ happytransformer==2.4.1
79
+ huggingface-hub==0.14.1
80
+ idna==2.10
81
+ imageio==2.21.1
82
+ imagesize==1.4.1
83
+ importlib-metadata==6.0.0
84
+ importlib-resources==5.10.2
85
+ iniconfig==2.0.0
86
+ interplate==0.0.0
87
+ invoke==2.0.0
88
+ iopath==0.1.10
89
+ ipykernel==6.21.1
90
+ ipython==8.9.0
91
+ ipython-genutils==0.2.0
92
+ ipywidgets==8.0.4
93
+ itsdangerous==2.1.2
94
+ jedi==0.18.2
95
+ Jinja2==3.1.2
96
+ joblib==1.2.0
97
+ json5==0.9.11
98
+ jsonschema==4.17.3
99
+ jupyter==1.0.0
100
+ jupyter-console==6.4.4
101
+ jupyter-server==1.23.5
102
+ jupyter_client==8.0.2
103
+ jupyter_core==5.2.0
104
+ jupyterlab==3.3.4
105
+ jupyterlab-pygments==0.2.2
106
+ jupyterlab-widgets==3.0.5
107
+ kiwisolver==1.4.4
108
+ linecache2==1.0.0
109
+ lpips==0.1.4
110
+ lxml==4.9.2
111
+ Markdown==3.4.1
112
+ MarkupSafe==2.1.2
113
+ matplotlib==3.5.1
114
+ matplotlib-inline==0.1.6
115
+ MCGpu==0.0.0
116
+ mediapy==1.1.0
117
+ mistune==2.0.4
118
+ msgpack==1.0.4
119
+ msgpack-numpy==0.4.8
120
+ multidict==6.0.4
121
+ multiprocess==0.70.14
122
+ nbclassic==0.5.1
123
+ nbclient==0.7.2
124
+ nbconvert==7.2.9
125
+ nbformat==5.5.0
126
+ nerfacc==0.3.4
127
+ nest-asyncio==1.5.6
128
+ netifaces==0.11.0
129
+ networkx==3.0
130
+ ninja==1.11.1
131
+ nose==1.3.7
132
+ notebook==6.5.2
133
+ notebook_shim==0.2.2
134
+ numpy==1.21.5
135
+ nuscenes-devkit==1.1.9
136
+ nvidia-ml-py==11.495.46
137
+ oauthlib==3.2.2
138
+ open3d==0.16.0
139
+ opencv-python==4.6.0.66
140
+ openmesh==1.2.1
141
+ packaging==23.0
142
+ pandas==1.2.4
143
+ pandocfilters==1.5.0
144
+ paramiko==3.1.0
145
+ parso==0.8.3
146
+ pathtools==0.1.2
147
+ pexpect==4.8.0
148
+ pickleshare==0.7.5
149
+ Pillow==9.4.0
150
+ PIMS==0.5
151
+ pkgutil_resolve_name==1.3.10
152
+ platformdirs==2.6.2
153
+ plotly==5.7.0
154
+ pluggy==1.0.0
155
+ portalocker==2.7.0
156
+ POT==0.9.0
157
+ prometheus-client==0.16.0
158
+ prompt-toolkit==3.0.36
159
+ protobuf==3.20.0
160
+ psutil==5.9.4
161
+ ptyprocess==0.7.0
162
+ pure-eval==0.2.2
163
+ pyarrow==12.0.0
164
+ pyasn1==0.4.8
165
+ pyasn1-modules==0.2.8
166
+ pycocotools==2.0.6
167
+ pycparser==2.21
168
+ pyee==9.0.4
169
+ pyglet==2.0.5
170
+ Pygments==2.14.0
171
+ pyhocon==0.3.60
172
+ pylibsrtp==0.8.0
173
+ pymeshlab==2022.2.post2
174
+ PyNaCl==1.5.0
175
+ pyngrok==5.1.0
176
+ PyOpenGL==3.1.0
177
+ pyparsing==3.0.9
178
+ pyquaternion==0.9.9
179
+ pyrender==0.1.45
180
+ pyrsistent==0.19.3
181
+ PySocks==1.7.1
182
+ pytest==7.3.1
183
+ python-dateutil==2.8.2
184
+ python-engineio==4.3.4
185
+ python-socketio==5.7.1
186
+ pytorch3d==0.4.0
187
+ pytz==2022.7.1
188
+ PyWavelets==1.4.1
189
+ PyYAML==6.0
190
+ pyzmq==25.0.0
191
+ qtconsole==5.4.0
192
+ QtPy==2.3.0
193
+ regex==2023.5.5
194
+ requests==2.25.1
195
+ requests-oauthlib==1.3.1
196
+ responses==0.18.0
197
+ rich==12.5.1
198
+ rsa==4.9
199
+ scikit-image==0.19.3
200
+ scikit-learn==1.2.1
201
+ scikit-sparse==0.4.8
202
+ scipy==1.10.0
203
+ seaborn==0.12.2
204
+ Send2Trash==1.8.0
205
+ sentencepiece==0.1.99
206
+ sentry-sdk==1.14.0
207
+ setproctitle==1.3.2
208
+ shapely==2.0.1
209
+ shtab==1.5.8
210
+ six==1.16.0
211
+ slicerator==1.1.0
212
+ smmap==5.0.0
213
+ smplx==0.1.28
214
+ sniffio==1.3.0
215
+ snowballstemmer==2.2.0
216
+ soupsieve==2.3.2.post1
217
+ Sphinx==6.1.3
218
+ sphinxcontrib-applehelp==1.0.4
219
+ sphinxcontrib-devhelp==1.0.2
220
+ sphinxcontrib-htmlhelp==2.0.1
221
+ sphinxcontrib-jsmath==1.0.1
222
+ sphinxcontrib-qthelp==1.0.3
223
+ sphinxcontrib-serializinghtml==1.1.5
224
+ stack-data==0.6.2
225
+ tabulate==0.9.0
226
+ tenacity==8.1.0
227
+ tensorboard==2.12.1
228
+ tensorboard-data-server==0.7.0
229
+ tensorboard-plugin-wit==1.8.1
230
+ termcolor==2.2.0
231
+ terminado==0.17.1
232
+ threadpoolctl==3.1.0
233
+ tifffile==2023.2.3
234
+ tinycss2==1.2.1
235
+ tinycudann==1.7
236
+ tokenizers==0.13.3
237
+ tomli==2.0.1
238
+ torch==1.10.2+cu113
239
+ torch-fidelity==0.3.0
240
+ torch-scatter==2.0.9
241
+ torchmetrics==0.11.1
242
+ torchtyping==0.1.4
243
+ torchvision==0.11.3+cu113
244
+ tornado==6.2
245
+ tqdm==4.65.0
246
+ traceback2==1.4.0
247
+ traitlets==5.9.0
248
+ transformers==4.28.1
249
+ trimesh==3.18.3
250
+ typeguard==2.13.3
251
+ typing_extensions==4.4.0
252
+ tyro==0.3.38
253
+ u-msgpack-python==2.7.2
254
+ unittest2==1.1.0
255
+ urllib3==1.26.14
256
+ wandb==0.13.9
257
+ wcwidth==0.2.6
258
+ webencodings==0.5.1
259
+ websocket-client==1.5.1
260
+ Werkzeug==2.2.2
261
+ widgetsnbextension==4.0.5
262
+ xatlas==0.0.7
263
+ xxhash==3.2.0
264
+ yacs==0.1.8
265
+ yarl==1.8.2
266
+ zipp==3.12.1
smpl_process.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''
2
+ @Desc: This file is used to process the smpl: convert rotation matrix to axis-angle
3
+ '''
4
+
5
+ import numpy as np
6
+ import os, os.path as osp, sys, pdb, argparse
7
+ from scipy.spatial.transform import Rotation
8
+
9
+ def convert_rotmat_to_axis_angle(rotmat):
10
+ '''
11
+ Args: rotmat: (N, 3, 3)
12
+ Return: axis_angle: (N, 3)
13
+ '''
14
+ rotation = Rotation.from_matrix(rotmat)
15
+ axis_angle = rotation.as_rotvec()
16
+ return axis_angle
17
+
18
+ def parse_args():
19
+ argparser = argparse.ArgumentParser()
20
+ argparser.add_argument('--root', help='the root dir of an identity')
21
+ argparser.add_argument('--smpl_file')
22
+ return argparser.parse_args()
23
+
24
+ def main():
25
+ args = parse_args()
26
+ root = args.root
27
+ smpl_file = osp.join(root, args.smpl_file)
28
+ npz = np.load(smpl_file, allow_pickle=True)
29
+ smpl_params = {}
30
+ for key in npz.keys():
31
+ smpl_params[key] = npz[key]
32
+
33
+ pdb.set_trace()
34
+ rotmat_batch = smpl_params['poses'].reshape(-1, 3, 3)
35
+ smpl_params['poses'] = convert_rotmat_to_axis_angle(rotmat_batch).reshape(-1, 24, 3)
36
+ np.savez(smpl_file, **smpl_params)
37
+ return
38
+
39
+ if __name__ == '__main__':
40
+ main()