Skip to content

Commit

Permalink
add mmrotate huawei
Browse files Browse the repository at this point in the history
  • Loading branch information
triple-Mu committed Sep 2, 2024
1 parent d50ab76 commit c4acacd
Show file tree
Hide file tree
Showing 10 changed files with 961 additions and 2 deletions.
4 changes: 2 additions & 2 deletions mmrotate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from .version import __version__, short_version

mmcv_minimum_version = '2.0.0rc4'
mmcv_maximum_version = '2.1.0'
mmcv_maximum_version = '2.2.0'
mmcv_version = digit_version(mmcv.__version__)

assert (mmcv_version >= digit_version(mmcv_minimum_version)
Expand All @@ -27,7 +27,7 @@
f'<{mmengine_maximum_version}.'

mmdet_minimum_version = '3.0.0rc6'
mmdet_maximum_version = '3.1.0'
mmdet_maximum_version = '3.3.0'
mmdet_version = digit_version(mmdet.__version__)

assert (mmdet_version >= digit_version(mmdet_minimum_version)
Expand Down
19 changes: 19 additions & 0 deletions mmrotate/datasets/transforms/loading.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
from typing import Sequence, Union

import mmcv
import numpy as np
from mmcv.transforms import BaseTransform
from mmdet.datasets.transforms import LoadAnnotations as MMDET_LoadAnnotations

from mmrotate.registry import TRANSFORMS

Expand Down Expand Up @@ -65,3 +67,20 @@ def transform(self, results: dict) -> dict:
results['img_shape'] = patch.shape[:2]
results['ori_shape'] = patch.shape[:2]
return results


@TRANSFORMS.register_module()
class MMROTATE_LoadAnnotations(MMDET_LoadAnnotations):

def _load_regressions(self, results: dict) -> None:
gt_bboxes_regressions = []
for instance in results.get('instances', []):
gt_bboxes_regressions.append(instance['bbox_regression'])
# TODO: Inconsistent with mmcv, consider how to deal with it later.
results['gt_bboxes_regressions'] = np.array(
gt_bboxes_regressions, dtype=np.float32)

def transform(self, results: dict) -> dict:
super().transform(results)
self._load_regressions(results)
return results
34 changes: 34 additions & 0 deletions projects/triplemu/config/_base_/default_runtime.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
default_scope = 'mmrotate'

default_hooks = dict(
timer=dict(type='IterTimerHook'),
logger=dict(type='LoggerHook', interval=50),
param_scheduler=dict(type='ParamSchedulerHook'),
checkpoint=dict(type='CheckpointHook', interval=12, max_keep_ckpts=3),
sampler_seed=dict(type='DistSamplerSeedHook'),
visualization=dict(type='mmdet.DetVisualizationHook'))

env_cfg = dict(
cudnn_benchmark=False,
mp_cfg=dict(mp_start_method='fork', opencv_num_threads=0),
dist_cfg=dict(backend='nccl'),
)

vis_backends = [dict(type='LocalVisBackend')]
visualizer = dict(
type='RotLocalVisualizer', vis_backends=vis_backends, name='visualizer')
log_processor = dict(type='LogProcessor', window_size=50, by_epoch=True)

log_level = 'INFO'
load_from = None
resume = False

custom_hooks = [
dict(type='mmdet.NumClassCheckHook'),
dict(
type='EMAHook',
ema_type='mmdet.ExpMomentumEMA',
momentum=0.0002,
update_buffers=True,
priority=49)
]
105 changes: 105 additions & 0 deletions projects/triplemu/config/_base_/dota_rr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# dataset settings
dataset_type = 'DOTARegDataset'
data_root = 'data/mlc/'

backend_args = None

train_pipeline = [
dict(type='mmdet.LoadImageFromFile', backend_args=backend_args),
dict(
type='mmrotate.MMROTATE_LoadAnnotations',
with_bbox=True,
box_type='qbox'),
dict(type='ConvertBoxType', box_type_mapping=dict(gt_bboxes='rbox')),
dict(type='mmdet.Resize', scale=(512, 512), keep_ratio=True),
dict(
type='mmdet.RandomFlip',
prob=0.75,
direction=['horizontal', 'vertical', 'diagonal']),
dict(
type='RandomRotate',
prob=0.5,
angle_range=180,
rect_obj_labels=[9, 11]),
dict(type='mmdet.Pad', size=(512, 512), pad_val=dict(img=(114, 114, 114))),
dict(
type='mmdet.PackDetInputs',
meta_keys=('img_id', 'img_path', 'ori_shape', 'img_shape',
'scale_factor', 'flip', 'flip_direction',
'gt_bboxes_regressions'))
]
val_pipeline = [
dict(type='mmdet.LoadImageFromFile', backend_args=backend_args),
dict(type='mmdet.Resize', scale=(512, 512), keep_ratio=True),
# avoid bboxes being resized
dict(
type='mmrotate.MMROTATE_LoadAnnotations',
with_bbox=True,
box_type='qbox'),
dict(type='ConvertBoxType', box_type_mapping=dict(gt_bboxes='rbox')),
dict(type='mmdet.Pad', size=(512, 512), pad_val=dict(img=(114, 114, 114))),
dict(
type='mmdet.PackDetInputs',
meta_keys=('img_id', 'img_path', 'ori_shape', 'img_shape',
'scale_factor', 'gt_bboxes_regressions'))
]
test_pipeline = [
dict(type='mmdet.LoadImageFromFile', backend_args=backend_args),
dict(type='mmdet.Resize', scale=(512, 512), keep_ratio=True),
dict(type='mmdet.Pad', size=(512, 512), pad_val=dict(img=(114, 114, 114))),
dict(
type='mmdet.PackDetInputs',
meta_keys=('img_id', 'img_path', 'ori_shape', 'img_shape',
'scale_factor', 'gt_bboxes_regressions'))
]
train_dataloader = dict(
batch_size=8,
num_workers=8,
persistent_workers=True,
sampler=dict(type='DefaultSampler', shuffle=True),
batch_sampler=None,
pin_memory=False,
dataset=dict(
type=dataset_type,
data_root=data_root,
ann_file='train/annfiles/',
data_prefix=dict(img_path='train/images/'),
filter_cfg=dict(filter_empty_gt=True),
pipeline=train_pipeline))
val_dataloader = dict(
batch_size=1,
num_workers=2,
persistent_workers=True,
drop_last=False,
sampler=dict(type='DefaultSampler', shuffle=False),
dataset=dict(
type=dataset_type,
data_root=data_root,
ann_file='val/annfiles/',
data_prefix=dict(img_path='val/images/'),
test_mode=True,
pipeline=val_pipeline))
test_dataloader = val_dataloader

val_evaluator = dict(type='DOTAMetric', metric='mAP')
test_evaluator = val_evaluator

# inference on test dataset and format the output results
# for submission. Note: the test set has no annotation.
# test_dataloader = dict(
# batch_size=8,
# num_workers=8,
# persistent_workers=False,
# drop_last=False,
# sampler=dict(type='DefaultSampler', shuffle=False),
# dataset=dict(
# type=dataset_type,
# data_root=data_root,
# data_prefix=dict(img_path='test/images/'),
# test_mode=True,
# pipeline=test_pipeline))
# test_evaluator = dict(
# type='DOTAMetric',
# format_only=True,
# merge_patches=True,
# outfile_prefix='./work_dirs/rtmdet_r/Task1')
33 changes: 33 additions & 0 deletions projects/triplemu/config/_base_/schedule_3x.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
max_epochs = 3 * 12
base_lr = 0.004 / 16
interval = 12

train_cfg = dict(
type='EpochBasedTrainLoop', max_epochs=max_epochs, val_interval=interval)
val_cfg = dict(type='ValLoop')
test_cfg = dict(type='TestLoop')

# learning rate
param_scheduler = [
dict(
type='LinearLR',
start_factor=1.0e-5,
by_epoch=False,
begin=0,
end=1000),
dict(
type='CosineAnnealingLR',
eta_min=base_lr * 0.05,
begin=max_epochs // 2,
end=max_epochs,
T_max=max_epochs // 2,
by_epoch=True,
convert_to_iter_based=True),
]

# optimizer
optim_wrapper = dict(
type='OptimWrapper',
optimizer=dict(type='AdamW', lr=base_lr, weight_decay=0.05),
paramwise_cfg=dict(
norm_decay_mult=0, bias_decay_mult=0, bypass_duplicate=True))
88 changes: 88 additions & 0 deletions projects/triplemu/config/rotated_rtmdet_l-3x-dota.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
_base_ = [
'./_base_/default_runtime.py', './_base_/schedule_3x.py',
'./_base_/dota_rr.py'
]
custom_imports = dict(
imports=[
'projects.triplemu.core',
'projects.triplemu.core.dataset',
'projects.triplemu.core.loading',
'projects.triplemu.core.rotated_rtmdet_head',
],
allow_failed_imports=False)

checkpoint = 'weights/rotated_rtmdet_l-coco_pretrain-3x-dota_ms-06d248a2.pth' # noqa
num_classes = 1
angle_version = 'le90'
model = dict(
type='mmdet.RTMDet',
data_preprocessor=dict(
type='mmdet.DetDataPreprocessor',
mean=[103.53, 116.28, 123.675],
std=[57.375, 57.12, 58.395],
bgr_to_rgb=False,
boxtype2tensor=False,
batch_augments=None),
backbone=dict(
type='mmdet.CSPNeXt',
arch='P5',
expand_ratio=0.5,
deepen_factor=1,
widen_factor=1,
channel_attention=True,
norm_cfg=dict(type='SyncBN'),
act_cfg=dict(type='SiLU'),
init_cfg=dict(
type='Pretrained', prefix='backbone.', checkpoint=checkpoint)),
neck=dict(
type='mmdet.CSPNeXtPAFPN',
in_channels=[256, 512, 1024],
out_channels=256,
num_csp_blocks=3,
expand_ratio=0.5,
norm_cfg=dict(type='SyncBN'),
act_cfg=dict(type='SiLU')),
bbox_head=dict(
type='RotatedRTMDetSepBNRegHead',
num_classes=num_classes,
in_channels=256,
stacked_convs=2,
feat_channels=256,
angle_version=angle_version,
anchor_generator=dict(
type='mmdet.MlvlPointGenerator', offset=0, strides=[8, 16, 32]),
bbox_coder=dict(
type='DistanceAnglePointCoder', angle_version=angle_version),
loss_cls=dict(
type='mmdet.QualityFocalLoss',
use_sigmoid=True,
beta=2.0,
loss_weight=1.0),
loss_bbox=dict(type='RotatedIoULoss', mode='linear', loss_weight=2.0),
with_objectness=False,
exp_on_reg=True,
share_conv=True,
pred_kernel_size=1,
use_hbbox_loss=False,
scale_angle=False,
loss_angle=None,
norm_cfg=dict(type='SyncBN'),
act_cfg=dict(type='SiLU')),
train_cfg=dict(
assigner=dict(
type='mmdet.DynamicSoftLabelAssigner',
iou_calculator=dict(type='RBboxOverlaps2D'),
topk=13),
allowed_border=-1,
pos_weight=-1,
debug=False),
test_cfg=dict(
nms_pre=2000,
min_bbox_size=0,
score_thr=0.05,
nms=dict(type='nms_rotated', iou_threshold=0.1),
max_per_img=2000),
)

# batch_size = (2 GPUs) x (4 samples per GPU) = 8
train_dataloader = dict(batch_size=4, num_workers=4)
Empty file.
73 changes: 73 additions & 0 deletions projects/triplemu/core/dataset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import glob
import os.path as osp
from typing import List

from mmrotate.datasets import DOTADataset
from mmrotate.registry import DATASETS


@DATASETS.register_module()
class DOTARegDataset(DOTADataset):
METAINFO = {
'classes': ('building', ),
'palette': [
(165, 42, 42),
]
}

def load_data_list(self) -> List[dict]:
cls_map = {c: i
for i, c in enumerate(self.metainfo['classes'])
} # in mmdet v2.0 label is 0-based
data_list = []
if self.ann_file == '':
img_files = glob.glob(
osp.join(self.data_prefix['img_path'], f'*.{self.img_suffix}'))
for img_path in img_files:
data_info = {}
data_info['img_path'] = img_path
img_name = osp.split(img_path)[1]
data_info['file_name'] = img_name
img_id = img_name[:-4]
data_info['img_id'] = img_id

instance = dict(
bbox=[], bbox_label=[], bbox_regression=[], ignore_flag=0)
data_info['instances'] = [instance]
data_list.append(data_info)

return data_list
else:
txt_files = glob.glob(osp.join(self.ann_file, '*.txt'))
if len(txt_files) == 0:
raise ValueError('There is no txt file in '
f'{self.ann_file}')
for txt_file in txt_files:
data_info = {}
img_id = osp.split(txt_file)[1][:-4]
data_info['img_id'] = img_id
img_name = img_id + f'.{self.img_suffix}'
data_info['file_name'] = img_name
data_info['img_path'] = osp.join(self.data_prefix['img_path'],
img_name)

instances = []
with open(txt_file) as f:
s = f.readlines()
for si in s:
instance = {}
bbox_info = si.split()
instance['bbox'] = [float(i) for i in bbox_info[:8]]
cls_name = bbox_info[8]
instance['bbox_label'] = cls_map[cls_name]
difficulty = int(bbox_info[9])
if difficulty > self.diff_thr:
instance['ignore_flag'] = 1
else:
instance['ignore_flag'] = 0
instance['bbox_regression'] = float(bbox_info[10])
instances.append(instance)
data_info['instances'] = instances
data_list.append(data_info)

return data_list
Loading

0 comments on commit c4acacd

Please sign in to comment.