Unverified Commit 76e351a7 authored by Wenwei Zhang's avatar Wenwei Zhang Committed by GitHub
Browse files

Release v1.0.0rc2

parents 5111eda8 4422eaab
...@@ -8,8 +8,7 @@ import numpy as np ...@@ -8,8 +8,7 @@ import numpy as np
from mmdet3d.core.bbox import box_np_ops from mmdet3d.core.bbox import box_np_ops
from mmdet3d.datasets.pipelines import data_augment_utils from mmdet3d.datasets.pipelines import data_augment_utils
from mmdet.datasets import PIPELINES from ..builder import OBJECTSAMPLERS, PIPELINES
from ..builder import OBJECTSAMPLERS
class BatchSampler: class BatchSampler:
......
...@@ -4,10 +4,8 @@ from mmcv.parallel import DataContainer as DC ...@@ -4,10 +4,8 @@ from mmcv.parallel import DataContainer as DC
from mmdet3d.core.bbox import BaseInstance3DBoxes from mmdet3d.core.bbox import BaseInstance3DBoxes
from mmdet3d.core.points import BasePoints from mmdet3d.core.points import BasePoints
from mmdet.datasets.builder import PIPELINES
from mmdet.datasets.pipelines import to_tensor from mmdet.datasets.pipelines import to_tensor
from ..builder import PIPELINES
PIPELINES._module_dict.pop('DefaultFormatBundle')
@PIPELINES.register_module() @PIPELINES.register_module()
......
...@@ -3,8 +3,8 @@ import mmcv ...@@ -3,8 +3,8 @@ import mmcv
import numpy as np import numpy as np
from mmdet3d.core.points import BasePoints, get_points_type from mmdet3d.core.points import BasePoints, get_points_type
from mmdet.datasets.builder import PIPELINES
from mmdet.datasets.pipelines import LoadAnnotations, LoadImageFromFile from mmdet.datasets.pipelines import LoadAnnotations, LoadImageFromFile
from ..builder import PIPELINES
@PIPELINES.register_module() @PIPELINES.register_module()
......
...@@ -4,8 +4,115 @@ from copy import deepcopy ...@@ -4,8 +4,115 @@ from copy import deepcopy
import mmcv import mmcv
from mmdet.datasets.builder import PIPELINES from ..builder import PIPELINES
from mmdet.datasets.pipelines import Compose from .compose import Compose
@PIPELINES.register_module()
class MultiScaleFlipAug:
"""Test-time augmentation with multiple scales and flipping. An example
configuration is as followed:
.. code-block::
img_scale=[(1333, 400), (1333, 800)],
flip=True,
transforms=[
dict(type='Resize', keep_ratio=True),
dict(type='RandomFlip'),
dict(type='Normalize', **img_norm_cfg),
dict(type='Pad', size_divisor=32),
dict(type='ImageToTensor', keys=['img']),
dict(type='Collect', keys=['img']),
]
After MultiScaleFLipAug with above configuration, the results are wrapped
into lists of the same length as followed:
.. code-block::
dict(
img=[...],
img_shape=[...],
scale=[(1333, 400), (1333, 400), (1333, 800), (1333, 800)]
flip=[False, True, False, True]
...
)
Args:
transforms (list[dict]): Transforms to apply in each augmentation.
img_scale (tuple | list[tuple] | None): Images scales for resizing.
scale_factor (float | list[float] | None): Scale factors for resizing.
flip (bool): Whether apply flip augmentation. Default: False.
flip_direction (str | list[str]): Flip augmentation directions,
options are "horizontal", "vertical" and "diagonal". If
flip_direction is a list, multiple flip augmentations will be
applied. It has no effect when flip == False. Default:
"horizontal".
"""
def __init__(self,
transforms,
img_scale=None,
scale_factor=None,
flip=False,
flip_direction='horizontal'):
self.transforms = Compose(transforms)
assert (img_scale is None) ^ (scale_factor is None), (
'Must have but only one variable can be set')
if img_scale is not None:
self.img_scale = img_scale if isinstance(img_scale,
list) else [img_scale]
self.scale_key = 'scale'
assert mmcv.is_list_of(self.img_scale, tuple)
else:
self.img_scale = scale_factor if isinstance(
scale_factor, list) else [scale_factor]
self.scale_key = 'scale_factor'
self.flip = flip
self.flip_direction = flip_direction if isinstance(
flip_direction, list) else [flip_direction]
assert mmcv.is_list_of(self.flip_direction, str)
if not self.flip and self.flip_direction != ['horizontal']:
warnings.warn(
'flip_direction has no effect when flip is set to False')
if (self.flip
and not any([t['type'] == 'RandomFlip' for t in transforms])):
warnings.warn(
'flip has no effect when RandomFlip is not in transforms')
def __call__(self, results):
"""Call function to apply test time augment transforms on results.
Args:
results (dict): Result dict contains the data to transform.
Returns:
dict[str: list]: The augmented data, where each value is wrapped
into a list.
"""
aug_data = []
flip_args = [(False, None)]
if self.flip:
flip_args += [(True, direction)
for direction in self.flip_direction]
for scale in self.img_scale:
for flip, direction in flip_args:
_results = results.copy()
_results[self.scale_key] = scale
_results['flip'] = flip
_results['flip_direction'] = direction
data = self.transforms(_results)
aug_data.append(data)
# list of dict to dict of list
aug_data_dict = {key: [] for key in aug_data[0]}
for data in aug_data:
for key, val in data.items():
aug_data_dict[key].append(val)
return aug_data_dict
def __repr__(self):
repr_str = self.__class__.__name__
repr_str += f'(transforms={self.transforms}, '
repr_str += f'img_scale={self.img_scale}, flip={self.flip}, '
repr_str += f'flip_direction={self.flip_direction})'
return repr_str
@PIPELINES.register_module() @PIPELINES.register_module()
......
...@@ -10,9 +10,8 @@ from mmcv.utils import build_from_cfg ...@@ -10,9 +10,8 @@ from mmcv.utils import build_from_cfg
from mmdet3d.core import VoxelGenerator from mmdet3d.core import VoxelGenerator
from mmdet3d.core.bbox import (CameraInstance3DBoxes, DepthInstance3DBoxes, from mmdet3d.core.bbox import (CameraInstance3DBoxes, DepthInstance3DBoxes,
LiDARInstance3DBoxes, box_np_ops) LiDARInstance3DBoxes, box_np_ops)
from mmdet.datasets.builder import PIPELINES
from mmdet.datasets.pipelines import RandomFlip from mmdet.datasets.pipelines import RandomFlip
from ..builder import OBJECTSAMPLERS from ..builder import OBJECTSAMPLERS, PIPELINES
from .data_augment_utils import noise_per_object_v3_ from .data_augment_utils import noise_per_object_v3_
......
...@@ -5,8 +5,8 @@ import numpy as np ...@@ -5,8 +5,8 @@ import numpy as np
from mmdet3d.core import show_seg_result from mmdet3d.core import show_seg_result
from mmdet3d.core.bbox import DepthInstance3DBoxes from mmdet3d.core.bbox import DepthInstance3DBoxes
from mmdet.datasets import DATASETS
from mmseg.datasets import DATASETS as SEG_DATASETS from mmseg.datasets import DATASETS as SEG_DATASETS
from .builder import DATASETS
from .custom_3d import Custom3DDataset from .custom_3d import Custom3DDataset
from .custom_3d_seg import Custom3DSegDataset from .custom_3d_seg import Custom3DSegDataset
from .pipelines import Compose from .pipelines import Compose
......
...@@ -7,8 +7,8 @@ import numpy as np ...@@ -7,8 +7,8 @@ import numpy as np
from mmdet3d.core import instance_seg_eval, show_result, show_seg_result from mmdet3d.core import instance_seg_eval, show_result, show_seg_result
from mmdet3d.core.bbox import DepthInstance3DBoxes from mmdet3d.core.bbox import DepthInstance3DBoxes
from mmdet.datasets import DATASETS
from mmseg.datasets import DATASETS as SEG_DATASETS from mmseg.datasets import DATASETS as SEG_DATASETS
from .builder import DATASETS
from .custom_3d import Custom3DDataset from .custom_3d import Custom3DDataset
from .custom_3d_seg import Custom3DSegDataset from .custom_3d_seg import Custom3DSegDataset
from .pipelines import Compose from .pipelines import Compose
......
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
from os import path as osp from os import path as osp
from mmdet.datasets import DATASETS from .builder import DATASETS
from .custom_3d import Custom3DDataset from .custom_3d import Custom3DDataset
...@@ -60,6 +60,35 @@ class SemanticKITTIDataset(Custom3DDataset): ...@@ -60,6 +60,35 @@ class SemanticKITTIDataset(Custom3DDataset):
filter_empty_gt=filter_empty_gt, filter_empty_gt=filter_empty_gt,
test_mode=test_mode) test_mode=test_mode)
def get_data_info(self, index):
"""Get data info according to the given index.
Args:
index (int): Index of the sample data to get.
Returns:
dict: Data information that will be passed to the data
preprocessing pipelines. It includes the following keys:
- sample_idx (str): Sample index.
- pts_filename (str): Filename of point clouds.
- file_name (str): Filename of point clouds.
- ann_info (dict): Annotation info.
"""
info = self.data_infos[index]
sample_idx = info['point_cloud']['lidar_idx']
pts_filename = osp.join(self.data_root, info['pts_path'])
input_dict = dict(
pts_filename=pts_filename,
sample_idx=sample_idx,
file_name=pts_filename)
if not self.test_mode:
annos = self.get_ann_info(index)
input_dict['ann_info'] = annos
if self.filter_empty_gt and ~(annos['gt_labels_3d'] != -1).any():
return None
return input_dict
def get_ann_info(self, index): def get_ann_info(self, index):
"""Get annotation info according to the given index. """Get annotation info according to the given index.
......
...@@ -7,7 +7,7 @@ import numpy as np ...@@ -7,7 +7,7 @@ import numpy as np
from mmdet3d.core import show_multi_modality_result, show_result from mmdet3d.core import show_multi_modality_result, show_result
from mmdet3d.core.bbox import DepthInstance3DBoxes from mmdet3d.core.bbox import DepthInstance3DBoxes
from mmdet.core import eval_map from mmdet.core import eval_map
from mmdet.datasets import DATASETS from .builder import DATASETS
from .custom_3d import Custom3DDataset from .custom_3d import Custom3DDataset
from .pipelines import Compose from .pipelines import Compose
......
...@@ -10,9 +10,9 @@ from mmdet3d.datasets.pipelines import (Collect3D, DefaultFormatBundle3D, ...@@ -10,9 +10,9 @@ from mmdet3d.datasets.pipelines import (Collect3D, DefaultFormatBundle3D,
LoadPointsFromMultiSweeps, LoadPointsFromMultiSweeps,
MultiScaleFlipAug3D, MultiScaleFlipAug3D,
PointSegClassMapping) PointSegClassMapping)
# yapf: enable
from mmdet.datasets.builder import PIPELINES
from mmdet.datasets.pipelines import LoadImageFromFile, MultiScaleFlipAug from mmdet.datasets.pipelines import LoadImageFromFile, MultiScaleFlipAug
# yapf: enable
from .builder import PIPELINES
def is_loading_function(transform): def is_loading_function(transform):
......
...@@ -8,8 +8,8 @@ import numpy as np ...@@ -8,8 +8,8 @@ import numpy as np
import torch import torch
from mmcv.utils import print_log from mmcv.utils import print_log
from mmdet.datasets import DATASETS
from ..core.bbox import Box3DMode, points_cam2img from ..core.bbox import Box3DMode, points_cam2img
from .builder import DATASETS
from .kitti_dataset import KittiDataset from .kitti_dataset import KittiDataset
......
# Copyright (c) OpenMMLab. All rights reserved. # Copyright (c) OpenMMLab. All rights reserved.
from .backbones import * # noqa: F401,F403 from .backbones import * # noqa: F401,F403
from .builder import (FUSION_LAYERS, MIDDLE_ENCODERS, VOXEL_ENCODERS, from .builder import (BACKBONES, DETECTORS, FUSION_LAYERS, HEADS, LOSSES,
build_backbone, build_detector, build_fusion_layer, MIDDLE_ENCODERS, NECKS, ROI_EXTRACTORS, SEGMENTORS,
build_head, build_loss, build_middle_encoder, SHARED_HEADS, VOXEL_ENCODERS, build_backbone,
build_model, build_neck, build_roi_extractor, build_detector, build_fusion_layer, build_head,
build_shared_head, build_voxel_encoder) build_loss, build_middle_encoder, build_model,
build_neck, build_roi_extractor, build_shared_head,
build_voxel_encoder)
from .decode_heads import * # noqa: F401,F403 from .decode_heads import * # noqa: F401,F403
from .dense_heads import * # noqa: F401,F403 from .dense_heads import * # noqa: F401,F403
from .detectors import * # noqa: F401,F403 from .detectors import * # noqa: F401,F403
...@@ -18,8 +20,10 @@ from .segmentors import * # noqa: F401,F403 ...@@ -18,8 +20,10 @@ from .segmentors import * # noqa: F401,F403
from .voxel_encoders import * # noqa: F401,F403 from .voxel_encoders import * # noqa: F401,F403
__all__ = [ __all__ = [
'VOXEL_ENCODERS', 'MIDDLE_ENCODERS', 'FUSION_LAYERS', 'build_backbone', 'BACKBONES', 'NECKS', 'ROI_EXTRACTORS', 'SHARED_HEADS', 'HEADS', 'LOSSES',
'build_neck', 'build_roi_extractor', 'build_shared_head', 'build_head', 'DETECTORS', 'SEGMENTORS', 'VOXEL_ENCODERS', 'MIDDLE_ENCODERS',
'build_loss', 'build_detector', 'build_fusion_layer', 'build_model', 'FUSION_LAYERS', 'build_backbone', 'build_neck', 'build_roi_extractor',
'build_middle_encoder', 'build_voxel_encoder' 'build_shared_head', 'build_head', 'build_loss', 'build_detector',
'build_fusion_layer', 'build_model', 'build_middle_encoder',
'build_voxel_encoder'
] ]
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
from mmdet.models.backbones import SSDVGG, HRNet, ResNet, ResNetV1d, ResNeXt from mmdet.models.backbones import SSDVGG, HRNet, ResNet, ResNetV1d, ResNeXt
from .dgcnn import DGCNNBackbone from .dgcnn import DGCNNBackbone
from .dla import DLANet from .dla import DLANet
from .mink_resnet import MinkResNet
from .multi_backbone import MultiBackbone from .multi_backbone import MultiBackbone
from .nostem_regnet import NoStemRegNet from .nostem_regnet import NoStemRegNet
from .pointnet2_sa_msg import PointNet2SAMSG from .pointnet2_sa_msg import PointNet2SAMSG
...@@ -11,5 +12,5 @@ from .second import SECOND ...@@ -11,5 +12,5 @@ from .second import SECOND
__all__ = [ __all__ = [
'ResNet', 'ResNetV1d', 'ResNeXt', 'SSDVGG', 'HRNet', 'NoStemRegNet', 'ResNet', 'ResNetV1d', 'ResNeXt', 'SSDVGG', 'HRNet', 'NoStemRegNet',
'SECOND', 'DGCNNBackbone', 'PointNet2SASSG', 'PointNet2SAMSG', 'SECOND', 'DGCNNBackbone', 'PointNet2SASSG', 'PointNet2SAMSG',
'MultiBackbone', 'DLANet' 'MultiBackbone', 'DLANet', 'MinkResNet'
] ]
...@@ -3,7 +3,7 @@ from mmcv.runner import BaseModule, auto_fp16 ...@@ -3,7 +3,7 @@ from mmcv.runner import BaseModule, auto_fp16
from torch import nn as nn from torch import nn as nn
from mmdet3d.ops import DGCNNFAModule, DGCNNGFModule from mmdet3d.ops import DGCNNFAModule, DGCNNGFModule
from mmdet.models import BACKBONES from ..builder import BACKBONES
@BACKBONES.register_module() @BACKBONES.register_module()
......
...@@ -6,7 +6,7 @@ from mmcv.cnn import build_conv_layer, build_norm_layer ...@@ -6,7 +6,7 @@ from mmcv.cnn import build_conv_layer, build_norm_layer
from mmcv.runner import BaseModule from mmcv.runner import BaseModule
from torch import nn from torch import nn
from mmdet.models.builder import BACKBONES from ..builder import BACKBONES
def dla_build_norm_layer(cfg, num_features): def dla_build_norm_layer(cfg, num_features):
......
# Copyright (c) OpenMMLab. All rights reserved.
# Follow https://github.com/NVIDIA/MinkowskiEngine/blob/master/examples/resnet.py # noqa
# and mmcv.cnn.ResNet
try:
import MinkowskiEngine as ME
from MinkowskiEngine.modules.resnet_block import BasicBlock, Bottleneck
except ImportError:
import warnings
warnings.warn(
'Please follow `getting_started.md` to install MinkowskiEngine.`')
# blocks are used in the static part of MinkResNet
BasicBlock, Bottleneck = None, None
import torch.nn as nn
from mmdet3d.models.builder import BACKBONES
@BACKBONES.register_module()
class MinkResNet(nn.Module):
r"""Minkowski ResNet backbone. See `4D Spatio-Temporal ConvNets
<https://arxiv.org/abs/1904.08755>`_ for more details.
Args:
depth (int): Depth of resnet, from {18, 34, 50, 101, 152}.
in_channels (ont): Number of input channels, 3 for RGB.
num_stages (int, optional): Resnet stages. Default: 4.
pool (bool, optional): Add max pooling after first conv if True.
Default: True.
"""
arch_settings = {
18: (BasicBlock, (2, 2, 2, 2)),
34: (BasicBlock, (3, 4, 6, 3)),
50: (Bottleneck, (3, 4, 6, 3)),
101: (Bottleneck, (3, 4, 23, 3)),
152: (Bottleneck, (3, 8, 36, 3))
}
def __init__(self, depth, in_channels, num_stages=4, pool=True):
super(MinkResNet, self).__init__()
if depth not in self.arch_settings:
raise KeyError(f'invalid depth {depth} for resnet')
assert 4 >= num_stages >= 1
block, stage_blocks = self.arch_settings[depth]
stage_blocks = stage_blocks[:num_stages]
self.num_stages = num_stages
self.pool = pool
self.inplanes = 64
self.conv1 = ME.MinkowskiConvolution(
in_channels, self.inplanes, kernel_size=3, stride=2, dimension=3)
# May be BatchNorm is better, but we follow original implementation.
self.norm1 = ME.MinkowskiInstanceNorm(self.inplanes)
self.relu = ME.MinkowskiReLU(inplace=True)
if self.pool:
self.maxpool = ME.MinkowskiMaxPooling(
kernel_size=2, stride=2, dimension=3)
for i, num_blocks in enumerate(stage_blocks):
setattr(
self, f'layer{i}',
self._make_layer(block, 64 * 2**i, stage_blocks[i], stride=2))
def init_weights(self):
for m in self.modules():
if isinstance(m, ME.MinkowskiConvolution):
ME.utils.kaiming_normal_(
m.kernel, mode='fan_out', nonlinearity='relu')
if isinstance(m, ME.MinkowskiBatchNorm):
nn.init.constant_(m.bn.weight, 1)
nn.init.constant_(m.bn.bias, 0)
def _make_layer(self, block, planes, blocks, stride):
downsample = None
if stride != 1 or self.inplanes != planes * block.expansion:
downsample = nn.Sequential(
ME.MinkowskiConvolution(
self.inplanes,
planes * block.expansion,
kernel_size=1,
stride=stride,
dimension=3),
ME.MinkowskiBatchNorm(planes * block.expansion))
layers = []
layers.append(
block(
self.inplanes,
planes,
stride=stride,
downsample=downsample,
dimension=3))
self.inplanes = planes * block.expansion
for i in range(1, blocks):
layers.append(block(self.inplanes, planes, stride=1, dimension=3))
return nn.Sequential(*layers)
def forward(self, x):
"""Forward pass of ResNet.
Args:
x (ME.SparseTensor): Input sparse tensor.
Returns:
list[ME.SparseTensor]: Output sparse tensors.
"""
x = self.conv1(x)
x = self.norm1(x)
x = self.relu(x)
if self.pool:
x = self.maxpool(x)
outs = []
for i in range(self.num_stages):
x = getattr(self, f'layer{i}')(x)
outs.append(x)
return outs
...@@ -7,7 +7,7 @@ from mmcv.cnn import ConvModule ...@@ -7,7 +7,7 @@ from mmcv.cnn import ConvModule
from mmcv.runner import BaseModule, auto_fp16 from mmcv.runner import BaseModule, auto_fp16
from torch import nn as nn from torch import nn as nn
from mmdet.models import BACKBONES, build_backbone from ..builder import BACKBONES, build_backbone
@BACKBONES.register_module() @BACKBONES.register_module()
......
...@@ -5,7 +5,7 @@ from mmcv.runner import auto_fp16 ...@@ -5,7 +5,7 @@ from mmcv.runner import auto_fp16
from torch import nn as nn from torch import nn as nn
from mmdet3d.ops import build_sa_module from mmdet3d.ops import build_sa_module
from mmdet.models import BACKBONES from ..builder import BACKBONES
from .base_pointnet import BasePointNet from .base_pointnet import BasePointNet
......
...@@ -4,7 +4,7 @@ from mmcv.runner import auto_fp16 ...@@ -4,7 +4,7 @@ from mmcv.runner import auto_fp16
from torch import nn as nn from torch import nn as nn
from mmdet3d.ops import PointFPModule, build_sa_module from mmdet3d.ops import PointFPModule, build_sa_module
from mmdet.models import BACKBONES from ..builder import BACKBONES
from .base_pointnet import BasePointNet from .base_pointnet import BasePointNet
......
...@@ -5,7 +5,7 @@ from mmcv.cnn import build_conv_layer, build_norm_layer ...@@ -5,7 +5,7 @@ from mmcv.cnn import build_conv_layer, build_norm_layer
from mmcv.runner import BaseModule from mmcv.runner import BaseModule
from torch import nn as nn from torch import nn as nn
from mmdet.models import BACKBONES from ..builder import BACKBONES
@BACKBONES.register_module() @BACKBONES.register_module()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment