Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ModelZoo
SOLOv2-pytorch
Commits
c6fde230
Commit
c6fde230
authored
Dec 11, 2018
by
pangjm
Browse files
Merge branch 'master' of github.com:open-mmlab/mmdetection
Conflicts: tools/train.py
parents
e74519bb
826a5613
Changes
64
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
942 additions
and
73 deletions
+942
-73
mmdet/datasets/__init__.py
mmdet/datasets/__init__.py
+5
-2
mmdet/datasets/concat_dataset.py
mmdet/datasets/concat_dataset.py
+20
-0
mmdet/datasets/repeat_dataset.py
mmdet/datasets/repeat_dataset.py
+17
-0
mmdet/datasets/utils.py
mmdet/datasets/utils.py
+47
-0
mmdet/models/bbox_heads/bbox_head.py
mmdet/models/bbox_heads/bbox_head.py
+74
-4
mmdet/models/builder.py
mmdet/models/builder.py
+7
-2
mmdet/models/detectors/__init__.py
mmdet/models/detectors/__init__.py
+5
-2
mmdet/models/detectors/base.py
mmdet/models/detectors/base.py
+19
-2
mmdet/models/detectors/cascade_rcnn.py
mmdet/models/detectors/cascade_rcnn.py
+318
-0
mmdet/models/detectors/mask_rcnn.py
mmdet/models/detectors/mask_rcnn.py
+0
-7
mmdet/models/detectors/retinanet.py
mmdet/models/detectors/retinanet.py
+14
-0
mmdet/models/detectors/single_stage.py
mmdet/models/detectors/single_stage.py
+62
-0
mmdet/models/detectors/test_mixins.py
mmdet/models/detectors/test_mixins.py
+5
-5
mmdet/models/rpn_heads/rpn_head.py
mmdet/models/rpn_heads/rpn_head.py
+6
-6
mmdet/models/single_stage_heads/__init__.py
mmdet/models/single_stage_heads/__init__.py
+3
-0
mmdet/models/single_stage_heads/retina_head.py
mmdet/models/single_stage_heads/retina_head.py
+287
-0
mmdet/models/utils/__init__.py
mmdet/models/utils/__init__.py
+3
-2
mmdet/models/utils/weight_init.py
mmdet/models/utils/weight_init.py
+7
-0
mmdet/ops/nms/cpu_soft_nms.pyx
mmdet/ops/nms/cpu_soft_nms.pyx
+41
-39
mmdet/ops/nms/gpu_nms.pyx
mmdet/ops/nms/gpu_nms.pyx
+2
-2
No files found.
mmdet/datasets/__init__.py
View file @
c6fde230
from
.custom
import
CustomDataset
from
.custom
import
CustomDataset
from
.coco
import
CocoDataset
from
.coco
import
CocoDataset
from
.loader
import
GroupSampler
,
DistributedGroupSampler
,
build_dataloader
from
.loader
import
GroupSampler
,
DistributedGroupSampler
,
build_dataloader
from
.utils
import
to_tensor
,
random_scale
,
show_ann
from
.utils
import
to_tensor
,
random_scale
,
show_ann
,
get_dataset
from
.concat_dataset
import
ConcatDataset
from
.repeat_dataset
import
RepeatDataset
__all__
=
[
__all__
=
[
'CustomDataset'
,
'CocoDataset'
,
'GroupSampler'
,
'DistributedGroupSampler'
,
'CustomDataset'
,
'CocoDataset'
,
'GroupSampler'
,
'DistributedGroupSampler'
,
'build_dataloader'
,
'to_tensor'
,
'random_scale'
,
'show_ann'
'build_dataloader'
,
'to_tensor'
,
'random_scale'
,
'show_ann'
,
'get_dataset'
,
'ConcatDataset'
,
'RepeatDataset'
,
]
]
mmdet/datasets/concat_dataset.py
0 → 100644
View file @
c6fde230
import
numpy
as
np
from
torch.utils.data.dataset
import
ConcatDataset
as
_ConcatDataset
class
ConcatDataset
(
_ConcatDataset
):
"""
Same as torch.utils.data.dataset.ConcatDataset, but
concat the group flag for image aspect ratio.
"""
def
__init__
(
self
,
datasets
):
"""
flag: Images with aspect ratio greater than 1 will be set as group 1,
otherwise group 0.
"""
super
(
ConcatDataset
,
self
).
__init__
(
datasets
)
if
hasattr
(
datasets
[
0
],
'flag'
):
flags
=
[]
for
i
in
range
(
0
,
len
(
datasets
)):
flags
.
append
(
datasets
[
i
].
flag
)
self
.
flag
=
np
.
concatenate
(
flags
)
mmdet/datasets/repeat_dataset.py
0 → 100644
View file @
c6fde230
import
numpy
as
np
class
RepeatDataset
(
object
):
def
__init__
(
self
,
dataset
,
times
):
self
.
dataset
=
dataset
self
.
times
=
times
if
hasattr
(
self
.
dataset
,
'flag'
):
self
.
flag
=
np
.
tile
(
self
.
dataset
.
flag
,
times
)
self
.
_original_length
=
len
(
self
.
dataset
)
def
__getitem__
(
self
,
idx
):
return
self
.
dataset
[
idx
%
self
.
_original_length
]
def
__len__
(
self
):
return
self
.
times
*
self
.
_original_length
mmdet/datasets/utils.py
View file @
c6fde230
import
copy
from
collections
import
Sequence
from
collections
import
Sequence
import
mmcv
import
mmcv
from
mmcv.runner
import
obj_from_dict
import
torch
import
torch
import
matplotlib.pyplot
as
plt
import
matplotlib.pyplot
as
plt
import
numpy
as
np
import
numpy
as
np
from
.concat_dataset
import
ConcatDataset
from
.repeat_dataset
import
RepeatDataset
from
..
import
datasets
def
to_tensor
(
data
):
def
to_tensor
(
data
):
...
@@ -67,3 +72,45 @@ def show_ann(coco, img, ann_info):
...
@@ -67,3 +72,45 @@ def show_ann(coco, img, ann_info):
plt
.
axis
(
'off'
)
plt
.
axis
(
'off'
)
coco
.
showAnns
(
ann_info
)
coco
.
showAnns
(
ann_info
)
plt
.
show
()
plt
.
show
()
def
get_dataset
(
data_cfg
):
if
data_cfg
[
'type'
]
==
'RepeatDataset'
:
return
RepeatDataset
(
get_dataset
(
data_cfg
[
'dataset'
]),
data_cfg
[
'times'
])
if
isinstance
(
data_cfg
[
'ann_file'
],
(
list
,
tuple
)):
ann_files
=
data_cfg
[
'ann_file'
]
num_dset
=
len
(
ann_files
)
else
:
ann_files
=
[
data_cfg
[
'ann_file'
]]
num_dset
=
1
if
'proposal_file'
in
data_cfg
.
keys
():
if
isinstance
(
data_cfg
[
'proposal_file'
],
(
list
,
tuple
)):
proposal_files
=
data_cfg
[
'proposal_file'
]
else
:
proposal_files
=
[
data_cfg
[
'proposal_file'
]]
else
:
proposal_files
=
[
None
]
*
num_dset
assert
len
(
proposal_files
)
==
num_dset
if
isinstance
(
data_cfg
[
'img_prefix'
],
(
list
,
tuple
)):
img_prefixes
=
data_cfg
[
'img_prefix'
]
else
:
img_prefixes
=
[
data_cfg
[
'img_prefix'
]]
*
num_dset
assert
len
(
img_prefixes
)
==
num_dset
dsets
=
[]
for
i
in
range
(
num_dset
):
data_info
=
copy
.
deepcopy
(
data_cfg
)
data_info
[
'ann_file'
]
=
ann_files
[
i
]
data_info
[
'proposal_file'
]
=
proposal_files
[
i
]
data_info
[
'img_prefix'
]
=
img_prefixes
[
i
]
dset
=
obj_from_dict
(
data_info
,
datasets
)
dsets
.
append
(
dset
)
if
len
(
dsets
)
>
1
:
dset
=
ConcatDataset
(
dsets
)
else
:
dset
=
dsets
[
0
]
return
dset
mmdet/models/bbox_heads/bbox_head.py
View file @
c6fde230
import
torch
import
torch.nn
as
nn
import
torch.nn
as
nn
import
torch.nn.functional
as
F
import
torch.nn.functional
as
F
...
@@ -99,7 +100,7 @@ class BBoxHead(nn.Module):
...
@@ -99,7 +100,7 @@ class BBoxHead(nn.Module):
img_shape
,
img_shape
,
scale_factor
,
scale_factor
,
rescale
=
False
,
rescale
=
False
,
nms_
cfg
=
None
):
cfg
=
None
):
if
isinstance
(
cls_score
,
list
):
if
isinstance
(
cls_score
,
list
):
cls_score
=
sum
(
cls_score
)
/
float
(
len
(
cls_score
))
cls_score
=
sum
(
cls_score
)
/
float
(
len
(
cls_score
))
scores
=
F
.
softmax
(
cls_score
,
dim
=
1
)
if
cls_score
is
not
None
else
None
scores
=
F
.
softmax
(
cls_score
,
dim
=
1
)
if
cls_score
is
not
None
else
None
...
@@ -114,11 +115,80 @@ class BBoxHead(nn.Module):
...
@@ -114,11 +115,80 @@ class BBoxHead(nn.Module):
if
rescale
:
if
rescale
:
bboxes
/=
scale_factor
bboxes
/=
scale_factor
if
nms_
cfg
is
None
:
if
cfg
is
None
:
return
bboxes
,
scores
return
bboxes
,
scores
else
:
else
:
det_bboxes
,
det_labels
=
multiclass_nms
(
det_bboxes
,
det_labels
=
multiclass_nms
(
bboxes
,
scores
,
nms_cfg
.
score_thr
,
nms_cfg
.
nms_thr
,
bboxes
,
scores
,
cfg
.
score_thr
,
cfg
.
nms
,
cfg
.
max_per_img
)
nms_cfg
.
max_per_img
)
return
det_bboxes
,
det_labels
return
det_bboxes
,
det_labels
def
refine_bboxes
(
self
,
rois
,
labels
,
bbox_preds
,
pos_is_gts
,
img_metas
):
"""Refine bboxes during training.
Args:
rois (Tensor): Shape (n*bs, 5), where n is image number per GPU,
and bs is the sampled RoIs per image.
labels (Tensor): Shape (n*bs, ).
bbox_preds (Tensor): Shape (n*bs, 4) or (n*bs, 4*#class).
pos_is_gts (list[Tensor]): Flags indicating if each positive bbox
is a gt bbox.
img_metas (list[dict]): Meta info of each image.
Returns:
list[Tensor]: Refined bboxes of each image in a mini-batch.
"""
img_ids
=
rois
[:,
0
].
long
().
unique
(
sorted
=
True
)
assert
img_ids
.
numel
()
==
len
(
img_metas
)
bboxes_list
=
[]
for
i
in
range
(
len
(
img_metas
)):
inds
=
torch
.
nonzero
(
rois
[:,
0
]
==
i
).
squeeze
()
num_rois
=
inds
.
numel
()
bboxes_
=
rois
[
inds
,
1
:]
label_
=
labels
[
inds
]
bbox_pred_
=
bbox_preds
[
inds
]
img_meta_
=
img_metas
[
i
]
pos_is_gts_
=
pos_is_gts
[
i
]
bboxes
=
self
.
regress_by_class
(
bboxes_
,
label_
,
bbox_pred_
,
img_meta_
)
# filter gt bboxes
pos_keep
=
1
-
pos_is_gts_
keep_inds
=
pos_is_gts_
.
new_ones
(
num_rois
)
keep_inds
[:
len
(
pos_is_gts_
)]
=
pos_keep
bboxes_list
.
append
(
bboxes
[
keep_inds
])
return
bboxes_list
def
regress_by_class
(
self
,
rois
,
label
,
bbox_pred
,
img_meta
):
"""Regress the bbox for the predicted class. Used in Cascade R-CNN.
Args:
rois (Tensor): shape (n, 4) or (n, 5)
label (Tensor): shape (n, )
bbox_pred (Tensor): shape (n, 4*(#class+1)) or (n, 4)
img_meta (dict): Image meta info.
Returns:
Tensor: Regressed bboxes, the same shape as input rois.
"""
assert
rois
.
size
(
1
)
==
4
or
rois
.
size
(
1
)
==
5
if
not
self
.
reg_class_agnostic
:
label
=
label
*
4
inds
=
torch
.
stack
((
label
,
label
+
1
,
label
+
2
,
label
+
3
),
1
)
bbox_pred
=
torch
.
gather
(
bbox_pred
,
1
,
inds
)
assert
bbox_pred
.
size
(
1
)
==
4
if
rois
.
size
(
1
)
==
4
:
new_rois
=
delta2bbox
(
rois
,
bbox_pred
,
self
.
target_means
,
self
.
target_stds
,
img_meta
[
'img_shape'
])
else
:
bboxes
=
delta2bbox
(
rois
[:,
1
:],
bbox_pred
,
self
.
target_means
,
self
.
target_stds
,
img_meta
[
'img_shape'
])
new_rois
=
torch
.
cat
((
rois
[:,
[
0
]],
bboxes
),
dim
=
1
)
return
new_rois
mmdet/models/builder.py
View file @
c6fde230
...
@@ -2,11 +2,12 @@ from mmcv.runner import obj_from_dict
...
@@ -2,11 +2,12 @@ from mmcv.runner import obj_from_dict
from
torch
import
nn
from
torch
import
nn
from
.
import
(
backbones
,
necks
,
roi_extractors
,
rpn_heads
,
bbox_heads
,
from
.
import
(
backbones
,
necks
,
roi_extractors
,
rpn_heads
,
bbox_heads
,
mask_heads
)
mask_heads
,
single_stage_heads
)
__all__
=
[
__all__
=
[
'build_backbone'
,
'build_neck'
,
'build_rpn_head'
,
'build_roi_extractor'
,
'build_backbone'
,
'build_neck'
,
'build_rpn_head'
,
'build_roi_extractor'
,
'build_bbox_head'
,
'build_mask_head'
,
'build_detector'
'build_bbox_head'
,
'build_mask_head'
,
'build_single_stage_head'
,
'build_detector'
]
]
...
@@ -47,6 +48,10 @@ def build_mask_head(cfg):
...
@@ -47,6 +48,10 @@ def build_mask_head(cfg):
return
build
(
cfg
,
mask_heads
)
return
build
(
cfg
,
mask_heads
)
def
build_single_stage_head
(
cfg
):
return
build
(
cfg
,
single_stage_heads
)
def
build_detector
(
cfg
,
train_cfg
=
None
,
test_cfg
=
None
):
def
build_detector
(
cfg
,
train_cfg
=
None
,
test_cfg
=
None
):
from
.
import
detectors
from
.
import
detectors
return
build
(
cfg
,
detectors
,
dict
(
train_cfg
=
train_cfg
,
test_cfg
=
test_cfg
))
return
build
(
cfg
,
detectors
,
dict
(
train_cfg
=
train_cfg
,
test_cfg
=
test_cfg
))
mmdet/models/detectors/__init__.py
View file @
c6fde230
from
.base
import
BaseDetector
from
.base
import
BaseDetector
from
.single_stage
import
SingleStageDetector
from
.two_stage
import
TwoStageDetector
from
.two_stage
import
TwoStageDetector
from
.rpn
import
RPN
from
.rpn
import
RPN
from
.fast_rcnn
import
FastRCNN
from
.fast_rcnn
import
FastRCNN
from
.faster_rcnn
import
FasterRCNN
from
.faster_rcnn
import
FasterRCNN
from
.mask_rcnn
import
MaskRCNN
from
.mask_rcnn
import
MaskRCNN
from
.cascade_rcnn
import
CascadeRCNN
from
.retinanet
import
RetinaNet
__all__
=
[
__all__
=
[
'BaseDetector'
,
'
Two
StageDetector'
,
'
RPN'
,
'FastRCNN'
,
'FasterRCN
N'
,
'BaseDetector'
,
'
Single
StageDetector'
,
'
TwoStageDetector'
,
'RP
N'
,
'
MaskRCNN
'
'
FastRCNN'
,
'FasterRCNN'
,
'MaskRCNN'
,
'CascadeRCNN'
,
'RetinaNet
'
]
]
mmdet/models/detectors/base.py
View file @
c6fde230
...
@@ -4,6 +4,7 @@ from abc import ABCMeta, abstractmethod
...
@@ -4,6 +4,7 @@ from abc import ABCMeta, abstractmethod
import
mmcv
import
mmcv
import
numpy
as
np
import
numpy
as
np
import
torch.nn
as
nn
import
torch.nn
as
nn
import
pycocotools.mask
as
maskUtils
from
mmdet.core
import
tensor2imgs
,
get_classes
from
mmdet.core
import
tensor2imgs
,
get_classes
...
@@ -86,6 +87,11 @@ class BaseDetector(nn.Module):
...
@@ -86,6 +87,11 @@ class BaseDetector(nn.Module):
img_norm_cfg
,
img_norm_cfg
,
dataset
=
'coco'
,
dataset
=
'coco'
,
score_thr
=
0.3
):
score_thr
=
0.3
):
if
isinstance
(
result
,
tuple
):
bbox_result
,
segm_result
=
result
else
:
bbox_result
,
segm_result
=
result
,
None
img_tensor
=
data
[
'img'
][
0
]
img_tensor
=
data
[
'img'
][
0
]
img_metas
=
data
[
'img_meta'
][
0
].
data
[
0
]
img_metas
=
data
[
'img_meta'
][
0
].
data
[
0
]
imgs
=
tensor2imgs
(
img_tensor
,
**
img_norm_cfg
)
imgs
=
tensor2imgs
(
img_tensor
,
**
img_norm_cfg
)
...
@@ -102,12 +108,23 @@ class BaseDetector(nn.Module):
...
@@ -102,12 +108,23 @@ class BaseDetector(nn.Module):
for
img
,
img_meta
in
zip
(
imgs
,
img_metas
):
for
img
,
img_meta
in
zip
(
imgs
,
img_metas
):
h
,
w
,
_
=
img_meta
[
'img_shape'
]
h
,
w
,
_
=
img_meta
[
'img_shape'
]
img_show
=
img
[:
h
,
:
w
,
:]
img_show
=
img
[:
h
,
:
w
,
:]
bboxes
=
np
.
vstack
(
bbox_result
)
# draw segmentation masks
if
segm_result
is
not
None
:
segms
=
mmcv
.
concat_list
(
segm_result
)
inds
=
np
.
where
(
bboxes
[:,
-
1
]
>
score_thr
)[
0
]
for
i
in
inds
:
color_mask
=
np
.
random
.
randint
(
0
,
256
,
(
1
,
3
),
dtype
=
np
.
uint8
)
mask
=
maskUtils
.
decode
(
segms
[
i
]).
astype
(
np
.
bool
)
img_show
[
mask
]
=
img_show
[
mask
]
*
0.5
+
color_mask
*
0.5
# draw bounding boxes
labels
=
[
labels
=
[
np
.
full
(
bbox
.
shape
[
0
],
i
,
dtype
=
np
.
int32
)
np
.
full
(
bbox
.
shape
[
0
],
i
,
dtype
=
np
.
int32
)
for
i
,
bbox
in
enumerate
(
result
)
for
i
,
bbox
in
enumerate
(
bbox_
result
)
]
]
labels
=
np
.
concatenate
(
labels
)
labels
=
np
.
concatenate
(
labels
)
bboxes
=
np
.
vstack
(
result
)
mmcv
.
imshow_det_bboxes
(
mmcv
.
imshow_det_bboxes
(
img_show
,
img_show
,
bboxes
,
bboxes
,
...
...
mmdet/models/detectors/cascade_rcnn.py
0 → 100644
View file @
c6fde230
from
__future__
import
division
import
torch
import
torch.nn
as
nn
from
.base
import
BaseDetector
from
.test_mixins
import
RPNTestMixin
from
..
import
builder
from
mmdet.core
import
(
assign_and_sample
,
bbox2roi
,
bbox2result
,
multi_apply
,
merge_aug_masks
)
class
CascadeRCNN
(
BaseDetector
,
RPNTestMixin
):
def
__init__
(
self
,
num_stages
,
backbone
,
neck
=
None
,
rpn_head
=
None
,
bbox_roi_extractor
=
None
,
bbox_head
=
None
,
mask_roi_extractor
=
None
,
mask_head
=
None
,
train_cfg
=
None
,
test_cfg
=
None
,
pretrained
=
None
):
assert
bbox_roi_extractor
is
not
None
assert
bbox_head
is
not
None
super
(
CascadeRCNN
,
self
).
__init__
()
self
.
num_stages
=
num_stages
self
.
backbone
=
builder
.
build_backbone
(
backbone
)
if
neck
is
not
None
:
self
.
neck
=
builder
.
build_neck
(
neck
)
else
:
raise
NotImplementedError
if
rpn_head
is
not
None
:
self
.
rpn_head
=
builder
.
build_rpn_head
(
rpn_head
)
if
bbox_head
is
not
None
:
self
.
bbox_roi_extractor
=
nn
.
ModuleList
()
self
.
bbox_head
=
nn
.
ModuleList
()
if
not
isinstance
(
bbox_roi_extractor
,
list
):
bbox_roi_extractor
=
[
bbox_roi_extractor
for
_
in
range
(
num_stages
)
]
if
not
isinstance
(
bbox_head
,
list
):
bbox_head
=
[
bbox_head
for
_
in
range
(
num_stages
)]
assert
len
(
bbox_roi_extractor
)
==
len
(
bbox_head
)
==
self
.
num_stages
for
roi_extractor
,
head
in
zip
(
bbox_roi_extractor
,
bbox_head
):
self
.
bbox_roi_extractor
.
append
(
builder
.
build_roi_extractor
(
roi_extractor
))
self
.
bbox_head
.
append
(
builder
.
build_bbox_head
(
head
))
if
mask_head
is
not
None
:
self
.
mask_roi_extractor
=
nn
.
ModuleList
()
self
.
mask_head
=
nn
.
ModuleList
()
if
not
isinstance
(
mask_roi_extractor
,
list
):
mask_roi_extractor
=
[
mask_roi_extractor
for
_
in
range
(
num_stages
)
]
if
not
isinstance
(
mask_head
,
list
):
mask_head
=
[
mask_head
for
_
in
range
(
num_stages
)]
assert
len
(
mask_roi_extractor
)
==
len
(
mask_head
)
==
self
.
num_stages
for
roi_extractor
,
head
in
zip
(
mask_roi_extractor
,
mask_head
):
self
.
mask_roi_extractor
.
append
(
builder
.
build_roi_extractor
(
roi_extractor
))
self
.
mask_head
.
append
(
builder
.
build_mask_head
(
head
))
self
.
train_cfg
=
train_cfg
self
.
test_cfg
=
test_cfg
self
.
init_weights
(
pretrained
=
pretrained
)
@
property
def
with_rpn
(
self
):
return
hasattr
(
self
,
'rpn_head'
)
and
self
.
rpn_head
is
not
None
def
init_weights
(
self
,
pretrained
=
None
):
super
(
CascadeRCNN
,
self
).
init_weights
(
pretrained
)
self
.
backbone
.
init_weights
(
pretrained
=
pretrained
)
if
self
.
with_neck
:
if
isinstance
(
self
.
neck
,
nn
.
Sequential
):
for
m
in
self
.
neck
:
m
.
init_weights
()
else
:
self
.
neck
.
init_weights
()
if
self
.
with_rpn
:
self
.
rpn_head
.
init_weights
()
for
i
in
range
(
self
.
num_stages
):
if
self
.
with_bbox
:
self
.
bbox_roi_extractor
[
i
].
init_weights
()
self
.
bbox_head
[
i
].
init_weights
()
if
self
.
with_mask
:
self
.
mask_roi_extractor
[
i
].
init_weights
()
self
.
mask_head
[
i
].
init_weights
()
def
extract_feat
(
self
,
img
):
x
=
self
.
backbone
(
img
)
if
self
.
with_neck
:
x
=
self
.
neck
(
x
)
return
x
def
forward_train
(
self
,
img
,
img_meta
,
gt_bboxes
,
gt_bboxes_ignore
,
gt_labels
,
gt_masks
=
None
,
proposals
=
None
):
x
=
self
.
extract_feat
(
img
)
losses
=
dict
()
if
self
.
with_rpn
:
rpn_outs
=
self
.
rpn_head
(
x
)
rpn_loss_inputs
=
rpn_outs
+
(
gt_bboxes
,
img_meta
,
self
.
train_cfg
.
rpn
)
rpn_losses
=
self
.
rpn_head
.
loss
(
*
rpn_loss_inputs
)
losses
.
update
(
rpn_losses
)
proposal_inputs
=
rpn_outs
+
(
img_meta
,
self
.
test_cfg
.
rpn
)
proposal_list
=
self
.
rpn_head
.
get_proposals
(
*
proposal_inputs
)
else
:
proposal_list
=
proposals
for
i
in
range
(
self
.
num_stages
):
rcnn_train_cfg
=
self
.
train_cfg
.
rcnn
[
i
]
lw
=
self
.
train_cfg
.
stage_loss_weights
[
i
]
# assign gts and sample proposals
assign_results
,
sampling_results
=
multi_apply
(
assign_and_sample
,
proposal_list
,
gt_bboxes
,
gt_bboxes_ignore
,
gt_labels
,
cfg
=
rcnn_train_cfg
)
# bbox head forward and loss
bbox_roi_extractor
=
self
.
bbox_roi_extractor
[
i
]
bbox_head
=
self
.
bbox_head
[
i
]
rois
=
bbox2roi
([
res
.
bboxes
for
res
in
sampling_results
])
bbox_feats
=
bbox_roi_extractor
(
x
[:
bbox_roi_extractor
.
num_inputs
],
rois
)
cls_score
,
bbox_pred
=
bbox_head
(
bbox_feats
)
bbox_targets
=
bbox_head
.
get_target
(
sampling_results
,
gt_bboxes
,
gt_labels
,
rcnn_train_cfg
)
loss_bbox
=
bbox_head
.
loss
(
cls_score
,
bbox_pred
,
*
bbox_targets
)
for
name
,
value
in
loss_bbox
.
items
():
losses
[
's{}.{}'
.
format
(
i
,
name
)]
=
(
value
*
lw
if
'loss'
in
name
else
value
)
# mask head forward and loss
if
self
.
with_mask
:
mask_roi_extractor
=
self
.
mask_roi_extractor
[
i
]
mask_head
=
self
.
mask_head
[
i
]
pos_rois
=
bbox2roi
(
[
res
.
pos_bboxes
for
res
in
sampling_results
])
mask_feats
=
mask_roi_extractor
(
x
[:
mask_roi_extractor
.
num_inputs
],
pos_rois
)
mask_pred
=
mask_head
(
mask_feats
)
mask_targets
=
mask_head
.
get_target
(
sampling_results
,
gt_masks
,
rcnn_train_cfg
)
pos_labels
=
torch
.
cat
(
[
res
.
pos_gt_labels
for
res
in
sampling_results
])
loss_mask
=
mask_head
.
loss
(
mask_pred
,
mask_targets
,
pos_labels
)
for
name
,
value
in
loss_mask
.
items
():
losses
[
's{}.{}'
.
format
(
i
,
name
)]
=
(
value
*
lw
if
'loss'
in
name
else
value
)
# refine bboxes
if
i
<
self
.
num_stages
-
1
:
pos_is_gts
=
[
res
.
pos_is_gt
for
res
in
sampling_results
]
roi_labels
=
bbox_targets
[
0
]
# bbox_targets is a tuple
with
torch
.
no_grad
():
proposal_list
=
bbox_head
.
refine_bboxes
(
rois
,
roi_labels
,
bbox_pred
,
pos_is_gts
,
img_meta
)
return
losses
def
simple_test
(
self
,
img
,
img_meta
,
proposals
=
None
,
rescale
=
False
):
x
=
self
.
extract_feat
(
img
)
proposal_list
=
self
.
simple_test_rpn
(
x
,
img_meta
,
self
.
test_cfg
.
rpn
)
if
proposals
is
None
else
proposals
img_shape
=
img_meta
[
0
][
'img_shape'
]
ori_shape
=
img_meta
[
0
][
'ori_shape'
]
scale_factor
=
img_meta
[
0
][
'scale_factor'
]
# "ms" in variable names means multi-stage
ms_bbox_result
=
{}
ms_segm_result
=
{}
ms_scores
=
[]
rcnn_test_cfg
=
self
.
test_cfg
.
rcnn
rois
=
bbox2roi
(
proposal_list
)
for
i
in
range
(
self
.
num_stages
):
bbox_roi_extractor
=
self
.
bbox_roi_extractor
[
i
]
bbox_head
=
self
.
bbox_head
[
i
]
bbox_feats
=
bbox_roi_extractor
(
x
[:
len
(
bbox_roi_extractor
.
featmap_strides
)],
rois
)
cls_score
,
bbox_pred
=
bbox_head
(
bbox_feats
)
ms_scores
.
append
(
cls_score
)
if
self
.
test_cfg
.
keep_all_stages
:
det_bboxes
,
det_labels
=
bbox_head
.
get_det_bboxes
(
rois
,
cls_score
,
bbox_pred
,
img_shape
,
scale_factor
,
rescale
=
rescale
,
cfg
=
rcnn_test_cfg
)
bbox_result
=
bbox2result
(
det_bboxes
,
det_labels
,
bbox_head
.
num_classes
)
ms_bbox_result
[
'stage{}'
.
format
(
i
)]
=
bbox_result
if
self
.
with_mask
:
mask_roi_extractor
=
self
.
mask_roi_extractor
[
i
]
mask_head
=
self
.
mask_head
[
i
]
if
det_bboxes
.
shape
[
0
]
==
0
:
segm_result
=
[
[]
for
_
in
range
(
mask_head
.
num_classes
-
1
)
]
else
:
_bboxes
=
(
det_bboxes
[:,
:
4
]
*
scale_factor
if
rescale
else
det_bboxes
)
mask_rois
=
bbox2roi
([
_bboxes
])
mask_feats
=
mask_roi_extractor
(
x
[:
len
(
mask_roi_extractor
.
featmap_strides
)],
mask_rois
)
mask_pred
=
mask_head
(
mask_feats
)
segm_result
=
mask_head
.
get_seg_masks
(
mask_pred
,
_bboxes
,
det_labels
,
rcnn_test_cfg
,
ori_shape
,
scale_factor
,
rescale
)
ms_segm_result
[
'stage{}'
.
format
(
i
)]
=
segm_result
if
i
<
self
.
num_stages
-
1
:
bbox_label
=
cls_score
.
argmax
(
dim
=
1
)
rois
=
bbox_head
.
regress_by_class
(
rois
,
bbox_label
,
bbox_pred
,
img_meta
[
0
])
cls_score
=
sum
(
ms_scores
)
/
self
.
num_stages
det_bboxes
,
det_labels
=
self
.
bbox_head
[
-
1
].
get_det_bboxes
(
rois
,
cls_score
,
bbox_pred
,
img_shape
,
scale_factor
,
rescale
=
rescale
,
cfg
=
rcnn_test_cfg
)
bbox_result
=
bbox2result
(
det_bboxes
,
det_labels
,
self
.
bbox_head
[
-
1
].
num_classes
)
ms_bbox_result
[
'ensemble'
]
=
bbox_result
if
self
.
with_mask
:
if
det_bboxes
.
shape
[
0
]
==
0
:
segm_result
=
[
[]
for
_
in
range
(
self
.
mask_head
[
-
1
].
num_classes
-
1
)
]
else
:
_bboxes
=
(
det_bboxes
[:,
:
4
]
*
scale_factor
if
rescale
else
det_bboxes
)
mask_rois
=
bbox2roi
([
_bboxes
])
aug_masks
=
[]
for
i
in
range
(
self
.
num_stages
):
mask_roi_extractor
=
self
.
mask_roi_extractor
[
i
]
mask_feats
=
mask_roi_extractor
(
x
[:
len
(
mask_roi_extractor
.
featmap_strides
)],
mask_rois
)
mask_pred
=
self
.
mask_head
[
i
](
mask_feats
)
aug_masks
.
append
(
mask_pred
.
sigmoid
().
cpu
().
numpy
())
merged_masks
=
merge_aug_masks
(
aug_masks
,
[
img_meta
]
*
self
.
num_stages
,
self
.
test_cfg
.
rcnn
)
segm_result
=
self
.
mask_head
[
-
1
].
get_seg_masks
(
merged_masks
,
_bboxes
,
det_labels
,
rcnn_test_cfg
,
ori_shape
,
scale_factor
,
rescale
)
ms_segm_result
[
'ensemble'
]
=
segm_result
if
not
self
.
test_cfg
.
keep_all_stages
:
if
self
.
with_mask
:
results
=
(
ms_bbox_result
[
'ensemble'
],
ms_segm_result
[
'ensemble'
])
else
:
results
=
ms_bbox_result
[
'ensemble'
]
else
:
if
self
.
with_mask
:
results
=
{
stage
:
(
ms_bbox_result
[
stage
],
ms_segm_result
[
stage
])
for
stage
in
ms_bbox_result
}
else
:
results
=
ms_bbox_result
return
results
def
aug_test
(
self
,
img
,
img_meta
,
proposals
=
None
,
rescale
=
False
):
raise
NotImplementedError
def
show_result
(
self
,
data
,
result
,
img_norm_cfg
,
**
kwargs
):
if
self
.
with_mask
:
ms_bbox_result
,
ms_segm_result
=
result
if
isinstance
(
ms_bbox_result
,
dict
):
result
=
(
ms_bbox_result
[
'ensemble'
],
ms_segm_result
[
'ensemble'
])
else
:
if
isinstance
(
result
,
dict
):
result
=
result
[
'ensemble'
]
super
(
CascadeRCNN
,
self
).
show_result
(
data
,
result
,
img_norm_cfg
,
**
kwargs
)
mmdet/models/detectors/mask_rcnn.py
View file @
c6fde230
...
@@ -25,10 +25,3 @@ class MaskRCNN(TwoStageDetector):
...
@@ -25,10 +25,3 @@ class MaskRCNN(TwoStageDetector):
train_cfg
=
train_cfg
,
train_cfg
=
train_cfg
,
test_cfg
=
test_cfg
,
test_cfg
=
test_cfg
,
pretrained
=
pretrained
)
pretrained
=
pretrained
)
def
show_result
(
self
,
data
,
result
,
img_norm_cfg
,
**
kwargs
):
# TODO: show segmentation masks
assert
isinstance
(
result
,
tuple
)
assert
len
(
result
)
==
2
# (bbox_results, segm_results)
super
(
MaskRCNN
,
self
).
show_result
(
data
,
result
[
0
],
img_norm_cfg
,
**
kwargs
)
mmdet/models/detectors/retinanet.py
0 → 100644
View file @
c6fde230
from
.single_stage
import
SingleStageDetector
class
RetinaNet
(
SingleStageDetector
):
def
__init__
(
self
,
backbone
,
neck
,
bbox_head
,
train_cfg
=
None
,
test_cfg
=
None
,
pretrained
=
None
):
super
(
RetinaNet
,
self
).
__init__
(
backbone
,
neck
,
bbox_head
,
train_cfg
,
test_cfg
,
pretrained
)
mmdet/models/detectors/single_stage.py
0 → 100644
View file @
c6fde230
import
torch.nn
as
nn
from
.base
import
BaseDetector
from
..
import
builder
from
mmdet.core
import
bbox2result
class
SingleStageDetector
(
BaseDetector
):
def
__init__
(
self
,
backbone
,
neck
=
None
,
bbox_head
=
None
,
train_cfg
=
None
,
test_cfg
=
None
,
pretrained
=
None
):
super
(
SingleStageDetector
,
self
).
__init__
()
self
.
backbone
=
builder
.
build_backbone
(
backbone
)
if
neck
is
not
None
:
self
.
neck
=
builder
.
build_neck
(
neck
)
self
.
bbox_head
=
builder
.
build_single_stage_head
(
bbox_head
)
self
.
train_cfg
=
train_cfg
self
.
test_cfg
=
test_cfg
self
.
init_weights
(
pretrained
=
pretrained
)
def
init_weights
(
self
,
pretrained
=
None
):
super
(
SingleStageDetector
,
self
).
init_weights
(
pretrained
)
self
.
backbone
.
init_weights
(
pretrained
=
pretrained
)
if
self
.
with_neck
:
if
isinstance
(
self
.
neck
,
nn
.
Sequential
):
for
m
in
self
.
neck
:
m
.
init_weights
()
else
:
self
.
neck
.
init_weights
()
self
.
bbox_head
.
init_weights
()
def
extract_feat
(
self
,
img
):
x
=
self
.
backbone
(
img
)
if
self
.
with_neck
:
x
=
self
.
neck
(
x
)
return
x
def
forward_train
(
self
,
img
,
img_metas
,
gt_bboxes
,
gt_labels
):
x
=
self
.
extract_feat
(
img
)
outs
=
self
.
bbox_head
(
x
)
loss_inputs
=
outs
+
(
gt_bboxes
,
gt_labels
,
img_metas
,
self
.
train_cfg
)
losses
=
self
.
bbox_head
.
loss
(
*
loss_inputs
)
return
losses
def
simple_test
(
self
,
img
,
img_meta
,
rescale
=
False
):
x
=
self
.
extract_feat
(
img
)
outs
=
self
.
bbox_head
(
x
)
bbox_inputs
=
outs
+
(
img_meta
,
self
.
test_cfg
,
rescale
)
bbox_list
=
self
.
bbox_head
.
get_det_bboxes
(
*
bbox_inputs
)
bbox_results
=
[
bbox2result
(
det_bboxes
,
det_labels
,
self
.
bbox_head
.
num_classes
)
for
det_bboxes
,
det_labels
in
bbox_list
]
return
bbox_results
[
0
]
def
aug_test
(
self
,
imgs
,
img_metas
,
rescale
=
False
):
raise
NotImplementedError
mmdet/models/detectors/test_mixins.py
View file @
c6fde230
...
@@ -47,7 +47,7 @@ class BBoxTestMixin(object):
...
@@ -47,7 +47,7 @@ class BBoxTestMixin(object):
img_shape
,
img_shape
,
scale_factor
,
scale_factor
,
rescale
=
rescale
,
rescale
=
rescale
,
nms_
cfg
=
rcnn_test_cfg
)
cfg
=
rcnn_test_cfg
)
return
det_bboxes
,
det_labels
return
det_bboxes
,
det_labels
def
aug_test_bboxes
(
self
,
feats
,
img_metas
,
proposal_list
,
rcnn_test_cfg
):
def
aug_test_bboxes
(
self
,
feats
,
img_metas
,
proposal_list
,
rcnn_test_cfg
):
...
@@ -73,15 +73,15 @@ class BBoxTestMixin(object):
...
@@ -73,15 +73,15 @@ class BBoxTestMixin(object):
img_shape
,
img_shape
,
scale_factor
,
scale_factor
,
rescale
=
False
,
rescale
=
False
,
nms_
cfg
=
None
)
cfg
=
None
)
aug_bboxes
.
append
(
bboxes
)
aug_bboxes
.
append
(
bboxes
)
aug_scores
.
append
(
scores
)
aug_scores
.
append
(
scores
)
# after merging, bboxes will be rescaled to the original image size
# after merging, bboxes will be rescaled to the original image size
merged_bboxes
,
merged_scores
=
merge_aug_bboxes
(
merged_bboxes
,
merged_scores
=
merge_aug_bboxes
(
aug_bboxes
,
aug_scores
,
img_metas
,
self
.
test_cfg
.
rcnn
)
aug_bboxes
,
aug_scores
,
img_metas
,
rcnn_
test_cfg
)
det_bboxes
,
det_labels
=
multiclass_nms
(
det_bboxes
,
det_labels
=
multiclass_nms
(
merged_bboxes
,
merged_scores
,
self
.
test_cfg
.
rcnn
.
score_thr
,
merged_bboxes
,
merged_scores
,
rcnn_
test_cfg
.
score_thr
,
self
.
test_cfg
.
rcnn
.
nms_thr
,
self
.
test_cfg
.
rcnn
.
max_per_img
)
rcnn_
test_cfg
.
nms
,
rcnn_
test_cfg
.
max_per_img
)
return
det_bboxes
,
det_labels
return
det_bboxes
,
det_labels
...
...
mmdet/models/rpn_heads/rpn_head.py
View file @
c6fde230
...
@@ -160,7 +160,7 @@ class RPNHead(nn.Module):
...
@@ -160,7 +160,7 @@ class RPNHead(nn.Module):
if
cls_reg_targets
is
None
:
if
cls_reg_targets
is
None
:
return
None
return
None
(
labels_list
,
label_weights_list
,
bbox_targets_list
,
bbox_weights_list
,
(
labels_list
,
label_weights_list
,
bbox_targets_list
,
bbox_weights_list
,
num_total_
samples
)
=
cls_reg_targets
num_total_
pos
,
num_total_neg
)
=
cls_reg_targets
losses_cls
,
losses_reg
=
multi_apply
(
losses_cls
,
losses_reg
=
multi_apply
(
self
.
loss_single
,
self
.
loss_single
,
rpn_cls_scores
,
rpn_cls_scores
,
...
@@ -169,7 +169,7 @@ class RPNHead(nn.Module):
...
@@ -169,7 +169,7 @@ class RPNHead(nn.Module):
label_weights_list
,
label_weights_list
,
bbox_targets_list
,
bbox_targets_list
,
bbox_weights_list
,
bbox_weights_list
,
num_total_samples
=
num_total_
samples
,
num_total_samples
=
num_total_
pos
+
num_total_neg
,
cfg
=
cfg
)
cfg
=
cfg
)
return
dict
(
loss_rpn_cls
=
losses_cls
,
loss_rpn_reg
=
losses_reg
)
return
dict
(
loss_rpn_cls
=
losses_cls
,
loss_rpn_reg
=
losses_reg
)
...
@@ -234,13 +234,13 @@ class RPNHead(nn.Module):
...
@@ -234,13 +234,13 @@ class RPNHead(nn.Module):
proposals
=
proposals
[
valid_inds
,
:]
proposals
=
proposals
[
valid_inds
,
:]
scores
=
scores
[
valid_inds
]
scores
=
scores
[
valid_inds
]
proposals
=
torch
.
cat
([
proposals
,
scores
.
unsqueeze
(
-
1
)],
dim
=-
1
)
proposals
=
torch
.
cat
([
proposals
,
scores
.
unsqueeze
(
-
1
)],
dim
=-
1
)
nms_keep
=
nms
(
proposals
,
cfg
.
nms_thr
)
[:
cfg
.
nms_post
]
proposals
,
_
=
nms
(
proposals
,
cfg
.
nms_thr
)
proposals
=
proposals
[
nms_keep
,
:]
proposals
=
proposals
[
:
cfg
.
nms_post
,
:]
mlvl_proposals
.
append
(
proposals
)
mlvl_proposals
.
append
(
proposals
)
proposals
=
torch
.
cat
(
mlvl_proposals
,
0
)
proposals
=
torch
.
cat
(
mlvl_proposals
,
0
)
if
cfg
.
nms_across_levels
:
if
cfg
.
nms_across_levels
:
nms_keep
=
nms
(
proposals
,
cfg
.
nms_thr
)
[:
cfg
.
max_num
]
proposals
,
_
=
nms
(
proposals
,
cfg
.
nms_thr
)
proposals
=
proposals
[
nms_keep
,
:]
proposals
=
proposals
[
:
cfg
.
max_num
,
:]
else
:
else
:
scores
=
proposals
[:,
4
]
scores
=
proposals
[:,
4
]
_
,
order
=
scores
.
sort
(
0
,
descending
=
True
)
_
,
order
=
scores
.
sort
(
0
,
descending
=
True
)
...
...
mmdet/models/single_stage_heads/__init__.py
0 → 100644
View file @
c6fde230
from
.retina_head
import
RetinaHead
__all__
=
[
'RetinaHead'
]
mmdet/models/single_stage_heads/retina_head.py
0 → 100644
View file @
c6fde230
from
__future__
import
division
import
numpy
as
np
import
torch
import
torch.nn
as
nn
from
mmdet.core
import
(
AnchorGenerator
,
anchor_target
,
multi_apply
,
delta2bbox
,
weighted_smoothl1
,
weighted_sigmoid_focal_loss
,
multiclass_nms
)
from
..utils
import
normal_init
,
bias_init_with_prob
class
RetinaHead
(
nn
.
Module
):
"""Head of RetinaNet.
/ cls_convs - retina_cls (3x3 conv)
input -
\ reg_convs - retina_reg (3x3 conv)
Args:
in_channels (int): Number of channels in the input feature map.
num_classes (int): Class number (including background).
stacked_convs (int): Number of convolutional layers added for cls and
reg branch.
feat_channels (int): Number of channels for the RPN feature map.
scales_per_octave (int): Number of anchor scales per octave.
octave_base_scale (int): Base octave scale. Anchor scales are computed
as `s*2^(i/n)`, for i in [0, n-1], where s is `octave_base_scale`
and n is `scales_per_octave`.
anchor_ratios (Iterable): Anchor aspect ratios.
anchor_strides (Iterable): Anchor strides.
target_means (Iterable): Mean values of regression targets.
target_stds (Iterable): Std values of regression targets.
"""
# noqa: W605
def
__init__
(
self
,
in_channels
,
num_classes
,
stacked_convs
=
4
,
feat_channels
=
256
,
octave_base_scale
=
4
,
scales_per_octave
=
3
,
anchor_ratios
=
[
0.5
,
1.0
,
2.0
],
anchor_strides
=
[
8
,
16
,
32
,
64
,
128
],
anchor_base_sizes
=
None
,
target_means
=
(.
0
,
.
0
,
.
0
,
.
0
),
target_stds
=
(
1.0
,
1.0
,
1.0
,
1.0
)):
super
(
RetinaHead
,
self
).
__init__
()
self
.
in_channels
=
in_channels
self
.
num_classes
=
num_classes
self
.
octave_base_scale
=
octave_base_scale
self
.
scales_per_octave
=
scales_per_octave
self
.
anchor_ratios
=
anchor_ratios
self
.
anchor_strides
=
anchor_strides
self
.
anchor_base_sizes
=
list
(
anchor_strides
)
if
anchor_base_sizes
is
None
else
anchor_base_sizes
self
.
target_means
=
target_means
self
.
target_stds
=
target_stds
self
.
anchor_generators
=
[]
for
anchor_base
in
self
.
anchor_base_sizes
:
octave_scales
=
np
.
array
(
[
2
**
(
i
/
scales_per_octave
)
for
i
in
range
(
scales_per_octave
)])
anchor_scales
=
octave_scales
*
octave_base_scale
self
.
anchor_generators
.
append
(
AnchorGenerator
(
anchor_base
,
anchor_scales
,
anchor_ratios
))
self
.
relu
=
nn
.
ReLU
(
inplace
=
True
)
self
.
num_anchors
=
int
(
len
(
self
.
anchor_ratios
)
*
self
.
scales_per_octave
)
self
.
cls_out_channels
=
self
.
num_classes
-
1
self
.
bbox_pred_dim
=
4
self
.
stacked_convs
=
stacked_convs
self
.
cls_convs
=
nn
.
ModuleList
()
self
.
reg_convs
=
nn
.
ModuleList
()
for
i
in
range
(
self
.
stacked_convs
):
chn
=
in_channels
if
i
==
0
else
feat_channels
self
.
cls_convs
.
append
(
nn
.
Conv2d
(
chn
,
feat_channels
,
3
,
stride
=
1
,
padding
=
1
))
self
.
reg_convs
.
append
(
nn
.
Conv2d
(
chn
,
feat_channels
,
3
,
stride
=
1
,
padding
=
1
))
self
.
retina_cls
=
nn
.
Conv2d
(
feat_channels
,
self
.
num_anchors
*
self
.
cls_out_channels
,
3
,
stride
=
1
,
padding
=
1
)
self
.
retina_reg
=
nn
.
Conv2d
(
feat_channels
,
self
.
num_anchors
*
self
.
bbox_pred_dim
,
3
,
stride
=
1
,
padding
=
1
)
self
.
debug_imgs
=
None
def
init_weights
(
self
):
for
m
in
self
.
cls_convs
:
normal_init
(
m
,
std
=
0.01
)
for
m
in
self
.
reg_convs
:
normal_init
(
m
,
std
=
0.01
)
bias_cls
=
bias_init_with_prob
(
0.01
)
normal_init
(
self
.
retina_cls
,
std
=
0.01
,
bias
=
bias_cls
)
normal_init
(
self
.
retina_reg
,
std
=
0.01
)
def
forward_single
(
self
,
x
):
cls_feat
=
x
reg_feat
=
x
for
cls_conv
in
self
.
cls_convs
:
cls_feat
=
self
.
relu
(
cls_conv
(
cls_feat
))
for
reg_conv
in
self
.
reg_convs
:
reg_feat
=
self
.
relu
(
reg_conv
(
reg_feat
))
cls_score
=
self
.
retina_cls
(
cls_feat
)
bbox_pred
=
self
.
retina_reg
(
reg_feat
)
return
cls_score
,
bbox_pred
def
forward
(
self
,
feats
):
return
multi_apply
(
self
.
forward_single
,
feats
)
def
get_anchors
(
self
,
featmap_sizes
,
img_metas
):
"""Get anchors according to feature map sizes.
Args:
featmap_sizes (list[tuple]): Multi-level feature map sizes.
img_metas (list[dict]): Image meta info.
Returns:
tuple: anchors of each image, valid flags of each image
"""
num_imgs
=
len
(
img_metas
)
num_levels
=
len
(
featmap_sizes
)
# since feature map sizes of all images are the same, we only compute
# anchors for one time
multi_level_anchors
=
[]
for
i
in
range
(
num_levels
):
anchors
=
self
.
anchor_generators
[
i
].
grid_anchors
(
featmap_sizes
[
i
],
self
.
anchor_strides
[
i
])
multi_level_anchors
.
append
(
anchors
)
anchor_list
=
[
multi_level_anchors
for
_
in
range
(
num_imgs
)]
# for each image, we compute valid flags of multi level anchors
valid_flag_list
=
[]
for
img_id
,
img_meta
in
enumerate
(
img_metas
):
multi_level_flags
=
[]
for
i
in
range
(
num_levels
):
anchor_stride
=
self
.
anchor_strides
[
i
]
feat_h
,
feat_w
=
featmap_sizes
[
i
]
h
,
w
,
_
=
img_meta
[
'pad_shape'
]
valid_feat_h
=
min
(
int
(
np
.
ceil
(
h
/
anchor_stride
)),
feat_h
)
valid_feat_w
=
min
(
int
(
np
.
ceil
(
w
/
anchor_stride
)),
feat_w
)
flags
=
self
.
anchor_generators
[
i
].
valid_flags
(
(
feat_h
,
feat_w
),
(
valid_feat_h
,
valid_feat_w
))
multi_level_flags
.
append
(
flags
)
valid_flag_list
.
append
(
multi_level_flags
)
return
anchor_list
,
valid_flag_list
def
loss_single
(
self
,
cls_score
,
bbox_pred
,
labels
,
label_weights
,
bbox_targets
,
bbox_weights
,
num_pos_samples
,
cfg
):
# classification loss
labels
=
labels
.
contiguous
().
view
(
-
1
,
self
.
cls_out_channels
)
label_weights
=
label_weights
.
contiguous
().
view
(
-
1
,
self
.
cls_out_channels
)
cls_score
=
cls_score
.
permute
(
0
,
2
,
3
,
1
).
contiguous
().
view
(
-
1
,
self
.
cls_out_channels
)
loss_cls
=
weighted_sigmoid_focal_loss
(
cls_score
,
labels
,
label_weights
,
cfg
.
gamma
,
cfg
.
alpha
,
avg_factor
=
num_pos_samples
)
# regression loss
bbox_targets
=
bbox_targets
.
contiguous
().
view
(
-
1
,
4
)
bbox_weights
=
bbox_weights
.
contiguous
().
view
(
-
1
,
4
)
bbox_pred
=
bbox_pred
.
permute
(
0
,
2
,
3
,
1
).
contiguous
().
view
(
-
1
,
4
)
loss_reg
=
weighted_smoothl1
(
bbox_pred
,
bbox_targets
,
bbox_weights
,
beta
=
cfg
.
smoothl1_beta
,
avg_factor
=
num_pos_samples
)
return
loss_cls
,
loss_reg
def
loss
(
self
,
cls_scores
,
bbox_preds
,
gt_bboxes
,
gt_labels
,
img_metas
,
cfg
):
featmap_sizes
=
[
featmap
.
size
()[
-
2
:]
for
featmap
in
cls_scores
]
assert
len
(
featmap_sizes
)
==
len
(
self
.
anchor_generators
)
anchor_list
,
valid_flag_list
=
self
.
get_anchors
(
featmap_sizes
,
img_metas
)
cls_reg_targets
=
anchor_target
(
anchor_list
,
valid_flag_list
,
gt_bboxes
,
img_metas
,
self
.
target_means
,
self
.
target_stds
,
cfg
,
gt_labels_list
=
gt_labels
,
cls_out_channels
=
self
.
cls_out_channels
,
sampling
=
False
)
if
cls_reg_targets
is
None
:
return
None
(
labels_list
,
label_weights_list
,
bbox_targets_list
,
bbox_weights_list
,
num_total_pos
,
num_total_neg
)
=
cls_reg_targets
losses_cls
,
losses_reg
=
multi_apply
(
self
.
loss_single
,
cls_scores
,
bbox_preds
,
labels_list
,
label_weights_list
,
bbox_targets_list
,
bbox_weights_list
,
num_pos_samples
=
num_total_pos
,
cfg
=
cfg
)
return
dict
(
loss_cls
=
losses_cls
,
loss_reg
=
losses_reg
)
def
get_det_bboxes
(
self
,
cls_scores
,
bbox_preds
,
img_metas
,
cfg
,
rescale
=
False
):
assert
len
(
cls_scores
)
==
len
(
bbox_preds
)
num_levels
=
len
(
cls_scores
)
mlvl_anchors
=
[
self
.
anchor_generators
[
i
].
grid_anchors
(
cls_scores
[
i
].
size
()[
-
2
:],
self
.
anchor_strides
[
i
])
for
i
in
range
(
num_levels
)
]
result_list
=
[]
for
img_id
in
range
(
len
(
img_metas
)):
cls_score_list
=
[
cls_scores
[
i
][
img_id
].
detach
()
for
i
in
range
(
num_levels
)
]
bbox_pred_list
=
[
bbox_preds
[
i
][
img_id
].
detach
()
for
i
in
range
(
num_levels
)
]
img_shape
=
img_metas
[
img_id
][
'img_shape'
]
scale_factor
=
img_metas
[
img_id
][
'scale_factor'
]
results
=
self
.
_get_det_bboxes_single
(
cls_score_list
,
bbox_pred_list
,
mlvl_anchors
,
img_shape
,
scale_factor
,
cfg
,
rescale
)
result_list
.
append
(
results
)
return
result_list
def
_get_det_bboxes_single
(
self
,
cls_scores
,
bbox_preds
,
mlvl_anchors
,
img_shape
,
scale_factor
,
cfg
,
rescale
=
False
):
assert
len
(
cls_scores
)
==
len
(
bbox_preds
)
==
len
(
mlvl_anchors
)
mlvl_proposals
=
[]
mlvl_scores
=
[]
for
cls_score
,
bbox_pred
,
anchors
in
zip
(
cls_scores
,
bbox_preds
,
mlvl_anchors
):
assert
cls_score
.
size
()[
-
2
:]
==
bbox_pred
.
size
()[
-
2
:]
cls_score
=
cls_score
.
permute
(
1
,
2
,
0
).
contiguous
().
view
(
-
1
,
self
.
cls_out_channels
)
scores
=
cls_score
.
sigmoid
()
bbox_pred
=
bbox_pred
.
permute
(
1
,
2
,
0
).
contiguous
().
view
(
-
1
,
4
)
proposals
=
delta2bbox
(
anchors
,
bbox_pred
,
self
.
target_means
,
self
.
target_stds
,
img_shape
)
if
cfg
.
nms_pre
>
0
and
scores
.
shape
[
0
]
>
cfg
.
nms_pre
:
maxscores
,
_
=
scores
.
max
(
dim
=
1
)
_
,
topk_inds
=
maxscores
.
topk
(
cfg
.
nms_pre
)
proposals
=
proposals
[
topk_inds
,
:]
scores
=
scores
[
topk_inds
,
:]
mlvl_proposals
.
append
(
proposals
)
mlvl_scores
.
append
(
scores
)
mlvl_proposals
=
torch
.
cat
(
mlvl_proposals
)
if
rescale
:
mlvl_proposals
/=
scale_factor
mlvl_scores
=
torch
.
cat
(
mlvl_scores
)
padding
=
mlvl_scores
.
new_zeros
(
mlvl_scores
.
shape
[
0
],
1
)
mlvl_scores
=
torch
.
cat
([
padding
,
mlvl_scores
],
dim
=
1
)
det_bboxes
,
det_labels
=
multiclass_nms
(
mlvl_proposals
,
mlvl_scores
,
cfg
.
score_thr
,
cfg
.
nms
,
cfg
.
max_per_img
)
return
det_bboxes
,
det_labels
mmdet/models/utils/__init__.py
View file @
c6fde230
from
.conv_module
import
ConvModule
from
.conv_module
import
ConvModule
from
.norm
import
build_norm_layer
from
.norm
import
build_norm_layer
from
.weight_init
import
xavier_init
,
normal_init
,
uniform_init
,
kaiming_init
from
.weight_init
import
(
xavier_init
,
normal_init
,
uniform_init
,
kaiming_init
,
bias_init_with_prob
)
__all__
=
[
__all__
=
[
'ConvModule'
,
'build_norm_layer'
,
'xavier_init'
,
'normal_init'
,
'ConvModule'
,
'build_norm_layer'
,
'xavier_init'
,
'normal_init'
,
'uniform_init'
,
'kaiming_init'
'uniform_init'
,
'kaiming_init'
,
'bias_init_with_prob'
]
]
mmdet/models/utils/weight_init.py
View file @
c6fde230
import
numpy
as
np
import
torch.nn
as
nn
import
torch.nn
as
nn
...
@@ -37,3 +38,9 @@ def kaiming_init(module,
...
@@ -37,3 +38,9 @@ def kaiming_init(module,
module
.
weight
,
mode
=
mode
,
nonlinearity
=
nonlinearity
)
module
.
weight
,
mode
=
mode
,
nonlinearity
=
nonlinearity
)
if
hasattr
(
module
,
'bias'
):
if
hasattr
(
module
,
'bias'
):
nn
.
init
.
constant_
(
module
.
bias
,
bias
)
nn
.
init
.
constant_
(
module
.
bias
,
bias
)
def
bias_init_with_prob
(
prior_prob
):
""" initialize conv/fc bias value according to giving probablity"""
bias_init
=
float
(
-
np
.
log
((
1
-
prior_prob
)
/
prior_prob
))
return
bias_init
mmdet/ops/nms/cpu_soft_nms.pyx
View file @
c6fde230
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
# Copyright (c) University of Maryland, College Park
# Copyright (c) University of Maryland, College Park
# Licensed under The MIT License [see LICENSE for details]
# Licensed under The MIT License [see LICENSE for details]
# Written by Navaneeth Bodla and Bharat Singh
# Written by Navaneeth Bodla and Bharat Singh
# Modified by Kai Chen
# ----------------------------------------------------------
# ----------------------------------------------------------
import
numpy
as
np
import
numpy
as
np
...
@@ -15,12 +16,13 @@ cdef inline np.float32_t max(np.float32_t a, np.float32_t b):
...
@@ -15,12 +16,13 @@ cdef inline np.float32_t max(np.float32_t a, np.float32_t b):
cdef
inline
np
.
float32_t
min
(
np
.
float32_t
a
,
np
.
float32_t
b
):
cdef
inline
np
.
float32_t
min
(
np
.
float32_t
a
,
np
.
float32_t
b
):
return
a
if
a
<=
b
else
b
return
a
if
a
<=
b
else
b
def
cpu_soft_nms
(
def
cpu_soft_nms
(
np
.
ndarray
[
float
,
ndim
=
2
]
boxes_in
,
np
.
ndarray
[
float
,
ndim
=
2
]
boxes_in
,
float
iou_thr
,
unsigned
int
method
=
1
,
float
sigma
=
0.5
,
float
sigma
=
0.5
,
float
Nt
=
0.3
,
float
min_score
=
0.001
,
float
threshold
=
0.001
,
unsigned
int
method
=
0
):
):
boxes
=
boxes_in
.
copy
()
boxes
=
boxes_in
.
copy
()
cdef
unsigned
int
N
=
boxes
.
shape
[
0
]
cdef
unsigned
int
N
=
boxes
.
shape
[
0
]
...
@@ -36,11 +38,11 @@ def cpu_soft_nms(
...
@@ -36,11 +38,11 @@ def cpu_soft_nms(
maxscore
=
boxes
[
i
,
4
]
maxscore
=
boxes
[
i
,
4
]
maxpos
=
i
maxpos
=
i
tx1
=
boxes
[
i
,
0
]
tx1
=
boxes
[
i
,
0
]
ty1
=
boxes
[
i
,
1
]
ty1
=
boxes
[
i
,
1
]
tx2
=
boxes
[
i
,
2
]
tx2
=
boxes
[
i
,
2
]
ty2
=
boxes
[
i
,
3
]
ty2
=
boxes
[
i
,
3
]
ts
=
boxes
[
i
,
4
]
ts
=
boxes
[
i
,
4
]
ti
=
inds
[
i
]
ti
=
inds
[
i
]
pos
=
i
+
1
pos
=
i
+
1
...
@@ -52,26 +54,26 @@ def cpu_soft_nms(
...
@@ -52,26 +54,26 @@ def cpu_soft_nms(
pos
=
pos
+
1
pos
=
pos
+
1
# add max box as a detection
# add max box as a detection
boxes
[
i
,
0
]
=
boxes
[
maxpos
,
0
]
boxes
[
i
,
0
]
=
boxes
[
maxpos
,
0
]
boxes
[
i
,
1
]
=
boxes
[
maxpos
,
1
]
boxes
[
i
,
1
]
=
boxes
[
maxpos
,
1
]
boxes
[
i
,
2
]
=
boxes
[
maxpos
,
2
]
boxes
[
i
,
2
]
=
boxes
[
maxpos
,
2
]
boxes
[
i
,
3
]
=
boxes
[
maxpos
,
3
]
boxes
[
i
,
3
]
=
boxes
[
maxpos
,
3
]
boxes
[
i
,
4
]
=
boxes
[
maxpos
,
4
]
boxes
[
i
,
4
]
=
boxes
[
maxpos
,
4
]
inds
[
i
]
=
inds
[
maxpos
]
inds
[
i
]
=
inds
[
maxpos
]
# swap ith box with position of max box
# swap ith box with position of max box
boxes
[
maxpos
,
0
]
=
tx1
boxes
[
maxpos
,
0
]
=
tx1
boxes
[
maxpos
,
1
]
=
ty1
boxes
[
maxpos
,
1
]
=
ty1
boxes
[
maxpos
,
2
]
=
tx2
boxes
[
maxpos
,
2
]
=
tx2
boxes
[
maxpos
,
3
]
=
ty2
boxes
[
maxpos
,
3
]
=
ty2
boxes
[
maxpos
,
4
]
=
ts
boxes
[
maxpos
,
4
]
=
ts
inds
[
maxpos
]
=
ti
inds
[
maxpos
]
=
ti
tx1
=
boxes
[
i
,
0
]
tx1
=
boxes
[
i
,
0
]
ty1
=
boxes
[
i
,
1
]
ty1
=
boxes
[
i
,
1
]
tx2
=
boxes
[
i
,
2
]
tx2
=
boxes
[
i
,
2
]
ty2
=
boxes
[
i
,
3
]
ty2
=
boxes
[
i
,
3
]
ts
=
boxes
[
i
,
4
]
ts
=
boxes
[
i
,
4
]
pos
=
i
+
1
pos
=
i
+
1
# NMS iterations, note that N changes if detection boxes fall below
# NMS iterations, note that N changes if detection boxes fall below
...
@@ -89,35 +91,35 @@ def cpu_soft_nms(
...
@@ -89,35 +91,35 @@ def cpu_soft_nms(
ih
=
(
min
(
ty2
,
y2
)
-
max
(
ty1
,
y1
)
+
1
)
ih
=
(
min
(
ty2
,
y2
)
-
max
(
ty1
,
y1
)
+
1
)
if
ih
>
0
:
if
ih
>
0
:
ua
=
float
((
tx2
-
tx1
+
1
)
*
(
ty2
-
ty1
+
1
)
+
area
-
iw
*
ih
)
ua
=
float
((
tx2
-
tx1
+
1
)
*
(
ty2
-
ty1
+
1
)
+
area
-
iw
*
ih
)
ov
=
iw
*
ih
/
ua
#
iou between max box and detection box
ov
=
iw
*
ih
/
ua
#
iou between max box and detection box
if
method
==
1
:
# linear
if
method
==
1
:
# linear
if
ov
>
Nt
:
if
ov
>
iou_thr
:
weight
=
1
-
ov
weight
=
1
-
ov
else
:
else
:
weight
=
1
weight
=
1
elif
method
==
2
:
# gaussian
elif
method
==
2
:
# gaussian
weight
=
np
.
exp
(
-
(
ov
*
ov
)
/
sigma
)
weight
=
np
.
exp
(
-
(
ov
*
ov
)
/
sigma
)
else
:
# original NMS
else
:
# original NMS
if
ov
>
Nt
:
if
ov
>
iou_thr
:
weight
=
0
weight
=
0
else
:
else
:
weight
=
1
weight
=
1
boxes
[
pos
,
4
]
=
weight
*
boxes
[
pos
,
4
]
boxes
[
pos
,
4
]
=
weight
*
boxes
[
pos
,
4
]
# if box score falls below threshold, discard the box by
# if box score falls below threshold, discard the box by
# swapping with last box update N
# swapping with last box update N
if
boxes
[
pos
,
4
]
<
threshold
:
if
boxes
[
pos
,
4
]
<
min_score
:
boxes
[
pos
,
0
]
=
boxes
[
N
-
1
,
0
]
boxes
[
pos
,
0
]
=
boxes
[
N
-
1
,
0
]
boxes
[
pos
,
1
]
=
boxes
[
N
-
1
,
1
]
boxes
[
pos
,
1
]
=
boxes
[
N
-
1
,
1
]
boxes
[
pos
,
2
]
=
boxes
[
N
-
1
,
2
]
boxes
[
pos
,
2
]
=
boxes
[
N
-
1
,
2
]
boxes
[
pos
,
3
]
=
boxes
[
N
-
1
,
3
]
boxes
[
pos
,
3
]
=
boxes
[
N
-
1
,
3
]
boxes
[
pos
,
4
]
=
boxes
[
N
-
1
,
4
]
boxes
[
pos
,
4
]
=
boxes
[
N
-
1
,
4
]
inds
[
pos
]
=
inds
[
N
-
1
]
inds
[
pos
]
=
inds
[
N
-
1
]
N
=
N
-
1
N
=
N
-
1
pos
=
pos
-
1
pos
=
pos
-
1
pos
=
pos
+
1
pos
=
pos
+
1
return
boxes
[:
N
],
inds
[:
N
]
return
boxes
[:
N
],
inds
[:
N
]
\ No newline at end of file
mmdet/ops/nms/gpu_nms.pyx
View file @
c6fde230
...
@@ -19,7 +19,7 @@ memory_pool = {}
...
@@ -19,7 +19,7 @@ memory_pool = {}
def
gpu_nms
(
np
.
ndarray
[
np
.
float32_t
,
ndim
=
2
]
dets
,
np
.
float
thresh
,
def
gpu_nms
(
np
.
ndarray
[
np
.
float32_t
,
ndim
=
2
]
dets
,
np
.
float
thresh
,
np
.
int32_t
device_id
=
0
):
np
.
int32_t
device_id
=
0
):
cdef
int
boxes_num
=
dets
.
shape
[
0
]
cdef
int
boxes_num
=
dets
.
shape
[
0
]
cdef
int
boxes_dim
=
dets
.
shape
[
1
]
cdef
int
boxes_dim
=
5
cdef
int
num_out
cdef
int
num_out
cdef
size_t
base
cdef
size_t
base
cdef
np
.
ndarray
[
np
.
int32_t
,
ndim
=
1
]
\
cdef
np
.
ndarray
[
np
.
int32_t
,
ndim
=
1
]
\
...
@@ -29,7 +29,7 @@ def gpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh,
...
@@ -29,7 +29,7 @@ def gpu_nms(np.ndarray[np.float32_t, ndim=2] dets, np.float thresh,
cdef
np
.
ndarray
[
np
.
int_t
,
ndim
=
1
]
\
cdef
np
.
ndarray
[
np
.
int_t
,
ndim
=
1
]
\
order
=
scores
.
argsort
()[::
-
1
]
order
=
scores
.
argsort
()[::
-
1
]
cdef
np
.
ndarray
[
np
.
float32_t
,
ndim
=
2
]
\
cdef
np
.
ndarray
[
np
.
float32_t
,
ndim
=
2
]
\
sorted_dets
=
dets
[
order
,
:]
sorted_dets
=
dets
[
order
,
:
5
]
cdef
float
cthresh
=
thresh
cdef
float
cthresh
=
thresh
if
device_id
not
in
memory_pool
:
if
device_id
not
in
memory_pool
:
with
nogil
:
with
nogil
:
...
...
Prev
1
2
3
4
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment