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
dcnv3
Commits
41b18fd8
Commit
41b18fd8
authored
Jan 06, 2025
by
zhe chen
Browse files
Use pre-commit to reformat code
Use pre-commit to reformat code
parent
ff20ea39
Changes
390
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
544 additions
and
625 deletions
+544
-625
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/bevformer/runner/__init__.py
...tion/projects/mmdet3d_plugin/bevformer/runner/__init__.py
+1
-1
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/bevformer/runner/epoch_based_runner.py
...cts/mmdet3d_plugin/bevformer/runner/epoch_based_runner.py
+93
-97
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/core/bbox/assigners/hungarian_assigner_3d.py
...det3d_plugin/core/bbox/assigners/hungarian_assigner_3d.py
+9
-12
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/core/bbox/coders/nms_free_coder.py
...rojects/mmdet3d_plugin/core/bbox/coders/nms_free_coder.py
+5
-8
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/core/bbox/match_costs/__init__.py
...projects/mmdet3d_plugin/core/bbox/match_costs/__init__.py
+1
-2
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/core/bbox/match_costs/match_cost.py
...ojects/mmdet3d_plugin/core/bbox/match_costs/match_cost.py
+1
-1
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/core/bbox/util.py
...ancy_prediction/projects/mmdet3d_plugin/core/bbox/util.py
+10
-10
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/core/evaluation/__init__.py
...ction/projects/mmdet3d_plugin/core/evaluation/__init__.py
+1
-1
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/core/evaluation/eval_hooks.py
...ion/projects/mmdet3d_plugin/core/evaluation/eval_hooks.py
+4
-7
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/__init__.py
...y_prediction/projects/mmdet3d_plugin/datasets/__init__.py
+1
-1
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/builder.py
...cy_prediction/projects/mmdet3d_plugin/datasets/builder.py
+26
-23
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/nuscenes_dataset.py
...tion/projects/mmdet3d_plugin/datasets/nuscenes_dataset.py
+11
-16
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/nuscenes_occ.py
...ediction/projects/mmdet3d_plugin/datasets/nuscenes_occ.py
+16
-23
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/nuscnes_eval.py
...ediction/projects/mmdet3d_plugin/datasets/nuscnes_eval.py
+36
-69
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/occ_metrics.py
...rediction/projects/mmdet3d_plugin/datasets/occ_metrics.py
+225
-239
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/pipelines/__init__.py
...on/projects/mmdet3d_plugin/datasets/pipelines/__init__.py
+9
-6
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/pipelines/formating.py
...n/projects/mmdet3d_plugin/datasets/pipelines/formating.py
+35
-39
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/pipelines/loading.py
...ion/projects/mmdet3d_plugin/datasets/pipelines/loading.py
+44
-46
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/pipelines/transform_3d.py
...rojects/mmdet3d_plugin/datasets/pipelines/transform_3d.py
+15
-22
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/samplers/__init__.py
...ion/projects/mmdet3d_plugin/datasets/samplers/__init__.py
+1
-2
No files found.
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/bevformer/runner/__init__.py
View file @
41b18fd8
from
.epoch_based_runner
import
EpochBasedRunner_video
\ No newline at end of file
from
.epoch_based_runner
import
EpochBasedRunner_video
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/bevformer/runner/epoch_based_runner.py
View file @
41b18fd8
# Copyright (c) OpenMMLab. All rights reserved.
# ---------------------------------------------
# Modified by Zhiqi Li
# ---------------------------------------------
import
os.path
as
osp
import
torch
import
mmcv
from
mmcv.runner.base_runner
import
BaseRunner
from
mmcv.runner.epoch_based_runner
import
EpochBasedRunner
from
mmcv.runner.builder
import
RUNNERS
from
mmcv.runner.checkpoint
import
save_checkpoint
from
mmcv.runner.utils
import
get_host_info
from
pprint
import
pprint
from
mmcv.parallel.data_container
import
DataContainer
@
RUNNERS
.
register_module
()
class
EpochBasedRunner_video
(
EpochBasedRunner
):
'''
# basic logic
input_sequence = [a, b, c] # given a sequence of samples
prev_bev = None
for each in input_sequcene[:-1]
prev_bev = eval_model(each, prev_bev)) # inference only.
model(input_sequcene[-1], prev_bev) # train the last sample.
'''
def
__init__
(
self
,
model
,
eval_model
=
None
,
batch_processor
=
None
,
optimizer
=
None
,
work_dir
=
None
,
logger
=
None
,
meta
=
None
,
keys
=
[
'gt_bboxes_3d'
,
'gt_labels_3d'
,
'img'
],
max_iters
=
None
,
max_epochs
=
None
):
super
().
__init__
(
model
,
batch_processor
,
optimizer
,
work_dir
,
logger
,
meta
,
max_iters
,
max_epochs
)
keys
.
append
(
'img_metas'
)
self
.
keys
=
keys
self
.
eval_model
=
eval_model
self
.
eval_model
.
eval
()
def
run_iter
(
self
,
data_batch
,
train_mode
,
**
kwargs
):
if
self
.
batch_processor
is
not
None
:
assert
False
# outputs = self.batch_processor(
# self.model, data_batch, train_mode=train_mode, **kwargs)
elif
train_mode
:
num_samples
=
data_batch
[
'img'
].
data
[
0
].
size
(
1
)
data_list
=
[]
prev_bev
=
None
for
i
in
range
(
num_samples
):
data
=
{}
for
key
in
self
.
keys
:
if
key
not
in
[
'img_metas'
,
'img'
,
'points'
]:
data
[
key
]
=
data_batch
[
key
]
else
:
if
key
==
'img'
:
data
[
'img'
]
=
DataContainer
(
data
=
[
data_batch
[
'img'
].
data
[
0
][:,
i
]],
cpu_only
=
data_batch
[
'img'
].
cpu_only
,
stack
=
True
)
elif
key
==
'img_metas'
:
data
[
'img_metas'
]
=
DataContainer
(
data
=
[[
each
[
i
]
for
each
in
data_batch
[
'img_metas'
].
data
[
0
]]],
cpu_only
=
data_batch
[
'img_metas'
].
cpu_only
)
else
:
assert
False
data_list
.
append
(
data
)
with
torch
.
no_grad
():
for
i
in
range
(
num_samples
-
1
):
if
data_list
[
i
][
'img_metas'
].
data
[
0
][
0
][
'prev_bev_exists'
]:
data_list
[
i
][
'prev_bev'
]
=
DataContainer
(
data
=
[
prev_bev
],
cpu_only
=
False
)
prev_bev
=
self
.
eval_model
.
val_step
(
data_list
[
i
],
self
.
optimizer
,
**
kwargs
)
if
data_list
[
-
1
][
'img_metas'
].
data
[
0
][
0
][
'prev_bev_exists'
]:
data_list
[
-
1
][
'prev_bev'
]
=
DataContainer
(
data
=
[
prev_bev
],
cpu_only
=
False
)
outputs
=
self
.
model
.
train_step
(
data_list
[
-
1
],
self
.
optimizer
,
**
kwargs
)
else
:
assert
False
# outputs = self.model.val_step(data_batch, self.optimizer, **kwargs)
if
not
isinstance
(
outputs
,
dict
):
raise
TypeError
(
'"batch_processor()" or "model.train_step()"'
'and "model.val_step()" must return a dict'
)
if
'log_vars'
in
outputs
:
self
.
log_buffer
.
update
(
outputs
[
'log_vars'
],
outputs
[
'num_samples'
])
self
.
outputs
=
outputs
\ No newline at end of file
# Copyright (c) OpenMMLab. All rights reserved.
# ---------------------------------------------
# Modified by Zhiqi Li
# ---------------------------------------------
import
torch
from
mmcv.parallel.data_container
import
DataContainer
from
mmcv.runner.builder
import
RUNNERS
from
mmcv.runner.epoch_based_runner
import
EpochBasedRunner
@
RUNNERS
.
register_module
()
class
EpochBasedRunner_video
(
EpochBasedRunner
):
'''
# basic logic
input_sequence = [a, b, c] # given a sequence of samples
prev_bev = None
for each in input_sequcene[:-1]
prev_bev = eval_model(each, prev_bev)) # inference only.
model(input_sequcene[-1], prev_bev) # train the last sample.
'''
def
__init__
(
self
,
model
,
eval_model
=
None
,
batch_processor
=
None
,
optimizer
=
None
,
work_dir
=
None
,
logger
=
None
,
meta
=
None
,
keys
=
[
'gt_bboxes_3d'
,
'gt_labels_3d'
,
'img'
],
max_iters
=
None
,
max_epochs
=
None
):
super
().
__init__
(
model
,
batch_processor
,
optimizer
,
work_dir
,
logger
,
meta
,
max_iters
,
max_epochs
)
keys
.
append
(
'img_metas'
)
self
.
keys
=
keys
self
.
eval_model
=
eval_model
self
.
eval_model
.
eval
()
def
run_iter
(
self
,
data_batch
,
train_mode
,
**
kwargs
):
if
self
.
batch_processor
is
not
None
:
assert
False
# outputs = self.batch_processor(
# self.model, data_batch, train_mode=train_mode, **kwargs)
elif
train_mode
:
num_samples
=
data_batch
[
'img'
].
data
[
0
].
size
(
1
)
data_list
=
[]
prev_bev
=
None
for
i
in
range
(
num_samples
):
data
=
{}
for
key
in
self
.
keys
:
if
key
not
in
[
'img_metas'
,
'img'
,
'points'
]:
data
[
key
]
=
data_batch
[
key
]
else
:
if
key
==
'img'
:
data
[
'img'
]
=
DataContainer
(
data
=
[
data_batch
[
'img'
].
data
[
0
][:,
i
]],
cpu_only
=
data_batch
[
'img'
].
cpu_only
,
stack
=
True
)
elif
key
==
'img_metas'
:
data
[
'img_metas'
]
=
DataContainer
(
data
=
[[
each
[
i
]
for
each
in
data_batch
[
'img_metas'
].
data
[
0
]]],
cpu_only
=
data_batch
[
'img_metas'
].
cpu_only
)
else
:
assert
False
data_list
.
append
(
data
)
with
torch
.
no_grad
():
for
i
in
range
(
num_samples
-
1
):
if
data_list
[
i
][
'img_metas'
].
data
[
0
][
0
][
'prev_bev_exists'
]:
data_list
[
i
][
'prev_bev'
]
=
DataContainer
(
data
=
[
prev_bev
],
cpu_only
=
False
)
prev_bev
=
self
.
eval_model
.
val_step
(
data_list
[
i
],
self
.
optimizer
,
**
kwargs
)
if
data_list
[
-
1
][
'img_metas'
].
data
[
0
][
0
][
'prev_bev_exists'
]:
data_list
[
-
1
][
'prev_bev'
]
=
DataContainer
(
data
=
[
prev_bev
],
cpu_only
=
False
)
outputs
=
self
.
model
.
train_step
(
data_list
[
-
1
],
self
.
optimizer
,
**
kwargs
)
else
:
assert
False
# outputs = self.model.val_step(data_batch, self.optimizer, **kwargs)
if
not
isinstance
(
outputs
,
dict
):
raise
TypeError
(
'"batch_processor()" or "model.train_step()"'
'and "model.val_step()" must return a dict'
)
if
'log_vars'
in
outputs
:
self
.
log_buffer
.
update
(
outputs
[
'log_vars'
],
outputs
[
'num_samples'
])
self
.
outputs
=
outputs
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/core/bbox/assigners/hungarian_assigner_3d.py
View file @
41b18fd8
import
torch
from
mmdet.core.bbox.assigners
import
AssignResult
,
BaseAssigner
from
mmdet.core.bbox.builder
import
BBOX_ASSIGNERS
from
mmdet.core.bbox.assigners
import
AssignResult
from
mmdet.core.bbox.assigners
import
BaseAssigner
from
mmdet.core.bbox.match_costs
import
build_match_cost
from
mmdet.models.utils.transformer
import
inverse_sigmoid
from
projects.mmdet3d_plugin.core.bbox.util
import
normalize_bbox
try
:
...
...
@@ -52,7 +49,7 @@ class HungarianAssigner3D(BaseAssigner):
def
assign
(
self
,
bbox_pred
,
cls_pred
,
gt_bboxes
,
gt_bboxes
,
gt_labels
,
gt_bboxes_ignore
=
None
,
eps
=
1e-7
):
...
...
@@ -89,10 +86,10 @@ class HungarianAssigner3D(BaseAssigner):
num_gts
,
num_bboxes
=
gt_bboxes
.
size
(
0
),
bbox_pred
.
size
(
0
)
# 1. assign -1 by default
assigned_gt_inds
=
bbox_pred
.
new_full
((
num_bboxes
,
),
assigned_gt_inds
=
bbox_pred
.
new_full
((
num_bboxes
,),
-
1
,
dtype
=
torch
.
long
)
assigned_labels
=
bbox_pred
.
new_full
((
num_bboxes
,
),
assigned_labels
=
bbox_pred
.
new_full
((
num_bboxes
,),
-
1
,
dtype
=
torch
.
long
)
if
num_gts
==
0
or
num_bboxes
==
0
:
...
...
@@ -107,14 +104,14 @@ class HungarianAssigner3D(BaseAssigner):
# classification and bboxcost.
cls_cost
=
self
.
cls_cost
(
cls_pred
,
gt_labels
)
# regression L1 cost
normalized_gt_bboxes
=
normalize_bbox
(
gt_bboxes
,
self
.
pc_range
)
reg_cost
=
self
.
reg_cost
(
bbox_pred
[:,
:
8
],
normalized_gt_bboxes
[:,
:
8
])
# weighted sum of above two costs
cost
=
cls_cost
+
reg_cost
# 3. do Hungarian matching on CPU using linear_sum_assignment
cost
=
cost
.
detach
().
cpu
()
if
linear_sum_assignment
is
None
:
...
...
@@ -133,4 +130,4 @@ class HungarianAssigner3D(BaseAssigner):
assigned_gt_inds
[
matched_row_inds
]
=
matched_col_inds
+
1
assigned_labels
[
matched_row_inds
]
=
gt_labels
[
matched_col_inds
]
return
AssignResult
(
num_gts
,
assigned_gt_inds
,
None
,
labels
=
assigned_labels
)
\ No newline at end of file
num_gts
,
assigned_gt_inds
,
None
,
labels
=
assigned_labels
)
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/core/bbox/coders/nms_free_coder.py
View file @
41b18fd8
import
torch
from
mmdet.core.bbox
import
BaseBBoxCoder
from
mmdet.core.bbox.builder
import
BBOX_CODERS
from
projects.mmdet3d_plugin.core.bbox.util
import
denormalize_bbox
import
numpy
as
np
@
BBOX_CODERS
.
register_module
()
...
...
@@ -56,10 +54,10 @@ class NMSFreeCoder(BaseBBoxCoder):
labels
=
indexs
%
self
.
num_classes
bbox_index
=
indexs
//
self
.
num_classes
bbox_preds
=
bbox_preds
[
bbox_index
]
final_box_preds
=
denormalize_bbox
(
bbox_preds
,
self
.
pc_range
)
final_scores
=
scores
final_preds
=
labels
final_box_preds
=
denormalize_bbox
(
bbox_preds
,
self
.
pc_range
)
final_scores
=
scores
final_preds
=
labels
# use score threshold
if
self
.
score_threshold
is
not
None
:
...
...
@@ -113,10 +111,9 @@ class NMSFreeCoder(BaseBBoxCoder):
"""
all_cls_scores
=
preds_dicts
[
'all_cls_scores'
][
-
1
]
all_bbox_preds
=
preds_dicts
[
'all_bbox_preds'
][
-
1
]
batch_size
=
all_cls_scores
.
size
()[
0
]
predictions_list
=
[]
for
i
in
range
(
batch_size
):
predictions_list
.
append
(
self
.
decode_single
(
all_cls_scores
[
i
],
all_bbox_preds
[
i
]))
return
predictions_list
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/core/bbox/match_costs/__init__.py
View file @
41b18fd8
from
mmdet.core.bbox.match_costs
import
build_match_cost
from
.match_cost
import
BBox3DL1Cost
__all__
=
[
'build_match_cost'
,
'BBox3DL1Cost'
]
\ No newline at end of file
__all__
=
[
'build_match_cost'
,
'BBox3DL1Cost'
]
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/core/bbox/match_costs/match_cost.py
View file @
41b18fd8
...
...
@@ -24,4 +24,4 @@ class BBox3DL1Cost(object):
torch.Tensor: bbox_cost value with weight
"""
bbox_cost
=
torch
.
cdist
(
bbox_pred
,
gt_bboxes
,
p
=
1
)
return
bbox_cost
*
self
.
weight
\ No newline at end of file
return
bbox_cost
*
self
.
weight
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/core/bbox/util.py
View file @
41b18fd8
import
torch
import
torch
def
normalize_bbox
(
bboxes
,
pc_range
):
cx
=
bboxes
[...,
0
:
1
]
cy
=
bboxes
[...,
1
:
2
]
cz
=
bboxes
[...,
2
:
3
]
...
...
@@ -12,7 +11,7 @@ def normalize_bbox(bboxes, pc_range):
rot
=
bboxes
[...,
6
:
7
]
if
bboxes
.
size
(
-
1
)
>
7
:
vx
=
bboxes
[...,
7
:
8
]
vx
=
bboxes
[...,
7
:
8
]
vy
=
bboxes
[...,
8
:
9
]
normalized_bboxes
=
torch
.
cat
(
(
cx
,
cy
,
w
,
l
,
cz
,
h
,
rot
.
sin
(),
rot
.
cos
(),
vx
,
vy
),
dim
=-
1
...
...
@@ -23,8 +22,9 @@ def normalize_bbox(bboxes, pc_range):
)
return
normalized_bboxes
def
denormalize_bbox
(
normalized_bboxes
,
pc_range
):
# rotation
# rotation
rot_sine
=
normalized_bboxes
[...,
6
:
7
]
rot_cosine
=
normalized_bboxes
[...,
7
:
8
]
...
...
@@ -34,20 +34,20 @@ def denormalize_bbox(normalized_bboxes, pc_range):
cx
=
normalized_bboxes
[...,
0
:
1
]
cy
=
normalized_bboxes
[...,
1
:
2
]
cz
=
normalized_bboxes
[...,
4
:
5
]
# size
w
=
normalized_bboxes
[...,
2
:
3
]
l
=
normalized_bboxes
[...,
3
:
4
]
h
=
normalized_bboxes
[...,
5
:
6
]
w
=
w
.
exp
()
l
=
l
.
exp
()
h
=
h
.
exp
()
w
=
w
.
exp
()
l
=
l
.
exp
()
h
=
h
.
exp
()
if
normalized_bboxes
.
size
(
-
1
)
>
8
:
# velocity
# velocity
vx
=
normalized_bboxes
[:,
8
:
9
]
vy
=
normalized_bboxes
[:,
9
:
10
]
denormalized_bboxes
=
torch
.
cat
([
cx
,
cy
,
cz
,
w
,
l
,
h
,
rot
,
vx
,
vy
],
dim
=-
1
)
else
:
denormalized_bboxes
=
torch
.
cat
([
cx
,
cy
,
cz
,
w
,
l
,
h
,
rot
],
dim
=-
1
)
return
denormalized_bboxes
\ No newline at end of file
return
denormalized_bboxes
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/core/evaluation/__init__.py
View file @
41b18fd8
from
.eval_hooks
import
CustomDistEvalHook
\ No newline at end of file
from
.eval_hooks
import
CustomDistEvalHook
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/core/evaluation/eval_hooks.py
View file @
41b18fd8
# Note: Considering that MMCV's EvalHook updated its interface in V1.3.16,
# in order to avoid strong version dependency, we did not directly
# inherit EvalHook but BaseDistEvalHook.
...
...
@@ -9,9 +8,7 @@ import os.path as osp
import
mmcv
import
torch.distributed
as
dist
from
mmcv.runner
import
DistEvalHook
as
BaseDistEvalHook
from
mmcv.runner
import
EvalHook
as
BaseEvalHook
from
torch.nn.modules.batchnorm
import
_BatchNorm
from
mmdet.core.evaluation.eval_hooks
import
DistEvalHook
def
_calc_dynamic_intervals
(
start_interval
,
dynamic_interval_list
):
...
...
@@ -28,7 +25,7 @@ def _calc_dynamic_intervals(start_interval, dynamic_interval_list):
class
CustomDistEvalHook
(
BaseDistEvalHook
):
def
__init__
(
self
,
*
args
,
dynamic_intervals
=
None
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
dynamic_intervals
=
None
,
**
kwargs
):
super
(
CustomDistEvalHook
,
self
).
__init__
(
*
args
,
**
kwargs
)
self
.
use_dynamic_intervals
=
dynamic_intervals
is
not
None
if
self
.
use_dynamic_intervals
:
...
...
@@ -73,7 +70,8 @@ class CustomDistEvalHook(BaseDistEvalHook):
if
tmpdir
is
None
:
tmpdir
=
osp
.
join
(
runner
.
work_dir
,
'.eval_hook'
)
from
projects.mmdet3d_plugin.bevformer.apis.test
import
custom_multi_gpu_test
# to solve circlur import
from
projects.mmdet3d_plugin.bevformer.apis.test
import
\
custom_multi_gpu_test
# to solve circlur import
results
=
custom_multi_gpu_test
(
runner
.
model
,
...
...
@@ -86,7 +84,6 @@ class CustomDistEvalHook(BaseDistEvalHook):
# key_score = self.evaluate(runner, results)
self
.
dataloader
.
dataset
.
evaluate_miou
(
results
,
runner
=
runner
)
runner
=
runner
)
# if self.save_best:
# self._save_ckpt(runner, key_score)
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/__init__.py
View file @
41b18fd8
from
.builder
import
custom_build_dataset
from
.nuscenes_dataset
import
CustomNuScenesDataset
from
.nuscenes_occ
import
NuSceneOcc
from
.builder
import
custom_build_dataset
__all__
=
[
'CustomNuScenesDataset'
...
...
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/builder.py
View file @
41b18fd8
# Copyright (c) OpenMMLab. All rights reserved.
import
copy
import
platform
...
...
@@ -8,13 +7,14 @@ from functools import partial
import
numpy
as
np
from
mmcv.parallel
import
collate
from
mmcv.runner
import
get_dist_info
from
mmcv.utils
import
Registry
,
build_from_cfg
from
torch.utils.data
import
DataLoader
from
mmdet.datasets.samplers
import
GroupSampler
from
projects.mmdet3d_plugin.datasets.samplers.group_sampler
import
DistributedGroupSampler
from
projects.mmdet3d_plugin.datasets.samplers.distributed_sampler
import
DistributedSampler
from
projects.mmdet3d_plugin.datasets.samplers.distributed_sampler
import
\
DistributedSampler
from
projects.mmdet3d_plugin.datasets.samplers.group_sampler
import
\
DistributedGroupSampler
from
projects.mmdet3d_plugin.datasets.samplers.sampler
import
build_sampler
from
torch.utils.data
import
DataLoader
def
build_dataloader
(
dataset
,
samples_per_gpu
,
...
...
@@ -48,24 +48,26 @@ def build_dataloader(dataset,
# DistributedGroupSampler will definitely shuffle the data to satisfy
# that images on each GPU are in the same group
if
shuffle
:
sampler
=
build_sampler
(
shuffler_sampler
if
shuffler_sampler
is
not
None
else
dict
(
type
=
'DistributedGroupSampler'
),
dict
(
dataset
=
dataset
,
samples_per_gpu
=
samples_per_gpu
,
num_replicas
=
world_size
,
rank
=
rank
,
seed
=
seed
)
)
sampler
=
build_sampler
(
shuffler_sampler
if
shuffler_sampler
is
not
None
else
dict
(
type
=
'DistributedGroupSampler'
),
dict
(
dataset
=
dataset
,
samples_per_gpu
=
samples_per_gpu
,
num_replicas
=
world_size
,
rank
=
rank
,
seed
=
seed
)
)
else
:
sampler
=
build_sampler
(
nonshuffler_sampler
if
nonshuffler_sampler
is
not
None
else
dict
(
type
=
'DistributedSampler'
),
dict
(
dataset
=
dataset
,
num_replicas
=
world_size
,
rank
=
rank
,
shuffle
=
shuffle
,
seed
=
seed
)
)
sampler
=
build_sampler
(
nonshuffler_sampler
if
nonshuffler_sampler
is
not
None
else
dict
(
type
=
'DistributedSampler'
),
dict
(
dataset
=
dataset
,
num_replicas
=
world_size
,
rank
=
rank
,
shuffle
=
shuffle
,
seed
=
seed
)
)
batch_size
=
samples_per_gpu
num_workers
=
workers_per_gpu
...
...
@@ -103,14 +105,15 @@ def worker_init_fn(worker_id, num_workers, rank, seed):
# Copyright (c) OpenMMLab. All rights reserved.
import
platform
from
mmcv.utils
import
Registry
,
build_from_cfg
from
mmcv.utils
import
Registry
,
build_from_cfg
from
mmdet.datasets
import
DATASETS
from
mmdet.datasets.builder
import
_concat_dataset
if
platform
.
system
()
!=
'Windows'
:
# https://github.com/pytorch/pytorch/issues/973
import
resource
rlimit
=
resource
.
getrlimit
(
resource
.
RLIMIT_NOFILE
)
base_soft_limit
=
rlimit
[
0
]
hard_limit
=
rlimit
[
1
]
...
...
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/nuscenes_dataset.py
View file @
41b18fd8
import
copy
import
random
from
os
import
path
as
osp
import
mmcv
import
numpy
as
np
from
mmdet.datasets
import
DATASETS
import
torch
from
mmcv.parallel
import
DataContainer
as
DC
from
mmdet3d.core.bbox
import
LiDARInstance3DBoxes
from
mmdet3d.datasets
import
NuScenesDataset
import
mmcv
from
os
import
path
as
osp
from
mmdet.datasets
import
DATASETS
import
torch
import
numpy
as
np
from
nuscenes.eval.common.utils
import
quaternion_yaw
,
Quaternion
from
mmdet3d.core.bbox
import
Box3DMode
,
Coord3DMode
,
LiDARInstance3DBoxes
from
nuscenes.eval.common.utils
import
Quaternion
,
quaternion_yaw
from
.nuscnes_eval
import
NuScenesEval_custom
from
projects.mmdet3d_plugin.models.utils.visual
import
save_tensor
from
mmcv.parallel
import
DataContainer
as
DC
import
random
@
DATASETS
.
register_module
()
...
...
@@ -28,7 +26,7 @@ class CustomNuScenesDataset(NuScenesDataset):
self
.
queue_length
=
queue_length
self
.
overlap_test
=
overlap_test
self
.
bev_size
=
bev_size
def
prepare_train_data
(
self
,
index
):
"""
Training data preparation.
...
...
@@ -38,7 +36,7 @@ class CustomNuScenesDataset(NuScenesDataset):
dict: Training data dict of the corresponding index.
"""
queue
=
[]
index_list
=
list
(
range
(
index
-
self
.
queue_length
,
index
))
index_list
=
list
(
range
(
index
-
self
.
queue_length
,
index
))
random
.
shuffle
(
index_list
)
index_list
=
sorted
(
index_list
[
1
:])
index_list
.
append
(
index
)
...
...
@@ -55,7 +53,6 @@ class CustomNuScenesDataset(NuScenesDataset):
queue
.
append
(
example
)
return
self
.
union2one
(
queue
)
def
union2one
(
self
,
queue
):
imgs_list
=
[
each
[
'img'
].
data
for
each
in
queue
]
metas_map
=
{}
...
...
@@ -127,8 +124,6 @@ class CustomNuScenesDataset(NuScenesDataset):
box_dim
=
gt_bboxes_3d
.
shape
[
-
1
],
origin
=
(
0.5
,
0.5
,
0.5
)).
convert_to
(
self
.
box_mode_3d
)
anns_results
=
dict
(
gt_bboxes_3d
=
gt_bboxes_3d
,
gt_labels_3d
=
gt_labels_3d
,
...
...
@@ -180,7 +175,7 @@ class CustomNuScenesDataset(NuScenesDataset):
# obtain lidar to image transformation matrix
lidar2cam_r
=
np
.
linalg
.
inv
(
cam_info
[
'sensor2lidar_rotation'
])
lidar2cam_t
=
cam_info
[
'sensor2lidar_translation'
]
@
lidar2cam_r
.
T
'sensor2lidar_translation'
]
@
lidar2cam_r
.
T
lidar2cam_rt
=
np
.
eye
(
4
)
lidar2cam_rt
[:
3
,
:
3
]
=
lidar2cam_r
.
T
lidar2cam_rt
[
3
,
:
3
]
=
-
lidar2cam_t
...
...
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/nuscenes_occ.py
View file @
41b18fd8
import
copy
import
os
import
numpy
as
np
from
tqdm
import
tqdm
from
mmdet.datasets
import
DATASETS
from
mmdet3d.datasets
import
NuScenesDataset
import
random
import
mmcv
from
os
import
path
as
osp
from
mmdet.datasets
import
DATASETS
import
torch
import
numpy
as
np
from
nuscenes.eval.common.utils
import
quaternion_yaw
,
Quaternion
from
.nuscnes_eval
import
NuScenesEval_custom
from
projects.mmdet3d_plugin.models.utils.visual
import
save_tensor
import
torch
from
mmcv.parallel
import
DataContainer
as
DC
import
random
from
mmdet3d.datasets
import
NuScenesDataset
from
mmdet.datasets
import
DATASETS
from
nuscenes.eval.common.utils
import
Quaternion
,
quaternion_yaw
from
nuscenes.utils.geometry_utils
import
transform_matrix
from
.occ_metrics
import
Metric_mIoU
,
Metric_FScore
from
tqdm
import
tqdm
from
.occ_metrics
import
Metric_FScore
,
Metric_mIoU
@
DATASETS
.
register_module
()
...
...
@@ -209,8 +206,8 @@ class NuSceneOcc(NuScenesDataset):
if
not
os
.
path
.
exists
(
show_dir
):
os
.
mkdir
(
show_dir
)
print
(
'
\n
Saving output and gt in {} for visualization.'
.
format
(
show_dir
))
begin
=
eval_kwargs
.
get
(
'begin'
,
None
)
end
=
eval_kwargs
.
get
(
'end'
,
None
)
begin
=
eval_kwargs
.
get
(
'begin'
,
None
)
end
=
eval_kwargs
.
get
(
'end'
,
None
)
self
.
occ_eval_metrics
=
Metric_mIoU
(
num_classes
=
18
,
use_lidar_mask
=
False
,
...
...
@@ -233,15 +230,14 @@ class NuSceneOcc(NuScenesDataset):
occ_gt
=
np
.
load
(
os
.
path
.
join
(
self
.
data_root
,
info
[
'occ_gt_path'
]))
if
show_dir
is
not
None
:
if
begin
is
not
None
and
end
is
not
None
:
if
index
>=
begin
and
index
<
end
:
if
index
>=
begin
and
index
<
end
:
sample_token
=
info
[
'token'
]
save_path
=
os
.
path
.
join
(
show_dir
,
str
(
index
).
zfill
(
4
))
save_path
=
os
.
path
.
join
(
show_dir
,
str
(
index
).
zfill
(
4
))
np
.
savez_compressed
(
save_path
,
pred
=
occ_pred
,
gt
=
occ_gt
,
sample_token
=
sample_token
)
else
:
sample_token
=
info
[
'token'
]
save_path
=
os
.
path
.
join
(
show_dir
,
str
(
index
).
zfill
(
4
))
np
.
savez_compressed
(
save_path
,
pred
=
occ_pred
,
gt
=
occ_gt
,
sample_token
=
sample_token
)
sample_token
=
info
[
'token'
]
save_path
=
os
.
path
.
join
(
show_dir
,
str
(
index
).
zfill
(
4
))
np
.
savez_compressed
(
save_path
,
pred
=
occ_pred
,
gt
=
occ_gt
,
sample_token
=
sample_token
)
gt_semantics
=
occ_gt
[
'semantics'
]
mask_lidar
=
occ_gt
[
'mask_lidar'
].
astype
(
bool
)
...
...
@@ -254,6 +250,3 @@ class NuSceneOcc(NuScenesDataset):
self
.
occ_eval_metrics
.
count_miou
()
if
self
.
eval_fscore
:
self
.
fscore_eval_metrics
.
count_fscore
()
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/nuscnes_eval.py
View file @
41b18fd8
...
...
@@ -3,74 +3,42 @@ import copy
import
json
import
os
import
time
from
typing
import
Tuple
,
Dict
,
Any
import
torch
import
numpy
as
np
from
typing
import
Any
,
Dict
,
Tuple
import
numpy
as
np
import
tqdm
from
matplotlib
import
pyplot
as
plt
from
nuscenes
import
NuScenes
from
nuscenes.eval.common.config
import
config_factory
from
nuscenes.eval.common.data_classes
import
EvalBoxes
from
nuscenes.eval.detection.data_classes
import
DetectionConfig
from
nuscenes.eval.common.loaders
import
(
add_center_dist
,
filter_eval_boxes
,
load_gt
,
load_prediction
)
from
nuscenes.eval.common.render
import
setup_axis
from
nuscenes.eval.detection.algo
import
accumulate
,
calc_ap
,
calc_tp
from
nuscenes.eval.detection.constants
import
(
DETECTION_NAMES
,
PRETTY_DETECTION_NAMES
,
PRETTY_TP_METRICS
,
TP_METRICS
,
TP_METRICS_UNITS
)
from
nuscenes.eval.detection.data_classes
import
(
DetectionBox
,
DetectionConfig
,
DetectionMetricDataList
,
DetectionMetrics
)
from
nuscenes.eval.detection.evaluate
import
NuScenesEval
from
pyquaternion
import
Quaternion
from
nuscenes
import
NuScenes
from
nuscenes.eval.common.data_classes
import
EvalBoxes
from
nuscenes.eval.detection.data_classes
import
DetectionBox
from
nuscenes.eval.detection.render
import
(
class_pr_curve
,
dist_pr_curve
,
summary_plot
)
from
nuscenes.eval.detection.utils
import
category_to_detection_name
from
nuscenes.eval.tracking.data_classes
import
TrackingBox
from
nuscenes.utils.data_classes
import
Box
from
nuscenes.utils.geometry_utils
import
points_in_box
from
nuscenes.utils.geometry_utils
import
(
BoxVisibility
,
transform_matrix
,
view_points
)
from
nuscenes.utils.splits
import
create_splits_scenes
from
nuscenes.eval.common.loaders
import
load_prediction
,
add_center_dist
,
filter_eval_boxes
import
tqdm
from
nuscenes.utils.geometry_utils
import
view_points
,
box_in_image
,
BoxVisibility
,
transform_matrix
from
torchvision.transforms.functional
import
rotate
import
pycocotools.mask
as
mask_util
# from projects.mmdet3d_plugin.models.utils.visual import save_tensor
from
torchvision.transforms.functional
import
rotate
import
cv2
import
argparse
import
json
import
os
import
random
import
time
from
typing
import
Tuple
,
Dict
,
Any
import
numpy
as
np
from
nuscenes
import
NuScenes
from
nuscenes.eval.common.config
import
config_factory
from
nuscenes.eval.common.data_classes
import
EvalBoxes
from
nuscenes.eval.common.loaders
import
load_prediction
,
load_gt
,
add_center_dist
,
filter_eval_boxes
from
nuscenes.eval.detection.algo
import
accumulate
,
calc_ap
,
calc_tp
from
nuscenes.eval.detection.constants
import
TP_METRICS
from
nuscenes.eval.detection.data_classes
import
DetectionConfig
,
DetectionMetrics
,
DetectionBox
,
\
DetectionMetricDataList
from
nuscenes.eval.detection.render
import
summary_plot
,
class_pr_curve
,
dist_pr_curve
,
visualize_sample
from
nuscenes.eval.common.utils
import
quaternion_yaw
,
Quaternion
from
mmdet3d.core.bbox.iou_calculators
import
BboxOverlaps3D
from
IPython
import
embed
import
json
from
typing
import
Any
import
numpy
as
np
from
matplotlib
import
pyplot
as
plt
from
nuscenes
import
NuScenes
from
nuscenes.eval.common.data_classes
import
EvalBoxes
from
nuscenes.eval.common.render
import
setup_axis
from
nuscenes.eval.common.utils
import
boxes_to_sensor
from
nuscenes.eval.detection.constants
import
TP_METRICS
,
DETECTION_NAMES
,
DETECTION_COLORS
,
TP_METRICS_UNITS
,
\
PRETTY_DETECTION_NAMES
,
PRETTY_TP_METRICS
from
nuscenes.eval.detection.data_classes
import
DetectionMetrics
,
DetectionMetricData
,
DetectionMetricDataList
from
nuscenes.utils.data_classes
import
LidarPointCloud
from
nuscenes.utils.geometry_utils
import
view_points
from
pyquaternion
import
Quaternion
# from projects.mmdet3d_plugin.models.utils.visual import save_tensor
Axis
=
Any
def
class_tp_curve
(
md_list
:
DetectionMetricDataList
,
metrics
:
DetectionMetrics
,
detection_name
:
str
,
...
...
@@ -124,7 +92,7 @@ def class_tp_curve(md_list: DetectionMetricDataList,
label
=
'{}: {:.2f} ({})'
.
format
(
PRETTY_TP_METRICS
[
metric
],
tp
,
TP_METRICS_UNITS
[
metric
])
if
metric
==
'trans_err'
:
label
+=
f
' (
{
md
.
max_recall_ind
}
)'
# add recall
print
(
f
'Recall:
{
detection_name
}
:
{
md
.
max_recall_ind
/
100
}
'
)
print
(
f
'Recall:
{
detection_name
}
:
{
md
.
max_recall_ind
/
100
}
'
)
ax
.
plot
(
recall
,
error
,
label
=
label
)
ax
.
axvline
(
x
=
md
.
max_recall
,
linestyle
=
'-.'
,
color
=
(
0
,
0
,
0
,
0.3
))
ax
.
legend
(
loc
=
'best'
)
...
...
@@ -211,7 +179,7 @@ def center_in_image(box, intrinsic: np.ndarray, imsize: Tuple[int, int], vis_lev
elif
vis_level
==
BoxVisibility
.
NONE
:
return
True
else
:
raise
ValueError
(
"
vis_level: {} not valid
"
.
format
(
vis_level
))
raise
ValueError
(
'
vis_level: {} not valid
'
.
format
(
vis_level
))
def
exist_corners_in_image_but_not_all
(
box
,
intrinsic
:
np
.
ndarray
,
imsize
:
Tuple
[
int
,
int
],
...
...
@@ -259,7 +227,7 @@ def load_gt(nusc: NuScenes, eval_split: str, box_cls, verbose: bool = False):
print
(
'Loading annotations for {} split from nuScenes version: {}'
.
format
(
eval_split
,
nusc
.
version
))
# Read out all sample_tokens in DB.
sample_tokens_all
=
[
s
[
'token'
]
for
s
in
nusc
.
sample
]
assert
len
(
sample_tokens_all
)
>
0
,
"
Error: Database has no samples!
"
assert
len
(
sample_tokens_all
)
>
0
,
'
Error: Database has no samples!
'
# Only keep samples from this split.
splits
=
create_splits_scenes
()
...
...
@@ -354,7 +322,7 @@ def load_gt(nusc: NuScenes, eval_split: str, box_cls, verbose: bool = False):
all_annotations
.
add_boxes
(
sample_token
,
sample_boxes
)
if
verbose
:
print
(
"
Loaded ground truth annotations for {} samples.
"
.
format
(
len
(
all_annotations
.
sample_tokens
)))
print
(
'
Loaded ground truth annotations for {} samples.
'
.
format
(
len
(
all_annotations
.
sample_tokens
)))
return
all_annotations
...
...
@@ -385,8 +353,8 @@ def filter_eval_boxes_by_id(nusc: NuScenes,
eval_boxes
.
boxes
[
sample_token
]
=
filtered_boxes
if
verbose
:
print
(
"
=> Original number of boxes: %d
"
%
total
)
print
(
"
=> After anns based filtering: %d
"
%
anns_filter
)
print
(
'
=> Original number of boxes: %d
'
%
total
)
print
(
'
=> After anns based filtering: %d
'
%
anns_filter
)
return
eval_boxes
...
...
@@ -417,13 +385,13 @@ def filter_eval_boxes_by_visibility(
eval_boxes
.
boxes
[
sample_token
]
=
filtered_boxes
if
verbose
:
print
(
"
=> Original number of boxes: %d
"
%
total
)
print
(
"
=> After visibility based filtering: %d
"
%
anns_filter
)
print
(
'
=> Original number of boxes: %d
'
%
total
)
print
(
'
=> After visibility based filtering: %d
'
%
anns_filter
)
return
eval_boxes
def
filter_by_sample_token
(
ori_eval_boxes
,
valid_sample_tokens
=
[],
verbose
=
False
):
def
filter_by_sample_token
(
ori_eval_boxes
,
valid_sample_tokens
=
[],
verbose
=
False
):
eval_boxes
=
copy
.
deepcopy
(
ori_eval_boxes
)
for
sample_token
in
eval_boxes
.
sample_tokens
:
if
sample_token
not
in
valid_sample_tokens
:
...
...
@@ -498,8 +466,8 @@ def filter_eval_boxes_by_overlap(nusc: NuScenes,
verbose
=
True
if
verbose
:
print
(
"
=> Original number of boxes: %d
"
%
total
)
print
(
"
=> After anns based filtering: %d
"
%
anns_filter
)
print
(
'
=> Original number of boxes: %d
'
%
total
)
print
(
'
=> After anns based filtering: %d
'
%
anns_filter
)
return
eval_boxes
...
...
@@ -620,7 +588,6 @@ class NuScenesEval_custom(NuScenesEval):
self
.
pred_boxes
=
filter_by_sample_token
(
self
.
all_preds
,
valid_tokens
)
self
.
sample_tokens
=
self
.
gt_boxes
.
sample_tokens
def
evaluate
(
self
)
->
Tuple
[
DetectionMetrics
,
DetectionMetricDataList
]:
"""
Performs the actual evaluation.
...
...
@@ -698,7 +665,7 @@ class NuScenesEval_custom(NuScenesEval):
savepath
=
savepath
(
'dist_pr_'
+
str
(
dist_th
)))
if
__name__
==
"
__main__
"
:
if
__name__
==
'
__main__
'
:
# Settings.
parser
=
argparse
.
ArgumentParser
(
description
=
'Evaluate nuScenes detection results.'
,
...
...
@@ -746,6 +713,6 @@ if __name__ == "__main__":
nusc_eval
.
update_gt
(
type_
=
'vis'
,
visibility
=
vis
)
print
(
f
'================
{
vis
}
==============='
)
nusc_eval
.
main
(
plot_examples
=
plot_examples_
,
render_curves
=
render_curves_
)
#for index in range(1, 41):
#
for index in range(1, 41):
# nusc_eval.update_gt(type_='ord', index=index)
#
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/occ_metrics.py
View file @
41b18fd8
import
numpy
as
np
import
os
from
pathlib
import
Path
from
tqdm
import
tqdm
import
pickle
as
pkl
import
argparse
import
time
import
torch
import
sys
,
platform
from
sklearn.neighbors
import
KDTree
from
termcolor
import
colored
from
pathlib
import
Path
from
copy
import
deepcopy
from
functools
import
reduce
np
.
seterr
(
divide
=
'ignore'
,
invalid
=
'ignore'
)
os
.
environ
[
"KMP_DUPLICATE_LIB_OK"
]
=
"TRUE"
def
pcolor
(
string
,
color
,
on_color
=
None
,
attrs
=
None
):
"""
Produces a colored string for printing
Parameters
----------
string : str
String that will be colored
color : str
Color to use
on_color : str
Background color to use
attrs : list of str
Different attributes for the string
Returns
-------
string: str
Colored string
"""
return
colored
(
string
,
color
,
on_color
,
attrs
)
def
getCellCoordinates
(
points
,
voxelSize
):
return
(
points
/
voxelSize
).
astype
(
np
.
int
)
def
getNumUniqueCells
(
cells
):
M
=
cells
.
max
()
+
1
return
np
.
unique
(
cells
[:,
0
]
+
M
*
cells
[:,
1
]
+
M
**
2
*
cells
[:,
2
]).
shape
[
0
]
class
Metric_mIoU
():
def
__init__
(
self
,
save_dir
=
'.'
,
num_classes
=
18
,
use_lidar_mask
=
False
,
use_image_mask
=
False
,
):
self
.
class_names
=
[
'others'
,
'barrier'
,
'bicycle'
,
'bus'
,
'car'
,
'construction_vehicle'
,
'motorcycle'
,
'pedestrian'
,
'traffic_cone'
,
'trailer'
,
'truck'
,
'driveable_surface'
,
'other_flat'
,
'sidewalk'
,
'terrain'
,
'manmade'
,
'vegetation'
,
'free'
]
self
.
save_dir
=
save_dir
self
.
use_lidar_mask
=
use_lidar_mask
self
.
use_image_mask
=
use_image_mask
self
.
num_classes
=
num_classes
self
.
point_cloud_range
=
[
-
40.0
,
-
40.0
,
-
1.0
,
40.0
,
40.0
,
5.4
]
self
.
occupancy_size
=
[
0.4
,
0.4
,
0.4
]
self
.
voxel_size
=
0.4
self
.
occ_xdim
=
int
((
self
.
point_cloud_range
[
3
]
-
self
.
point_cloud_range
[
0
])
/
self
.
occupancy_size
[
0
])
self
.
occ_ydim
=
int
((
self
.
point_cloud_range
[
4
]
-
self
.
point_cloud_range
[
1
])
/
self
.
occupancy_size
[
1
])
self
.
occ_zdim
=
int
((
self
.
point_cloud_range
[
5
]
-
self
.
point_cloud_range
[
2
])
/
self
.
occupancy_size
[
2
])
self
.
voxel_num
=
self
.
occ_xdim
*
self
.
occ_ydim
*
self
.
occ_zdim
self
.
hist
=
np
.
zeros
((
self
.
num_classes
,
self
.
num_classes
))
self
.
cnt
=
0
def
hist_info
(
self
,
n_cl
,
pred
,
gt
):
"""
build confusion matrix
# empty classes:0
non-empty class: 0-16
free voxel class: 17
Args:
n_cl (int): num_classes_occupancy
pred (1-d array): pred_occupancy_label
gt (1-d array): gt_occupancu_label
Returns:
tuple:(hist, correctly number_predicted_labels, num_labelled_sample)
"""
assert
pred
.
shape
==
gt
.
shape
k
=
(
gt
>=
0
)
&
(
gt
<
n_cl
)
# exclude 255
labeled
=
np
.
sum
(
k
)
correct
=
np
.
sum
((
pred
[
k
]
==
gt
[
k
]))
return
(
np
.
bincount
(
n_cl
*
gt
[
k
].
astype
(
int
)
+
pred
[
k
].
astype
(
int
),
minlength
=
n_cl
**
2
).
reshape
(
n_cl
,
n_cl
),
correct
,
labeled
,
)
def
per_class_iu
(
self
,
hist
):
return
np
.
diag
(
hist
)
/
(
hist
.
sum
(
1
)
+
hist
.
sum
(
0
)
-
np
.
diag
(
hist
))
def
compute_mIoU
(
self
,
pred
,
label
,
n_classes
):
hist
=
np
.
zeros
((
n_classes
,
n_classes
))
new_hist
,
correct
,
labeled
=
self
.
hist_info
(
n_classes
,
pred
.
flatten
(),
label
.
flatten
())
hist
+=
new_hist
mIoUs
=
self
.
per_class_iu
(
hist
)
# for ind_class in range(n_classes):
# print(str(round(mIoUs[ind_class] * 100, 2)))
# print('===> mIoU: ' + str(round(np.nanmean(mIoUs) * 100, 2)))
return
round
(
np
.
nanmean
(
mIoUs
)
*
100
,
2
),
hist
def
add_batch
(
self
,
semantics_pred
,
semantics_gt
,
mask_lidar
,
mask_camera
):
self
.
cnt
+=
1
if
self
.
use_image_mask
:
masked_semantics_gt
=
semantics_gt
[
mask_camera
]
masked_semantics_pred
=
semantics_pred
[
mask_camera
]
elif
self
.
use_lidar_mask
:
masked_semantics_gt
=
semantics_gt
[
mask_lidar
]
masked_semantics_pred
=
semantics_pred
[
mask_lidar
]
else
:
masked_semantics_gt
=
semantics_gt
masked_semantics_pred
=
semantics_pred
# # pred = np.random.randint(low=0, high=17, size=masked_semantics.shape)
_
,
_hist
=
self
.
compute_mIoU
(
masked_semantics_pred
,
masked_semantics_gt
,
self
.
num_classes
)
self
.
hist
+=
_hist
def
count_miou
(
self
):
mIoU
=
self
.
per_class_iu
(
self
.
hist
)
# assert cnt == num_samples, 'some samples are not included in the miou calculation'
print
(
f
'===> per class IoU of
{
self
.
cnt
}
samples:'
)
for
ind_class
in
range
(
self
.
num_classes
-
1
):
print
(
f
'===>
{
self
.
class_names
[
ind_class
]
}
- IoU = '
+
str
(
round
(
mIoU
[
ind_class
]
*
100
,
2
)))
print
(
f
'===> mIoU of
{
self
.
cnt
}
samples: '
+
str
(
round
(
np
.
nanmean
(
mIoU
[:
self
.
num_classes
-
1
])
*
100
,
2
)))
# print(f'===> sample-wise averaged mIoU of {cnt} samples: ' + str(round(np.nanmean(mIoU_avg), 2)))
# return mIoU
class
Metric_FScore
():
def
__init__
(
self
,
leaf_size
=
10
,
threshold_acc
=
0.6
,
threshold_complete
=
0.6
,
voxel_size
=
[
0.4
,
0.4
,
0.4
],
range
=
[
-
40
,
-
40
,
-
1
,
40
,
40
,
5.4
],
void
=
[
17
,
255
],
use_lidar_mask
=
False
,
use_image_mask
=
False
,
)
->
None
:
self
.
leaf_size
=
leaf_size
self
.
threshold_acc
=
threshold_acc
self
.
threshold_complete
=
threshold_complete
self
.
voxel_size
=
voxel_size
self
.
range
=
range
self
.
void
=
void
self
.
use_lidar_mask
=
use_lidar_mask
self
.
use_image_mask
=
use_image_mask
self
.
cnt
=
0
self
.
tot_acc
=
0.
self
.
tot_cmpl
=
0.
self
.
tot_f1_mean
=
0.
self
.
eps
=
1e-8
def
voxel2points
(
self
,
voxel
):
# occIdx = torch.where(torch.logical_and(voxel != FREE, voxel != NOT_OBSERVED))
# if isinstance(voxel, np.ndarray): voxel = torch.from_numpy(voxel)
mask
=
np
.
logical_not
(
reduce
(
np
.
logical_or
,
[
voxel
==
self
.
void
[
i
]
for
i
in
range
(
len
(
self
.
void
))]))
occIdx
=
np
.
where
(
mask
)
points
=
np
.
concatenate
((
occIdx
[
0
][:,
None
]
*
self
.
voxel_size
[
0
]
+
self
.
voxel_size
[
0
]
/
2
+
self
.
range
[
0
],
\
occIdx
[
1
][:,
None
]
*
self
.
voxel_size
[
1
]
+
self
.
voxel_size
[
1
]
/
2
+
self
.
range
[
1
],
\
occIdx
[
2
][:,
None
]
*
self
.
voxel_size
[
2
]
+
self
.
voxel_size
[
2
]
/
2
+
self
.
range
[
2
]),
axis
=
1
)
return
points
def
add_batch
(
self
,
semantics_pred
,
semantics_gt
,
mask_lidar
,
mask_camera
):
# for scene_token in tqdm(preds_dict.keys()):
self
.
cnt
+=
1
if
self
.
use_image_mask
:
semantics_gt
[
mask_camera
==
False
]
=
255
semantics_pred
[
mask_camera
==
False
]
=
255
elif
self
.
use_lidar_mask
:
semantics_gt
[
mask_lidar
==
False
]
=
255
semantics_pred
[
mask_lidar
==
False
]
=
255
else
:
pass
ground_truth
=
self
.
voxel2points
(
semantics_gt
)
prediction
=
self
.
voxel2points
(
semantics_pred
)
if
prediction
.
shape
[
0
]
==
0
:
accuracy
=
0
completeness
=
0
fmean
=
0
else
:
prediction_tree
=
KDTree
(
prediction
,
leaf_size
=
self
.
leaf_size
)
ground_truth_tree
=
KDTree
(
ground_truth
,
leaf_size
=
self
.
leaf_size
)
complete_distance
,
_
=
prediction_tree
.
query
(
ground_truth
)
complete_distance
=
complete_distance
.
flatten
()
accuracy_distance
,
_
=
ground_truth_tree
.
query
(
prediction
)
accuracy_distance
=
accuracy_distance
.
flatten
()
# evaluate completeness
complete_mask
=
complete_distance
<
self
.
threshold_complete
completeness
=
complete_mask
.
mean
()
# evalute accuracy
accuracy_mask
=
accuracy_distance
<
self
.
threshold_acc
accuracy
=
accuracy_mask
.
mean
()
fmean
=
2.0
/
(
1
/
(
accuracy
+
self
.
eps
)
+
1
/
(
completeness
+
self
.
eps
))
self
.
tot_acc
+=
accuracy
self
.
tot_cmpl
+=
completeness
self
.
tot_f1_mean
+=
fmean
def
count_fscore
(
self
,):
base_color
,
attrs
=
'red'
,
[
'bold'
,
'dark'
]
print
(
pcolor
(
'
\n
######## F score: {} #######'
.
format
(
self
.
tot_f1_mean
/
self
.
cnt
),
base_color
,
attrs
=
attrs
))
import
os
from
functools
import
reduce
import
numpy
as
np
from
sklearn.neighbors
import
KDTree
from
termcolor
import
colored
np
.
seterr
(
divide
=
'ignore'
,
invalid
=
'ignore'
)
os
.
environ
[
'KMP_DUPLICATE_LIB_OK'
]
=
'TRUE'
def
pcolor
(
string
,
color
,
on_color
=
None
,
attrs
=
None
):
"""
Produces a colored string for printing
Parameters
----------
string : str
String that will be colored
color : str
Color to use
on_color : str
Background color to use
attrs : list of str
Different attributes for the string
Returns
-------
string: str
Colored string
"""
return
colored
(
string
,
color
,
on_color
,
attrs
)
def
getCellCoordinates
(
points
,
voxelSize
):
return
(
points
/
voxelSize
).
astype
(
np
.
int
)
def
getNumUniqueCells
(
cells
):
M
=
cells
.
max
()
+
1
return
np
.
unique
(
cells
[:,
0
]
+
M
*
cells
[:,
1
]
+
M
**
2
*
cells
[:,
2
]).
shape
[
0
]
class
Metric_mIoU
():
def
__init__
(
self
,
save_dir
=
'.'
,
num_classes
=
18
,
use_lidar_mask
=
False
,
use_image_mask
=
False
,
):
self
.
class_names
=
[
'others'
,
'barrier'
,
'bicycle'
,
'bus'
,
'car'
,
'construction_vehicle'
,
'motorcycle'
,
'pedestrian'
,
'traffic_cone'
,
'trailer'
,
'truck'
,
'driveable_surface'
,
'other_flat'
,
'sidewalk'
,
'terrain'
,
'manmade'
,
'vegetation'
,
'free'
]
self
.
save_dir
=
save_dir
self
.
use_lidar_mask
=
use_lidar_mask
self
.
use_image_mask
=
use_image_mask
self
.
num_classes
=
num_classes
self
.
point_cloud_range
=
[
-
40.0
,
-
40.0
,
-
1.0
,
40.0
,
40.0
,
5.4
]
self
.
occupancy_size
=
[
0.4
,
0.4
,
0.4
]
self
.
voxel_size
=
0.4
self
.
occ_xdim
=
int
((
self
.
point_cloud_range
[
3
]
-
self
.
point_cloud_range
[
0
])
/
self
.
occupancy_size
[
0
])
self
.
occ_ydim
=
int
((
self
.
point_cloud_range
[
4
]
-
self
.
point_cloud_range
[
1
])
/
self
.
occupancy_size
[
1
])
self
.
occ_zdim
=
int
((
self
.
point_cloud_range
[
5
]
-
self
.
point_cloud_range
[
2
])
/
self
.
occupancy_size
[
2
])
self
.
voxel_num
=
self
.
occ_xdim
*
self
.
occ_ydim
*
self
.
occ_zdim
self
.
hist
=
np
.
zeros
((
self
.
num_classes
,
self
.
num_classes
))
self
.
cnt
=
0
def
hist_info
(
self
,
n_cl
,
pred
,
gt
):
"""
build confusion matrix
# empty classes:0
non-empty class: 0-16
free voxel class: 17
Args:
n_cl (int): num_classes_occupancy
pred (1-d array): pred_occupancy_label
gt (1-d array): gt_occupancu_label
Returns:
tuple:(hist, correctly number_predicted_labels, num_labelled_sample)
"""
assert
pred
.
shape
==
gt
.
shape
k
=
(
gt
>=
0
)
&
(
gt
<
n_cl
)
# exclude 255
labeled
=
np
.
sum
(
k
)
correct
=
np
.
sum
((
pred
[
k
]
==
gt
[
k
]))
return
(
np
.
bincount
(
n_cl
*
gt
[
k
].
astype
(
int
)
+
pred
[
k
].
astype
(
int
),
minlength
=
n_cl
**
2
).
reshape
(
n_cl
,
n_cl
),
correct
,
labeled
,
)
def
per_class_iu
(
self
,
hist
):
return
np
.
diag
(
hist
)
/
(
hist
.
sum
(
1
)
+
hist
.
sum
(
0
)
-
np
.
diag
(
hist
))
def
compute_mIoU
(
self
,
pred
,
label
,
n_classes
):
hist
=
np
.
zeros
((
n_classes
,
n_classes
))
new_hist
,
correct
,
labeled
=
self
.
hist_info
(
n_classes
,
pred
.
flatten
(),
label
.
flatten
())
hist
+=
new_hist
mIoUs
=
self
.
per_class_iu
(
hist
)
# for ind_class in range(n_classes):
# print(str(round(mIoUs[ind_class] * 100, 2)))
# print('===> mIoU: ' + str(round(np.nanmean(mIoUs) * 100, 2)))
return
round
(
np
.
nanmean
(
mIoUs
)
*
100
,
2
),
hist
def
add_batch
(
self
,
semantics_pred
,
semantics_gt
,
mask_lidar
,
mask_camera
):
self
.
cnt
+=
1
if
self
.
use_image_mask
:
masked_semantics_gt
=
semantics_gt
[
mask_camera
]
masked_semantics_pred
=
semantics_pred
[
mask_camera
]
elif
self
.
use_lidar_mask
:
masked_semantics_gt
=
semantics_gt
[
mask_lidar
]
masked_semantics_pred
=
semantics_pred
[
mask_lidar
]
else
:
masked_semantics_gt
=
semantics_gt
masked_semantics_pred
=
semantics_pred
# # pred = np.random.randint(low=0, high=17, size=masked_semantics.shape)
_
,
_hist
=
self
.
compute_mIoU
(
masked_semantics_pred
,
masked_semantics_gt
,
self
.
num_classes
)
self
.
hist
+=
_hist
def
count_miou
(
self
):
mIoU
=
self
.
per_class_iu
(
self
.
hist
)
# assert cnt == num_samples, 'some samples are not included in the miou calculation'
print
(
f
'===> per class IoU of
{
self
.
cnt
}
samples:'
)
for
ind_class
in
range
(
self
.
num_classes
-
1
):
print
(
f
'===>
{
self
.
class_names
[
ind_class
]
}
- IoU = '
+
str
(
round
(
mIoU
[
ind_class
]
*
100
,
2
)))
print
(
f
'===> mIoU of
{
self
.
cnt
}
samples: '
+
str
(
round
(
np
.
nanmean
(
mIoU
[:
self
.
num_classes
-
1
])
*
100
,
2
)))
# print(f'===> sample-wise averaged mIoU of {cnt} samples: ' + str(round(np.nanmean(mIoU_avg), 2)))
# return mIoU
class
Metric_FScore
():
def
__init__
(
self
,
leaf_size
=
10
,
threshold_acc
=
0.6
,
threshold_complete
=
0.6
,
voxel_size
=
[
0.4
,
0.4
,
0.4
],
range
=
[
-
40
,
-
40
,
-
1
,
40
,
40
,
5.4
],
void
=
[
17
,
255
],
use_lidar_mask
=
False
,
use_image_mask
=
False
,
)
->
None
:
self
.
leaf_size
=
leaf_size
self
.
threshold_acc
=
threshold_acc
self
.
threshold_complete
=
threshold_complete
self
.
voxel_size
=
voxel_size
self
.
range
=
range
self
.
void
=
void
self
.
use_lidar_mask
=
use_lidar_mask
self
.
use_image_mask
=
use_image_mask
self
.
cnt
=
0
self
.
tot_acc
=
0.
self
.
tot_cmpl
=
0.
self
.
tot_f1_mean
=
0.
self
.
eps
=
1e-8
def
voxel2points
(
self
,
voxel
):
# occIdx = torch.where(torch.logical_and(voxel != FREE, voxel != NOT_OBSERVED))
# if isinstance(voxel, np.ndarray): voxel = torch.from_numpy(voxel)
mask
=
np
.
logical_not
(
reduce
(
np
.
logical_or
,
[
voxel
==
self
.
void
[
i
]
for
i
in
range
(
len
(
self
.
void
))]))
occIdx
=
np
.
where
(
mask
)
points
=
np
.
concatenate
((
occIdx
[
0
][:,
None
]
*
self
.
voxel_size
[
0
]
+
self
.
voxel_size
[
0
]
/
2
+
self
.
range
[
0
],
\
occIdx
[
1
][:,
None
]
*
self
.
voxel_size
[
1
]
+
self
.
voxel_size
[
1
]
/
2
+
self
.
range
[
1
],
\
occIdx
[
2
][:,
None
]
*
self
.
voxel_size
[
2
]
+
self
.
voxel_size
[
2
]
/
2
+
self
.
range
[
2
]),
axis
=
1
)
return
points
def
add_batch
(
self
,
semantics_pred
,
semantics_gt
,
mask_lidar
,
mask_camera
):
# for scene_token in tqdm(preds_dict.keys()):
self
.
cnt
+=
1
if
self
.
use_image_mask
:
semantics_gt
[
mask_camera
==
False
]
=
255
semantics_pred
[
mask_camera
==
False
]
=
255
elif
self
.
use_lidar_mask
:
semantics_gt
[
mask_lidar
==
False
]
=
255
semantics_pred
[
mask_lidar
==
False
]
=
255
else
:
pass
ground_truth
=
self
.
voxel2points
(
semantics_gt
)
prediction
=
self
.
voxel2points
(
semantics_pred
)
if
prediction
.
shape
[
0
]
==
0
:
accuracy
=
0
completeness
=
0
fmean
=
0
else
:
prediction_tree
=
KDTree
(
prediction
,
leaf_size
=
self
.
leaf_size
)
ground_truth_tree
=
KDTree
(
ground_truth
,
leaf_size
=
self
.
leaf_size
)
complete_distance
,
_
=
prediction_tree
.
query
(
ground_truth
)
complete_distance
=
complete_distance
.
flatten
()
accuracy_distance
,
_
=
ground_truth_tree
.
query
(
prediction
)
accuracy_distance
=
accuracy_distance
.
flatten
()
# evaluate completeness
complete_mask
=
complete_distance
<
self
.
threshold_complete
completeness
=
complete_mask
.
mean
()
# evalute accuracy
accuracy_mask
=
accuracy_distance
<
self
.
threshold_acc
accuracy
=
accuracy_mask
.
mean
()
fmean
=
2.0
/
(
1
/
(
accuracy
+
self
.
eps
)
+
1
/
(
completeness
+
self
.
eps
))
self
.
tot_acc
+=
accuracy
self
.
tot_cmpl
+=
completeness
self
.
tot_f1_mean
+=
fmean
def
count_fscore
(
self
,
):
base_color
,
attrs
=
'red'
,
[
'bold'
,
'dark'
]
print
(
pcolor
(
'
\n
######## F score: {} #######'
.
format
(
self
.
tot_f1_mean
/
self
.
cnt
),
base_color
,
attrs
=
attrs
))
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/pipelines/__init__.py
View file @
41b18fd8
from
.transform_3d
import
(
PadMultiViewImage
,
NormalizeMultiviewImage
,
PhotoMetricDistortionMultiViewImage
,
CustomCollect3D
,
RandomScaleImageMultiViewImage
)
from
.formating
import
CustomDefaultFormatBundle3D
from
.loading
import
LoadOccGTFromFile
from
.transform_3d
import
(
CustomCollect3D
,
NormalizeMultiviewImage
,
PadMultiViewImage
,
PhotoMetricDistortionMultiViewImage
,
RandomScaleImageMultiViewImage
)
__all__
=
[
'PadMultiViewImage'
,
'NormalizeMultiviewImage'
,
'PhotoMetricDistortionMultiViewImage'
,
'CustomDefaultFormatBundle3D'
,
'CustomCollect3D'
,
'RandomScaleImageMultiViewImage'
]
\ No newline at end of file
'PadMultiViewImage'
,
'NormalizeMultiviewImage'
,
'PhotoMetricDistortionMultiViewImage'
,
'CustomDefaultFormatBundle3D'
,
'CustomCollect3D'
,
'RandomScaleImageMultiViewImage'
]
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/pipelines/formating.py
View file @
41b18fd8
# Copyright (c) OpenMMLab. All rights reserved.
import
numpy
as
np
from
mmcv.parallel
import
DataContainer
as
DC
from
mmdet3d.core.bbox
import
BaseInstance3DBoxes
from
mmdet3d.core.points
import
BasePoints
from
mmdet.datasets.builder
import
PIPELINES
from
mmdet.datasets.pipelines
import
to_tensor
from
mmdet3d.datasets.pipelines
import
DefaultFormatBundle3D
@
PIPELINES
.
register_module
()
class
CustomDefaultFormatBundle3D
(
DefaultFormatBundle3D
):
"""Default formatting bundle.
It simplifies the pipeline of formatting common fields for voxels,
including "proposals", "gt_bboxes", "gt_labels", "gt_masks" and
"gt_semantic_seg".
These fields are formatted as follows.
- img: (1)transpose, (2)to tensor, (3)to DataContainer (stack=True)
- proposals: (1)to tensor, (2)to DataContainer
- gt_bboxes: (1)to tensor, (2)to DataContainer
- gt_bboxes_ignore: (1)to tensor, (2)to DataContainer
- gt_labels: (1)to tensor, (2)to DataContainer
"""
def
__call__
(
self
,
results
):
"""Call function to transform and format common fields in results.
Args:
results (dict): Result dict contains the data to convert.
Returns:
dict: The result dict contains the data that is formatted with
default bundle.
"""
# Format 3D data
results
=
super
(
CustomDefaultFormatBundle3D
,
self
).
__call__
(
results
)
results
[
'gt_map_masks'
]
=
DC
(
to_tensor
(
results
[
'gt_map_masks'
]),
stack
=
True
)
return
results
\ No newline at end of file
# Copyright (c) OpenMMLab. All rights reserved.
from
mmcv.parallel
import
DataContainer
as
DC
from
mmdet3d.datasets.pipelines
import
DefaultFormatBundle3D
from
mmdet.datasets.builder
import
PIPELINES
from
mmdet.datasets.pipelines
import
to_tensor
@
PIPELINES
.
register_module
()
class
CustomDefaultFormatBundle3D
(
DefaultFormatBundle3D
):
"""Default formatting bundle.
It simplifies the pipeline of formatting common fields for voxels,
including "proposals", "gt_bboxes", "gt_labels", "gt_masks" and
"gt_semantic_seg".
These fields are formatted as follows.
- img: (1)transpose, (2)to tensor, (3)to DataContainer (stack=True)
- proposals: (1)to tensor, (2)to DataContainer
- gt_bboxes: (1)to tensor, (2)to DataContainer
- gt_bboxes_ignore: (1)to tensor, (2)to DataContainer
- gt_labels: (1)to tensor, (2)to DataContainer
"""
def
__call__
(
self
,
results
):
"""Call function to transform and format common fields in results.
Args:
results (dict): Result dict contains the data to convert.
Returns:
dict: The result dict contains the data that is formatted with
default bundle.
"""
# Format 3D data
results
=
super
(
CustomDefaultFormatBundle3D
,
self
).
__call__
(
results
)
results
[
'gt_map_masks'
]
=
DC
(
to_tensor
(
results
[
'gt_map_masks'
]),
stack
=
True
)
return
results
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/pipelines/loading.py
View file @
41b18fd8
import
numpy
as
np
from
numpy
import
random
import
mmcv
from
mmdet.datasets.builder
import
PIPELINES
from
mmcv.parallel
import
DataContainer
as
DC
import
os
@
PIPELINES
.
register_module
()
class
LoadOccGTFromFile
(
object
):
"""Load multi channel images from a list of separate channel files.
Expects results['img_filename'] to be a list of filenames.
note that we read image in BGR style to align with opencv.imread
Args:
to_float32 (bool): Whether to convert the img to float32.
Defaults to False.
color_type (str): Color type of the file. Defaults to 'unchanged'.
"""
def
__init__
(
self
,
data_root
,
):
self
.
data_root
=
data_root
def
__call__
(
self
,
results
):
# print(results.keys())
occ_gt_path
=
results
[
'occ_gt_path'
]
occ_gt_path
=
os
.
path
.
join
(
self
.
data_root
,
occ_gt_path
)
occ_labels
=
np
.
load
(
occ_gt_path
)
semantics
=
occ_labels
[
'semantics'
]
mask_lidar
=
occ_labels
[
'mask_lidar'
]
mask_camera
=
occ_labels
[
'mask_camera'
]
results
[
'voxel_semantics'
]
=
semantics
results
[
'mask_lidar'
]
=
mask_lidar
results
[
'mask_camera'
]
=
mask_camera
return
results
def
__repr__
(
self
):
"""str: Return a string that describes the module."""
return
"{} (data_root={}')"
.
format
(
self
.
__class__
.
__name__
,
self
.
data_root
)
\ No newline at end of file
import
os
import
numpy
as
np
from
mmdet.datasets.builder
import
PIPELINES
@
PIPELINES
.
register_module
()
class
LoadOccGTFromFile
(
object
):
"""Load multi channel images from a list of separate channel files.
Expects results['img_filename'] to be a list of filenames.
note that we read image in BGR style to align with opencv.imread
Args:
to_float32 (bool): Whether to convert the img to float32.
Defaults to False.
color_type (str): Color type of the file. Defaults to 'unchanged'.
"""
def
__init__
(
self
,
data_root
,
):
self
.
data_root
=
data_root
def
__call__
(
self
,
results
):
# print(results.keys())
occ_gt_path
=
results
[
'occ_gt_path'
]
occ_gt_path
=
os
.
path
.
join
(
self
.
data_root
,
occ_gt_path
)
occ_labels
=
np
.
load
(
occ_gt_path
)
semantics
=
occ_labels
[
'semantics'
]
mask_lidar
=
occ_labels
[
'mask_lidar'
]
mask_camera
=
occ_labels
[
'mask_camera'
]
results
[
'voxel_semantics'
]
=
semantics
results
[
'mask_lidar'
]
=
mask_lidar
results
[
'mask_camera'
]
=
mask_camera
return
results
def
__repr__
(
self
):
"""str: Return a string that describes the module."""
return
"{} (data_root={}')"
.
format
(
self
.
__class__
.
__name__
,
self
.
data_root
)
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/pipelines/transform_3d.py
View file @
41b18fd8
import
numpy
as
np
from
numpy
import
random
import
mmcv
from
mmdet.datasets.builder
import
PIPELINES
import
numpy
as
np
from
mmcv.parallel
import
DataContainer
as
DC
import
os
from
mmdet.datasets.builder
import
PIPELINES
from
numpy
import
random
@
PIPELINES
.
register_module
()
...
...
@@ -36,7 +33,7 @@ class PadMultiViewImage(object):
elif
self
.
size_divisor
is
not
None
:
padded_img
=
[
mmcv
.
impad_to_multiple
(
img
,
self
.
size_divisor
,
pad_val
=
self
.
pad_val
)
for
img
in
results
[
'img'
]]
results
[
'ori_shape'
]
=
[
img
.
shape
for
img
in
results
[
'img'
]]
results
[
'img'
]
=
padded_img
results
[
'img_shape'
]
=
[
img
.
shape
for
img
in
padded_img
]
...
...
@@ -78,7 +75,6 @@ class NormalizeMultiviewImage(object):
self
.
std
=
np
.
array
(
std
,
dtype
=
np
.
float32
)
self
.
to_rgb
=
to_rgb
def
__call__
(
self
,
results
):
"""Call function to normalize images.
Args:
...
...
@@ -140,12 +136,12 @@ class PhotoMetricDistortionMultiViewImage:
new_imgs
=
[]
for
img
in
imgs
:
assert
img
.
dtype
==
np
.
float32
,
\
'PhotoMetricDistortion needs the input image of dtype np.float32,'
\
'PhotoMetricDistortion needs the input image of dtype np.float32,'
\
' please set "to_float32=True" in "LoadImageFromFile" pipeline'
# random brightness
if
random
.
randint
(
2
):
delta
=
random
.
uniform
(
-
self
.
brightness_delta
,
self
.
brightness_delta
)
self
.
brightness_delta
)
img
+=
delta
# mode == 0 --> do random contrast first
...
...
@@ -154,7 +150,7 @@ class PhotoMetricDistortionMultiViewImage:
if
mode
==
1
:
if
random
.
randint
(
2
):
alpha
=
random
.
uniform
(
self
.
contrast_lower
,
self
.
contrast_upper
)
self
.
contrast_upper
)
img
*=
alpha
# convert color from BGR to HSV
...
...
@@ -163,7 +159,7 @@ class PhotoMetricDistortionMultiViewImage:
# random saturation
if
random
.
randint
(
2
):
img
[...,
1
]
*=
random
.
uniform
(
self
.
saturation_lower
,
self
.
saturation_upper
)
self
.
saturation_upper
)
# random hue
if
random
.
randint
(
2
):
...
...
@@ -178,7 +174,7 @@ class PhotoMetricDistortionMultiViewImage:
if
mode
==
0
:
if
random
.
randint
(
2
):
alpha
=
random
.
uniform
(
self
.
contrast_lower
,
self
.
contrast_upper
)
self
.
contrast_upper
)
img
*=
alpha
# randomly swap channels
...
...
@@ -199,7 +195,6 @@ class PhotoMetricDistortionMultiViewImage:
return
repr_str
@
PIPELINES
.
register_module
()
class
CustomCollect3D
(
object
):
"""Collect data from the loader relevant to the specific task.
...
...
@@ -247,7 +242,7 @@ class CustomCollect3D(object):
def
__init__
(
self
,
keys
,
meta_keys
=
(
'filename'
,
'ori_shape'
,
'img_shape'
,
'lidar2img'
,
'ego2lidar'
,
meta_keys
=
(
'filename'
,
'ori_shape'
,
'img_shape'
,
'lidar2img'
,
'ego2lidar'
,
'depth2img'
,
'cam2img'
,
'pad_shape'
,
'scale_factor'
,
'flip'
,
'pcd_horizontal_flip'
,
'pcd_vertical_flip'
,
'box_mode_3d'
,
'box_type_3d'
,
...
...
@@ -269,10 +264,10 @@ class CustomCollect3D(object):
- keys in ``self.keys``
- ``img_metas``
"""
data
=
{}
img_metas
=
{}
for
key
in
self
.
meta_keys
:
if
key
in
results
:
img_metas
[
key
]
=
results
[
key
]
...
...
@@ -285,8 +280,7 @@ class CustomCollect3D(object):
def
__repr__
(
self
):
"""str: Return a string that describes the module."""
return
self
.
__class__
.
__name__
+
\
f
'(keys=
{
self
.
keys
}
, meta_keys=
{
self
.
meta_keys
}
)'
f
'(keys=
{
self
.
keys
}
, meta_keys=
{
self
.
meta_keys
}
)'
@
PIPELINES
.
register_module
()
...
...
@@ -298,7 +292,7 @@ class RandomScaleImageMultiViewImage(object):
def
__init__
(
self
,
scales
=
[]):
self
.
scales
=
scales
assert
len
(
self
.
scales
)
==
1
assert
len
(
self
.
scales
)
==
1
def
__call__
(
self
,
results
):
"""Call function to pad images, masks, semantic segmentation maps.
...
...
@@ -324,8 +318,7 @@ class RandomScaleImageMultiViewImage(object):
return
results
def
__repr__
(
self
):
repr_str
=
self
.
__class__
.
__name__
repr_str
+=
f
'(size=
{
self
.
scales
}
, '
return
repr_str
\ No newline at end of file
return
repr_str
autonomous_driving/occupancy_prediction/projects/mmdet3d_plugin/datasets/samplers/__init__.py
View file @
41b18fd8
from
.group_sampler
import
DistributedGroupSampler
from
.distributed_sampler
import
DistributedSampler
from
.group_sampler
import
DistributedGroupSampler
from
.sampler
import
SAMPLER
,
build_sampler
Prev
1
2
3
4
5
6
7
8
9
10
…
20
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