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
27a546e9
Commit
27a546e9
authored
Jul 19, 2022
by
ZCMax
Committed by
ChaimZhu
Jul 20, 2022
Browse files
[Refactor] Visualization Refactor
parent
0e17beab
Changes
16
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
981 additions
and
1344 deletions
+981
-1344
configs/_base_/default_runtime.py
configs/_base_/default_runtime.py
+5
-0
demo/mono_det_demo.py
demo/mono_det_demo.py
+36
-12
demo/multi_modality_demo.py
demo/multi_modality_demo.py
+39
-13
demo/pc_seg_demo.py
demo/pc_seg_demo.py
+35
-12
demo/pcd_demo.py
demo/pcd_demo.py
+36
-12
mmdet3d/apis/__init__.py
mmdet3d/apis/__init__.py
+1
-2
mmdet3d/apis/inference.py
mmdet3d/apis/inference.py
+1
-205
mmdet3d/core/__init__.py
mmdet3d/core/__init__.py
+1
-1
mmdet3d/core/visualization/__init__.py
mmdet3d/core/visualization/__init__.py
+11
-0
mmdet3d/core/visualization/local_visualizer.py
mmdet3d/core/visualization/local_visualizer.py
+606
-0
mmdet3d/core/visualization/vis_utils.py
mmdet3d/core/visualization/vis_utils.py
+178
-0
mmdet3d/core/visualizer/__init__.py
mmdet3d/core/visualizer/__init__.py
+0
-5
mmdet3d/core/visualizer/image_vis.py
mmdet3d/core/visualizer/image_vis.py
+0
-206
mmdet3d/core/visualizer/open3d_vis.py
mmdet3d/core/visualizer/open3d_vis.py
+0
-460
mmdet3d/core/visualizer/show_result.py
mmdet3d/core/visualizer/show_result.py
+0
-291
tools/misc/browse_dataset.py
tools/misc/browse_dataset.py
+32
-125
No files found.
configs/_base_/default_runtime.py
View file @
27a546e9
...
@@ -14,6 +14,11 @@ env_cfg = dict(
...
@@ -14,6 +14,11 @@ env_cfg = dict(
dist_cfg
=
dict
(
backend
=
'nccl'
),
dist_cfg
=
dict
(
backend
=
'nccl'
),
)
)
vis_backends
=
[
dict
(
type
=
'LocalVisBackend'
)]
visualizer
=
dict
(
type
=
'Det3DLocalVisualizer'
,
vis_backends
=
vis_backends
,
name
=
'visualizer'
)
log_processor
=
dict
(
type
=
'LogProcessor'
,
window_size
=
50
,
by_epoch
=
True
)
log_level
=
'INFO'
log_level
=
'INFO'
load_from
=
None
load_from
=
None
resume
=
False
resume
=
False
...
...
demo/mono_det_demo.py
View file @
27a546e9
# Copyright (c) OpenMMLab. All rights reserved.
# Copyright (c) OpenMMLab. All rights reserved.
from
argparse
import
ArgumentParser
from
argparse
import
ArgumentParser
from
mmdet3d.apis
import
(
inference_mono_3d_detector
,
init_model
,
import
mmcv
show_result_meshlab
)
from
mmdet3d.apis
import
inference_mono_3d_detector
,
init_model
from
mmdet3d.registry
import
VISUALIZERS
from
mmdet3d.utils
import
register_all_modules
def
main
():
def
parse_args
():
parser
=
ArgumentParser
()
parser
=
ArgumentParser
()
parser
.
add_argument
(
'image'
,
help
=
'image file'
)
parser
.
add_argument
(
'image'
,
help
=
'image file'
)
parser
.
add_argument
(
'ann'
,
help
=
'ann file'
)
parser
.
add_argument
(
'ann'
,
help
=
'ann file'
)
...
@@ -26,21 +29,42 @@ def main():
...
@@ -26,21 +29,42 @@ def main():
action
=
'store_true'
,
action
=
'store_true'
,
help
=
'whether to save online visualization results'
)
help
=
'whether to save online visualization results'
)
args
=
parser
.
parse_args
()
args
=
parser
.
parse_args
()
return
args
def
main
(
args
):
# register all modules in mmdet into the registries
register_all_modules
()
# build the model from a config file and a checkpoint file
# build the model from a config file and a checkpoint file
model
=
init_model
(
args
.
config
,
args
.
checkpoint
,
device
=
args
.
device
)
model
=
init_model
(
args
.
config
,
args
.
checkpoint
,
device
=
args
.
device
)
# init visualizer
visualizer
=
VISUALIZERS
.
build
(
model
.
cfg
.
visualizer
)
visualizer
.
dataset_meta
=
{
'CLASSES'
:
model
.
CLASSES
,
'PALETTE'
:
model
.
PALETTE
}
# test a single image
# test a single image
result
,
data
=
inference_mono_3d_detector
(
model
,
args
.
image
,
args
.
ann
)
result
,
data
=
inference_mono_3d_detector
(
model
,
args
.
image
,
args
.
ann
)
img
=
mmcv
.
imread
(
args
.
img
)
img
=
mmcv
.
imconvert
(
img
,
'bgr'
,
'rgb'
)
data_input
=
dict
(
img
=
img
)
# show the results
# show the results
show_result_meshlab
(
visualizer
.
add_datasample
(
data
,
'result'
,
result
,
data_input
,
args
.
out_dir
,
pred_sample
=
result
,
args
.
score_thr
,
show
=
True
,
show
=
args
.
show
,
wait_time
=
0
,
snapshot
=
args
.
snapshot
,
out_file
=
args
.
out_file
,
task
=
'mono-det'
)
pred_score_thr
=
args
.
score_thr
,
vis_task
=
'multi_modality-det'
)
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
main
()
args
=
parse_args
()
main
(
args
)
demo/multi_modality_demo.py
View file @
27a546e9
# Copyright (c) OpenMMLab. All rights reserved.
# Copyright (c) OpenMMLab. All rights reserved.
from
argparse
import
ArgumentParser
from
argparse
import
ArgumentParser
from
mmdet3d.apis
import
(
inference_multi_modality_detector
,
init_model
,
import
mmcv
show_result_meshlab
)
import
numpy
as
np
from
mmdet3d.apis
import
inference_multi_modality_detector
,
init_model
from
mmdet3d.registry
import
VISUALIZERS
from
mmdet3d.utils
import
register_all_modules
def
main
():
def
parse_args
():
parser
=
ArgumentParser
()
parser
=
ArgumentParser
()
parser
.
add_argument
(
'pcd'
,
help
=
'Point cloud file'
)
parser
.
add_argument
(
'pcd'
,
help
=
'Point cloud file'
)
parser
.
add_argument
(
'image'
,
help
=
'image file'
)
parser
.
add_argument
(
'image'
,
help
=
'image file'
)
...
@@ -27,22 +31,44 @@ def main():
...
@@ -27,22 +31,44 @@ def main():
action
=
'store_true'
,
action
=
'store_true'
,
help
=
'whether to save online visualization results'
)
help
=
'whether to save online visualization results'
)
args
=
parser
.
parse_args
()
args
=
parser
.
parse_args
()
return
args
def
main
(
args
):
# register all modules in mmdet into the registries
register_all_modules
()
# build the model from a config file and a checkpoint file
# build the model from a config file and a checkpoint file
model
=
init_model
(
args
.
config
,
args
.
checkpoint
,
device
=
args
.
device
)
model
=
init_model
(
args
.
config
,
args
.
checkpoint
,
device
=
args
.
device
)
# test a single image
# init visualizer
visualizer
=
VISUALIZERS
.
build
(
model
.
cfg
.
visualizer
)
visualizer
.
dataset_meta
=
{
'CLASSES'
:
model
.
CLASSES
,
'PALETTE'
:
model
.
PALETTE
}
# test a single image and point cloud sample
result
,
data
=
inference_multi_modality_detector
(
model
,
args
.
pcd
,
result
,
data
=
inference_multi_modality_detector
(
model
,
args
.
pcd
,
args
.
image
,
args
.
ann
)
args
.
image
,
args
.
ann
)
points
=
np
.
fromfile
(
args
.
pcd
,
dtype
=
np
.
float32
)
img
=
mmcv
.
imread
(
args
.
img
)
img
=
mmcv
.
imconvert
(
img
,
'bgr'
,
'rgb'
)
data_input
=
dict
(
points
=
points
,
img
=
img
)
# show the results
# show the results
show_result_meshlab
(
visualizer
.
add_datasample
(
data
,
'result'
,
result
,
data_input
,
args
.
out_dir
,
pred_sample
=
result
,
args
.
score_thr
,
show
=
True
,
show
=
args
.
show
,
wait_time
=
0
,
snapshot
=
args
.
snapshot
,
out_file
=
args
.
out_file
,
task
=
'multi_modality-det'
)
pred_score_thr
=
args
.
score_thr
,
vis_task
=
'multi_modality-det'
)
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
main
()
args
=
parse_args
()
main
(
args
)
demo/pc_seg_demo.py
View file @
27a546e9
# Copyright (c) OpenMMLab. All rights reserved.
# Copyright (c) OpenMMLab. All rights reserved.
from
argparse
import
ArgumentParser
from
argparse
import
ArgumentParser
from
mmdet3d.apis
import
inference_segmentor
,
init_model
,
show_result_meshlab
import
numpy
as
np
from
mmdet3d.apis
import
inference_segmentor
,
init_model
from
mmdet3d.registry
import
VISUALIZERS
from
mmdet3d.utils
import
register_all_modules
def
main
():
def
parse_args
():
parser
=
ArgumentParser
()
parser
=
ArgumentParser
()
parser
.
add_argument
(
'pcd'
,
help
=
'Point cloud file'
)
parser
.
add_argument
(
'pcd'
,
help
=
'Point cloud file'
)
parser
.
add_argument
(
'config'
,
help
=
'Config file'
)
parser
.
add_argument
(
'config'
,
help
=
'Config file'
)
...
@@ -22,21 +26,40 @@ def main():
...
@@ -22,21 +26,40 @@ def main():
action
=
'store_true'
,
action
=
'store_true'
,
help
=
'whether to save online visualization results'
)
help
=
'whether to save online visualization results'
)
args
=
parser
.
parse_args
()
args
=
parser
.
parse_args
()
return
args
def
main
(
args
):
# register all modules in mmdet into the registries
register_all_modules
()
# build the model from a config file and a checkpoint file
# build the model from a config file and a checkpoint file
model
=
init_model
(
args
.
config
,
args
.
checkpoint
,
device
=
args
.
device
)
model
=
init_model
(
args
.
config
,
args
.
checkpoint
,
device
=
args
.
device
)
# test a single image
# init visualizer
visualizer
=
VISUALIZERS
.
build
(
model
.
cfg
.
visualizer
)
visualizer
.
dataset_meta
=
{
'CLASSES'
:
model
.
CLASSES
,
'PALETTE'
:
model
.
PALETTE
}
# test a single point cloud sample
result
,
data
=
inference_segmentor
(
model
,
args
.
pcd
)
result
,
data
=
inference_segmentor
(
model
,
args
.
pcd
)
points
=
np
.
fromfile
(
args
.
pcd
,
dtype
=
np
.
float32
)
data_input
=
dict
(
points
=
points
)
# show the results
# show the results
show_result_meshlab
(
visualizer
.
add_datasample
(
data
,
'result'
,
result
,
data_input
,
args
.
out_dir
,
pred_sample
=
result
,
show
=
args
.
show
,
show
=
True
,
snapshot
=
args
.
snapshot
,
wait_time
=
0
,
task
=
'seg'
,
out_file
=
args
.
out_file
,
palette
=
model
.
PALETTE
)
pred_score_thr
=
args
.
score_thr
,
vis_task
=
'seg'
)
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
main
()
args
=
parse_args
()
main
(
args
)
demo/pcd_demo.py
View file @
27a546e9
# Copyright (c) OpenMMLab. All rights reserved.
# Copyright (c) OpenMMLab. All rights reserved.
from
argparse
import
ArgumentParser
from
argparse
import
ArgumentParser
from
mmdet3d.apis
import
inference_detector
,
init_model
,
show_result_meshlab
import
numpy
as
np
from
mmdet3d.apis
import
inference_detector
,
init_model
from
mmdet3d.registry
import
VISUALIZERS
from
mmdet3d.utils
import
register_all_modules
def
main
():
def
parse_args
():
parser
=
ArgumentParser
()
parser
=
ArgumentParser
()
parser
.
add_argument
(
'pcd'
,
help
=
'Point cloud file'
)
parser
.
add_argument
(
'pcd'
,
help
=
'Point cloud file'
)
parser
.
add_argument
(
'config'
,
help
=
'Config file'
)
parser
.
add_argument
(
'config'
,
help
=
'Config file'
)
...
@@ -24,21 +28,41 @@ def main():
...
@@ -24,21 +28,41 @@ def main():
action
=
'store_true'
,
action
=
'store_true'
,
help
=
'whether to save online visualization results'
)
help
=
'whether to save online visualization results'
)
args
=
parser
.
parse_args
()
args
=
parser
.
parse_args
()
return
args
def
main
(
args
):
# register all modules in mmdet into the registries
register_all_modules
()
# TODO: Support inference of point cloud numpy file.
# build the model from a config file and a checkpoint file
# build the model from a config file and a checkpoint file
model
=
init_model
(
args
.
config
,
args
.
checkpoint
,
device
=
args
.
device
)
model
=
init_model
(
args
.
config
,
args
.
checkpoint
,
device
=
args
.
device
)
# test a single image
# init visualizer
visualizer
=
VISUALIZERS
.
build
(
model
.
cfg
.
visualizer
)
visualizer
.
dataset_meta
=
{
'CLASSES'
:
model
.
CLASSES
,
'PALETTE'
:
model
.
palette
}
# test a single point cloud sample
result
,
data
=
inference_detector
(
model
,
args
.
pcd
)
result
,
data
=
inference_detector
(
model
,
args
.
pcd
)
points
=
np
.
fromfile
(
args
.
pcd
,
dtype
=
np
.
float32
)
data_input
=
dict
(
points
=
points
)
# show the results
# show the results
show_result_meshlab
(
visualizer
.
add_datasample
(
data
,
'result'
,
result
,
data_input
,
args
.
out_dir
,
pred_sample
=
result
,
args
.
score_thr
,
show
=
True
,
show
=
args
.
show
,
wait_time
=
0
,
snapshot
=
args
.
snapshot
,
out_file
=
args
.
out_file
,
task
=
'det'
)
pred_score_thr
=
args
.
score_thr
,
vis_task
=
'det'
)
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
main
()
args
=
parse_args
()
main
(
args
)
mmdet3d/apis/__init__.py
View file @
27a546e9
...
@@ -2,13 +2,12 @@
...
@@ -2,13 +2,12 @@
from
.inference
import
(
convert_SyncBN
,
inference_detector
,
from
.inference
import
(
convert_SyncBN
,
inference_detector
,
inference_mono_3d_detector
,
inference_mono_3d_detector
,
inference_multi_modality_detector
,
inference_segmentor
,
inference_multi_modality_detector
,
inference_segmentor
,
init_model
,
show_result_meshlab
)
init_model
)
__all__
=
[
__all__
=
[
'inference_detector'
,
'inference_detector'
,
'init_model'
,
'init_model'
,
'inference_mono_3d_detector'
,
'inference_mono_3d_detector'
,
'show_result_meshlab'
,
'convert_SyncBN'
,
'convert_SyncBN'
,
'inference_multi_modality_detector'
,
'inference_multi_modality_detector'
,
'inference_segmentor'
,
'inference_segmentor'
,
...
...
mmdet3d/apis/inference.py
View file @
27a546e9
...
@@ -9,10 +9,7 @@ import torch
...
@@ -9,10 +9,7 @@ import torch
from
mmcv.parallel
import
collate
,
scatter
from
mmcv.parallel
import
collate
,
scatter
from
mmcv.runner
import
load_checkpoint
from
mmcv.runner
import
load_checkpoint
from
mmdet3d.core
import
(
Box3DMode
,
CameraInstance3DBoxes
,
Coord3DMode
,
from
mmdet3d.core
import
Box3DMode
DepthInstance3DBoxes
,
LiDARInstance3DBoxes
,
show_multi_modality_result
,
show_result
,
show_seg_result
)
from
mmdet3d.core.bbox
import
get_box_type
from
mmdet3d.core.bbox
import
get_box_type
from
mmdet3d.datasets.pipelines
import
Compose
from
mmdet3d.datasets.pipelines
import
Compose
from
mmdet3d.models
import
build_model
from
mmdet3d.models
import
build_model
...
@@ -323,204 +320,3 @@ def inference_segmentor(model, pcd):
...
@@ -323,204 +320,3 @@ def inference_segmentor(model, pcd):
with
torch
.
no_grad
():
with
torch
.
no_grad
():
result
=
model
(
return_loss
=
False
,
rescale
=
True
,
**
data
)
result
=
model
(
return_loss
=
False
,
rescale
=
True
,
**
data
)
return
result
,
data
return
result
,
data
def
show_det_result_meshlab
(
data
,
result
,
out_dir
,
score_thr
=
0.0
,
show
=
False
,
snapshot
=
False
):
"""Show 3D detection result by meshlab."""
points
=
data
[
'points'
][
0
][
0
].
cpu
().
numpy
()
pts_filename
=
data
[
'img_metas'
][
0
][
0
][
'pts_filename'
]
file_name
=
osp
.
split
(
pts_filename
)[
-
1
].
split
(
'.'
)[
0
]
if
'pts_bbox'
in
result
[
0
].
keys
():
pred_bboxes
=
result
[
0
][
'pts_bbox'
][
'boxes_3d'
].
tensor
.
numpy
()
pred_scores
=
result
[
0
][
'pts_bbox'
][
'scores_3d'
].
numpy
()
else
:
pred_bboxes
=
result
[
0
][
'boxes_3d'
].
tensor
.
numpy
()
pred_scores
=
result
[
0
][
'scores_3d'
].
numpy
()
# filter out low score bboxes for visualization
if
score_thr
>
0
:
inds
=
pred_scores
>
score_thr
pred_bboxes
=
pred_bboxes
[
inds
]
# for now we convert points into depth mode
box_mode
=
data
[
'img_metas'
][
0
][
0
][
'box_mode_3d'
]
if
box_mode
!=
Box3DMode
.
DEPTH
:
points
=
Coord3DMode
.
convert
(
points
,
box_mode
,
Coord3DMode
.
DEPTH
)
show_bboxes
=
Box3DMode
.
convert
(
pred_bboxes
,
box_mode
,
Box3DMode
.
DEPTH
)
else
:
show_bboxes
=
deepcopy
(
pred_bboxes
)
show_result
(
points
,
None
,
show_bboxes
,
out_dir
,
file_name
,
show
=
show
,
snapshot
=
snapshot
)
return
file_name
def
show_seg_result_meshlab
(
data
,
result
,
out_dir
,
palette
,
show
=
False
,
snapshot
=
False
):
"""Show 3D segmentation result by meshlab."""
points
=
data
[
'points'
][
0
][
0
].
cpu
().
numpy
()
pts_filename
=
data
[
'img_metas'
][
0
][
0
][
'pts_filename'
]
file_name
=
osp
.
split
(
pts_filename
)[
-
1
].
split
(
'.'
)[
0
]
pred_seg
=
result
[
0
][
'semantic_mask'
].
numpy
()
if
palette
is
None
:
# generate random color map
max_idx
=
pred_seg
.
max
()
palette
=
np
.
random
.
randint
(
0
,
256
,
size
=
(
max_idx
+
1
,
3
))
palette
=
np
.
array
(
palette
).
astype
(
np
.
int
)
show_seg_result
(
points
,
None
,
pred_seg
,
out_dir
,
file_name
,
palette
=
palette
,
show
=
show
,
snapshot
=
snapshot
)
return
file_name
def
show_proj_det_result_meshlab
(
data
,
result
,
out_dir
,
score_thr
=
0.0
,
show
=
False
,
snapshot
=
False
):
"""Show result of projecting 3D bbox to 2D image by meshlab."""
assert
'img'
in
data
.
keys
(),
'image data is not provided for visualization'
img_filename
=
data
[
'img_metas'
][
0
][
0
][
'filename'
]
file_name
=
osp
.
split
(
img_filename
)[
-
1
].
split
(
'.'
)[
0
]
# read from file because img in data_dict has undergone pipeline transform
img
=
mmcv
.
imread
(
img_filename
)
if
'pts_bbox'
in
result
[
0
].
keys
():
result
[
0
]
=
result
[
0
][
'pts_bbox'
]
elif
'img_bbox'
in
result
[
0
].
keys
():
result
[
0
]
=
result
[
0
][
'img_bbox'
]
pred_bboxes
=
result
[
0
][
'boxes_3d'
].
tensor
.
numpy
()
pred_scores
=
result
[
0
][
'scores_3d'
].
numpy
()
# filter out low score bboxes for visualization
if
score_thr
>
0
:
inds
=
pred_scores
>
score_thr
pred_bboxes
=
pred_bboxes
[
inds
]
box_mode
=
data
[
'img_metas'
][
0
][
0
][
'box_mode_3d'
]
if
box_mode
==
Box3DMode
.
LIDAR
:
if
'lidar2img'
not
in
data
[
'img_metas'
][
0
][
0
]:
raise
NotImplementedError
(
'LiDAR to image transformation matrix is not provided'
)
show_bboxes
=
LiDARInstance3DBoxes
(
pred_bboxes
,
origin
=
(
0.5
,
0.5
,
0
))
show_multi_modality_result
(
img
,
None
,
show_bboxes
,
data
[
'img_metas'
][
0
][
0
][
'lidar2img'
],
out_dir
,
file_name
,
box_mode
=
'lidar'
,
show
=
show
)
elif
box_mode
==
Box3DMode
.
DEPTH
:
show_bboxes
=
DepthInstance3DBoxes
(
pred_bboxes
,
origin
=
(
0.5
,
0.5
,
0
))
show_multi_modality_result
(
img
,
None
,
show_bboxes
,
None
,
out_dir
,
file_name
,
box_mode
=
'depth'
,
img_metas
=
data
[
'img_metas'
][
0
][
0
],
show
=
show
)
elif
box_mode
==
Box3DMode
.
CAM
:
if
'cam2img'
not
in
data
[
'img_metas'
][
0
][
0
]:
raise
NotImplementedError
(
'camera intrinsic matrix is not provided'
)
show_bboxes
=
CameraInstance3DBoxes
(
pred_bboxes
,
box_dim
=
pred_bboxes
.
shape
[
-
1
],
origin
=
(
0.5
,
1.0
,
0.5
))
show_multi_modality_result
(
img
,
None
,
show_bboxes
,
data
[
'img_metas'
][
0
][
0
][
'cam2img'
],
out_dir
,
file_name
,
box_mode
=
'camera'
,
show
=
show
)
else
:
raise
NotImplementedError
(
f
'visualization of
{
box_mode
}
bbox is not supported'
)
return
file_name
def
show_result_meshlab
(
data
,
result
,
out_dir
,
score_thr
=
0.0
,
show
=
False
,
snapshot
=
False
,
task
=
'det'
,
palette
=
None
):
"""Show result by meshlab.
Args:
data (dict): Contain data from pipeline.
result (dict): Predicted result from model.
out_dir (str): Directory to save visualized result.
score_thr (float, optional): Minimum score of bboxes to be shown.
Default: 0.0
show (bool, optional): Visualize the results online. Defaults to False.
snapshot (bool, optional): Whether to save the online results.
Defaults to False.
task (str, optional): Distinguish which task result to visualize.
Currently we support 3D detection, multi-modality detection and
3D segmentation. Defaults to 'det'.
palette (list[list[int]]] | np.ndarray, optional): The palette
of segmentation map. If None is given, random palette will be
generated. Defaults to None.
"""
assert
task
in
[
'det'
,
'multi_modality-det'
,
'seg'
,
'mono-det'
],
\
f
'unsupported visualization task
{
task
}
'
assert
out_dir
is
not
None
,
'Expect out_dir, got none.'
if
task
in
[
'det'
,
'multi_modality-det'
]:
file_name
=
show_det_result_meshlab
(
data
,
result
,
out_dir
,
score_thr
,
show
,
snapshot
)
if
task
in
[
'seg'
]:
file_name
=
show_seg_result_meshlab
(
data
,
result
,
out_dir
,
palette
,
show
,
snapshot
)
if
task
in
[
'multi_modality-det'
,
'mono-det'
]:
file_name
=
show_proj_det_result_meshlab
(
data
,
result
,
out_dir
,
score_thr
,
show
,
snapshot
)
return
out_dir
,
file_name
mmdet3d/core/__init__.py
View file @
27a546e9
...
@@ -6,5 +6,5 @@ from .evaluation import * # noqa: F401, F403
...
@@ -6,5 +6,5 @@ from .evaluation import * # noqa: F401, F403
from
.points
import
*
# noqa: F401, F403
from
.points
import
*
# noqa: F401, F403
from
.post_processing
import
*
# noqa: F401, F403
from
.post_processing
import
*
# noqa: F401, F403
from
.utils
import
*
# noqa: F401, F403
from
.utils
import
*
# noqa: F401, F403
from
.visualiz
er
import
*
# noqa: F401, F403
from
.visualiz
ation
import
*
# noqa: F401, F403
from
.voxel
import
*
# noqa: F401, F403
from
.voxel
import
*
# noqa: F401, F403
mmdet3d/core/visualization/__init__.py
0 → 100644
View file @
27a546e9
# Copyright (c) OpenMMLab. All rights reserved.
from
.local_visualizer
import
Det3DLocalVisualizer
from
.vis_utils
import
(
proj_camera_bbox3d_to_img
,
proj_depth_bbox3d_to_img
,
proj_lidar_bbox3d_to_img
,
write_obj
,
write_oriented_bbox
)
__all__
=
[
'Det3DLocalVisualizer'
,
'proj_depth_bbox3d_to_img'
,
'proj_camera_bbox3d_to_img'
,
'proj_lidar_bbox3d_to_img'
,
'write_oriented_bbox'
,
'write_obj'
]
mmdet3d/core/visualization/local_visualizer.py
0 → 100644
View file @
27a546e9
This diff is collapsed.
Click to expand it.
mmdet3d/core/visualization/vis_utils.py
0 → 100644
View file @
27a546e9
# Copyright (c) OpenMMLab. All rights reserved.
import
copy
import
numpy
as
np
import
torch
import
trimesh
from
mmdet3d.core.bbox
import
Box3DMode
,
Coord3DMode
from
mmdet3d.core.bbox.structures.cam_box3d
import
CameraInstance3DBoxes
from
mmdet3d.core.bbox.structures.depth_box3d
import
DepthInstance3DBoxes
from
mmdet3d.core.bbox.structures.lidar_box3d
import
LiDARInstance3DBoxes
def
write_obj
(
points
,
out_filename
):
"""Write points into ``obj`` format for meshlab visualization.
Args:
points (np.ndarray): Points in shape (N, dim).
out_filename (str): Filename to be saved.
"""
N
=
points
.
shape
[
0
]
fout
=
open
(
out_filename
,
'w'
)
for
i
in
range
(
N
):
if
points
.
shape
[
1
]
==
6
:
c
=
points
[
i
,
3
:].
astype
(
int
)
fout
.
write
(
'v %f %f %f %d %d %d
\n
'
%
(
points
[
i
,
0
],
points
[
i
,
1
],
points
[
i
,
2
],
c
[
0
],
c
[
1
],
c
[
2
]))
else
:
fout
.
write
(
'v %f %f %f
\n
'
%
(
points
[
i
,
0
],
points
[
i
,
1
],
points
[
i
,
2
]))
fout
.
close
()
def
write_oriented_bbox
(
scene_bbox
,
out_filename
):
"""Export oriented (around Z axis) scene bbox to meshes.
Args:
scene_bbox(list[ndarray] or ndarray): xyz pos of center and
3 lengths (x_size, y_size, z_size) and heading angle around Z axis.
Y forward, X right, Z upward. heading angle of positive X is 0,
heading angle of positive Y is 90 degrees.
out_filename(str): Filename.
"""
def
heading2rotmat
(
heading_angle
):
rotmat
=
np
.
zeros
((
3
,
3
))
rotmat
[
2
,
2
]
=
1
cosval
=
np
.
cos
(
heading_angle
)
sinval
=
np
.
sin
(
heading_angle
)
rotmat
[
0
:
2
,
0
:
2
]
=
np
.
array
([[
cosval
,
-
sinval
],
[
sinval
,
cosval
]])
return
rotmat
def
convert_oriented_box_to_trimesh_fmt
(
box
):
ctr
=
box
[:
3
]
lengths
=
box
[
3
:
6
]
trns
=
np
.
eye
(
4
)
trns
[
0
:
3
,
3
]
=
ctr
trns
[
3
,
3
]
=
1.0
trns
[
0
:
3
,
0
:
3
]
=
heading2rotmat
(
box
[
6
])
box_trimesh_fmt
=
trimesh
.
creation
.
box
(
lengths
,
trns
)
return
box_trimesh_fmt
if
len
(
scene_bbox
)
==
0
:
scene_bbox
=
np
.
zeros
((
1
,
7
))
scene
=
trimesh
.
scene
.
Scene
()
for
box
in
scene_bbox
:
scene
.
add_geometry
(
convert_oriented_box_to_trimesh_fmt
(
box
))
mesh_list
=
trimesh
.
util
.
concatenate
(
scene
.
dump
())
# save to obj file
trimesh
.
io
.
export
.
export_mesh
(
mesh_list
,
out_filename
,
file_type
=
'obj'
)
return
def
to_depth_mode
(
points
,
bboxes
):
"""Convert points and bboxes to Depth Coord and Depth Box mode."""
if
points
is
not
None
:
points
=
Coord3DMode
.
convert_point
(
points
.
copy
(),
Coord3DMode
.
LIDAR
,
Coord3DMode
.
DEPTH
)
if
bboxes
is
not
None
:
bboxes
=
Box3DMode
.
convert
(
bboxes
.
clone
(),
Box3DMode
.
LIDAR
,
Box3DMode
.
DEPTH
)
return
points
,
bboxes
# TODO: refactor lidar2img to img_meta
def
proj_lidar_bbox3d_to_img
(
bboxes_3d
:
LiDARInstance3DBoxes
,
input_meta
:
dict
)
->
np
.
array
:
"""Project the 3D bbox on 2D plane.
Args:
bboxes_3d (:obj:`LiDARInstance3DBoxes`):
3d bbox in lidar coordinate system to visualize.
lidar2img (numpy.array, shape=[4, 4]): The projection matrix
according to the camera intrinsic parameters.
"""
corners_3d
=
bboxes_3d
.
corners
num_bbox
=
corners_3d
.
shape
[
0
]
pts_4d
=
np
.
concatenate
(
[
corners_3d
.
reshape
(
-
1
,
3
),
np
.
ones
((
num_bbox
*
8
,
1
))],
axis
=-
1
)
lidar2img
=
copy
.
deepcopy
(
input_meta
[
'lidar2img'
]).
reshape
(
4
,
4
)
if
isinstance
(
lidar2img
,
torch
.
Tensor
):
lidar2img
=
lidar2img
.
cpu
().
numpy
()
pts_2d
=
pts_4d
@
lidar2img
.
T
pts_2d
[:,
2
]
=
np
.
clip
(
pts_2d
[:,
2
],
a_min
=
1e-5
,
a_max
=
1e5
)
pts_2d
[:,
0
]
/=
pts_2d
[:,
2
]
pts_2d
[:,
1
]
/=
pts_2d
[:,
2
]
imgfov_pts_2d
=
pts_2d
[...,
:
2
].
reshape
(
num_bbox
,
8
,
2
)
return
imgfov_pts_2d
# TODO: remove third parameter in all functions here in favour of img_metas
def
proj_depth_bbox3d_to_img
(
bboxes_3d
:
DepthInstance3DBoxes
,
input_meta
:
dict
)
->
np
.
array
:
"""Project the 3D bbox on 2D plane and draw on input image.
Args:
bboxes_3d (:obj:`DepthInstance3DBoxes`, shape=[M, 7]):
3d bbox in depth coordinate system to visualize.
input_meta (dict): Used in coordinates transformation.
"""
from
mmdet3d.core.bbox
import
points_cam2img
from
mmdet3d.models
import
apply_3d_transformation
input_meta
=
copy
.
deepcopy
(
input_meta
)
corners_3d
=
bboxes_3d
.
corners
num_bbox
=
corners_3d
.
shape
[
0
]
points_3d
=
corners_3d
.
reshape
(
-
1
,
3
)
# first reverse the data transformations
xyz_depth
=
apply_3d_transformation
(
points_3d
,
'DEPTH'
,
input_meta
,
reverse
=
True
)
# project to 2d to get image coords (uv)
uv_origin
=
points_cam2img
(
xyz_depth
,
xyz_depth
.
new_tensor
(
input_meta
[
'depth2img'
]))
uv_origin
=
(
uv_origin
-
1
).
round
()
imgfov_pts_2d
=
uv_origin
[...,
:
2
].
reshape
(
num_bbox
,
8
,
2
).
numpy
()
return
imgfov_pts_2d
# project the camera bboxes 3d to image
def
proj_camera_bbox3d_to_img
(
bboxes_3d
:
CameraInstance3DBoxes
,
input_meta
:
dict
)
->
np
.
array
:
"""Project the 3D bbox on 2D plane and draw on input image.
Args:
bboxes_3d (:obj:`CameraInstance3DBoxes`, shape=[M, 7]):
3d bbox in camera coordinate system to visualize.
cam2img (np.array)): Camera intrinsic matrix,
denoted as `K` in depth bbox coordinate system.
"""
from
mmdet3d.core.bbox
import
points_cam2img
cam2img
=
copy
.
deepcopy
(
input_meta
[
'cam2img'
])
corners_3d
=
bboxes_3d
.
corners
num_bbox
=
corners_3d
.
shape
[
0
]
points_3d
=
corners_3d
.
reshape
(
-
1
,
3
)
if
not
isinstance
(
cam2img
,
torch
.
Tensor
):
cam2img
=
torch
.
from_numpy
(
np
.
array
(
cam2img
))
assert
(
cam2img
.
shape
==
torch
.
Size
([
3
,
3
])
or
cam2img
.
shape
==
torch
.
Size
([
4
,
4
]))
cam2img
=
cam2img
.
float
().
cpu
()
# project to 2d to get image coords (uv)
uv_origin
=
points_cam2img
(
points_3d
,
cam2img
)
uv_origin
=
(
uv_origin
-
1
).
round
()
imgfov_pts_2d
=
uv_origin
[...,
:
2
].
reshape
(
num_bbox
,
8
,
2
).
numpy
()
return
imgfov_pts_2d
mmdet3d/core/visualizer/__init__.py
deleted
100644 → 0
View file @
0e17beab
# Copyright (c) OpenMMLab. All rights reserved.
from
.show_result
import
(
show_multi_modality_result
,
show_result
,
show_seg_result
)
__all__
=
[
'show_result'
,
'show_seg_result'
,
'show_multi_modality_result'
]
mmdet3d/core/visualizer/image_vis.py
deleted
100644 → 0
View file @
0e17beab
# Copyright (c) OpenMMLab. All rights reserved.
import
copy
import
cv2
import
numpy
as
np
import
torch
from
matplotlib
import
pyplot
as
plt
def
project_pts_on_img
(
points
,
raw_img
,
lidar2img_rt
,
max_distance
=
70
,
thickness
=-
1
):
"""Project the 3D points cloud on 2D image.
Args:
points (numpy.array): 3D points cloud (x, y, z) to visualize.
raw_img (numpy.array): The numpy array of image.
lidar2img_rt (numpy.array, shape=[4, 4]): The projection matrix
according to the camera intrinsic parameters.
max_distance (float, optional): the max distance of the points cloud.
Default: 70.
thickness (int, optional): The thickness of 2D points. Default: -1.
"""
img
=
raw_img
.
copy
()
num_points
=
points
.
shape
[
0
]
pts_4d
=
np
.
concatenate
([
points
[:,
:
3
],
np
.
ones
((
num_points
,
1
))],
axis
=-
1
)
pts_2d
=
pts_4d
@
lidar2img_rt
.
T
# cam_points is Tensor of Nx4 whose last column is 1
# transform camera coordinate to image coordinate
pts_2d
[:,
2
]
=
np
.
clip
(
pts_2d
[:,
2
],
a_min
=
1e-5
,
a_max
=
99999
)
pts_2d
[:,
0
]
/=
pts_2d
[:,
2
]
pts_2d
[:,
1
]
/=
pts_2d
[:,
2
]
fov_inds
=
((
pts_2d
[:,
0
]
<
img
.
shape
[
1
])
&
(
pts_2d
[:,
0
]
>=
0
)
&
(
pts_2d
[:,
1
]
<
img
.
shape
[
0
])
&
(
pts_2d
[:,
1
]
>=
0
))
imgfov_pts_2d
=
pts_2d
[
fov_inds
,
:
3
]
# u, v, d
cmap
=
plt
.
cm
.
get_cmap
(
'hsv'
,
256
)
cmap
=
np
.
array
([
cmap
(
i
)
for
i
in
range
(
256
)])[:,
:
3
]
*
255
for
i
in
range
(
imgfov_pts_2d
.
shape
[
0
]):
depth
=
imgfov_pts_2d
[
i
,
2
]
color
=
cmap
[
np
.
clip
(
int
(
max_distance
*
10
/
depth
),
0
,
255
),
:]
cv2
.
circle
(
img
,
center
=
(
int
(
np
.
round
(
imgfov_pts_2d
[
i
,
0
])),
int
(
np
.
round
(
imgfov_pts_2d
[
i
,
1
]))),
radius
=
1
,
color
=
tuple
(
color
),
thickness
=
thickness
,
)
cv2
.
imshow
(
'project_pts_img'
,
img
.
astype
(
np
.
uint8
))
cv2
.
waitKey
(
100
)
def
plot_rect3d_on_img
(
img
,
num_rects
,
rect_corners
,
color
=
(
0
,
255
,
0
),
thickness
=
1
):
"""Plot the boundary lines of 3D rectangular on 2D images.
Args:
img (numpy.array): The numpy array of image.
num_rects (int): Number of 3D rectangulars.
rect_corners (numpy.array): Coordinates of the corners of 3D
rectangulars. Should be in the shape of [num_rect, 8, 2].
color (tuple[int], optional): The color to draw bboxes.
Default: (0, 255, 0).
thickness (int, optional): The thickness of bboxes. Default: 1.
"""
line_indices
=
((
0
,
1
),
(
0
,
3
),
(
0
,
4
),
(
1
,
2
),
(
1
,
5
),
(
3
,
2
),
(
3
,
7
),
(
4
,
5
),
(
4
,
7
),
(
2
,
6
),
(
5
,
6
),
(
6
,
7
))
for
i
in
range
(
num_rects
):
corners
=
rect_corners
[
i
].
astype
(
np
.
int
)
for
start
,
end
in
line_indices
:
cv2
.
line
(
img
,
(
corners
[
start
,
0
],
corners
[
start
,
1
]),
(
corners
[
end
,
0
],
corners
[
end
,
1
]),
color
,
thickness
,
cv2
.
LINE_AA
)
return
img
.
astype
(
np
.
uint8
)
def
draw_lidar_bbox3d_on_img
(
bboxes3d
,
raw_img
,
lidar2img_rt
,
img_metas
,
color
=
(
0
,
255
,
0
),
thickness
=
1
):
"""Project the 3D bbox on 2D plane and draw on input image.
Args:
bboxes3d (:obj:`LiDARInstance3DBoxes`):
3d bbox in lidar coordinate system to visualize.
raw_img (numpy.array): The numpy array of image.
lidar2img_rt (numpy.array, shape=[4, 4]): The projection matrix
according to the camera intrinsic parameters.
img_metas (dict): Useless here.
color (tuple[int], optional): The color to draw bboxes.
Default: (0, 255, 0).
thickness (int, optional): The thickness of bboxes. Default: 1.
"""
img
=
raw_img
.
copy
()
corners_3d
=
bboxes3d
.
corners
num_bbox
=
corners_3d
.
shape
[
0
]
pts_4d
=
np
.
concatenate
(
[
corners_3d
.
reshape
(
-
1
,
3
),
np
.
ones
((
num_bbox
*
8
,
1
))],
axis
=-
1
)
lidar2img_rt
=
copy
.
deepcopy
(
lidar2img_rt
).
reshape
(
4
,
4
)
if
isinstance
(
lidar2img_rt
,
torch
.
Tensor
):
lidar2img_rt
=
lidar2img_rt
.
cpu
().
numpy
()
pts_2d
=
pts_4d
@
lidar2img_rt
.
T
pts_2d
[:,
2
]
=
np
.
clip
(
pts_2d
[:,
2
],
a_min
=
1e-5
,
a_max
=
1e5
)
pts_2d
[:,
0
]
/=
pts_2d
[:,
2
]
pts_2d
[:,
1
]
/=
pts_2d
[:,
2
]
imgfov_pts_2d
=
pts_2d
[...,
:
2
].
reshape
(
num_bbox
,
8
,
2
)
return
plot_rect3d_on_img
(
img
,
num_bbox
,
imgfov_pts_2d
,
color
,
thickness
)
# TODO: remove third parameter in all functions here in favour of img_metas
def
draw_depth_bbox3d_on_img
(
bboxes3d
,
raw_img
,
calibs
,
img_metas
,
color
=
(
0
,
255
,
0
),
thickness
=
1
):
"""Project the 3D bbox on 2D plane and draw on input image.
Args:
bboxes3d (:obj:`DepthInstance3DBoxes`, shape=[M, 7]):
3d bbox in depth coordinate system to visualize.
raw_img (numpy.array): The numpy array of image.
calibs (dict): Camera calibration information, Rt and K.
img_metas (dict): Used in coordinates transformation.
color (tuple[int], optional): The color to draw bboxes.
Default: (0, 255, 0).
thickness (int, optional): The thickness of bboxes. Default: 1.
"""
from
mmdet3d.core.bbox
import
points_cam2img
from
mmdet3d.models
import
apply_3d_transformation
img
=
raw_img
.
copy
()
img_metas
=
copy
.
deepcopy
(
img_metas
)
corners_3d
=
bboxes3d
.
corners
num_bbox
=
corners_3d
.
shape
[
0
]
points_3d
=
corners_3d
.
reshape
(
-
1
,
3
)
# first reverse the data transformations
xyz_depth
=
apply_3d_transformation
(
points_3d
,
'DEPTH'
,
img_metas
,
reverse
=
True
)
# project to 2d to get image coords (uv)
uv_origin
=
points_cam2img
(
xyz_depth
,
xyz_depth
.
new_tensor
(
img_metas
[
'depth2img'
]))
uv_origin
=
(
uv_origin
-
1
).
round
()
imgfov_pts_2d
=
uv_origin
[...,
:
2
].
reshape
(
num_bbox
,
8
,
2
).
numpy
()
return
plot_rect3d_on_img
(
img
,
num_bbox
,
imgfov_pts_2d
,
color
,
thickness
)
def
draw_camera_bbox3d_on_img
(
bboxes3d
,
raw_img
,
cam2img
,
img_metas
,
color
=
(
0
,
255
,
0
),
thickness
=
1
):
"""Project the 3D bbox on 2D plane and draw on input image.
Args:
bboxes3d (:obj:`CameraInstance3DBoxes`, shape=[M, 7]):
3d bbox in camera coordinate system to visualize.
raw_img (numpy.array): The numpy array of image.
cam2img (dict): Camera intrinsic matrix,
denoted as `K` in depth bbox coordinate system.
img_metas (dict): Useless here.
color (tuple[int], optional): The color to draw bboxes.
Default: (0, 255, 0).
thickness (int, optional): The thickness of bboxes. Default: 1.
"""
from
mmdet3d.core.bbox
import
points_cam2img
img
=
raw_img
.
copy
()
cam2img
=
copy
.
deepcopy
(
cam2img
)
corners_3d
=
bboxes3d
.
corners
num_bbox
=
corners_3d
.
shape
[
0
]
points_3d
=
corners_3d
.
reshape
(
-
1
,
3
)
if
not
isinstance
(
cam2img
,
torch
.
Tensor
):
cam2img
=
torch
.
from_numpy
(
np
.
array
(
cam2img
))
assert
(
cam2img
.
shape
==
torch
.
Size
([
3
,
3
])
or
cam2img
.
shape
==
torch
.
Size
([
4
,
4
]))
cam2img
=
cam2img
.
float
().
cpu
()
# project to 2d to get image coords (uv)
uv_origin
=
points_cam2img
(
points_3d
,
cam2img
)
uv_origin
=
(
uv_origin
-
1
).
round
()
imgfov_pts_2d
=
uv_origin
[...,
:
2
].
reshape
(
num_bbox
,
8
,
2
).
numpy
()
return
plot_rect3d_on_img
(
img
,
num_bbox
,
imgfov_pts_2d
,
color
,
thickness
)
mmdet3d/core/visualizer/open3d_vis.py
deleted
100644 → 0
View file @
0e17beab
# Copyright (c) OpenMMLab. All rights reserved.
import
copy
import
numpy
as
np
import
torch
try
:
import
open3d
as
o3d
from
open3d
import
geometry
except
ImportError
:
raise
ImportError
(
'Please run "pip install open3d" to install open3d first.'
)
def
_draw_points
(
points
,
vis
,
points_size
=
2
,
point_color
=
(
0.5
,
0.5
,
0.5
),
mode
=
'xyz'
):
"""Draw points on visualizer.
Args:
points (numpy.array | torch.tensor, shape=[N, 3+C]):
points to visualize.
vis (:obj:`open3d.visualization.Visualizer`): open3d visualizer.
points_size (int, optional): the size of points to show on visualizer.
Default: 2.
point_color (tuple[float], optional): the color of points.
Default: (0.5, 0.5, 0.5).
mode (str, optional): indicate type of the input points,
available mode ['xyz', 'xyzrgb']. Default: 'xyz'.
Returns:
tuple: points, color of each point.
"""
vis
.
get_render_option
().
point_size
=
points_size
# set points size
if
isinstance
(
points
,
torch
.
Tensor
):
points
=
points
.
cpu
().
numpy
()
points
=
points
.
copy
()
pcd
=
geometry
.
PointCloud
()
if
mode
==
'xyz'
:
pcd
.
points
=
o3d
.
utility
.
Vector3dVector
(
points
[:,
:
3
])
points_colors
=
np
.
tile
(
np
.
array
(
point_color
),
(
points
.
shape
[
0
],
1
))
elif
mode
==
'xyzrgb'
:
pcd
.
points
=
o3d
.
utility
.
Vector3dVector
(
points
[:,
:
3
])
points_colors
=
points
[:,
3
:
6
]
# normalize to [0, 1] for open3d drawing
if
not
((
points_colors
>=
0.0
)
&
(
points_colors
<=
1.0
)).
all
():
points_colors
/=
255.0
else
:
raise
NotImplementedError
pcd
.
colors
=
o3d
.
utility
.
Vector3dVector
(
points_colors
)
vis
.
add_geometry
(
pcd
)
return
pcd
,
points_colors
def
_draw_bboxes
(
bbox3d
,
vis
,
points_colors
,
pcd
=
None
,
bbox_color
=
(
0
,
1
,
0
),
points_in_box_color
=
(
1
,
0
,
0
),
rot_axis
=
2
,
center_mode
=
'lidar_bottom'
,
mode
=
'xyz'
):
"""Draw bbox on visualizer and change the color of points inside bbox3d.
Args:
bbox3d (numpy.array | torch.tensor, shape=[M, 7]):
3d bbox (x, y, z, x_size, y_size, z_size, yaw) to visualize.
vis (:obj:`open3d.visualization.Visualizer`): open3d visualizer.
points_colors (numpy.array): color of each points.
pcd (:obj:`open3d.geometry.PointCloud`, optional): point cloud.
Default: None.
bbox_color (tuple[float], optional): the color of bbox.
Default: (0, 1, 0).
points_in_box_color (tuple[float], optional):
the color of points inside bbox3d. Default: (1, 0, 0).
rot_axis (int, optional): rotation axis of bbox. Default: 2.
center_mode (bool, optional): indicate the center of bbox is
bottom center or gravity center. available mode
['lidar_bottom', 'camera_bottom']. Default: 'lidar_bottom'.
mode (str, optional): indicate type of the input points,
available mode ['xyz', 'xyzrgb']. Default: 'xyz'.
"""
if
isinstance
(
bbox3d
,
torch
.
Tensor
):
bbox3d
=
bbox3d
.
cpu
().
numpy
()
bbox3d
=
bbox3d
.
copy
()
in_box_color
=
np
.
array
(
points_in_box_color
)
for
i
in
range
(
len
(
bbox3d
)):
center
=
bbox3d
[
i
,
0
:
3
]
dim
=
bbox3d
[
i
,
3
:
6
]
yaw
=
np
.
zeros
(
3
)
yaw
[
rot_axis
]
=
bbox3d
[
i
,
6
]
rot_mat
=
geometry
.
get_rotation_matrix_from_xyz
(
yaw
)
if
center_mode
==
'lidar_bottom'
:
center
[
rot_axis
]
+=
dim
[
rot_axis
]
/
2
# bottom center to gravity center
elif
center_mode
==
'camera_bottom'
:
center
[
rot_axis
]
-=
dim
[
rot_axis
]
/
2
# bottom center to gravity center
box3d
=
geometry
.
OrientedBoundingBox
(
center
,
rot_mat
,
dim
)
line_set
=
geometry
.
LineSet
.
create_from_oriented_bounding_box
(
box3d
)
line_set
.
paint_uniform_color
(
bbox_color
)
# draw bboxes on visualizer
vis
.
add_geometry
(
line_set
)
# change the color of points which are in box
if
pcd
is
not
None
and
mode
==
'xyz'
:
indices
=
box3d
.
get_point_indices_within_bounding_box
(
pcd
.
points
)
points_colors
[
indices
]
=
in_box_color
# update points colors
if
pcd
is
not
None
:
pcd
.
colors
=
o3d
.
utility
.
Vector3dVector
(
points_colors
)
vis
.
update_geometry
(
pcd
)
def
show_pts_boxes
(
points
,
bbox3d
=
None
,
show
=
True
,
save_path
=
None
,
points_size
=
2
,
point_color
=
(
0.5
,
0.5
,
0.5
),
bbox_color
=
(
0
,
1
,
0
),
points_in_box_color
=
(
1
,
0
,
0
),
rot_axis
=
2
,
center_mode
=
'lidar_bottom'
,
mode
=
'xyz'
):
"""Draw bbox and points on visualizer.
Args:
points (numpy.array | torch.tensor, shape=[N, 3+C]):
points to visualize.
bbox3d (numpy.array | torch.tensor, shape=[M, 7], optional):
3D bbox (x, y, z, x_size, y_size, z_size, yaw) to visualize.
Defaults to None.
show (bool, optional): whether to show the visualization results.
Default: True.
save_path (str, optional): path to save visualized results.
Default: None.
points_size (int, optional): the size of points to show on visualizer.
Default: 2.
point_color (tuple[float], optional): the color of points.
Default: (0.5, 0.5, 0.5).
bbox_color (tuple[float], optional): the color of bbox.
Default: (0, 1, 0).
points_in_box_color (tuple[float], optional):
the color of points which are in bbox3d. Default: (1, 0, 0).
rot_axis (int, optional): rotation axis of bbox. Default: 2.
center_mode (bool, optional): indicate the center of bbox is bottom
center or gravity center. available mode
['lidar_bottom', 'camera_bottom']. Default: 'lidar_bottom'.
mode (str, optional): indicate type of the input points, available
mode ['xyz', 'xyzrgb']. Default: 'xyz'.
"""
# TODO: support score and class info
assert
0
<=
rot_axis
<=
2
# init visualizer
vis
=
o3d
.
visualization
.
Visualizer
()
vis
.
create_window
()
mesh_frame
=
geometry
.
TriangleMesh
.
create_coordinate_frame
(
size
=
1
,
origin
=
[
0
,
0
,
0
])
# create coordinate frame
vis
.
add_geometry
(
mesh_frame
)
# draw points
pcd
,
points_colors
=
_draw_points
(
points
,
vis
,
points_size
,
point_color
,
mode
)
# draw boxes
if
bbox3d
is
not
None
:
_draw_bboxes
(
bbox3d
,
vis
,
points_colors
,
pcd
,
bbox_color
,
points_in_box_color
,
rot_axis
,
center_mode
,
mode
)
if
show
:
vis
.
run
()
if
save_path
is
not
None
:
vis
.
capture_screen_image
(
save_path
)
vis
.
destroy_window
()
def
_draw_bboxes_ind
(
bbox3d
,
vis
,
indices
,
points_colors
,
pcd
=
None
,
bbox_color
=
(
0
,
1
,
0
),
points_in_box_color
=
(
1
,
0
,
0
),
rot_axis
=
2
,
center_mode
=
'lidar_bottom'
,
mode
=
'xyz'
):
"""Draw bbox on visualizer and change the color or points inside bbox3d
with indices.
Args:
bbox3d (numpy.array | torch.tensor, shape=[M, 7]):
3d bbox (x, y, z, x_size, y_size, z_size, yaw) to visualize.
vis (:obj:`open3d.visualization.Visualizer`): open3d visualizer.
indices (numpy.array | torch.tensor, shape=[N, M]):
indicate which bbox3d that each point lies in.
points_colors (numpy.array): color of each points.
pcd (:obj:`open3d.geometry.PointCloud`, optional): point cloud.
Default: None.
bbox_color (tuple[float], optional): the color of bbox.
Default: (0, 1, 0).
points_in_box_color (tuple[float], optional):
the color of points which are in bbox3d. Default: (1, 0, 0).
rot_axis (int, optional): rotation axis of bbox. Default: 2.
center_mode (bool, optional): indicate the center of bbox is
bottom center or gravity center. available mode
['lidar_bottom', 'camera_bottom']. Default: 'lidar_bottom'.
mode (str, optional): indicate type of the input points,
available mode ['xyz', 'xyzrgb']. Default: 'xyz'.
"""
if
isinstance
(
bbox3d
,
torch
.
Tensor
):
bbox3d
=
bbox3d
.
cpu
().
numpy
()
if
isinstance
(
indices
,
torch
.
Tensor
):
indices
=
indices
.
cpu
().
numpy
()
bbox3d
=
bbox3d
.
copy
()
in_box_color
=
np
.
array
(
points_in_box_color
)
for
i
in
range
(
len
(
bbox3d
)):
center
=
bbox3d
[
i
,
0
:
3
]
dim
=
bbox3d
[
i
,
3
:
6
]
yaw
=
np
.
zeros
(
3
)
# TODO: fix problem of current coordinate system
# dim[0], dim[1] = dim[1], dim[0] # for current coordinate
# yaw[rot_axis] = -(bbox3d[i, 6] - 0.5 * np.pi)
yaw
[
rot_axis
]
=
-
bbox3d
[
i
,
6
]
rot_mat
=
geometry
.
get_rotation_matrix_from_xyz
(
yaw
)
if
center_mode
==
'lidar_bottom'
:
center
[
rot_axis
]
+=
dim
[
rot_axis
]
/
2
# bottom center to gravity center
elif
center_mode
==
'camera_bottom'
:
center
[
rot_axis
]
-=
dim
[
rot_axis
]
/
2
# bottom center to gravity center
box3d
=
geometry
.
OrientedBoundingBox
(
center
,
rot_mat
,
dim
)
line_set
=
geometry
.
LineSet
.
create_from_oriented_bounding_box
(
box3d
)
line_set
.
paint_uniform_color
(
bbox_color
)
# draw bboxes on visualizer
vis
.
add_geometry
(
line_set
)
# change the color of points which are in box
if
pcd
is
not
None
and
mode
==
'xyz'
:
points_colors
[
indices
[:,
i
].
astype
(
np
.
bool
)]
=
in_box_color
# update points colors
if
pcd
is
not
None
:
pcd
.
colors
=
o3d
.
utility
.
Vector3dVector
(
points_colors
)
vis
.
update_geometry
(
pcd
)
def
show_pts_index_boxes
(
points
,
bbox3d
=
None
,
show
=
True
,
indices
=
None
,
save_path
=
None
,
points_size
=
2
,
point_color
=
(
0.5
,
0.5
,
0.5
),
bbox_color
=
(
0
,
1
,
0
),
points_in_box_color
=
(
1
,
0
,
0
),
rot_axis
=
2
,
center_mode
=
'lidar_bottom'
,
mode
=
'xyz'
):
"""Draw bbox and points on visualizer with indices that indicate which
bbox3d that each point lies in.
Args:
points (numpy.array | torch.tensor, shape=[N, 3+C]):
points to visualize.
bbox3d (numpy.array | torch.tensor, shape=[M, 7]):
3D bbox (x, y, z, x_size, y_size, z_size, yaw) to visualize.
Defaults to None.
show (bool, optional): whether to show the visualization results.
Default: True.
indices (numpy.array | torch.tensor, shape=[N, M], optional):
indicate which bbox3d that each point lies in. Default: None.
save_path (str, optional): path to save visualized results.
Default: None.
points_size (int, optional): the size of points to show on visualizer.
Default: 2.
point_color (tuple[float], optional): the color of points.
Default: (0.5, 0.5, 0.5).
bbox_color (tuple[float], optional): the color of bbox.
Default: (0, 1, 0).
points_in_box_color (tuple[float], optional):
the color of points which are in bbox3d. Default: (1, 0, 0).
rot_axis (int, optional): rotation axis of bbox. Default: 2.
center_mode (bool, optional): indicate the center of bbox is
bottom center or gravity center. available mode
['lidar_bottom', 'camera_bottom']. Default: 'lidar_bottom'.
mode (str, optional): indicate type of the input points,
available mode ['xyz', 'xyzrgb']. Default: 'xyz'.
"""
# TODO: support score and class info
assert
0
<=
rot_axis
<=
2
# init visualizer
vis
=
o3d
.
visualization
.
Visualizer
()
vis
.
create_window
()
mesh_frame
=
geometry
.
TriangleMesh
.
create_coordinate_frame
(
size
=
1
,
origin
=
[
0
,
0
,
0
])
# create coordinate frame
vis
.
add_geometry
(
mesh_frame
)
# draw points
pcd
,
points_colors
=
_draw_points
(
points
,
vis
,
points_size
,
point_color
,
mode
)
# draw boxes
if
bbox3d
is
not
None
:
_draw_bboxes_ind
(
bbox3d
,
vis
,
indices
,
points_colors
,
pcd
,
bbox_color
,
points_in_box_color
,
rot_axis
,
center_mode
,
mode
)
if
show
:
vis
.
run
()
if
save_path
is
not
None
:
vis
.
capture_screen_image
(
save_path
)
vis
.
destroy_window
()
class
Visualizer
(
object
):
r
"""Online visualizer implemented with Open3d.
Args:
points (numpy.array, shape=[N, 3+C]): Points to visualize. The Points
cloud is in mode of Coord3DMode.DEPTH (please refer to
core.structures.coord_3d_mode).
bbox3d (numpy.array, shape=[M, 7], optional): 3D bbox
(x, y, z, x_size, y_size, z_size, yaw) to visualize.
The 3D bbox is in mode of Box3DMode.DEPTH with
gravity_center (please refer to core.structures.box_3d_mode).
Default: None.
save_path (str, optional): path to save visualized results.
Default: None.
points_size (int, optional): the size of points to show on visualizer.
Default: 2.
point_color (tuple[float], optional): the color of points.
Default: (0.5, 0.5, 0.5).
bbox_color (tuple[float], optional): the color of bbox.
Default: (0, 1, 0).
points_in_box_color (tuple[float], optional):
the color of points which are in bbox3d. Default: (1, 0, 0).
rot_axis (int, optional): rotation axis of bbox. Default: 2.
center_mode (bool, optional): indicate the center of bbox is
bottom center or gravity center. available mode
['lidar_bottom', 'camera_bottom']. Default: 'lidar_bottom'.
mode (str, optional): indicate type of the input points,
available mode ['xyz', 'xyzrgb']. Default: 'xyz'.
"""
def
__init__
(
self
,
points
,
bbox3d
=
None
,
save_path
=
None
,
points_size
=
2
,
point_color
=
(
0.5
,
0.5
,
0.5
),
bbox_color
=
(
0
,
1
,
0
),
points_in_box_color
=
(
1
,
0
,
0
),
rot_axis
=
2
,
center_mode
=
'lidar_bottom'
,
mode
=
'xyz'
):
super
(
Visualizer
,
self
).
__init__
()
assert
0
<=
rot_axis
<=
2
# init visualizer
self
.
o3d_visualizer
=
o3d
.
visualization
.
Visualizer
()
self
.
o3d_visualizer
.
create_window
()
mesh_frame
=
geometry
.
TriangleMesh
.
create_coordinate_frame
(
size
=
1
,
origin
=
[
0
,
0
,
0
])
# create coordinate frame
self
.
o3d_visualizer
.
add_geometry
(
mesh_frame
)
self
.
points_size
=
points_size
self
.
point_color
=
point_color
self
.
bbox_color
=
bbox_color
self
.
points_in_box_color
=
points_in_box_color
self
.
rot_axis
=
rot_axis
self
.
center_mode
=
center_mode
self
.
mode
=
mode
self
.
seg_num
=
0
# draw points
if
points
is
not
None
:
self
.
pcd
,
self
.
points_colors
=
_draw_points
(
points
,
self
.
o3d_visualizer
,
points_size
,
point_color
,
mode
)
# draw boxes
if
bbox3d
is
not
None
:
_draw_bboxes
(
bbox3d
,
self
.
o3d_visualizer
,
self
.
points_colors
,
self
.
pcd
,
bbox_color
,
points_in_box_color
,
rot_axis
,
center_mode
,
mode
)
def
add_bboxes
(
self
,
bbox3d
,
bbox_color
=
None
,
points_in_box_color
=
None
):
"""Add bounding box to visualizer.
Args:
bbox3d (numpy.array, shape=[M, 7]):
3D bbox (x, y, z, x_size, y_size, z_size, yaw)
to be visualized. The 3d bbox is in mode of
Box3DMode.DEPTH with gravity_center (please refer to
core.structures.box_3d_mode).
bbox_color (tuple[float]): the color of bbox. Default: None.
points_in_box_color (tuple[float]): the color of points which
are in bbox3d. Default: None.
"""
if
bbox_color
is
None
:
bbox_color
=
self
.
bbox_color
if
points_in_box_color
is
None
:
points_in_box_color
=
self
.
points_in_box_color
_draw_bboxes
(
bbox3d
,
self
.
o3d_visualizer
,
self
.
points_colors
,
self
.
pcd
,
bbox_color
,
points_in_box_color
,
self
.
rot_axis
,
self
.
center_mode
,
self
.
mode
)
def
add_seg_mask
(
self
,
seg_mask_colors
):
"""Add segmentation mask to visualizer via per-point colorization.
Args:
seg_mask_colors (numpy.array, shape=[N, 6]):
The segmentation mask whose first 3 dims are point coordinates
and last 3 dims are converted colors.
"""
# we can't draw the colors on existing points
# in case gt and pred mask would overlap
# instead we set a large offset along x-axis for each seg mask
self
.
seg_num
+=
1
offset
=
(
np
.
array
(
self
.
pcd
.
points
).
max
(
0
)
-
np
.
array
(
self
.
pcd
.
points
).
min
(
0
))[
0
]
*
1.2
*
self
.
seg_num
mesh_frame
=
geometry
.
TriangleMesh
.
create_coordinate_frame
(
size
=
1
,
origin
=
[
offset
,
0
,
0
])
# create coordinate frame for seg
self
.
o3d_visualizer
.
add_geometry
(
mesh_frame
)
seg_points
=
copy
.
deepcopy
(
seg_mask_colors
)
seg_points
[:,
0
]
+=
offset
_draw_points
(
seg_points
,
self
.
o3d_visualizer
,
self
.
points_size
,
mode
=
'xyzrgb'
)
def
show
(
self
,
save_path
=
None
):
"""Visualize the points cloud.
Args:
save_path (str, optional): path to save image. Default: None.
"""
self
.
o3d_visualizer
.
run
()
if
save_path
is
not
None
:
self
.
o3d_visualizer
.
capture_screen_image
(
save_path
)
self
.
o3d_visualizer
.
destroy_window
()
return
mmdet3d/core/visualizer/show_result.py
deleted
100644 → 0
View file @
0e17beab
# Copyright (c) OpenMMLab. All rights reserved.
from
os
import
path
as
osp
import
mmcv
import
numpy
as
np
import
trimesh
from
.image_vis
import
(
draw_camera_bbox3d_on_img
,
draw_depth_bbox3d_on_img
,
draw_lidar_bbox3d_on_img
)
def
_write_obj
(
points
,
out_filename
):
"""Write points into ``obj`` format for meshlab visualization.
Args:
points (np.ndarray): Points in shape (N, dim).
out_filename (str): Filename to be saved.
"""
N
=
points
.
shape
[
0
]
fout
=
open
(
out_filename
,
'w'
)
for
i
in
range
(
N
):
if
points
.
shape
[
1
]
==
6
:
c
=
points
[
i
,
3
:].
astype
(
int
)
fout
.
write
(
'v %f %f %f %d %d %d
\n
'
%
(
points
[
i
,
0
],
points
[
i
,
1
],
points
[
i
,
2
],
c
[
0
],
c
[
1
],
c
[
2
]))
else
:
fout
.
write
(
'v %f %f %f
\n
'
%
(
points
[
i
,
0
],
points
[
i
,
1
],
points
[
i
,
2
]))
fout
.
close
()
def
_write_oriented_bbox
(
scene_bbox
,
out_filename
):
"""Export oriented (around Z axis) scene bbox to meshes.
Args:
scene_bbox(list[ndarray] or ndarray): xyz pos of center and
3 lengths (x_size, y_size, z_size) and heading angle around Z axis.
Y forward, X right, Z upward. heading angle of positive X is 0,
heading angle of positive Y is 90 degrees.
out_filename(str): Filename.
"""
def
heading2rotmat
(
heading_angle
):
rotmat
=
np
.
zeros
((
3
,
3
))
rotmat
[
2
,
2
]
=
1
cosval
=
np
.
cos
(
heading_angle
)
sinval
=
np
.
sin
(
heading_angle
)
rotmat
[
0
:
2
,
0
:
2
]
=
np
.
array
([[
cosval
,
-
sinval
],
[
sinval
,
cosval
]])
return
rotmat
def
convert_oriented_box_to_trimesh_fmt
(
box
):
ctr
=
box
[:
3
]
lengths
=
box
[
3
:
6
]
trns
=
np
.
eye
(
4
)
trns
[
0
:
3
,
3
]
=
ctr
trns
[
3
,
3
]
=
1.0
trns
[
0
:
3
,
0
:
3
]
=
heading2rotmat
(
box
[
6
])
box_trimesh_fmt
=
trimesh
.
creation
.
box
(
lengths
,
trns
)
return
box_trimesh_fmt
if
len
(
scene_bbox
)
==
0
:
scene_bbox
=
np
.
zeros
((
1
,
7
))
scene
=
trimesh
.
scene
.
Scene
()
for
box
in
scene_bbox
:
scene
.
add_geometry
(
convert_oriented_box_to_trimesh_fmt
(
box
))
mesh_list
=
trimesh
.
util
.
concatenate
(
scene
.
dump
())
# save to obj file
trimesh
.
io
.
export
.
export_mesh
(
mesh_list
,
out_filename
,
file_type
=
'obj'
)
return
def
show_result
(
points
,
gt_bboxes
,
pred_bboxes
,
out_dir
,
filename
,
show
=
False
,
snapshot
=
False
,
pred_labels
=
None
):
"""Convert results into format that is directly readable for meshlab.
Args:
points (np.ndarray): Points.
gt_bboxes (np.ndarray): Ground truth boxes.
pred_bboxes (np.ndarray): Predicted boxes.
out_dir (str): Path of output directory
filename (str): Filename of the current frame.
show (bool, optional): Visualize the results online. Defaults to False.
snapshot (bool, optional): Whether to save the online results.
Defaults to False.
pred_labels (np.ndarray, optional): Predicted labels of boxes.
Defaults to None.
"""
result_path
=
osp
.
join
(
out_dir
,
filename
)
mmcv
.
mkdir_or_exist
(
result_path
)
if
show
:
from
.open3d_vis
import
Visualizer
vis
=
Visualizer
(
points
)
if
pred_bboxes
is
not
None
:
if
pred_labels
is
None
:
vis
.
add_bboxes
(
bbox3d
=
pred_bboxes
)
else
:
palette
=
np
.
random
.
randint
(
0
,
255
,
size
=
(
pred_labels
.
max
()
+
1
,
3
))
/
256
labelDict
=
{}
for
j
in
range
(
len
(
pred_labels
)):
i
=
int
(
pred_labels
[
j
].
numpy
())
if
labelDict
.
get
(
i
)
is
None
:
labelDict
[
i
]
=
[]
labelDict
[
i
].
append
(
pred_bboxes
[
j
])
for
i
in
labelDict
:
vis
.
add_bboxes
(
bbox3d
=
np
.
array
(
labelDict
[
i
]),
bbox_color
=
palette
[
i
],
points_in_box_color
=
palette
[
i
])
if
gt_bboxes
is
not
None
:
vis
.
add_bboxes
(
bbox3d
=
gt_bboxes
,
bbox_color
=
(
0
,
0
,
1
))
show_path
=
osp
.
join
(
result_path
,
f
'
{
filename
}
_online.png'
)
if
snapshot
else
None
vis
.
show
(
show_path
)
if
points
is
not
None
:
_write_obj
(
points
,
osp
.
join
(
result_path
,
f
'
{
filename
}
_points.obj'
))
if
gt_bboxes
is
not
None
:
# bottom center to gravity center
gt_bboxes
[...,
2
]
+=
gt_bboxes
[...,
5
]
/
2
_write_oriented_bbox
(
gt_bboxes
,
osp
.
join
(
result_path
,
f
'
{
filename
}
_gt.obj'
))
if
pred_bboxes
is
not
None
:
# bottom center to gravity center
pred_bboxes
[...,
2
]
+=
pred_bboxes
[...,
5
]
/
2
_write_oriented_bbox
(
pred_bboxes
,
osp
.
join
(
result_path
,
f
'
{
filename
}
_pred.obj'
))
def
show_seg_result
(
points
,
gt_seg
,
pred_seg
,
out_dir
,
filename
,
palette
,
ignore_index
=
None
,
show
=
False
,
snapshot
=
False
):
"""Convert results into format that is directly readable for meshlab.
Args:
points (np.ndarray): Points.
gt_seg (np.ndarray): Ground truth segmentation mask.
pred_seg (np.ndarray): Predicted segmentation mask.
out_dir (str): Path of output directory
filename (str): Filename of the current frame.
palette (np.ndarray): Mapping between class labels and colors.
ignore_index (int, optional): The label index to be ignored, e.g.
unannotated points. Defaults to None.
show (bool, optional): Visualize the results online. Defaults to False.
snapshot (bool, optional): Whether to save the online results.
Defaults to False.
"""
# we need 3D coordinates to visualize segmentation mask
if
gt_seg
is
not
None
or
pred_seg
is
not
None
:
assert
points
is
not
None
,
\
'3D coordinates are required for segmentation visualization'
# filter out ignored points
if
gt_seg
is
not
None
and
ignore_index
is
not
None
:
if
points
is
not
None
:
points
=
points
[
gt_seg
!=
ignore_index
]
if
pred_seg
is
not
None
:
pred_seg
=
pred_seg
[
gt_seg
!=
ignore_index
]
gt_seg
=
gt_seg
[
gt_seg
!=
ignore_index
]
if
gt_seg
is
not
None
:
gt_seg_color
=
palette
[
gt_seg
]
gt_seg_color
=
np
.
concatenate
([
points
[:,
:
3
],
gt_seg_color
],
axis
=
1
)
if
pred_seg
is
not
None
:
pred_seg_color
=
palette
[
pred_seg
]
pred_seg_color
=
np
.
concatenate
([
points
[:,
:
3
],
pred_seg_color
],
axis
=
1
)
result_path
=
osp
.
join
(
out_dir
,
filename
)
mmcv
.
mkdir_or_exist
(
result_path
)
# online visualization of segmentation mask
# we show three masks in a row, scene_points, gt_mask, pred_mask
if
show
:
from
.open3d_vis
import
Visualizer
mode
=
'xyzrgb'
if
points
.
shape
[
1
]
==
6
else
'xyz'
vis
=
Visualizer
(
points
,
mode
=
mode
)
if
gt_seg
is
not
None
:
vis
.
add_seg_mask
(
gt_seg_color
)
if
pred_seg
is
not
None
:
vis
.
add_seg_mask
(
pred_seg_color
)
show_path
=
osp
.
join
(
result_path
,
f
'
{
filename
}
_online.png'
)
if
snapshot
else
None
vis
.
show
(
show_path
)
if
points
is
not
None
:
_write_obj
(
points
,
osp
.
join
(
result_path
,
f
'
{
filename
}
_points.obj'
))
if
gt_seg
is
not
None
:
_write_obj
(
gt_seg_color
,
osp
.
join
(
result_path
,
f
'
{
filename
}
_gt.obj'
))
if
pred_seg
is
not
None
:
_write_obj
(
pred_seg_color
,
osp
.
join
(
result_path
,
f
'
{
filename
}
_pred.obj'
))
def
show_multi_modality_result
(
img
,
gt_bboxes
,
pred_bboxes
,
proj_mat
,
out_dir
,
filename
,
box_mode
=
'lidar'
,
img_metas
=
None
,
show
=
False
,
gt_bbox_color
=
(
61
,
102
,
255
),
pred_bbox_color
=
(
241
,
101
,
72
)):
"""Convert multi-modality detection results into 2D results.
Project the predicted 3D bbox to 2D image plane and visualize them.
Args:
img (np.ndarray): The numpy array of image in cv2 fashion.
gt_bboxes (:obj:`BaseInstance3DBoxes`): Ground truth boxes.
pred_bboxes (:obj:`BaseInstance3DBoxes`): Predicted boxes.
proj_mat (numpy.array, shape=[4, 4]): The projection matrix
according to the camera intrinsic parameters.
out_dir (str): Path of output directory.
filename (str): Filename of the current frame.
box_mode (str, optional): Coordinate system the boxes are in.
Should be one of 'depth', 'lidar' and 'camera'.
Defaults to 'lidar'.
img_metas (dict, optional): Used in projecting depth bbox.
Defaults to None.
show (bool, optional): Visualize the results online. Defaults to False.
gt_bbox_color (str or tuple(int), optional): Color of bbox lines.
The tuple of color should be in BGR order. Default: (255, 102, 61).
pred_bbox_color (str or tuple(int), optional): Color of bbox lines.
The tuple of color should be in BGR order. Default: (72, 101, 241).
"""
if
box_mode
==
'depth'
:
draw_bbox
=
draw_depth_bbox3d_on_img
elif
box_mode
==
'lidar'
:
draw_bbox
=
draw_lidar_bbox3d_on_img
elif
box_mode
==
'camera'
:
draw_bbox
=
draw_camera_bbox3d_on_img
else
:
raise
NotImplementedError
(
f
'unsupported box mode
{
box_mode
}
'
)
result_path
=
osp
.
join
(
out_dir
,
filename
)
mmcv
.
mkdir_or_exist
(
result_path
)
if
show
:
show_img
=
img
.
copy
()
if
gt_bboxes
is
not
None
:
show_img
=
draw_bbox
(
gt_bboxes
,
show_img
,
proj_mat
,
img_metas
,
color
=
gt_bbox_color
)
if
pred_bboxes
is
not
None
:
show_img
=
draw_bbox
(
pred_bboxes
,
show_img
,
proj_mat
,
img_metas
,
color
=
pred_bbox_color
)
mmcv
.
imshow
(
show_img
,
win_name
=
'project_bbox3d_img'
,
wait_time
=
0
)
if
img
is
not
None
:
mmcv
.
imwrite
(
img
,
osp
.
join
(
result_path
,
f
'
{
filename
}
_img.png'
))
if
gt_bboxes
is
not
None
:
gt_img
=
draw_bbox
(
gt_bboxes
,
img
,
proj_mat
,
img_metas
,
color
=
gt_bbox_color
)
mmcv
.
imwrite
(
gt_img
,
osp
.
join
(
result_path
,
f
'
{
filename
}
_gt.png'
))
if
pred_bboxes
is
not
None
:
pred_img
=
draw_bbox
(
pred_bboxes
,
img
,
proj_mat
,
img_metas
,
color
=
pred_bbox_color
)
mmcv
.
imwrite
(
pred_img
,
osp
.
join
(
result_path
,
f
'
{
filename
}
_pred.png'
))
tools/misc/browse_dataset.py
View file @
27a546e9
# Copyright (c) OpenMMLab. All rights reserved.
# Copyright (c) OpenMMLab. All rights reserved.
import
argparse
import
argparse
import
warnings
from
os
import
path
as
osp
from
os
import
path
as
osp
from
pathlib
import
Path
import
mmcv
import
mmcv
import
numpy
as
np
from
mmcv
import
Config
,
DictAction
,
mkdir_or_exist
from
mmcv
import
Config
,
DictAction
,
mkdir_or_exist
from
mmdet3d.core.bbox
import
(
Box3DMode
,
CameraInstance3DBoxes
,
Coord3DMode
,
DepthInstance3DBoxes
,
LiDARInstance3DBoxes
)
from
mmdet3d.core.visualizer
import
(
show_multi_modality_result
,
show_result
,
show_seg_result
)
from
mmdet3d.datasets
import
build_dataset
from
mmdet3d.datasets
import
build_dataset
from
mmdet3d.registry
import
VISUALIZERS
from
mmdet3d.utils
import
register_all_modules
def
parse_args
():
def
parse_args
():
...
@@ -80,8 +75,8 @@ def build_data_cfg(config_path, skip_type, aug, cfg_options):
...
@@ -80,8 +75,8 @@ def build_data_cfg(config_path, skip_type, aug, cfg_options):
if
cfg
.
train_pipeline
[
i
][
'type'
]
==
'LoadAnnotations3D'
:
if
cfg
.
train_pipeline
[
i
][
'type'
]
==
'LoadAnnotations3D'
:
show_pipeline
.
insert
(
i
,
cfg
.
train_pipeline
[
i
])
show_pipeline
.
insert
(
i
,
cfg
.
train_pipeline
[
i
])
# Collect points as well as labels
# Collect points as well as labels
if
cfg
.
train_pipeline
[
i
][
'type'
]
==
'
Collect3D
'
:
if
cfg
.
train_pipeline
[
i
][
'type'
]
==
'
Pack3DInputs
'
:
if
show_pipeline
[
-
1
][
'type'
]
==
'
Collect3D
'
:
if
show_pipeline
[
-
1
][
'type'
]
==
'
Pack3DInputs
'
:
show_pipeline
[
-
1
]
=
cfg
.
train_pipeline
[
i
]
show_pipeline
[
-
1
]
=
cfg
.
train_pipeline
[
i
]
else
:
else
:
show_pipeline
.
append
(
cfg
.
train_pipeline
[
i
])
show_pipeline
.
append
(
cfg
.
train_pipeline
[
i
])
...
@@ -93,105 +88,6 @@ def build_data_cfg(config_path, skip_type, aug, cfg_options):
...
@@ -93,105 +88,6 @@ def build_data_cfg(config_path, skip_type, aug, cfg_options):
return
cfg
return
cfg
def
to_depth_mode
(
points
,
bboxes
):
"""Convert points and bboxes to Depth Coord and Depth Box mode."""
if
points
is
not
None
:
points
=
Coord3DMode
.
convert_point
(
points
.
copy
(),
Coord3DMode
.
LIDAR
,
Coord3DMode
.
DEPTH
)
if
bboxes
is
not
None
:
bboxes
=
Box3DMode
.
convert
(
bboxes
.
clone
(),
Box3DMode
.
LIDAR
,
Box3DMode
.
DEPTH
)
return
points
,
bboxes
def
show_det_data
(
input
,
out_dir
,
show
=
False
):
"""Visualize 3D point cloud and 3D bboxes."""
img_metas
=
input
[
'img_metas'
].
_data
points
=
input
[
'points'
].
_data
.
numpy
()
gt_bboxes
=
input
[
'gt_bboxes_3d'
].
_data
.
tensor
if
img_metas
[
'box_mode_3d'
]
!=
Box3DMode
.
DEPTH
:
points
,
gt_bboxes
=
to_depth_mode
(
points
,
gt_bboxes
)
filename
=
osp
.
splitext
(
osp
.
basename
(
img_metas
[
'pts_filename'
]))[
0
]
show_result
(
points
,
gt_bboxes
.
clone
(),
None
,
out_dir
,
filename
,
show
=
show
,
snapshot
=
True
)
def
show_seg_data
(
input
,
out_dir
,
show
=
False
):
"""Visualize 3D point cloud and segmentation mask."""
img_metas
=
input
[
'img_metas'
].
_data
points
=
input
[
'points'
].
_data
.
numpy
()
gt_seg
=
input
[
'pts_semantic_mask'
].
_data
.
numpy
()
filename
=
osp
.
splitext
(
osp
.
basename
(
img_metas
[
'pts_filename'
]))[
0
]
show_seg_result
(
points
,
gt_seg
.
copy
(),
None
,
out_dir
,
filename
,
np
.
array
(
img_metas
[
'PALETTE'
]),
img_metas
[
'ignore_index'
],
show
=
show
,
snapshot
=
True
)
def
show_proj_bbox_img
(
input
,
out_dir
,
show
=
False
,
is_nus_mono
=
False
):
"""Visualize 3D bboxes on 2D image by projection."""
gt_bboxes
=
input
[
'gt_bboxes_3d'
].
_data
img_metas
=
input
[
'img_metas'
].
_data
img
=
input
[
'img'
].
_data
.
numpy
()
# need to transpose channel to first dim
img
=
img
.
transpose
(
1
,
2
,
0
)
# no 3D gt bboxes, just show img
if
gt_bboxes
.
tensor
.
shape
[
0
]
==
0
:
gt_bboxes
=
None
filename
=
Path
(
img_metas
[
'filename'
]).
name
if
isinstance
(
gt_bboxes
,
DepthInstance3DBoxes
):
show_multi_modality_result
(
img
,
gt_bboxes
,
None
,
None
,
out_dir
,
filename
,
box_mode
=
'depth'
,
img_metas
=
img_metas
,
show
=
show
)
elif
isinstance
(
gt_bboxes
,
LiDARInstance3DBoxes
):
show_multi_modality_result
(
img
,
gt_bboxes
,
None
,
img_metas
[
'lidar2img'
],
out_dir
,
filename
,
box_mode
=
'lidar'
,
img_metas
=
img_metas
,
show
=
show
)
elif
isinstance
(
gt_bboxes
,
CameraInstance3DBoxes
):
show_multi_modality_result
(
img
,
gt_bboxes
,
None
,
img_metas
[
'cam2img'
],
out_dir
,
filename
,
box_mode
=
'camera'
,
img_metas
=
img_metas
,
show
=
show
)
else
:
# can't project, just show img
warnings
.
warn
(
f
'unrecognized gt box type
{
type
(
gt_bboxes
)
}
, only show image'
)
show_multi_modality_result
(
img
,
None
,
None
,
None
,
out_dir
,
filename
,
show
=
show
)
def
main
():
def
main
():
args
=
parse_args
()
args
=
parse_args
()
...
@@ -200,31 +96,42 @@ def main():
...
@@ -200,31 +96,42 @@ def main():
cfg
=
build_data_cfg
(
args
.
config
,
args
.
skip_type
,
args
.
aug
,
cfg
=
build_data_cfg
(
args
.
config
,
args
.
skip_type
,
args
.
aug
,
args
.
cfg_options
)
args
.
cfg_options
)
# register all modules in mmdet3d into the registries
register_all_modules
()
try
:
try
:
dataset
=
build_dataset
(
dataset
=
build_dataset
(
cfg
.
data
.
train
,
default_args
=
dict
(
filter_empty_gt
=
False
))
cfg
.
train_dataloader
.
dataset
,
default_args
=
dict
(
filter_empty_gt
=
False
))
except
TypeError
:
# seg dataset doesn't have `filter_empty_gt` key
except
TypeError
:
# seg dataset doesn't have `filter_empty_gt` key
dataset
=
build_dataset
(
cfg
.
data
.
train
)
dataset
=
build_dataset
(
cfg
.
train
_dataloader
.
dataset
)
dataset_type
=
cfg
.
dataset_type
# configure visualization mode
# configure visualization mode
vis_task
=
args
.
task
# 'det', 'seg', 'multi_modality-det', 'mono-det'
vis_task
=
args
.
task
# 'det', 'seg', 'multi_modality-det', 'mono-det'
visualizer
=
VISUALIZERS
.
build
(
cfg
.
visualizer
)
visualizer
.
dataset_meta
=
dataset
.
metainfo
progress_bar
=
mmcv
.
ProgressBar
(
len
(
dataset
))
progress_bar
=
mmcv
.
ProgressBar
(
len
(
dataset
))
for
input
in
dataset
:
for
item
in
dataset
:
if
vis_task
in
[
'det'
,
'multi_modality-det'
]:
# the 3D Boxes in input could be in any of three coordinates
# show 3D bboxes on 3D point clouds
data_input
=
item
[
'inputs'
]
show_det_data
(
input
,
args
.
output_dir
,
show
=
args
.
online
)
data_sample
=
item
[
'data_sample'
].
numpy
()
if
vis_task
in
[
'multi_modality-det'
,
'mono-det'
]:
# project 3D bboxes to 2D image
out_file
=
osp
.
join
(
show_proj_bbox_img
(
args
.
output_dir
)
if
args
.
output_dir
is
not
None
else
None
input
,
args
.
output_dir
,
visualizer
.
add_datasample
(
show
=
args
.
online
,
'3d visualzier'
,
is_nus_mono
=
(
dataset_type
==
'NuScenesMonoDataset'
))
data_input
,
elif
vis_task
in
[
'seg'
]:
data_sample
,
# show 3D segmentation mask on 3D point clouds
show
=
not
args
.
not_show
,
show_seg_data
(
input
,
args
.
output_dir
,
show
=
args
.
online
)
wait_time
=
args
.
show_interval
,
out_file
=
out_file
,
vis_task
=
vis_task
)
progress_bar
.
update
()
progress_bar
.
update
()
...
...
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