Skip to content

Commit 77904c9

Browse files
committed
Update Dataset and Support MMDET Training
1 parent 32a1e42 commit 77904c9

17 files changed

Lines changed: 294 additions & 331 deletions

File tree

configs/quasi_dense_r50_12e.py

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@
176176
dict(type='SeqDefaultFormatBundle'),
177177
dict(
178178
type='SeqCollect',
179-
keys=['img', 'gt_bboxes', 'gt_labels', 'gt_mids'],
179+
keys=['img', 'gt_bboxes', 'gt_labels', 'gt_match_indices'],
180180
ref_prefix='ref'),
181181
]
182182
test_pipeline = [
@@ -191,27 +191,28 @@
191191
dict(type='Normalize', **img_norm_cfg),
192192
dict(type='Pad', size_divisor=32),
193193
dict(type='ImageToTensor', keys=['img']),
194-
dict(
195-
type='Collect',
196-
keys=['img'],
197-
meta_keys=('filename', 'img_shape', 'scale_factor', 'flip',
198-
'img_norm_cfg', 'frame_id')),
194+
dict(type='VideoCollect', keys=['img'])
199195
])
200196
]
201197
data = dict(
202198
samples_per_gpu=2,
203199
workers_per_gpu=2,
204-
train=dict(
205-
type=dataset_type,
206-
ann_file=dict(
207-
DET=data_root + 'detection/annotations/train_coco-format.json',
208-
VID=data_root + 'tracking/annotations/train_coco-format.json'),
209-
img_prefix=dict(
210-
DET=data_root + 'detection/images/train/',
211-
VID=data_root + 'tracking/images/train/'),
212-
key_img_sampler=dict(interval=1),
213-
ref_img_sampler=dict(num=1, scope=3, method='uniform'),
214-
pipeline=train_pipeline),
200+
train=[
201+
dict(
202+
type=dataset_type,
203+
ann_file=data_root + 'tracking/annotations/train_coco-format.json',
204+
img_prefix=data_root + 'tracking/images/train/',
205+
key_img_sampler=dict(interval=1),
206+
ref_img_sampler=dict(num_ref_imgs=1, scope=3, method='uniform'),
207+
pipeline=train_pipeline),
208+
dict(
209+
type=dataset_type,
210+
load_as_video=False,
211+
ann_file=data_root +
212+
'detection/annotations/train_coco-format.json',
213+
img_prefix=data_root + 'detection/images/train/',
214+
pipeline=train_pipeline)
215+
],
215216
val=dict(
216217
type=dataset_type,
217218
ann_file=data_root + 'tracking/annotations/val_coco-format.json',

qdtrack/apis/test.py

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ def multi_gpu_test(model, data_loader, tmpdir=None, gpu_collect=False):
7676
# collect results from all ranks
7777
if gpu_collect:
7878
raise NotImplementedError
79-
# results = collect_results_gpu(results, len(dataset))
8079
else:
8180
results = collect_results_cpu(results, len(dataset), tmpdir)
8281
return results
@@ -115,47 +114,5 @@ def collect_results_cpu(result_part, size, tmpdir=None):
115114
part_file = mmcv.load(part_file)
116115
for k, v in part_file.items():
117116
part_list[k].extend(v)
118-
# TODO: consider the case for DET
119-
# # sort the results
120-
# ordered_results = []
121-
# for res in zip(*part_list):
122-
# ordered_results.extend(list(res))
123-
# # the dataloader may pad some samples
124-
# ordered_results = ordered_results[:size]
125-
# remove tmp dir
126117
shutil.rmtree(tmpdir)
127118
return part_list
128-
129-
130-
# def collect_results_gpu(result_part, size):
131-
# rank, world_size = get_dist_info()
132-
# # dump result part to tensor with pickle
133-
# part_tensor = torch.tensor(
134-
# bytearray(pickle.dumps(result_part)), dtype=torch.uint8,
135-
# device='cuda')
136-
# # gather all result part tensor shape
137-
# shape_tensor = torch.tensor(part_tensor.shape, device='cuda')
138-
# shape_list = [shape_tensor.clone() for _ in range(world_size)]
139-
# dist.all_gather(shape_list, shape_tensor)
140-
# # padding result part tensor to max length
141-
# shape_max = torch.tensor(shape_list).max()
142-
# part_send = torch.zeros(shape_max, dtype=torch.uint8, device='cuda')
143-
# part_send[:shape_tensor[0]] = part_tensor
144-
# part_recv_list = [
145-
# part_tensor.new_zeros(shape_max) for _ in range(world_size)
146-
# ]
147-
# # gather all result part
148-
# dist.all_gather(part_recv_list, part_send)
149-
150-
# if rank == 0:
151-
# part_list = []
152-
# for recv, shape in zip(part_recv_list, shape_list):
153-
# part_list.append(
154-
# pickle.loads(recv[:shape[0]].cpu().numpy().tobytes()))
155-
# # sort the results
156-
# ordered_results = []
157-
# for res in zip(*part_list):
158-
# ordered_results.extend(list(res))
159-
# # the dataloader may pad some samples
160-
# ordered_results = ordered_results[:size]
161-
# return ordered_results

qdtrack/apis/train.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
from mmcv.runner import (HOOKS, DistSamplerSeedHook, EpochBasedRunner,
44
OptimizerHook, build_optimizer)
55
from mmcv.utils import build_from_cfg
6-
from mmdet.core import DistEvalHook, EvalHook, Fp16OptimizerHook
7-
from mmdet.datasets import build_dataloader, build_dataset
8-
from mmdet.utils import get_root_logger
6+
from mmdet.core import Fp16OptimizerHook
7+
from mmdet.datasets import build_dataset
98

10-
from qdtrack.datasets import build_video_dataloader
9+
from qdtrack.core import DistEvalHook, EvalHook
10+
from qdtrack.datasets import build_dataloader
11+
from qdtrack.utils import get_root_logger
1112

1213

1314
def train_model(model,
@@ -91,7 +92,7 @@ def train_model(model,
9192
# register eval hooks
9293
if validate:
9394
val_dataset = build_dataset(cfg.data.val, dict(test_mode=True))
94-
val_dataloader = build_video_dataloader(
95+
val_dataloader = build_dataloader(
9596
val_dataset,
9697
samples_per_gpu=1,
9798
workers_per_gpu=cfg.data.workers_per_gpu,
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from .eval_hooks import EvalHook, DistEvalHook
12
from .mot import eval_mot
23

3-
__all__ = ['eval_mot']
4+
__all__ = ['eval_mot', 'EvalHook', 'DistEvalHook']
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import os.path as osp
2+
3+
from mmdet.core import DistEvalHook as _DistEvalHook
4+
from mmdet.core import EvalHook as _EvalHook
5+
6+
7+
class EvalHook(_EvalHook):
8+
9+
def after_train_epoch(self, runner):
10+
if not self.evaluation_flag(runner):
11+
return
12+
from qdtrack.apis import single_gpu_test
13+
results = single_gpu_test(runner.model, self.dataloader, show=False)
14+
self.evaluate(runner, results)
15+
16+
17+
class DistEvalHook(_DistEvalHook):
18+
19+
def after_train_epoch(self, runner):
20+
if not self.evaluation_flag(runner):
21+
return
22+
from qdtrack.apis import multi_gpu_test
23+
tmpdir = self.tmpdir
24+
if tmpdir is None:
25+
tmpdir = osp.join(runner.work_dir, '.eval_hook')
26+
results = multi_gpu_test(
27+
runner.model,
28+
self.dataloader,
29+
tmpdir=tmpdir,
30+
gpu_collect=self.gpu_collect)
31+
if runner.rank == 0:
32+
print('\n')
33+
self.evaluate(runner, results)

qdtrack/datasets/__init__.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
1-
from mmdet.datasets.builder import (DATASETS, PIPELINES, build_dataloader,
2-
build_dataset)
1+
from mmdet.datasets.builder import (DATASETS, PIPELINES, build_dataset)
32

43
from .bdd_video_dataset import BDDVideoDataset
5-
from .builder import build_video_dataloader
4+
from .builder import build_dataloader
65
from .coco_video_dataset import CocoVideoDataset
76
from .parsers import CocoVID
87
from .pipelines import (LoadMultiImagesFromFile, SeqCollect,
98
SeqDefaultFormatBundle, SeqLoadAnnotations,
109
SeqNormalize, SeqPad, SeqRandomFlip, SeqResize)
1110

1211
__all__ = [
13-
'DATASETS', 'PIPELINES', 'build_dataloader', 'build_video_dataloader',
14-
'build_dataset', 'CocoVID', 'BDDVideoDataset', 'CocoVideoDataset',
15-
'LoadMultiImagesFromFile', 'SeqLoadAnnotations', 'SeqResize',
16-
'SeqNormalize', 'SeqRandomFlip', 'SeqPad', 'SeqDefaultFormatBundle',
17-
'SeqCollect'
12+
'DATASETS', 'PIPELINES', 'build_dataloader', 'build_dataset', 'CocoVID',
13+
'BDDVideoDataset', 'CocoVideoDataset', 'LoadMultiImagesFromFile',
14+
'SeqLoadAnnotations', 'SeqResize', 'SeqNormalize', 'SeqRandomFlip',
15+
'SeqPad', 'SeqDefaultFormatBundle', 'SeqCollect'
1816
]

qdtrack/datasets/builder.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@
44
import numpy as np
55
from mmcv.parallel import collate
66
from mmcv.runner import get_dist_info
7-
from mmdet.datasets.samplers import GroupSampler
7+
from mmdet.datasets.samplers import DistributedGroupSampler, GroupSampler
88
from torch.utils.data import DataLoader
99

1010
from .samplers import DistributedVideoSampler
1111

1212

13-
def build_video_dataloader(dataset,
14-
samples_per_gpu,
15-
workers_per_gpu,
16-
num_gpus=1,
17-
dist=True,
18-
shuffle=False,
19-
seed=None,
20-
**kwargs):
13+
def build_dataloader(dataset,
14+
samples_per_gpu,
15+
workers_per_gpu,
16+
num_gpus=1,
17+
dist=True,
18+
shuffle=True,
19+
seed=None,
20+
**kwargs):
2121
"""Build PyTorch DataLoader.
2222
2323
In distributed training, each GPU/process has a dataloader.
@@ -38,12 +38,14 @@ def build_video_dataloader(dataset,
3838
Returns:
3939
DataLoader: A PyTorch dataloader.
4040
"""
41-
if shuffle:
42-
raise ValueError('This dataloader is specifically for video testing.')
4341
rank, world_size = get_dist_info()
4442
if dist:
45-
sampler = DistributedVideoSampler(
46-
dataset, world_size, rank, shuffle=False)
43+
if shuffle:
44+
sampler = DistributedGroupSampler(dataset, samples_per_gpu,
45+
world_size, rank)
46+
else:
47+
sampler = DistributedVideoSampler(
48+
dataset, world_size, rank, shuffle=False)
4749
batch_size = samples_per_gpu
4850
num_workers = workers_per_gpu
4951
else:

0 commit comments

Comments
 (0)