Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] add SMOKE augmentation method #955

Merged
merged 41 commits into from
Oct 10, 2021
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
46d420f
[Refactor] Main code modification for coordinate system refactor (#677)
yezhen17 Jul 22, 2021
6877232
[Enhance] Add script for data update (#774)
yezhen17 Jul 29, 2021
febd2eb
fix import (#839)
yezhen17 Aug 5, 2021
3f64754
[Enhance] refactor iou_neg_piecewise_sampler.py (#842)
xiliu8006 Aug 9, 2021
b2abf1e
[Feature] Add roipooling cuda ops (#843)
xiliu8006 Aug 9, 2021
5a07dfe
[Refactor] Refactor code structure and docstrings (#803)
yezhen17 Aug 11, 2021
3d9268b
[Feature] PointXYZWHLRBBoxCoder (#856)
xiliu8006 Aug 16, 2021
3389237
[Enhance] Change Groupfree3D config (#855)
yezhen17 Aug 13, 2021
fc4bb0c
[Doc] Add tutorials/data_pipeline Chinese version (#827)
wHao-Wu Aug 18, 2021
0f81e49
[Doc] Add Chinese doc for `scannet_det.md` (#836)
yezhen17 Aug 18, 2021
cac2ef8
[Doc] Add Chinese doc for `waymo_det.md` (#859)
yezhen17 Aug 18, 2021
8d0b12a
Remove 2D annotations on Lyft (#867)
Tai-Wang Aug 18, 2021
2375d3c
Add header for files (#869)
DCNSW Aug 19, 2021
63fd399
[fix] fix typos (#872)
xieenze Aug 19, 2021
884b593
Fix 3 unworking configs (#882)
yezhen17 Aug 24, 2021
d688160
[Fix] Fix `index.rst` for Chinese docs (#873)
yezhen17 Aug 24, 2021
a000db5
[Fix] Centerpoint head nested list transpose (#879)
robin-karlsson0 Aug 25, 2021
4e9c992
[Enhance] Update PointFusion (#791)
filaPro Aug 25, 2021
08dae04
[Doc] Add nuscenes_det.md Chinese version (#854)
ZCMax Aug 26, 2021
93de7c2
[Fix] Fix RegNet pretrained weight loading (#889)
yezhen17 Aug 27, 2021
0eb7e71
Fix centerpoint tta (#892)
yezhen17 Aug 30, 2021
00c037a
[Enhance] Add benchmark regression script (#808)
yezhen17 Aug 30, 2021
1e6cdea
Initial commit
yezhen17 Sep 1, 2021
d4b1244
Merge pull request #899 from THU17cyz/coord_sys_tutorial_again
yezhen17 Sep 1, 2021
f095eb6
[Feature] Support DGCNN (v1.0.0.dev0) (#896)
DCNSW Sep 3, 2021
459c637
Change cam rot_3d_in_axis (#906)
yezhen17 Sep 6, 2021
2ae6b55
[Doc] Add coord sys tutorial pic and change links to dev branch (#912)
yezhen17 Sep 7, 2021
fce176f
[Feature] add kitti AP40 evaluation metric (v1.0.0.dev0) (#927)
ZCMax Sep 13, 2021
66f0c07
[Feature] add smoke backbone neck (#939)
ZCMax Sep 15, 2021
0b26a9a
[Refactor] Refactor the transformation from image to camera coordinat…
Tai-Wang Sep 15, 2021
911a333
[Feature] FCOS3D BBox Coder (#940)
Tai-Wang Sep 15, 2021
506f929
[Feature] PGD BBox Coder (#948)
Tai-Wang Sep 22, 2021
7252253
add smoke augmentation method
ZCMax Sep 22, 2021
73b6ea1
Merge branch 'v1.0.0.dev0' into add_smoke_aug_method
ZCMax Sep 28, 2021
875ad9c
add docs
ZCMax Sep 28, 2021
17efa12
fix docstrings
ZCMax Sep 29, 2021
5e7b205
fix typos
ZCMax Sep 30, 2021
dce4836
change point name
ZCMax Sep 30, 2021
7e2cdd6
fix typos
ZCMax Sep 30, 2021
dddb6b0
fix typos
ZCMax Oct 9, 2021
8af8e70
fix typos
ZCMax Oct 9, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions mmdet3d/datasets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
from .nuscenes_dataset import NuScenesDataset
from .nuscenes_mono_dataset import NuScenesMonoDataset
# yapf: disable
from .pipelines import (BackgroundPointsFilter, GlobalAlignment,
from .pipelines import (AffineResize, BackgroundPointsFilter, GlobalAlignment,
GlobalRotScaleTrans, IndoorPatchPointSample,
IndoorPointSample, LoadAnnotations3D,
LoadPointsFromFile, LoadPointsFromMultiSweeps,
NormalizePointsColor, ObjectNameFilter, ObjectNoise,
ObjectRangeFilter, ObjectSample, PointSample,
PointShuffle, PointsRangeFilter, RandomDropPointsColor,
RandomFlip3D, RandomJitterPoints,
RandomFlip3D, RandomJitterPoints, RandomShiftScale,
VoxelBasedPointSampler)
# yapf: enable
from .s3dis_dataset import S3DISDataset, S3DISSegDataset
Expand All @@ -38,5 +38,5 @@
'Custom3DDataset', 'Custom3DSegDataset', 'LoadPointsFromMultiSweeps',
'WaymoDataset', 'BackgroundPointsFilter', 'VoxelBasedPointSampler',
'get_loading_pipeline', 'RandomDropPointsColor', 'RandomJitterPoints',
'ObjectNameFilter'
'ObjectNameFilter', 'AffineResize', 'RandomShiftScale'
]
18 changes: 10 additions & 8 deletions mmdet3d/datasets/pipelines/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
LoadPointsFromMultiSweeps, NormalizePointsColor,
PointSegClassMapping)
from .test_time_aug import MultiScaleFlipAug3D
from .transforms_3d import (BackgroundPointsFilter, GlobalAlignment,
GlobalRotScaleTrans, IndoorPatchPointSample,
IndoorPointSample, ObjectNameFilter, ObjectNoise,
ObjectRangeFilter, ObjectSample, PointSample,
PointShuffle, PointsRangeFilter,
RandomDropPointsColor, RandomFlip3D,
RandomJitterPoints, VoxelBasedPointSampler)
# yapf: disable
from .transforms_3d import (AffineResize, BackgroundPointsFilter,
GlobalAlignment, GlobalRotScaleTrans,
IndoorPatchPointSample, IndoorPointSample,
ObjectNameFilter, ObjectNoise, ObjectRangeFilter,
ObjectSample, PointSample, PointShuffle,
PointsRangeFilter, RandomDropPointsColor,
RandomFlip3D, RandomJitterPoints, RandomShiftScale,
VoxelBasedPointSampler)

__all__ = [
'ObjectSample', 'RandomFlip3D', 'ObjectNoise', 'GlobalRotScaleTrans',
Expand All @@ -25,5 +27,5 @@
'LoadPointsFromMultiSweeps', 'BackgroundPointsFilter',
'VoxelBasedPointSampler', 'GlobalAlignment', 'IndoorPatchPointSample',
'LoadImageFromFileMono3D', 'ObjectNameFilter', 'RandomDropPointsColor',
'RandomJitterPoints'
'RandomJitterPoints', 'AffineResize', 'RandomShiftScale'
]
260 changes: 260 additions & 0 deletions mmdet3d/datasets/pipelines/transforms_3d.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Copyright (c) OpenMMLab. All rights reserved.
import cv2
import numpy as np
import random
import warnings
from mmcv import is_tuple_of
from mmcv.utils import build_from_cfg
Expand Down Expand Up @@ -1422,3 +1424,261 @@ def _auto_indent(repr_str, indent):
repr_str += ' ' * indent + 'prev_voxel_generator=\n'
repr_str += f'{_auto_indent(repr(self.prev_voxel_generator), 8)})'
return repr_str


@PIPELINES.register_module()
class AffineResize(object):
"""Get the affine transform matrices to the target size.

Different from RandomAffine in MMDetection, this class can calculate
ZCMax marked this conversation as resolved.
Show resolved Hide resolved
the affine transform matrices while resizing the input image to a fixed
size. The affine transform matrices include:
1) matrix transforming original image to the network input image
size.
2) matrix transforming original image to the network output feature
map size.

Args:
img_scale (tuple): Images scales for resizing.
down_ratio (int): The down ratio of feature map.
Actually the arg should be >= 1.
bbox_clip_border (bool, optional): Whether clip the objects
outside the border of the image. Defaults to True.
"""

def __init__(self, img_scale, down_ratio, bbox_clip_border=True):

self.img_scale = img_scale
self.down_ratio = down_ratio
self.bbox_clip_border = bbox_clip_border

def __call__(self, results):
"""Call function to do affine transform to input image and labels.

Args:
results (dict): Result dict from loading pipeline.

Returns:
dict: Results after affine resize, 'affine_aug', 'trans_mat'
keys are added in the result dict.
"""
# Without passing RandomShiftScale before AffineResize
if 'center' not in results:
ZCMax marked this conversation as resolved.
Show resolved Hide resolved
img = results['img']
height, width = img.shape[:2]
center = np.array([width / 2, height / 2], dtype=np.float32)
size = np.array([width, height], dtype=np.float32)
results['affine_aug'] = False
else: # Passing RandomShiftScale before AffineResize
ZCMax marked this conversation as resolved.
Show resolved Hide resolved
img = results['img']
center = results['center']
size = results['size']

trans_affine = self._get_transform_matrix(center, size, self.img_scale)

img = cv2.warpAffine(img, trans_affine[:2, :], self.img_scale)

if isinstance(self.down_ratio, tuple):
trans_mat = [
self._get_transform_matrix(
center, size,
(self.img_scale[0] // ratio, self.img_scale[1] // ratio))
for ratio in self.down_ratio
] # (3, 3)
else:
trans_mat = self._get_transform_matrix(
center, size, (self.img_scale[0] // self.down_ratio,
self.img_scale[1] // self.down_ratio))

results['img'] = img
results['img_shape'] = img.shape
results['pad_shape'] = img.shape
results['trans_mat'] = trans_mat

self._affine_bboxes(results, trans_affine)

if 'centers2d' in results:
centers2d = self._affine_transform(results['centers2d'],
trans_affine)
valid_index = (centers2d[:, 0] >
0) & (centers2d[:, 0] <
self.img_scale[0]) & (centers2d[:, 1] > 0) & (
centers2d[:, 1] < self.img_scale[1])
results['centers2d'] = centers2d[valid_index]

for key in results.get('bbox_fields', []):
if key in ['gt_bboxes']:
results[key] = results[key][valid_index]
if 'gt_labels' in results:
results['gt_labels'] = results['gt_labels'][
valid_index]
if 'gt_masks' in results:
raise NotImplementedError(
'AffineResize only supports bbox.')

for key in results.get('bbox3d_fields', []):
if key in ['gt_bboxes_3d']:
results[key].tensor = results[key].tensor[valid_index]
if 'gt_labels_3d' in results:
results['gt_labels_3d'] = results['gt_labels_3d'][
valid_index]

results['depths'] = results['depths'][valid_index]

return results

def _affine_bboxes(self, results, matrix):
"""Affine transform bboxes to input image.

Args:
results (dict): Result dict from loading pipeline.
matrix (np.ndarray): Matrix transforming original
image to the network input image size.
shape: (3, 3)
"""

for key in results.get('bbox_fields', []):
bboxes = results[key]
bboxes[:, :2] = self._affine_transform(bboxes[:, :2], matrix)
bboxes[:, 2:] = self._affine_transform(bboxes[:, 2:], matrix)
if self.bbox_clip_border:
bboxes[:,
[0, 2]] = bboxes[:,
[0, 2]].clip(0, self.img_scale[0] - 1)
bboxes[:,
[1, 3]] = bboxes[:,
[1, 3]].clip(0, self.img_scale[1] - 1)
results[key] = bboxes

def _affine_transform(self, points, matrix):
"""Affine transform bbox points to input iamge.

Args:
points (np.ndarray): Points to be transformed.
ZCMax marked this conversation as resolved.
Show resolved Hide resolved
shape: (N, 2)
matrix (np.ndarray): Affine transform matrix.
shape: (3, 3)

Returns:
np.ndarray: Transformed points.
"""
num_points = points.shape[0]
hom_points_2d = np.concatenate((points, np.ones((num_points, 1))),
axis=1)
hom_points_2d = hom_points_2d.T
affined_points = np.matmul(matrix, hom_points_2d).T
return affined_points[:, :2]

def _get_transform_matrix(self, center, scale, output_scale):
"""Get affine transform matrix.

Args:
center (tuple): Center of current image.
scale (tuple): Scale of current image.
output_scale (tuple): The transform target image scales.
ZCMax marked this conversation as resolved.
Show resolved Hide resolved

Returns:
np.ndarray: Affine transform matrix.
"""
# TODO: further add rot and shift here.
src_w = scale[0]
dst_w = output_scale[0]
dst_h = output_scale[1]

src_dir = np.array([0, src_w * -0.5])
dst_dir = np.array([0, dst_w * -0.5])

src = np.zeros((3, 2), dtype=np.float32)
dst = np.zeros((3, 2), dtype=np.float32)
src[0, :] = center
src[1, :] = center + src_dir
dst[0, :] = np.array([dst_w * 0.5, dst_h * 0.5])
dst[1, :] = np.array([dst_w * 0.5, dst_h * 0.5]) + dst_dir

src[2, :] = self._get_ref_point(src[0, :], src[1, :])
dst[2, :] = self._get_ref_point(dst[0, :], dst[1, :])

get_matrix = cv2.getAffineTransform(src, dst)

matrix = np.concatenate((get_matrix, [[0., 0., 1.]]))

return matrix.astype(np.float32)

def _get_ref_point(self, ref_point1, ref_point2):
"""Get reference point to calculate affine transfrom matrix.

While using opencv to calculate the affine matrix, we need at least
three corresponding points seperately on original image and target
image. Here we use two points to get the the third reference point.
"""
d = ref_point1 - ref_point2
ref_point3 = ref_point2 + np.array([-d[1], d[0]])
return ref_point3

def __repr__(self):
repr_str = self.__class__.__name__
repr_str += f'(img_scale={self.img_scale}, '
repr_str += f'down_ratio={self.down_ratio}) '
return repr_str


@PIPELINES.register_module()
class RandomShiftScale(object):
"""Random shift scale.

Different from the normal shift and scale function, it doesn't
directly shift or scale image. It can record the shift and scale
infos into loading pipelines. It's desgined to be used with
AffineResize together.

Args:
shift_scale (tuple): Shift and scale range.
ZCMax marked this conversation as resolved.
Show resolved Hide resolved
aug_prob (float): The shifting and scaling probability.
"""

def __init__(self, shift_scale, aug_prob):

self.shift_scale = shift_scale
self.aug_prob = aug_prob

def __call__(self, results):
"""Call function to record random shift and scale infos.

Args:
results (dict): Result dict from loading pipeline.

Returns:
dict: Results after random shift and scale, 'center', 'size'
and 'affine_aug' keys are added in the result dict.
"""
img = results['img']

height, width = img.shape[:2]

center = np.array([width / 2, height / 2], dtype=np.float32)
size = np.array([width, height], dtype=np.float32)

if random.random() < self.aug_prob:
shift, scale = self.shift_scale[0], self.shift_scale[1]

shift_ranges = np.arange(-shift, shift + 0.1, 0.1)
center[0] += size[0] * random.choice(shift_ranges)
center[1] += size[1] * random.choice(shift_ranges)
scale_ranges = np.arange(1 - scale, 1 + scale + 0.1, 0.1)
size *= random.choice(scale_ranges)

results['center'] = center
results['size'] = size
results['affine_aug'] = True
else:
results['center'] = center
results['size'] = size
ZCMax marked this conversation as resolved.
Show resolved Hide resolved
results['affine_aug'] = False

return results

def __repr__(self):
repr_str = self.__class__.__name__
repr_str += f'(shift_scale={self.shift_scale}, '
repr_str += f'aug_prob={self.aug_prob}) '
return repr_str
Loading