Skip to content
Snippets Groups Projects
Unverified Commit 915ffe8b authored by Wenwei Zhang's avatar Wenwei Zhang Committed by GitHub
Browse files

Support GitHub action (#4)

* Support github action:

* fix docs package

* reduce action items

* Update cuda arch

* Set cuda arch

* Add information

* add cocotools in installation

* skip gpu

* remove duplicated module

* Clean ci

* Update docstring requirements
parent 5d1cbe77
Branches
Tags
No related merge requests found
...@@ -25,7 +25,7 @@ jobs: ...@@ -25,7 +25,7 @@ jobs:
- name: Format python codes with yapf - name: Format python codes with yapf
run: yapf -r -d mmdet3d/ tests/ examples/ run: yapf -r -d mmdet3d/ tests/ examples/
- name: Check docstring - name: Check docstring
run: interrogate -v --ignore-init-method --ignore-module --ignore-nested-functions --exclude mmdet3d/ops --ignore-regex "__repr__" --fail-under 80 mmdet3d run: interrogate -v --ignore-init-method --ignore-module --ignore-nested-functions --exclude mmdet3d/ops --ignore-regex "__repr__" --fail-under 95 mmdet3d
build: build:
env: env:
...@@ -33,23 +33,19 @@ jobs: ...@@ -33,23 +33,19 @@ jobs:
CUDA_SHORT: 10.1 CUDA_SHORT: 10.1
UBUNTU_VERSION: ubuntu1804 UBUNTU_VERSION: ubuntu1804
FORCE_CUDA: 1 FORCE_CUDA: 1
MMCV_CUDA_ARGS: -gencode=arch=compute_61,code=sm_61 CUDA_ARCH: ${{matrix.cuda_arch}}
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
python-version: [3.6, 3.7] python-version: [3.6, 3.7]
torch: [1.3.0+cpu, 1.5.0+cpu] torch: [1.3.0, 1.5.0]
include: include:
- torch: 1.3.0+cpu - torch: 1.3.0
torchvision: 0.4.2+cpu torchvision: 0.4.2
- torch: 1.5.0+cpu cuda_arch: "6.0"
torchvision: 0.6.0+cpu - torch: 1.5.0
- torch: 1.5.0+cpu torchvision: 0.6.0
torchvision: 0.6.0+cpu cuda_arch: "7.0"
python-version: 3.8
- torch: 1.5.0+cu101
torchvision: 0.6.0+cu101
python-version: 3.7
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
...@@ -58,7 +54,6 @@ jobs: ...@@ -58,7 +54,6 @@ jobs:
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: Install CUDA - name: Install CUDA
if: ${{matrix.torch == '1.5.0+cu101'}}
run: | run: |
export INSTALLER=cuda-repo-${UBUNTU_VERSION}_${CUDA}_amd64.deb export INSTALLER=cuda-repo-${UBUNTU_VERSION}_${CUDA}_amd64.deb
wget http://developer.download.nvidia.com/compute/cuda/repos/${UBUNTU_VERSION}/x86_64/${INSTALLER} wget http://developer.download.nvidia.com/compute/cuda/repos/${UBUNTU_VERSION}/x86_64/${INSTALLER}
...@@ -73,16 +68,21 @@ jobs: ...@@ -73,16 +68,21 @@ jobs:
export PATH=${CUDA_HOME}/bin:${PATH} export PATH=${CUDA_HOME}/bin:${PATH}
sudo apt-get install -y ninja-build sudo apt-get install -y ninja-build
- name: Install Pillow - name: Install Pillow
if: ${{matrix.torchvision == '0.4.2+cpu'}}
run: pip install Pillow==6.2.2 run: pip install Pillow==6.2.2
if: ${{matrix.torchvision < 0.5}}
- name: Install PyTorch - name: Install PyTorch
run: pip install torch==${{matrix.torch}} torchvision==${{matrix.torchvision}} -f https://download.pytorch.org/whl/torch_stable.html run: pip install torch==${{matrix.torch}} torchvision==${{matrix.torchvision}} -f https://download.pytorch.org/whl/torch_stable.html
- name: Install mmdet3d dependencies - name: Install mmdet3d dependencies
run: | run: |
pip install mmcv==1.0rc0+torch${{matrix.torch}} -f https://openmmlab.oss-accelerate.aliyuncs.com/mmcv/dist/index.html pip install -q "git+https://github.com/open-mmlab/cocoapi.git#subdirectory=pycocotools"
pip install mmcv-full==latest+torch${{matrix.torch}}+cu101 -f https://openmmlab.oss-accelerate.aliyuncs.com/mmcv/dist/index.html
pip install -q git+https://github.com/open-mmlab/mmdetection.git
pip install -r requirements.txt pip install -r requirements.txt
- name: Build and install - name: Build and install
run: rm -rf .eggs && pip install -e . run: |
rm -rf .eggs
python setup.py check -m -s
TORCH_CUDA_ARCH_LIST=${CUDA_ARCH} python setup.py build_ext --inplace
- name: Run unittests and generate coverage report - name: Run unittests and generate coverage report
run: | run: |
coverage run --branch --source mmdet3d -m pytest tests/ coverage run --branch --source mmdet3d -m pytest tests/
......
variables:
PYTORCH_IMAGE: registry.sensetime.com/eig-research/pytorch:1.3.1-cuda10.1-cudnn7-devel
stages:
- linting
- test
- deploy
before_script:
- echo $PATH
- gcc --version
- nvcc --version
- python --version
- pip --version
- python -c "import torch; print(torch.__version__)"
linting:
image: $PYTORCH_IMAGE
stage: linting
script:
- pip install flake8==3.7.9 yapf isort
- flake8 .
- isort --check-only --diff mmdet3d/ tools/ tests/
- yapf -r -d mmdet3d/ tools/ tests/ configs/
.test_template: &test_template_def
stage: test
script:
- echo "Start building..."
- pip install -q "git+https://github.com/open-mmlab/cocoapi.git#subdirectory=pycocotools"
- pip install -q pip install mmcv==1.0rc0+torch1.3.0+cu101 -f https://openmmlab.oss-accelerate.aliyuncs.com/mmcv/dist/index.html
- pip install -q git+https://github.com/open-mmlab/mmdetection.git
- python -c "import mmdet; print(mmdet.__version__)"
- pip install -e .[all]
- python -c "import mmdet3d; print(mmdet3d.__version__)"
- echo "Start testing..."
- coverage run --branch --source mmdet3d -m pytest tests/
- coverage report -m
- interrogate -v --ignore-init-method --ignore-module --ignore-nested-functions --exclude mmdet3d/ops --ignore-regex "__repr__" --fail-under 80 mmdet3d
test:pytorch1.3-cuda10:
image: $PYTORCH_IMAGE
<<: *test_template_def
pages:
image: $PYTORCH_IMAGE
stage: deploy
script:
- pip install numba==0.48.0
- pip install sphinx sphinx_rtd_theme recommonmark sphinx_markdown_tables m2r
- cd docs
- make html
- cd ..
- mkdir -p ./public
- cp -r docs/_build/html/* ./public
- ls ./public
artifacts:
paths:
- public
only:
- master
...@@ -199,10 +199,13 @@ if __name__ == '__main__': ...@@ -199,10 +199,13 @@ if __name__ == '__main__':
setup( setup(
name='mmdet3d', name='mmdet3d',
version=get_version(), version=get_version(),
description='3D Detection Toolbox', description=("OpenMMLab's next-generation platform"
'for general 3D object detection.'),
long_description=readme(), long_description=readme(),
author='OpenMMLab',
author_email='zwwdev@gmail.com',
keywords='computer vision, 3D object detection', keywords='computer vision, 3D object detection',
url='https://github.com/ZwwWayne/mmdetection3d', url='https://github.com/open-mmlab/mmdetection3d',
packages=find_packages(exclude=('configs', 'tools', 'demo')), packages=find_packages(exclude=('configs', 'tools', 'demo')),
package_data={'mmdet3d.ops': ['*/*.so']}, package_data={'mmdet3d.ops': ['*/*.so']},
classifiers=[ classifiers=[
...@@ -210,7 +213,6 @@ if __name__ == '__main__': ...@@ -210,7 +213,6 @@ if __name__ == '__main__':
'License :: OSI Approved :: Apache Software License', 'License :: OSI Approved :: Apache Software License',
'Operating System :: OS Independent', 'Operating System :: OS Independent',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.7',
], ],
......
from os.path import dirname, exists, join, relpath from os.path import dirname, exists, join, relpath
from mmdet.core import BitmapMasks, PolygonMasks
def _get_config_directory(): def _get_config_directory():
"""Find the predefined detector config directory.""" """Find the predefined detector config directory."""
...@@ -101,139 +99,6 @@ def test_config_build_pipeline(): ...@@ -101,139 +99,6 @@ def test_config_build_pipeline():
assert test_pipeline is not None assert test_pipeline is not None
def test_config_data_pipeline():
"""Test whether the data pipeline is valid and can process corner cases.
CommandLine:
xdoctest -m tests/test_config.py test_config_build_data_pipeline
"""
import numpy as np
from mmcv import Config
from mmdet3d.datasets.pipelines import Compose
config_dpath = _get_config_directory()
print('Found config_dpath = {!r}'.format(config_dpath))
# Only tests a representative subset of configurations
config_names = [
'mvxnet/faster_rcnn_r50_fpn_caffe_2x8_1x_nus.py',
'mvxnet/'
'faster_rcnn_r50_fpn_caffe_1x_kitti-2d-3class_coco-3x-pretrain.py',
]
def dummy_masks(h, w, num_obj=3, mode='bitmap'):
assert mode in ('polygon', 'bitmap')
if mode == 'bitmap':
masks = np.random.randint(0, 2, (num_obj, h, w), dtype=np.uint8)
masks = BitmapMasks(masks, h, w)
else:
masks = []
for i in range(num_obj):
masks.append([])
masks[-1].append(
np.random.uniform(0, min(h - 1, w - 1), (8 + 4 * i, )))
masks[-1].append(
np.random.uniform(0, min(h - 1, w - 1), (10 + 4 * i, )))
masks = PolygonMasks(masks, h, w)
return masks
print('Using {} config files'.format(len(config_names)))
for config_fname in config_names:
config_fpath = join(config_dpath, config_fname)
config_mod = Config.fromfile(config_fpath)
# remove loading pipeline
loading_pipeline = config_mod.train_pipeline.pop(0)
loading_ann_pipeline = config_mod.train_pipeline.pop(0)
config_mod.test_pipeline.pop(0)
train_pipeline = Compose(config_mod.train_pipeline)
test_pipeline = Compose(config_mod.test_pipeline)
print(
'Building data pipeline, config_fpath = {!r}'.format(config_fpath))
print('Test training data pipeline: \n{!r}'.format(train_pipeline))
img = np.random.randint(0, 255, size=(888, 666, 3), dtype=np.uint8)
if loading_pipeline.get('to_float32', False):
img = img.astype(np.float32)
mode = 'bitmap' if loading_ann_pipeline.get('poly2mask',
True) else 'polygon'
results = dict(
filename='test_img.png',
ori_filename='test_img.png',
img=img,
img_shape=img.shape,
ori_shape=img.shape,
gt_bboxes=np.array([[35.2, 11.7, 39.7, 15.7]], dtype=np.float32),
gt_labels=np.array([1], dtype=np.int64),
gt_masks=dummy_masks(img.shape[0], img.shape[1], mode=mode),
)
results['img_fields'] = ['img']
results['bbox_fields'] = ['gt_bboxes']
results['mask_fields'] = ['gt_masks']
output_results = train_pipeline(results)
assert output_results is not None
print('Test testing data pipeline: \n{!r}'.format(test_pipeline))
results = dict(
filename='test_img.png',
ori_filename='test_img.png',
img=img,
img_shape=img.shape,
ori_shape=img.shape,
gt_bboxes=np.array([[35.2, 11.7, 39.7, 15.7]], dtype=np.float32),
gt_labels=np.array([1], dtype=np.int64),
gt_masks=dummy_masks(img.shape[0], img.shape[1], mode=mode),
)
results['img_fields'] = ['img']
results['bbox_fields'] = ['gt_bboxes']
results['mask_fields'] = ['gt_masks']
output_results = test_pipeline(results)
assert output_results is not None
# test empty GT
print('Test empty GT with training data pipeline: \n{!r}'.format(
train_pipeline))
results = dict(
filename='test_img.png',
ori_filename='test_img.png',
img=img,
img_shape=img.shape,
ori_shape=img.shape,
gt_bboxes=np.zeros((0, 4), dtype=np.float32),
gt_labels=np.array([], dtype=np.int64),
gt_masks=dummy_masks(
img.shape[0], img.shape[1], num_obj=0, mode=mode),
)
results['img_fields'] = ['img']
results['bbox_fields'] = ['gt_bboxes']
results['mask_fields'] = ['gt_masks']
output_results = train_pipeline(results)
assert output_results is not None
print('Test empty GT with testing data pipeline: \n{!r}'.format(
test_pipeline))
results = dict(
filename='test_img.png',
ori_filename='test_img.png',
img=img,
img_shape=img.shape,
ori_shape=img.shape,
gt_bboxes=np.zeros((0, 4), dtype=np.float32),
gt_labels=np.array([], dtype=np.int64),
gt_masks=dummy_masks(
img.shape[0], img.shape[1], num_obj=0, mode=mode),
)
results['img_fields'] = ['img']
results['bbox_fields'] = ['gt_bboxes']
results['mask_fields'] = ['gt_masks']
output_results = test_pipeline(results)
assert output_results is not None
def _check_roi_head(config, head): def _check_roi_head(config, head):
# check consistency between head_config and roi_head # check consistency between head_config and roi_head
assert config['type'] == head.__class__.__name__ assert config['type'] == head.__class__.__name__
......
import numpy as np import numpy as np
import pytest
import torch import torch
from mmdet3d.core.evaluation.indoor_eval import average_precision, indoor_eval from mmdet3d.core.evaluation.indoor_eval import average_precision, indoor_eval
def test_indoor_eval(): def test_indoor_eval():
if not torch.cuda.is_available():
pytest.skip()
from mmdet3d.core.bbox.structures import Box3DMode, DepthInstance3DBoxes from mmdet3d.core.bbox.structures import Box3DMode, DepthInstance3DBoxes
det_infos = [{ det_infos = [{
'labels_3d': 'labels_3d':
......
import numpy as np import numpy as np
import pytest
import torch import torch
from mmdet3d.datasets import ScanNetDataset from mmdet3d.datasets import ScanNetDataset
...@@ -111,6 +112,8 @@ def test_getitem(): ...@@ -111,6 +112,8 @@ def test_getitem():
def test_evaluate(): def test_evaluate():
if not torch.cuda.is_available():
pytest.skip()
from mmdet3d.core.bbox.structures import DepthInstance3DBoxes from mmdet3d.core.bbox.structures import DepthInstance3DBoxes
root_path = './tests/data/scannet' root_path = './tests/data/scannet'
ann_file = './tests/data/scannet/scannet_infos.pkl' ann_file = './tests/data/scannet/scannet_infos.pkl'
......
import numpy as np import numpy as np
import pytest
import torch import torch
from mmdet3d.datasets import SUNRGBDDataset from mmdet3d.datasets import SUNRGBDDataset
...@@ -95,6 +96,8 @@ def test_getitem(): ...@@ -95,6 +96,8 @@ def test_getitem():
def test_evaluate(): def test_evaluate():
if not torch.cuda.is_available():
pytest.skip()
from mmdet3d.core.bbox.structures import DepthInstance3DBoxes from mmdet3d.core.bbox.structures import DepthInstance3DBoxes
root_path = './tests/data/sunrgbd' root_path = './tests/data/sunrgbd'
ann_file = './tests/data/sunrgbd/sunrgbd_infos.pkl' ann_file = './tests/data/sunrgbd/sunrgbd_infos.pkl'
......
...@@ -48,10 +48,6 @@ def _get_detector_cfg(fname): ...@@ -48,10 +48,6 @@ def _get_detector_cfg(fname):
return model, train_cfg, test_cfg return model, train_cfg, test_cfg
def test_faster_rcnn_forward():
_test_two_stage_forward('mvxnet/faster_rcnn_r50_fpn_caffe_2x8_1x_nus.py')
def _test_two_stage_forward(cfg_file): def _test_two_stage_forward(cfg_file):
model, train_cfg, test_cfg = _get_detector_cfg(cfg_file) model, train_cfg, test_cfg = _get_detector_cfg(cfg_file)
model['pretrained'] = None model['pretrained'] = None
......
...@@ -34,66 +34,6 @@ def test_remove_points_in_boxes(): ...@@ -34,66 +34,6 @@ def test_remove_points_in_boxes():
assert points.shape == (10, 4) assert points.shape == (10, 4)
def test_object_sample():
db_sampler = mmcv.ConfigDict({
'data_root': './tests/data/kitti/',
'info_path': './tests/data/kitti/kitti_dbinfos_train.pkl',
'rate': 1.0,
'prepare': {
'filter_by_difficulty': [-1],
'filter_by_min_points': {
'Pedestrian': 10
}
},
'classes': ['Pedestrian', 'Cyclist', 'Car'],
'sample_groups': {
'Pedestrian': 6
}
})
object_sample = ObjectSample(db_sampler)
points = np.fromfile(
'./tests/data/kitti/training/velodyne_reduced/000000.bin',
np.float32).reshape(-1, 4)
annos = mmcv.load('./tests/data/kitti/kitti_infos_train.pkl')
info = annos[0]
rect = info['calib']['R0_rect'].astype(np.float32)
Trv2c = info['calib']['Tr_velo_to_cam'].astype(np.float32)
annos = info['annos']
loc = annos['location']
dims = annos['dimensions']
rots = annos['rotation_y']
gt_names = annos['name']
gt_bboxes_3d = np.concatenate([loc, dims, rots[..., np.newaxis]],
axis=1).astype(np.float32)
gt_bboxes_3d = CameraInstance3DBoxes(gt_bboxes_3d).convert_to(
Box3DMode.LIDAR, np.linalg.inv(rect @ Trv2c))
CLASSES = ('car', 'pedestrian', 'cyclist')
gt_labels = []
for cat in gt_names:
if cat in CLASSES:
gt_labels.append(CLASSES.index(cat))
else:
gt_labels.append(-1)
input_dict = dict(
points=points, gt_bboxes_3d=gt_bboxes_3d, gt_labels_3d=gt_labels)
input_dict = object_sample(input_dict)
points = input_dict['points']
gt_bboxes_3d = input_dict['gt_bboxes_3d']
gt_labels_3d = input_dict['gt_labels_3d']
expected_gt_bboxes_3d = torch.tensor(
[[8.7314, -1.8559, -1.5997, 0.4800, 1.2000, 1.8900, 0.0100],
[8.7314, -1.8559, -1.5997, 0.4800, 1.2000, 1.8900, 0.0100]])
expected_gt_labels_3d = np.array([-1, 0])
repr_str = repr(object_sample)
expected_repr_str = 'ObjectSample'
assert repr_str == expected_repr_str
assert points.shape == (1177, 4)
assert torch.allclose(gt_bboxes_3d.tensor, expected_gt_bboxes_3d)
assert np.all(gt_labels_3d == expected_gt_labels_3d)
def test_object_noise(): def test_object_noise():
np.random.seed(0) np.random.seed(0)
object_noise = ObjectNoise() object_noise = ObjectNoise()
......
...@@ -248,6 +248,8 @@ def test_three_interpolate(): ...@@ -248,6 +248,8 @@ def test_three_interpolate():
def test_three_nn(): def test_three_nn():
if not torch.cuda.is_available():
pytest.skip()
known = torch.tensor([[[-1.8373, 3.5605, known = torch.tensor([[[-1.8373, 3.5605,
-0.7867], [0.7615, 2.9420, 0.2314], -0.7867], [0.7615, 2.9420, 0.2314],
[-0.6503, 3.6637, -1.0622], [-0.6503, 3.6637, -1.0622],
......
import pytest
import torch import torch
from mmdet3d.core.bbox.assigners import MaxIoUAssigner from mmdet3d.core.bbox.assigners import MaxIoUAssigner
...@@ -5,6 +6,8 @@ from mmdet3d.core.bbox.samplers import IoUNegPiecewiseSampler ...@@ -5,6 +6,8 @@ from mmdet3d.core.bbox.samplers import IoUNegPiecewiseSampler
def test_iou_piecewise_sampler(): def test_iou_piecewise_sampler():
if not torch.cuda.is_available():
pytest.skip()
assigner = MaxIoUAssigner( assigner = MaxIoUAssigner(
pos_iou_thr=0.55, pos_iou_thr=0.55,
neg_iou_thr=0.55, neg_iou_thr=0.55,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment