Skip to content

Commit f78af77

Browse files
authored
Release v3.1.0 (#10572)
2 parents ecac3a7 + c5c8aa0 commit f78af77

File tree

447 files changed

+41969
-1981
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

447 files changed

+41969
-1981
lines changed

Diff for: .circleci/test.yml

+13-8
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ jobs:
6262
equal: ["3.9.0", << parameters.python >>]
6363
steps:
6464
- run: pip install "protobuf <= 3.20.1" && sudo apt-get update && sudo apt-get -y install libprotobuf-dev protobuf-compiler cmake
65+
- run: pip install dsdl
6566
- run:
6667
name: Install mmdet dependencies
6768
# numpy may be downgraded after building pycocotools, which causes `ImportError: numpy.core.multiarray failed to import`
@@ -73,7 +74,9 @@ jobs:
7374
pip install -r requirements/tests.txt -r requirements/optional.txt
7475
pip install --force-reinstall pycocotools
7576
pip install albumentations>=0.3.2 --no-binary imgaug,albumentations
77+
pip install -r requirements/tracking.txt
7678
pip install git+https://github.com/cocodataset/panopticapi.git
79+
pip install git+https://github.com/JonathonLuiten/TrackEval.git
7780
- run:
7881
name: Build and install
7982
command: |
@@ -91,10 +94,10 @@ jobs:
9194
type: string
9295
cuda:
9396
type: enum
94-
enum: ["10.1", "10.2", "11.1", "11.7"]
97+
enum: ["11.1", "11.7"]
9598
cudnn:
9699
type: integer
97-
default: 7
100+
default: 8
98101
machine:
99102
image: ubuntu-2004-cuda-11.4:202110-01
100103
# docker_layer_caching: true
@@ -121,7 +124,9 @@ jobs:
121124
docker exec mmdetection pip install -r requirements/tests.txt -r requirements/optional.txt
122125
docker exec mmdetection pip install pycocotools
123126
docker exec mmdetection pip install albumentations>=0.3.2 --no-binary imgaug,albumentations
127+
docker exec mmdetection pip install -r requirements/tracking.txt
124128
docker exec mmdetection pip install git+https://github.com/cocodataset/panopticapi.git
129+
docker exec mmdetection pip install git+https://github.com/JonathonLuiten/TrackEval.git
125130
docker exec mmdetection python -c 'import mmcv; print(mmcv.__version__)'
126131
- run:
127132
name: Build and install
@@ -154,9 +159,9 @@ workflows:
154159
- dev-3.x
155160
- build_cpu:
156161
name: minimum_version_cpu
157-
torch: 1.6.0
158-
torchvision: 0.7.0
159-
python: 3.7.4 # The lowest python 3.7.x version available on CircleCI images
162+
torch: 1.8.0
163+
torchvision: 0.9.0
164+
python: 3.7.16
160165
requires:
161166
- lint
162167
- build_cpu:
@@ -175,7 +180,7 @@ workflows:
175180
torch: 1.8.1
176181
# Use double quotation mark to explicitly specify its type
177182
# as string instead of number
178-
cuda: "10.2"
183+
cuda: "11.1"
179184
requires:
180185
- hold
181186
- build_cuda:
@@ -191,8 +196,8 @@ workflows:
191196
jobs:
192197
- build_cuda:
193198
name: minimum_version_gpu
194-
torch: 1.6.0
195-
cuda: "10.1"
199+
torch: 1.8.0
200+
cuda: "11.1"
196201
filters:
197202
branches:
198203
only:

Diff for: .dev_scripts/benchmark_full_models.txt

+10-5
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,13 @@ free_anchor/freeanchor_r50_fpn_1x_coco.py
3333
fsaf/fsaf_r50_fpn_1x_coco.py
3434
gcnet/mask-rcnn_r50-gcb-r4-c3-c5_fpn_1x_coco.py
3535
gfl/gfl_r50_fpn_1x_coco.py
36+
glip/glip_atss_swin-t_a_fpn_dyhead_pretrain_obj365.py
3637
ghm/retinanet_r50_fpn_ghm-1x_coco.py
3738
gn/mask-rcnn_r50_fpn_gn-all_2x_coco.py
3839
gn+ws/faster-rcnn_r50_fpn_gn-ws-all_1x_coco.py
39-
grid_rcnn/grid-rcnn_r50_fpn_gn-head_1x_coco.py
40+
grid_rcnn/grid-rcnn_r50_fpn_gn-head_2x_coco.py
4041
groie/faste-rcnn_r50_fpn_groie_1x_coco.py
41-
guided_anchoring/ga-faster-rcnn_r50_fpn_1x_coco.py
42+
guided_anchoring/ga-faster-rcnn_r50-caffe_fpn_1x_coco.py
4243
hrnet/htc_hrnetv2p-w18_20e_coco.py
4344
htc/htc_r50_fpn_1x_coco.py
4445
instaboost/mask-rcnn_r50_fpn_instaboost-4x_coco.py
@@ -50,7 +51,7 @@ mask2former/mask2former_r50_8xb2-lsj-50e_coco.py
5051
mask2former/mask2former_r50_8xb2-lsj-50e_coco-panoptic.py
5152
mask_rcnn/mask-rcnn_r50_fpn_1x_coco.py
5253
maskformer/maskformer_r50_ms-16xb1-75e_coco.py
53-
ms_rcnn/ms-rcnn_r50_fpn_1x_coco.py
54+
ms_rcnn/ms-rcnn_r50-caffe_fpn_1x_coco.py
5455
nas_fcos/nas-fcos_r50-caffe_fpn_nashead-gn-head_4xb4-1x_coco.py
5556
nas_fpn/retinanet_r50_nasfpn_crop640-50e_coco.py
5657
paa/paa_r50_fpn_1x_coco.py
@@ -79,13 +80,17 @@ solo/solo_r50_fpn_1x_coco.py
7980
solov2/solov2_r50_fpn_1x_coco.py
8081
sparse_rcnn/sparse-rcnn_r50_fpn_1x_coco.py
8182
ssd/ssd300_coco.py
82-
strong_baselines/mask-rcnn_r50-caffe_fpn_rpn-2conv_4conv1fc_syncbn-all_amp-lsj-100e_coco.py
8383
swin/mask-rcnn_swin-t-p4-w7_fpn_1x_coco.py
84-
timm_example/retinanet_timm-tv-resnet50_fpn_1x_coco.py
8584
tood/tood_r50_fpn_1x_coco.py
8685
tridentnet/tridentnet_r50-caffe_1x_coco.py
8786
vfnet/vfnet_r50_fpn_1x_coco.py
8887
yolact/yolact_r50_8xb8-55e_coco.py
8988
yolo/yolov3_d53_8xb8-320-273e_coco.py
9089
yolof/yolof_r50-c5_8xb8-1x_coco.py
9190
yolox/yolox_s_8xb8-300e_coco.py
91+
deepsort/deepsort_faster-rcnn_r50_fpn_8xb2-4e_mot17halftrain_test-mot17halfval.py
92+
mask2former_vis/mask2former_r50_8xb2-8e_youtubevis2021.py
93+
masktrack_rcnn/masktrack-rcnn_mask-rcnn_r50_fpn_8xb1-12e_youtubevis2021.py
94+
ocsort/ocsort_yolox_x_8xb4-amp-80e_crowdhuman-mot17halftrain_test-mot17halfval.py
95+
qdtrack/qdtrack_faster-rcnn_r50_fpn_8xb2-4e_mot17halftrain_test-mot17halfval.py
96+
strongsort/strongsort_yolox_x_8xb4-80e_crowdhuman-mot17halftrain_test-mot17halfval.py

Diff for: .dev_scripts/benchmark_options.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
'pip install instaboostfast',
66
'pip install git+https://github.com/cocodataset/panopticapi.git',
77
'pip install timm',
8-
'pip install mmcls>=1.0.0rc0',
8+
'pip install mmpretrain',
99
'pip install git+https://github.com/lvis-dataset/lvis-api.git',
10+
'pip install -r ../requirements/multimodal.txt',
11+
'pip install -r ../requirements/tracking.txt',
12+
'pip install git+https://github.com/JonathonLuiten/TrackEval.git',
1013
]
1114

