├── .github
└── workflows
│ └── close_stale_issues.yml
├── .gitignore
├── LICENSE
├── M3Net.md
├── README.md
├── data
├── argo2
│ └── ImageSets
│ │ ├── train.txt
│ │ └── val.txt
├── kitti
│ └── ImageSets
│ │ ├── test.txt
│ │ ├── train.txt
│ │ └── val.txt
├── lyft
│ └── ImageSets
│ │ ├── test.txt
│ │ ├── train.txt
│ │ └── val.txt
├── once
│ └── ImageSets
│ │ ├── test.txt
│ │ ├── train.txt
│ │ └── val.txt
└── waymo
│ └── ImageSets
│ ├── train.txt
│ └── val.txt
├── docker
├── Dockerfile
├── README.md
└── cu116.Dockerfile
├── docs
├── CUSTOM_DATASET_TUTORIAL.md
├── DEMO.md
├── GETTING_STARTED.md
├── INSTALL.md
├── changelog.md
├── dataset_vs_model.png
├── demo.png
├── guidelines_of_approaches
│ ├── bevfusion.md
│ └── mppnet.md
├── model_framework.png
├── multiple_models_demo.png
└── open_mmlab.png
├── pcdet
├── __init__.py
├── config.py
├── datasets
│ ├── __init__.py
│ ├── argo2
│ │ ├── __init__.py
│ │ ├── argo2_dataset.py
│ │ └── argo2_utils
│ │ │ ├── constants.py
│ │ │ └── so3.py
│ ├── augmentor
│ │ ├── __init__.py
│ │ ├── augmentor_utils.py
│ │ ├── data_augmentor.py
│ │ └── database_sampler.py
│ ├── custom
│ │ ├── __init__.py
│ │ └── custom_dataset.py
│ ├── dataset.py
│ ├── kitti
│ │ ├── __init__.py
│ │ ├── kitti_dataset.py
│ │ ├── kitti_object_eval_python
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ ├── __init__.py
│ │ │ ├── eval.py
│ │ │ ├── evaluate.py
│ │ │ ├── kitti_common.py
│ │ │ └── rotate_iou.py
│ │ └── kitti_utils.py
│ ├── lyft
│ │ ├── __init__.py
│ │ ├── lyft_dataset.py
│ │ ├── lyft_mAP_eval
│ │ │ ├── __init__.py
│ │ │ └── lyft_eval.py
│ │ └── lyft_utils.py
│ ├── nuscenes
│ │ ├── __init__.py
│ │ ├── nuscenes_dataset.py
│ │ ├── nuscenes_dataset_mtl.py
│ │ └── nuscenes_utils.py
│ ├── once
│ │ ├── __init__.py
│ │ ├── once_dataset.py
│ │ ├── once_eval
│ │ │ ├── eval_utils.py
│ │ │ ├── evaluation.py
│ │ │ └── iou_utils.py
│ │ └── once_toolkits.py
│ ├── pandaset
│ │ ├── __init__.py
│ │ └── pandaset_dataset.py
│ ├── processor
│ │ ├── __init__.py
│ │ ├── data_processor.py
│ │ └── point_feature_encoder.py
│ └── waymo
│ │ ├── __init__.py
│ │ ├── waymo_dataset.py
│ │ ├── waymo_eval.py
│ │ └── waymo_utils.py
├── models
│ ├── __init__.py
│ ├── backbones_2d
│ │ ├── __init__.py
│ │ ├── base_bev_backbone.py
│ │ ├── fuser
│ │ │ ├── __init__.py
│ │ │ └── convfuser.py
│ │ ├── map_to_bev
│ │ │ ├── __init__.py
│ │ │ ├── conv2d_collapse.py
│ │ │ ├── height_compression.py
│ │ │ └── pointpillar_scatter.py
│ │ └── neck
│ │ │ ├── __init__.py
│ │ │ └── lssfpn.py
│ ├── backbones_3d
│ │ ├── __init__.py
│ │ ├── dsvt.py
│ │ ├── focal_sparse_conv
│ │ │ ├── SemanticSeg
│ │ │ │ ├── basic_blocks.py
│ │ │ │ ├── pyramid_ffn.py
│ │ │ │ └── sem_deeplabv3.py
│ │ │ ├── focal_sparse_conv.py
│ │ │ └── focal_sparse_utils.py
│ │ ├── pfe
│ │ │ ├── __init__.py
│ │ │ └── voxel_set_abstraction.py
│ │ ├── pointnet2_backbone.py
│ │ ├── spconv_backbone.py
│ │ ├── spconv_backbone_2d.py
│ │ ├── spconv_backbone_focal.py
│ │ ├── spconv_backbone_voxelnext.py
│ │ ├── spconv_backbone_voxelnext2d.py
│ │ ├── spconv_unet.py
│ │ └── vfe
│ │ │ ├── __init__.py
│ │ │ ├── dynamic_mean_vfe.py
│ │ │ ├── dynamic_pillar_vfe.py
│ │ │ ├── dynamic_voxel_vfe.py
│ │ │ ├── image_vfe.py
│ │ │ ├── image_vfe_modules
│ │ │ ├── __init__.py
│ │ │ ├── f2v
│ │ │ │ ├── __init__.py
│ │ │ │ ├── frustum_grid_generator.py
│ │ │ │ ├── frustum_to_voxel.py
│ │ │ │ └── sampler.py
│ │ │ └── ffn
│ │ │ │ ├── __init__.py
│ │ │ │ ├── ddn
│ │ │ │ ├── __init__.py
│ │ │ │ ├── ddn_deeplabv3.py
│ │ │ │ └── ddn_template.py
│ │ │ │ ├── ddn_loss
│ │ │ │ ├── __init__.py
│ │ │ │ ├── balancer.py
│ │ │ │ └── ddn_loss.py
│ │ │ │ └── depth_ffn.py
│ │ │ ├── mean_vfe.py
│ │ │ ├── pillar_vfe.py
│ │ │ └── vfe_template.py
│ ├── backbones_image
│ │ ├── __init__.py
│ │ ├── img_neck
│ │ │ ├── __init__.py
│ │ │ └── generalized_lss.py
│ │ └── swin.py
│ ├── dense_heads
│ │ ├── __init__.py
│ │ ├── anchor_head_multi.py
│ │ ├── anchor_head_single.py
│ │ ├── anchor_head_template.py
│ │ ├── center_head.py
│ │ ├── m3net_head.py
│ │ ├── point_head_box.py
│ │ ├── point_head_simple.py
│ │ ├── point_head_template.py
│ │ ├── point_intra_part_head.py
│ │ ├── target_assigner
│ │ │ ├── __init__.py
│ │ │ ├── anchor_generator.py
│ │ │ ├── atss_target_assigner.py
│ │ │ ├── axis_aligned_target_assigner.py
│ │ │ └── hungarian_assigner.py
│ │ ├── transfusion_head.py
│ │ └── voxelnext_head.py
│ ├── detectors
│ │ ├── PartA2_net.py
│ │ ├── __init__.py
│ │ ├── bevfusion.py
│ │ ├── caddn.py
│ │ ├── centerpoint.py
│ │ ├── detector3d_template.py
│ │ ├── m3net.py
│ │ ├── mppnet.py
│ │ ├── mppnet_e2e.py
│ │ ├── pillarnet.py
│ │ ├── point_rcnn.py
│ │ ├── pointpillar.py
│ │ ├── pv_rcnn.py
│ │ ├── pv_rcnn_plusplus.py
│ │ ├── second_net.py
│ │ ├── second_net_iou.py
│ │ ├── transfusion.py
│ │ ├── voxel_rcnn.py
│ │ └── voxelnext.py
│ ├── model_utils
│ │ ├── __init__.py
│ │ ├── basic_block_2d.py
│ │ ├── centernet_utils.py
│ │ ├── deform3d_utils.py
│ │ ├── dsvt_utils.py
│ │ ├── lovasz_softmax.py
│ │ ├── m3net_utils.py
│ │ ├── model_nms_utils.py
│ │ ├── mppnet_utils.py
│ │ ├── swin_utils.py
│ │ ├── transfusion_utils.py
│ │ └── vmamba.py
│ ├── roi_heads
│ │ ├── __init__.py
│ │ ├── mppnet_head.py
│ │ ├── mppnet_memory_bank_e2e.py
│ │ ├── partA2_head.py
│ │ ├── pointrcnn_head.py
│ │ ├── pvrcnn_head.py
│ │ ├── roi_head_template.py
│ │ ├── second_head.py
│ │ ├── target_assigner
│ │ │ ├── __init__.py
│ │ │ └── proposal_target_layer.py
│ │ └── voxelrcnn_head.py
│ └── view_transforms
│ │ ├── __init__.py
│ │ └── depth_lss.py
├── ops
│ ├── __init__.py
│ ├── bev_pool
│ │ ├── __init__.py
│ │ ├── bev_pool.py
│ │ └── src
│ │ │ ├── bev_pool.cpp
│ │ │ └── bev_pool_cuda.cu
│ ├── deform_attn_3d
│ │ ├── csrc
│ │ │ ├── common_cuda_helper.hpp
│ │ │ ├── ms_deform_attn_cuda.cu
│ │ │ ├── ms_deform_attn_cuda_kernel.cuh
│ │ │ └── pytorch_cuda_helper.hpp
│ │ ├── deform_attn_3d_utils.py
│ │ └── setup.py
│ ├── ingroup_inds
│ │ ├── ingroup_inds_op.py
│ │ └── src
│ │ │ ├── error.cuh
│ │ │ ├── ingroup_inds.cpp
│ │ │ └── ingroup_inds_kernel.cu
│ ├── iou3d_nms
│ │ ├── __init__.py
│ │ ├── iou3d_nms_utils.py
│ │ └── src
│ │ │ ├── iou3d_cpu.cpp
│ │ │ ├── iou3d_cpu.h
│ │ │ ├── iou3d_nms.cpp
│ │ │ ├── iou3d_nms.h
│ │ │ ├── iou3d_nms_api.cpp
│ │ │ └── iou3d_nms_kernel.cu
│ ├── multi_scale_deformable_attn
│ │ ├── multi_scale_deform_attn_utils.py
│ │ └── src
│ │ │ ├── common_cuda_helper.hpp
│ │ │ ├── ms_deform_attn.cpp
│ │ │ ├── ms_deform_attn_cuda.cu
│ │ │ ├── ms_deform_attn_cuda_kernel.cuh
│ │ │ ├── pytorch_cpp_helper.hpp
│ │ │ ├── pytorch_cuda_helper.hpp
│ │ │ └── pytorch_cuda_helper_old.hpp
│ ├── pointnet2
│ │ ├── __init__.py
│ │ ├── pointnet2_batch
│ │ │ ├── __init__.py
│ │ │ ├── pointnet2_modules.py
│ │ │ ├── pointnet2_utils.py
│ │ │ └── src
│ │ │ │ ├── ball_query.cpp
│ │ │ │ ├── ball_query_gpu.cu
│ │ │ │ ├── ball_query_gpu.h
│ │ │ │ ├── cuda_utils.h
│ │ │ │ ├── group_points.cpp
│ │ │ │ ├── group_points_gpu.cu
│ │ │ │ ├── group_points_gpu.h
│ │ │ │ ├── interpolate.cpp
│ │ │ │ ├── interpolate_gpu.cu
│ │ │ │ ├── interpolate_gpu.h
│ │ │ │ ├── pointnet2_api.cpp
│ │ │ │ ├── sampling.cpp
│ │ │ │ ├── sampling_gpu.cu
│ │ │ │ └── sampling_gpu.h
│ │ └── pointnet2_stack
│ │ │ ├── __init__.py
│ │ │ ├── pointnet2_modules.py
│ │ │ ├── pointnet2_utils.py
│ │ │ ├── src
│ │ │ ├── ball_query.cpp
│ │ │ ├── ball_query_gpu.cu
│ │ │ ├── ball_query_gpu.h
│ │ │ ├── cuda_utils.h
│ │ │ ├── group_points.cpp
│ │ │ ├── group_points_gpu.cu
│ │ │ ├── group_points_gpu.h
│ │ │ ├── interpolate.cpp
│ │ │ ├── interpolate_gpu.cu
│ │ │ ├── interpolate_gpu.h
│ │ │ ├── pointnet2_api.cpp
│ │ │ ├── sampling.cpp
│ │ │ ├── sampling_gpu.cu
│ │ │ ├── sampling_gpu.h
│ │ │ ├── vector_pool.cpp
│ │ │ ├── vector_pool_gpu.cu
│ │ │ ├── vector_pool_gpu.h
│ │ │ ├── voxel_query.cpp
│ │ │ ├── voxel_query_gpu.cu
│ │ │ └── voxel_query_gpu.h
│ │ │ ├── voxel_pool_modules.py
│ │ │ └── voxel_query_utils.py
│ ├── roiaware_pool3d
│ │ ├── __init__.py
│ │ ├── roiaware_pool3d_utils.py
│ │ └── src
│ │ │ ├── roiaware_pool3d.cpp
│ │ │ └── roiaware_pool3d_kernel.cu
│ └── roipoint_pool3d
│ │ ├── __init__.py
│ │ ├── roipoint_pool3d_utils.py
│ │ └── src
│ │ ├── roipoint_pool3d.cpp
│ │ └── roipoint_pool3d_kernel.cu
└── utils
│ ├── __init__.py
│ ├── box_coder_utils.py
│ ├── box_utils.py
│ ├── calibration_kitti.py
│ ├── common_utils.py
│ ├── commu_utils.py
│ ├── loss_utils.py
│ ├── object3d_custom.py
│ ├── object3d_kitti.py
│ ├── remove_head_weights.py
│ ├── spconv_utils.py
│ └── transform_utils.py
├── requirements.txt
├── setup.py
└── tools
├── _init_path.py
├── cfgs
├── argo2_models
│ └── cbgs_voxel01_voxelnext.yaml
├── custom_models
│ ├── pv_rcnn.yaml
│ └── second.yaml
├── dataset_configs
│ ├── argo2_dataset.yaml
│ ├── custom_dataset.yaml
│ ├── kitti_dataset.yaml
│ ├── lyft_dataset.yaml
│ ├── nuscenes_dataset.yaml
│ ├── once_dataset.yaml
│ ├── pandaset_dataset.yaml
│ ├── waymo_dataset.yaml
│ └── waymo_dataset_multiframe.yaml
├── kitti_models
│ ├── CaDDN.yaml
│ ├── PartA2.yaml
│ ├── PartA2_free.yaml
│ ├── pillarnet.yaml
│ ├── pointpillar.yaml
│ ├── pointpillar_newaugs.yaml
│ ├── pointpillar_pyramid_aug.yaml
│ ├── pointrcnn.yaml
│ ├── pointrcnn_iou.yaml
│ ├── pv_rcnn.yaml
│ ├── pv_rcnn_plusplus_reproduced_by_community.yaml
│ ├── second.yaml
│ ├── second_iou.yaml
│ ├── second_multihead.yaml
│ ├── voxel_rcnn_car.yaml
│ └── voxel_rcnn_car_focal_multimodal.yaml
├── lyft_models
│ ├── cbgs_second-nores_multihead.yaml
│ └── cbgs_second_multihead.yaml
├── nuscenes_models
│ ├── bevfusion.yaml
│ ├── cbgs_dyn_pp_centerpoint.yaml
│ ├── cbgs_pillar0075_res2d_centerpoint.yaml
│ ├── cbgs_pp_multihead.yaml
│ ├── cbgs_second_multihead.yaml
│ ├── cbgs_voxel0075_res3d_centerpoint.yaml
│ ├── cbgs_voxel0075_voxelnext.yaml
│ ├── cbgs_voxel0075_voxelnext_doubleflip.yaml
│ ├── cbgs_voxel01_res3d_centerpoint.yaml
│ ├── m3net_det.yaml
│ ├── m3net_det_map.yaml
│ ├── m3net_det_map_occ.yaml
│ └── transfusion_lidar.yaml
├── once_models
│ ├── centerpoint.yaml
│ ├── pointpillar.yaml
│ ├── pointrcnn.yaml
│ ├── pv_rcnn.yaml
│ └── second.yaml
└── waymo_models
│ ├── PartA2.yaml
│ ├── centerpoint.yaml
│ ├── centerpoint_4frames.yaml
│ ├── centerpoint_dyn_pillar_1x.yaml
│ ├── centerpoint_pillar_1x.yaml
│ ├── centerpoint_without_resnet.yaml
│ ├── dsvt_pillar.yaml
│ ├── dsvt_voxel.yaml
│ ├── mppnet_16frames.yaml
│ ├── mppnet_4frames.yaml
│ ├── mppnet_e2e_memorybank_inference.yaml
│ ├── pillarnet.yaml
│ ├── pointpillar_1x.yaml
│ ├── pv_rcnn.yaml
│ ├── pv_rcnn_plusplus.yaml
│ ├── pv_rcnn_plusplus_resnet.yaml
│ ├── pv_rcnn_plusplus_resnet_2frames.yaml
│ ├── pv_rcnn_with_centerhead_rpn.yaml
│ ├── second.yaml
│ ├── voxel_rcnn_with_centerhead_dyn_voxel.yaml
│ ├── voxelnext2d_ioubranch.yaml
│ └── voxelnext_ioubranch_large.yaml
├── demo.py
├── eval_utils
└── eval_utils.py
├── process_tools
└── create_integrated_database.py
├── scripts
├── dist_test.sh
├── dist_train.sh
├── slurm_test_mgpu.sh
├── slurm_test_single.sh
├── slurm_train.sh
├── slurm_train_v2.sh
├── torch_test.sh
└── torch_train.sh
├── test.py
├── train.py
├── train_utils
├── optimization
│ ├── __init__.py
│ ├── fastai_optim.py
│ └── learning_schedules_fastai.py
└── train_utils.py
└── visual_utils
├── open3d_vis_utils.py
└── visualize_utils.py
/.github/workflows/close_stale_issues.yml:
--------------------------------------------------------------------------------
1 | # https://github.com/actions/stale
2 | # https://github.com/marketplace/actions/close-stale-issues
3 | # https://docs.github.com/en/actions/managing-issues-and-pull-requests/closing-inactive-issues
4 |
5 | name: close stale issues
6 | on:
7 | schedule:
8 | - cron: "30 1 * * *"
9 |
10 | jobs:
11 | close-issues:
12 | runs-on: ubuntu-latest
13 | permissions:
14 | issues: write
15 | pull-requests: write
16 | steps:
17 | - uses: actions/stale@v4.1.0
18 | with:
19 | days-before-issue-stale: 30
20 | days-before-issue-close: 14
21 | stale-issue-label: "stale"
22 | stale-issue-message: "This issue is stale because it has been open for 30 days with no activity."
23 | close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale."
24 | days-before-pr-stale: -1
25 | days-before-pr-close: -1
26 | repo-token: ${{ secrets.GITHUB_TOKEN }}
27 | operations-per-run: 1000
28 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **__pycache__**
2 | **build**
3 | **egg-info**
4 | **dist**
5 | data/
6 | *.pyc
7 | venv/
8 | *.idea/
9 | *.so
10 | *.yaml
11 | *.sh
12 | *.pth
13 | *.pkl
14 | *.zip
15 | *.bin
16 | output
17 | version.py
18 |
--------------------------------------------------------------------------------
/data/lyft/ImageSets/val.txt:
--------------------------------------------------------------------------------
1 | host-a004-lidar0-1233080749298771736-1233080774198118416
2 | host-a004-lidar0-1232905197298264546-1232905222198133856
3 | host-a011-lidar0-1232732468299489666-1232732493199050666
4 | host-a101-lidar0-1241561147998866622-1241561172899320654
5 | host-a006-lidar0-1237322885198285226-1237322910098576786
6 | host-a004-lidar0-1233963848198981116-1233963873098642176
7 | host-a011-lidar0-1232752543198025666-1232752568099126026
8 | host-a004-lidar0-1232842367198056546-1232842392097783226
9 | host-a004-lidar0-1233615989298293586-1233616014198854636
10 | host-a011-lidar0-1233965426299054906-1233965451199121906
11 | host-a011-lidar0-1236104034298928316-1236104059198988026
12 | host-a007-lidar0-1233946614199227636-1233946639098289666
13 | host-a015-lidar0-1235423696198069636-1235423721098551296
14 | host-a004-lidar0-1233014843199117706-1233014868098023786
15 | host-a011-lidar0-1236093962299300416-1236093987199363346
16 | host-a011-lidar0-1234639296198260986-1234639321099417316
17 | host-a011-lidar0-1233524871199389346-1233524896098591466
18 | host-a011-lidar0-1235933781298838116-1235933806199517736
19 | host-a011-lidar0-1233965312298542226-1233965337198958586
20 | host-a011-lidar0-1233090567199118316-1233090592098933996
21 | host-a007-lidar0-1233621256298511876-1233621281197988026
22 | host-a007-lidar0-1233079617197863906-1233079642098533586
23 | host-a015-lidar0-1236112516098396876-1236112540999028556
24 | host-a008-lidar0-1236016333197799906-1236016358099063636
25 | host-a101-lidar0-1240710366399037786-1240710391298976894
26 | host-a102-lidar0-1242755350298764586-1242755375198787666
27 | host-a101-lidar0-1240877587199107226-1240877612099413030
28 | host-a101-lidar0-1242583745399163026-1242583770298821706
29 | host-a011-lidar0-1232817034199342856-1232817059098800346
30 | host-a004-lidar0-1232905117299287546-1232905142198246226
--------------------------------------------------------------------------------
/data/once/ImageSets/test.txt:
--------------------------------------------------------------------------------
1 | 000034
2 | 000077
3 | 000168
4 | 000200
5 | 000273
6 | 000275
7 | 000303
8 | 000318
9 | 000322
10 | 000334
11 |
--------------------------------------------------------------------------------
/data/once/ImageSets/train.txt:
--------------------------------------------------------------------------------
1 | 000076
2 | 000080
3 | 000092
4 | 000104
5 | 000113
6 | 000121
7 |
--------------------------------------------------------------------------------
/data/once/ImageSets/val.txt:
--------------------------------------------------------------------------------
1 | 000027
2 | 000028
3 | 000112
4 | 000201
5 |
--------------------------------------------------------------------------------
/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM nvidia/cuda:10.2-cudnn7-devel-ubuntu18.04
2 |
3 | RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
4 |
5 | # Install basics
6 | RUN apt-get update -y \
7 | && apt-get install build-essential \
8 | && apt-get install -y apt-utils git curl ca-certificates bzip2 tree htop wget \
9 | && apt-get install -y libglib2.0-0 libsm6 libxext6 libxrender-dev bmon iotop g++ python3.7 python3.7-dev python3.7-distutils
10 |
11 | # Install cmake v3.13.2
12 | RUN apt-get purge -y cmake && \
13 | mkdir /root/temp && \
14 | cd /root/temp && \
15 | wget https://github.com/Kitware/CMake/releases/download/v3.13.2/cmake-3.13.2.tar.gz && \
16 | tar -xzvf cmake-3.13.2.tar.gz && \
17 | cd cmake-3.13.2 && \
18 | bash ./bootstrap && \
19 | make && \
20 | make install && \
21 | cmake --version && \
22 | rm -rf /root/temp
23 |
24 | # Install python
25 | RUN ln -sv /usr/bin/python3.7 /usr/bin/python
26 | RUN wget https://bootstrap.pypa.io/get-pip.py && \
27 | python get-pip.py && \
28 | rm get-pip.py
29 |
30 | # Install python packages
31 | RUN PIP_INSTALL="python -m pip --no-cache-dir install" && \
32 | $PIP_INSTALL numpy==1.19.3 llvmlite numba
33 |
34 | # Install torch and torchvision
35 | # See https://pytorch.org/ for other options if you use a different version of CUDA
36 | RUN pip install --user torch==1.6 torchvision==0.7.0 -f https://download.pytorch.org/whl/cu102/torch_stable.html
37 |
38 | # Install python packages
39 | RUN PIP_INSTALL="python -m pip --no-cache-dir install" && \
40 | $PIP_INSTALL tensorboardX easydict pyyaml scikit-image tqdm SharedArray six
41 |
42 | WORKDIR /root
43 |
44 | # Install Boost geometry
45 | RUN wget https://jaist.dl.sourceforge.net/project/boost/boost/1.68.0/boost_1_68_0.tar.gz && \
46 | tar xzvf boost_1_68_0.tar.gz && \
47 | cp -r ./boost_1_68_0/boost /usr/include && \
48 | rm -rf ./boost_1_68_0 && \
49 | rm -rf ./boost_1_68_0.tar.gz
50 |
51 | # A weired problem that hasn't been solved yet
52 | RUN pip uninstall -y SharedArray && \
53 | pip install SharedArray
54 |
55 | RUN pip install spconv-cu102
--------------------------------------------------------------------------------
/docker/README.md:
--------------------------------------------------------------------------------
1 | # Guidance to use OpenPCDet with docker
2 |
3 | You can either build the docker image through Dockerfile or pull the docker image from dockerhub. Please make sure nvidia-docker is corretly installed.
4 |
5 | ## Build Through Dockerfile
6 | Build docker image that support OpenPCDet through:
7 | ```shell script
8 | docker build ./ -t openpcdet-docker
9 | ```
10 | Note that if you would like to use dynamic voxelization, you need further install [`torch_scatter`](https://github.com/rusty1s/pytorch_scatter) package.
11 |
12 | From this Dockerfile, the installed version of spconv is 2.x, if you would like to use spconv 1.2.1, please follow these steps:
13 | ```shell script
14 | git clone -b v1.2.1 https://github.com/djiajunustc/spconv spconv --recursive
15 | cd spconv
16 | python setup.py bdist_wheel
17 | cd ./dist
18 | pip install *.whl
19 | ```
20 |
21 | ## Pull From Dockerhub
22 | Run the following script to pull the docker image:
23 | ```shell script
24 | docker pull djiajun1206/pcdet:pytorch1.6
25 | ```
26 |
--------------------------------------------------------------------------------
/docs/DEMO.md:
--------------------------------------------------------------------------------
1 | # Quick Demo
2 |
3 | Here we provide a quick demo to test a pretrained model on the custom point cloud data and visualize the predicted results.
4 |
5 | We suppose you already followed the [INSTALL.md](INSTALL.md) to install the `OpenPCDet` repo successfully.
6 |
7 | 1. Download the provided pretrained models as shown in the [README.md](../README.md).
8 |
9 | 2. Make sure you have already installed the [`Open3D`](https://github.com/isl-org/Open3D) (faster) or `mayavi` visualization tools.
10 | If not, you could install it as follows:
11 | ```
12 | pip install open3d
13 | # or
14 | pip install mayavi
15 | ```
16 |
17 | 3. Prepare your custom point cloud data (skip this step if you use the original KITTI data).
18 | * You need to transform the coordinate of your custom point cloud to
19 | the unified normative coordinate of `OpenPCDet`, that is, x-axis points towards to front direction,
20 | y-axis points towards to the left direction, and z-axis points towards to the top direction.
21 | * (Optional) the z-axis origin of your point cloud coordinate should be about 1.6m above the ground surface,
22 | since currently the provided models are trained on the KITTI dataset.
23 | * Set the intensity information, and save your transformed custom data to `numpy file`:
24 | ```python
25 | # Transform your point cloud data
26 | ...
27 |
28 | # Save it to the file.
29 | # The shape of points should be (num_points, 4), that is [x, y, z, intensity] (Only for KITTI dataset).
30 | # If you doesn't have the intensity information, just set them to zeros.
31 | # If you have the intensity information, you should normalize them to [0, 1].
32 | points[:, 3] = 0
33 | np.save(`my_data.npy`, points)
34 | ```
35 |
36 | 4. Run the demo with a pretrained model (e.g. PV-RCNN) and your custom point cloud data as follows:
37 | ```shell
38 | python demo.py --cfg_file cfgs/kitti_models/pv_rcnn.yaml \
39 | --ckpt pv_rcnn_8369.pth \
40 | --data_path ${POINT_CLOUD_DATA}
41 | ```
42 | Here `${POINT_CLOUD_DATA}` could be in any of the following format:
43 | * Your transformed custom data with a single numpy file like `my_data.npy`.
44 | * Your transformed custom data with a directory to test with multiple point cloud data.
45 | * The original KITTI `.bin` data within `data/kitti`, like `data/kitti/training/velodyne/000008.bin`.
46 |
47 | Then you could see the predicted results with visualized point cloud as follows:
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/docs/INSTALL.md:
--------------------------------------------------------------------------------
1 | # Installation
2 |
3 | ### Requirements
4 | All the codes are tested in the following environment:
5 | * Linux (tested on Ubuntu 14.04/16.04/18.04/20.04/21.04)
6 | * Python 3.6+
7 | * PyTorch 1.1 or higher (tested on PyTorch 1.1, 1,3, 1,5~1.10)
8 | * CUDA 9.0 or higher (PyTorch 1.3+ needs CUDA 9.2+)
9 | * [`spconv v1.0 (commit 8da6f96)`](https://github.com/traveller59/spconv/tree/8da6f967fb9a054d8870c3515b1b44eca2103634) or [`spconv v1.2`](https://github.com/traveller59/spconv) or [`spconv v2.x`](https://github.com/traveller59/spconv)
10 |
11 |
12 | ### Install `pcdet v0.5`
13 | NOTE: Please re-install `pcdet v0.5` by running `python setup.py develop` even if you have already installed previous version.
14 |
15 | a. Clone this repository.
16 | ```shell
17 | git clone https://github.com/open-mmlab/OpenPCDet.git
18 | ```
19 |
20 | b. Install the dependent libraries as follows:
21 |
22 | [comment]: <> (* Install the dependent python libraries: )
23 |
24 | [comment]: <> (```)
25 |
26 | [comment]: <> (pip install -r requirements.txt )
27 |
28 | [comment]: <> (```)
29 |
30 | * Install the SparseConv library, we use the implementation from [`[spconv]`](https://github.com/traveller59/spconv).
31 | * If you use PyTorch 1.1, then make sure you install the `spconv v1.0` with ([commit 8da6f96](https://github.com/traveller59/spconv/tree/8da6f967fb9a054d8870c3515b1b44eca2103634)) instead of the latest one.
32 | * If you use PyTorch 1.3+, then you need to install the `spconv v1.2`. As mentioned by the author of [`spconv`](https://github.com/traveller59/spconv), you need to use their docker if you use PyTorch 1.4+.
33 | * You could also install latest `spconv v2.x` with pip, see the official documents of [spconv](https://github.com/traveller59/spconv).
34 |
35 | c. Install this `pcdet` library and its dependent libraries by running the following command:
36 | ```shell
37 | python setup.py develop
38 | ```
39 |
--------------------------------------------------------------------------------
/docs/changelog.md:
--------------------------------------------------------------------------------
1 | # Changelog and Guidelines
2 |
3 | ### [2022-09-02] Update to v0.6.0:
4 |
5 | * How to process data to support multi-frame training/testing on Waymo Open Dataset?
6 | * If you never use the OpenPCDet, you can directly follow the [GETTING_STARTED.md](GETTING_STARTED.md)
7 | * If you have been using previous OpenPCDet (`v0.5`), then you need to follow the following steps to update your data:
8 | * Update your waymo infos (the `*.pkl` files for each sequence) by adding argument `--update_info_only`:
9 | ```
10 | python -m pcdet.datasets.waymo.waymo_dataset --func create_waymo_infos --cfg_file tools/cfgs/dataset_configs/waymo_dataset.yaml --update_info_only
11 | ```
12 | * Generate multi-frame GT database for copy-paste augmentation of multi-frame training. There is also a faster version with parallel data generation by adding `--use_parallel`, but you need to read the codes and rename the file after getting the results.
13 | ```
14 | python -m pcdet.datasets.waymo.waymo_dataset --func create_waymo_gt_database --cfg_file tools/cfgs/dataset_configs/waymo_dataset_multiframe.yaml
15 | ```
16 | This will generate the new files like the following (the last three lines under `data/waymo`):
17 |
18 | ```
19 | OpenPCDet
20 | ├── data
21 | │ ├── waymo
22 | │ │ │── ImageSets
23 | │ │ │── raw_data
24 | │ │ │ │── segment-xxxxxxxx.tfrecord
25 | | | | |── ...
26 | | | |── waymo_processed_data_v0_5_0
27 | │ │ │ │── segment-xxxxxxxx/
28 | | | | |── ...
29 | │ │ │── waymo_processed_data_v0_5_0_gt_database_train_sampled_1/
30 | │ │ │── waymo_processed_data_v0_5_0_waymo_dbinfos_train_sampled_1.pkl
31 | │ │ │── waymo_processed_data_v0_5_0_gt_database_train_sampled_1_global.npy (optional)
32 | │ │ │── waymo_processed_data_v0_5_0_infos_train.pkl (optional)
33 | │ │ │── waymo_processed_data_v0_5_0_infos_val.pkl (optional)
34 | | | |── waymo_processed_data_v0_5_0_gt_database_train_sampled_1_multiframe_-4_to_0 (new)
35 | │ │ │── waymo_processed_data_v0_5_0_waymo_dbinfos_train_sampled_1_multiframe_-4_to_0.pkl (new)
36 | │ │ │── waymo_processed_data_v0_5_0_gt_database_train_sampled_1_multiframe_-4_to_0_global.np (new, optional)
37 |
38 | ├── pcdet
39 | ├── tools
40 | ```
41 |
--------------------------------------------------------------------------------
/docs/dataset_vs_model.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/docs/dataset_vs_model.png
--------------------------------------------------------------------------------
/docs/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/docs/demo.png
--------------------------------------------------------------------------------
/docs/guidelines_of_approaches/bevfusion.md:
--------------------------------------------------------------------------------
1 |
2 | ## Installation
3 |
4 | Please refer to [INSTALL.md](../INSTALL.md) for the installation of `OpenPCDet`.
5 | * We recommend the users to check the version of pillow and use pillow==8.4.0 to avoid bug in bev pooling.
6 |
7 | ## Data Preparation
8 | Please refer to [GETTING_STARTED.md](../GETTING_STARTED.md) to process the multi-modal Nuscenes Dataset.
9 |
10 | ## Training
11 |
12 | 1. Train the lidar branch for BEVFusion:
13 | ```shell
14 | bash scripts/dist_train.sh ${NUM_GPUS} --cfg_file cfgs/nuscenes_models/transfusion_lidar.yaml \
15 | ```
16 | The ckpt will be saved in ../output/nuscenes_models/transfusion_lidar/default/ckpt, or you can download pretrained checkpoint directly form [here](https://drive.google.com/file/d/1cuZ2qdDnxSwTCsiXWwbqCGF-uoazTXbz/view?usp=share_link).
17 |
18 | 2. To train BEVFusion, you need to download pretrained parameters for image backbone [here](https://drive.google.com/file/d/1v74WCt4_5ubjO7PciA5T0xhQc9bz_jZu/view?usp=share_link), and specify the path in [config](../../tools/cfgs/nuscenes_models/bevfusion.yaml#L88). Then run the following command:
19 | ```shell
20 | bash scripts/dist_train.sh ${NUM_GPUS} --cfg_file cfgs/nuscenes_models/bevfusion.yaml \
21 | --pretrained_model path_to_pretrained_lidar_branch_ckpt \
22 | ```
23 | ## Evaluation
24 | * Test with a pretrained model:
25 | ```shell
26 | bash scripts/dist_test.sh ${NUM_GPUS} --cfg_file cfgs/nuscenes_models/bevfusion.yaml \
27 | --ckpt ../output/cfgs/nuscenes_models/bevfusion/default/ckpt/checkpoint_epoch_6.pth
28 | ```
29 |
30 | ## Performance
31 | All models are trained with spconv 1.0, but you can directly load them for testing regardless of the spconv version.
32 | | | mATE | mASE | mAOE | mAVE | mAAE | mAP | NDS | download |
33 | |----------------------------------------------------------------------------------------------------|-------:|:------:|:------:|:-----:|:-----:|:-----:|:------:|:--------------------------------------------------------------------------------------------------:|
34 | | [TransFusion-L](../../tools/cfgs/nuscenes_models/transfusion_lidar.yaml) | 27.96 | 25.37 | 29.35 | 27.31 | 18.55 | 64.58 | 69.43 | [model-32M](https://drive.google.com/file/d/1cuZ2qdDnxSwTCsiXWwbqCGF-uoazTXbz/view?usp=share_link) |
35 | | [BEVFusion](../../tools/cfgs/nuscenes_models/bevfusion.yaml) | 28.03 | 25.43 | 30.19 | 26.76 | 18.48 | 67.75 | 70.98 | [model-157M](https://drive.google.com/file/d/1X50b-8immqlqD8VPAUkSKI0Ls-4k37g9/view?usp=share_link) |
36 |
--------------------------------------------------------------------------------
/docs/model_framework.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/docs/model_framework.png
--------------------------------------------------------------------------------
/docs/multiple_models_demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/docs/multiple_models_demo.png
--------------------------------------------------------------------------------
/docs/open_mmlab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/docs/open_mmlab.png
--------------------------------------------------------------------------------
/pcdet/__init__.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 | from pathlib import Path
3 |
4 | from .version import __version__
5 |
6 | __all__ = [
7 | '__version__'
8 | ]
9 |
10 |
11 | def get_git_commit_number():
12 | if not (Path(__file__).parent / '../.git').exists():
13 | return '0000000'
14 |
15 | cmd_out = subprocess.run(['git', 'rev-parse', 'HEAD'], stdout=subprocess.PIPE)
16 | git_commit_number = cmd_out.stdout.decode('utf-8')[:7]
17 | return git_commit_number
18 |
19 |
20 | script_version = get_git_commit_number()
21 |
22 |
23 | if script_version not in __version__:
24 | __version__ = __version__ + '+py%s' % script_version
25 |
--------------------------------------------------------------------------------
/pcdet/config.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 |
3 | import yaml
4 | from easydict import EasyDict
5 |
6 |
7 | def log_config_to_file(cfg, pre='cfg', logger=None):
8 | for key, val in cfg.items():
9 | if isinstance(cfg[key], EasyDict):
10 | logger.info('----------- %s -----------' % (key))
11 | log_config_to_file(cfg[key], pre=pre + '.' + key, logger=logger)
12 | continue
13 | logger.info('%s.%s: %s' % (pre, key, val))
14 |
15 |
16 | def cfg_from_list(cfg_list, config):
17 | """Set config keys via list (e.g., from command line)."""
18 | from ast import literal_eval
19 | assert len(cfg_list) % 2 == 0
20 | for k, v in zip(cfg_list[0::2], cfg_list[1::2]):
21 | key_list = k.split('.')
22 | d = config
23 | for subkey in key_list[:-1]:
24 | assert subkey in d, 'NotFoundKey: %s' % subkey
25 | d = d[subkey]
26 | subkey = key_list[-1]
27 | assert subkey in d, 'NotFoundKey: %s' % subkey
28 | try:
29 | value = literal_eval(v)
30 | except:
31 | value = v
32 |
33 | if type(value) != type(d[subkey]) and isinstance(d[subkey], EasyDict):
34 | key_val_list = value.split(',')
35 | for src in key_val_list:
36 | cur_key, cur_val = src.split(':')
37 | val_type = type(d[subkey][cur_key])
38 | cur_val = val_type(cur_val)
39 | d[subkey][cur_key] = cur_val
40 | elif type(value) != type(d[subkey]) and isinstance(d[subkey], list):
41 | val_list = value.split(',')
42 | for k, x in enumerate(val_list):
43 | val_list[k] = type(d[subkey][0])(x)
44 | d[subkey] = val_list
45 | else:
46 | assert type(value) == type(d[subkey]), \
47 | 'type {} does not match original type {}'.format(type(value), type(d[subkey]))
48 | d[subkey] = value
49 |
50 |
51 | def merge_new_config(config, new_config):
52 | if '_BASE_CONFIG_' in new_config:
53 | with open(new_config['_BASE_CONFIG_'], 'r') as f:
54 | try:
55 | yaml_config = yaml.safe_load(f, Loader=yaml.FullLoader)
56 | except:
57 | yaml_config = yaml.safe_load(f)
58 | config.update(EasyDict(yaml_config))
59 |
60 | for key, val in new_config.items():
61 | if not isinstance(val, dict):
62 | config[key] = val
63 | continue
64 | if key not in config:
65 | config[key] = EasyDict()
66 | merge_new_config(config[key], val)
67 |
68 | return config
69 |
70 |
71 | def cfg_from_yaml_file(cfg_file, config):
72 | with open(cfg_file, 'r') as f:
73 | try:
74 | new_config = yaml.safe_load(f, Loader=yaml.FullLoader)
75 | except:
76 | new_config = yaml.safe_load(f)
77 |
78 | merge_new_config(config=config, new_config=new_config)
79 |
80 | return config
81 |
82 |
83 | cfg = EasyDict()
84 | cfg.ROOT_DIR = (Path(__file__).resolve().parent / '../').resolve()
85 | cfg.LOCAL_RANK = 0
86 |
--------------------------------------------------------------------------------
/pcdet/datasets/__init__.py:
--------------------------------------------------------------------------------
1 | import torch
2 | from functools import partial
3 | from torch.utils.data import DataLoader
4 | from torch.utils.data import DistributedSampler as _DistributedSampler
5 |
6 | from pcdet.utils import common_utils
7 |
8 | from .dataset import DatasetTemplate
9 | from .kitti.kitti_dataset import KittiDataset
10 | from .nuscenes.nuscenes_dataset import NuScenesDataset
11 | from .nuscenes.nuscenes_dataset_mtl import NuScenesDatasetMTL
12 | from .waymo.waymo_dataset import WaymoDataset
13 | from .pandaset.pandaset_dataset import PandasetDataset
14 | from .lyft.lyft_dataset import LyftDataset
15 | from .once.once_dataset import ONCEDataset
16 | from .argo2.argo2_dataset import Argo2Dataset
17 | from .custom.custom_dataset import CustomDataset
18 |
19 | __all__ = {
20 | 'DatasetTemplate': DatasetTemplate,
21 | 'KittiDataset': KittiDataset,
22 | 'NuScenesDataset': NuScenesDataset,
23 | 'WaymoDataset': WaymoDataset,
24 | 'PandasetDataset': PandasetDataset,
25 | 'LyftDataset': LyftDataset,
26 | 'ONCEDataset': ONCEDataset,
27 | 'CustomDataset': CustomDataset,
28 | 'Argo2Dataset': Argo2Dataset,
29 | 'NuScenesDatasetMTL': NuScenesDatasetMTL
30 | }
31 |
32 |
33 | class DistributedSampler(_DistributedSampler):
34 |
35 | def __init__(self, dataset, num_replicas=None, rank=None, shuffle=True):
36 | super().__init__(dataset, num_replicas=num_replicas, rank=rank)
37 | self.shuffle = shuffle
38 |
39 | def __iter__(self):
40 | if self.shuffle:
41 | g = torch.Generator()
42 | g.manual_seed(self.epoch)
43 | indices = torch.randperm(len(self.dataset), generator=g).tolist()
44 | else:
45 | indices = torch.arange(len(self.dataset)).tolist()
46 |
47 | indices += indices[:(self.total_size - len(indices))]
48 | assert len(indices) == self.total_size
49 |
50 | indices = indices[self.rank:self.total_size:self.num_replicas]
51 | assert len(indices) == self.num_samples
52 |
53 | return iter(indices)
54 |
55 |
56 | def build_dataloader(dataset_cfg, class_names, batch_size, dist, root_path=None, workers=4, seed=None,
57 | logger=None, training=True, merge_all_iters_to_one_epoch=False, total_epochs=0):
58 |
59 | dataset = __all__[dataset_cfg.DATASET](
60 | dataset_cfg=dataset_cfg,
61 | class_names=class_names,
62 | root_path=root_path,
63 | training=training,
64 | logger=logger,
65 | )
66 |
67 | if merge_all_iters_to_one_epoch:
68 | assert hasattr(dataset, 'merge_all_iters_to_one_epoch')
69 | dataset.merge_all_iters_to_one_epoch(merge=True, epochs=total_epochs)
70 |
71 | if dist:
72 | if training:
73 | sampler = torch.utils.data.distributed.DistributedSampler(dataset)
74 | else:
75 | rank, world_size = common_utils.get_dist_info()
76 | sampler = DistributedSampler(dataset, world_size, rank, shuffle=False)
77 | else:
78 | sampler = None
79 | dataloader = DataLoader(
80 | dataset, batch_size=batch_size, pin_memory=True, num_workers=workers,
81 | shuffle=(sampler is None) and training, collate_fn=dataset.collate_batch,
82 | drop_last=False, sampler=sampler, timeout=0, worker_init_fn=partial(common_utils.worker_init_fn, seed=seed)
83 | )
84 |
85 | return dataset, dataloader, sampler
86 |
--------------------------------------------------------------------------------
/pcdet/datasets/argo2/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/pcdet/datasets/argo2/argo2_utils/constants.py:
--------------------------------------------------------------------------------
1 | LABEL_ATTR = (
2 | "tx_m",
3 | "ty_m",
4 | "tz_m",
5 | "length_m",
6 | "width_m",
7 | "height_m",
8 | "qw",
9 | "qx",
10 | "qy",
11 | "qz",
12 | )
--------------------------------------------------------------------------------
/pcdet/datasets/augmentor/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/datasets/augmentor/__init__.py
--------------------------------------------------------------------------------
/pcdet/datasets/custom/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/datasets/custom/__init__.py
--------------------------------------------------------------------------------
/pcdet/datasets/kitti/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/datasets/kitti/__init__.py
--------------------------------------------------------------------------------
/pcdet/datasets/kitti/kitti_object_eval_python/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/pcdet/datasets/kitti/kitti_object_eval_python/README.md:
--------------------------------------------------------------------------------
1 | # kitti-object-eval-python
2 | **Note**: This is borrowed from [traveller59/kitti-object-eval-python](https://github.com/traveller59/kitti-object-eval-python)
3 |
4 | Fast kitti object detection eval in python(finish eval in less than 10 second), support 2d/bev/3d/aos. , support coco-style AP. If you use command line interface, numba need some time to compile jit functions.
5 | ## Dependencies
6 | Only support python 3.6+, need `numpy`, `skimage`, `numba`, `fire`. If you have Anaconda, just install `cudatoolkit` in anaconda. Otherwise, please reference to this [page](https://github.com/numba/numba#custom-python-environments) to set up llvm and cuda for numba.
7 | * Install by conda:
8 | ```
9 | conda install -c numba cudatoolkit=x.x (8.0, 9.0, 9.1, depend on your environment)
10 | ```
11 | ## Usage
12 | * commandline interface:
13 | ```
14 | python evaluate.py evaluate --label_path=/path/to/your_gt_label_folder --result_path=/path/to/your_result_folder --label_split_file=/path/to/val.txt --current_class=0 --coco=False
15 | ```
16 | * python interface:
17 | ```Python
18 | import kitti_common as kitti
19 | from eval import get_official_eval_result, get_coco_eval_result
20 | def _read_imageset_file(path):
21 | with open(path, 'r') as f:
22 | lines = f.readlines()
23 | return [int(line) for line in lines]
24 | det_path = "/path/to/your_result_folder"
25 | dt_annos = kitti.get_label_annos(det_path)
26 | gt_path = "/path/to/your_gt_label_folder"
27 | gt_split_file = "/path/to/val.txt" # from https://xiaozhichen.github.io/files/mv3d/imagesets.tar.gz
28 | val_image_ids = _read_imageset_file(gt_split_file)
29 | gt_annos = kitti.get_label_annos(gt_path, val_image_ids)
30 | print(get_official_eval_result(gt_annos, dt_annos, 0)) # 6s in my computer
31 | print(get_coco_eval_result(gt_annos, dt_annos, 0)) # 18s in my computer
32 | ```
33 |
--------------------------------------------------------------------------------
/pcdet/datasets/kitti/kitti_object_eval_python/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/datasets/kitti/kitti_object_eval_python/__init__.py
--------------------------------------------------------------------------------
/pcdet/datasets/kitti/kitti_object_eval_python/evaluate.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | import fire
4 |
5 | import .kitti_common as kitti
6 | from .eval import get_coco_eval_result, get_official_eval_result
7 |
8 |
9 | def _read_imageset_file(path):
10 | with open(path, 'r') as f:
11 | lines = f.readlines()
12 | return [int(line) for line in lines]
13 |
14 |
15 | def evaluate(label_path,
16 | result_path,
17 | label_split_file,
18 | current_class=0,
19 | coco=False,
20 | score_thresh=-1):
21 | dt_annos = kitti.get_label_annos(result_path)
22 | if score_thresh > 0:
23 | dt_annos = kitti.filter_annos_low_score(dt_annos, score_thresh)
24 | val_image_ids = _read_imageset_file(label_split_file)
25 | gt_annos = kitti.get_label_annos(label_path, val_image_ids)
26 | if coco:
27 | return get_coco_eval_result(gt_annos, dt_annos, current_class)
28 | else:
29 | return get_official_eval_result(gt_annos, dt_annos, current_class)
30 |
31 |
32 | if __name__ == '__main__':
33 | fire.Fire()
34 |
--------------------------------------------------------------------------------
/pcdet/datasets/kitti/kitti_utils.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from ...utils import box_utils
3 |
4 |
5 | def transform_annotations_to_kitti_format(annos, map_name_to_kitti=None, info_with_fakelidar=False):
6 | """
7 | Args:
8 | annos:
9 | map_name_to_kitti: dict, map name to KITTI names (Car, Pedestrian, Cyclist)
10 | info_with_fakelidar:
11 | Returns:
12 |
13 | """
14 | for anno in annos:
15 | # For lyft and nuscenes, different anno key in info
16 | if 'name' not in anno:
17 | anno['name'] = anno['gt_names']
18 | anno.pop('gt_names')
19 |
20 | for k in range(anno['name'].shape[0]):
21 | anno['name'][k] = map_name_to_kitti[anno['name'][k]]
22 |
23 | anno['bbox'] = np.zeros((len(anno['name']), 4))
24 | anno['bbox'][:, 2:4] = 50 # [0, 0, 50, 50]
25 | anno['truncated'] = np.zeros(len(anno['name']))
26 | anno['occluded'] = np.zeros(len(anno['name']))
27 | if 'boxes_lidar' in anno:
28 | gt_boxes_lidar = anno['boxes_lidar'].copy()
29 | else:
30 | gt_boxes_lidar = anno['gt_boxes_lidar'].copy()
31 |
32 | if len(gt_boxes_lidar) > 0:
33 | if info_with_fakelidar:
34 | gt_boxes_lidar = box_utils.boxes3d_kitti_fakelidar_to_lidar(gt_boxes_lidar)
35 |
36 | gt_boxes_lidar[:, 2] -= gt_boxes_lidar[:, 5] / 2
37 | anno['location'] = np.zeros((gt_boxes_lidar.shape[0], 3))
38 | anno['location'][:, 0] = -gt_boxes_lidar[:, 1] # x = -y_lidar
39 | anno['location'][:, 1] = -gt_boxes_lidar[:, 2] # y = -z_lidar
40 | anno['location'][:, 2] = gt_boxes_lidar[:, 0] # z = x_lidar
41 | dxdydz = gt_boxes_lidar[:, 3:6]
42 | anno['dimensions'] = dxdydz[:, [0, 2, 1]] # lwh ==> lhw
43 | anno['rotation_y'] = -gt_boxes_lidar[:, 6] - np.pi / 2.0
44 | anno['alpha'] = -np.arctan2(-gt_boxes_lidar[:, 1], gt_boxes_lidar[:, 0]) + anno['rotation_y']
45 | else:
46 | anno['location'] = anno['dimensions'] = np.zeros((0, 3))
47 | anno['rotation_y'] = anno['alpha'] = np.zeros(0)
48 |
49 | return annos
50 |
51 |
52 | def calib_to_matricies(calib):
53 | """
54 | Converts calibration object to transformation matricies
55 | Args:
56 | calib: calibration.Calibration, Calibration object
57 | Returns
58 | V2R: (4, 4), Lidar to rectified camera transformation matrix
59 | P2: (3, 4), Camera projection matrix
60 | """
61 | V2C = np.vstack((calib.V2C, np.array([0, 0, 0, 1], dtype=np.float32))) # (4, 4)
62 | R0 = np.hstack((calib.R0, np.zeros((3, 1), dtype=np.float32))) # (3, 4)
63 | R0 = np.vstack((R0, np.array([0, 0, 0, 1], dtype=np.float32))) # (4, 4)
64 | V2R = R0 @ V2C
65 | P2 = calib.P2
66 | return V2R, P2
--------------------------------------------------------------------------------
/pcdet/datasets/lyft/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/datasets/lyft/__init__.py
--------------------------------------------------------------------------------
/pcdet/datasets/lyft/lyft_mAP_eval/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/datasets/lyft/lyft_mAP_eval/__init__.py
--------------------------------------------------------------------------------
/pcdet/datasets/nuscenes/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/datasets/nuscenes/__init__.py
--------------------------------------------------------------------------------
/pcdet/datasets/once/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/datasets/once/__init__.py
--------------------------------------------------------------------------------
/pcdet/datasets/once/once_eval/eval_utils.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 |
4 | def compute_split_parts(num_samples, num_parts):
5 | part_samples = num_samples // num_parts
6 | remain_samples = num_samples % num_parts
7 | if part_samples == 0:
8 | return [num_samples]
9 | if remain_samples == 0:
10 | return [part_samples] * num_parts
11 | else:
12 | return [part_samples] * num_parts + [remain_samples]
13 |
14 |
15 | def overall_filter(boxes):
16 | ignore = np.zeros(boxes.shape[0], dtype=bool) # all false
17 | return ignore
18 |
19 |
20 | def distance_filter(boxes, level):
21 | ignore = np.ones(boxes.shape[0], dtype=bool) # all true
22 | dist = np.sqrt(np.sum(boxes[:, 0:3] * boxes[:, 0:3], axis=1))
23 |
24 | if level == 0: # 0-30m
25 | flag = dist < 30
26 | elif level == 1: # 30-50m
27 | flag = (dist >= 30) & (dist < 50)
28 | elif level == 2: # 50m-inf
29 | flag = dist >= 50
30 | else:
31 | assert False, 'level < 3 for distance metric, found level %s' % (str(level))
32 |
33 | ignore[flag] = False
34 | return ignore
35 |
36 |
37 | def overall_distance_filter(boxes, level):
38 | ignore = np.ones(boxes.shape[0], dtype=bool) # all true
39 | dist = np.sqrt(np.sum(boxes[:, 0:3] * boxes[:, 0:3], axis=1))
40 |
41 | if level == 0:
42 | flag = np.ones(boxes.shape[0], dtype=bool)
43 | elif level == 1: # 0-30m
44 | flag = dist < 30
45 | elif level == 2: # 30-50m
46 | flag = (dist >= 30) & (dist < 50)
47 | elif level == 3: # 50m-inf
48 | flag = dist >= 50
49 | else:
50 | assert False, 'level < 4 for overall & distance metric, found level %s' % (str(level))
51 |
52 | ignore[flag] = False
53 | return ignore
--------------------------------------------------------------------------------
/pcdet/datasets/pandaset/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/datasets/pandaset/__init__.py
--------------------------------------------------------------------------------
/pcdet/datasets/processor/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/datasets/processor/__init__.py
--------------------------------------------------------------------------------
/pcdet/datasets/processor/point_feature_encoder.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 |
4 | class PointFeatureEncoder(object):
5 | def __init__(self, config, point_cloud_range=None):
6 | super().__init__()
7 | self.point_encoding_config = config
8 | assert list(self.point_encoding_config.src_feature_list[0:3]) == ['x', 'y', 'z']
9 | self.used_feature_list = self.point_encoding_config.used_feature_list
10 | self.src_feature_list = self.point_encoding_config.src_feature_list
11 | self.point_cloud_range = point_cloud_range
12 |
13 | @property
14 | def num_point_features(self):
15 | return getattr(self, self.point_encoding_config.encoding_type)(points=None)
16 |
17 | def forward(self, data_dict):
18 | """
19 | Args:
20 | data_dict:
21 | points: (N, 3 + C_in)
22 | ...
23 | Returns:
24 | data_dict:
25 | points: (N, 3 + C_out),
26 | use_lead_xyz: whether to use xyz as point-wise features
27 | ...
28 | """
29 | data_dict['points'], use_lead_xyz = getattr(self, self.point_encoding_config.encoding_type)(
30 | data_dict['points']
31 | )
32 | data_dict['use_lead_xyz'] = use_lead_xyz
33 |
34 | if self.point_encoding_config.get('filter_sweeps', False) and 'timestamp' in self.src_feature_list:
35 | max_sweeps = self.point_encoding_config.max_sweeps
36 | idx = self.src_feature_list.index('timestamp')
37 | dt = np.round(data_dict['points'][:, idx], 2)
38 | max_dt = sorted(np.unique(dt))[min(len(np.unique(dt))-1, max_sweeps-1)]
39 | data_dict['points'] = data_dict['points'][dt <= max_dt]
40 |
41 | return data_dict
42 |
43 | def absolute_coordinates_encoding(self, points=None):
44 | if points is None:
45 | if 'seq_idx' in self.used_feature_list:
46 | num_output_features = len(self.used_feature_list) - 1
47 | else:
48 | num_output_features = len(self.used_feature_list)
49 | return num_output_features
50 | assert points.shape[-1] == len(self.src_feature_list)
51 | point_feature_list = [points[:, 0:3]]
52 | for x in self.used_feature_list:
53 | if x in ['x', 'y', 'z']:
54 | continue
55 | idx = self.src_feature_list.index(x)
56 | point_feature_list.append(points[:, idx:idx+1])
57 | point_features = np.concatenate(point_feature_list, axis=1)
58 |
59 | return point_features, True
60 |
--------------------------------------------------------------------------------
/pcdet/datasets/waymo/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/datasets/waymo/__init__.py
--------------------------------------------------------------------------------
/pcdet/models/__init__.py:
--------------------------------------------------------------------------------
1 | from collections import namedtuple
2 |
3 | import numpy as np
4 | import torch
5 |
6 | from .detectors import build_detector
7 |
8 | try:
9 | import kornia
10 | except:
11 | pass
12 | # print('Warning: kornia is not installed. This package is only required by CaDDN')
13 |
14 |
15 |
16 | def build_network(model_cfg, num_class, dataset):
17 | model = build_detector(
18 | model_cfg=model_cfg, num_class=num_class, dataset=dataset
19 | )
20 | return model
21 |
22 |
23 | def load_data_to_gpu(batch_dict):
24 |
25 | for key, val in batch_dict.items():
26 | if key == 'camera_imgs':
27 | batch_dict[key] = val.cuda()
28 | elif not isinstance(val, np.ndarray):
29 | continue
30 | elif key in ['frame_id', 'metadata', 'calib', 'image_paths','ori_shape','img_process_infos']:
31 | continue
32 | elif key in ['images']:
33 | batch_dict[key] = kornia.image_to_tensor(val).float().cuda().contiguous()
34 | elif key in ['image_shape']:
35 | batch_dict[key] = torch.from_numpy(val).int().cuda()
36 | elif key in ['timestamp']:
37 | batch_dict[key] = torch.from_numpy(val).double().cuda()
38 | else:
39 | try:
40 | batch_dict[key] = torch.from_numpy(val).float().cuda()
41 | except:
42 | pass
43 |
44 |
45 |
46 | def model_fn_decorator():
47 | ModelReturn = namedtuple('ModelReturn', ['loss', 'tb_dict', 'disp_dict'])
48 |
49 | def model_func(model, batch_dict):
50 | load_data_to_gpu(batch_dict)
51 | ret_dict, tb_dict, disp_dict = model(batch_dict)
52 |
53 | loss = ret_dict['loss'].mean()
54 | if hasattr(model, 'update_global_step'):
55 | model.update_global_step()
56 | else:
57 | model.module.update_global_step()
58 |
59 | return ModelReturn(loss, tb_dict, disp_dict)
60 |
61 | return model_func
62 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_2d/__init__.py:
--------------------------------------------------------------------------------
1 | from .base_bev_backbone import BaseBEVBackbone, BaseBEVBackboneV1, BaseBEVResBackbone
2 |
3 | __all__ = {
4 | 'BaseBEVBackbone': BaseBEVBackbone,
5 | 'BaseBEVBackboneV1': BaseBEVBackboneV1,
6 | 'BaseBEVResBackbone': BaseBEVResBackbone,
7 | }
8 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_2d/fuser/__init__.py:
--------------------------------------------------------------------------------
1 | from .convfuser import ConvFuser, MAFI
2 | __all__ = {
3 | 'ConvFuser':ConvFuser,
4 | 'MAFI':MAFI,
5 | }
--------------------------------------------------------------------------------
/pcdet/models/backbones_2d/map_to_bev/__init__.py:
--------------------------------------------------------------------------------
1 | from .height_compression import HeightCompression
2 | from .pointpillar_scatter import PointPillarScatter, PointPillarScatter3d
3 | from .conv2d_collapse import Conv2DCollapse
4 |
5 | __all__ = {
6 | 'HeightCompression': HeightCompression,
7 | 'PointPillarScatter': PointPillarScatter,
8 | 'Conv2DCollapse': Conv2DCollapse,
9 | 'PointPillarScatter3d': PointPillarScatter3d,
10 | }
11 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_2d/map_to_bev/conv2d_collapse.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 |
4 | from pcdet.models.model_utils.basic_block_2d import BasicBlock2D
5 |
6 |
7 | class Conv2DCollapse(nn.Module):
8 |
9 | def __init__(self, model_cfg, grid_size):
10 | """
11 | Initializes 2D convolution collapse module
12 | Args:
13 | model_cfg: EasyDict, Model configuration
14 | grid_size: (X, Y, Z) Voxel grid size
15 | """
16 | super().__init__()
17 | self.model_cfg = model_cfg
18 | self.num_heights = grid_size[-1]
19 | self.num_bev_features = self.model_cfg.NUM_BEV_FEATURES
20 | self.block = BasicBlock2D(in_channels=self.num_bev_features * self.num_heights,
21 | out_channels=self.num_bev_features,
22 | **self.model_cfg.ARGS)
23 |
24 | def forward(self, batch_dict):
25 | """
26 | Collapses voxel features to BEV via concatenation and channel reduction
27 | Args:
28 | batch_dict:
29 | voxel_features: (B, C, Z, Y, X), Voxel feature representation
30 | Returns:
31 | batch_dict:
32 | spatial_features: (B, C, Y, X), BEV feature representation
33 | """
34 | voxel_features = batch_dict["voxel_features"]
35 | bev_features = voxel_features.flatten(start_dim=1, end_dim=2) # (B, C, Z, Y, X) -> (B, C*Z, Y, X)
36 | bev_features = self.block(bev_features) # (B, C*Z, Y, X) -> (B, C, Y, X)
37 | batch_dict["spatial_features"] = bev_features
38 | return batch_dict
39 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_2d/map_to_bev/height_compression.py:
--------------------------------------------------------------------------------
1 | import torch.nn as nn
2 |
3 |
4 | class HeightCompression(nn.Module):
5 | def __init__(self, model_cfg, **kwargs):
6 | super().__init__()
7 | self.model_cfg = model_cfg
8 | self.num_bev_features = self.model_cfg.NUM_BEV_FEATURES
9 |
10 | def forward(self, batch_dict):
11 | """
12 | Args:
13 | batch_dict:
14 | encoded_spconv_tensor: sparse tensor
15 | Returns:
16 | batch_dict:
17 | spatial_features:
18 |
19 | """
20 | encoded_spconv_tensor = batch_dict['encoded_spconv_tensor']
21 | spatial_features = encoded_spconv_tensor.dense()
22 | N, C, D, H, W = spatial_features.shape
23 | spatial_features = spatial_features.view(N, C * D, H, W)
24 | batch_dict['spatial_features_lidar'] = spatial_features
25 | batch_dict['spatial_features_stride'] = batch_dict['encoded_spconv_tensor_stride']
26 | return batch_dict
--------------------------------------------------------------------------------
/pcdet/models/backbones_2d/neck/__init__.py:
--------------------------------------------------------------------------------
1 | from .lssfpn import LSSFPN
2 | __all__ = {
3 | 'LSSFPN': LSSFPN,
4 | }
--------------------------------------------------------------------------------
/pcdet/models/backbones_2d/neck/lssfpn.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 | import torch.nn.functional as F
4 | from typing import List, Tuple
5 |
6 | class LSSFPN(nn.Module):
7 | def __init__(
8 | self,
9 | model_cfg
10 | ) -> None:
11 | super().__init__()
12 | self.in_indices = model_cfg.in_indices
13 | self.in_channels = model_cfg.in_channels
14 | self.out_channels = model_cfg.out_channels
15 | self.scale_factor = model_cfg.scale_factor
16 | self.fuse = nn.Sequential(
17 | nn.Conv2d(self.in_channels[0] + self.in_channels[1], self.out_channels, 1, bias=False),
18 | nn.BatchNorm2d(self.out_channels),
19 | nn.ReLU(True),
20 | nn.Conv2d(self.out_channels, self.out_channels, 3, padding=1, bias=False),
21 | nn.BatchNorm2d(self.out_channels),
22 | nn.ReLU(True),
23 | )
24 | if self.scale_factor > 1:
25 | self.upsample = nn.Sequential(
26 | nn.Upsample(
27 | scale_factor=self.scale_factor,
28 | mode="bilinear",
29 | align_corners=True,
30 | ),
31 | nn.Conv2d(self.out_channels, self.out_channels, 3, padding=1, bias=False),
32 | nn.BatchNorm2d(self.out_channels),
33 | nn.ReLU(True),
34 | )
35 |
36 | def forward(self, data_dict) -> torch.Tensor:
37 | x = data_dict['spatial_features_2d']
38 | x1 = x[self.in_indices[0]]
39 | assert x1.shape[1] == self.in_channels[0]
40 | x2 = x[self.in_indices[1]]
41 | assert x2.shape[1] == self.in_channels[1]
42 |
43 | x1 = F.interpolate(
44 | x1,
45 | size=x2.shape[-2:],
46 | mode="bilinear",
47 | align_corners=True,
48 | )
49 | x = torch.cat([x1, x2], dim=1)
50 |
51 | x = self.fuse(x)
52 | if self.scale_factor > 1:
53 | x = self.upsample(x)
54 | data_dict['spatial_features_2d'] = x
55 | x = self.upsample(x)
56 | data_dict['spatial_features_2d_4x'] = x
57 | return data_dict
58 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/__init__.py:
--------------------------------------------------------------------------------
1 | from .pointnet2_backbone import PointNet2Backbone, PointNet2MSG
2 | from .spconv_backbone import VoxelBackBone8x, VoxelResBackBone8x
3 | from .spconv_backbone_2d import PillarBackBone8x, PillarRes18BackBone8x
4 | from .spconv_backbone_focal import VoxelBackBone8xFocal
5 | from .spconv_backbone_voxelnext import VoxelResBackBone8xVoxelNeXt
6 | from .spconv_backbone_voxelnext2d import VoxelResBackBone8xVoxelNeXt2D
7 | from .spconv_unet import UNetV2
8 | from .dsvt import DSVT
9 |
10 | __all__ = {
11 | 'VoxelBackBone8x': VoxelBackBone8x,
12 | 'UNetV2': UNetV2,
13 | 'PointNet2Backbone': PointNet2Backbone,
14 | 'PointNet2MSG': PointNet2MSG,
15 | 'VoxelResBackBone8x': VoxelResBackBone8x,
16 | 'VoxelBackBone8xFocal': VoxelBackBone8xFocal,
17 | 'VoxelResBackBone8xVoxelNeXt': VoxelResBackBone8xVoxelNeXt,
18 | 'VoxelResBackBone8xVoxelNeXt2D': VoxelResBackBone8xVoxelNeXt2D,
19 | 'PillarBackBone8x': PillarBackBone8x,
20 | 'PillarRes18BackBone8x': PillarRes18BackBone8x,
21 | 'DSVT': DSVT,
22 | }
23 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/focal_sparse_conv/SemanticSeg/basic_blocks.py:
--------------------------------------------------------------------------------
1 | import torch.nn as nn
2 |
3 | class BasicBlock1D(nn.Module):
4 |
5 | def __init__(self, in_channels, out_channels, **kwargs):
6 | """
7 | Initializes convolutional block
8 | Args:
9 | in_channels: int, Number of input channels
10 | out_channels: int, Number of output channels
11 | **kwargs: Dict, Extra arguments for nn.Conv2d
12 | """
13 | super().__init__()
14 | self.in_channels = in_channels
15 | self.out_channels = out_channels
16 | self.conv = nn.Conv1d(in_channels=in_channels,
17 | out_channels=out_channels,
18 | **kwargs)
19 | self.bn = nn.BatchNorm1d(out_channels)
20 | self.relu = nn.ReLU(inplace=True)
21 |
22 | def forward(self, features):
23 | """
24 | Applies convolutional block
25 | Args:
26 | features: (B, C_in, H, W), Input features
27 | Returns:
28 | x: (B, C_out, H, W), Output features
29 | """
30 | x = self.conv(features)
31 | x = self.bn(x)
32 | x = self.relu(x)
33 | return x
34 |
35 | class BasicBlock2D(nn.Module):
36 |
37 | def __init__(self, in_channels, out_channels, **kwargs):
38 | """
39 | Initializes convolutional block
40 | Args:
41 | in_channels: int, Number of input channels
42 | out_channels: int, Number of output channels
43 | **kwargs: Dict, Extra arguments for nn.Conv2d
44 | """
45 | super().__init__()
46 | self.in_channels = in_channels
47 | self.out_channels = out_channels
48 | self.conv = nn.Conv2d(in_channels=in_channels,
49 | out_channels=out_channels,
50 | **kwargs)
51 | self.bn = nn.BatchNorm2d(out_channels)
52 | self.relu = nn.ReLU(inplace=True)
53 |
54 | def forward(self, features):
55 | """
56 | Applies convolutional block
57 | Args:
58 | features: (B, C_in, H, W), Input features
59 | Returns:
60 | x: (B, C_out, H, W), Output features
61 | """
62 | x = self.conv(features)
63 | x = self.bn(x)
64 | x = self.relu(x)
65 | return x
66 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/focal_sparse_conv/SemanticSeg/pyramid_ffn.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 | from .basic_blocks import BasicBlock2D
4 | from .sem_deeplabv3 import SemDeepLabV3
5 |
6 | class PyramidFeat2D(nn.Module):
7 |
8 | def __init__(self, optimize, model_cfg):
9 | """
10 | Initialize 2D feature network via pretrained model
11 | Args:
12 | model_cfg: EasyDict, Dense classification network config
13 | """
14 | super().__init__()
15 | self.model_cfg = model_cfg
16 | self.is_optimize = optimize
17 |
18 | # Create modules
19 | self.ifn = SemDeepLabV3(
20 | num_classes=model_cfg.num_class,
21 | backbone_name=model_cfg.backbone,
22 | **model_cfg.args
23 | )
24 | self.reduce_blocks = torch.nn.ModuleList()
25 | self.out_channels = {}
26 | for _idx, _channel in enumerate(model_cfg.channel_reduce["in_channels"]):
27 | _channel_out = model_cfg.channel_reduce["out_channels"][_idx]
28 | self.out_channels[model_cfg.args['feat_extract_layer'][_idx]] = _channel_out
29 | block_cfg = {"in_channels": _channel,
30 | "out_channels": _channel_out,
31 | "kernel_size": model_cfg.channel_reduce["kernel_size"][_idx],
32 | "stride": model_cfg.channel_reduce["stride"][_idx],
33 | "bias": model_cfg.channel_reduce["bias"][_idx]}
34 | self.reduce_blocks.append(BasicBlock2D(**block_cfg))
35 |
36 | def get_output_feature_dim(self):
37 | return self.out_channels
38 |
39 | def forward(self, images):
40 | """
41 | Predicts depths and creates image depth feature volume using depth distributions
42 | Args:
43 | images: (N, 3, H_in, W_in), Input images
44 | Returns:
45 | batch_dict:
46 | frustum_features: (N, C, D, H_out, W_out), Image depth features
47 | """
48 | # Pixel-wise depth classification
49 | batch_dict = {}
50 | ifn_result = self.ifn(images)
51 |
52 | for _idx, _layer in enumerate(self.model_cfg.args['feat_extract_layer']):
53 | image_features = ifn_result[_layer]
54 | # Channel reduce
55 | if self.reduce_blocks[_idx] is not None:
56 | image_features = self.reduce_blocks[_idx](image_features)
57 |
58 | batch_dict[_layer+"_feat2d"] = image_features
59 |
60 | if self.training:
61 | # detach feature from graph if not optimize
62 | if "logits" in ifn_result:
63 | ifn_result["logits"].detach_()
64 | if not self.is_optimize:
65 | image_features.detach_()
66 |
67 | return batch_dict
68 |
69 | def get_loss(self):
70 | """
71 | Gets loss
72 | Args:
73 | Returns:
74 | loss: (1), Network loss
75 | tb_dict: dict[float], All losses to log in tensorboard
76 | """
77 | return None, None
78 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/pfe/__init__.py:
--------------------------------------------------------------------------------
1 | from .voxel_set_abstraction import VoxelSetAbstraction
2 |
3 | __all__ = {
4 | 'VoxelSetAbstraction': VoxelSetAbstraction
5 | }
6 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/vfe/__init__.py:
--------------------------------------------------------------------------------
1 | from .mean_vfe import MeanVFE
2 | from .pillar_vfe import PillarVFE
3 | from .dynamic_mean_vfe import DynamicMeanVFE
4 | from .dynamic_pillar_vfe import DynamicPillarVFE, DynamicPillarVFESimple2D
5 | from .dynamic_voxel_vfe import DynamicVoxelVFE
6 | from .image_vfe import ImageVFE
7 | from .vfe_template import VFETemplate
8 |
9 | __all__ = {
10 | 'VFETemplate': VFETemplate,
11 | 'MeanVFE': MeanVFE,
12 | 'PillarVFE': PillarVFE,
13 | 'ImageVFE': ImageVFE,
14 | 'DynMeanVFE': DynamicMeanVFE,
15 | 'DynPillarVFE': DynamicPillarVFE,
16 | 'DynamicPillarVFESimple2D': DynamicPillarVFESimple2D,
17 | 'DynamicVoxelVFE': DynamicVoxelVFE,
18 | }
19 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/vfe/dynamic_mean_vfe.py:
--------------------------------------------------------------------------------
1 | import torch
2 |
3 | from .vfe_template import VFETemplate
4 |
5 | try:
6 | import torch_scatter
7 | except Exception as e:
8 | # Incase someone doesn't want to use dynamic pillar vfe and hasn't installed torch_scatter
9 | pass
10 |
11 | from .vfe_template import VFETemplate
12 |
13 |
14 | class DynamicMeanVFE(VFETemplate):
15 | def __init__(self, model_cfg, num_point_features, voxel_size, grid_size, point_cloud_range, **kwargs):
16 | super().__init__(model_cfg=model_cfg)
17 | self.num_point_features = num_point_features
18 |
19 | self.grid_size = torch.tensor(grid_size).cuda()
20 | self.voxel_size = torch.tensor(voxel_size).cuda()
21 | self.point_cloud_range = torch.tensor(point_cloud_range).cuda()
22 |
23 | self.voxel_x = voxel_size[0]
24 | self.voxel_y = voxel_size[1]
25 | self.voxel_z = voxel_size[2]
26 | self.x_offset = self.voxel_x / 2 + point_cloud_range[0]
27 | self.y_offset = self.voxel_y / 2 + point_cloud_range[1]
28 | self.z_offset = self.voxel_z / 2 + point_cloud_range[2]
29 |
30 | self.scale_xyz = grid_size[0] * grid_size[1] * grid_size[2]
31 | self.scale_yz = grid_size[1] * grid_size[2]
32 | self.scale_z = grid_size[2]
33 |
34 | def get_output_feature_dim(self):
35 | return self.num_point_features
36 |
37 | @torch.no_grad()
38 | def forward(self, batch_dict, **kwargs):
39 | """
40 | Args:
41 | batch_dict:
42 | voxels: (num_voxels, max_points_per_voxel, C)
43 | voxel_num_points: optional (num_voxels)
44 | **kwargs:
45 |
46 | Returns:
47 | vfe_features: (num_voxels, C)
48 | """
49 | batch_size = batch_dict['batch_size']
50 | points = batch_dict['points'] # (batch_idx, x, y, z, i, e)
51 |
52 | # # debug
53 | point_coords = torch.floor((points[:, 1:4] - self.point_cloud_range[0:3]) / self.voxel_size).int()
54 | mask = ((point_coords >= 0) & (point_coords < self.grid_size)).all(dim=1)
55 | points = points[mask]
56 | point_coords = point_coords[mask]
57 | merge_coords = points[:, 0].int() * self.scale_xyz + \
58 | point_coords[:, 0] * self.scale_yz + \
59 | point_coords[:, 1] * self.scale_z + \
60 | point_coords[:, 2]
61 | points_data = points[:, 1:].contiguous()
62 |
63 | unq_coords, unq_inv, unq_cnt = torch.unique(merge_coords, return_inverse=True, return_counts=True)
64 |
65 | points_mean = torch_scatter.scatter_mean(points_data, unq_inv, dim=0)
66 |
67 | unq_coords = unq_coords.int()
68 | voxel_coords = torch.stack((unq_coords // self.scale_xyz,
69 | (unq_coords % self.scale_xyz) // self.scale_yz,
70 | (unq_coords % self.scale_yz) // self.scale_z,
71 | unq_coords % self.scale_z), dim=1)
72 | voxel_coords = voxel_coords[:, [0, 3, 2, 1]]
73 |
74 | batch_dict['voxel_features'] = points_mean.contiguous()
75 | batch_dict['voxel_coords'] = voxel_coords.contiguous()
76 | return batch_dict
77 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/vfe/image_vfe.py:
--------------------------------------------------------------------------------
1 | import torch
2 |
3 | from .vfe_template import VFETemplate
4 | from .image_vfe_modules import ffn, f2v
5 |
6 |
7 | class ImageVFE(VFETemplate):
8 | def __init__(self, model_cfg, grid_size, point_cloud_range, depth_downsample_factor, **kwargs):
9 | super().__init__(model_cfg=model_cfg)
10 | self.grid_size = grid_size
11 | self.pc_range = point_cloud_range
12 | self.downsample_factor = depth_downsample_factor
13 | self.module_topology = [
14 | 'ffn', 'f2v'
15 | ]
16 | self.build_modules()
17 |
18 | def build_modules(self):
19 | """
20 | Builds modules
21 | """
22 | for module_name in self.module_topology:
23 | module = getattr(self, 'build_%s' % module_name)()
24 | self.add_module(module_name, module)
25 |
26 | def build_ffn(self):
27 | """
28 | Builds frustum feature network
29 | Returns:
30 | ffn_module: nn.Module, Frustum feature network
31 | """
32 | ffn_module = ffn.__all__[self.model_cfg.FFN.NAME](
33 | model_cfg=self.model_cfg.FFN,
34 | downsample_factor=self.downsample_factor
35 | )
36 | self.disc_cfg = ffn_module.disc_cfg
37 | return ffn_module
38 |
39 | def build_f2v(self):
40 | """
41 | Builds frustum to voxel transformation
42 | Returns:
43 | f2v_module: nn.Module, Frustum to voxel transformation
44 | """
45 | f2v_module = f2v.__all__[self.model_cfg.F2V.NAME](
46 | model_cfg=self.model_cfg.F2V,
47 | grid_size=self.grid_size,
48 | pc_range=self.pc_range,
49 | disc_cfg=self.disc_cfg
50 | )
51 | return f2v_module
52 |
53 | def get_output_feature_dim(self):
54 | """
55 | Gets number of output channels
56 | Returns:
57 | out_feature_dim: int, Number of output channels
58 | """
59 | out_feature_dim = self.ffn.get_output_feature_dim()
60 | return out_feature_dim
61 |
62 | def forward(self, batch_dict, **kwargs):
63 | """
64 | Args:
65 | batch_dict:
66 | images: (N, 3, H_in, W_in), Input images
67 | **kwargs:
68 | Returns:
69 | batch_dict:
70 | voxel_features: (B, C, Z, Y, X), Image voxel features
71 | """
72 | batch_dict = self.ffn(batch_dict)
73 | batch_dict = self.f2v(batch_dict)
74 | return batch_dict
75 |
76 | def get_loss(self):
77 | """
78 | Gets DDN loss
79 | Returns:
80 | loss: (1), Depth distribution network loss
81 | tb_dict: dict[float], All losses to log in tensorboard
82 | """
83 |
84 | loss, tb_dict = self.ffn.get_loss()
85 | return loss, tb_dict
86 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/vfe/image_vfe_modules/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/models/backbones_3d/vfe/image_vfe_modules/__init__.py
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/vfe/image_vfe_modules/f2v/__init__.py:
--------------------------------------------------------------------------------
1 | from .frustum_to_voxel import FrustumToVoxel
2 |
3 | __all__ = {
4 | 'FrustumToVoxel': FrustumToVoxel
5 | }
6 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/vfe/image_vfe_modules/f2v/frustum_to_voxel.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 |
4 | from .frustum_grid_generator import FrustumGridGenerator
5 | from .sampler import Sampler
6 |
7 |
8 | class FrustumToVoxel(nn.Module):
9 |
10 | def __init__(self, model_cfg, grid_size, pc_range, disc_cfg):
11 | """
12 | Initializes module to transform frustum features to voxel features via 3D transformation and sampling
13 | Args:
14 | model_cfg: EasyDict, Module configuration
15 | grid_size: [X, Y, Z], Voxel grid size
16 | pc_range: [x_min, y_min, z_min, x_max, y_max, z_max], Voxelization point cloud range (m)
17 | disc_cfg: EasyDict, Depth discretiziation configuration
18 | """
19 | super().__init__()
20 | self.model_cfg = model_cfg
21 | self.grid_size = grid_size
22 | self.pc_range = pc_range
23 | self.disc_cfg = disc_cfg
24 | self.grid_generator = FrustumGridGenerator(grid_size=grid_size,
25 | pc_range=pc_range,
26 | disc_cfg=disc_cfg)
27 | self.sampler = Sampler(**model_cfg.SAMPLER)
28 |
29 | def forward(self, batch_dict):
30 | """
31 | Generates voxel features via 3D transformation and sampling
32 | Args:
33 | batch_dict:
34 | frustum_features: (B, C, D, H_image, W_image), Image frustum features
35 | lidar_to_cam: (B, 4, 4), LiDAR to camera frame transformation
36 | cam_to_img: (B, 3, 4), Camera projection matrix
37 | image_shape: (B, 2), Image shape [H, W]
38 | Returns:
39 | batch_dict:
40 | voxel_features: (B, C, Z, Y, X), Image voxel features
41 | """
42 | # Generate sampling grid for frustum volume
43 | grid = self.grid_generator(lidar_to_cam=batch_dict["trans_lidar_to_cam"],
44 | cam_to_img=batch_dict["trans_cam_to_img"],
45 | image_shape=batch_dict["image_shape"]) # (B, X, Y, Z, 3)
46 |
47 | # Sample frustum volume to generate voxel volume
48 | voxel_features = self.sampler(input_features=batch_dict["frustum_features"],
49 | grid=grid) # (B, C, X, Y, Z)
50 |
51 | # (B, C, X, Y, Z) -> (B, C, Z, Y, X)
52 | voxel_features = voxel_features.permute(0, 1, 4, 3, 2)
53 | batch_dict["voxel_features"] = voxel_features
54 | return batch_dict
55 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/vfe/image_vfe_modules/f2v/sampler.py:
--------------------------------------------------------------------------------
1 | from functools import partial
2 |
3 | import torch
4 | import torch.nn as nn
5 | import torch.nn.functional as F
6 |
7 |
8 | class Sampler(nn.Module):
9 |
10 | def __init__(self, mode="bilinear", padding_mode="zeros"):
11 | """
12 | Initializes module
13 | Args:
14 | mode: string, Sampling mode [bilinear/nearest]
15 | padding_mode: string, Padding mode for outside grid values [zeros/border/reflection]
16 | """
17 | super().__init__()
18 | self.mode = mode
19 | self.padding_mode = padding_mode
20 |
21 | if torch.__version__ >= '1.3':
22 | self.grid_sample = partial(F.grid_sample, align_corners=True)
23 | else:
24 | self.grid_sample = F.grid_sample
25 |
26 | def forward(self, input_features, grid):
27 | """
28 | Samples input using sampling grid
29 | Args:
30 | input_features: (B, C, D, H, W), Input frustum features
31 | grid: (B, X, Y, Z, 3), Sampling grids for input features
32 | Returns
33 | output_features: (B, C, X, Y, Z) Output voxel features
34 | """
35 | # Sample from grid
36 | output = self.grid_sample(input=input_features, grid=grid, mode=self.mode, padding_mode=self.padding_mode)
37 | return output
38 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/vfe/image_vfe_modules/ffn/__init__.py:
--------------------------------------------------------------------------------
1 | from .depth_ffn import DepthFFN
2 |
3 | __all__ = {
4 | 'DepthFFN': DepthFFN
5 | }
6 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/vfe/image_vfe_modules/ffn/ddn/__init__.py:
--------------------------------------------------------------------------------
1 | from .ddn_deeplabv3 import DDNDeepLabV3
2 |
3 | __all__ = {
4 | 'DDNDeepLabV3': DDNDeepLabV3
5 | }
6 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/vfe/image_vfe_modules/ffn/ddn/ddn_deeplabv3.py:
--------------------------------------------------------------------------------
1 | from .ddn_template import DDNTemplate
2 |
3 | try:
4 | import torchvision
5 | except:
6 | pass
7 |
8 |
9 | class DDNDeepLabV3(DDNTemplate):
10 |
11 | def __init__(self, backbone_name, **kwargs):
12 | """
13 | Initializes DDNDeepLabV3 model
14 | Args:
15 | backbone_name: string, ResNet Backbone Name [ResNet50/ResNet101]
16 | """
17 | if backbone_name == "ResNet50":
18 | constructor = torchvision.models.segmentation.deeplabv3_resnet50
19 | elif backbone_name == "ResNet101":
20 | constructor = torchvision.models.segmentation.deeplabv3_resnet101
21 | else:
22 | raise NotImplementedError
23 |
24 | super().__init__(constructor=constructor, **kwargs)
25 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/vfe/image_vfe_modules/ffn/ddn_loss/__init__.py:
--------------------------------------------------------------------------------
1 | from .ddn_loss import DDNLoss
2 |
3 | __all__ = {
4 | "DDNLoss": DDNLoss
5 | }
6 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/vfe/image_vfe_modules/ffn/ddn_loss/balancer.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 |
4 | from pcdet.utils import loss_utils
5 |
6 |
7 | class Balancer(nn.Module):
8 | def __init__(self, fg_weight, bg_weight, downsample_factor=1):
9 | """
10 | Initialize fixed foreground/background loss balancer
11 | Args:
12 | fg_weight: float, Foreground loss weight
13 | bg_weight: float, Background loss weight
14 | downsample_factor: int, Depth map downsample factor
15 | """
16 | super().__init__()
17 | self.fg_weight = fg_weight
18 | self.bg_weight = bg_weight
19 | self.downsample_factor = downsample_factor
20 |
21 | def forward(self, loss, gt_boxes2d):
22 | """
23 | Forward pass
24 | Args:
25 | loss: (B, H, W), Pixel-wise loss
26 | gt_boxes2d: (B, N, 4), 2D box labels for foreground/background balancing
27 | Returns:
28 | loss: (1), Total loss after foreground/background balancing
29 | tb_dict: dict[float], All losses to log in tensorboard
30 | """
31 | # Compute masks
32 | fg_mask = loss_utils.compute_fg_mask(gt_boxes2d=gt_boxes2d,
33 | shape=loss.shape,
34 | downsample_factor=self.downsample_factor,
35 | device=loss.device)
36 | bg_mask = ~fg_mask
37 |
38 | # Compute balancing weights
39 | weights = self.fg_weight * fg_mask + self.bg_weight * bg_mask
40 | num_pixels = fg_mask.sum() + bg_mask.sum()
41 |
42 | # Compute losses
43 | loss *= weights
44 | fg_loss = loss[fg_mask].sum() / num_pixels
45 | bg_loss = loss[bg_mask].sum() / num_pixels
46 |
47 | # Get total loss
48 | loss = fg_loss + bg_loss
49 | tb_dict = {"balancer_loss": loss.item(), "fg_loss": fg_loss.item(), "bg_loss": bg_loss.item()}
50 | return loss, tb_dict
51 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/vfe/image_vfe_modules/ffn/ddn_loss/ddn_loss.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 |
4 |
5 | from .balancer import Balancer
6 | from pcdet.utils import transform_utils
7 |
8 | try:
9 | from kornia.losses.focal import FocalLoss
10 | except:
11 | pass
12 | # print('Warning: kornia is not installed. This package is only required by CaDDN')
13 |
14 |
15 | class DDNLoss(nn.Module):
16 |
17 | def __init__(self,
18 | weight,
19 | alpha,
20 | gamma,
21 | disc_cfg,
22 | fg_weight,
23 | bg_weight,
24 | downsample_factor):
25 | """
26 | Initializes DDNLoss module
27 | Args:
28 | weight: float, Loss function weight
29 | alpha: float, Alpha value for Focal Loss
30 | gamma: float, Gamma value for Focal Loss
31 | disc_cfg: dict, Depth discretiziation configuration
32 | fg_weight: float, Foreground loss weight
33 | bg_weight: float, Background loss weight
34 | downsample_factor: int, Depth map downsample factor
35 | """
36 | super().__init__()
37 | self.device = torch.cuda.current_device()
38 | self.disc_cfg = disc_cfg
39 | self.balancer = Balancer(downsample_factor=downsample_factor,
40 | fg_weight=fg_weight,
41 | bg_weight=bg_weight)
42 |
43 | # Set loss function
44 | self.alpha = alpha
45 | self.gamma = gamma
46 | self.loss_func = FocalLoss(alpha=self.alpha, gamma=self.gamma, reduction="none")
47 | self.weight = weight
48 |
49 | def forward(self, depth_logits, depth_maps, gt_boxes2d):
50 | """
51 | Gets DDN loss
52 | Args:
53 | depth_logits: (B, D+1, H, W), Predicted depth logits
54 | depth_maps: (B, H, W), Depth map [m]
55 | gt_boxes2d: torch.Tensor (B, N, 4), 2D box labels for foreground/background balancing
56 | Returns:
57 | loss: (1), Depth distribution network loss
58 | tb_dict: dict[float], All losses to log in tensorboard
59 | """
60 | tb_dict = {}
61 |
62 | # Bin depth map to create target
63 | depth_target = transform_utils.bin_depths(depth_maps, **self.disc_cfg, target=True)
64 |
65 | # Compute loss
66 | loss = self.loss_func(depth_logits, depth_target)
67 |
68 | # Compute foreground/background balancing
69 | loss, tb_dict = self.balancer(loss=loss, gt_boxes2d=gt_boxes2d)
70 |
71 | # Final loss
72 | loss *= self.weight
73 | tb_dict.update({"ddn_loss": loss.item()})
74 |
75 | return loss, tb_dict
76 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/vfe/mean_vfe.py:
--------------------------------------------------------------------------------
1 | import torch
2 |
3 | from .vfe_template import VFETemplate
4 |
5 |
6 | class MeanVFE(VFETemplate):
7 | def __init__(self, model_cfg, num_point_features, **kwargs):
8 | super().__init__(model_cfg=model_cfg)
9 | self.num_point_features = num_point_features
10 |
11 | def get_output_feature_dim(self):
12 | return self.num_point_features
13 |
14 | def forward(self, batch_dict, **kwargs):
15 | """
16 | Args:
17 | batch_dict:
18 | voxels: (num_voxels, max_points_per_voxel, C)
19 | voxel_num_points: optional (num_voxels)
20 | **kwargs:
21 |
22 | Returns:
23 | vfe_features: (num_voxels, C)
24 | """
25 | voxel_features, voxel_num_points = batch_dict['voxels'], batch_dict['voxel_num_points']
26 | points_mean = voxel_features[:, :, :].sum(dim=1, keepdim=False)
27 | normalizer = torch.clamp_min(voxel_num_points.view(-1, 1), min=1.0).type_as(voxel_features)
28 | points_mean = points_mean / normalizer
29 | batch_dict['voxel_features'] = points_mean.contiguous()
30 |
31 | return batch_dict
32 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_3d/vfe/vfe_template.py:
--------------------------------------------------------------------------------
1 | import torch.nn as nn
2 |
3 |
4 | class VFETemplate(nn.Module):
5 | def __init__(self, model_cfg, **kwargs):
6 | super().__init__()
7 | self.model_cfg = model_cfg
8 |
9 | def get_output_feature_dim(self):
10 | raise NotImplementedError
11 |
12 | def forward(self, **kwargs):
13 | """
14 | Args:
15 | **kwargs:
16 |
17 | Returns:
18 | batch_dict:
19 | ...
20 | vfe_features: (num_voxels, C)
21 | """
22 | raise NotImplementedError
23 |
--------------------------------------------------------------------------------
/pcdet/models/backbones_image/__init__.py:
--------------------------------------------------------------------------------
1 | from .swin import SwinTransformer
2 | __all__ = {
3 | 'SwinTransformer':SwinTransformer,
4 | }
--------------------------------------------------------------------------------
/pcdet/models/backbones_image/img_neck/__init__.py:
--------------------------------------------------------------------------------
1 | from .generalized_lss import GeneralizedLSSFPN
2 | __all__ = {
3 | 'GeneralizedLSSFPN':GeneralizedLSSFPN,
4 | }
--------------------------------------------------------------------------------
/pcdet/models/backbones_image/img_neck/generalized_lss.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 | import torch.nn.functional as F
4 | from ...model_utils.basic_block_2d import BasicBlock2D
5 |
6 |
7 | class GeneralizedLSSFPN(nn.Module):
8 | """
9 | This module implements FPN, which creates pyramid features built on top of some input feature maps.
10 | This code is adapted from https://github.com/open-mmlab/mmdetection/blob/main/mmdet/models/necks/fpn.py with minimal modifications.
11 | """
12 | def __init__(self, model_cfg):
13 | super().__init__()
14 | self.model_cfg = model_cfg
15 | in_channels = self.model_cfg.IN_CHANNELS
16 | out_channels = self.model_cfg.OUT_CHANNELS
17 | num_ins = len(in_channels)
18 | num_outs = self.model_cfg.NUM_OUTS
19 | start_level = self.model_cfg.START_LEVEL
20 | end_level = self.model_cfg.END_LEVEL
21 |
22 | self.in_channels = in_channels
23 |
24 | if end_level == -1:
25 | self.backbone_end_level = num_ins - 1
26 | else:
27 | self.backbone_end_level = end_level
28 | assert end_level <= len(in_channels)
29 | assert num_outs == end_level - start_level
30 | self.start_level = start_level
31 | self.end_level = end_level
32 |
33 | self.lateral_convs = nn.ModuleList()
34 | self.fpn_convs = nn.ModuleList()
35 |
36 | for i in range(self.start_level, self.backbone_end_level):
37 | l_conv = BasicBlock2D(
38 | in_channels[i] + (in_channels[i + 1] if i == self.backbone_end_level - 1 else out_channels),
39 | out_channels, kernel_size=1, bias = False
40 | )
41 | fpn_conv = BasicBlock2D(out_channels,out_channels, kernel_size=3, padding=1, bias = False)
42 | self.lateral_convs.append(l_conv)
43 | self.fpn_convs.append(fpn_conv)
44 |
45 | def forward(self, batch_dict):
46 | """
47 | Args:
48 | batch_dict:
49 | image_features (list[tensor]): Multi-stage features from image backbone.
50 | Returns:
51 | batch_dict:
52 | image_fpn (list(tensor)): FPN features.
53 | """
54 | # upsample -> cat -> conv1x1 -> conv3x3
55 | inputs = batch_dict['image_features']
56 | assert len(inputs) == len(self.in_channels)
57 |
58 | # build laterals
59 | laterals = [inputs[i + self.start_level] for i in range(len(inputs))]
60 |
61 | # build top-down path
62 | used_backbone_levels = len(laterals) - 1
63 | for i in range(used_backbone_levels - 1, -1, -1):
64 | x = F.interpolate(
65 | laterals[i + 1],
66 | size=laterals[i].shape[2:],
67 | mode='bilinear', align_corners=False,
68 | )
69 | laterals[i] = torch.cat([laterals[i], x], dim=1)
70 | laterals[i] = self.lateral_convs[i](laterals[i])
71 | laterals[i] = self.fpn_convs[i](laterals[i])
72 |
73 | # build outputs
74 | outs = [laterals[i] for i in range(used_backbone_levels)]
75 | batch_dict['image_fpn'] = tuple(outs)
76 | return batch_dict
77 |
--------------------------------------------------------------------------------
/pcdet/models/dense_heads/__init__.py:
--------------------------------------------------------------------------------
1 | from .anchor_head_multi import AnchorHeadMulti
2 | from .anchor_head_single import AnchorHeadSingle
3 | from .anchor_head_template import AnchorHeadTemplate
4 | from .point_head_box import PointHeadBox
5 | from .point_head_simple import PointHeadSimple
6 | from .point_intra_part_head import PointIntraPartOffsetHead
7 | from .center_head import CenterHead
8 | from .voxelnext_head import VoxelNeXtHead
9 | from .transfusion_head import TransFusionHead
10 | from .m3net_head import M3NetHead
11 |
12 | __all__ = {
13 | 'AnchorHeadTemplate': AnchorHeadTemplate,
14 | 'AnchorHeadSingle': AnchorHeadSingle,
15 | 'PointIntraPartOffsetHead': PointIntraPartOffsetHead,
16 | 'PointHeadSimple': PointHeadSimple,
17 | 'PointHeadBox': PointHeadBox,
18 | 'AnchorHeadMulti': AnchorHeadMulti,
19 | 'CenterHead': CenterHead,
20 | 'VoxelNeXtHead': VoxelNeXtHead,
21 | 'TransFusionHead': TransFusionHead,
22 | 'M3NetHead': M3NetHead,
23 | }
24 |
--------------------------------------------------------------------------------
/pcdet/models/dense_heads/anchor_head_single.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import torch.nn as nn
3 |
4 | from .anchor_head_template import AnchorHeadTemplate
5 |
6 |
7 | class AnchorHeadSingle(AnchorHeadTemplate):
8 | def __init__(self, model_cfg, input_channels, num_class, class_names, grid_size, point_cloud_range,
9 | predict_boxes_when_training=True, **kwargs):
10 | super().__init__(
11 | model_cfg=model_cfg, num_class=num_class, class_names=class_names, grid_size=grid_size, point_cloud_range=point_cloud_range,
12 | predict_boxes_when_training=predict_boxes_when_training
13 | )
14 |
15 | self.num_anchors_per_location = sum(self.num_anchors_per_location)
16 |
17 | self.conv_cls = nn.Conv2d(
18 | input_channels, self.num_anchors_per_location * self.num_class,
19 | kernel_size=1
20 | )
21 | self.conv_box = nn.Conv2d(
22 | input_channels, self.num_anchors_per_location * self.box_coder.code_size,
23 | kernel_size=1
24 | )
25 |
26 | if self.model_cfg.get('USE_DIRECTION_CLASSIFIER', None) is not None:
27 | self.conv_dir_cls = nn.Conv2d(
28 | input_channels,
29 | self.num_anchors_per_location * self.model_cfg.NUM_DIR_BINS,
30 | kernel_size=1
31 | )
32 | else:
33 | self.conv_dir_cls = None
34 | self.init_weights()
35 |
36 | def init_weights(self):
37 | pi = 0.01
38 | nn.init.constant_(self.conv_cls.bias, -np.log((1 - pi) / pi))
39 | nn.init.normal_(self.conv_box.weight, mean=0, std=0.001)
40 |
41 | def forward(self, data_dict):
42 | spatial_features_2d = data_dict['spatial_features_2d']
43 |
44 | cls_preds = self.conv_cls(spatial_features_2d)
45 | box_preds = self.conv_box(spatial_features_2d)
46 |
47 | cls_preds = cls_preds.permute(0, 2, 3, 1).contiguous() # [N, H, W, C]
48 | box_preds = box_preds.permute(0, 2, 3, 1).contiguous() # [N, H, W, C]
49 |
50 | self.forward_ret_dict['cls_preds'] = cls_preds
51 | self.forward_ret_dict['box_preds'] = box_preds
52 |
53 | if self.conv_dir_cls is not None:
54 | dir_cls_preds = self.conv_dir_cls(spatial_features_2d)
55 | dir_cls_preds = dir_cls_preds.permute(0, 2, 3, 1).contiguous()
56 | self.forward_ret_dict['dir_cls_preds'] = dir_cls_preds
57 | else:
58 | dir_cls_preds = None
59 |
60 | if self.training:
61 | targets_dict = self.assign_targets(
62 | gt_boxes=data_dict['gt_boxes']
63 | )
64 | self.forward_ret_dict.update(targets_dict)
65 |
66 | if not self.training or self.predict_boxes_when_training:
67 | batch_cls_preds, batch_box_preds = self.generate_predicted_boxes(
68 | batch_size=data_dict['batch_size'],
69 | cls_preds=cls_preds, box_preds=box_preds, dir_cls_preds=dir_cls_preds
70 | )
71 | data_dict['batch_cls_preds'] = batch_cls_preds
72 | data_dict['batch_box_preds'] = batch_box_preds
73 | data_dict['cls_preds_normalized'] = False
74 |
75 | return data_dict
76 |
--------------------------------------------------------------------------------
/pcdet/models/dense_heads/target_assigner/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/models/dense_heads/target_assigner/__init__.py
--------------------------------------------------------------------------------
/pcdet/models/detectors/PartA2_net.py:
--------------------------------------------------------------------------------
1 | from .detector3d_template import Detector3DTemplate
2 |
3 |
4 | class PartA2Net(Detector3DTemplate):
5 | def __init__(self, model_cfg, num_class, dataset):
6 | super().__init__(model_cfg=model_cfg, num_class=num_class, dataset=dataset)
7 | self.module_list = self.build_networks()
8 |
9 | def forward(self, batch_dict):
10 | for cur_module in self.module_list:
11 | batch_dict = cur_module(batch_dict)
12 |
13 | if self.training:
14 | loss, tb_dict, disp_dict = self.get_training_loss()
15 |
16 | ret_dict = {
17 | 'loss': loss
18 | }
19 | return ret_dict, tb_dict, disp_dict
20 | else:
21 | pred_dicts, recall_dicts = self.post_processing(batch_dict)
22 | return pred_dicts, recall_dicts
23 |
24 | def get_training_loss(self):
25 | disp_dict = {}
26 | loss_rpn, tb_dict = self.dense_head.get_loss()
27 | loss_point, tb_dict = self.point_head.get_loss(tb_dict)
28 | loss_rcnn, tb_dict = self.roi_head.get_loss(tb_dict)
29 |
30 | loss = loss_rpn + loss_point + loss_rcnn
31 | return loss, tb_dict, disp_dict
32 |
--------------------------------------------------------------------------------
/pcdet/models/detectors/__init__.py:
--------------------------------------------------------------------------------
1 | from .detector3d_template import Detector3DTemplate
2 | from .PartA2_net import PartA2Net
3 | from .point_rcnn import PointRCNN
4 | from .pointpillar import PointPillar
5 | from .pv_rcnn import PVRCNN
6 | from .second_net import SECONDNet
7 | from .second_net_iou import SECONDNetIoU
8 | from .caddn import CaDDN
9 | from .voxel_rcnn import VoxelRCNN
10 | from .centerpoint import CenterPoint
11 | from .pv_rcnn_plusplus import PVRCNNPlusPlus
12 | from .mppnet import MPPNet
13 | from .mppnet_e2e import MPPNetE2E
14 | from .pillarnet import PillarNet
15 | from .voxelnext import VoxelNeXt
16 | from .transfusion import TransFusion
17 | from .bevfusion import BevFusion
18 | from .m3net import M3Net
19 |
20 | __all__ = {
21 | 'Detector3DTemplate': Detector3DTemplate,
22 | 'SECONDNet': SECONDNet,
23 | 'PartA2Net': PartA2Net,
24 | 'PVRCNN': PVRCNN,
25 | 'PointPillar': PointPillar,
26 | 'PointRCNN': PointRCNN,
27 | 'SECONDNetIoU': SECONDNetIoU,
28 | 'CaDDN': CaDDN,
29 | 'VoxelRCNN': VoxelRCNN,
30 | 'CenterPoint': CenterPoint,
31 | 'PillarNet': PillarNet,
32 | 'PVRCNNPlusPlus': PVRCNNPlusPlus,
33 | 'MPPNet': MPPNet,
34 | 'MPPNetE2E': MPPNetE2E,
35 | 'PillarNet': PillarNet,
36 | 'VoxelNeXt': VoxelNeXt,
37 | 'TransFusion': TransFusion,
38 | 'BevFusion': BevFusion,
39 | 'M3Net': M3Net,
40 | }
41 |
42 |
43 | def build_detector(model_cfg, num_class, dataset):
44 | model = __all__[model_cfg.NAME](
45 | model_cfg=model_cfg, num_class=num_class, dataset=dataset
46 | )
47 |
48 | return model
49 |
--------------------------------------------------------------------------------
/pcdet/models/detectors/caddn.py:
--------------------------------------------------------------------------------
1 | from .detector3d_template import Detector3DTemplate
2 |
3 |
4 | class CaDDN(Detector3DTemplate):
5 | def __init__(self, model_cfg, num_class, dataset):
6 | super().__init__(model_cfg=model_cfg, num_class=num_class, dataset=dataset)
7 | self.module_list = self.build_networks()
8 |
9 | def forward(self, batch_dict):
10 | for cur_module in self.module_list:
11 | batch_dict = cur_module(batch_dict)
12 |
13 | if self.training:
14 | loss, tb_dict, disp_dict = self.get_training_loss()
15 |
16 | ret_dict = {
17 | 'loss': loss
18 | }
19 | return ret_dict, tb_dict, disp_dict
20 | else:
21 | pred_dicts, recall_dicts = self.post_processing(batch_dict)
22 | return pred_dicts, recall_dicts
23 |
24 | def get_training_loss(self):
25 | disp_dict = {}
26 |
27 | loss_rpn, tb_dict_rpn = self.dense_head.get_loss()
28 | loss_depth, tb_dict_depth = self.vfe.get_loss()
29 |
30 | tb_dict = {
31 | 'loss_rpn': loss_rpn.item(),
32 | 'loss_depth': loss_depth.item(),
33 | **tb_dict_rpn,
34 | **tb_dict_depth
35 | }
36 |
37 | loss = loss_rpn + loss_depth
38 | return loss, tb_dict, disp_dict
39 |
--------------------------------------------------------------------------------
/pcdet/models/detectors/centerpoint.py:
--------------------------------------------------------------------------------
1 | from .detector3d_template import Detector3DTemplate
2 |
3 |
4 | class CenterPoint(Detector3DTemplate):
5 | def __init__(self, model_cfg, num_class, dataset):
6 | super().__init__(model_cfg=model_cfg, num_class=num_class, dataset=dataset)
7 | self.module_list = self.build_networks()
8 |
9 | def forward(self, batch_dict):
10 | for cur_module in self.module_list:
11 | batch_dict = cur_module(batch_dict)
12 |
13 | if self.training:
14 | loss, tb_dict, disp_dict = self.get_training_loss()
15 |
16 | ret_dict = {
17 | 'loss': loss
18 | }
19 | return ret_dict, tb_dict, disp_dict
20 | else:
21 | pred_dicts, recall_dicts = self.post_processing(batch_dict)
22 | return pred_dicts, recall_dicts
23 |
24 | def get_training_loss(self):
25 | disp_dict = {}
26 |
27 | loss_rpn, tb_dict = self.dense_head.get_loss()
28 | tb_dict = {
29 | 'loss_rpn': loss_rpn.item(),
30 | **tb_dict
31 | }
32 |
33 | loss = loss_rpn
34 | return loss, tb_dict, disp_dict
35 |
36 | def post_processing(self, batch_dict):
37 | post_process_cfg = self.model_cfg.POST_PROCESSING
38 | batch_size = batch_dict['batch_size']
39 | final_pred_dict = batch_dict['final_box_dicts']
40 | recall_dict = {}
41 | for index in range(batch_size):
42 | pred_boxes = final_pred_dict[index]['pred_boxes']
43 |
44 | recall_dict = self.generate_recall_record(
45 | box_preds=pred_boxes,
46 | recall_dict=recall_dict, batch_index=index, data_dict=batch_dict,
47 | thresh_list=post_process_cfg.RECALL_THRESH_LIST
48 | )
49 |
50 | return final_pred_dict, recall_dict
51 |
--------------------------------------------------------------------------------
/pcdet/models/detectors/pillarnet.py:
--------------------------------------------------------------------------------
1 | from .detector3d_template import Detector3DTemplate
2 |
3 |
4 | class PillarNet(Detector3DTemplate):
5 | def __init__(self, model_cfg, num_class, dataset):
6 | super().__init__(model_cfg=model_cfg, num_class=num_class, dataset=dataset)
7 | self.module_list = self.build_networks()
8 |
9 | def forward(self, batch_dict):
10 | for cur_module in self.module_list:
11 | batch_dict = cur_module(batch_dict)
12 |
13 | if self.training:
14 | loss, tb_dict, disp_dict = self.get_training_loss()
15 |
16 | ret_dict = {
17 | 'loss': loss
18 | }
19 | return ret_dict, tb_dict, disp_dict
20 | else:
21 | pred_dicts, recall_dicts = self.post_processing(batch_dict)
22 | return pred_dicts, recall_dicts
23 |
24 | def get_training_loss(self):
25 | disp_dict = {}
26 |
27 | loss_rpn, tb_dict = self.dense_head.get_loss()
28 | tb_dict = {
29 | 'loss_rpn': loss_rpn.item(),
30 | **tb_dict
31 | }
32 |
33 | loss = loss_rpn
34 | return loss, tb_dict, disp_dict
35 |
36 | def post_processing(self, batch_dict):
37 | post_process_cfg = self.model_cfg.POST_PROCESSING
38 | batch_size = batch_dict['batch_size']
39 | final_pred_dict = batch_dict['final_box_dicts']
40 | recall_dict = {}
41 | for index in range(batch_size):
42 | pred_boxes = final_pred_dict[index]['pred_boxes']
43 |
44 | recall_dict = self.generate_recall_record(
45 | box_preds=pred_boxes,
46 | recall_dict=recall_dict, batch_index=index, data_dict=batch_dict,
47 | thresh_list=post_process_cfg.RECALL_THRESH_LIST
48 | )
49 |
50 | return final_pred_dict, recall_dict
--------------------------------------------------------------------------------
/pcdet/models/detectors/point_rcnn.py:
--------------------------------------------------------------------------------
1 | from .detector3d_template import Detector3DTemplate
2 |
3 |
4 | class PointRCNN(Detector3DTemplate):
5 | def __init__(self, model_cfg, num_class, dataset):
6 | super().__init__(model_cfg=model_cfg, num_class=num_class, dataset=dataset)
7 | self.module_list = self.build_networks()
8 |
9 | def forward(self, batch_dict):
10 | for cur_module in self.module_list:
11 | batch_dict = cur_module(batch_dict)
12 |
13 | if self.training:
14 | loss, tb_dict, disp_dict = self.get_training_loss()
15 |
16 | ret_dict = {
17 | 'loss': loss
18 | }
19 | return ret_dict, tb_dict, disp_dict
20 | else:
21 | pred_dicts, recall_dicts = self.post_processing(batch_dict)
22 | return pred_dicts, recall_dicts
23 |
24 | def get_training_loss(self):
25 | disp_dict = {}
26 | loss_point, tb_dict = self.point_head.get_loss()
27 | loss_rcnn, tb_dict = self.roi_head.get_loss(tb_dict)
28 |
29 | loss = loss_point + loss_rcnn
30 | return loss, tb_dict, disp_dict
31 |
--------------------------------------------------------------------------------
/pcdet/models/detectors/pointpillar.py:
--------------------------------------------------------------------------------
1 | from .detector3d_template import Detector3DTemplate
2 |
3 |
4 | class PointPillar(Detector3DTemplate):
5 | def __init__(self, model_cfg, num_class, dataset):
6 | super().__init__(model_cfg=model_cfg, num_class=num_class, dataset=dataset)
7 | self.module_list = self.build_networks()
8 |
9 | def forward(self, batch_dict):
10 | for cur_module in self.module_list:
11 | batch_dict = cur_module(batch_dict)
12 |
13 | if self.training:
14 | loss, tb_dict, disp_dict = self.get_training_loss()
15 |
16 | ret_dict = {
17 | 'loss': loss
18 | }
19 | return ret_dict, tb_dict, disp_dict
20 | else:
21 | pred_dicts, recall_dicts = self.post_processing(batch_dict)
22 | return pred_dicts, recall_dicts
23 |
24 | def get_training_loss(self):
25 | disp_dict = {}
26 |
27 | loss_rpn, tb_dict = self.dense_head.get_loss()
28 | tb_dict = {
29 | 'loss_rpn': loss_rpn.item(),
30 | **tb_dict
31 | }
32 |
33 | loss = loss_rpn
34 | return loss, tb_dict, disp_dict
35 |
--------------------------------------------------------------------------------
/pcdet/models/detectors/pv_rcnn.py:
--------------------------------------------------------------------------------
1 | from .detector3d_template import Detector3DTemplate
2 |
3 |
4 | class PVRCNN(Detector3DTemplate):
5 | def __init__(self, model_cfg, num_class, dataset):
6 | super().__init__(model_cfg=model_cfg, num_class=num_class, dataset=dataset)
7 | self.module_list = self.build_networks()
8 |
9 | def forward(self, batch_dict):
10 | for cur_module in self.module_list:
11 | batch_dict = cur_module(batch_dict)
12 |
13 | if self.training:
14 | loss, tb_dict, disp_dict = self.get_training_loss()
15 |
16 | ret_dict = {
17 | 'loss': loss
18 | }
19 | return ret_dict, tb_dict, disp_dict
20 | else:
21 | pred_dicts, recall_dicts = self.post_processing(batch_dict)
22 | return pred_dicts, recall_dicts
23 |
24 | def get_training_loss(self):
25 | disp_dict = {}
26 | loss_rpn, tb_dict = self.dense_head.get_loss()
27 | loss_point, tb_dict = self.point_head.get_loss(tb_dict)
28 | loss_rcnn, tb_dict = self.roi_head.get_loss(tb_dict)
29 |
30 | loss = loss_rpn + loss_point + loss_rcnn
31 |
32 | if hasattr(self.backbone_3d, 'get_loss'):
33 | loss_backbone3d, tb_dict = self.backbone_3d.get_loss(tb_dict)
34 | loss += loss_backbone3d
35 |
36 | return loss, tb_dict, disp_dict
37 |
--------------------------------------------------------------------------------
/pcdet/models/detectors/pv_rcnn_plusplus.py:
--------------------------------------------------------------------------------
1 | from .detector3d_template import Detector3DTemplate
2 |
3 |
4 | class PVRCNNPlusPlus(Detector3DTemplate):
5 | def __init__(self, model_cfg, num_class, dataset):
6 | super().__init__(model_cfg=model_cfg, num_class=num_class, dataset=dataset)
7 | self.module_list = self.build_networks()
8 |
9 | def forward(self, batch_dict):
10 | batch_dict = self.vfe(batch_dict)
11 | batch_dict = self.backbone_3d(batch_dict)
12 | batch_dict = self.map_to_bev_module(batch_dict)
13 | batch_dict = self.backbone_2d(batch_dict)
14 | batch_dict = self.dense_head(batch_dict)
15 |
16 | batch_dict = self.roi_head.proposal_layer(
17 | batch_dict, nms_config=self.roi_head.model_cfg.NMS_CONFIG['TRAIN' if self.training else 'TEST']
18 | )
19 | if self.training:
20 | targets_dict = self.roi_head.assign_targets(batch_dict)
21 | batch_dict['rois'] = targets_dict['rois']
22 | batch_dict['roi_labels'] = targets_dict['roi_labels']
23 | batch_dict['roi_targets_dict'] = targets_dict
24 | num_rois_per_scene = targets_dict['rois'].shape[1]
25 | if 'roi_valid_num' in batch_dict:
26 | batch_dict['roi_valid_num'] = [num_rois_per_scene for _ in range(batch_dict['batch_size'])]
27 |
28 | batch_dict = self.pfe(batch_dict)
29 | batch_dict = self.point_head(batch_dict)
30 | batch_dict = self.roi_head(batch_dict)
31 |
32 | if self.training:
33 | loss, tb_dict, disp_dict = self.get_training_loss()
34 |
35 | ret_dict = {
36 | 'loss': loss
37 | }
38 | return ret_dict, tb_dict, disp_dict
39 | else:
40 | pred_dicts, recall_dicts = self.post_processing(batch_dict)
41 | return pred_dicts, recall_dicts
42 |
43 | def get_training_loss(self):
44 | disp_dict = {}
45 | loss_rpn, tb_dict = self.dense_head.get_loss()
46 | if self.point_head is not None:
47 | loss_point, tb_dict = self.point_head.get_loss(tb_dict)
48 | else:
49 | loss_point = 0
50 | loss_rcnn, tb_dict = self.roi_head.get_loss(tb_dict)
51 |
52 | loss = loss_rpn + loss_point + loss_rcnn
53 | return loss, tb_dict, disp_dict
54 |
--------------------------------------------------------------------------------
/pcdet/models/detectors/second_net.py:
--------------------------------------------------------------------------------
1 | from .detector3d_template import Detector3DTemplate
2 |
3 |
4 | class SECONDNet(Detector3DTemplate):
5 | def __init__(self, model_cfg, num_class, dataset):
6 | super().__init__(model_cfg=model_cfg, num_class=num_class, dataset=dataset)
7 | self.module_list = self.build_networks()
8 |
9 | def forward(self, batch_dict):
10 | for cur_module in self.module_list:
11 | batch_dict = cur_module(batch_dict)
12 |
13 | if self.training:
14 | loss, tb_dict, disp_dict = self.get_training_loss()
15 |
16 | ret_dict = {
17 | 'loss': loss
18 | }
19 | return ret_dict, tb_dict, disp_dict
20 | else:
21 | pred_dicts, recall_dicts = self.post_processing(batch_dict)
22 | return pred_dicts, recall_dicts
23 |
24 | def get_training_loss(self):
25 | disp_dict = {}
26 |
27 | loss_rpn, tb_dict = self.dense_head.get_loss()
28 | tb_dict = {
29 | 'loss_rpn': loss_rpn.item(),
30 | **tb_dict
31 | }
32 |
33 | loss = loss_rpn
34 | return loss, tb_dict, disp_dict
35 |
--------------------------------------------------------------------------------
/pcdet/models/detectors/transfusion.py:
--------------------------------------------------------------------------------
1 | from .detector3d_template import Detector3DTemplate
2 |
3 |
4 | class TransFusion(Detector3DTemplate):
5 | def __init__(self, model_cfg, num_class, dataset):
6 | super().__init__(model_cfg=model_cfg, num_class=num_class, dataset=dataset)
7 | self.module_list = self.build_networks()
8 |
9 | def forward(self, batch_dict):
10 | for cur_module in self.module_list:
11 | batch_dict = cur_module(batch_dict)
12 |
13 | if self.training:
14 | loss, tb_dict, disp_dict = self.get_training_loss(batch_dict)
15 |
16 | ret_dict = {
17 | 'loss': loss
18 | }
19 | return ret_dict, tb_dict, disp_dict
20 | else:
21 | pred_dicts, recall_dicts = self.post_processing(batch_dict)
22 | return pred_dicts, recall_dicts
23 |
24 | def get_training_loss(self,batch_dict):
25 | disp_dict = {}
26 |
27 | loss_trans, tb_dict = batch_dict['loss'],batch_dict['tb_dict']
28 | tb_dict = {
29 | 'loss_trans': loss_trans.item(),
30 | **tb_dict
31 | }
32 |
33 | loss = loss_trans
34 | return loss, tb_dict, disp_dict
35 |
36 | def post_processing(self, batch_dict):
37 | post_process_cfg = self.model_cfg.POST_PROCESSING
38 | batch_size = batch_dict['batch_size']
39 | final_pred_dict = batch_dict['final_box_dicts']
40 | recall_dict = {}
41 | for index in range(batch_size):
42 | pred_boxes = final_pred_dict[index]['pred_boxes']
43 |
44 | recall_dict = self.generate_recall_record(
45 | box_preds=pred_boxes,
46 | recall_dict=recall_dict, batch_index=index, data_dict=batch_dict,
47 | thresh_list=post_process_cfg.RECALL_THRESH_LIST
48 | )
49 |
50 | return final_pred_dict, recall_dict
51 |
--------------------------------------------------------------------------------
/pcdet/models/detectors/voxel_rcnn.py:
--------------------------------------------------------------------------------
1 | from .detector3d_template import Detector3DTemplate
2 |
3 |
4 | class VoxelRCNN(Detector3DTemplate):
5 | def __init__(self, model_cfg, num_class, dataset):
6 | super().__init__(model_cfg=model_cfg, num_class=num_class, dataset=dataset)
7 | self.module_list = self.build_networks()
8 |
9 | def forward(self, batch_dict):
10 | for cur_module in self.module_list:
11 | batch_dict = cur_module(batch_dict)
12 |
13 | if self.training:
14 | loss, tb_dict, disp_dict = self.get_training_loss()
15 |
16 | ret_dict = {
17 | 'loss': loss
18 | }
19 | return ret_dict, tb_dict, disp_dict
20 | else:
21 | pred_dicts, recall_dicts = self.post_processing(batch_dict)
22 | return pred_dicts, recall_dicts
23 |
24 | def get_training_loss(self):
25 | disp_dict = {}
26 | loss = 0
27 |
28 | loss_rpn, tb_dict = self.dense_head.get_loss()
29 | loss_rcnn, tb_dict = self.roi_head.get_loss(tb_dict)
30 |
31 | loss = loss + loss_rpn + loss_rcnn
32 |
33 | if hasattr(self.backbone_3d, 'get_loss'):
34 | loss_backbone3d, tb_dict = self.backbone_3d.get_loss(tb_dict)
35 | loss += loss_backbone3d
36 |
37 | return loss, tb_dict, disp_dict
38 |
--------------------------------------------------------------------------------
/pcdet/models/detectors/voxelnext.py:
--------------------------------------------------------------------------------
1 | from .detector3d_template import Detector3DTemplate
2 |
3 | class VoxelNeXt(Detector3DTemplate):
4 | def __init__(self, model_cfg, num_class, dataset):
5 | super().__init__(model_cfg=model_cfg, num_class=num_class, dataset=dataset)
6 | self.module_list = self.build_networks()
7 |
8 | def forward(self, batch_dict):
9 |
10 | for cur_module in self.module_list:
11 | batch_dict = cur_module(batch_dict)
12 |
13 | if self.training:
14 | loss, tb_dict, disp_dict = self.get_training_loss()
15 | ret_dict = {
16 | 'loss': loss
17 | }
18 | return ret_dict, tb_dict, disp_dict
19 | else:
20 | pred_dicts, recall_dicts = self.post_processing(batch_dict)
21 | return pred_dicts, recall_dicts
22 |
23 | def get_training_loss(self):
24 |
25 | disp_dict = {}
26 | loss, tb_dict = self.dense_head.get_loss()
27 |
28 | return loss, tb_dict, disp_dict
29 |
30 | def post_processing(self, batch_dict):
31 | post_process_cfg = self.model_cfg.POST_PROCESSING
32 | batch_size = batch_dict['batch_size']
33 | final_pred_dict = batch_dict['final_box_dicts']
34 | recall_dict = {}
35 | for index in range(batch_size):
36 | pred_boxes = final_pred_dict[index]['pred_boxes']
37 |
38 | recall_dict = self.generate_recall_record(
39 | box_preds=pred_boxes,
40 | recall_dict=recall_dict, batch_index=index, data_dict=batch_dict,
41 | thresh_list=post_process_cfg.RECALL_THRESH_LIST
42 | )
43 |
44 | return final_pred_dict, recall_dict
45 |
--------------------------------------------------------------------------------
/pcdet/models/model_utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/models/model_utils/__init__.py
--------------------------------------------------------------------------------
/pcdet/models/model_utils/basic_block_2d.py:
--------------------------------------------------------------------------------
1 | import torch.nn as nn
2 |
3 |
4 | class BasicBlock2D(nn.Module):
5 |
6 | def __init__(self, in_channels, out_channels, **kwargs):
7 | """
8 | Initializes convolutional block
9 | Args:
10 | in_channels: int, Number of input channels
11 | out_channels: int, Number of output channels
12 | **kwargs: Dict, Extra arguments for nn.Conv2d
13 | """
14 | super().__init__()
15 | self.in_channels = in_channels
16 | self.out_channels = out_channels
17 | self.conv = nn.Conv2d(in_channels=in_channels,
18 | out_channels=out_channels,
19 | **kwargs)
20 | self.bn = nn.BatchNorm2d(out_channels)
21 | self.relu = nn.ReLU(inplace=True)
22 |
23 | def forward(self, features):
24 | """
25 | Applies convolutional block
26 | Args:
27 | features: (B, C_in, H, W), Input features
28 | Returns:
29 | x: (B, C_out, H, W), Output features
30 | """
31 | x = self.conv(features)
32 | x = self.bn(x)
33 | x = self.relu(x)
34 | return x
35 |
--------------------------------------------------------------------------------
/pcdet/models/roi_heads/__init__.py:
--------------------------------------------------------------------------------
1 | from .partA2_head import PartA2FCHead
2 | from .pointrcnn_head import PointRCNNHead
3 | from .pvrcnn_head import PVRCNNHead
4 | from .second_head import SECONDHead
5 | from .voxelrcnn_head import VoxelRCNNHead
6 | from .roi_head_template import RoIHeadTemplate
7 | from .mppnet_head import MPPNetHead
8 | from .mppnet_memory_bank_e2e import MPPNetHeadE2E
9 |
10 | __all__ = {
11 | 'RoIHeadTemplate': RoIHeadTemplate,
12 | 'PartA2FCHead': PartA2FCHead,
13 | 'PVRCNNHead': PVRCNNHead,
14 | 'SECONDHead': SECONDHead,
15 | 'PointRCNNHead': PointRCNNHead,
16 | 'VoxelRCNNHead': VoxelRCNNHead,
17 | 'MPPNetHead': MPPNetHead,
18 | 'MPPNetHeadE2E': MPPNetHeadE2E,
19 | }
20 |
--------------------------------------------------------------------------------
/pcdet/models/roi_heads/target_assigner/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/models/roi_heads/target_assigner/__init__.py
--------------------------------------------------------------------------------
/pcdet/models/view_transforms/__init__.py:
--------------------------------------------------------------------------------
1 | from .depth_lss import DepthLSSTransform
2 | __all__ = {
3 | 'DepthLSSTransform': DepthLSSTransform,
4 | }
--------------------------------------------------------------------------------
/pcdet/ops/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/ops/__init__.py
--------------------------------------------------------------------------------
/pcdet/ops/bev_pool/__init__.py:
--------------------------------------------------------------------------------
1 | from .bev_pool import bev_pool
--------------------------------------------------------------------------------
/pcdet/ops/bev_pool/bev_pool.py:
--------------------------------------------------------------------------------
1 | import torch
2 |
3 | from . import bev_pool_ext
4 |
5 | __all__ = ["bev_pool"]
6 |
7 |
8 | class QuickCumsum(torch.autograd.Function):
9 | @staticmethod
10 | def forward(ctx, x, geom_feats, ranks):
11 | x = x.cumsum(0)
12 | kept = torch.ones(x.shape[0], device=x.device, dtype=torch.bool)
13 | kept[:-1] = ranks[1:] != ranks[:-1]
14 |
15 | x, geom_feats = x[kept], geom_feats[kept]
16 | x = torch.cat((x[:1], x[1:] - x[:-1]))
17 |
18 | # save kept for backward
19 | ctx.save_for_backward(kept)
20 |
21 | # no gradient for geom_feats
22 | ctx.mark_non_differentiable(geom_feats)
23 |
24 | return x, geom_feats
25 |
26 | @staticmethod
27 | def backward(ctx, gradx, gradgeom):
28 | (kept,) = ctx.saved_tensors
29 | back = torch.cumsum(kept, 0)
30 | back[kept] -= 1
31 |
32 | val = gradx[back]
33 |
34 | return val, None, None
35 |
36 |
37 | class QuickCumsumCuda(torch.autograd.Function):
38 | @staticmethod
39 | def forward(ctx, x, geom_feats, ranks, B, D, H, W):
40 | kept = torch.ones(x.shape[0], device=x.device, dtype=torch.bool)
41 | kept[1:] = ranks[1:] != ranks[:-1]
42 | interval_starts = torch.where(kept)[0].int()
43 | interval_lengths = torch.zeros_like(interval_starts)
44 | interval_lengths[:-1] = interval_starts[1:] - interval_starts[:-1]
45 | interval_lengths[-1] = x.shape[0] - interval_starts[-1]
46 | geom_feats = geom_feats.int()
47 |
48 | out = bev_pool_ext.bev_pool_forward(
49 | x,
50 | geom_feats,
51 | interval_lengths,
52 | interval_starts,
53 | B,
54 | D,
55 | H,
56 | W,
57 | )
58 |
59 | ctx.save_for_backward(interval_starts, interval_lengths, geom_feats)
60 | ctx.saved_shapes = B, D, H, W
61 | return out
62 |
63 | @staticmethod
64 | def backward(ctx, out_grad):
65 | interval_starts, interval_lengths, geom_feats = ctx.saved_tensors
66 | B, D, H, W = ctx.saved_shapes
67 |
68 | out_grad = out_grad.contiguous()
69 | x_grad = bev_pool_ext.bev_pool_backward(
70 | out_grad,
71 | geom_feats,
72 | interval_lengths,
73 | interval_starts,
74 | B,
75 | D,
76 | H,
77 | W,
78 | )
79 |
80 | return x_grad, None, None, None, None, None, None
81 |
82 |
83 | def bev_pool(feats, coords, B, D, H, W):
84 | assert feats.shape[0] == coords.shape[0]
85 |
86 | ranks = (
87 | coords[:, 0] * (W * D * B)
88 | + coords[:, 1] * (D * B)
89 | + coords[:, 2] * B
90 | + coords[:, 3]
91 | )
92 | indices = ranks.argsort()
93 | feats, coords, ranks = feats[indices], coords[indices], ranks[indices]
94 |
95 | x = QuickCumsumCuda.apply(feats, coords, ranks, B, D, H, W)
96 | x = x.permute(0, 4, 1, 2, 3).contiguous()
97 | return x
98 |
--------------------------------------------------------------------------------
/pcdet/ops/deform_attn_3d/csrc/pytorch_cuda_helper.hpp:
--------------------------------------------------------------------------------
1 | #ifndef PYTORCH_CUDA_HELPER
2 | #define PYTORCH_CUDA_HELPER
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 | #include
10 |
11 | #include "common_cuda_helper.hpp"
12 |
13 | using at::Half;
14 | using at::Tensor;
15 | using phalf = at::Half;
16 |
17 | #define __PHALF(x) (x)
18 | #define DIVUP(m, n) ((m) / (n) + ((m) % (n) > 0))
19 |
20 | #endif // PYTORCH_CUDA_HELPER
21 |
--------------------------------------------------------------------------------
/pcdet/ops/deform_attn_3d/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup
2 | import torch
3 | import os,glob
4 | from torch.utils.cpp_extension import (CUDAExtension, CppExtension, BuildExtension)
5 |
6 |
7 | def get_extensions():
8 | extensions = []
9 | ext_name = 'deform3dattn_custom_cn'
10 | # prevent ninja from using too many resources
11 | # os.environ.setdefault('MAX_JOBS', '4')
12 | try:
13 | import psutil
14 | num_cpu = len(psutil.Process().cpu_affinity())
15 | cpu_use = max(4, num_cpu - 1)
16 | except (ModuleNotFoundError, AttributeError):
17 | cpu_use = 4
18 |
19 | os.environ.setdefault('MAX_JOBS', str(cpu_use))
20 | define_macros = []
21 |
22 | if torch.cuda.is_available():
23 | print(f'Compiling {ext_name} with CUDA')
24 | define_macros += [('WITH_CUDA', None)]
25 | # op_files = glob.glob('./csrc/*')
26 | op_files = glob.glob('./csrc/*.cu')
27 | extension = CUDAExtension
28 | else:
29 | print(f'Compiling {ext_name} without CUDA')
30 | op_files = glob.glob('./csrc/*.cpp')
31 | extension = CppExtension
32 |
33 | include_path = os.path.abspath('./csrc')
34 | ext_ops = extension(
35 | name=ext_name,
36 | sources=op_files,
37 | include_dirs=[include_path],
38 | define_macros=define_macros)
39 | extensions.append(ext_ops)
40 | return extensions
41 |
42 | setup(
43 | name='extension_example',
44 | ext_modules=get_extensions(),
45 | cmdclass={'build_ext': BuildExtension},
46 | )
47 |
--------------------------------------------------------------------------------
/pcdet/ops/ingroup_inds/ingroup_inds_op.py:
--------------------------------------------------------------------------------
1 | import torch
2 |
3 | try:
4 | from . import ingroup_inds_cuda
5 | # import ingroup_indices
6 | except ImportError:
7 | ingroup_indices = None
8 | print('Can not import ingroup indices')
9 |
10 | ingroup_indices = ingroup_inds_cuda
11 |
12 | from torch.autograd import Function
13 | class IngroupIndicesFunction(Function):
14 |
15 | @staticmethod
16 | def forward(ctx, group_inds):
17 |
18 | out_inds = torch.zeros_like(group_inds) - 1
19 |
20 | ingroup_indices.forward(group_inds, out_inds)
21 |
22 | ctx.mark_non_differentiable(out_inds)
23 |
24 | return out_inds
25 |
26 | @staticmethod
27 | def backward(ctx, g):
28 |
29 | return None
30 |
31 | ingroup_inds = IngroupIndicesFunction.apply
--------------------------------------------------------------------------------
/pcdet/ops/ingroup_inds/src/error.cuh:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | #define CHECK_CALL(call) \
5 | do \
6 | { \
7 | const cudaError_t error_code = call; \
8 | if (error_code != cudaSuccess) \
9 | { \
10 | printf("CUDA Error:\n"); \
11 | printf(" File: %s\n", __FILE__); \
12 | printf(" Line: %d\n", __LINE__); \
13 | printf(" Error code: %d\n", error_code); \
14 | printf(" Error text: %s\n", \
15 | cudaGetErrorString(error_code)); \
16 | exit(1); \
17 | } \
18 | } while (0)
--------------------------------------------------------------------------------
/pcdet/ops/ingroup_inds/src/ingroup_inds.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #define CHECK_CUDA(x) \
7 | TORCH_CHECK(x.device().is_cuda(), #x, " must be a CUDAtensor ")
8 | #define CHECK_CONTIGUOUS(x) \
9 | TORCH_CHECK(x.is_contiguous(), #x, " must be contiguous ")
10 | #define CHECK_INPUT(x) \
11 | CHECK_CUDA(x); \
12 | CHECK_CONTIGUOUS(x)
13 |
14 |
15 | void ingroup_inds_launcher(
16 | const long *group_inds_data,
17 | long *out_inds_data,
18 | int N,
19 | int max_group_id
20 | );
21 |
22 |
23 | void ingroup_inds_gpu(
24 | at::Tensor group_inds,
25 | at::Tensor out_inds
26 | );
27 |
28 | void ingroup_inds_gpu(
29 | at::Tensor group_inds,
30 | at::Tensor out_inds
31 | ) {
32 |
33 | CHECK_INPUT(group_inds);
34 | CHECK_INPUT(out_inds);
35 | int N = group_inds.size(0);
36 | int max_group_id = group_inds.max().item().toLong();
37 |
38 |
39 | long *group_inds_data = group_inds.data_ptr();
40 | long *out_inds_data = out_inds.data_ptr();
41 |
42 | ingroup_inds_launcher(
43 | group_inds_data,
44 | out_inds_data,
45 | N,
46 | max_group_id
47 | );
48 |
49 | }
50 |
51 |
52 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
53 | m.def("forward", &ingroup_inds_gpu, "cuda version of get_inner_win_inds of SST");
54 | }
--------------------------------------------------------------------------------
/pcdet/ops/ingroup_inds/src/ingroup_inds_kernel.cu:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include "cuda_fp16.h"
8 |
9 | #define CHECK_CALL(call) \
10 | do \
11 | { \
12 | const cudaError_t error_code = call; \
13 | if (error_code != cudaSuccess) \
14 | { \
15 | printf("CUDA Error:\n"); \
16 | printf(" File: %s\n", __FILE__); \
17 | printf(" Line: %d\n", __LINE__); \
18 | printf(" Error code: %d\n", error_code); \
19 | printf(" Error text: %s\n", \
20 | cudaGetErrorString(error_code)); \
21 | exit(1); \
22 | } \
23 | } while (0)
24 |
25 | #define THREADS_PER_BLOCK 256
26 | #define DIVUP(m, n) ((m) / (n) + ((m) % (n) > 0))
27 |
28 | // #define DEBUG
29 | // #define ASSERTION
30 |
31 | __global__ void ingroup_inds_kernel(
32 | const long *group_inds,
33 | long *out_inds,
34 | int *ingroup_counter,
35 | int N
36 | ) {
37 |
38 | int idx = blockIdx.x * blockDim.x + threadIdx.x;
39 | if (idx >= N) return;
40 | long this_group_id = group_inds[idx];
41 |
42 | int cnt = atomicAdd(&ingroup_counter[this_group_id], 1);
43 | out_inds[idx] = cnt;
44 | }
45 |
46 |
47 | void ingroup_inds_launcher(
48 | const long *group_inds,
49 | long *out_inds,
50 | int N,
51 | int max_group_id
52 | ) {
53 |
54 | int *ingroup_counter = NULL;
55 | CHECK_CALL(cudaMalloc(&ingroup_counter, (max_group_id + 1) * sizeof(int)));
56 | CHECK_CALL(cudaMemset(ingroup_counter, 0, (max_group_id + 1) * sizeof(int)));
57 |
58 | dim3 blocks(DIVUP(N, THREADS_PER_BLOCK));
59 | dim3 threads(THREADS_PER_BLOCK);
60 |
61 | ingroup_inds_kernel<<>>(
62 | group_inds,
63 | out_inds,
64 | ingroup_counter,
65 | N
66 | );
67 |
68 | cudaFree(ingroup_counter);
69 |
70 | #ifdef DEBUG
71 | CHECK_CALL(cudaGetLastError());
72 | CHECK_CALL(cudaDeviceSynchronize());
73 | #endif
74 |
75 | return;
76 |
77 | }
--------------------------------------------------------------------------------
/pcdet/ops/iou3d_nms/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/ops/iou3d_nms/__init__.py
--------------------------------------------------------------------------------
/pcdet/ops/iou3d_nms/src/iou3d_cpu.h:
--------------------------------------------------------------------------------
1 | #ifndef IOU3D_CPU_H
2 | #define IOU3D_CPU_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | int boxes_iou_bev_cpu(at::Tensor boxes_a_tensor, at::Tensor boxes_b_tensor, at::Tensor ans_iou_tensor);
10 | int boxes_aligned_iou_bev_cpu(at::Tensor boxes_a_tensor, at::Tensor boxes_b_tensor, at::Tensor ans_iou_tensor);
11 | #endif
12 |
--------------------------------------------------------------------------------
/pcdet/ops/iou3d_nms/src/iou3d_nms.h:
--------------------------------------------------------------------------------
1 | #ifndef IOU3D_NMS_H
2 | #define IOU3D_NMS_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | int boxes_aligned_overlap_bev_gpu(at::Tensor boxes_a, at::Tensor boxes_b, at::Tensor ans_overlap);
11 | int boxes_overlap_bev_gpu(at::Tensor boxes_a, at::Tensor boxes_b, at::Tensor ans_overlap);
12 | int paired_boxes_overlap_bev_gpu(at::Tensor boxes_a, at::Tensor boxes_b, at::Tensor ans_overlap);
13 | int boxes_iou_bev_gpu(at::Tensor boxes_a, at::Tensor boxes_b, at::Tensor ans_iou);
14 | int nms_gpu(at::Tensor boxes, at::Tensor keep, float nms_overlap_thresh);
15 | int nms_normal_gpu(at::Tensor boxes, at::Tensor keep, float nms_overlap_thresh);
16 |
17 | #endif
18 |
--------------------------------------------------------------------------------
/pcdet/ops/iou3d_nms/src/iou3d_nms_api.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #include "iou3d_cpu.h"
8 | #include "iou3d_nms.h"
9 |
10 |
11 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
12 | m.def("boxes_aligned_overlap_bev_gpu", &boxes_aligned_overlap_bev_gpu, "aligned oriented boxes overlap");
13 | m.def("boxes_overlap_bev_gpu", &boxes_overlap_bev_gpu, "oriented boxes overlap");
14 | m.def("paired_boxes_overlap_bev_gpu", &paired_boxes_overlap_bev_gpu, "oriented boxes overlap");
15 | m.def("boxes_iou_bev_gpu", &boxes_iou_bev_gpu, "oriented boxes iou");
16 | m.def("nms_gpu", &nms_gpu, "oriented nms gpu");
17 | m.def("nms_normal_gpu", &nms_normal_gpu, "nms gpu");
18 | m.def("boxes_aligned_iou_bev_cpu", &boxes_aligned_iou_bev_cpu, "aligned oriented boxes iou");
19 | m.def("boxes_iou_bev_cpu", &boxes_iou_bev_cpu, "oriented boxes iou");
20 | }
21 |
--------------------------------------------------------------------------------
/pcdet/ops/multi_scale_deformable_attn/src/common_cuda_helper.hpp:
--------------------------------------------------------------------------------
1 | #ifndef VOYDET_OPS_CSRC_KERNELS_COMMON_CUDA_HELPER_HPP_
2 | #define VOYDET_OPS_CSRC_KERNELS_COMMON_CUDA_HELPER_HPP_
3 |
4 | #include
5 |
6 | #include
7 |
8 | #define CUDA_1D_KERNEL_LOOP(i, n) \
9 | for (int i = blockIdx.x * blockDim.x + threadIdx.x; i < (n); \
10 | i += blockDim.x * gridDim.x)
11 |
12 | inline int GET_BLOCKS(const int N, const int num_threads = 512) {
13 | int optimal_block_num = (N + num_threads - 1) / num_threads;
14 | int max_block_num = 4096;
15 | return min(optimal_block_num, max_block_num);
16 | }
17 |
18 | // This func is used to get the no limited number of blocks and can avoid some
19 | // potential bugs in ops
20 | inline int GET_BLOCKS_NO_LIMIT(const int N, const int num_threads) {
21 | return (N + num_threads - 1) / num_threads;
22 | }
23 |
24 | #endif // VOYDET_OPS_CSRC_KERNELS_COMMON_CUDA_HELPER_HPP_
25 |
--------------------------------------------------------------------------------
/pcdet/ops/multi_scale_deformable_attn/src/ms_deform_attn.cpp:
--------------------------------------------------------------------------------
1 | /*!
2 | * Modified from
3 | *https://github.com/chengdazhi/Deformable-Convolution-V2-PyTorch/tree/pytorch_1.0.0
4 | **************************************************************************************************
5 | */
6 |
7 | #include "pytorch_cpp_helper.hpp"
8 |
9 | at::Tensor ms_deform_attn_cuda_forward(const at::Tensor &value,
10 | const at::Tensor &spatial_shapes,
11 | const at::Tensor &level_start_index,
12 | const at::Tensor &sampling_loc,
13 | const at::Tensor &attn_weight,
14 | const int im2col_step);
15 |
16 | void ms_deform_attn_cuda_backward(
17 | const at::Tensor &value, const at::Tensor &spatial_shapes,
18 | const at::Tensor &level_start_index, const at::Tensor &sampling_loc,
19 | const at::Tensor &attn_weight, const at::Tensor &grad_output,
20 | at::Tensor &grad_value, at::Tensor &grad_sampling_loc,
21 | at::Tensor &grad_attn_weight, const int im2col_step);
22 |
23 | Tensor ms_deform_attn_forward_gpu(const Tensor &value,
24 | const Tensor &spatial_shapes,
25 | const Tensor &level_start_index,
26 | const Tensor &sampling_loc,
27 | const Tensor &attn_weight,
28 | const int im2col_step) {
29 | at::DeviceGuard guard(value.device());
30 | return ms_deform_attn_cuda_forward(value, spatial_shapes, level_start_index,
31 | sampling_loc, attn_weight, im2col_step);
32 | }
33 |
34 | void ms_deform_attn_backward_gpu(
35 | const Tensor &value, const Tensor &spatial_shapes,
36 | const Tensor &level_start_index, const Tensor &sampling_loc,
37 | const Tensor &attn_weight, const Tensor &grad_output, Tensor &grad_value,
38 | Tensor &grad_sampling_loc, Tensor &grad_attn_weight,
39 | const int im2col_step) {
40 | at::DeviceGuard guard(value.device());
41 | ms_deform_attn_cuda_backward(value, spatial_shapes, level_start_index,
42 | sampling_loc, attn_weight, grad_output,
43 | grad_value, grad_sampling_loc, grad_attn_weight,
44 | im2col_step);
45 | }
46 |
47 | PYBIND11_MODULE (TORCH_EXTENSION_NAME, m) {
48 | m.def("ms_deform_attn_forward_gpu", &ms_deform_attn_forward_gpu,
49 | "ms_deform_attn_forward_gpu", py::arg("value"),
50 | py::arg("spatial_shapes"), py::arg("level_start_index"),
51 | py::arg("sampling_loc"), py::arg("attn_weight"),
52 | py::arg("im2col_step"));
53 | m.def("ms_deform_attn_backward_gpu", &ms_deform_attn_backward_gpu,
54 | "ms_deform_attn_backward_gpu", py::arg("value"),
55 | py::arg("spatial_shapes"), py::arg("level_start_index"),
56 | py::arg("sampling_loc"), py::arg("attn_weight"), py::arg("grad_output"),
57 | py::arg("grad_value"), py::arg("grad_sampling_loc"),
58 | py::arg("grad_attn_weight"), py::arg("im2col_step"));
59 | }
60 |
--------------------------------------------------------------------------------
/pcdet/ops/multi_scale_deformable_attn/src/pytorch_cpp_helper.hpp:
--------------------------------------------------------------------------------
1 | #ifndef PYTORCH_CPP_HELPER
2 | #define PYTORCH_CPP_HELPER
3 | #include
4 | #include
5 |
6 | #include
7 |
8 | using namespace at;
9 |
10 | #define CHECK_CUDA(x) \
11 | TORCH_CHECK(x.device().is_cuda(), #x " must be a CUDA tensor")
12 | #define CHECK_CPU(x) \
13 | TORCH_CHECK(!x.device().is_cuda(), #x " must be a CPU tensor")
14 | #define CHECK_CONTIGUOUS(x) \
15 | TORCH_CHECK(x.is_contiguous(), #x " must be contiguous")
16 | #define CHECK_CUDA_INPUT(x) \
17 | CHECK_CUDA(x); \
18 | CHECK_CONTIGUOUS(x)
19 | #define CHECK_CPU_INPUT(x) \
20 | CHECK_CPU(x); \
21 | CHECK_CONTIGUOUS(x)
22 |
23 | #define DIVUP(m, n) ((m) / (n) + ((m) % (n) > 0))
24 |
25 | #define CHECK_CUDA_ERROR(ans) \
26 | { gpuAssert((ans), __FILE__, __LINE__); }
27 | inline void gpuAssert(cudaError_t code, const char *file, int line,
28 | bool abort = true) {
29 | if (code != cudaSuccess) {
30 | fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code), file,
31 | line);
32 | if (abort) exit(code);
33 | }
34 | }
35 |
36 | #endif // PYTORCH_CPP_HELPER
37 |
--------------------------------------------------------------------------------
/pcdet/ops/multi_scale_deformable_attn/src/pytorch_cuda_helper.hpp:
--------------------------------------------------------------------------------
1 | #ifndef PYTORCH_CUDA_HELPER
2 | #define PYTORCH_CUDA_HELPER
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 | #include
10 |
11 | #include "common_cuda_helper.hpp"
12 |
13 | using at::Half;
14 | using at::Tensor;
15 | using phalf = at::Half;
16 |
17 | #define __PHALF(x) (x)
18 |
19 | #define DIVUP(m, n) ((m) / (n) + ((m) % (n) > 0))
20 |
21 | #endif // PYTORCH_CUDA_HELPER
22 |
--------------------------------------------------------------------------------
/pcdet/ops/multi_scale_deformable_attn/src/pytorch_cuda_helper_old.hpp:
--------------------------------------------------------------------------------
1 | #ifndef PYTORCH_CUDA_HELPER
2 | #define PYTORCH_CUDA_HELPER
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 | #include
10 |
11 | #include
12 |
13 | using at::Half;
14 | using at::Tensor;
15 | using phalf = at::Half;
16 |
17 | #define CUDA_1D_KERNEL_LOOP(i, n) \
18 | for (int i = blockIdx.x * blockDim.x + threadIdx.x; i < (n); \
19 | i += blockDim.x * gridDim.x)
20 |
21 | inline int GET_BLOCKS(const int N, const int num_threads = 512) {
22 | int optimal_block_num = (N + num_threads - 1) / num_threads;
23 | int max_block_num = 4096;
24 | return min(optimal_block_num, max_block_num);
25 | }
26 |
27 | // This func is used to get the no limited number of blocks and can avoid some
28 | // potential bugs in ops
29 | inline int GET_BLOCKS_NO_LIMIT(const int N, const int num_threads) {
30 | return (N + num_threads - 1) / num_threads;
31 | }
32 |
33 | #define __PHALF(x) (x)
34 |
35 | #define DIVUP(m, n) ((m) / (n) + ((m) % (n) > 0))
36 |
37 | #endif // PYTORCH_CUDA_HELPER
38 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/ops/pointnet2/__init__.py
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_batch/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/ops/pointnet2/pointnet2_batch/__init__.py
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_batch/src/ball_query.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | batch version of ball query, modified from the original implementation of official PointNet++ codes.
3 | Written by Shaoshuai Shi
4 | All Rights Reserved 2018.
5 | */
6 |
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include "ball_query_gpu.h"
13 |
14 | #define CHECK_CUDA(x) do { \
15 | if (!x.type().is_cuda()) { \
16 | fprintf(stderr, "%s must be CUDA tensor at %s:%d\n", #x, __FILE__, __LINE__); \
17 | exit(-1); \
18 | } \
19 | } while (0)
20 | #define CHECK_CONTIGUOUS(x) do { \
21 | if (!x.is_contiguous()) { \
22 | fprintf(stderr, "%s must be contiguous tensor at %s:%d\n", #x, __FILE__, __LINE__); \
23 | exit(-1); \
24 | } \
25 | } while (0)
26 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x)
27 |
28 |
29 | int ball_query_wrapper_fast(int b, int n, int m, float radius, int nsample,
30 | at::Tensor new_xyz_tensor, at::Tensor xyz_tensor, at::Tensor idx_tensor) {
31 | CHECK_INPUT(new_xyz_tensor);
32 | CHECK_INPUT(xyz_tensor);
33 | const float *new_xyz = new_xyz_tensor.data();
34 | const float *xyz = xyz_tensor.data();
35 | int *idx = idx_tensor.data();
36 |
37 | ball_query_kernel_launcher_fast(b, n, m, radius, nsample, new_xyz, xyz, idx);
38 | return 1;
39 | }
40 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_batch/src/ball_query_gpu.cu:
--------------------------------------------------------------------------------
1 | /*
2 | batch version of ball query, modified from the original implementation of official PointNet++ codes.
3 | Written by Shaoshuai Shi
4 | All Rights Reserved 2018.
5 | */
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | #include "ball_query_gpu.h"
12 | #include "cuda_utils.h"
13 |
14 |
15 | __global__ void ball_query_kernel_fast(int b, int n, int m, float radius, int nsample,
16 | const float *__restrict__ new_xyz, const float *__restrict__ xyz, int *__restrict__ idx) {
17 | // new_xyz: (B, M, 3)
18 | // xyz: (B, N, 3)
19 | // output:
20 | // idx: (B, M, nsample)
21 | int bs_idx = blockIdx.y;
22 | int pt_idx = blockIdx.x * blockDim.x + threadIdx.x;
23 | if (bs_idx >= b || pt_idx >= m) return;
24 |
25 | new_xyz += bs_idx * m * 3 + pt_idx * 3;
26 | xyz += bs_idx * n * 3;
27 | idx += bs_idx * m * nsample + pt_idx * nsample;
28 |
29 | float radius2 = radius * radius;
30 | float new_x = new_xyz[0];
31 | float new_y = new_xyz[1];
32 | float new_z = new_xyz[2];
33 |
34 | int cnt = 0;
35 | for (int k = 0; k < n; ++k) {
36 | float x = xyz[k * 3 + 0];
37 | float y = xyz[k * 3 + 1];
38 | float z = xyz[k * 3 + 2];
39 | float d2 = (new_x - x) * (new_x - x) + (new_y - y) * (new_y - y) + (new_z - z) * (new_z - z);
40 | if (d2 < radius2){
41 | if (cnt == 0){
42 | for (int l = 0; l < nsample; ++l) {
43 | idx[l] = k;
44 | }
45 | }
46 | idx[cnt] = k;
47 | ++cnt;
48 | if (cnt >= nsample) break;
49 | }
50 | }
51 | }
52 |
53 |
54 | void ball_query_kernel_launcher_fast(int b, int n, int m, float radius, int nsample, \
55 | const float *new_xyz, const float *xyz, int *idx) {
56 | // new_xyz: (B, M, 3)
57 | // xyz: (B, N, 3)
58 | // output:
59 | // idx: (B, M, nsample)
60 |
61 | cudaError_t err;
62 |
63 | dim3 blocks(DIVUP(m, THREADS_PER_BLOCK), b); // blockIdx.x(col), blockIdx.y(row)
64 | dim3 threads(THREADS_PER_BLOCK);
65 |
66 | ball_query_kernel_fast<<>>(b, n, m, radius, nsample, new_xyz, xyz, idx);
67 | // cudaDeviceSynchronize(); // for using printf in kernel function
68 | err = cudaGetLastError();
69 | if (cudaSuccess != err) {
70 | fprintf(stderr, "CUDA kernel failed : %s\n", cudaGetErrorString(err));
71 | exit(-1);
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_batch/src/ball_query_gpu.h:
--------------------------------------------------------------------------------
1 | #ifndef _BALL_QUERY_GPU_H
2 | #define _BALL_QUERY_GPU_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | int ball_query_wrapper_fast(int b, int n, int m, float radius, int nsample,
10 | at::Tensor new_xyz_tensor, at::Tensor xyz_tensor, at::Tensor idx_tensor);
11 |
12 | void ball_query_kernel_launcher_fast(int b, int n, int m, float radius, int nsample,
13 | const float *xyz, const float *new_xyz, int *idx);
14 |
15 | #endif
16 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_batch/src/cuda_utils.h:
--------------------------------------------------------------------------------
1 | #ifndef _CUDA_UTILS_H
2 | #define _CUDA_UTILS_H
3 |
4 | #include
5 |
6 | #define TOTAL_THREADS 1024
7 | #define THREADS_PER_BLOCK 256
8 | #define DIVUP(m,n) ((m) / (n) + ((m) % (n) > 0))
9 |
10 | inline int opt_n_threads(int work_size) {
11 | const int pow_2 = std::log(static_cast(work_size)) / std::log(2.0);
12 |
13 | return max(min(1 << pow_2, TOTAL_THREADS), 1);
14 | }
15 | #endif
16 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_batch/src/group_points.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | batch version of point grouping, modified from the original implementation of official PointNet++ codes.
3 | Written by Shaoshuai Shi
4 | All Rights Reserved 2018.
5 | */
6 |
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include "group_points_gpu.h"
13 |
14 |
15 | int group_points_grad_wrapper_fast(int b, int c, int n, int npoints, int nsample,
16 | at::Tensor grad_out_tensor, at::Tensor idx_tensor, at::Tensor grad_points_tensor) {
17 |
18 | float *grad_points = grad_points_tensor.data();
19 | const int *idx = idx_tensor.data();
20 | const float *grad_out = grad_out_tensor.data();
21 |
22 | group_points_grad_kernel_launcher_fast(b, c, n, npoints, nsample, grad_out, idx, grad_points);
23 | return 1;
24 | }
25 |
26 |
27 | int group_points_wrapper_fast(int b, int c, int n, int npoints, int nsample,
28 | at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor out_tensor) {
29 |
30 | const float *points = points_tensor.data();
31 | const int *idx = idx_tensor.data();
32 | float *out = out_tensor.data();
33 |
34 | group_points_kernel_launcher_fast(b, c, n, npoints, nsample, points, idx, out);
35 | return 1;
36 | }
37 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_batch/src/group_points_gpu.h:
--------------------------------------------------------------------------------
1 | #ifndef _GROUP_POINTS_GPU_H
2 | #define _GROUP_POINTS_GPU_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 |
10 | int group_points_wrapper_fast(int b, int c, int n, int npoints, int nsample,
11 | at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor out_tensor);
12 |
13 | void group_points_kernel_launcher_fast(int b, int c, int n, int npoints, int nsample,
14 | const float *points, const int *idx, float *out);
15 |
16 | int group_points_grad_wrapper_fast(int b, int c, int n, int npoints, int nsample,
17 | at::Tensor grad_out_tensor, at::Tensor idx_tensor, at::Tensor grad_points_tensor);
18 |
19 | void group_points_grad_kernel_launcher_fast(int b, int c, int n, int npoints, int nsample,
20 | const float *grad_out, const int *idx, float *grad_points);
21 |
22 | #endif
23 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_batch/src/interpolate.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | batch version of point interpolation, modified from the original implementation of official PointNet++ codes.
3 | Written by Shaoshuai Shi
4 | All Rights Reserved 2018.
5 | */
6 |
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include "interpolate_gpu.h"
16 |
17 |
18 | void three_nn_wrapper_fast(int b, int n, int m, at::Tensor unknown_tensor,
19 | at::Tensor known_tensor, at::Tensor dist2_tensor, at::Tensor idx_tensor) {
20 | const float *unknown = unknown_tensor.data();
21 | const float *known = known_tensor.data();
22 | float *dist2 = dist2_tensor.data();
23 | int *idx = idx_tensor.data();
24 |
25 | three_nn_kernel_launcher_fast(b, n, m, unknown, known, dist2, idx);
26 | }
27 |
28 |
29 | void three_interpolate_wrapper_fast(int b, int c, int m, int n,
30 | at::Tensor points_tensor,
31 | at::Tensor idx_tensor,
32 | at::Tensor weight_tensor,
33 | at::Tensor out_tensor) {
34 |
35 | const float *points = points_tensor.data();
36 | const float *weight = weight_tensor.data();
37 | float *out = out_tensor.data();
38 | const int *idx = idx_tensor.data();
39 |
40 | three_interpolate_kernel_launcher_fast(b, c, m, n, points, idx, weight, out);
41 | }
42 |
43 |
44 | void three_interpolate_grad_wrapper_fast(int b, int c, int n, int m,
45 | at::Tensor grad_out_tensor,
46 | at::Tensor idx_tensor,
47 | at::Tensor weight_tensor,
48 | at::Tensor grad_points_tensor) {
49 |
50 | const float *grad_out = grad_out_tensor.data();
51 | const float *weight = weight_tensor.data();
52 | float *grad_points = grad_points_tensor.data();
53 | const int *idx = idx_tensor.data();
54 |
55 | three_interpolate_grad_kernel_launcher_fast(b, c, n, m, grad_out, idx, weight, grad_points);
56 | }
57 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_batch/src/interpolate_gpu.h:
--------------------------------------------------------------------------------
1 | #ifndef _INTERPOLATE_GPU_H
2 | #define _INTERPOLATE_GPU_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 |
10 | void three_nn_wrapper_fast(int b, int n, int m, at::Tensor unknown_tensor,
11 | at::Tensor known_tensor, at::Tensor dist2_tensor, at::Tensor idx_tensor);
12 |
13 | void three_nn_kernel_launcher_fast(int b, int n, int m, const float *unknown,
14 | const float *known, float *dist2, int *idx);
15 |
16 |
17 | void three_interpolate_wrapper_fast(int b, int c, int m, int n, at::Tensor points_tensor,
18 | at::Tensor idx_tensor, at::Tensor weight_tensor, at::Tensor out_tensor);
19 |
20 | void three_interpolate_kernel_launcher_fast(int b, int c, int m, int n,
21 | const float *points, const int *idx, const float *weight, float *out);
22 |
23 |
24 | void three_interpolate_grad_wrapper_fast(int b, int c, int n, int m, at::Tensor grad_out_tensor,
25 | at::Tensor idx_tensor, at::Tensor weight_tensor, at::Tensor grad_points_tensor);
26 |
27 | void three_interpolate_grad_kernel_launcher_fast(int b, int c, int n, int m, const float *grad_out,
28 | const int *idx, const float *weight, float *grad_points);
29 |
30 | #endif
31 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_batch/src/pointnet2_api.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include "ball_query_gpu.h"
5 | #include "group_points_gpu.h"
6 | #include "sampling_gpu.h"
7 | #include "interpolate_gpu.h"
8 |
9 |
10 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
11 | m.def("ball_query_wrapper", &ball_query_wrapper_fast, "ball_query_wrapper_fast");
12 |
13 | m.def("group_points_wrapper", &group_points_wrapper_fast, "group_points_wrapper_fast");
14 | m.def("group_points_grad_wrapper", &group_points_grad_wrapper_fast, "group_points_grad_wrapper_fast");
15 |
16 | m.def("gather_points_wrapper", &gather_points_wrapper_fast, "gather_points_wrapper_fast");
17 | m.def("gather_points_grad_wrapper", &gather_points_grad_wrapper_fast, "gather_points_grad_wrapper_fast");
18 |
19 | m.def("farthest_point_sampling_wrapper", &farthest_point_sampling_wrapper, "farthest_point_sampling_wrapper");
20 |
21 | m.def("three_nn_wrapper", &three_nn_wrapper_fast, "three_nn_wrapper_fast");
22 | m.def("three_interpolate_wrapper", &three_interpolate_wrapper_fast, "three_interpolate_wrapper_fast");
23 | m.def("three_interpolate_grad_wrapper", &three_interpolate_grad_wrapper_fast, "three_interpolate_grad_wrapper_fast");
24 | }
25 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_batch/src/sampling.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | batch version of point sampling and gathering, modified from the original implementation of official PointNet++ codes.
3 | Written by Shaoshuai Shi
4 | All Rights Reserved 2018.
5 | */
6 |
7 |
8 | #include
9 | #include
10 | #include
11 | #include "sampling_gpu.h"
12 |
13 |
14 | int gather_points_wrapper_fast(int b, int c, int n, int npoints,
15 | at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor out_tensor){
16 | const float *points = points_tensor.data();
17 | const int *idx = idx_tensor.data();
18 | float *out = out_tensor.data();
19 |
20 | gather_points_kernel_launcher_fast(b, c, n, npoints, points, idx, out);
21 | return 1;
22 | }
23 |
24 |
25 | int gather_points_grad_wrapper_fast(int b, int c, int n, int npoints,
26 | at::Tensor grad_out_tensor, at::Tensor idx_tensor, at::Tensor grad_points_tensor) {
27 |
28 | const float *grad_out = grad_out_tensor.data();
29 | const int *idx = idx_tensor.data();
30 | float *grad_points = grad_points_tensor.data();
31 |
32 | gather_points_grad_kernel_launcher_fast(b, c, n, npoints, grad_out, idx, grad_points);
33 | return 1;
34 | }
35 |
36 |
37 | int farthest_point_sampling_wrapper(int b, int n, int m,
38 | at::Tensor points_tensor, at::Tensor temp_tensor, at::Tensor idx_tensor) {
39 |
40 | const float *points = points_tensor.data();
41 | float *temp = temp_tensor.data();
42 | int *idx = idx_tensor.data();
43 |
44 | farthest_point_sampling_kernel_launcher(b, n, m, points, temp, idx);
45 | return 1;
46 | }
47 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_batch/src/sampling_gpu.h:
--------------------------------------------------------------------------------
1 | #ifndef _SAMPLING_GPU_H
2 | #define _SAMPLING_GPU_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 |
9 | int gather_points_wrapper_fast(int b, int c, int n, int npoints,
10 | at::Tensor points_tensor, at::Tensor idx_tensor, at::Tensor out_tensor);
11 |
12 | void gather_points_kernel_launcher_fast(int b, int c, int n, int npoints,
13 | const float *points, const int *idx, float *out);
14 |
15 |
16 | int gather_points_grad_wrapper_fast(int b, int c, int n, int npoints,
17 | at::Tensor grad_out_tensor, at::Tensor idx_tensor, at::Tensor grad_points_tensor);
18 |
19 | void gather_points_grad_kernel_launcher_fast(int b, int c, int n, int npoints,
20 | const float *grad_out, const int *idx, float *grad_points);
21 |
22 |
23 | int farthest_point_sampling_wrapper(int b, int n, int m,
24 | at::Tensor points_tensor, at::Tensor temp_tensor, at::Tensor idx_tensor);
25 |
26 | void farthest_point_sampling_kernel_launcher(int b, int n, int m,
27 | const float *dataset, float *temp, int *idxs);
28 |
29 | #endif
30 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_stack/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/ops/pointnet2/pointnet2_stack/__init__.py
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_stack/src/ball_query.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Stacked-batch-data version of ball query, modified from the original implementation of official PointNet++ codes.
3 | Written by Shaoshuai Shi
4 | All Rights Reserved 2019-2020.
5 | */
6 |
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include "ball_query_gpu.h"
13 |
14 | #define CHECK_CUDA(x) do { \
15 | if (!x.type().is_cuda()) { \
16 | fprintf(stderr, "%s must be CUDA tensor at %s:%d\n", #x, __FILE__, __LINE__); \
17 | exit(-1); \
18 | } \
19 | } while (0)
20 | #define CHECK_CONTIGUOUS(x) do { \
21 | if (!x.is_contiguous()) { \
22 | fprintf(stderr, "%s must be contiguous tensor at %s:%d\n", #x, __FILE__, __LINE__); \
23 | exit(-1); \
24 | } \
25 | } while (0)
26 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x)
27 |
28 |
29 | int ball_query_wrapper_stack(int B, int M, float radius, int nsample,
30 | at::Tensor new_xyz_tensor, at::Tensor new_xyz_batch_cnt_tensor,
31 | at::Tensor xyz_tensor, at::Tensor xyz_batch_cnt_tensor, at::Tensor idx_tensor) {
32 | CHECK_INPUT(new_xyz_tensor);
33 | CHECK_INPUT(xyz_tensor);
34 | CHECK_INPUT(new_xyz_batch_cnt_tensor);
35 | CHECK_INPUT(xyz_batch_cnt_tensor);
36 |
37 | const float *new_xyz = new_xyz_tensor.data();
38 | const float *xyz = xyz_tensor.data();
39 | const int *new_xyz_batch_cnt = new_xyz_batch_cnt_tensor.data();
40 | const int *xyz_batch_cnt = xyz_batch_cnt_tensor.data();
41 | int *idx = idx_tensor.data();
42 |
43 | ball_query_kernel_launcher_stack(B, M, radius, nsample, new_xyz, new_xyz_batch_cnt, xyz, xyz_batch_cnt, idx);
44 | return 1;
45 | }
46 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_stack/src/ball_query_gpu.h:
--------------------------------------------------------------------------------
1 | /*
2 | Stacked-batch-data version of ball query, modified from the original implementation of official PointNet++ codes.
3 | Written by Shaoshuai Shi
4 | All Rights Reserved 2019-2020.
5 | */
6 |
7 |
8 | #ifndef _STACK_BALL_QUERY_GPU_H
9 | #define _STACK_BALL_QUERY_GPU_H
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | int ball_query_wrapper_stack(int B, int M, float radius, int nsample,
17 | at::Tensor new_xyz_tensor, at::Tensor new_xyz_batch_cnt_tensor,
18 | at::Tensor xyz_tensor, at::Tensor xyz_batch_cnt_tensor, at::Tensor idx_tensor);
19 |
20 |
21 | void ball_query_kernel_launcher_stack(int B, int M, float radius, int nsample,
22 | const float *new_xyz, const int *new_xyz_batch_cnt, const float *xyz, const int *xyz_batch_cnt, int *idx);
23 |
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_stack/src/cuda_utils.h:
--------------------------------------------------------------------------------
1 | #ifndef _STACK_CUDA_UTILS_H
2 | #define _STACK_CUDA_UTILS_H
3 |
4 | #include
5 |
6 | #define THREADS_PER_BLOCK 256
7 | #define DIVUP(m,n) ((m) / (n) + ((m) % (n) > 0))
8 |
9 | #endif
10 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_stack/src/group_points.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Stacked-batch-data version of point grouping, modified from the original implementation of official PointNet++ codes.
3 | Written by Shaoshuai Shi
4 | All Rights Reserved 2019-2020.
5 | */
6 |
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include "group_points_gpu.h"
13 |
14 | #define CHECK_CUDA(x) do { \
15 | if (!x.type().is_cuda()) { \
16 | fprintf(stderr, "%s must be CUDA tensor at %s:%d\n", #x, __FILE__, __LINE__); \
17 | exit(-1); \
18 | } \
19 | } while (0)
20 | #define CHECK_CONTIGUOUS(x) do { \
21 | if (!x.is_contiguous()) { \
22 | fprintf(stderr, "%s must be contiguous tensor at %s:%d\n", #x, __FILE__, __LINE__); \
23 | exit(-1); \
24 | } \
25 | } while (0)
26 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x)
27 |
28 |
29 | int group_points_grad_wrapper_stack(int B, int M, int C, int N, int nsample,
30 | at::Tensor grad_out_tensor, at::Tensor idx_tensor, at::Tensor idx_batch_cnt_tensor,
31 | at::Tensor features_batch_cnt_tensor, at::Tensor grad_features_tensor) {
32 |
33 | CHECK_INPUT(grad_out_tensor);
34 | CHECK_INPUT(idx_tensor);
35 | CHECK_INPUT(idx_batch_cnt_tensor);
36 | CHECK_INPUT(features_batch_cnt_tensor);
37 | CHECK_INPUT(grad_features_tensor);
38 |
39 | const float *grad_out = grad_out_tensor.data();
40 | const int *idx = idx_tensor.data();
41 | const int *idx_batch_cnt = idx_batch_cnt_tensor.data();
42 | const int *features_batch_cnt = features_batch_cnt_tensor.data();
43 | float *grad_features = grad_features_tensor.data();
44 |
45 | group_points_grad_kernel_launcher_stack(B, M, C, N, nsample, grad_out, idx, idx_batch_cnt, features_batch_cnt, grad_features);
46 | return 1;
47 | }
48 |
49 |
50 | int group_points_wrapper_stack(int B, int M, int C, int nsample,
51 | at::Tensor features_tensor, at::Tensor features_batch_cnt_tensor,
52 | at::Tensor idx_tensor, at::Tensor idx_batch_cnt_tensor, at::Tensor out_tensor) {
53 |
54 | CHECK_INPUT(features_tensor);
55 | CHECK_INPUT(features_batch_cnt_tensor);
56 | CHECK_INPUT(idx_tensor);
57 | CHECK_INPUT(idx_batch_cnt_tensor);
58 | CHECK_INPUT(out_tensor);
59 |
60 | const float *features = features_tensor.data();
61 | const int *idx = idx_tensor.data();
62 | const int *features_batch_cnt = features_batch_cnt_tensor.data();
63 | const int *idx_batch_cnt = idx_batch_cnt_tensor.data();
64 | float *out = out_tensor.data();
65 |
66 | group_points_kernel_launcher_stack(B, M, C, nsample, features, features_batch_cnt, idx, idx_batch_cnt, out);
67 | return 1;
68 | }
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_stack/src/group_points_gpu.h:
--------------------------------------------------------------------------------
1 | /*
2 | Stacked-batch-data version of point grouping, modified from the original implementation of official PointNet++ codes.
3 | Written by Shaoshuai Shi
4 | All Rights Reserved 2019-2020.
5 | */
6 |
7 |
8 | #ifndef _STACK_GROUP_POINTS_GPU_H
9 | #define _STACK_GROUP_POINTS_GPU_H
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 |
17 | int group_points_wrapper_stack(int B, int M, int C, int nsample,
18 | at::Tensor features_tensor, at::Tensor features_batch_cnt_tensor,
19 | at::Tensor idx_tensor, at::Tensor idx_batch_cnt_tensor, at::Tensor out_tensor);
20 |
21 | void group_points_kernel_launcher_stack(int B, int M, int C, int nsample,
22 | const float *features, const int *features_batch_cnt, const int *idx, const int *idx_batch_cnt, float *out);
23 |
24 | int group_points_grad_wrapper_stack(int B, int M, int C, int N, int nsample,
25 | at::Tensor grad_out_tensor, at::Tensor idx_tensor, at::Tensor idx_batch_cnt_tensor,
26 | at::Tensor features_batch_cnt_tensor, at::Tensor grad_features_tensor);
27 |
28 | void group_points_grad_kernel_launcher_stack(int B, int M, int C, int N, int nsample,
29 | const float *grad_out, const int *idx, const int *idx_batch_cnt, const int *features_batch_cnt, float *grad_features);
30 |
31 | #endif
32 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_stack/src/interpolate_gpu.h:
--------------------------------------------------------------------------------
1 | #ifndef _INTERPOLATE_GPU_H
2 | #define _INTERPOLATE_GPU_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 |
10 | void three_nn_wrapper_stack(at::Tensor unknown_tensor,
11 | at::Tensor unknown_batch_cnt_tensor, at::Tensor known_tensor,
12 | at::Tensor known_batch_cnt_tensor, at::Tensor dist2_tensor, at::Tensor idx_tensor);
13 |
14 |
15 | void three_interpolate_wrapper_stack(at::Tensor features_tensor,
16 | at::Tensor idx_tensor, at::Tensor weight_tensor, at::Tensor out_tensor);
17 |
18 |
19 |
20 | void three_interpolate_grad_wrapper_stack(at::Tensor grad_out_tensor, at::Tensor idx_tensor,
21 | at::Tensor weight_tensor, at::Tensor grad_features_tensor);
22 |
23 |
24 | void three_nn_kernel_launcher_stack(int batch_size, int N, int M, const float *unknown,
25 | const int *unknown_batch_cnt, const float *known, const int *known_batch_cnt,
26 | float *dist2, int *idx);
27 |
28 |
29 | void three_interpolate_kernel_launcher_stack(int N, int channels,
30 | const float *features, const int *idx, const float *weight, float *out);
31 |
32 |
33 |
34 | void three_interpolate_grad_kernel_launcher_stack(int N, int channels, const float *grad_out,
35 | const int *idx, const float *weight, float *grad_features);
36 |
37 |
38 |
39 | #endif
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_stack/src/pointnet2_api.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include "ball_query_gpu.h"
5 | #include "group_points_gpu.h"
6 | #include "sampling_gpu.h"
7 | #include "interpolate_gpu.h"
8 | #include "voxel_query_gpu.h"
9 | #include "vector_pool_gpu.h"
10 |
11 |
12 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
13 | m.def("ball_query_wrapper", &ball_query_wrapper_stack, "ball_query_wrapper_stack");
14 | m.def("voxel_query_wrapper", &voxel_query_wrapper_stack, "voxel_query_wrapper_stack");
15 |
16 | m.def("farthest_point_sampling_wrapper", &farthest_point_sampling_wrapper, "farthest_point_sampling_wrapper");
17 | m.def("stack_farthest_point_sampling_wrapper", &stack_farthest_point_sampling_wrapper, "stack_farthest_point_sampling_wrapper");
18 |
19 | m.def("group_points_wrapper", &group_points_wrapper_stack, "group_points_wrapper_stack");
20 | m.def("group_points_grad_wrapper", &group_points_grad_wrapper_stack, "group_points_grad_wrapper_stack");
21 |
22 | m.def("three_nn_wrapper", &three_nn_wrapper_stack, "three_nn_wrapper_stack");
23 | m.def("three_interpolate_wrapper", &three_interpolate_wrapper_stack, "three_interpolate_wrapper_stack");
24 | m.def("three_interpolate_grad_wrapper", &three_interpolate_grad_wrapper_stack, "three_interpolate_grad_wrapper_stack");
25 |
26 | m.def("query_stacked_local_neighbor_idxs_wrapper_stack", &query_stacked_local_neighbor_idxs_wrapper_stack, "query_stacked_local_neighbor_idxs_wrapper_stack");
27 | m.def("query_three_nn_by_stacked_local_idxs_wrapper_stack", &query_three_nn_by_stacked_local_idxs_wrapper_stack, "query_three_nn_by_stacked_local_idxs_wrapper_stack");
28 |
29 | m.def("vector_pool_wrapper", &vector_pool_wrapper_stack, "vector_pool_grad_wrapper_stack");
30 | m.def("vector_pool_grad_wrapper", &vector_pool_grad_wrapper_stack, "vector_pool_grad_wrapper_stack");
31 | }
32 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_stack/src/sampling.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "sampling_gpu.h"
5 |
6 | #define CHECK_CUDA(x) do { \
7 | if (!x.type().is_cuda()) { \
8 | fprintf(stderr, "%s must be CUDA tensor at %s:%d\n", #x, __FILE__, __LINE__); \
9 | exit(-1); \
10 | } \
11 | } while (0)
12 | #define CHECK_CONTIGUOUS(x) do { \
13 | if (!x.is_contiguous()) { \
14 | fprintf(stderr, "%s must be contiguous tensor at %s:%d\n", #x, __FILE__, __LINE__); \
15 | exit(-1); \
16 | } \
17 | } while (0)
18 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x)
19 |
20 |
21 | int farthest_point_sampling_wrapper(int b, int n, int m,
22 | at::Tensor points_tensor, at::Tensor temp_tensor, at::Tensor idx_tensor) {
23 |
24 | CHECK_INPUT(points_tensor);
25 | CHECK_INPUT(temp_tensor);
26 | CHECK_INPUT(idx_tensor);
27 |
28 | const float *points = points_tensor.data();
29 | float *temp = temp_tensor.data();
30 | int *idx = idx_tensor.data();
31 |
32 | farthest_point_sampling_kernel_launcher(b, n, m, points, temp, idx);
33 | return 1;
34 | }
35 |
36 |
37 | int stack_farthest_point_sampling_wrapper(at::Tensor points_tensor,
38 | at::Tensor temp_tensor, at::Tensor xyz_batch_cnt_tensor, at::Tensor idx_tensor,
39 | at::Tensor num_sampled_points_tensor) {
40 |
41 | CHECK_INPUT(points_tensor);
42 | CHECK_INPUT(temp_tensor);
43 | CHECK_INPUT(idx_tensor);
44 | CHECK_INPUT(xyz_batch_cnt_tensor);
45 | CHECK_INPUT(num_sampled_points_tensor);
46 |
47 | int batch_size = xyz_batch_cnt_tensor.size(0);
48 | int N = points_tensor.size(0);
49 | const float *points = points_tensor.data();
50 | float *temp = temp_tensor.data();
51 | int *xyz_batch_cnt = xyz_batch_cnt_tensor.data();
52 | int *idx = idx_tensor.data();
53 | int *num_sampled_points = num_sampled_points_tensor.data();
54 |
55 | stack_farthest_point_sampling_kernel_launcher(N, batch_size, points, temp, xyz_batch_cnt, idx, num_sampled_points);
56 | return 1;
57 | }
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_stack/src/sampling_gpu.h:
--------------------------------------------------------------------------------
1 | #ifndef _SAMPLING_GPU_H
2 | #define _SAMPLING_GPU_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 |
9 | int farthest_point_sampling_wrapper(int b, int n, int m,
10 | at::Tensor points_tensor, at::Tensor temp_tensor, at::Tensor idx_tensor);
11 |
12 | void farthest_point_sampling_kernel_launcher(int b, int n, int m,
13 | const float *dataset, float *temp, int *idxs);
14 |
15 | int stack_farthest_point_sampling_wrapper(
16 | at::Tensor points_tensor, at::Tensor temp_tensor, at::Tensor xyz_batch_cnt_tensor,
17 | at::Tensor idx_tensor, at::Tensor num_sampled_points_tensor);
18 |
19 |
20 | void stack_farthest_point_sampling_kernel_launcher(int N, int batch_size,
21 | const float *dataset, float *temp, int *xyz_batch_cnt, int *idxs, int *num_sampled_points);
22 |
23 | #endif
24 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_stack/src/voxel_query.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include "voxel_query_gpu.h"
9 |
10 | #define CHECK_CUDA(x) do { \
11 | if (!x.type().is_cuda()) { \
12 | fprintf(stderr, "%s must be CUDA tensor at %s:%d\n", #x, __FILE__, __LINE__); \
13 | exit(-1); \
14 | } \
15 | } while (0)
16 | #define CHECK_CONTIGUOUS(x) do { \
17 | if (!x.is_contiguous()) { \
18 | fprintf(stderr, "%s must be contiguous tensor at %s:%d\n", #x, __FILE__, __LINE__); \
19 | exit(-1); \
20 | } \
21 | } while (0)
22 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x)
23 |
24 |
25 | int voxel_query_wrapper_stack(int M, int R1, int R2, int R3, int nsample, float radius,
26 | int z_range, int y_range, int x_range, at::Tensor new_xyz_tensor, at::Tensor xyz_tensor,
27 | at::Tensor new_coords_tensor, at::Tensor point_indices_tensor, at::Tensor idx_tensor) {
28 | CHECK_INPUT(new_coords_tensor);
29 | CHECK_INPUT(point_indices_tensor);
30 | CHECK_INPUT(new_xyz_tensor);
31 | CHECK_INPUT(xyz_tensor);
32 |
33 | const float *new_xyz = new_xyz_tensor.data();
34 | const float *xyz = xyz_tensor.data();
35 | const int *new_coords = new_coords_tensor.data();
36 | const int *point_indices = point_indices_tensor.data();
37 | int *idx = idx_tensor.data();
38 |
39 | voxel_query_kernel_launcher_stack(M, R1, R2, R3, nsample, radius, z_range, y_range, x_range, new_xyz, xyz, new_coords, point_indices, idx);
40 | return 1;
41 | }
42 |
--------------------------------------------------------------------------------
/pcdet/ops/pointnet2/pointnet2_stack/src/voxel_query_gpu.h:
--------------------------------------------------------------------------------
1 | #ifndef _STACK_VOXEL_QUERY_GPU_H
2 | #define _STACK_VOXEL_QUERY_GPU_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | int voxel_query_wrapper_stack(int M, int R1, int R2, int R3, int nsample, float radius,
10 | int z_range, int y_range, int x_range, at::Tensor new_xyz_tensor, at::Tensor xyz_tensor,
11 | at::Tensor new_coords_tensor, at::Tensor point_indices_tensor, at::Tensor idx_tensor);
12 |
13 |
14 | void voxel_query_kernel_launcher_stack(int M, int R1, int R2, int R3, int nsample,
15 | float radius, int z_range, int y_range, int x_range, const float *new_xyz,
16 | const float *xyz, const int *new_coords, const int *point_indices, int *idx);
17 |
18 |
19 | #endif
20 |
--------------------------------------------------------------------------------
/pcdet/ops/roiaware_pool3d/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/ops/roiaware_pool3d/__init__.py
--------------------------------------------------------------------------------
/pcdet/ops/roipoint_pool3d/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/ops/roipoint_pool3d/__init__.py
--------------------------------------------------------------------------------
/pcdet/ops/roipoint_pool3d/roipoint_pool3d_utils.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 | from torch.autograd import Function
4 |
5 | from ...utils import box_utils
6 | from . import roipoint_pool3d_cuda
7 |
8 |
9 | class RoIPointPool3d(nn.Module):
10 | def __init__(self, num_sampled_points=512, pool_extra_width=1.0):
11 | super().__init__()
12 | self.num_sampled_points = num_sampled_points
13 | self.pool_extra_width = pool_extra_width
14 |
15 | def forward(self, points, point_features, boxes3d):
16 | """
17 | Args:
18 | points: (B, N, 3)
19 | point_features: (B, N, C)
20 | boxes3d: (B, M, 7), [x, y, z, dx, dy, dz, heading]
21 |
22 | Returns:
23 | pooled_features: (B, M, 512, 3 + C)
24 | pooled_empty_flag: (B, M)
25 | """
26 | return RoIPointPool3dFunction.apply(
27 | points, point_features, boxes3d, self.pool_extra_width, self.num_sampled_points
28 | )
29 |
30 |
31 | class RoIPointPool3dFunction(Function):
32 | @staticmethod
33 | def forward(ctx, points, point_features, boxes3d, pool_extra_width, num_sampled_points=512):
34 | """
35 | Args:
36 | ctx:
37 | points: (B, N, 3)
38 | point_features: (B, N, C)
39 | boxes3d: (B, num_boxes, 7), [x, y, z, dx, dy, dz, heading]
40 | pool_extra_width:
41 | num_sampled_points:
42 |
43 | Returns:
44 | pooled_features: (B, num_boxes, 512, 3 + C)
45 | pooled_empty_flag: (B, num_boxes)
46 | """
47 | assert points.shape.__len__() == 3 and points.shape[2] == 3
48 | batch_size, boxes_num, feature_len = points.shape[0], boxes3d.shape[1], point_features.shape[2]
49 | pooled_boxes3d = box_utils.enlarge_box3d(boxes3d.view(-1, 7), pool_extra_width).view(batch_size, -1, 7)
50 |
51 | pooled_features = point_features.new_zeros((batch_size, boxes_num, num_sampled_points, 3 + feature_len))
52 | pooled_empty_flag = point_features.new_zeros((batch_size, boxes_num)).int()
53 |
54 | roipoint_pool3d_cuda.forward(
55 | points.contiguous(), pooled_boxes3d.contiguous(),
56 | point_features.contiguous(), pooled_features, pooled_empty_flag
57 | )
58 |
59 | return pooled_features, pooled_empty_flag
60 |
61 | @staticmethod
62 | def backward(ctx, grad_out):
63 | raise NotImplementedError
64 |
65 |
66 | if __name__ == '__main__':
67 | pass
68 |
--------------------------------------------------------------------------------
/pcdet/ops/roipoint_pool3d/src/roipoint_pool3d.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #define CHECK_CUDA(x) do { \
5 | if (!x.type().is_cuda()) { \
6 | fprintf(stderr, "%s must be CUDA tensor at %s:%d\n", #x, __FILE__, __LINE__); \
7 | exit(-1); \
8 | } \
9 | } while (0)
10 | #define CHECK_CONTIGUOUS(x) do { \
11 | if (!x.is_contiguous()) { \
12 | fprintf(stderr, "%s must be contiguous tensor at %s:%d\n", #x, __FILE__, __LINE__); \
13 | exit(-1); \
14 | } \
15 | } while (0)
16 | #define CHECK_INPUT(x) CHECK_CUDA(x);CHECK_CONTIGUOUS(x)
17 |
18 |
19 | void roipool3dLauncher(int batch_size, int pts_num, int boxes_num, int feature_in_len, int sampled_pts_num,
20 | const float *xyz, const float *boxes3d, const float *pts_feature, float *pooled_features, int *pooled_empty_flag);
21 |
22 |
23 | int roipool3d_gpu(at::Tensor xyz, at::Tensor boxes3d, at::Tensor pts_feature, at::Tensor pooled_features, at::Tensor pooled_empty_flag){
24 | // params xyz: (B, N, 3)
25 | // params boxes3d: (B, M, 7)
26 | // params pts_feature: (B, N, C)
27 | // params pooled_features: (B, M, 512, 3+C)
28 | // params pooled_empty_flag: (B, M)
29 | CHECK_INPUT(xyz);
30 | CHECK_INPUT(boxes3d);
31 | CHECK_INPUT(pts_feature);
32 | CHECK_INPUT(pooled_features);
33 | CHECK_INPUT(pooled_empty_flag);
34 |
35 | int batch_size = xyz.size(0);
36 | int pts_num = xyz.size(1);
37 | int boxes_num = boxes3d.size(1);
38 | int feature_in_len = pts_feature.size(2);
39 | int sampled_pts_num = pooled_features.size(2);
40 |
41 |
42 | const float * xyz_data = xyz.data();
43 | const float * boxes3d_data = boxes3d.data();
44 | const float * pts_feature_data = pts_feature.data();
45 | float * pooled_features_data = pooled_features.data();
46 | int * pooled_empty_flag_data = pooled_empty_flag.data();
47 |
48 | roipool3dLauncher(batch_size, pts_num, boxes_num, feature_in_len, sampled_pts_num,
49 | xyz_data, boxes3d_data, pts_feature_data, pooled_features_data, pooled_empty_flag_data);
50 |
51 |
52 |
53 | return 1;
54 | }
55 |
56 |
57 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
58 | m.def("forward", &roipool3d_gpu, "roipool3d forward (CUDA)");
59 | }
60 |
61 |
--------------------------------------------------------------------------------
/pcdet/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cedarch/M3Net/50e175ddf52c37339a1f7d1f5a4a1697f5ffade3/pcdet/utils/__init__.py
--------------------------------------------------------------------------------
/pcdet/utils/remove_head_weights.py:
--------------------------------------------------------------------------------
1 | import torch
2 | from collections import OrderedDict
3 | import argparse
4 |
5 | def main():
6 | # Create argument parser
7 | parser = argparse.ArgumentParser(description='Remove dense_head weights from model checkpoint')
8 |
9 | # Add command line arguments
10 | parser.add_argument('--input_path', type=str, required=True,
11 | help='Input model checkpoint path')
12 | parser.add_argument('--output_path', type=str, required=True,
13 | help='Output model checkpoint path')
14 | parser.add_argument('--remove_key', type=str, default='dense_head',
15 | help='Key prefix to remove, default is dense_head')
16 |
17 | # Parse command line arguments
18 | args = parser.parse_args()
19 |
20 | # Load model checkpoint
21 | print(f"Loading checkpoint from: {args.input_path}")
22 | ckpt = torch.load(args.input_path)
23 |
24 | # Create new model state dictionary
25 | new_ckpt = OrderedDict()
26 | remove_count = 0
27 | keep_count = 0
28 |
29 | # Iterate and filter weights
30 | for key, val in ckpt['model_state'].items():
31 | if args.remove_key not in key:
32 | new_ckpt[key] = val
33 | keep_count += 1
34 | else:
35 | remove_count += 1
36 |
37 | # Save new model checkpoint
38 | save_ckpt = {}
39 | save_ckpt['model_state'] = new_ckpt
40 |
41 | print(f"Removed {remove_count} weights, kept {keep_count} weights")
42 | print(f"Saving checkpoint to: {args.output_path}")
43 | torch.save(save_ckpt, args.output_path)
44 | print("Save completed")
45 |
46 | if __name__ == "__main__":
47 | main()
--------------------------------------------------------------------------------
/pcdet/utils/spconv_utils.py:
--------------------------------------------------------------------------------
1 | from typing import Set
2 |
3 | import spconv
4 | if float(spconv.__version__[2:]) >= 2.2:
5 | spconv.constants.SPCONV_USE_DIRECT_TABLE = False
6 |
7 | try:
8 | import spconv.pytorch as spconv
9 | except:
10 | import spconv as spconv
11 |
12 | import torch.nn as nn
13 |
14 |
15 | def find_all_spconv_keys(model: nn.Module, prefix="") -> Set[str]:
16 | """
17 | Finds all spconv keys that need to have weight's transposed
18 | """
19 | found_keys: Set[str] = set()
20 | for name, child in model.named_children():
21 | new_prefix = f"{prefix}.{name}" if prefix != "" else name
22 |
23 | if isinstance(child, spconv.conv.SparseConvolution):
24 | new_prefix = f"{new_prefix}.weight"
25 | found_keys.add(new_prefix)
26 |
27 | found_keys.update(find_all_spconv_keys(child, prefix=new_prefix))
28 |
29 | return found_keys
30 |
31 |
32 | def replace_feature(out, new_features):
33 | if "replace_feature" in out.__dir__():
34 | # spconv 2.x behaviour
35 | return out.replace_feature(new_features)
36 | else:
37 | out.features = new_features
38 | return out
39 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | numpy
2 | llvmlite
3 | numba
4 | torch>=1.1
5 | tensorboardX
6 | easydict
7 | pyyaml
8 | scikit-image
9 | tqdm
10 | torchvision
11 | SharedArray
12 | opencv-python
13 | pyquaternion
14 | nuscenes-devkit==1.1.10
15 | timm
16 | kornia
--------------------------------------------------------------------------------
/tools/_init_path.py:
--------------------------------------------------------------------------------
1 | import sys
2 | sys.path.insert(0, '../')
--------------------------------------------------------------------------------
/tools/cfgs/dataset_configs/argo2_dataset.yaml:
--------------------------------------------------------------------------------
1 | DATASET: 'Argo2Dataset'
2 | DATA_PATH: '../data/argo2'
3 |
4 | POINT_CLOUD_RANGE: [-200, -200, -20, 200, 200, 20]
5 |
6 | DATA_SPLIT: {
7 | 'train': train,
8 | 'test': val
9 | }
10 |
11 | INFO_PATH: {
12 | 'train': [argo2_infos_train.pkl],
13 | 'test': [argo2_infos_val.pkl],
14 | }
15 |
16 | GET_ITEM_LIST: ["points"]
17 |
18 | DATA_AUGMENTOR:
19 | DISABLE_AUG_LIST: ['placeholder']
20 | AUG_CONFIG_LIST:
21 |
22 | - NAME: random_world_flip
23 | ALONG_AXIS_LIST: ['x']
24 |
25 | - NAME: random_world_rotation
26 | WORLD_ROT_ANGLE: [-0.78539816, 0.78539816]
27 |
28 | - NAME: random_world_scaling
29 | WORLD_SCALE_RANGE: [0.95, 1.05]
30 |
31 |
32 | POINT_FEATURE_ENCODING: {
33 | encoding_type: absolute_coordinates_encoding,
34 | used_feature_list: ['x', 'y', 'z', 'intensity'],
35 | src_feature_list: ['x', 'y', 'z', 'intensity'],
36 | }
37 |
38 |
39 | DATA_PROCESSOR:
40 | - NAME: mask_points_and_boxes_outside_range
41 | REMOVE_OUTSIDE_BOXES: True
42 |
43 | - NAME: shuffle_points
44 | SHUFFLE_ENABLED: {
45 | 'train': True,
46 | 'test': False
47 | }
48 |
49 | - NAME: transform_points_to_voxels
50 | VOXEL_SIZE: [0.1, 0.1, 0.2]
51 | MAX_POINTS_PER_VOXEL: 5
52 | MAX_NUMBER_OF_VOXELS: {
53 | 'train': 160000,
54 | 'test': 400000
55 | }
56 |
--------------------------------------------------------------------------------
/tools/cfgs/dataset_configs/custom_dataset.yaml:
--------------------------------------------------------------------------------
1 | DATASET: 'CustomDataset'
2 | DATA_PATH: '../data/custom'
3 |
4 | POINT_CLOUD_RANGE: [-75.2, -75.2, -2, 75.2, 75.2, 4]
5 |
6 | MAP_CLASS_TO_KITTI: {
7 | 'Vehicle': 'Car',
8 | 'Pedestrian': 'Pedestrian',
9 | 'Cyclist': 'Cyclist',
10 | }
11 |
12 | DATA_SPLIT: {
13 | 'train': train,
14 | 'test': val
15 | }
16 |
17 | INFO_PATH: {
18 | 'train': [custom_infos_train.pkl],
19 | 'test': [custom_infos_val.pkl],
20 | }
21 |
22 | POINT_FEATURE_ENCODING: {
23 | encoding_type: absolute_coordinates_encoding,
24 | used_feature_list: ['x', 'y', 'z', 'intensity'],
25 | src_feature_list: ['x', 'y', 'z', 'intensity'],
26 | }
27 |
28 | DATA_AUGMENTOR:
29 | DISABLE_AUG_LIST: ['placeholder']
30 | AUG_CONFIG_LIST:
31 | - NAME: gt_sampling
32 | USE_ROAD_PLANE: False
33 | DB_INFO_PATH:
34 | - custom_dbinfos_train.pkl
35 | PREPARE: {
36 | filter_by_min_points: ['Vehicle:5', 'Pedestrian:5', 'Cyclist:5'],
37 | }
38 |
39 | SAMPLE_GROUPS: ['Vehicle:20', 'Pedestrian:15', 'Cyclist:15']
40 | NUM_POINT_FEATURES: 4
41 | DATABASE_WITH_FAKELIDAR: False
42 | REMOVE_EXTRA_WIDTH: [0.0, 0.0, 0.0]
43 | LIMIT_WHOLE_SCENE: True
44 |
45 | - NAME: random_world_flip
46 | ALONG_AXIS_LIST: ['x', 'y']
47 |
48 | - NAME: random_world_rotation
49 | WORLD_ROT_ANGLE: [-0.78539816, 0.78539816]
50 |
51 | - NAME: random_world_scaling
52 | WORLD_SCALE_RANGE: [0.95, 1.05]
53 |
54 | DATA_PROCESSOR:
55 | - NAME: mask_points_and_boxes_outside_range
56 | REMOVE_OUTSIDE_BOXES: True
57 |
58 | - NAME: shuffle_points
59 | SHUFFLE_ENABLED: {
60 | 'train': True,
61 | 'test': False
62 | }
63 |
64 | - NAME: transform_points_to_voxels
65 | VOXEL_SIZE: [0.1, 0.1, 0.15]
66 | MAX_POINTS_PER_VOXEL: 5
67 | MAX_NUMBER_OF_VOXELS: {
68 | 'train': 150000,
69 | 'test': 150000
70 | }
--------------------------------------------------------------------------------
/tools/cfgs/dataset_configs/kitti_dataset.yaml:
--------------------------------------------------------------------------------
1 | DATASET: 'KittiDataset'
2 | DATA_PATH: '../data/kitti'
3 |
4 | POINT_CLOUD_RANGE: [0, -40, -3, 70.4, 40, 1]
5 |
6 | DATA_SPLIT: {
7 | 'train': train,
8 | 'test': val
9 | }
10 |
11 | INFO_PATH: {
12 | 'train': [kitti_infos_train.pkl],
13 | 'test': [kitti_infos_val.pkl],
14 | }
15 |
16 | GET_ITEM_LIST: ["points"]
17 | FOV_POINTS_ONLY: True
18 |
19 | DATA_AUGMENTOR:
20 | DISABLE_AUG_LIST: ['placeholder']
21 | AUG_CONFIG_LIST:
22 | - NAME: gt_sampling
23 | USE_ROAD_PLANE: True
24 | DB_INFO_PATH:
25 | - kitti_dbinfos_train.pkl
26 | PREPARE: {
27 | filter_by_min_points: ['Car:5', 'Pedestrian:5', 'Cyclist:5'],
28 | filter_by_difficulty: [-1],
29 | }
30 |
31 | SAMPLE_GROUPS: ['Car:20','Pedestrian:15', 'Cyclist:15']
32 | NUM_POINT_FEATURES: 4
33 | DATABASE_WITH_FAKELIDAR: False
34 | REMOVE_EXTRA_WIDTH: [0.0, 0.0, 0.0]
35 | LIMIT_WHOLE_SCENE: True
36 |
37 | - NAME: random_world_flip
38 | ALONG_AXIS_LIST: ['x']
39 |
40 | - NAME: random_world_rotation
41 | WORLD_ROT_ANGLE: [-0.78539816, 0.78539816]
42 |
43 | - NAME: random_world_scaling
44 | WORLD_SCALE_RANGE: [0.95, 1.05]
45 |
46 |
47 | POINT_FEATURE_ENCODING: {
48 | encoding_type: absolute_coordinates_encoding,
49 | used_feature_list: ['x', 'y', 'z', 'intensity'],
50 | src_feature_list: ['x', 'y', 'z', 'intensity'],
51 | }
52 |
53 |
54 | DATA_PROCESSOR:
55 | - NAME: mask_points_and_boxes_outside_range
56 | REMOVE_OUTSIDE_BOXES: True
57 |
58 | - NAME: shuffle_points
59 | SHUFFLE_ENABLED: {
60 | 'train': True,
61 | 'test': False
62 | }
63 |
64 | - NAME: transform_points_to_voxels
65 | VOXEL_SIZE: [0.05, 0.05, 0.1]
66 | MAX_POINTS_PER_VOXEL: 5
67 | MAX_NUMBER_OF_VOXELS: {
68 | 'train': 16000,
69 | 'test': 40000
70 | }
71 |
--------------------------------------------------------------------------------
/tools/cfgs/dataset_configs/lyft_dataset.yaml:
--------------------------------------------------------------------------------
1 | DATASET: 'LyftDataset'
2 | DATA_PATH: '../data/lyft'
3 |
4 | VERSION: 'trainval'
5 | SET_NAN_VELOCITY_TO_ZEROS: True
6 | FILTER_MIN_POINTS_IN_GT: 1
7 | MAX_SWEEPS: 5
8 | EVAL_LYFT_IOU_LIST: [0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95]
9 |
10 | DATA_SPLIT: {
11 | 'train': train,
12 | 'test': val
13 | }
14 |
15 | INFO_PATH: {
16 | 'train': [lyft_infos_train.pkl],
17 | 'test': [lyft_infos_val.pkl],
18 | }
19 |
20 | POINT_CLOUD_RANGE: [-80.0, -80.0, -5.0, 80.0, 80.0, 3.0]
21 |
22 | DATA_AUGMENTOR:
23 | DISABLE_AUG_LIST: ['placeholder']
24 | AUG_CONFIG_LIST:
25 | - NAME: gt_sampling
26 | DB_INFO_PATH:
27 | - lyft_dbinfos_10sweeps.pkl
28 | PREPARE: {
29 | filter_by_min_points: [
30 | 'car:5','pedestrian:5', 'motorcycle:5', 'bicycle:5', 'other_vehicle:5',
31 | 'bus:5', 'truck:5', 'emergency_vehicle:5', 'animal:5'
32 | ],
33 | }
34 |
35 | SAMPLE_GROUPS: [
36 | 'car:3','pedestrian:3', 'motorcycle:6', 'bicycle:6', 'other_vehicle:4',
37 | 'bus:4', 'truck:3', 'emergency_vehicle:7', 'animal:3'
38 | ]
39 |
40 | NUM_POINT_FEATURES: 5
41 | DATABASE_WITH_FAKELIDAR: False
42 | REMOVE_EXTRA_WIDTH: [0.0, 0.0, 0.0]
43 | LIMIT_WHOLE_SCENE: True
44 |
45 | - NAME: random_world_flip
46 | ALONG_AXIS_LIST: ['x', 'y']
47 |
48 | - NAME: random_world_rotation
49 | WORLD_ROT_ANGLE: [-0.3925, 0.3925]
50 |
51 | - NAME: random_world_scaling
52 | WORLD_SCALE_RANGE: [0.95, 1.05]
53 |
54 |
55 | POINT_FEATURE_ENCODING: {
56 | encoding_type: absolute_coordinates_encoding,
57 | used_feature_list: ['x', 'y', 'z', 'intensity', 'timestamp'],
58 | src_feature_list: ['x', 'y', 'z', 'intensity', 'timestamp'],
59 | }
60 |
61 |
62 | DATA_PROCESSOR:
63 | - NAME: mask_points_and_boxes_outside_range
64 | REMOVE_OUTSIDE_BOXES: True
65 |
66 | - NAME: shuffle_points
67 | SHUFFLE_ENABLED: {
68 | 'train': True,
69 | 'test': True
70 | }
71 |
72 | - NAME: transform_points_to_voxels
73 | VOXEL_SIZE: [0.1, 0.1, 0.2]
74 | MAX_POINTS_PER_VOXEL: 10
75 | MAX_NUMBER_OF_VOXELS: {
76 | 'train': 80000,
77 | 'test': 80000
78 | }
--------------------------------------------------------------------------------
/tools/cfgs/dataset_configs/nuscenes_dataset.yaml:
--------------------------------------------------------------------------------
1 | DATASET: 'NuScenesDataset'
2 | DATA_PATH: '../data/nuscenes'
3 |
4 | VERSION: 'v1.0-trainval'
5 | MAX_SWEEPS: 10
6 | PRED_VELOCITY: True
7 | SET_NAN_VELOCITY_TO_ZEROS: True
8 | FILTER_MIN_POINTS_IN_GT: 1
9 |
10 | DATA_SPLIT: {
11 | 'train': train,
12 | 'test': val
13 | }
14 |
15 | INFO_PATH: {
16 | 'train': [nuscenes_infos_10sweeps_train.pkl],
17 | 'test': [nuscenes_infos_10sweeps_val.pkl],
18 | }
19 |
20 | POINT_CLOUD_RANGE: [-51.2, -51.2, -5.0, 51.2, 51.2, 3.0]
21 |
22 | BALANCED_RESAMPLING: True
23 |
24 | DATA_AUGMENTOR:
25 | DISABLE_AUG_LIST: ['placeholder']
26 | AUG_CONFIG_LIST:
27 | - NAME: gt_sampling
28 | DB_INFO_PATH:
29 | - nuscenes_dbinfos_10sweeps_withvelo.pkl
30 | PREPARE: {
31 | filter_by_min_points: [
32 | 'car:5','truck:5', 'construction_vehicle:5', 'bus:5', 'trailer:5',
33 | 'barrier:5', 'motorcycle:5', 'bicycle:5', 'pedestrian:5', 'traffic_cone:5'
34 | ],
35 | }
36 |
37 | SAMPLE_GROUPS: [
38 | 'car:2','truck:3', 'construction_vehicle:7', 'bus:4', 'trailer:6',
39 | 'barrier:2', 'motorcycle:6', 'bicycle:6', 'pedestrian:2', 'traffic_cone:2'
40 | ]
41 |
42 | NUM_POINT_FEATURES: 5
43 | DATABASE_WITH_FAKELIDAR: False
44 | REMOVE_EXTRA_WIDTH: [0.0, 0.0, 0.0]
45 | LIMIT_WHOLE_SCENE: True
46 |
47 | - NAME: random_world_flip
48 | ALONG_AXIS_LIST: ['x', 'y']
49 |
50 | - NAME: random_world_rotation
51 | WORLD_ROT_ANGLE: [-0.3925, 0.3925]
52 |
53 | - NAME: random_world_scaling
54 | WORLD_SCALE_RANGE: [0.95, 1.05]
55 |
56 |
57 | POINT_FEATURE_ENCODING: {
58 | encoding_type: absolute_coordinates_encoding,
59 | used_feature_list: ['x', 'y', 'z', 'intensity', 'timestamp'],
60 | src_feature_list: ['x', 'y', 'z', 'intensity', 'timestamp'],
61 | }
62 |
63 |
64 | DATA_PROCESSOR:
65 | - NAME: mask_points_and_boxes_outside_range
66 | REMOVE_OUTSIDE_BOXES: True
67 |
68 | - NAME: shuffle_points
69 | SHUFFLE_ENABLED: {
70 | 'train': True,
71 | 'test': True
72 | }
73 |
74 | - NAME: transform_points_to_voxels
75 | VOXEL_SIZE: [0.1, 0.1, 0.2]
76 | MAX_POINTS_PER_VOXEL: 10
77 | MAX_NUMBER_OF_VOXELS: {
78 | 'train': 60000,
79 | 'test': 60000
80 | }
81 |
--------------------------------------------------------------------------------
/tools/cfgs/dataset_configs/once_dataset.yaml:
--------------------------------------------------------------------------------
1 | DATASET: 'ONCEDataset'
2 | DATA_PATH: '../data/once'
3 | CLOUD_DATA_PATH: '/cache/once'
4 |
5 | POINT_CLOUD_RANGE: [-75.2, -75.2, -5.0, 75.2, 75.2, 3.0]
6 |
7 | INFO_PATH: {
8 | 'train': [once_infos_train.pkl],
9 | 'val': [once_infos_val.pkl],
10 | 'test': [once_infos_test.pkl],
11 | }
12 |
13 | DATA_SPLIT: {
14 | 'train': train,
15 | 'test': val
16 | }
17 |
18 | DATA_AUGMENTOR:
19 | DISABLE_AUG_LIST: ['placeholder']
20 | AUG_CONFIG_LIST:
21 | - NAME: gt_sampling
22 | USE_ROAD_PLANE: False
23 | DB_INFO_PATH:
24 | - once_dbinfos_train.pkl
25 | PREPARE: {
26 | filter_by_min_points: ['Car:5', 'Bus:5', 'Truck:5', 'Pedestrian:5', 'Cyclist:5'],
27 | }
28 |
29 | SAMPLE_GROUPS: ['Car:1', 'Bus:4', 'Truck:3', 'Pedestrian:2', 'Cyclist:2']
30 | NUM_POINT_FEATURES: 4
31 | REMOVE_EXTRA_WIDTH: [0.0, 0.0, 0.0]
32 | LIMIT_WHOLE_SCENE: True
33 |
34 | - NAME: random_world_flip
35 | ALONG_AXIS_LIST: ['x', 'y']
36 |
37 | - NAME: random_world_rotation
38 | WORLD_ROT_ANGLE: [-0.78539816, 0.78539816]
39 |
40 | - NAME: random_world_scaling
41 | WORLD_SCALE_RANGE: [0.95, 1.05]
42 |
43 |
44 | POINT_FEATURE_ENCODING: {
45 | encoding_type: absolute_coordinates_encoding,
46 | used_feature_list: ['x', 'y', 'z', 'intensity'],
47 | src_feature_list: ['x', 'y', 'z', 'intensity'],
48 | }
49 |
50 |
51 | DATA_PROCESSOR:
52 | - NAME: mask_points_and_boxes_outside_range
53 | REMOVE_OUTSIDE_BOXES: True
54 |
55 | - NAME: shuffle_points
56 | SHUFFLE_ENABLED: {
57 | 'train': True,
58 | 'test': False
59 | }
60 |
61 | - NAME: transform_points_to_voxels
62 | VOXEL_SIZE: [0.1, 0.1, 0.2]
63 | MAX_POINTS_PER_VOXEL: 5
64 | MAX_NUMBER_OF_VOXELS: {
65 | 'train': 60000,
66 | 'test': 60000
67 | }
--------------------------------------------------------------------------------
/tools/cfgs/dataset_configs/waymo_dataset.yaml:
--------------------------------------------------------------------------------
1 | DATASET: 'WaymoDataset'
2 | DATA_PATH: '../data/waymo'
3 | PROCESSED_DATA_TAG: 'waymo_processed_data_v0_5_0'
4 |
5 | POINT_CLOUD_RANGE: [-75.2, -75.2, -2, 75.2, 75.2, 4]
6 |
7 | DATA_SPLIT: {
8 | 'train': train,
9 | 'test': val
10 | }
11 |
12 | SAMPLED_INTERVAL: {
13 | 'train': 5,
14 | 'test': 1
15 | }
16 |
17 | FILTER_EMPTY_BOXES_FOR_TRAIN: True
18 | DISABLE_NLZ_FLAG_ON_POINTS: True
19 |
20 | USE_SHARED_MEMORY: False # it will load the data to shared memory to speed up (DO NOT USE IT IF YOU DO NOT FULLY UNDERSTAND WHAT WILL HAPPEN)
21 | SHARED_MEMORY_FILE_LIMIT: 35000 # set it based on the size of your shared memory
22 |
23 | DATA_AUGMENTOR:
24 | DISABLE_AUG_LIST: ['placeholder']
25 | AUG_CONFIG_LIST:
26 | - NAME: gt_sampling
27 | USE_ROAD_PLANE: False
28 | DB_INFO_PATH:
29 | - waymo_processed_data_v0_5_0_waymo_dbinfos_train_sampled_1.pkl
30 |
31 | USE_SHARED_MEMORY: False # set it to True to speed up (it costs about 15GB shared memory)
32 | DB_DATA_PATH:
33 | - waymo_processed_data_v0_5_0_gt_database_train_sampled_1_global.npy
34 |
35 | BACKUP_DB_INFO:
36 | # if the above DB_INFO cannot be found, will use this backup one
37 | DB_INFO_PATH: waymo_processed_data_v0_5_0_waymo_dbinfos_train_sampled_1_multiframe_-4_to_0.pkl
38 | DB_DATA_PATH: waymo_processed_data_v0_5_0_gt_database_train_sampled_1_multiframe_-4_to_0_global.npy
39 | NUM_POINT_FEATURES: 6
40 |
41 | PREPARE: {
42 | filter_by_min_points: ['Vehicle:5', 'Pedestrian:5', 'Cyclist:5'],
43 | filter_by_difficulty: [-1],
44 | }
45 |
46 | SAMPLE_GROUPS: ['Vehicle:15', 'Pedestrian:10', 'Cyclist:10']
47 | NUM_POINT_FEATURES: 5
48 | REMOVE_EXTRA_WIDTH: [0.0, 0.0, 0.0]
49 | LIMIT_WHOLE_SCENE: True
50 |
51 | - NAME: random_world_flip
52 | ALONG_AXIS_LIST: ['x', 'y']
53 |
54 | - NAME: random_world_rotation
55 | WORLD_ROT_ANGLE: [-0.78539816, 0.78539816]
56 |
57 | - NAME: random_world_scaling
58 | WORLD_SCALE_RANGE: [0.95, 1.05]
59 |
60 |
61 | POINT_FEATURE_ENCODING: {
62 | encoding_type: absolute_coordinates_encoding,
63 | used_feature_list: ['x', 'y', 'z', 'intensity', 'elongation'],
64 | src_feature_list: ['x', 'y', 'z', 'intensity', 'elongation'],
65 | }
66 |
67 |
68 | DATA_PROCESSOR:
69 | - NAME: mask_points_and_boxes_outside_range
70 | REMOVE_OUTSIDE_BOXES: True
71 |
72 | - NAME: shuffle_points
73 | SHUFFLE_ENABLED: {
74 | 'train': True,
75 | 'test': True
76 | }
77 |
78 | - NAME: transform_points_to_voxels
79 | VOXEL_SIZE: [0.1, 0.1, 0.15]
80 | MAX_POINTS_PER_VOXEL: 5
81 | MAX_NUMBER_OF_VOXELS: {
82 | 'train': 150000,
83 | 'test': 150000
84 | }
85 |
--------------------------------------------------------------------------------
/tools/cfgs/dataset_configs/waymo_dataset_multiframe.yaml:
--------------------------------------------------------------------------------
1 | DATASET: 'WaymoDataset'
2 | DATA_PATH: '../data/waymo'
3 | PROCESSED_DATA_TAG: 'waymo_processed_data_v0_5_0'
4 |
5 | POINT_CLOUD_RANGE: [-75.2, -75.2, -2, 75.2, 75.2, 4]
6 |
7 | DATA_SPLIT: {
8 | 'train': train,
9 | 'test': val
10 | }
11 |
12 | SAMPLED_INTERVAL: {
13 | 'train': 5,
14 | 'test': 1
15 | }
16 |
17 | FILTER_EMPTY_BOXES_FOR_TRAIN: True
18 | DISABLE_NLZ_FLAG_ON_POINTS: True
19 |
20 | USE_SHARED_MEMORY: False # it will load the data to shared memory to speed up (DO NOT USE IT IF YOU DO NOT FULLY UNDERSTAND WHAT WILL HAPPEN)
21 | SHARED_MEMORY_FILE_LIMIT: 35000 # set it based on the size of your shared memory
22 |
23 | SEQUENCE_CONFIG:
24 | ENABLED: True
25 | SAMPLE_OFFSET: [-3, 0]
26 |
27 | TRAIN_WITH_SPEED: True
28 |
29 |
30 | DATA_AUGMENTOR:
31 | DISABLE_AUG_LIST: ['placeholder']
32 | AUG_CONFIG_LIST:
33 | - NAME: gt_sampling
34 | USE_ROAD_PLANE: False
35 | DB_INFO_PATH:
36 | - waymo_processed_data_v0_5_0_waymo_dbinfos_train_sampled_1_multiframe_-4_to_0.pkl
37 |
38 | USE_SHARED_MEMORY: False # set it to True to speed up (it costs about 50GB? shared memory)
39 | DB_DATA_PATH:
40 | - waymo_processed_data_v0_5_0_gt_database_train_sampled_1_multiframe_-4_to_0_global.npy
41 |
42 | PREPARE: {
43 | filter_by_min_points: ['Vehicle:5', 'Pedestrian:5', 'Cyclist:5'],
44 | filter_by_difficulty: [-1],
45 | }
46 |
47 | SAMPLE_GROUPS: ['Vehicle:15', 'Pedestrian:10', 'Cyclist:10']
48 | NUM_POINT_FEATURES: 6
49 | REMOVE_EXTRA_WIDTH: [0.0, 0.0, 0.0]
50 | LIMIT_WHOLE_SCENE: True
51 |
52 | FILTER_OBJ_POINTS_BY_TIMESTAMP: True
53 | TIME_RANGE: [0.3, 0.0] # 0.3s-0.0s indicates 4 frames
54 |
55 | - NAME: random_world_flip
56 | ALONG_AXIS_LIST: ['x', 'y']
57 |
58 | - NAME: random_world_rotation
59 | WORLD_ROT_ANGLE: [-0.78539816, 0.78539816]
60 |
61 | - NAME: random_world_scaling
62 | WORLD_SCALE_RANGE: [0.95, 1.05]
63 |
64 |
65 | POINT_FEATURE_ENCODING: {
66 | encoding_type: absolute_coordinates_encoding,
67 | used_feature_list: ['x', 'y', 'z', 'intensity', 'elongation', 'timestamp'],
68 | src_feature_list: ['x', 'y', 'z', 'intensity', 'elongation', 'timestamp'],
69 | }
70 |
71 |
72 | DATA_PROCESSOR:
73 | - NAME: mask_points_and_boxes_outside_range
74 | REMOVE_OUTSIDE_BOXES: True
75 | USE_CENTER_TO_FILTER: True
76 |
77 | - NAME: shuffle_points
78 | SHUFFLE_ENABLED: {
79 | 'train': True,
80 | 'test': True
81 | }
82 |
83 | - NAME: transform_points_to_voxels
84 | VOXEL_SIZE: [0.1, 0.1, 0.15]
85 | MAX_POINTS_PER_VOXEL: 5
86 | MAX_NUMBER_OF_VOXELS: {
87 | 'train': 180000,
88 | 'test': 400000
89 | }
90 |
--------------------------------------------------------------------------------
/tools/cfgs/nuscenes_models/cbgs_voxel01_res3d_centerpoint.yaml:
--------------------------------------------------------------------------------
1 | CLASS_NAMES: ['car','truck', 'construction_vehicle', 'bus', 'trailer',
2 | 'barrier', 'motorcycle', 'bicycle', 'pedestrian', 'traffic_cone']
3 |
4 | DATA_CONFIG:
5 | _BASE_CONFIG_: cfgs/dataset_configs/nuscenes_dataset.yaml
6 |
7 | MODEL:
8 | NAME: CenterPoint
9 |
10 | VFE:
11 | NAME: MeanVFE
12 |
13 | BACKBONE_3D:
14 | NAME: VoxelResBackBone8x
15 |
16 | MAP_TO_BEV:
17 | NAME: HeightCompression
18 | NUM_BEV_FEATURES: 256
19 |
20 | BACKBONE_2D:
21 | NAME: BaseBEVBackbone
22 |
23 | LAYER_NUMS: [5, 5]
24 | LAYER_STRIDES: [1, 2]
25 | NUM_FILTERS: [128, 256]
26 | UPSAMPLE_STRIDES: [1, 2]
27 | NUM_UPSAMPLE_FILTERS: [256, 256]
28 |
29 | DENSE_HEAD:
30 | NAME: CenterHead
31 | CLASS_AGNOSTIC: False
32 |
33 | CLASS_NAMES_EACH_HEAD: [
34 | ['car'],
35 | ['truck', 'construction_vehicle'],
36 | ['bus', 'trailer'],
37 | ['barrier'],
38 | ['motorcycle', 'bicycle'],
39 | ['pedestrian', 'traffic_cone'],
40 | ]
41 |
42 | SHARED_CONV_CHANNEL: 64
43 | USE_BIAS_BEFORE_NORM: True
44 | NUM_HM_CONV: 2
45 | SEPARATE_HEAD_CFG:
46 | HEAD_ORDER: ['center', 'center_z', 'dim', 'rot', 'vel']
47 | HEAD_DICT: {
48 | 'center': {'out_channels': 2, 'num_conv': 2},
49 | 'center_z': {'out_channels': 1, 'num_conv': 2},
50 | 'dim': {'out_channels': 3, 'num_conv': 2},
51 | 'rot': {'out_channels': 2, 'num_conv': 2},
52 | 'vel': {'out_channels': 2, 'num_conv': 2},
53 | }
54 |
55 | TARGET_ASSIGNER_CONFIG:
56 | FEATURE_MAP_STRIDE: 8
57 | NUM_MAX_OBJS: 500
58 | GAUSSIAN_OVERLAP: 0.1
59 | MIN_RADIUS: 2
60 |
61 | LOSS_CONFIG:
62 | LOSS_WEIGHTS: {
63 | 'cls_weight': 1.0,
64 | 'loc_weight': 0.25,
65 | 'code_weights': [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.2, 0.2, 1.0, 1.0]
66 | }
67 |
68 | POST_PROCESSING:
69 | SCORE_THRESH: 0.1
70 | POST_CENTER_LIMIT_RANGE: [-61.2, -61.2, -10.0, 61.2, 61.2, 10.0]
71 | MAX_OBJ_PER_SAMPLE: 500
72 | NMS_CONFIG:
73 | NMS_TYPE: nms_gpu
74 | NMS_THRESH: 0.2
75 | NMS_PRE_MAXSIZE: 1000
76 | NMS_POST_MAXSIZE: 83
77 |
78 | POST_PROCESSING:
79 | RECALL_THRESH_LIST: [0.3, 0.5, 0.7]
80 |
81 | EVAL_METRIC: kitti
82 |
83 |
84 |
85 | OPTIMIZATION:
86 | BATCH_SIZE_PER_GPU: 4
87 | NUM_EPOCHS: 30
88 |
89 | OPTIMIZER: adam_onecycle
90 | LR: 0.003
91 | WEIGHT_DECAY: 0.01
92 | MOMENTUM: 0.9
93 |
94 | MOMS: [0.95, 0.85]
95 | PCT_START: 0.4
96 | DIV_FACTOR: 10
97 | DECAY_STEP_LIST: [35, 45]
98 | LR_DECAY: 0.1
99 | LR_CLIP: 0.0000001
100 |
101 | LR_WARMUP: False
102 | WARMUP_EPOCH: 1
103 |
104 | GRAD_NORM_CLIP: 10
105 |
--------------------------------------------------------------------------------
/tools/cfgs/once_models/centerpoint.yaml:
--------------------------------------------------------------------------------
1 | CLASS_NAMES: ['Car', 'Bus', 'Truck', 'Pedestrian', 'Cyclist']
2 |
3 | DATA_CONFIG:
4 | _BASE_CONFIG_: cfgs/dataset_configs/once_dataset.yaml
5 |
6 | MODEL:
7 | NAME: CenterPoint
8 |
9 | VFE:
10 | NAME: MeanVFE
11 |
12 | BACKBONE_3D:
13 | NAME: VoxelResBackBone8x
14 |
15 | MAP_TO_BEV:
16 | NAME: HeightCompression
17 | NUM_BEV_FEATURES: 256
18 |
19 | BACKBONE_2D:
20 | NAME: BaseBEVBackbone
21 |
22 | LAYER_NUMS: [5, 5]
23 | LAYER_STRIDES: [1, 2]
24 | NUM_FILTERS: [128, 256]
25 | UPSAMPLE_STRIDES: [1, 2]
26 | NUM_UPSAMPLE_FILTERS: [256, 256]
27 |
28 | DENSE_HEAD:
29 | NAME: CenterHead
30 | CLASS_AGNOSTIC: False
31 |
32 | CLASS_NAMES_EACH_HEAD: [
33 | ['Car', 'Bus', 'Truck', 'Pedestrian', 'Cyclist']
34 | ]
35 |
36 | SHARED_CONV_CHANNEL: 64
37 | USE_BIAS_BEFORE_NORM: True # TODO
38 | NUM_HM_CONV: 2 # TODO
39 | SEPARATE_HEAD_CFG:
40 | HEAD_ORDER: ['center', 'center_z', 'dim', 'rot']
41 | HEAD_DICT: {
42 | 'center': {'out_channels': 2, 'num_conv': 2},
43 | 'center_z': {'out_channels': 1, 'num_conv': 2},
44 | 'dim': {'out_channels': 3, 'num_conv': 2},
45 | 'rot': {'out_channels': 2, 'num_conv': 2},
46 | }
47 |
48 | TARGET_ASSIGNER_CONFIG:
49 | FEATURE_MAP_STRIDE: 8
50 | NUM_MAX_OBJS: 500
51 | GAUSSIAN_OVERLAP: 0.1
52 | MIN_RADIUS: 2
53 | DENSE_REG: 1
54 |
55 | LOSS_CONFIG:
56 | LOSS_WEIGHTS: {
57 | 'cls_weight': 1.0,
58 | 'loc_weight': 1.0,
59 | 'code_weights': [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
60 | }
61 |
62 | POST_PROCESSING:
63 | SCORE_THRESH: 0.1
64 | POST_CENTER_LIMIT_RANGE: [-75.2, -75.2, -5.0, 75.2, 75.2, 3.0]
65 | MAX_OBJ_PER_SAMPLE: 500
66 | NMS_CONFIG:
67 | MULTI_CLASSES_NMS: False
68 | NMS_TYPE: nms_gpu
69 | NMS_THRESH: 0.01
70 | NMS_PRE_MAXSIZE: 4096
71 | NMS_POST_MAXSIZE: 500
72 |
73 |
74 | POST_PROCESSING:
75 | RECALL_THRESH_LIST: [0.3, 0.5, 0.7]
76 |
77 | OUTPUT_RAW_SCORE: False
78 |
79 | EVAL_METRIC: once
80 |
81 | OPTIMIZATION:
82 | BATCH_SIZE_PER_GPU: 4
83 | NUM_EPOCHS: 80
84 |
85 | OPTIMIZER: adam_onecycle
86 | LR: 0.003
87 | WEIGHT_DECAY: 0.01
88 | MOMENTUM: 0.9
89 |
90 | MOMS: [0.95, 0.85]
91 | PCT_START: 0.4
92 | DIV_FACTOR: 10
93 | DECAY_STEP_LIST: [35, 45]
94 | LR_DECAY: 0.1
95 | LR_CLIP: 0.0000001
96 |
97 | LR_WARMUP: False
98 | WARMUP_EPOCH: 1
99 |
100 | GRAD_NORM_CLIP: 35
101 |
--------------------------------------------------------------------------------
/tools/cfgs/waymo_models/centerpoint.yaml:
--------------------------------------------------------------------------------
1 | CLASS_NAMES: ['Vehicle', 'Pedestrian', 'Cyclist']
2 |
3 | DATA_CONFIG:
4 | _BASE_CONFIG_: cfgs/dataset_configs/waymo_dataset.yaml
5 |
6 | MODEL:
7 | NAME: CenterPoint
8 |
9 | VFE:
10 | NAME: MeanVFE
11 |
12 | BACKBONE_3D:
13 | NAME: VoxelResBackBone8x
14 |
15 | MAP_TO_BEV:
16 | NAME: HeightCompression
17 | NUM_BEV_FEATURES: 256
18 |
19 | BACKBONE_2D:
20 | NAME: BaseBEVBackbone
21 |
22 | LAYER_NUMS: [5, 5]
23 | LAYER_STRIDES: [1, 2]
24 | NUM_FILTERS: [128, 256]
25 | UPSAMPLE_STRIDES: [1, 2]
26 | NUM_UPSAMPLE_FILTERS: [256, 256]
27 |
28 | DENSE_HEAD:
29 | NAME: CenterHead
30 | CLASS_AGNOSTIC: False
31 |
32 | CLASS_NAMES_EACH_HEAD: [
33 | ['Vehicle', 'Pedestrian', 'Cyclist']
34 | ]
35 |
36 | SHARED_CONV_CHANNEL: 64
37 | USE_BIAS_BEFORE_NORM: True
38 | NUM_HM_CONV: 2
39 | SEPARATE_HEAD_CFG:
40 | HEAD_ORDER: ['center', 'center_z', 'dim', 'rot']
41 | HEAD_DICT: {
42 | 'center': {'out_channels': 2, 'num_conv': 2},
43 | 'center_z': {'out_channels': 1, 'num_conv': 2},
44 | 'dim': {'out_channels': 3, 'num_conv': 2},
45 | 'rot': {'out_channels': 2, 'num_conv': 2},
46 | }
47 |
48 | TARGET_ASSIGNER_CONFIG:
49 | FEATURE_MAP_STRIDE: 8
50 | NUM_MAX_OBJS: 500
51 | GAUSSIAN_OVERLAP: 0.1
52 | MIN_RADIUS: 2
53 |
54 | LOSS_CONFIG:
55 | LOSS_WEIGHTS: {
56 | 'cls_weight': 1.0,
57 | 'loc_weight': 2.0,
58 | 'code_weights': [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
59 | }
60 |
61 | POST_PROCESSING:
62 | SCORE_THRESH: 0.1
63 | POST_CENTER_LIMIT_RANGE: [-75.2, -75.2, -2, 75.2, 75.2, 4]
64 | MAX_OBJ_PER_SAMPLE: 500
65 | NMS_CONFIG:
66 | NMS_TYPE: nms_gpu
67 | NMS_THRESH: 0.7
68 | NMS_PRE_MAXSIZE: 4096
69 | NMS_POST_MAXSIZE: 500
70 |
71 | POST_PROCESSING:
72 | RECALL_THRESH_LIST: [0.3, 0.5, 0.7]
73 |
74 | EVAL_METRIC: waymo
75 |
76 |
77 | OPTIMIZATION:
78 | BATCH_SIZE_PER_GPU: 4
79 | NUM_EPOCHS: 30
80 |
81 | OPTIMIZER: adam_onecycle
82 | LR: 0.003
83 | WEIGHT_DECAY: 0.01
84 | MOMENTUM: 0.9
85 |
86 | MOMS: [0.95, 0.85]
87 | PCT_START: 0.4
88 | DIV_FACTOR: 10
89 | DECAY_STEP_LIST: [35, 45]
90 | LR_DECAY: 0.1
91 | LR_CLIP: 0.0000001
92 |
93 | LR_WARMUP: False
94 | WARMUP_EPOCH: 1
95 |
96 | GRAD_NORM_CLIP: 10
97 |
--------------------------------------------------------------------------------
/tools/cfgs/waymo_models/centerpoint_4frames.yaml:
--------------------------------------------------------------------------------
1 | CLASS_NAMES: ['Vehicle', 'Pedestrian', 'Cyclist']
2 |
3 | DATA_CONFIG:
4 | _BASE_CONFIG_: cfgs/dataset_configs/waymo_dataset_multiframe.yaml
5 |
6 | SAMPLED_INTERVAL: {
7 | 'train': 1,
8 | 'test': 1
9 | }
10 |
11 | MODEL:
12 | NAME: CenterPoint
13 |
14 | VFE:
15 | NAME: MeanVFE
16 |
17 | BACKBONE_3D:
18 | NAME: VoxelResBackBone8x
19 |
20 | MAP_TO_BEV:
21 | NAME: HeightCompression
22 | NUM_BEV_FEATURES: 256
23 |
24 | BACKBONE_2D:
25 | NAME: BaseBEVBackbone
26 |
27 | LAYER_NUMS: [5, 5]
28 | LAYER_STRIDES: [1, 2]
29 | NUM_FILTERS: [128, 256]
30 | UPSAMPLE_STRIDES: [1, 2]
31 | NUM_UPSAMPLE_FILTERS: [256, 256]
32 |
33 | DENSE_HEAD:
34 | NAME: CenterHead
35 | CLASS_AGNOSTIC: False
36 |
37 | CLASS_NAMES_EACH_HEAD: [
38 | ['Vehicle', 'Pedestrian', 'Cyclist']
39 | ]
40 |
41 | SHARED_CONV_CHANNEL: 64
42 | USE_BIAS_BEFORE_NORM: True
43 | NUM_HM_CONV: 2
44 | SEPARATE_HEAD_CFG:
45 | HEAD_ORDER: ['center', 'center_z', 'dim', 'rot', 'vel']
46 | HEAD_DICT: {
47 | 'center': {'out_channels': 2, 'num_conv': 2},
48 | 'center_z': {'out_channels': 1, 'num_conv': 2},
49 | 'dim': {'out_channels': 3, 'num_conv': 2},
50 | 'rot': {'out_channels': 2, 'num_conv': 2},
51 | 'vel': {'out_channels': 2, 'num_conv': 2},
52 | }
53 |
54 | TARGET_ASSIGNER_CONFIG:
55 | FEATURE_MAP_STRIDE: 8
56 | NUM_MAX_OBJS: 500
57 | GAUSSIAN_OVERLAP: 0.1
58 | MIN_RADIUS: 2
59 |
60 | LOSS_CONFIG:
61 | LOSS_WEIGHTS: {
62 | 'cls_weight': 1.0,
63 | 'loc_weight': 2.0,
64 | 'code_weights': [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.2, 0.2]
65 | }
66 |
67 | POST_PROCESSING:
68 | SCORE_THRESH: 0.1
69 | POST_CENTER_LIMIT_RANGE: [-75.2, -75.2, -2, 75.2, 75.2, 4]
70 | MAX_OBJ_PER_SAMPLE: 500
71 | NMS_CONFIG:
72 | NMS_TYPE: nms_gpu
73 | NMS_THRESH: 0.7
74 | NMS_PRE_MAXSIZE: 4096
75 | NMS_POST_MAXSIZE: 500
76 |
77 | POST_PROCESSING:
78 | RECALL_THRESH_LIST: [0.3, 0.5, 0.7]
79 |
80 | EVAL_METRIC: waymo
81 |
82 |
83 | OPTIMIZATION:
84 | BATCH_SIZE_PER_GPU: 4
85 | NUM_EPOCHS: 36
86 |
87 | OPTIMIZER: adam_onecycle
88 | LR: 0.003
89 | WEIGHT_DECAY: 0.01
90 | MOMENTUM: 0.9
91 |
92 | MOMS: [0.95, 0.85]
93 | PCT_START: 0.4
94 | DIV_FACTOR: 10
95 | DECAY_STEP_LIST: [35, 45]
96 | LR_DECAY: 0.1
97 | LR_CLIP: 0.0000001
98 |
99 | LR_WARMUP: False
100 | WARMUP_EPOCH: 1
101 |
102 | GRAD_NORM_CLIP: 10
103 |
--------------------------------------------------------------------------------
/tools/cfgs/waymo_models/centerpoint_dyn_pillar_1x.yaml:
--------------------------------------------------------------------------------
1 | CLASS_NAMES: ['Vehicle', 'Pedestrian', 'Cyclist']
2 |
3 | DATA_CONFIG:
4 | _BASE_CONFIG_: cfgs/dataset_configs/waymo_dataset.yaml
5 |
6 | POINT_CLOUD_RANGE: [-74.88, -74.88, -2, 74.88, 74.88, 4.0]
7 | DATA_PROCESSOR:
8 | - NAME: mask_points_and_boxes_outside_range
9 | REMOVE_OUTSIDE_BOXES: True
10 |
11 | - NAME: shuffle_points
12 | SHUFFLE_ENABLED: {
13 | 'train': True,
14 | 'test': True
15 | }
16 |
17 | - NAME: transform_points_to_voxels_placeholder
18 | VOXEL_SIZE: [ 0.32, 0.32, 6.0 ]
19 |
20 | MODEL:
21 | NAME: CenterPoint
22 |
23 | VFE:
24 | NAME: DynPillarVFE
25 | WITH_DISTANCE: False
26 | USE_ABSLOTE_XYZ: True
27 | USE_NORM: True
28 | NUM_FILTERS: [ 64, 64 ]
29 |
30 | MAP_TO_BEV:
31 | NAME: PointPillarScatter
32 | NUM_BEV_FEATURES: 64
33 |
34 | BACKBONE_2D:
35 | NAME: BaseBEVBackbone
36 | LAYER_NUMS: [ 3, 5, 5 ]
37 | LAYER_STRIDES: [ 1, 2, 2 ]
38 | NUM_FILTERS: [ 64, 128, 256 ]
39 | UPSAMPLE_STRIDES: [ 1, 2, 4 ]
40 | NUM_UPSAMPLE_FILTERS: [ 128, 128, 128 ]
41 |
42 | DENSE_HEAD:
43 | NAME: CenterHead
44 | CLASS_AGNOSTIC: False
45 |
46 | CLASS_NAMES_EACH_HEAD: [
47 | ['Vehicle', 'Pedestrian', 'Cyclist']
48 | ]
49 |
50 | SHARED_CONV_CHANNEL: 64
51 | USE_BIAS_BEFORE_NORM: True
52 | NUM_HM_CONV: 2
53 | SEPARATE_HEAD_CFG:
54 | HEAD_ORDER: ['center', 'center_z', 'dim', 'rot']
55 | HEAD_DICT: {
56 | 'center': {'out_channels': 2, 'num_conv': 2},
57 | 'center_z': {'out_channels': 1, 'num_conv': 2},
58 | 'dim': {'out_channels': 3, 'num_conv': 2},
59 | 'rot': {'out_channels': 2, 'num_conv': 2},
60 | }
61 |
62 | TARGET_ASSIGNER_CONFIG:
63 | FEATURE_MAP_STRIDE: 1
64 | NUM_MAX_OBJS: 500
65 | GAUSSIAN_OVERLAP: 0.1
66 | MIN_RADIUS: 2
67 |
68 | LOSS_CONFIG:
69 | LOSS_WEIGHTS: {
70 | 'cls_weight': 1.0,
71 | 'loc_weight': 2.0,
72 | 'code_weights': [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
73 | }
74 |
75 | POST_PROCESSING:
76 | SCORE_THRESH: 0.1
77 | POST_CENTER_LIMIT_RANGE: [-80, -80, -10.0, 80, 80, 10.0]
78 | MAX_OBJ_PER_SAMPLE: 500
79 | NMS_CONFIG:
80 | NMS_TYPE: nms_gpu
81 | NMS_THRESH: 0.7
82 | NMS_PRE_MAXSIZE: 4096
83 | NMS_POST_MAXSIZE: 500
84 |
85 | POST_PROCESSING:
86 | RECALL_THRESH_LIST: [0.3, 0.5, 0.7]
87 |
88 | EVAL_METRIC: waymo
89 |
90 |
91 | OPTIMIZATION:
92 | BATCH_SIZE_PER_GPU: 2
93 | NUM_EPOCHS: 30
94 |
95 | OPTIMIZER: adam_onecycle
96 | LR: 0.003
97 | WEIGHT_DECAY: 0.01
98 | MOMENTUM: 0.9
99 |
100 | MOMS: [0.95, 0.85]
101 | PCT_START: 0.4
102 | DIV_FACTOR: 10
103 | DECAY_STEP_LIST: [35, 45]
104 | LR_DECAY: 0.1
105 | LR_CLIP: 0.0000001
106 |
107 | LR_WARMUP: False
108 | WARMUP_EPOCH: 1
109 |
110 | GRAD_NORM_CLIP: 10
111 |
--------------------------------------------------------------------------------
/tools/cfgs/waymo_models/centerpoint_without_resnet.yaml:
--------------------------------------------------------------------------------
1 | CLASS_NAMES: ['Vehicle', 'Pedestrian', 'Cyclist']
2 |
3 | DATA_CONFIG:
4 | _BASE_CONFIG_: cfgs/dataset_configs/waymo_dataset.yaml
5 |
6 | MODEL:
7 | NAME: CenterPoint
8 |
9 | VFE:
10 | NAME: MeanVFE
11 |
12 | BACKBONE_3D:
13 | NAME: VoxelBackBone8x
14 |
15 | MAP_TO_BEV:
16 | NAME: HeightCompression
17 | NUM_BEV_FEATURES: 256
18 |
19 | BACKBONE_2D:
20 | NAME: BaseBEVBackbone
21 |
22 | LAYER_NUMS: [5, 5]
23 | LAYER_STRIDES: [1, 2]
24 | NUM_FILTERS: [128, 256]
25 | UPSAMPLE_STRIDES: [1, 2]
26 | NUM_UPSAMPLE_FILTERS: [256, 256]
27 |
28 | DENSE_HEAD:
29 | NAME: CenterHead
30 | CLASS_AGNOSTIC: False
31 |
32 | CLASS_NAMES_EACH_HEAD: [
33 | ['Vehicle', 'Pedestrian', 'Cyclist']
34 | ]
35 |
36 | SHARED_CONV_CHANNEL: 64
37 | USE_BIAS_BEFORE_NORM: True
38 | NUM_HM_CONV: 2
39 | SEPARATE_HEAD_CFG:
40 | HEAD_ORDER: ['center', 'center_z', 'dim', 'rot']
41 | HEAD_DICT: {
42 | 'center': {'out_channels': 2, 'num_conv': 2},
43 | 'center_z': {'out_channels': 1, 'num_conv': 2},
44 | 'dim': {'out_channels': 3, 'num_conv': 2},
45 | 'rot': {'out_channels': 2, 'num_conv': 2},
46 | }
47 |
48 | TARGET_ASSIGNER_CONFIG:
49 | FEATURE_MAP_STRIDE: 8
50 | NUM_MAX_OBJS: 500
51 | GAUSSIAN_OVERLAP: 0.1
52 | MIN_RADIUS: 2
53 |
54 | LOSS_CONFIG:
55 | LOSS_WEIGHTS: {
56 | 'cls_weight': 1.0,
57 | 'loc_weight': 2.0,
58 | 'code_weights': [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
59 | }
60 |
61 | POST_PROCESSING:
62 | SCORE_THRESH: 0.1
63 | POST_CENTER_LIMIT_RANGE: [-75.2, -75.2, -2, 75.2, 75.2, 4]
64 | MAX_OBJ_PER_SAMPLE: 500
65 | NMS_CONFIG:
66 | NMS_TYPE: nms_gpu
67 | NMS_THRESH: 0.7
68 | NMS_PRE_MAXSIZE: 4096
69 | NMS_POST_MAXSIZE: 500
70 |
71 | POST_PROCESSING:
72 | RECALL_THRESH_LIST: [0.3, 0.5, 0.7]
73 |
74 | EVAL_METRIC: waymo
75 |
76 |
77 | OPTIMIZATION:
78 | BATCH_SIZE_PER_GPU: 4
79 | NUM_EPOCHS: 30
80 |
81 | OPTIMIZER: adam_onecycle
82 | LR: 0.003
83 | WEIGHT_DECAY: 0.01
84 | MOMENTUM: 0.9
85 |
86 | MOMS: [0.95, 0.85]
87 | PCT_START: 0.4
88 | DIV_FACTOR: 10
89 | DECAY_STEP_LIST: [35, 45]
90 | LR_DECAY: 0.1
91 | LR_CLIP: 0.0000001
92 |
93 | LR_WARMUP: False
94 | WARMUP_EPOCH: 1
95 |
96 | GRAD_NORM_CLIP: 10
97 |
--------------------------------------------------------------------------------
/tools/cfgs/waymo_models/pillarnet.yaml:
--------------------------------------------------------------------------------
1 | CLASS_NAMES: ['Vehicle', 'Pedestrian', 'Cyclist']
2 |
3 | DATA_CONFIG:
4 | _BASE_CONFIG_: cfgs/dataset_configs/waymo_dataset.yaml
5 |
6 | MODEL:
7 | NAME: PillarNet
8 |
9 | VFE:
10 | NAME: DynamicPillarVFESimple2D
11 | WITH_DISTANCE: False
12 | USE_ABSLOTE_XYZ: True
13 | USE_CLUSTER_XYZ: False
14 | USE_NORM: True
15 | NUM_FILTERS: [32]
16 |
17 | BACKBONE_3D:
18 | NAME: PillarRes18BackBone8x
19 |
20 | BACKBONE_2D:
21 | NAME: BaseBEVBackboneV1
22 |
23 | LAYER_NUMS: [5, 5]
24 | LAYER_STRIDES: [1, 2]
25 | NUM_FILTERS: [256, 256]
26 | UPSAMPLE_STRIDES: [1, 2]
27 | NUM_UPSAMPLE_FILTERS: [128, 128]
28 |
29 | DENSE_HEAD:
30 | NAME: CenterHead
31 | CLASS_AGNOSTIC: False
32 |
33 | CLASS_NAMES_EACH_HEAD: [
34 | ['Vehicle', 'Pedestrian', 'Cyclist']
35 | ]
36 |
37 | SHARED_CONV_CHANNEL: 64
38 | USE_BIAS_BEFORE_NORM: True
39 | NUM_HM_CONV: 2
40 | SEPARATE_HEAD_CFG:
41 | HEAD_ORDER: ['center', 'center_z', 'dim', 'rot']
42 | HEAD_DICT: {
43 | 'center': {'out_channels': 2, 'num_conv': 2},
44 | 'center_z': {'out_channels': 1, 'num_conv': 2},
45 | 'dim': {'out_channels': 3, 'num_conv': 2},
46 | 'rot': {'out_channels': 2, 'num_conv': 2},
47 | }
48 |
49 | TARGET_ASSIGNER_CONFIG:
50 | FEATURE_MAP_STRIDE: 8
51 | NUM_MAX_OBJS: 500
52 | GAUSSIAN_OVERLAP: 0.1
53 | MIN_RADIUS: 2
54 |
55 | LOSS_CONFIG:
56 | LOSS_WEIGHTS: {
57 | 'cls_weight': 1.0,
58 | 'loc_weight': 2.0,
59 | 'code_weights': [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
60 | }
61 |
62 | POST_PROCESSING:
63 | SCORE_THRESH: 0.1
64 | POST_CENTER_LIMIT_RANGE: [-75.2, -75.2, -2, 75.2, 75.2, 4]
65 | MAX_OBJ_PER_SAMPLE: 500
66 | NMS_CONFIG:
67 | NMS_TYPE: nms_gpu
68 | NMS_THRESH: 0.7
69 | NMS_PRE_MAXSIZE: 4096
70 | NMS_POST_MAXSIZE: 500
71 |
72 | POST_PROCESSING:
73 | RECALL_THRESH_LIST: [0.3, 0.5, 0.7]
74 |
75 | EVAL_METRIC: waymo
76 |
77 |
78 | OPTIMIZATION:
79 | BATCH_SIZE_PER_GPU: 4
80 | NUM_EPOCHS: 30
81 |
82 | OPTIMIZER: adam_onecycle
83 | LR: 0.003
84 | WEIGHT_DECAY: 0.01
85 | MOMENTUM: 0.9
86 |
87 | MOMS: [0.95, 0.85]
88 | PCT_START: 0.4
89 | DIV_FACTOR: 10
90 | DECAY_STEP_LIST: [35, 45]
91 | LR_DECAY: 0.1
92 | LR_CLIP: 0.0000001
93 |
94 | LR_WARMUP: False
95 | WARMUP_EPOCH: 1
96 |
97 | GRAD_NORM_CLIP: 10
98 |
--------------------------------------------------------------------------------
/tools/cfgs/waymo_models/voxelnext2d_ioubranch.yaml:
--------------------------------------------------------------------------------
1 | CLASS_NAMES: ['Vehicle', 'Pedestrian', 'Cyclist']
2 |
3 | DATA_CONFIG:
4 | _BASE_CONFIG_: cfgs/dataset_configs/waymo_dataset.yaml
5 |
6 | MODEL:
7 | NAME: VoxelNeXt
8 |
9 | VFE:
10 | NAME: DynamicPillarVFESimple2D
11 | WITH_DISTANCE: False
12 | USE_ABSLOTE_XYZ: True
13 | USE_CLUSTER_XYZ: False
14 | USE_NORM: True
15 | NUM_FILTERS: [32]
16 |
17 | BACKBONE_3D:
18 | NAME: VoxelResBackBone8xVoxelNeXt2D
19 |
20 | DENSE_HEAD:
21 | NAME: VoxelNeXtHead
22 | IOU_BRANCH: True
23 | CLASS_AGNOSTIC: False
24 | INPUT_FEATURES: 256
25 |
26 | CLASS_NAMES_EACH_HEAD: [
27 | ['Vehicle', 'Pedestrian', 'Cyclist'],
28 | ]
29 |
30 | SHARED_CONV_CHANNEL: 256
31 | USE_BIAS_BEFORE_NORM: True
32 | NUM_HM_CONV: 2
33 | SEPARATE_HEAD_CFG:
34 | HEAD_ORDER: ['center', 'center_z', 'dim', 'rot']
35 | HEAD_DICT: {
36 | 'center': {'out_channels': 2, 'num_conv': 2},
37 | 'center_z': {'out_channels': 1, 'num_conv': 2},
38 | 'dim': {'out_channels': 3, 'num_conv': 2},
39 | 'rot': {'out_channels': 2, 'num_conv': 2},
40 | 'iou': {'out_channels': 1, 'num_conv': 2},
41 | }
42 | RECTIFIER: [0.68, 0.71, 0.65]
43 | TARGET_ASSIGNER_CONFIG:
44 | FEATURE_MAP_STRIDE: 8
45 | NUM_MAX_OBJS: 500
46 | GAUSSIAN_OVERLAP: 0.1
47 | MIN_RADIUS: 2
48 |
49 | LOSS_CONFIG:
50 | LOSS_WEIGHTS: {
51 | 'cls_weight': 1.0,
52 | 'loc_weight': 2.0,
53 | 'code_weights': [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
54 | }
55 |
56 | POST_PROCESSING:
57 | SCORE_THRESH: 0.1
58 | POST_CENTER_LIMIT_RANGE: [-75.2, -75.2, -2, 75.2, 75.2, 4]
59 | MAX_OBJ_PER_SAMPLE: 500
60 | NMS_CONFIG:
61 | NMS_TYPE: nms_gpu
62 | NMS_THRESH: [0.8, 0.55, 0.55] #0.7
63 | NMS_PRE_MAXSIZE: [2048, 1024, 1024] #[4096]
64 | NMS_POST_MAXSIZE: [200, 150, 150] #500
65 |
66 | POST_PROCESSING:
67 | RECALL_THRESH_LIST: [0.3, 0.5, 0.7]
68 |
69 | EVAL_METRIC: waymo
70 |
71 |
72 | OPTIMIZATION:
73 | BATCH_SIZE_PER_GPU: 4
74 | NUM_EPOCHS: 12
75 |
76 | OPTIMIZER: adam_onecycle
77 | LR: 0.003
78 | WEIGHT_DECAY: 0.01
79 | MOMENTUM: 0.9
80 |
81 | MOMS: [0.95, 0.85]
82 | PCT_START: 0.4
83 | DIV_FACTOR: 10
84 | DECAY_STEP_LIST: [35, 45]
85 | LR_DECAY: 0.1
86 | LR_CLIP: 0.0000001
87 |
88 | LR_WARMUP: False
89 | WARMUP_EPOCH: 1
90 |
91 | GRAD_NORM_CLIP: 10
92 |
--------------------------------------------------------------------------------
/tools/cfgs/waymo_models/voxelnext_ioubranch_large.yaml:
--------------------------------------------------------------------------------
1 | CLASS_NAMES: ['Vehicle', 'Pedestrian', 'Cyclist']
2 |
3 | DATA_CONFIG:
4 | _BASE_CONFIG_: cfgs/dataset_configs/waymo_dataset.yaml
5 |
6 | MODEL:
7 | NAME: VoxelNeXt
8 |
9 | VFE:
10 | NAME: MeanVFE
11 |
12 | BACKBONE_3D:
13 | NAME: VoxelResBackBone8xVoxelNeXt
14 | SPCONV_KERNEL_SIZES: [5, 5, 3, 3]
15 | OUT_CHANNEL: 256
16 | CHANNELS: [32, 64, 128, 256, 256]
17 |
18 | DENSE_HEAD:
19 | NAME: VoxelNeXtHead
20 | IOU_BRANCH: True
21 | CLASS_AGNOSTIC: False
22 | INPUT_FEATURES: 256
23 |
24 | CLASS_NAMES_EACH_HEAD: [
25 | ['Vehicle', 'Pedestrian', 'Cyclist']
26 | ]
27 |
28 | SHARED_CONV_CHANNEL: 256
29 | USE_BIAS_BEFORE_NORM: True
30 | NUM_HM_CONV: 2
31 | SEPARATE_HEAD_CFG:
32 | HEAD_ORDER: ['center', 'center_z', 'dim', 'rot']
33 | HEAD_DICT: {
34 | 'center': {'out_channels': 2, 'num_conv': 2},
35 | 'center_z': {'out_channels': 1, 'num_conv': 2},
36 | 'dim': {'out_channels': 3, 'num_conv': 2},
37 | 'rot': {'out_channels': 2, 'num_conv': 2},
38 | 'iou': {'out_channels': 1, 'num_conv': 2},
39 | }
40 | RECTIFIER: [0.68, 0.71, 0.65]
41 | TARGET_ASSIGNER_CONFIG:
42 | FEATURE_MAP_STRIDE: 8
43 | NUM_MAX_OBJS: 500
44 | GAUSSIAN_OVERLAP: 0.1
45 | MIN_RADIUS: 2
46 |
47 | LOSS_CONFIG:
48 | LOSS_WEIGHTS: {
49 | 'cls_weight': 1.0,
50 | 'loc_weight': 2.0,
51 | 'code_weights': [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
52 | }
53 |
54 | POST_PROCESSING:
55 | SCORE_THRESH: 0.1
56 | POST_CENTER_LIMIT_RANGE: [-75.2, -75.2, -2, 75.2, 75.2, 4]
57 | MAX_OBJ_PER_SAMPLE: 500
58 | NMS_CONFIG:
59 | NMS_TYPE: nms_gpu
60 | NMS_THRESH: [0.8, 0.55, 0.55] #0.7
61 | NMS_PRE_MAXSIZE: [2048, 1024, 1024] #[4096]
62 | NMS_POST_MAXSIZE: [200, 150, 150] #500
63 |
64 | POST_PROCESSING:
65 | RECALL_THRESH_LIST: [0.3, 0.5, 0.7]
66 |
67 | EVAL_METRIC: waymo
68 |
69 |
70 | OPTIMIZATION:
71 | BATCH_SIZE_PER_GPU: 4
72 | NUM_EPOCHS: 12
73 |
74 | OPTIMIZER: adam_onecycle
75 | LR: 0.003
76 | WEIGHT_DECAY: 0.01
77 | MOMENTUM: 0.9
78 |
79 | MOMS: [0.95, 0.85]
80 | PCT_START: 0.4
81 | DIV_FACTOR: 10
82 | DECAY_STEP_LIST: [35, 45]
83 | LR_DECAY: 0.1
84 | LR_CLIP: 0.0000001
85 |
86 | LR_WARMUP: False
87 | WARMUP_EPOCH: 1
88 |
89 | GRAD_NORM_CLIP: 10
90 |
--------------------------------------------------------------------------------
/tools/scripts/dist_test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -x
4 | NGPUS=$1
5 | PY_ARGS=${@:2}
6 |
7 | python -m torch.distributed.launch --nproc_per_node=${NGPUS} test.py --launcher pytorch ${PY_ARGS}
8 |
--------------------------------------------------------------------------------
/tools/scripts/dist_train.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -x
4 | NGPUS=$1
5 | PY_ARGS=${@:2}
6 |
7 | while true
8 | do
9 | PORT=$(( ((RANDOM<<15)|RANDOM) % 49152 + 10000 ))
10 | status="$(nc -z 127.0.0.1 $PORT < /dev/null &>/dev/null; echo $?)"
11 | if [ "${status}" != "0" ]; then
12 | break;
13 | fi
14 | done
15 | echo $PORT
16 |
17 | python -m torch.distributed.launch --nproc_per_node=${NGPUS} --rdzv_endpoint=localhost:${PORT} train.py --launcher pytorch ${PY_ARGS}
18 |
19 |
--------------------------------------------------------------------------------
/tools/scripts/slurm_test_mgpu.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -x
4 |
5 | PARTITION=$1
6 | GPUS=$2
7 | GPUS_PER_NODE=$GPUS
8 | PY_ARGS=${@:3}
9 | JOB_NAME=eval
10 | SRUN_ARGS=${SRUN_ARGS:-""}
11 |
12 | while true
13 | do
14 | PORT=$(( ((RANDOM<<15)|RANDOM) % 49152 + 10000 ))
15 | status="$(nc -z 127.0.0.1 $PORT < /dev/null &>/dev/null; echo $?)"
16 | if [ "${status}" != "0" ]; then
17 | break;
18 | fi
19 | done
20 | echo $PORT
21 |
22 | srun -p ${PARTITION} \
23 | --job-name=${JOB_NAME} \
24 | --gres=gpu:${GPUS_PER_NODE} \
25 | --ntasks=${GPUS} \
26 | --ntasks-per-node=${GPUS_PER_NODE} \
27 | --kill-on-bad-exit=1 \
28 | ${SRUN_ARGS} \
29 | python -u test.py --launcher slurm --tcp_port $PORT ${PY_ARGS}
30 |
31 |
--------------------------------------------------------------------------------
/tools/scripts/slurm_test_single.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -x
4 |
5 | PARTITION=$1
6 | GPUS=1
7 | GPUS_PER_NODE=1
8 | PY_ARGS=${@:2}
9 | JOB_NAME=eval
10 | SRUN_ARGS=${SRUN_ARGS:-""}
11 |
12 | srun -p ${PARTITION} \
13 | --job-name=${JOB_NAME} \
14 | --gres=gpu:${GPUS_PER_NODE} \
15 | --ntasks=${GPUS} \
16 | --ntasks-per-node=${GPUS_PER_NODE} \
17 | --kill-on-bad-exit=1 \
18 | ${SRUN_ARGS} \
19 | python -u test.py ${PY_ARGS}
20 |
--------------------------------------------------------------------------------
/tools/scripts/slurm_train.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -x
4 |
5 | PARTITION=$1
6 | JOB_NAME=$2
7 | GPUS=$3
8 | PY_ARGS=${@:4}
9 |
10 | GPUS_PER_NODE=${GPUS_PER_NODE:-8}
11 | CPUS_PER_TASK=${CPUS_PER_TASK:-5}
12 | SRUN_ARGS=${SRUN_ARGS:-""}
13 |
14 | while true
15 | do
16 | PORT=$(( ((RANDOM<<15)|RANDOM) % 49152 + 10000 ))
17 | status="$(nc -z 127.0.0.1 $PORT < /dev/null &>/dev/null; echo $?)"
18 | if [ "${status}" != "0" ]; then
19 | break;
20 | fi
21 | done
22 | echo $PORT
23 |
24 | srun -p ${PARTITION} \
25 | --job-name=${JOB_NAME} \
26 | --gres=gpu:${GPUS_PER_NODE} \
27 | --ntasks=${GPUS} \
28 | --ntasks-per-node=${GPUS_PER_NODE} \
29 | --cpus-per-task=${CPUS_PER_TASK} \
30 | --kill-on-bad-exit=1 \
31 | ${SRUN_ARGS} \
32 | python -u train.py --launcher slurm --tcp_port $PORT ${PY_ARGS}
33 |
--------------------------------------------------------------------------------
/tools/scripts/slurm_train_v2.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -x
4 |
5 | PARTITION=$1
6 | JOB_NAME=$2
7 | GPUS=$3
8 | PY_ARGS=${@:4}
9 |
10 | GPUS_PER_NODE=${GPUS_PER_NODE:-8}
11 | CPUS_PER_TASK=${CPUS_PER_TASK:-40}
12 | SRUN_ARGS=${SRUN_ARGS:-""}
13 |
14 | while true
15 | do
16 | PORT=$(( ((RANDOM<<15)|RANDOM) % 49152 + 10000 ))
17 | status="$(nc -z 127.0.0.1 $PORT < /dev/null &>/dev/null; echo $?)"
18 | if [ "${status}" != "0" ]; then
19 | break;
20 | fi
21 | done
22 | echo $PORT
23 |
24 | srun -p ${PARTITION} \
25 | --job-name=${JOB_NAME} \
26 | --gres=gpu:${GPUS_PER_NODE} \
27 | --cpus-per-task=${CPUS_PER_TASK} \
28 | --kill-on-bad-exit=1 \
29 | ${SRUN_ARGS} \
30 | python -m torch.distributed.launch --nproc_per_node=${GPUS_PER_NODE} train.py --launcher pytorch --tcp_port ${PORT} ${PY_ARGS}
31 |
--------------------------------------------------------------------------------
/tools/scripts/torch_test.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -x
4 | NGPUS=$1
5 | PY_ARGS=${@:2}
6 |
7 | while true
8 | do
9 | PORT=$(( ((RANDOM<<15)|RANDOM) % 49152 + 10000 ))
10 | status="$(nc -z 127.0.0.1 $PORT < /dev/null &>/dev/null; echo $?)"
11 | if [ "${status}" != "0" ]; then
12 | break;
13 | fi
14 | done
15 | echo $PORT
16 |
17 | torchrun --nproc_per_node=${NGPUS} --rdzv_endpoint=localhost:${PORT} test.py --launcher pytorch ${PY_ARGS}
18 |
19 |
--------------------------------------------------------------------------------
/tools/scripts/torch_train.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -x
4 | NGPUS=$1
5 | PY_ARGS=${@:2}
6 |
7 | while true
8 | do
9 | PORT=$(( ((RANDOM<<15)|RANDOM) % 49152 + 10000 ))
10 | status="$(nc -z 127.0.0.1 $PORT < /dev/null &>/dev/null; echo $?)"
11 | if [ "${status}" != "0" ]; then
12 | break;
13 | fi
14 | done
15 | echo $PORT
16 |
17 | torchrun --nproc_per_node=${NGPUS} --rdzv_endpoint=localhost:${PORT} train.py --launcher pytorch ${PY_ARGS}
18 |
19 |
--------------------------------------------------------------------------------
/tools/train_utils/optimization/__init__.py:
--------------------------------------------------------------------------------
1 | from functools import partial
2 |
3 | import torch.nn as nn
4 | import torch.optim as optim
5 | import torch.optim.lr_scheduler as lr_sched
6 |
7 | from .fastai_optim import OptimWrapper
8 | from .learning_schedules_fastai import CosineWarmupLR, OneCycle, CosineAnnealing
9 |
10 |
11 | def build_optimizer(model, optim_cfg):
12 | if optim_cfg.OPTIMIZER == 'adam':
13 | optimizer = optim.Adam(model.parameters(), lr=optim_cfg.LR, weight_decay=optim_cfg.WEIGHT_DECAY)
14 | elif optim_cfg.OPTIMIZER == 'sgd':
15 | optimizer = optim.SGD(
16 | model.parameters(), lr=optim_cfg.LR, weight_decay=optim_cfg.WEIGHT_DECAY,
17 | momentum=optim_cfg.MOMENTUM
18 | )
19 | elif optim_cfg.OPTIMIZER in ['adam_onecycle','adam_cosineanneal']:
20 | def children(m: nn.Module):
21 | return list(m.children())
22 |
23 | def num_children(m: nn.Module) -> int:
24 | return len(children(m))
25 |
26 | flatten_model = lambda m: sum(map(flatten_model, m.children()), []) if num_children(m) else [m]
27 | get_layer_groups = lambda m: [nn.Sequential(*flatten_model(m))]
28 | betas = optim_cfg.get('BETAS', (0.9, 0.99))
29 | betas = tuple(betas)
30 | optimizer_func = partial(optim.Adam, betas=betas)
31 | optimizer = OptimWrapper.create(
32 | optimizer_func, 3e-3, get_layer_groups(model), wd=optim_cfg.WEIGHT_DECAY, true_wd=True, bn_wd=True
33 | )
34 | else:
35 | raise NotImplementedError
36 |
37 | return optimizer
38 |
39 |
40 | def build_scheduler(optimizer, total_iters_each_epoch, total_epochs, last_epoch, optim_cfg):
41 | decay_steps = [x * total_iters_each_epoch for x in optim_cfg.DECAY_STEP_LIST]
42 | def lr_lbmd(cur_epoch):
43 | cur_decay = 1
44 | for decay_step in decay_steps:
45 | if cur_epoch >= decay_step:
46 | cur_decay = cur_decay * optim_cfg.LR_DECAY
47 | return max(cur_decay, optim_cfg.LR_CLIP / optim_cfg.LR)
48 |
49 | lr_warmup_scheduler = None
50 | total_steps = total_iters_each_epoch * total_epochs
51 | if optim_cfg.OPTIMIZER == 'adam_onecycle':
52 | lr_scheduler = OneCycle(
53 | optimizer, total_steps, optim_cfg.LR, list(optim_cfg.MOMS), optim_cfg.DIV_FACTOR, optim_cfg.PCT_START
54 | )
55 | elif optim_cfg.OPTIMIZER == 'adam_cosineanneal':
56 | lr_scheduler = CosineAnnealing(
57 | optimizer, total_steps, total_epochs, optim_cfg.LR, list(optim_cfg.MOMS), optim_cfg.PCT_START, optim_cfg.WARMUP_ITER
58 | )
59 | else:
60 | lr_scheduler = lr_sched.LambdaLR(optimizer, lr_lbmd, last_epoch=last_epoch)
61 |
62 | if optim_cfg.LR_WARMUP:
63 | lr_warmup_scheduler = CosineWarmupLR(
64 | optimizer, T_max=optim_cfg.WARMUP_EPOCH * len(total_iters_each_epoch),
65 | eta_min=optim_cfg.LR / optim_cfg.DIV_FACTOR
66 | )
67 |
68 | return lr_scheduler, lr_warmup_scheduler
69 |
--------------------------------------------------------------------------------