├── .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 | --------------------------------------------------------------------------------