Skip to content

Commit 01d89df

Browse files
authored
Merge pull request #9 from OpenPerceptionX/dev
v0.0 of tool box
2 parents 114095a + 91d0cc7 commit 01d89df

202 files changed

Lines changed: 93482 additions & 165 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
*.mp4
6+
# C extensions
7+
#*.so
8+
*.txt
9+
*.bin
10+
*.json
11+
npy/
12+
npys/
13+
# Distribution / packaging
14+
.Python
15+
arun_log/
16+
test/
17+
build/
18+
develop-eggs/
19+
dist/
20+
downloads/
21+
eggs/
22+
.eggs/
23+
lib/
24+
lib64/
25+
parts/
26+
sdist/
27+
var/
28+
wheels/
29+
*.egg-info/
30+
.installed.cfg
31+
*.egg
32+
MANIFEST
33+
test/
34+
val/
35+
arun_log/
36+
# PyInstaller
37+
# Usually these files are written by a python script from a template
38+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
39+
*.manifest
40+
*.spec
41+
42+
# Installer logs
43+
pip-log.txt
44+
pip-delete-this-directory.txt
45+
46+
# Unit test / coverage reports
47+
htmlcov/
48+
.tox/
49+
.coverage
50+
.coverage.*
51+
.cache
52+
nosetests.xml
53+
coverage.xml
54+
*.cover
55+
.hypothesis/
56+
.pytest_cache/
57+
58+
# Translations
59+
*.mo
60+
*.pot
61+
62+
# Django stuff:
63+
*.log
64+
local_settings.py
65+
db.sqlite3
66+
67+
# Flask stuff:
68+
instance/
69+
.webassets-cache
70+
71+
# Scrapy stuff:
72+
.scrapy
73+
74+
# Sphinx documentation
75+
docs/_build/
76+
77+
# PyBuilder
78+
target/
79+
80+
# Jupyter Notebook
81+
.ipynb_checkpoints
82+
83+
# pyenv
84+
.python-version
85+
86+
# celery beat schedule file
87+
celerybeat-schedule
88+
89+
# SageMath parsed files
90+
*.sage.py
91+
92+
# Environments
93+
.env
94+
.venv
95+
.cache/
96+
env/
97+
venv/
98+
ENV/
99+
env.bak/
100+
venv.bak/
101+
102+
# Spyder project settings
103+
.spyderproject
104+
.spyproject
105+
106+
# Rope project settings
107+
.ropeproject
108+
109+
# mkdocs documentation
110+
/site
111+
112+
# mypy
113+
.mypy_cache/
114+
115+
# cython generated cpp
116+
data
117+
.vscode
118+
.idea
119+
*.tfrecord
120+
# custom
121+
*.pkl
122+
*.pkl.json
123+
*.log.json
124+
*.npy
125+
work_dirs/
126+
ckpts
127+
notebooks
128+
*~
129+
mmdet3d/.mim
130+
visual/
131+
# Pytorch
132+
*.pth
133+
*.tmp
134+
# demo
135+
*.obj
136+
*.ply
137+
*.zip
138+
.DS_Store

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "mmdetection3d"]
2+
path = code/mmdetection3d
3+
url = git@github.com:open-mmlab/mmdetection3d.git

README.md

Lines changed: 264 additions & 165 deletions
Large diffs are not rendered by default.

bev_toolbox/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from . import data_aug
2+
from .init_toolbox import init_toolbox_mmdet3d

bev_toolbox/data_aug/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .transforms import RandomScaleImageMultiViewImage, RandomHorizontalFlipMultiViewImage
2+
3+
__all__ = ['RandomScaleImageMultiViewImage', 'RandomHorizontalFlipMultiViewImage']

bev_toolbox/data_aug/functional.py

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
######################################################################
2+
# Copyright (c) 2022 OpenPerceptionX. All Rights Reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
######################################################################
16+
17+
######################################################################
18+
# This file includes concrete implementation for different data augmentation
19+
# methods in transforms.py.
20+
######################################################################
21+
22+
import numpy as np
23+
import cv2
24+
from typing import List, Tuple
25+
26+
# Available interpolation modes (opencv)
27+
cv2_interp_codes = {
28+
'nearest': cv2.INTER_NEAREST,
29+
'bilinear': cv2.INTER_LINEAR,
30+
'bicubic': cv2.INTER_CUBIC,
31+
'area': cv2.INTER_AREA,
32+
'lanczos': cv2.INTER_LANCZOS4
33+
}
34+
35+
36+
def scale_image_multiple_view(imgs: List[np.ndarray],
37+
cam_intrinsics: List[np.ndarray],
38+
cam_extrinsics: List[np.ndarray],
39+
lidar2img: List[np.ndarray],
40+
rand_scale: float,
41+
interpolation='bilinear') -> Tuple[List[np.ndarray], List[np.ndarray], List[np.ndarray]]:
42+
"""Resize the multiple-view images with the same scale selected randomly.
43+
Notably used in :class:`.transforms.RandomScaleImageMultiViewImage_naive
44+
Args:
45+
imgs (list of numpy.array): Multiple-view images to be resized. len(img) is the number of cameras.
46+
img shape: [H, W, 3].
47+
cam_intrinsics (list of numpy.array): Intrinsic parameters of different cameras. Transformations from camera
48+
to image. len(cam_intrinsics) is the number of camera. For each camera, shape is 4 * 4.
49+
cam_extrinsics (list of numpy.array): Extrinsic parameters of different cameras. Transformations from
50+
lidar to cameras. len(cam_extrinsics) is the number of camera. For each camera, shape is 4 * 4.
51+
lidar2img (list of numpy.array): Transformations from lidar to images. len(lidar2img) is the number
52+
of camera. For each camera, shape is 4 * 4.
53+
rand_scale (float): resize ratio
54+
interpolation (string): mode for interpolation in opencv.
55+
Returns:
56+
imgs_new (list of numpy.array): Updated multiple-view images
57+
cam_intrinsics_new (list of numpy.array): Updated intrinsic parameters of different cameras.
58+
lidar2img_new (list of numpy.array): Updated Transformations from lidar to images.
59+
"""
60+
61+
y_size = [int(img.shape[0] * rand_scale) for img in imgs]
62+
x_size = [int(img.shape[1] * rand_scale) for img in imgs]
63+
64+
scale_factor = np.eye(4)
65+
scale_factor[0, 0] *= rand_scale
66+
scale_factor[1, 1] *= rand_scale
67+
imgs_new = [
68+
cv2.resize(img, (x_size[idx], y_size[idx]), interpolation=cv2_interp_codes[interpolation])
69+
for idx, img in enumerate(imgs)
70+
]
71+
cam_intrinsics_new = [scale_factor @ cam_intrinsic for cam_intrinsic in cam_intrinsics]
72+
lidar2img_new = [scale_factor @ l2i for l2i in lidar2img]
73+
74+
return imgs_new, cam_intrinsics_new, lidar2img_new
75+
76+
77+
def horizontal_flip_image_multiview(imgs: List[np.ndarray]) -> List[np.ndarray]:
78+
"""Flip every image horizontally.
79+
Args:
80+
imgs (list of numpy.array): Multiple-view images to be resized. len(img) is the number of cameras.
81+
img shape: [H, W, 3].
82+
Returns:
83+
imgs_new (list of numpy.array): Flippd multiple-view images
84+
"""
85+
imgs_new = [np.flip(img, axis=1) for img in imgs]
86+
return imgs_new
87+
88+
89+
def vertical_flip_image_multiview(imgs: List[np.ndarray]) -> List[np.ndarray]:
90+
"""Flip every image vertically.
91+
Args:
92+
imgs (list of numpy.array): Multiple-view images to be resized. len(img) is the number of cameras.
93+
img shape: [H, W, 3].
94+
Returns:
95+
imgs_new (list of numpy.array): Flippd multiple-view images
96+
"""
97+
imgs_new = [np.flip(img, axis=0) for img in imgs]
98+
return imgs_new
99+
100+
101+
def horizontal_flip_bbox(bboxes_3d: np.ndarray, dataset: str) -> np.ndarray:
102+
"""Flip bounding boxes horizontally.
103+
Args:
104+
bboxes_3d (np.ndarray): bounding boxes of shape [N * 7], N is the number of objects.
105+
dataset (string): 'waymo' coordinate system or 'nuscenes' coordinate system.
106+
Returns:
107+
bboxes_3d (numpy.array): Flippd bounding boxes.
108+
"""
109+
if dataset == 'nuScenes':
110+
bboxes_3d[:, 0::7] = -bboxes_3d[:, 0::7]
111+
bboxes_3d[:, 6] = -bboxes_3d[:, 6] # + np.pi
112+
elif dataset == 'waymo':
113+
bboxes_3d[:, 1::7] = -bboxes_3d[:, 1::7]
114+
bboxes_3d[:, 6] = -bboxes_3d[:, 6] + np.pi
115+
return bboxes_3d
116+
117+
118+
def horizontal_flip_cam_params(img_shape: np.ndarray, cam_intrinsics: List[np.ndarray],
119+
cam_extrinsics: List[np.ndarray], lidar2imgs: List[np.ndarray],
120+
dataset: str) -> Tuple[List[np.ndarray], List[np.ndarray], List[np.ndarray]]:
121+
"""Flip camera parameters horizontally.
122+
Args:
123+
img_shape (numpy.array) of shape [3].
124+
cam_intrinsics (list of numpy.array): Intrinsic parameters of different cameras. Transformations from camera
125+
to image. len(cam_intrinsics) is the number of camera. For each camera, shape is 4 * 4.
126+
cam_extrinsics (list of numpy.array): Extrinsic parameters of different cameras. Transformations from
127+
lidar to cameras. len(cam_extrinsics) is the number of camera. For each camera, shape is 4 * 4.
128+
lidar2img (list of numpy.array): Transformations from lidar to images. len(lidar2img) is the number
129+
of camera. For each camera, shape is 4 * 4.
130+
dataset (string): Specify 'waymo' coordinate system or 'nuscenes' coordinate system.
131+
Returns:
132+
cam_intrinsics (list of numpy.array): Updated intrinsic parameters of different cameras.
133+
cam_extrinsics (list of numpy.array): Updated extrinsic parameters of different cameras.
134+
lidar2img (list of numpy.array): Updated Transformations from lidar to images.
135+
"""
136+
flip_factor = np.eye(4)
137+
lidar2imgs = []
138+
139+
w = img_shape[1]
140+
if dataset == 'nuScenes':
141+
flip_factor[0, 0] = -1
142+
cam_extrinsics = [l2c @ flip_factor for l2c in cam_extrinsics]
143+
for cam_intrinsic, l2c in zip(cam_intrinsics, cam_extrinsics):
144+
cam_intrinsic[0, 0] = -cam_intrinsic[0, 0]
145+
cam_intrinsic[0, 2] = w - cam_intrinsic[0, 2]
146+
lidar2imgs.append(cam_intrinsic @ l2c)
147+
elif dataset == 'waymo':
148+
flip_factor[1, 1] = -1
149+
cam_extrinsics = [l2c @ flip_factor for l2c in cam_extrinsics]
150+
for cam_intrinsic, l2c in zip(cam_intrinsics, cam_extrinsics):
151+
cam_intrinsic[0, 0] = -cam_intrinsic[0, 0]
152+
cam_intrinsic[0, 2] = w - cam_intrinsic[0, 2]
153+
lidar2imgs.append(cam_intrinsic @ l2c)
154+
else:
155+
assert False
156+
157+
return cam_intrinsics, cam_extrinsics, lidar2imgs
158+
159+
160+
def horizontal_flip_canbus(canbus: np.ndarray, dataset: str) -> np.ndarray:
161+
"""Flip can bus horizontally.
162+
Args:
163+
canbus (numpy.ndarray) of shape [18,]
164+
dataset (string): 'waymo' or 'nuscenes'
165+
Returns:
166+
canbus_new (list of numpy.array): Flipped canbus.
167+
"""
168+
if dataset == 'nuScenes':
169+
# results['canbus'][1] = -results['canbus'][1] # flip location
170+
# results['canbus'][-2] = -results['canbus'][-2] # flip direction
171+
canbus[-1] = -canbus[-1] # flip direction
172+
elif dataset == 'waymo':
173+
# results['canbus'][1] = -results['canbus'][-1] # flip location
174+
# results['canbus'][-2] = -results['canbus'][-2] # flip direction
175+
canbus[-1] = -canbus[-1] # flip direction
176+
else:
177+
raise NotImplementedError((f"Not support {dataset} dataset"))
178+
return canbus

0 commit comments

Comments
 (0)