当前位置:   article > 正文

使用pyskl训练自己的数据集_python如何训练数据

python如何训练数据

1.数据集的准备

参考这个博主的:数据集准备

2.生成train.json和test.json

由于我是用的命名方式是A后面是类别,R后面是次数,所以更改了两个地方。
注意:label 是从0开始的,所以需要-1。
我的代码都是在/root/pyskl下运行的。
  1. import os
  2. import json
  3. import decord
  4. def writeJson(path_train, jsonpath):
  5. outpot_list = []
  6. trainfile_list = os.listdir(path_train)
  7. for train_name in trainfile_list:
  8. traindit = {}
  9. sp = train_name.split('A')
  10. sp2 = sp[1].split('R')
  11. traindit['vid_name'] = train_name.replace('.avi', '')
  12. traindit['label'] = int(sp2[0])-1
  13. traindit['start_frame'] = 0
  14. video_path = os.path.join(path_train, train_name)
  15. vid = decord.VideoReader(video_path)
  16. traindit['end_frame'] = len(vid)
  17. outpot_list.append(traindit.copy())
  18. with open(jsonpath, 'w') as outfile:
  19. json.dump(outpot_list, outfile)
  20. def main():
  21. path = './mydata/train'
  22. j_path = './mydata/train.json'
  23. writeJson(path,j_path)
  24. if __name__ == '__main__':
  25. main()
 路径是:~/pyskl/mydata/test和~/pyskl/mydata/train
上面的代码为create_json.py,路径是~/pyskl/json
终端在pyskl的环境下:
python json/create_json.py
就能在 ~/pyskl/mydata路径下看到生成的test.js和train.js文件了
用记事本打开是这样的

3.生成tools/data/custom_2d_skeleton.py需要的list文件

  1. import os
  2. def mwlines(lines, fname):
  3. with open(fname, 'w') as fout:
  4. fout.write('\n'.join(lines))
  5. def writeList(dirpath, name):
  6. path_train = os.path.join(dirpath, 'train')
  7. path_test = os.path.join(dirpath, 'test')
  8. trainfile_list = os.listdir(path_train)
  9. testfile_list = os.listdir(path_test)
  10. train = []
  11. for train_name in trainfile_list:
  12. traindit = {}
  13. sp = train_name.split('A')
  14. sp2 = sp[1].split('R')
  15. traindit['vid_name'] = train_name
  16. traindit['label'] = int(sp2[0])-1
  17. train.append(traindit)
  18. test = []
  19. for test_name in testfile_list:
  20. testdit = {}
  21. sp3 = test_name.split('A')
  22. sp4 = sp3[1].split('R')
  23. testdit['vid_name'] = test_name
  24. testdit['label'] = int(sp4[0])-1
  25. test.append(testdit)
  26. tmpl1 = os.path.join(path_train, '{}')
  27. lines1 = [(tmpl1 + ' {}').format(x['vid_name'], x['label']) for x in train]
  28. tmpl2 = os.path.join(path_test, '{}')
  29. lines2 = [(tmpl2 + ' {}').format(x['vid_name'], x['label']) for x in test]
  30. lines = lines1 + lines2
  31. mwlines(lines, os.path.join(dirpath, name))
  32. if __name__ == '__main__':
  33. path = './mydata'
  34. name = 'mydata.list'
  35. writeList(path, name)
上面的代码为create_list.py,路径是~/pyskl/json
path是数据集的路径:我的是~/pyskl/mydata
name为生成的list文件名称,这里为 ‘mydata’,不要忘记加.list,不然生成的不是.list文件。
运行代码:
 python json/create_list.py
记事本打开mydata.list