1215
default_floating_range = 0.5

Diff for: .dev_scripts/benchmark_train_models.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,6 @@ mask2former/mask2former_r50_8xb2-lsj-50e_coco-panoptic.py
1515
swin/mask-rcnn_swin-t-p4-w7_fpn_1x_coco.py
1616
condinst/condinst_r50_fpn_ms-poly-90k_coco_instance.py
1717
lvis/mask-rcnn_r50_fpn_sample1e-3_ms-1x_lvis-v1.py
18-
convnext/mask-rcnn_convnext-t-p4-w7_fpn_amp-ms-crop-3x_coco.py
18+
mask2former_vis/mask2former_r50_8xb2-8e_youtubevis2021.py
19+
masktrack_rcnn/masktrack-rcnn_mask-rcnn_r50_fpn_8xb1-12e_youtubevis2021.py
20+
qdtrack/qdtrack_faster-rcnn_r50_fpn_8xb2-4e_mot17halftrain_test-mot17halfval.py

Diff for: .dev_scripts/gather_models.py

+45-81
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
# Copyright (c) OpenMMLab. All rights reserved.
22
import argparse
33
import glob
4-
import json
4+
import os
55
import os.path as osp
66
import shutil
77
import subprocess
8+
import time
89
from collections import OrderedDict
910

