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
OpenDAS
mmdetection3d
Commits
6d71b439
Commit
6d71b439
authored
Apr 18, 2020
by
zhangwenwei
Browse files
Refactor optimizer and samplers
parent
ba492be7
Changes
38
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
32 additions
and
376 deletions
+32
-376
.gitlab-ci.yml
.gitlab-ci.yml
+1
-0
configs/kitti/dv_mvx-v2_second_secfpn_fpn-fusion_adamw_2x8_80e_kitti-3d-3class.py
...second_secfpn_fpn-fusion_adamw_2x8_80e_kitti-3d-3class.py
+1
-1
configs/kitti/dv_pointpillars_secfpn_6x8_160e_kitti-3d-car.py
...igs/kitti/dv_pointpillars_secfpn_6x8_160e_kitti-3d-car.py
+1
-1
configs/kitti/dv_second_secfpn_2x8_cosine_80e_kitti-3d-3class.py
.../kitti/dv_second_secfpn_2x8_cosine_80e_kitti-3d-3class.py
+1
-1
configs/kitti/dv_second_secfpn_6x8_80e_kitti-3d-car.py
configs/kitti/dv_second_secfpn_6x8_80e_kitti-3d-car.py
+1
-1
configs/kitti/faster_rcnn_r50_fpn_caffe_1x_kitti-2d-3class_coco-3x-pretrain.py
...rcnn_r50_fpn_caffe_1x_kitti-2d-3class_coco-3x-pretrain.py
+1
-1
configs/kitti/hv_pointpillars_secfpn_6x8_160e_kitti-3d-car.py
...igs/kitti/hv_pointpillars_secfpn_6x8_160e_kitti-3d-car.py
+1
-1
configs/kitti/hv_second_secfpn_6x8_80e_kitti-3d-car.py
configs/kitti/hv_second_secfpn_6x8_80e_kitti-3d-car.py
+1
-1
configs/nus/faster_rcnn_r50_fpn_caffe_2x8_1x_nus.py
configs/nus/faster_rcnn_r50_fpn_caffe_2x8_1x_nus.py
+1
-1
configs/nus/hv_pointpillars_secfpn_sbn-all_4x8_20e_nus-3d.py
configs/nus/hv_pointpillars_secfpn_sbn-all_4x8_20e_nus-3d.py
+1
-1
configs/nus/retinanet_r50_fpn_caffe_2x8_1x_nus.py
configs/nus/retinanet_r50_fpn_caffe_2x8_1x_nus.py
+1
-1
mmdet3d/apis/train.py
mmdet3d/apis/train.py
+0
-170
mmdet3d/core/anchor/__init__.py
mmdet3d/core/anchor/__init__.py
+5
-5
mmdet3d/core/anchor/anchor_3d_generator.py
mmdet3d/core/anchor/anchor_3d_generator.py
+0
-90
mmdet3d/core/bbox/__init__.py
mmdet3d/core/bbox/__init__.py
+7
-11
mmdet3d/core/bbox/assign_sampling.py
mmdet3d/core/bbox/assign_sampling.py
+1
-1
mmdet3d/core/bbox/coders/__init__.py
mmdet3d/core/bbox/coders/__init__.py
+2
-2
mmdet3d/core/bbox/coders/box_coder.py
mmdet3d/core/bbox/coders/box_coder.py
+1
-1
mmdet3d/core/bbox/samplers/__init__.py
mmdet3d/core/bbox/samplers/__init__.py
+5
-8
mmdet3d/core/bbox/samplers/base_sampler.py
mmdet3d/core/bbox/samplers/base_sampler.py
+0
-78
No files found.
.gitlab-ci.yml
View file @
6d71b439
...
@@ -25,6 +25,7 @@ before_script:
...
@@ -25,6 +25,7 @@ before_script:
stage
:
test
stage
:
test
script
:
script
:
-
echo "Start building..."
-
echo "Start building..."
-
pip install "git+https://github.com/cocodataset/cocoapi.git#subdirectory=PythonAPI"
-
pip install git+https://github.com/open-mmlab/mmdetection.git@v2.0
-
pip install git+https://github.com/open-mmlab/mmdetection.git@v2.0
-
python -c "import mmdet; print(mmdet.__version__)"
-
python -c "import mmdet; print(mmdet.__version__)"
-
pip install -v -e .[all]
-
pip install -v -e .[all]
...
...
configs/kitti/dv_mvx-v2_second_secfpn_fpn-fusion_adamw_2x8_80e_kitti-3d-3class.py
View file @
6d71b439
...
@@ -83,7 +83,7 @@ model = dict(
...
@@ -83,7 +83,7 @@ model = dict(
anchor_rotations
=
[
0
,
1.57
],
anchor_rotations
=
[
0
,
1.57
],
diff_rad_by_sin
=
True
,
diff_rad_by_sin
=
True
,
assign_per_class
=
True
,
assign_per_class
=
True
,
bbox_coder
=
dict
(
type
=
'ResidualCoder'
,
),
bbox_coder
=
dict
(
type
=
'Residual
3DBox
Coder'
,
),
loss_cls
=
dict
(
loss_cls
=
dict
(
type
=
'FocalLoss'
,
type
=
'FocalLoss'
,
use_sigmoid
=
True
,
use_sigmoid
=
True
,
...
...
configs/kitti/dv_pointpillars_secfpn_6x8_160e_kitti-3d-car.py
View file @
6d71b439
...
@@ -48,7 +48,7 @@ model = dict(
...
@@ -48,7 +48,7 @@ model = dict(
anchor_sizes
=
[[
1.6
,
3.9
,
1.56
]],
anchor_sizes
=
[[
1.6
,
3.9
,
1.56
]],
anchor_rotations
=
[
0
,
1.57
],
anchor_rotations
=
[
0
,
1.57
],
diff_rad_by_sin
=
True
,
diff_rad_by_sin
=
True
,
bbox_coder
=
dict
(
type
=
'ResidualCoder'
,
),
bbox_coder
=
dict
(
type
=
'Residual
3DBox
Coder'
,
),
loss_cls
=
dict
(
loss_cls
=
dict
(
type
=
'FocalLoss'
,
type
=
'FocalLoss'
,
use_sigmoid
=
True
,
use_sigmoid
=
True
,
...
...
configs/kitti/dv_second_secfpn_2x8_cosine_80e_kitti-3d-3class.py
View file @
6d71b439
...
@@ -52,7 +52,7 @@ model = dict(
...
@@ -52,7 +52,7 @@ model = dict(
diff_rad_by_sin
=
True
,
diff_rad_by_sin
=
True
,
assigner_per_size
=
True
,
assigner_per_size
=
True
,
assign_per_class
=
True
,
assign_per_class
=
True
,
bbox_coder
=
dict
(
type
=
'ResidualCoder'
,
),
bbox_coder
=
dict
(
type
=
'Residual
3DBox
Coder'
,
),
loss_cls
=
dict
(
loss_cls
=
dict
(
type
=
'FocalLoss'
,
type
=
'FocalLoss'
,
use_sigmoid
=
True
,
use_sigmoid
=
True
,
...
...
configs/kitti/dv_second_secfpn_6x8_80e_kitti-3d-car.py
View file @
6d71b439
...
@@ -46,7 +46,7 @@ model = dict(
...
@@ -46,7 +46,7 @@ model = dict(
anchor_sizes
=
[[
1.6
,
3.9
,
1.56
]],
anchor_sizes
=
[[
1.6
,
3.9
,
1.56
]],
anchor_rotations
=
[
0
,
1.57
],
anchor_rotations
=
[
0
,
1.57
],
diff_rad_by_sin
=
True
,
diff_rad_by_sin
=
True
,
bbox_coder
=
dict
(
type
=
'ResidualCoder'
,
),
bbox_coder
=
dict
(
type
=
'Residual
3DBox
Coder'
,
),
loss_cls
=
dict
(
loss_cls
=
dict
(
type
=
'FocalLoss'
,
type
=
'FocalLoss'
,
use_sigmoid
=
True
,
use_sigmoid
=
True
,
...
...
configs/kitti/faster_rcnn_r50_fpn_caffe_1x_kitti-2d-3class_coco-3x-pretrain.py
View file @
6d71b439
...
@@ -29,7 +29,7 @@ model = dict(
...
@@ -29,7 +29,7 @@ model = dict(
target_stds
=
[
1.0
,
1.0
,
1.0
,
1.0
],
target_stds
=
[
1.0
,
1.0
,
1.0
,
1.0
],
loss_cls
=
dict
(
loss_cls
=
dict
(
type
=
'CrossEntropyLoss'
,
use_sigmoid
=
True
,
loss_weight
=
1.0
),
type
=
'CrossEntropyLoss'
,
use_sigmoid
=
True
,
loss_weight
=
1.0
),
loss_bbox
=
dict
(
type
=
'
Smooth
L1Loss'
,
beta
=
0.0
,
loss_weight
=
1.0
)),
loss_bbox
=
dict
(
type
=
'L1Loss'
,
loss_weight
=
1.0
)),
roi_head
=
dict
(
roi_head
=
dict
(
type
=
'StandardRoIHead'
,
type
=
'StandardRoIHead'
,
bbox_roi_extractor
=
dict
(
bbox_roi_extractor
=
dict
(
...
...
configs/kitti/hv_pointpillars_secfpn_6x8_160e_kitti-3d-car.py
View file @
6d71b439
...
@@ -47,7 +47,7 @@ model = dict(
...
@@ -47,7 +47,7 @@ model = dict(
anchor_sizes
=
[[
1.6
,
3.9
,
1.56
]],
anchor_sizes
=
[[
1.6
,
3.9
,
1.56
]],
anchor_rotations
=
[
0
,
1.57
],
anchor_rotations
=
[
0
,
1.57
],
diff_rad_by_sin
=
True
,
diff_rad_by_sin
=
True
,
bbox_coder
=
dict
(
type
=
'ResidualCoder'
,
),
bbox_coder
=
dict
(
type
=
'Residual
3DBox
Coder'
,
),
loss_cls
=
dict
(
loss_cls
=
dict
(
type
=
'FocalLoss'
,
type
=
'FocalLoss'
,
use_sigmoid
=
True
,
use_sigmoid
=
True
,
...
...
configs/kitti/hv_second_secfpn_6x8_80e_kitti-3d-car.py
View file @
6d71b439
...
@@ -46,7 +46,7 @@ model = dict(
...
@@ -46,7 +46,7 @@ model = dict(
anchor_sizes
=
[[
1.6
,
3.9
,
1.56
]],
anchor_sizes
=
[[
1.6
,
3.9
,
1.56
]],
anchor_rotations
=
[
0
,
1.57
],
anchor_rotations
=
[
0
,
1.57
],
diff_rad_by_sin
=
True
,
diff_rad_by_sin
=
True
,
bbox_coder
=
dict
(
type
=
'ResidualCoder'
,
),
bbox_coder
=
dict
(
type
=
'Residual
3DBox
Coder'
,
),
loss_cls
=
dict
(
loss_cls
=
dict
(
type
=
'FocalLoss'
,
type
=
'FocalLoss'
,
use_sigmoid
=
True
,
use_sigmoid
=
True
,
...
...
configs/nus/faster_rcnn_r50_fpn_caffe_2x8_1x_nus.py
View file @
6d71b439
...
@@ -29,7 +29,7 @@ model = dict(
...
@@ -29,7 +29,7 @@ model = dict(
target_stds
=
[
1.0
,
1.0
,
1.0
,
1.0
],
target_stds
=
[
1.0
,
1.0
,
1.0
,
1.0
],
loss_cls
=
dict
(
loss_cls
=
dict
(
type
=
'CrossEntropyLoss'
,
use_sigmoid
=
True
,
loss_weight
=
1.0
),
type
=
'CrossEntropyLoss'
,
use_sigmoid
=
True
,
loss_weight
=
1.0
),
loss_bbox
=
dict
(
type
=
'
Smooth
L1Loss'
,
beta
=
0.0
,
loss_weight
=
1.0
)),
loss_bbox
=
dict
(
type
=
'L1Loss'
,
loss_weight
=
1.0
)),
roi_head
=
dict
(
roi_head
=
dict
(
type
=
'StandardRoIHead'
,
type
=
'StandardRoIHead'
,
bbox_roi_extractor
=
dict
(
bbox_roi_extractor
=
dict
(
...
...
configs/nus/hv_pointpillars_secfpn_sbn-all_4x8_20e_nus-3d.py
View file @
6d71b439
...
@@ -77,7 +77,7 @@ model = dict(
...
@@ -77,7 +77,7 @@ model = dict(
diff_rad_by_sin
=
True
,
diff_rad_by_sin
=
True
,
dir_offset
=
0.7854
,
# pi/4
dir_offset
=
0.7854
,
# pi/4
dir_limit_offset
=
0
,
dir_limit_offset
=
0
,
bbox_coder
=
dict
(
type
=
'ResidualCoder'
,
),
bbox_coder
=
dict
(
type
=
'Residual
3DBox
Coder'
,
),
loss_cls
=
dict
(
loss_cls
=
dict
(
type
=
'FocalLoss'
,
type
=
'FocalLoss'
,
use_sigmoid
=
True
,
use_sigmoid
=
True
,
...
...
configs/nus/retinanet_r50_fpn_caffe_2x8_1x_nus.py
View file @
6d71b439
...
@@ -38,7 +38,7 @@ model = dict(
...
@@ -38,7 +38,7 @@ model = dict(
gamma
=
2.0
,
gamma
=
2.0
,
alpha
=
0.25
,
alpha
=
0.25
,
loss_weight
=
1.0
),
loss_weight
=
1.0
),
loss_bbox
=
dict
(
type
=
'
Smooth
L1Loss'
,
beta
=
0.0
,
loss_weight
=
1.0
)))
loss_bbox
=
dict
(
type
=
'L1Loss'
,
loss_weight
=
1.0
)))
# training and testing settings
# training and testing settings
train_cfg
=
dict
(
train_cfg
=
dict
(
assigner
=
dict
(
assigner
=
dict
(
...
...
mmdet3d/apis/train.py
View file @
6d71b439
import
torch
from
mmcv.parallel
import
MMDataParallel
,
MMDistributedDataParallel
from
mmcv.runner
import
DistSamplerSeedHook
,
Runner
from
mmdet3d.core
import
build_optimizer
from
mmdet3d.datasets
import
build_dataloader
,
build_dataset
from
mmdet.apis.train
import
parse_losses
from
mmdet.apis.train
import
parse_losses
from
mmdet.core
import
(
DistEvalHook
,
DistOptimizerHook
,
EvalHook
,
Fp16OptimizerHook
)
from
mmdet.utils
import
get_root_logger
def
batch_processor
(
model
,
data
,
train_mode
):
def
batch_processor
(
model
,
data
,
train_mode
):
...
@@ -36,164 +27,3 @@ def batch_processor(model, data, train_mode):
...
@@ -36,164 +27,3 @@ def batch_processor(model, data, train_mode):
outputs
=
dict
(
loss
=
loss
,
log_vars
=
log_vars
,
num_samples
=
num_samples
)
outputs
=
dict
(
loss
=
loss
,
log_vars
=
log_vars
,
num_samples
=
num_samples
)
return
outputs
return
outputs
def
train_detector
(
model
,
dataset
,
cfg
,
distributed
=
False
,
validate
=
False
,
timestamp
=
None
,
meta
=
None
):
logger
=
get_root_logger
(
cfg
.
log_level
)
# start training
if
distributed
:
_dist_train
(
model
,
dataset
,
cfg
,
validate
=
validate
,
logger
=
logger
,
timestamp
=
timestamp
,
meta
=
meta
)
else
:
_non_dist_train
(
model
,
dataset
,
cfg
,
validate
=
validate
,
logger
=
logger
,
timestamp
=
timestamp
,
meta
=
meta
)
def
_dist_train
(
model
,
dataset
,
cfg
,
validate
=
False
,
logger
=
None
,
timestamp
=
None
,
meta
=
None
):
# prepare data loaders
dataset
=
dataset
if
isinstance
(
dataset
,
(
list
,
tuple
))
else
[
dataset
]
data_loaders
=
[
build_dataloader
(
ds
,
cfg
.
data
.
samples_per_gpu
,
cfg
.
data
.
workers_per_gpu
,
dist
=
True
,
seed
=
cfg
.
seed
)
for
ds
in
dataset
]
# put model on gpus
find_unused_parameters
=
cfg
.
get
(
'find_unused_parameters'
,
False
)
# Sets the `find_unused_parameters` parameter in
# torch.nn.parallel.DistributedDataParallel
model
=
MMDistributedDataParallel
(
model
.
cuda
(),
device_ids
=
[
torch
.
cuda
.
current_device
()],
broadcast_buffers
=
False
,
find_unused_parameters
=
find_unused_parameters
)
# build runner
optimizer
=
build_optimizer
(
model
,
cfg
.
optimizer
)
runner
=
Runner
(
model
,
batch_processor
,
optimizer
,
cfg
.
work_dir
,
logger
=
logger
,
meta
=
meta
)
# an ugly walkaround to make the .log and .log.json filenames the same
runner
.
timestamp
=
timestamp
# fp16 setting
fp16_cfg
=
cfg
.
get
(
'fp16'
,
None
)
if
fp16_cfg
is
not
None
:
optimizer_config
=
Fp16OptimizerHook
(
**
cfg
.
optimizer_config
,
**
fp16_cfg
)
else
:
optimizer_config
=
DistOptimizerHook
(
**
cfg
.
optimizer_config
)
# register hooks
runner
.
register_training_hooks
(
cfg
.
lr_config
,
optimizer_config
,
cfg
.
checkpoint_config
,
cfg
.
log_config
)
runner
.
register_hook
(
DistSamplerSeedHook
())
# register eval hooks
if
validate
:
val_dataset
=
build_dataset
(
cfg
.
data
.
val
,
dict
(
test_mode
=
True
))
val_dataloader
=
build_dataloader
(
val_dataset
,
samples_per_gpu
=
1
,
workers_per_gpu
=
cfg
.
data
.
workers_per_gpu
,
dist
=
True
,
shuffle
=
False
)
eval_cfg
=
cfg
.
get
(
'evaluation'
,
{})
runner
.
register_hook
(
DistEvalHook
(
val_dataloader
,
**
eval_cfg
))
if
cfg
.
resume_from
:
runner
.
resume
(
cfg
.
resume_from
)
elif
cfg
.
load_from
:
runner
.
load_checkpoint
(
cfg
.
load_from
)
runner
.
run
(
data_loaders
,
cfg
.
workflow
,
cfg
.
total_epochs
)
def
_non_dist_train
(
model
,
dataset
,
cfg
,
validate
=
False
,
logger
=
None
,
timestamp
=
None
,
meta
=
None
):
# prepare data loaders
dataset
=
dataset
if
isinstance
(
dataset
,
(
list
,
tuple
))
else
[
dataset
]
data_loaders
=
[
build_dataloader
(
ds
,
cfg
.
data
.
samples_per_gpu
,
cfg
.
data
.
workers_per_gpu
,
cfg
.
gpus
,
dist
=
False
,
seed
=
cfg
.
seed
)
for
ds
in
dataset
]
# put model on gpus
model
=
MMDataParallel
(
model
,
device_ids
=
range
(
cfg
.
gpus
)).
cuda
()
# build runner
optimizer
=
build_optimizer
(
model
,
cfg
.
optimizer
)
runner
=
Runner
(
model
,
batch_processor
,
optimizer
,
cfg
.
work_dir
,
logger
=
logger
,
meta
=
meta
)
# an ugly walkaround to make the .log and .log.json filenames the same
runner
.
timestamp
=
timestamp
# fp16 setting
fp16_cfg
=
cfg
.
get
(
'fp16'
,
None
)
if
fp16_cfg
is
not
None
:
optimizer_config
=
Fp16OptimizerHook
(
**
cfg
.
optimizer_config
,
**
fp16_cfg
,
distributed
=
False
)
else
:
optimizer_config
=
cfg
.
optimizer_config
runner
.
register_training_hooks
(
cfg
.
lr_config
,
optimizer_config
,
cfg
.
checkpoint_config
,
cfg
.
log_config
)
# register eval hooks
if
validate
:
val_dataset
=
build_dataset
(
cfg
.
data
.
val
,
dict
(
test_mode
=
True
))
val_dataloader
=
build_dataloader
(
val_dataset
,
samples_per_gpu
=
1
,
workers_per_gpu
=
cfg
.
data
.
workers_per_gpu
,
dist
=
False
,
shuffle
=
False
)
eval_cfg
=
cfg
.
get
(
'evaluation'
,
{})
runner
.
register_hook
(
EvalHook
(
val_dataloader
,
**
eval_cfg
))
if
cfg
.
resume_from
:
runner
.
resume
(
cfg
.
resume_from
)
elif
cfg
.
load_from
:
runner
.
load_checkpoint
(
cfg
.
load_from
)
runner
.
run
(
data_loaders
,
cfg
.
workflow
,
cfg
.
total_epochs
)
mmdet3d/core/anchor/__init__.py
View file @
6d71b439
from
.anchor_generator
import
(
AlignedAnchorGeneratorRange
,
AnchorGenerator
,
from
.anchor_
3d_
generator
import
(
AlignedAnchorGeneratorRange
,
AnchorGeneratorRange
)
AnchorGeneratorRange
)
__all__
=
[
__all__
=
[
'AnchorGenerator'
,
'AlignedAnchorGeneratorRange'
,
'AnchorGeneratorRange'
,
'AlignedAnchorGeneratorRange'
,
'AnchorGeneratorRange'
,
'build_anchor_generator'
'build_anchor_generator'
]
]
def
build_anchor_generator
(
cfg
,
**
kwargs
):
def
build_anchor_generator
(
cfg
,
**
kwargs
):
from
.
import
anchor_generator
from
.
import
anchor_
3d_
generator
import
mmcv
import
mmcv
if
isinstance
(
cfg
,
dict
):
if
isinstance
(
cfg
,
dict
):
return
mmcv
.
runner
.
obj_from_dict
(
return
mmcv
.
runner
.
obj_from_dict
(
cfg
,
anchor_generator
,
default_args
=
kwargs
)
cfg
,
anchor_
3d_
generator
,
default_args
=
kwargs
)
else
:
else
:
raise
TypeError
(
'Invalid type {} for building a sampler'
.
format
(
raise
TypeError
(
'Invalid type {} for building a sampler'
.
format
(
type
(
cfg
)))
type
(
cfg
)))
mmdet3d/core/anchor/anchor_generator.py
→
mmdet3d/core/anchor/anchor_
3d_
generator.py
View file @
6d71b439
import
torch
import
torch
class
AnchorGenerator
(
object
):
"""
Examples:
>>> from mmdet.core import AnchorGenerator
>>> self = AnchorGenerator(9, [1.], [1.])
>>> all_anchors = self.grid_anchors((2, 2), device='cpu')
>>> print(all_anchors)
tensor([[ 0., 0., 8., 8.],
[16., 0., 24., 8.],
[ 0., 16., 8., 24.],
[16., 16., 24., 24.]])
"""
def
__init__
(
self
,
base_size
,
scales
,
ratios
,
scale_major
=
True
,
ctr
=
None
):
self
.
base_size
=
base_size
self
.
scales
=
torch
.
Tensor
(
scales
)
self
.
ratios
=
torch
.
Tensor
(
ratios
)
self
.
scale_major
=
scale_major
self
.
ctr
=
ctr
self
.
base_anchors
=
self
.
gen_base_anchors
()
@
property
def
num_base_anchors
(
self
):
return
self
.
base_anchors
.
size
(
0
)
def
gen_base_anchors
(
self
):
w
=
self
.
base_size
h
=
self
.
base_size
h_ratios
=
torch
.
sqrt
(
self
.
ratios
)
w_ratios
=
1
/
h_ratios
if
self
.
scale_major
:
ws
=
(
w
*
w_ratios
[:,
None
]
*
self
.
scales
[
None
,
:]).
view
(
-
1
)
hs
=
(
h
*
h_ratios
[:,
None
]
*
self
.
scales
[
None
,
:]).
view
(
-
1
)
else
:
ws
=
(
w
*
self
.
scales
[:,
None
]
*
w_ratios
[
None
,
:]).
view
(
-
1
)
hs
=
(
h
*
self
.
scales
[:,
None
]
*
h_ratios
[
None
,
:]).
view
(
-
1
)
# yapf: disable
base_anchors
=
torch
.
stack
(
[
-
0.5
*
ws
,
-
0.5
*
hs
,
0.5
*
ws
,
0.5
*
hs
],
dim
=-
1
)
# yapf: enable
return
base_anchors
def
_meshgrid
(
self
,
x
,
y
,
row_major
=
True
):
xx
=
x
.
repeat
(
len
(
y
))
yy
=
y
.
view
(
-
1
,
1
).
repeat
(
1
,
len
(
x
)).
view
(
-
1
)
if
row_major
:
return
xx
,
yy
else
:
return
yy
,
xx
def
grid_anchors
(
self
,
featmap_size
,
stride
=
16
,
device
=
'cuda'
):
base_anchors
=
self
.
base_anchors
.
to
(
device
)
feat_h
,
feat_w
=
featmap_size
shift_x
=
torch
.
arange
(
0
,
feat_w
,
device
=
device
)
*
stride
shift_y
=
torch
.
arange
(
0
,
feat_h
,
device
=
device
)
*
stride
shift_xx
,
shift_yy
=
self
.
_meshgrid
(
shift_x
,
shift_y
)
shifts
=
torch
.
stack
([
shift_xx
,
shift_yy
,
shift_xx
,
shift_yy
],
dim
=-
1
)
shifts
=
shifts
.
type_as
(
base_anchors
)
# first feat_w elements correspond to the first row of shifts
# add A anchors (1, A, 4) to K shifts (K, 1, 4) to get
# shifted anchors (K, A, 4), reshape to (K*A, 4)
all_anchors
=
base_anchors
[
None
,
:,
:]
+
shifts
[:,
None
,
:]
all_anchors
=
all_anchors
.
view
(
-
1
,
4
)
# first A rows correspond to A anchors of (0, 0) in feature map,
# then (0, 1), (0, 2), ...
return
all_anchors
def
valid_flags
(
self
,
featmap_size
,
valid_size
,
device
=
'cuda'
):
feat_h
,
feat_w
=
featmap_size
valid_h
,
valid_w
=
valid_size
assert
valid_h
<=
feat_h
and
valid_w
<=
feat_w
valid_x
=
torch
.
zeros
(
feat_w
,
dtype
=
torch
.
uint8
,
device
=
device
)
valid_y
=
torch
.
zeros
(
feat_h
,
dtype
=
torch
.
uint8
,
device
=
device
)
valid_x
[:
valid_w
]
=
1
valid_y
[:
valid_h
]
=
1
valid_xx
,
valid_yy
=
self
.
_meshgrid
(
valid_x
,
valid_y
)
valid
=
valid_xx
&
valid_yy
valid
=
valid
[:,
None
].
expand
(
valid
.
size
(
0
),
self
.
num_base_anchors
).
contiguous
().
view
(
-
1
).
bool
()
return
valid
class
AnchorGeneratorRange
(
object
):
class
AnchorGeneratorRange
(
object
):
def
__init__
(
self
,
def
__init__
(
self
,
...
...
mmdet3d/core/bbox/__init__.py
View file @
6d71b439
from
.
import
box_torch_ops
from
.
import
box_torch_ops
from
.assigners
import
AssignResult
,
BaseAssigner
,
MaxIoUAssigner
from
.assigners
import
AssignResult
,
BaseAssigner
,
MaxIoUAssigner
from
.coders
import
ResidualCoder
from
.coders
import
Residual
3DBox
Coder
# from .bbox_target import bbox_target
# from .bbox_target import bbox_target
from
.iou_calculators
import
(
BboxOverlaps3D
,
BboxOverlapsNearest3D
,
from
.iou_calculators
import
(
BboxOverlaps3D
,
BboxOverlapsNearest3D
,
bbox_overlaps_3d
,
bbox_overlaps_nearest_3d
)
bbox_overlaps_3d
,
bbox_overlaps_nearest_3d
)
from
.samplers
import
(
BaseSampler
,
CombinedSampler
,
from
.samplers
import
(
BaseSampler
,
CombinedSampler
,
InstanceBalancedPosSampler
,
IoUBalancedNegSampler
,
InstanceBalancedPosSampler
,
IoUBalancedNegSampler
,
PseudoSampler
,
RandomSampler
,
SamplingResult
)
PseudoSampler
,
RandomSampler
,
SamplingResult
)
from
.transforms
import
delta2bbox
# bbox2result_kitti,
from
.transforms
import
boxes3d_to_bev_torch_lidar
from
.transforms
import
(
bbox2delta
,
bbox2result_coco
,
bbox2roi
,
bbox_flip
,
bbox_mapping
,
bbox_mapping_back
,
boxes3d_to_bev_torch_lidar
,
distance2bbox
,
roi2bbox
)
from
.assign_sampling
import
(
# isort:skip, avoid recursive imports
from
.assign_sampling
import
(
# isort:skip, avoid recursive imports
build_bbox_coder
,
# temporally settings
build_bbox_coder
,
# temporally settings
...
@@ -19,10 +16,9 @@ from .assign_sampling import ( # isort:skip, avoid recursive imports
...
@@ -19,10 +16,9 @@ from .assign_sampling import ( # isort:skip, avoid recursive imports
__all__
=
[
__all__
=
[
'BaseAssigner'
,
'MaxIoUAssigner'
,
'AssignResult'
,
'BaseSampler'
,
'BaseAssigner'
,
'MaxIoUAssigner'
,
'AssignResult'
,
'BaseSampler'
,
'PseudoSampler'
,
'RandomSampler'
,
'InstanceBalancedPosSampler'
,
'PseudoSampler'
,
'RandomSampler'
,
'InstanceBalancedPosSampler'
,
'IoUBalancedNegSampler'
,
'CombinedSampler'
,
'SamplingResult'
,
'bbox2delta'
,
'IoUBalancedNegSampler'
,
'CombinedSampler'
,
'SamplingResult'
,
'delta2bbox'
,
'bbox_flip'
,
'bbox_mapping'
,
'bbox_mapping_back'
,
'bbox2roi'
,
'build_assigner'
,
'build_sampler'
,
'assign_and_sample'
,
'box_torch_ops'
,
'roi2bbox'
,
'bbox2result_coco'
,
'distance2bbox'
,
'build_assigner'
,
'build_bbox_coder'
,
'Residual3DBoxCoder'
,
'boxes3d_to_bev_torch_lidar'
,
'build_sampler'
,
'assign_and_sample'
,
'box_torch_ops'
,
'build_bbox_coder'
,
'BboxOverlapsNearest3D'
,
'BboxOverlaps3D'
,
'bbox_overlaps_nearest_3d'
,
'ResidualCoder'
,
'boxes3d_to_bev_torch_lidar'
,
'BboxOverlapsNearest3D'
,
'bbox_overlaps_3d'
'BboxOverlaps3D'
,
'bbox_overlaps_nearest_3d'
,
'bbox_overlaps_3d'
]
]
mmdet3d/core/bbox/assign_sampling.py
View file @
6d71b439
...
@@ -14,7 +14,7 @@ def build_assigner(cfg, **kwargs):
...
@@ -14,7 +14,7 @@ def build_assigner(cfg, **kwargs):
def
build_bbox_coder
(
cfg
,
**
kwargs
):
def
build_bbox_coder
(
cfg
,
**
kwargs
):
if
isinstance
(
cfg
,
coders
.
ResidualCoder
):
if
isinstance
(
cfg
,
coders
.
Residual
3DBox
Coder
):
return
cfg
return
cfg
elif
isinstance
(
cfg
,
dict
):
elif
isinstance
(
cfg
,
dict
):
return
mmcv
.
runner
.
obj_from_dict
(
cfg
,
coders
,
default_args
=
kwargs
)
return
mmcv
.
runner
.
obj_from_dict
(
cfg
,
coders
,
default_args
=
kwargs
)
...
...
mmdet3d/core/bbox/coders/__init__.py
View file @
6d71b439
from
.box_coder
import
ResidualCoder
from
.box_coder
import
Residual
3DBox
Coder
__all__
=
[
'ResidualCoder'
]
__all__
=
[
'Residual
3DBox
Coder'
]
mmdet3d/core/bbox/coders/box_coder.py
View file @
6d71b439
...
@@ -2,7 +2,7 @@ import numpy as np
...
@@ -2,7 +2,7 @@ import numpy as np
import
torch
import
torch
class
ResidualCoder
(
object
):
class
Residual
3DBox
Coder
(
object
):
def
__init__
(
self
,
code_size
=
7
,
mean
=
None
,
std
=
None
):
def
__init__
(
self
,
code_size
=
7
,
mean
=
None
,
std
=
None
):
super
().
__init__
()
super
().
__init__
()
...
...
mmdet3d/core/bbox/samplers/__init__.py
View file @
6d71b439
from
.base_sampler
import
BaseSampler
from
mmdet.core.bbox.samplers
import
(
BaseSampler
,
CombinedSampler
,
from
.combined_sampler
import
CombinedSampler
InstanceBalancedPosSampler
,
from
.instance_balanced_pos_sampler
import
InstanceBalancedPosSampler
IoUBalancedNegSampler
,
OHEMSampler
,
from
.iou_balanced_neg_sampler
import
IoUBalancedNegSampler
PseudoSampler
,
RandomSampler
,
from
.ohem_sampler
import
OHEMSampler
SamplingResult
)
from
.pseudo_sampler
import
PseudoSampler
from
.random_sampler
import
RandomSampler
from
.sampling_result
import
SamplingResult
__all__
=
[
__all__
=
[
'BaseSampler'
,
'PseudoSampler'
,
'RandomSampler'
,
'BaseSampler'
,
'PseudoSampler'
,
'RandomSampler'
,
...
...
mmdet3d/core/bbox/samplers/base_sampler.py
deleted
100644 → 0
View file @
ba492be7
from
abc
import
ABCMeta
,
abstractmethod
import
torch
from
.sampling_result
import
SamplingResult
class
BaseSampler
(
metaclass
=
ABCMeta
):
def
__init__
(
self
,
num
,
pos_fraction
,
neg_pos_ub
=-
1
,
add_gt_as_proposals
=
True
,
**
kwargs
):
self
.
num
=
num
self
.
pos_fraction
=
pos_fraction
self
.
neg_pos_ub
=
neg_pos_ub
self
.
add_gt_as_proposals
=
add_gt_as_proposals
self
.
pos_sampler
=
self
self
.
neg_sampler
=
self
@
abstractmethod
def
_sample_pos
(
self
,
assign_result
,
num_expected
,
**
kwargs
):
pass
@
abstractmethod
def
_sample_neg
(
self
,
assign_result
,
num_expected
,
**
kwargs
):
pass
def
sample
(
self
,
assign_result
,
bboxes
,
gt_bboxes
,
gt_labels
=
None
,
**
kwargs
):
"""Sample positive and negative bboxes.
This is a simple implementation of bbox sampling given candidates,
assigning results and ground truth bboxes.
Args:
assign_result (:obj:`AssignResult`): Bbox assigning results.
bboxes (Tensor): Boxes to be sampled from.
gt_bboxes (Tensor): Ground truth bboxes.
gt_labels (Tensor, optional): Class labels of ground truth bboxes.
Returns:
:obj:`SamplingResult`: Sampling result.
"""
bboxes
=
bboxes
[:,
:
4
]
gt_flags
=
bboxes
.
new_zeros
((
bboxes
.
shape
[
0
],
),
dtype
=
torch
.
uint8
)
if
self
.
add_gt_as_proposals
:
bboxes
=
torch
.
cat
([
gt_bboxes
,
bboxes
],
dim
=
0
)
assign_result
.
add_gt_
(
gt_labels
)
gt_ones
=
bboxes
.
new_ones
(
gt_bboxes
.
shape
[
0
],
dtype
=
torch
.
uint8
)
gt_flags
=
torch
.
cat
([
gt_ones
,
gt_flags
])
num_expected_pos
=
int
(
self
.
num
*
self
.
pos_fraction
)
pos_inds
=
self
.
pos_sampler
.
_sample_pos
(
assign_result
,
num_expected_pos
,
bboxes
=
bboxes
,
**
kwargs
)
# We found that sampled indices have duplicated items occasionally.
# (may be a bug of PyTorch)
pos_inds
=
pos_inds
.
unique
()
num_sampled_pos
=
pos_inds
.
numel
()
num_expected_neg
=
self
.
num
-
num_sampled_pos
if
self
.
neg_pos_ub
>=
0
:
_pos
=
max
(
1
,
num_sampled_pos
)
neg_upper_bound
=
int
(
self
.
neg_pos_ub
*
_pos
)
if
num_expected_neg
>
neg_upper_bound
:
num_expected_neg
=
neg_upper_bound
neg_inds
=
self
.
neg_sampler
.
_sample_neg
(
assign_result
,
num_expected_neg
,
bboxes
=
bboxes
,
**
kwargs
)
neg_inds
=
neg_inds
.
unique
()
return
SamplingResult
(
pos_inds
,
neg_inds
,
bboxes
,
gt_bboxes
,
assign_result
,
gt_flags
)
Prev
1
2
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