4.调用custom_2d_skeleton.py,生成训练模型要用的pkl文件

  1. # Copyright (c) OpenMMLab. All rights reserved.
  2. import argparse
  3. import copy as cp
  4. import decord
  5. import mmcv
  6. import numpy as np
  7. import os
  8. import os.path as osp
  9. import torch.distributed as dist
  10. from mmcv.runner import get_dist_info, init_dist
  11. from tqdm import tqdm
  12. import pyskl # noqa: F401
  13. from pyskl.smp import mrlines
  14. try:
  15. import mmdet # noqa: F401
  16. from mmdet.apis import inference_detector, init_detector
  17. except (ImportError, ModuleNotFoundError):
  18. raise ImportError('Failed to import `inference_detector` and '
  19. '`init_detector` form `mmdet.apis`. These apis are '
  20. 'required in this script! ')
  21. try:
  22. import mmpose # noqa: F401
  23. from mmpose.apis import inference_top_down_pose_model, init_pose_model
  24. except (ImportError, ModuleNotFoundError):
  25. raise ImportError('Failed to import `inference_top_down_pose_model` and '
  26. '`init_pose_model` form `mmpose.apis`. These apis are '
  27. 'required in this script! ')
  28. pyskl_root = osp.dirname(pyskl.__path__[0])
  29. default_det_config = f'{pyskl_root}/demo/faster_rcnn_r50_fpn_1x_coco-person.py'
  30. default_det_ckpt = ('./faster_rcnn_r50_fpn_1x_coco-person_20201216_175929-d022e227.pth')
  31. # default_det_ckpt = (
  32. # 'https://download.openmmlab.com/mmdetection/v2.0/faster_rcnn/faster_rcnn_r50_fpn_1x_coco-person/'
  33. # 'faster_rcnn_r50_fpn_1x_coco-person_20201216_175929-d022e227.pth')
  34. default_pose_config = f'{pyskl_root}/demo/hrnet_w32_coco_256x192.py'
  35. default_pose_ckpt = ('./hrnet_w32_coco_256x192-c78dce93_20200708.pth')
  36. # default_pose_ckpt = (
  37. # 'https://download.openmmlab.com/mmpose/top_down/hrnet/'
  38. # 'hrnet_w32_coco_256x192-c78dce93_20200708.pth')
  39. def extract_frame(video_path):
  40. vid = decord.VideoReader(video_path)
  41. return [x.asnumpy() for x in vid]
  42. def detection_inference(model, frames):
  43. results = []
  44. for frame in frames:
  45. result = inference_detector(model, frame)
  46. results.append(result)
  47. return results
  48. def pose_inference(anno_in, model, frames, det_results, compress=False):
  49. anno = cp.deepcopy(anno_in)
  50. assert len(frames) == len(det_results)
  51. total_frames = len(frames)
  52. num_person = max([len(x) for x in det_results])
  53. anno['total_frames'] = total_frames
  54. anno['num_person_raw'] = num_person
  55. if compress:
  56. kp, frame_inds = [], []
  57. for i, (f, d) in enumerate(zip(frames, det_results)):
  58. # Align input format
  59. d = [dict(bbox=x) for x in list(d)]
  60. pose = inference_top_down_pose_model(model, f, d, format='xyxy')[0]
  61. for j, item in enumerate(pose):
  62. kp.append(item['keypoints'])
  63. frame_inds.append(i)
  64. anno['keypoint'] = np.stack(kp).astype(np.float16)
  65. anno['frame_inds'] = np.array(frame_inds, dtype=np.int16)
  66. else:
  67. kp = np.zeros((num_person, total_frames, 17, 3), dtype=np.float32)
  68. for i, (f, d) in enumerate(zip(frames, det_results)):
  69. # Align input format
  70. d = [dict(bbox=x) for x in list(d)]
  71. pose = inference_top_down_pose_model(model, f, d, format='xyxy')[0]
  72. for j, item in enumerate(pose):
  73. kp[j, i] = item['keypoints']
  74. anno['keypoint'] = kp[..., :2].astype(np.float16)
  75. anno['keypoint_score'] = kp[..., 2].astype(np.float16)
  76. return anno
  77. def parse_args():
  78. parser = argparse.ArgumentParser(
  79. description='Generate 2D pose annotations for a custom video dataset')
  80. # * Both mmdet and mmpose should be installed from source
  81. # parser.add_argument('--mmdet-root', type=str, default=default_mmdet_root)
  82. # parser.add_argument('--mmpose-root', type=str, default=default_mmpose_root)
  83. parser.add_argument('--det-config', type=str, default=default_det_config)
  84. parser.add_argument('--det-ckpt', type=str, default=default_det_ckpt)
  85. parser.add_argument('--pose-config', type=str, default=default_pose_config)
  86. parser.add_argument('--pose-ckpt', type=str, default=default_pose_ckpt)
  87. # * Only det boxes with score larger than det_score_thr will be kept
  88. parser.add_argument('--det-score-thr', type=float, default=0.7)
  89. # * Only det boxes with large enough sizes will be kept,
  90. parser.add_argument('--det-area-thr', type=float, default=1600)
  91. # * Accepted formats for each line in video_list are:
  92. # * 1. "xxx.mp4" ('label' is missing, the dataset can be used for inference, but not training)
  93. # * 2. "xxx.mp4 label" ('label' is an integer (category index),
  94. # * the result can be used for both training & testing)
  95. # * All lines should take the same format.
  96. parser.add_argument('--video-list', type=str, help='the list of source videos')
  97. # * out should ends with '.pkl'
  98. parser.add_argument('--out', type=str, help='output pickle name')
  99. parser.add_argument('--tmpdir', type=str, default='tmp')
  100. parser.add_argument('--local_rank', type=int, default=0)
  101. # * When non-dist is set, will only use 1 GPU
  102. parser.add_argument('--non-dist', action='store_true', help='whether to use distributed skeleton extraction')
  103. parser.add_argument('--compress', action='store_true', help='whether to do K400-style compression')
  104. args = parser.parse_args()
  105. # if 'LOCAL_RANK' not in os.environ:
  106. # os.environ['LOCAL_RANK'] = str(args.local_rank)
  107. args = parser.parse_args()
  108. return args
  109. def main():
  110. args = parse_args()
  111. assert args.out.endswith('.pkl')
  112. lines = mrlines(args.video_list)
  113. lines = [x.split() for x in lines]
  114. # * We set 'frame_dir' as the base name (w/o. suffix) of each video
  115. assert len(lines[0]) in [1, 2]
  116. if len(lines[0]) == 1:
  117. annos = [dict(frame_dir=osp.basename(x[0]).split('.')[0], filename=x[0]) for x in lines]
  118. else:
  119. annos = [dict(frame_dir=osp.basename(x[0]).split('.')[0], filename=x[0], label=int(x[1])) for x in lines]
  120. if args.non_dist:
  121. my_part = annos
  122. os.makedirs(args.tmpdir, exist_ok=True)
  123. else:
  124. # init_dist('pytorch', backend='nccl')
  125. # rank, world_size = get_dist_info()
  126. # if rank == 0:
  127. # os.makedirs(args.tmpdir, exist_ok=True)
  128. # dist.barrier()
  129. rank = 0 # 添加该
  130. world_size = 1 # 添加
  131. my_part = annos#[rank::world_size]
  132. det_model = init_detector(args.det_config, args.det_ckpt, 'cuda')
  133. assert det_model.CLASSES[0] == 'person', 'A detector trained on COCO is required'
  134. pose_model = init_pose_model(args.pose_config, args.pose_ckpt, 'cuda')
  135. results = []
  136. for anno in tqdm(my_part):
  137. frames = extract_frame(anno['filename'])
  138. det_results = detection_inference(det_model, frames)
  139. # * Get detection results for human
  140. det_results = [x[0] for x in det_results]
  141. for i, res in enumerate(det_results):
  142. # * filter boxes with small scores
  143. res = res[res[:, 4] >= args.det_score_thr]
  144. # * filter boxes with small areas
  145. box_areas = (res[:, 3] - res[:, 1]) * (res[:, 2] - res[:, 0])
  146. assert np.all(box_areas >= 0)
  147. res = res[box_areas >= args.det_area_thr]
  148. det_results[i] = res
  149. shape = frames[0].shape[:2]
  150. anno['img_shape'] = shape
  151. anno = pose_inference(anno, pose_model, frames, det_results, compress=args.compress)
  152. anno.pop('filename')
  153. results.append(anno)
  154. if args.non_dist:
  155. mmcv.dump(results, args.out)
  156. else:
  157. mmcv.dump(results, osp.join(args.tmpdir, f'part_{rank}.pkl'))
  158. # dist.barrier()
  159. if rank == 0:
  160. parts = [mmcv.load(osp.join(args.tmpdir, f'part_{i}.pkl')) for i in range(world_size)]
  161. rem = len(annos) % world_size
  162. if rem:
  163. for i in range(rem, world_size):
  164. parts[i].append(None)
  165. ordered_results = []
  166. for res in zip(*parts):
  167. ordered_results.extend(list(res))
  168. ordered_results = ordered_results[:len(annos)]
  169. mmcv.dump(ordered_results, args.out)
  170. if __name__ == '__main__':
  171. main()