1011
import torch
@@ -32,11 +33,15 @@ def process_checkpoint(in_file, out_file):
3233
# remove optimizer for smaller file size
3334
if 'optimizer' in checkpoint:
3435
del checkpoint['optimizer']
36+
if 'ema_state_dict' in checkpoint:
37+
del checkpoint['ema_state_dict']
3538

3639
# remove ema state_dict
3740
for key in list(checkpoint['state_dict']):
3841
if key.startswith('ema_'):
3942
checkpoint['state_dict'].pop(key)
43+
elif key.startswith('data_preprocessor'):
44+
checkpoint['state_dict'].pop(key)
4045

4146
# if it is necessary to remove some sensitive data in checkpoint['meta'],
4247
# add the code here.
@@ -52,15 +57,15 @@ def process_checkpoint(in_file, out_file):
5257

5358
def is_by_epoch(config):
5459
cfg = Config.fromfile('./configs/' + config)
55-
return cfg.runner.type == 'EpochBasedRunner'
60+
return cfg.train_cfg.type == 'EpochBasedTrainLoop'
5661

5762

5863
def get_final_epoch_or_iter(config):
5964
cfg = Config.fromfile('./configs/' + config)
60-
if cfg.runner.type == 'EpochBasedRunner':
61-
return cfg.runner.max_epochs
65+
if cfg.train_cfg.type == 'EpochBasedTrainLoop':
66+
return cfg.train_cfg.max_epochs
6267
else:
63-
return cfg.runner.max_iters
68+
return cfg.train_cfg.max_iters
6469

6570

6671
def get_best_epoch_or_iter(exp_dir):
@@ -74,60 +79,22 @@ def get_best_epoch_or_iter(exp_dir):
7479

7580
def get_real_epoch_or_iter(config):
7681
cfg = Config.fromfile('./configs/' + config)
77-
if cfg.runner.type == 'EpochBasedRunner':
78-
epoch = cfg.runner.max_epochs
79-
if cfg.data.train.type == 'RepeatDataset':
80-
epoch *= cfg.data.train.times
82+
if cfg.train_cfg.type == 'EpochBasedTrainLoop':
83+
epoch = cfg.train_cfg.max_epochs
8184
return epoch
8285
else:
83-
return cfg.runner.max_iters
86+
return cfg.train_cfg.max_iters
8487

8588

8689
def get_final_results(log_json_path,
8790
epoch_or_iter,
88-
results_lut,
91+
results_lut='coco/bbox_mAP',
8992
by_epoch=True):
9093
result_dict = dict()
91-
last_val_line = None
92-
last_train_line = None
93-
last_val_line_idx = -1
94-
last_train_line_idx = -1
95-
with open(log_json_path, 'r') as f:
96-
for i, line in enumerate(f.readlines()):
97-
log_line = json.loads(line)
98-
if 'mode' not in log_line.keys():
99-
continue
100-
101-
if by_epoch:
102-
if (log_line['mode'] == 'train'
103-
and log_line['epoch'] == epoch_or_iter):
104-
result_dict['memory'] = log_line['memory']
105-
106-
if (log_line['mode'] == 'val'
107-
and log_line['epoch'] == epoch_or_iter):
108-
result_dict.update({
109-
key: log_line[key]
110-
for key in results_lut if key in log_line
111-
})
112-
return result_dict
113-
else:
114-
if log_line['mode'] == 'train':
115-
last_train_line_idx = i
116-
last_train_line = log_line
117-
118-
if log_line and log_line['mode'] == 'val':
119-
last_val_line_idx = i
120-
last_val_line = log_line
121-
122-
# bug: max_iters = 768, last_train_line['iter'] = 750
123-
assert last_val_line_idx == last_train_line_idx + 1, \
124-
'Log file is incomplete'
125-
result_dict['memory'] = last_train_line['memory']
126-
result_dict.update({
127-
key: last_val_line[key]
128-
for key in results_lut if key in last_val_line
129-
})
130-
94+
with open(log_json_path) as f:
95+
r = f.readlines()[-1]
96+
last_metric = r.split(',')[0].split(': ')[-1].strip()
97+
result_dict[results_lut] = last_metric
13198
return result_dict
13299

133100

@@ -150,6 +117,16 @@ def get_dataset_name(config):
150117
return name_map[cfg.dataset_type]
151118

152119

120+
def find_last_dir(model_dir):
121+
dst_times = []
122+
for time_stamp in os.scandir(model_dir):
123+
if osp.isdir(time_stamp):
124+
dst_time = time.mktime(
125+
time.strptime(time_stamp.name, '%Y%m%d_%H%M%S'))
126+
dst_times.append([dst_time, time_stamp.name])
127+
return max(dst_times, key=lambda x: x[0])[1]
128+
129+
153130
def convert_model_info_to_pwc(model_infos):
154131
pwc_files = {}
155132
for model in model_infos:
@@ -160,9 +137,7 @@ def convert_model_info_to_pwc(model_infos):
160137
pwc_model_info['Config'] = osp.join('configs', model['config'])
161138

162139
# get metadata
163-
memory = round(model['results']['memory'] / 1024, 1)
164140
meta_data = OrderedDict()
165-
meta_data['Training Memory (GB)'] = memory
166141
if 'epochs' in model:
167142
meta_data['Epochs'] = get_real_epoch_or_iter(model['config'])
168143
else:
@@ -198,7 +173,7 @@ def convert_model_info_to_pwc(model_infos):
198173
Metrics={'PQ': metric}))
199174
pwc_model_info['Results'] = results
200175