参考了三个人的:做了一些修改,主要就是32-39行,可以本地下载好,也可以链接到官网下载。
Pyskl自定义数据集_墨末..的博客-CSDN博客
使用pyskl的stgcn++训练自己的数据集_大脸猫105的博客-CSDN博客
基于pyskl的poseC3D训练自己的数据集_骑走的小木马的博客-CSDN博客
因为我的 faster_rcnn_r50_fpn_1x_coco-person_20201216_175929-d022e227.pth和hrnet_w32_coco_256x192-c78dce93_20200708.pth文件是放在pyskl下面的,所以路径是./文件名
终端运行下面的命令:(这里我是将修改后的custom_2d_skeleton.py文件放在pyskl/json文件里的,如果不另存就是在tools/)
 python json/custom_2d_skeleton.py --video-list  ./mydata/mydata.list --out  ./mydata/train.pkl
慢慢等。。。。 

 此时的mydata文件及下的文件

 

5.训练模型

根据上面生成的train.pkl和train.json、test.json文件,生成训练要用的pkl文件。
运行: create_final_pkl.py文件生成 My_xsub_stgn++.pkl
  1. import os
  2. from mmcv import load, dump
  3. from pyskl.smp import *
  4. def traintest(dirpath,pklname,newpklname):
  5. os.chdir(dirpath)
  6. train = load('train.json')
  7. test = load('test.json')
  8. annotations = load(pklname)
  9. split = dict()
  10. split['xsub_train'] = [x['vid_name'] for x in train]
  11. split['xsub_val'] = [x['vid_name'] for x in test]
  12. dump(dict(split=split, annotations=annotations), newpklname)
  13. if __name__ == '__main__':
  14. path = './mydata'
  15. old_pklname = 'train.pkl'
  16. new_pklname = 'My_xsub_stgn++.pkl'
  17. traintest(path, old_pklname, new_pklname)

 

选择需要的模型,我选择了stgcn++,再打开\configs\stgcn++\stgcn++_ntu120_xsub_hrnet文件,打开j.py程序如下,做一些修改。

注意:ann_file的路径就是你上面生成的My_xsub_stgn++.pkl。

  1. # num_classes=11 改成自己数据集的类别数量,我的是11
  2. model = dict(
  3. type='RecognizerGCN',
  4. backbone=dict(
  5. type='STGCN',
  6. gcn_adaptive='init',
  7. gcn_with_res=True,
  8. tcn_type='mstcn',
  9. graph_cfg=dict(layout='coco', mode='spatial')),
  10. cls_head=dict(type='GCNHead', num_classes=11, in_channels=256))
  11. dataset_type = 'PoseDataset'
  12. # ann_file,改成上面存放pkl文件的路径
  13. ann_file = './mydata/My_xsub_stgn++.pkl'
  14. # 下面的train_pipeline、val_pipeline和test_pipeline中num_person可以改成1,我猜是视频中人的数
  15. # 量,但是没有证据
  16. train_pipeline = [
  17. dict(type='PreNormalize2D'),
  18. dict(type='GenSkeFeat', dataset='coco', feats=['j']),
  19. dict(type='UniformSample', clip_len=100),
  20. dict(type='PoseDecode'),
  21. dict(type='FormatGCNInput', num_person=1),
  22. dict(type='Collect', keys=['keypoint', 'label'], meta_keys=[]),
  23. dict(type='ToTensor', keys=['keypoint'])
  24. ]
  25. val_pipeline = [
  26. dict(type='PreNormalize2D'),
  27. dict(type='GenSkeFeat', dataset='coco', feats=['j']),
  28. dict(type='UniformSample', clip_len=100, num_clips=1, test_mode=True),
  29. dict(type='PoseDecode'),
  30. dict(type='FormatGCNInput', num_person=1),
  31. dict(type='Collect', keys=['keypoint', 'label'], meta_keys=[]),
  32. dict(type='ToTensor', keys=['keypoint'])
  33. ]
  34. test_pipeline = [
  35. dict(type='PreNormalize2D'),
  36. dict(type='GenSkeFeat', dataset='coco', feats=['j']),
  37. dict(type='UniformSample', clip_len=100, num_clips=10, test_mode=True),
  38. dict(type='PoseDecode'),
  39. dict(type='FormatGCNInput', num_person=1),
  40. dict(type='Collect', keys=['keypoint', 'label'], meta_keys=[]),
  41. dict(type='ToTensor', keys=['keypoint'])
  42. ]
  43. # 这里的split='xsub_train'、split='xsub_val'可以按照自己写入的时候的key键进行修改,但是要保证
  44. # wei_xsub_stgn++_ch.pkl中的和这里的一致
  45. data = dict(
  46. videos_per_gpu=16,
  47. workers_per_gpu=2,
  48. test_dataloader=dict(videos_per_gpu=1),
  49. train=dict(
  50. type='RepeatDataset',
  51. times=5,
  52. dataset=dict(type=dataset_type, ann_file=ann_file, pipeline=train_pipeline, split='xsub_train')),
  53. val=dict(type=dataset_type, ann_file=ann_file, pipeline=val_pipeline, split='xsub_val'),
  54. test=dict(type=dataset_type, ann_file=ann_file, pipeline=test_pipeline, split='xsub_val'))
  55. # optimizer
  56. optimizer = dict(type='SGD', lr=0.1, momentum=0.9, weight_decay=0.0005, nesterov=True)
  57. optimizer_config = dict(grad_clip=None)
  58. # learning policy
  59. lr_config = dict(policy='CosineAnnealing', min_lr=0, by_epoch=False)
  60. # 可以修改训练的轮数total_epochs
  61. total_epochs = 100
  62. checkpoint_config = dict(interval=1)
  63. evaluation = dict(interval=1, metrics=['top_k_accuracy'])
  64. log_config = dict(interval=100, hooks=[dict(type='TextLoggerHook')])
  65. # runtime settings
  66. log_level = 'INFO'
  67. # work_dir为保存训练结果文件的地方,可以自己修改
  68. work_dir = './work_dirs/stgcn++/stgcn++_ntu120_xsub_hrnet/j_Wei5'
bash tools/dist_train.sh configs/stgcn++/stgcn++_ntu120_xsub_hrnet/j.py 1 --validate --test-last --test-best

 

6.跑demo

使用自己训练好的模型生成demo
需要在 ./tools/data/label_map文件夹下建立数据集标签名称,从小到大排列,这样得到的输出视频画面中的标签才不会错。
 

 这里的--checkpoint根据自己生成的文件定我的是best_top1_acc_epoch_26.pth。

  1. python demo/demo_skeleton.py Video/C03P09A10R17.avi Video/C03P09A10R17_demo.mp4
  2. --config ./configs/stgcn++/stgcn++_ntu120_xsub_hrnet/j.py
  3. --checkpoint ./work_dirs/stgcn++/stgcn++_ntu120_xsub_hrnet/j_Wei5/best_top1_acc_epoch_26.pth
  4. --label-map ./tools/data/label_map/mydataset.txt

最后我测试向前摔倒的视频就输出了!!!! 

第一次跑代码跑模型太不容易了,起步很难,大家一起加油。 

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/107927
推荐阅读
相关标签
  

闽ICP备14008679号