201-
link_string = 'https://download.openmmlab.com/mmdetection/v2.0/'
176+
link_string = 'https://download.openmmlab.com/mmdetection/v3.0/'
202177
link_string += '{}/{}'.format(model['config'].rstrip('.py'),
203178
osp.split(model['model_path'])[-1])
204179
pwc_model_info['Weights'] = link_string
@@ -214,9 +189,13 @@ def parse_args():
214189
parser.add_argument(
215190
'root',
216191
type=str,
192+
default='work_dirs',
217193
help='root path of benchmarked models to be gathered')
218194
parser.add_argument(
219-
'out', type=str, help='output path of gathered models to be stored')
195+
'--out',
196+
type=str,
197+
default='gather',
198+
help='output path of gathered models to be stored')
220199
parser.add_argument(
221200
'--best',
222201
action='store_true',
@@ -262,32 +241,22 @@ def main():
262241
continue
263242

264243
# get the latest logs
265-
log_json_path = list(
266-
sorted(glob.glob(osp.join(exp_dir, '*.log.json'))))[-1]
267-
log_txt_path = list(sorted(glob.glob(osp.join(exp_dir, '*.log'))))[-1]
268-
cfg = Config.fromfile('./configs/' + used_config)
269-
results_lut = cfg.evaluation.metric
270-
if not isinstance(results_lut, list):
271-
results_lut = [results_lut]
272-
# case when using VOC, the evaluation key is only 'mAP'
273-
# when using Panoptic Dataset, the evaluation key is 'PQ'.
274-
for i, key in enumerate(results_lut):
275-
if 'mAP' not in key and 'PQ' not in key:
276-
results_lut[i] = key + '_mAP'
277-
model_performance = get_final_results(log_json_path,
278-
final_epoch_or_iter, results_lut,
279-
by_epoch)
244+
latest_exp_name = find_last_dir(exp_dir)
245+
latest_exp_json = osp.join(exp_dir, latest_exp_name, 'vis_data',
246+
latest_exp_name + '.json')
247+
248+
model_performance = get_final_results(
249+
latest_exp_json, final_epoch_or_iter, by_epoch=by_epoch)
280250

281251
if model_performance is None:
282252
continue
283253

284-
model_time = osp.split(log_txt_path)[-1].split('.')[0]
285254
model_info = dict(
286255
config=used_config,
287256
results=model_performance,
288-
model_time=model_time,
289257
final_model=final_model,
290-
log_json_path=osp.split(log_json_path)[-1])
258+
latest_exp_json=latest_exp_json,
259+
latest_exp_name=latest_exp_name)
291260
model_info['epochs' if by_epoch else 'iterations'] =\
292261
final_epoch_or_iter
293262
model_infos.append(model_info)
@@ -300,7 +269,7 @@ def main():
300269

301270
model_name = osp.split(model['config'])[-1].split('.')[0]
302271

303-
model_name += '_' + model['model_time']
272+
model_name += '_' + model['latest_exp_name']
304273
publish_model_path = osp.join(model_publish_dir, model_name)
305274
trained_model_path = osp.join(models_root, model['config'],
306275
model['final_model'])
@@ -310,13 +279,8 @@ def main():
310279
publish_model_path)
311280

312281
# copy log
313-
shutil.copy(
314-
osp.join(models_root, model['config'], model['log_json_path']),
315-
osp.join(model_publish_dir, f'{model_name}.log.json'))
316-
shutil.copy(
317-
osp.join(models_root, model['config'],
318-
model['log_json_path'].rstrip('.json')),
319-
osp.join(model_publish_dir, f'{model_name}.log'))
282+
shutil.copy(model['latest_exp_json'],
283+
osp.join(model_publish_dir, f'{model_name}.log.json'))
320284

321285
# copy config to guarantee reproducibility
322286
config_path = model['config']

Diff for: .github/pull_request_template.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@ If this PR introduces a new feature, it is better to list some use cases here, a
2121

2222
1. Pre-commit or other linting tools are used to fix the potential lint issues.
2323
2. The modification is covered by complete unit tests. If not, please add more unit test to ensure the correctness.
24-
3. If the modification has potential influence on downstream projects, this PR should be tested with downstream projects, like MMDet or MMCls.
24+
3. If the modification has potential influence on downstream projects, this PR should be tested with downstream projects, like MMDet or MMPreTrain.
2525
4. The documentation has been modified accordingly, like docstring or example tutorials.

Diff for: .readthedocs.yml

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
version: 2
22

3-
formats: all
3+
build:
4+
os: ubuntu-22.04
5+
tools:
6+
python: "3.8"
7+
8+
formats:
9+
- epub
410

511
python:
6-
version: 3.7
712
install:
813
- requirements: requirements/docs.txt
914
- requirements: requirements/readthedocs.txt

0 commit comments

Comments
 (0)