├── .gitignore ├── README.md ├── _init_paths.py ├── _submodules ├── mmdetection │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── configs │ │ ├── albu_example │ │ │ └── mask_rcnn_r50_fpn_1x.py │ │ ├── cascade_mask_rcnn_r101_fpn_1x.py │ │ ├── cascade_mask_rcnn_r50_caffe_c4_1x.py │ │ ├── cascade_mask_rcnn_r50_fpn_1x.py │ │ ├── cascade_mask_rcnn_x101_32x4d_fpn_1x.py │ │ ├── cascade_mask_rcnn_x101_64x4d_fpn_1x.py │ │ ├── cascade_rcnn_r101_fpn_1x.py │ │ ├── cascade_rcnn_r50_caffe_c4_1x.py │ │ ├── cascade_rcnn_r50_fpn_1x.py │ │ ├── cascade_rcnn_x101_32x4d_fpn_1x.py │ │ ├── cascade_rcnn_x101_64x4d_fpn_1x.py │ │ ├── cityscapes │ │ │ ├── README.md │ │ │ ├── faster_rcnn_r50_fpn_1x_cityscapes.py │ │ │ └── mask_rcnn_r50_fpn_1x_cityscapes.py │ │ ├── dcn │ │ │ ├── README.md │ │ │ ├── cascade_mask_rcnn_dconv_c3-c5_r50_fpn_1x.py │ │ │ ├── cascade_rcnn_dconv_c3-c5_r50_fpn_1x.py │ │ │ ├── faster_rcnn_dconv_c3-c5_r50_fpn_1x.py │ │ │ ├── faster_rcnn_dconv_c3-c5_x101_32x4d_fpn_1x.py │ │ │ ├── faster_rcnn_dpool_r50_fpn_1x.py │ │ │ ├── faster_rcnn_mdconv_c3-c5_group4_r50_fpn_1x.py │ │ │ ├── faster_rcnn_mdconv_c3-c5_r50_fpn_1x.py │ │ │ ├── faster_rcnn_mdpool_r50_fpn_1x.py │ │ │ └── mask_rcnn_dconv_c3-c5_r50_fpn_1x.py │ │ ├── double_heads │ │ │ └── dh_faster_rcnn_r50_fpn_1x.py │ │ ├── empirical_attention │ │ │ ├── README.md │ │ │ ├── faster_rcnn_r50_fpn_attention_0010_1x.py │ │ │ ├── faster_rcnn_r50_fpn_attention_0010_dcn_1x.py │ │ │ ├── faster_rcnn_r50_fpn_attention_1111_1x.py │ │ │ └── faster_rcnn_r50_fpn_attention_1111_dcn_1x.py │ │ ├── fast_mask_rcnn_r101_fpn_1x.py │ │ ├── fast_mask_rcnn_r50_caffe_c4_1x.py │ │ ├── fast_mask_rcnn_r50_fpn_1x.py │ │ ├── fast_rcnn_r101_fpn_1x.py │ │ ├── fast_rcnn_r50_caffe_c4_1x.py │ │ ├── fast_rcnn_r50_fpn_1x.py │ │ ├── faster_rcnn_ohem_r50_fpn_1x.py │ │ ├── faster_rcnn_r101_fpn_1x.py │ │ ├── faster_rcnn_r50_caffe_c4_1x.py │ │ ├── faster_rcnn_r50_fpn_1x.py │ │ ├── faster_rcnn_x101_32x4d_fpn_1x.py │ │ ├── faster_rcnn_x101_64x4d_fpn_1x.py │ │ ├── fcos │ │ │ ├── README.md │ │ │ ├── fcos_mstrain_640_800_r101_caffe_fpn_gn_2x_4gpu.py │ │ │ ├── fcos_mstrain_640_800_x101_64x4d_fpn_gn_2x.py │ │ │ └── fcos_r50_caffe_fpn_gn_1x_4gpu.py │ │ ├── foveabox │ │ │ ├── README.md │ │ │ ├── fovea_align_gn_ms_r101_fpn_4gpu_2x.py │ │ │ ├── fovea_align_gn_ms_r50_fpn_4gpu_2x.py │ │ │ ├── fovea_align_gn_r101_fpn_4gpu_2x.py │ │ │ ├── fovea_align_gn_r50_fpn_4gpu_2x.py │ │ │ └── fovea_r50_fpn_4gpu_1x.py │ │ ├── fp16 │ │ │ ├── faster_rcnn_r50_fpn_fp16_1x.py │ │ │ ├── mask_rcnn_r50_fpn_fp16_1x.py │ │ │ └── retinanet_r50_fpn_fp16_1x.py │ │ ├── gcnet │ │ │ ├── README.md │ │ │ ├── mask_rcnn_r16_gcb_c3-c5_r50_fpn_1x.py │ │ │ ├── mask_rcnn_r16_gcb_c3-c5_r50_fpn_syncbn_1x.py │ │ │ ├── mask_rcnn_r4_gcb_c3-c5_r50_fpn_1x.py │ │ │ ├── mask_rcnn_r4_gcb_c3-c5_r50_fpn_syncbn_1x.py │ │ │ └── mask_rcnn_r50_fpn_sbn_1x.py │ │ ├── ghm │ │ │ ├── README.md │ │ │ └── retinanet_ghm_r50_fpn_1x.py │ │ ├── gn+ws │ │ │ ├── README.md │ │ │ ├── faster_rcnn_r50_fpn_gn_ws_1x.py │ │ │ ├── mask_rcnn_r50_fpn_gn_ws_20_23_24e.py │ │ │ ├── mask_rcnn_r50_fpn_gn_ws_2x.py │ │ │ └── mask_rcnn_x101_32x4d_fpn_gn_ws_2x.py │ │ ├── gn │ │ │ ├── README.md │ │ │ ├── mask_rcnn_r101_fpn_gn_2x.py │ │ │ ├── mask_rcnn_r50_fpn_gn_2x.py │ │ │ └── mask_rcnn_r50_fpn_gn_contrib_2x.py │ │ ├── grid_rcnn │ │ │ ├── README.md │ │ │ ├── grid_rcnn_gn_head_r50_fpn_2x.py │ │ │ └── grid_rcnn_gn_head_x101_32x4d_fpn_2x.py │ │ ├── guided_anchoring │ │ │ ├── README.md │ │ │ ├── ga_fast_r50_caffe_fpn_1x.py │ │ │ ├── ga_faster_r50_caffe_fpn_1x.py │ │ │ ├── ga_faster_x101_32x4d_fpn_1x.py │ │ │ ├── ga_retinanet_r50_caffe_fpn_1x.py │ │ │ ├── ga_retinanet_x101_32x4d_fpn_1x.py │ │ │ ├── ga_rpn_r101_caffe_rpn_1x.py │ │ │ ├── ga_rpn_r50_caffe_fpn_1x.py │ │ │ └── ga_rpn_x101_32x4d_fpn_1x.py │ │ ├── hrnet │ │ │ ├── README.md │ │ │ ├── cascade_mask_rcnn_hrnetv2p_w32_20e.py │ │ │ ├── cascade_rcnn_hrnetv2p_w32_20e.py │ │ │ ├── faster_rcnn_hrnetv2p_w18_1x.py │ │ │ ├── faster_rcnn_hrnetv2p_w32_1x.py │ │ │ ├── faster_rcnn_hrnetv2p_w40_1x.py │ │ │ ├── fcos_hrnetv2p_w32_gn_1x_4gpu.py │ │ │ ├── htc_hrnetv2p_w32_20e.py │ │ │ ├── mask_rcnn_hrnetv2p_w18_1x.py │ │ │ └── mask_rcnn_hrnetv2p_w32_1x.py │ │ ├── htc │ │ │ ├── README.md │ │ │ ├── htc_dconv_c3-c5_mstrain_400_1400_x101_64x4d_fpn_20e.py │ │ │ ├── htc_r101_fpn_20e.py │ │ │ ├── htc_r50_fpn_1x.py │ │ │ ├── htc_r50_fpn_20e.py │ │ │ ├── htc_without_semantic_r50_fpn_1x.py │ │ │ ├── htc_x101_32x4d_fpn_20e_16gpu.py │ │ │ └── htc_x101_64x4d_fpn_20e_16gpu.py │ │ ├── libra_rcnn │ │ │ ├── README.md │ │ │ ├── libra_fast_rcnn_r50_fpn_1x.py │ │ │ ├── libra_faster_rcnn_r101_fpn_1x.py │ │ │ ├── libra_faster_rcnn_r50_fpn_1x.py │ │ │ ├── libra_faster_rcnn_x101_64x4d_fpn_1x.py │ │ │ └── libra_retinanet_r50_fpn_1x.py │ │ ├── mask_rcnn_r101_fpn_1x.py │ │ ├── mask_rcnn_r50_caffe_c4_1x.py │ │ ├── mask_rcnn_r50_fpn_1x.py │ │ ├── mask_rcnn_x101_32x4d_fpn_1x.py │ │ ├── mask_rcnn_x101_64x4d_fpn_1x.py │ │ ├── ms_rcnn │ │ │ ├── README.md │ │ │ ├── ms_rcnn_r101_caffe_fpn_1x.py │ │ │ ├── ms_rcnn_r50_caffe_fpn_1x.py │ │ │ └── ms_rcnn_x101_64x4d_fpn_1x.py │ │ ├── pascal_voc │ │ │ ├── README.md │ │ │ ├── faster_rcnn_r50_fpn_1x_voc0712.py │ │ │ ├── ssd300_voc.py │ │ │ └── ssd512_voc.py │ │ ├── reppoints │ │ │ ├── README.md │ │ │ ├── bbox_r50_grid_center_fpn_1x.py │ │ │ ├── bbox_r50_grid_fpn_1x.py │ │ │ ├── reppoints.png │ │ │ ├── reppoints_minmax_r50_fpn_1x.py │ │ │ ├── reppoints_moment_r101_dcn_fpn_2x.py │ │ │ ├── reppoints_moment_r101_dcn_fpn_2x_mt.py │ │ │ ├── reppoints_moment_r101_fpn_2x.py │ │ │ ├── reppoints_moment_r101_fpn_2x_mt.py │ │ │ ├── reppoints_moment_r50_fpn_1x.py │ │ │ ├── reppoints_moment_r50_fpn_2x.py │ │ │ ├── reppoints_moment_r50_fpn_2x_mt.py │ │ │ ├── reppoints_moment_x101_dcn_fpn_2x.py │ │ │ ├── reppoints_moment_x101_dcn_fpn_2x_mt.py │ │ │ └── reppoints_partial_minmax_r50_fpn_1x.py │ │ ├── retinanet_r101_fpn_1x.py │ │ ├── retinanet_r50_fpn_1x.py │ │ ├── retinanet_x101_32x4d_fpn_1x.py │ │ ├── retinanet_x101_64x4d_fpn_1x.py │ │ ├── rpn_r101_fpn_1x.py │ │ ├── rpn_r50_caffe_c4_1x.py │ │ ├── rpn_r50_fpn_1x.py │ │ ├── rpn_x101_32x4d_fpn_1x.py │ │ ├── rpn_x101_64x4d_fpn_1x.py │ │ ├── scratch │ │ │ ├── README.md │ │ │ ├── scratch_faster_rcnn_r50_fpn_gn_6x.py │ │ │ └── scratch_mask_rcnn_r50_fpn_gn_6x.py │ │ ├── ssd300_coco.py │ │ ├── ssd512_coco.py │ │ ├── ttfnet │ │ │ ├── ttfnet_d53_1x.py │ │ │ ├── ttfnet_d53_2x.py │ │ │ ├── ttfnet_r18_1x.py │ │ │ ├── ttfnet_r18_2x.py │ │ │ └── ttfnet_r34_2x.py │ │ └── wider_face │ │ │ ├── README.md │ │ │ └── ssd300_wider_face.py │ ├── demo │ │ ├── coco_test_12510.jpg │ │ ├── corruptions_sev_3.png │ │ ├── data_pipeline.png │ │ ├── demo.jpg │ │ ├── inference_demo.ipynb │ │ ├── loss_curve.png │ │ └── webcam_demo.py │ ├── docker │ │ └── Dockerfile │ ├── docs │ │ ├── DATA_PIPELINE.md │ │ ├── GETTING_STARTED.md │ │ ├── INSTALL.md │ │ ├── MODEL_ZOO.md │ │ ├── ROBUSTNESS_BENCHMARKING.md │ │ └── TECHNICAL_DETAILS.md │ ├── mmdet │ │ ├── __init__.py │ │ ├── apis │ │ │ ├── __init__.py │ │ │ ├── env.py │ │ │ ├── inference.py │ │ │ └── train.py │ │ ├── core │ │ │ ├── __init__.py │ │ │ ├── anchor │ │ │ │ ├── __init__.py │ │ │ │ ├── anchor_generator.py │ │ │ │ ├── anchor_target.py │ │ │ │ ├── guided_anchor_target.py │ │ │ │ ├── point_generator.py │ │ │ │ └── point_target.py │ │ │ ├── bbox │ │ │ │ ├── __init__.py │ │ │ │ ├── assign_sampling.py │ │ │ │ ├── assigners │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── approx_max_iou_assigner.py │ │ │ │ │ ├── assign_result.py │ │ │ │ │ ├── base_assigner.py │ │ │ │ │ ├── max_iou_assigner.py │ │ │ │ │ └── point_assigner.py │ │ │ │ ├── bbox_target.py │ │ │ │ ├── geometry.py │ │ │ │ ├── samplers │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── base_sampler.py │ │ │ │ │ ├── combined_sampler.py │ │ │ │ │ ├── instance_balanced_pos_sampler.py │ │ │ │ │ ├── iou_balanced_neg_sampler.py │ │ │ │ │ ├── ohem_sampler.py │ │ │ │ │ ├── pseudo_sampler.py │ │ │ │ │ ├── random_sampler.py │ │ │ │ │ └── sampling_result.py │ │ │ │ └── transforms.py │ │ │ ├── evaluation │ │ │ │ ├── __init__.py │ │ │ │ ├── bbox_overlaps.py │ │ │ │ ├── class_names.py │ │ │ │ ├── coco_utils.py │ │ │ │ ├── eval_hooks.py │ │ │ │ ├── mean_ap.py │ │ │ │ └── recall.py │ │ │ ├── fp16 │ │ │ │ ├── __init__.py │ │ │ │ ├── decorators.py │ │ │ │ ├── hooks.py │ │ │ │ └── utils.py │ │ │ ├── mask │ │ │ │ ├── __init__.py │ │ │ │ ├── mask_target.py │ │ │ │ └── utils.py │ │ │ ├── post_processing │ │ │ │ ├── __init__.py │ │ │ │ ├── bbox_nms.py │ │ │ │ └── merge_augs.py │ │ │ └── utils │ │ │ │ ├── __init__.py │ │ │ │ ├── dist_utils.py │ │ │ │ └── misc.py │ │ ├── datasets │ │ │ ├── __init__.py │ │ │ ├── builder.py │ │ │ ├── cityscapes.py │ │ │ ├── coco.py │ │ │ ├── custom.py │ │ │ ├── dataset_wrappers.py │ │ │ ├── extra_aug.py │ │ │ ├── loader │ │ │ │ ├── __init__.py │ │ │ │ ├── build_loader.py │ │ │ │ └── sampler.py │ │ │ ├── pipelines │ │ │ │ ├── __init__.py │ │ │ │ ├── compose.py │ │ │ │ ├── formating.py │ │ │ │ ├── loading.py │ │ │ │ ├── test_aug.py │ │ │ │ └── transforms.py │ │ │ ├── registry.py │ │ │ ├── transforms.py │ │ │ ├── voc.py │ │ │ ├── wider_face.py │ │ │ └── xml_style.py │ │ ├── models │ │ │ ├── __init__.py │ │ │ ├── anchor_heads │ │ │ │ ├── __init__.py │ │ │ │ ├── anchor_head.py │ │ │ │ ├── fcos_head.py │ │ │ │ ├── fovea_head.py │ │ │ │ ├── ga_retina_head.py │ │ │ │ ├── ga_rpn_head.py │ │ │ │ ├── guided_anchor_head.py │ │ │ │ ├── reppoints_head.py │ │ │ │ ├── retina_head.py │ │ │ │ ├── rpn_head.py │ │ │ │ ├── ssd_head.py │ │ │ │ └── ttf_head.py │ │ │ ├── backbones │ │ │ │ ├── __init__.py │ │ │ │ ├── darknet.py │ │ │ │ ├── hrnet.py │ │ │ │ ├── resnet.py │ │ │ │ ├── resnext.py │ │ │ │ └── ssd_vgg.py │ │ │ ├── bbox_heads │ │ │ │ ├── __init__.py │ │ │ │ ├── bbox_head.py │ │ │ │ ├── convfc_bbox_head.py │ │ │ │ └── double_bbox_head.py │ │ │ ├── builder.py │ │ │ ├── detectors │ │ │ │ ├── __init__.py │ │ │ │ ├── base.py │ │ │ │ ├── cascade_rcnn.py │ │ │ │ ├── double_head_rcnn.py │ │ │ │ ├── fast_rcnn.py │ │ │ │ ├── faster_rcnn.py │ │ │ │ ├── fcos.py │ │ │ │ ├── fovea.py │ │ │ │ ├── grid_rcnn.py │ │ │ │ ├── htc.py │ │ │ │ ├── mask_rcnn.py │ │ │ │ ├── mask_scoring_rcnn.py │ │ │ │ ├── reppoints_detector.py │ │ │ │ ├── retinanet.py │ │ │ │ ├── rpn.py │ │ │ │ ├── single_stage.py │ │ │ │ ├── test_mixins.py │ │ │ │ ├── ttfnet.py │ │ │ │ └── two_stage.py │ │ │ ├── losses │ │ │ │ ├── __init__.py │ │ │ │ ├── accuracy.py │ │ │ │ ├── balanced_l1_loss.py │ │ │ │ ├── cross_entropy_loss.py │ │ │ │ ├── focal_loss.py │ │ │ │ ├── ghm_loss.py │ │ │ │ ├── iou_loss.py │ │ │ │ ├── mse_loss.py │ │ │ │ ├── smooth_l1_loss.py │ │ │ │ └── utils.py │ │ │ ├── mask_heads │ │ │ │ ├── __init__.py │ │ │ │ ├── fcn_mask_head.py │ │ │ │ ├── fused_semantic_head.py │ │ │ │ ├── grid_head.py │ │ │ │ ├── htc_mask_head.py │ │ │ │ └── maskiou_head.py │ │ │ ├── necks │ │ │ │ ├── __init__.py │ │ │ │ ├── bfp.py │ │ │ │ ├── fpn.py │ │ │ │ └── hrfpn.py │ │ │ ├── plugins │ │ │ │ ├── __init__.py │ │ │ │ ├── generalized_attention.py │ │ │ │ └── non_local.py │ │ │ ├── registry.py │ │ │ ├── roi_extractors │ │ │ │ ├── __init__.py │ │ │ │ └── single_level.py │ │ │ ├── shared_heads │ │ │ │ ├── __init__.py │ │ │ │ └── res_layer.py │ │ │ └── utils │ │ │ │ ├── __init__.py │ │ │ │ ├── conv_module.py │ │ │ │ ├── conv_ws.py │ │ │ │ ├── norm.py │ │ │ │ ├── scale.py │ │ │ │ └── weight_init.py │ │ ├── ops │ │ │ ├── __init__.py │ │ │ ├── context_block.py │ │ │ ├── dcn │ │ │ │ ├── __init__.py │ │ │ │ ├── deform_conv.py │ │ │ │ ├── deform_pool.py │ │ │ │ └── src │ │ │ │ │ ├── deform_conv_cuda.cpp │ │ │ │ │ ├── deform_conv_cuda_kernel.cu │ │ │ │ │ ├── deform_pool_cuda.cpp │ │ │ │ │ └── deform_pool_cuda_kernel.cu │ │ │ ├── masked_conv │ │ │ │ ├── __init__.py │ │ │ │ ├── masked_conv.py │ │ │ │ └── src │ │ │ │ │ ├── masked_conv2d_cuda.cpp │ │ │ │ │ └── masked_conv2d_kernel.cu │ │ │ ├── nms │ │ │ │ ├── __init__.py │ │ │ │ ├── nms_wrapper.py │ │ │ │ └── src │ │ │ │ │ ├── nms_cpu.cpp │ │ │ │ │ ├── nms_cuda.cpp │ │ │ │ │ ├── nms_kernel.cu │ │ │ │ │ └── soft_nms_cpu.pyx │ │ │ ├── roi_align │ │ │ │ ├── __init__.py │ │ │ │ ├── gradcheck.py │ │ │ │ ├── roi_align.py │ │ │ │ └── src │ │ │ │ │ ├── roi_align_cuda.cpp │ │ │ │ │ └── roi_align_kernel.cu │ │ │ ├── roi_pool │ │ │ │ ├── __init__.py │ │ │ │ ├── gradcheck.py │ │ │ │ ├── roi_pool.py │ │ │ │ └── src │ │ │ │ │ ├── roi_pool_cuda.cpp │ │ │ │ │ └── roi_pool_kernel.cu │ │ │ └── sigmoid_focal_loss │ │ │ │ ├── __init__.py │ │ │ │ ├── sigmoid_focal_loss.py │ │ │ │ └── src │ │ │ │ ├── sigmoid_focal_loss.cpp │ │ │ │ └── sigmoid_focal_loss_cuda.cu │ │ └── utils │ │ │ ├── __init__.py │ │ │ ├── flops_counter.py │ │ │ └── registry.py │ ├── pytest.ini │ ├── requirements.txt │ ├── setup.py │ ├── tests │ │ ├── requirements.txt │ │ └── test_utils.py │ └── tools │ │ ├── analyze_logs.py │ │ ├── coco_error_analysis.py │ │ ├── coco_eval.py │ │ ├── convert_datasets │ │ └── pascal_voc.py │ │ ├── demo.py │ │ ├── detectron2pytorch.py │ │ ├── dist_test.sh │ │ ├── dist_test_ttfnet.sh │ │ ├── dist_train.sh │ │ ├── dist_train_ttfnet.sh │ │ ├── get_flops.py │ │ ├── publish_model.py │ │ ├── robustness_eval.py │ │ ├── slurm_test.sh │ │ ├── slurm_train.sh │ │ ├── test.py │ │ ├── test_robustness.py │ │ ├── train.py │ │ ├── upgrade_model_version.py │ │ └── voc_eval.py └── neuron │ ├── .gitignore │ ├── MANIFEST.in │ ├── configs │ ├── reid_baseline.yaml │ └── siamfc.yaml │ ├── neuron │ ├── __init__.py │ ├── config │ │ ├── __init__.py │ │ ├── _init_registry.py │ │ ├── config.py │ │ └── registry.py │ ├── data │ │ ├── __init__.py │ │ ├── collate.py │ │ ├── datasets │ │ │ ├── __init__.py │ │ │ ├── coco.py │ │ │ ├── dataset.py │ │ │ ├── dtb70.py │ │ │ ├── got10k.py │ │ │ ├── imagenet.py │ │ │ ├── lasot.json │ │ │ ├── lasot.py │ │ │ ├── mot.py │ │ │ ├── nfs.py │ │ │ ├── otb.py │ │ │ ├── oxuva.py │ │ │ ├── pot.py │ │ │ ├── structure.py │ │ │ ├── tcolor128.py │ │ │ ├── tlp.py │ │ │ ├── trackingnet.py │ │ │ ├── uav123.json │ │ │ ├── uav123.py │ │ │ ├── visdrone.py │ │ │ └── vot.py │ │ ├── evaluators │ │ │ ├── __init__.py │ │ │ ├── evaluator.py │ │ │ ├── got10k_eval.py │ │ │ ├── otb_eval.py │ │ │ ├── oxuva_eval.py │ │ │ └── vot_eval.py │ │ ├── parallel.py │ │ ├── samplers │ │ │ ├── __init__.py │ │ │ └── samplers.py │ │ └── transforms │ │ │ ├── __init__.py │ │ │ ├── img_transforms │ │ │ ├── __init__.py │ │ │ └── reid_transforms.py │ │ │ └── pair_transforms │ │ │ ├── __init__.py │ │ │ ├── mmdet_transforms.py │ │ │ └── siamfc_transforms.py │ ├── engine │ │ ├── __init__.py │ │ ├── inference.py │ │ ├── logger.py │ │ ├── meter.py │ │ └── trainer.py │ ├── models │ │ ├── __init__.py │ │ ├── backbones │ │ │ ├── __init__.py │ │ │ ├── alexnet.py │ │ │ ├── backbone.py │ │ │ └── resnet.py │ │ ├── heads │ │ │ ├── __init__.py │ │ │ └── xcorr.py │ │ ├── losses │ │ │ ├── __init__.py │ │ │ ├── losses.py │ │ │ └── multi_task_losses.py │ │ ├── metrics │ │ │ ├── __init__.py │ │ │ ├── metrics.py │ │ │ └── multi_task_metrics.py │ │ ├── model.py │ │ ├── reid │ │ │ ├── __init__.py │ │ │ └── reid_baseline.py │ │ └── trackers │ │ │ ├── __init__.py │ │ │ ├── _dummy.py │ │ │ ├── siamfc.py │ │ │ └── tracker.py │ ├── ops │ │ ├── __init__.py │ │ ├── image.py │ │ ├── io.py │ │ ├── losses.py │ │ ├── metrics.py │ │ ├── ops.py │ │ └── transforms.py │ └── optim │ │ ├── __init__.py │ │ ├── lr_scheduler.py │ │ └── param_grouper.py │ ├── setup.py │ ├── tests │ ├── test_config.py │ ├── test_datasets │ │ └── test_seq_datasets.py │ ├── test_evaluators │ │ └── test_seq_evaluators.py │ ├── test_models │ │ ├── test_backbones.py │ │ ├── test_heads.py │ │ └── test_losses.py │ ├── test_ops │ │ └── test_metrics.py │ └── test_transforms │ │ ├── test_instance_transforms.py │ │ └── test_pair_transforms.py │ └── tools │ ├── test.py │ └── train.py ├── configs └── qg_rcnn_r50_fpn.py ├── datasets ├── __init__.py └── wrappers.py ├── environment.yml ├── imgs └── figure2.jpg ├── modules ├── __init__.py ├── modulators.py ├── qg_rcnn.py └── qg_rpn.py ├── tests ├── test_datasets.py ├── test_modules.py └── test_trackers.py ├── tools ├── dist_train_qg_rcnn.sh ├── test_global_track.py └── train_qg_rcnn.py └── trackers ├── __init__.py └── global_track.py /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | *.py[cod] 3 | log 4 | log_* 5 | *.log 6 | /data 7 | __pycache__/ 8 | cache/ 9 | results*/ 10 | reports*/ 11 | screenshots/ 12 | screenshots*/ 13 | experiments/ 14 | *.egg-info/ 15 | work_dirs/ 16 | checkpoints/ 17 | !.gitignore 18 | -------------------------------------------------------------------------------- /_init_paths.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.insert(0, '_submodules/neuron') 3 | sys.path.insert(0, '_submodules/mmdetection') 4 | 5 | # register modules 6 | from modules import * 7 | from datasets import * 8 | -------------------------------------------------------------------------------- /_submodules/mmdetection/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | # cython generated cpp 107 | mmdet/ops/nms/src/soft_nms_cpu.cpp 108 | mmdet/version.py 109 | data 110 | .vscode 111 | .idea 112 | 113 | # custom 114 | *.pkl 115 | *.pkl.json 116 | *.log.json 117 | work_dirs/ 118 | 119 | # Pytorch 120 | *.pth 121 | -------------------------------------------------------------------------------- /_submodules/mmdetection/configs/cityscapes/README.md: -------------------------------------------------------------------------------- 1 | ## Common settings 2 | 3 | - All baselines were trained using 8 GPU with a batch size of 8 (1 images per GPU) using the [linear scaling rule](https://arxiv.org/abs/1706.02677) to scale the learning rate. 4 | - All models were trained on `cityscapes_train`, and tested on `cityscapes_val`. 5 | - 1x training schedule indicates 64 epochs which corresponds to slightly less than the 24k iterations reported in the original schedule from the [Mask R-CNN paper](https://arxiv.org/abs/1703.06870) 6 | - All pytorch-style pretrained backbones on ImageNet are from PyTorch model zoo. 7 | 8 | 9 | ## Baselines 10 | 11 | Download links and more models with different backbones and training schemes will be added to the model zoo. 12 | 13 | 14 | ### Faster R-CNN 15 | 16 | | Backbone | Style | Lr schd | Scale | Mem (GB) | Train time (s/iter) | Inf time (fps) | box AP | Download | 17 | | :-------------: | :-----: | :-----: | :---: | :------: | :-----------------: | :------------: | :----: | :------: | 18 | | R-50-FPN | pytorch | 1x | 800-1024 | 4.9 | 0.345 | 8.8 | 36.0 | [model](https://open-mmlab.s3.ap-northeast-2.amazonaws.com/mmdetection/models/cityscapes/faster_rcnn_r50_fpn_1x_city_20190727-7b9c0534.pth) | 19 | 20 | ### Mask R-CNN 21 | 22 | | Backbone | Style | Lr schd | Scale | Mem (GB) | Train time (s/iter) | Inf time (fps) | box AP | mask AP | Download | 23 | | :-------------: | :-----: | :-----: | :------: | :------: | :-----------------: | :------------: | :----: | :-----: | :------: | 24 | | R-50-FPN | pytorch | 1x | 800-1024 | 4.9 | 0.609 | 2.5 | 37.4 | 32.5 | [model](https://open-mmlab.s3.ap-northeast-2.amazonaws.com/mmdetection/models/cityscapes/mask_rcnn_r50_fpn_1x_city_20190727-9b3c56a5.pth) | 25 | 26 | **Notes:** 27 | - In the original paper, the mask AP of Mask R-CNN R-50-FPN is 31.5. 28 | 29 | -------------------------------------------------------------------------------- /_submodules/mmdetection/configs/empirical_attention/README.md: -------------------------------------------------------------------------------- 1 | # An Empirical Study of Spatial Attention Mechanisms in Deep Networks 2 | 3 | ## Introduction 4 | 5 | ``` 6 | @article{zhu2019empirical, 7 | title={An Empirical Study of Spatial Attention Mechanisms in Deep Networks}, 8 | author={Zhu, Xizhou and Cheng, Dazhi and Zhang, Zheng and Lin, Stephen and Dai, Jifeng}, 9 | journal={arXiv preprint arXiv:1904.05873}, 10 | year={2019} 11 | } 12 | ``` 13 | 14 | 15 | ## Results and Models 16 | 17 | | Backbone | Attention Component | DCN | Lr schd | box AP | Download | 18 | |:---------:|:-------------------:|:----:|:-------:|:------:|:--------:| 19 | | R-50 | 1111 | N | 1x | 38.6 | - | 20 | | R-50 | 0010 | N | 1x | 38.2 | - | 21 | | R-50 | 1111 | Y | 1x | 41.0 | - | 22 | | R-50 | 0010 | Y | 1x | 40.8 | - | 23 | 24 | -------------------------------------------------------------------------------- /_submodules/mmdetection/configs/fcos/README.md: -------------------------------------------------------------------------------- 1 | # FCOS: Fully Convolutional One-Stage Object Detection 2 | 3 | ## Introduction 4 | 5 | ``` 6 | @article{tian2019fcos, 7 | title={FCOS: Fully Convolutional One-Stage Object Detection}, 8 | author={Tian, Zhi and Shen, Chunhua and Chen, Hao and He, Tong}, 9 | journal={arXiv preprint arXiv:1904.01355}, 10 | year={2019} 11 | } 12 | ``` 13 | 14 | ## Results and Models 15 | 16 | | Backbone | Style | GN | MS train | Lr schd | Mem (GB) | Train time (s/iter) | Inf time (fps) | box AP | Download | 17 | |:---------:|:-------:|:-------:|:-------:|:-------:|:--------:|:-------------------:|:--------------:|:------:|:--------:| 18 | | R-50 | caffe | N | N | 1x | 5.5 | 0.373 | 13.7 | 35.7 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/fcos/fcos_r50_caffe_fpn_1x_4gpu_20190516-a7cac5ff.pth) | 19 | | R-50 | caffe | Y | N | 1x | 6.9 | 0.396 | 13.6 | 36.7 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/fcos/fcos_r50_caffe_fpn_gn_1x_4gpu_20190516-9f253a93.pth) | 20 | | R-50 | caffe | Y | N | 2x | - | - | - | 36.9 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/fcos/fcos_r50_caffe_fpn_gn_2x_4gpu_20190516_-93484354.pth) | 21 | | R-101 | caffe | Y | N | 1x | 10.4 | 0.558 | 11.6 | 39.1 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/fcos/fcos_r101_caffe_fpn_gn_1x_4gpu_20190516-e4889733.pth) | 22 | | R-101 | caffe | Y | N | 2x | - | - | - | 39.1 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/fcos/fcos_r101_caffe_fpn_gn_2x_4gpu_20190516-c03af97b.pth) | 23 | 24 | 25 | | Backbone | Style | GN | MS train | Lr schd | Mem (GB) | Train time (s/iter) | Inf time (fps) | box AP | Download | 26 | |:---------:|:-------:|:-------:|:-------:|:-------:|:--------:|:-------------------:|:--------------:|:------:|:--------:| 27 | | R-50 | caffe | Y | Y | 2x | - | - | - | 38.7 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/fcos/fcos_mstrain_640_800_r50_caffe_fpn_gn_2x_4gpu_20190516-f7329d80.pth) | 28 | | R-101 | caffe | Y | Y | 2x | - | - | - | 40.8 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/fcos/fcos_mstrain_640_800_r101_caffe_fpn_gn_2x_4gpu_20190516-42e6f62d.pth) | 29 | | X-101 | caffe | Y | Y | 2x | 9.7 | 0.892 | 7.0 | 42.8 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/fcos/fcos_mstrain_640_800_x101_64x4d_fpn_gn_2x_20190516-a36c0872.pth) | 30 | 31 | **Notes:** 32 | - To be consistent with the author's implementation, we use 4 GPUs with 4 images/GPU for R-50 and R-101 models, and 8 GPUs with 2 image/GPU for X-101 models. 33 | - The X-101 backbone is X-101-64x4d. 34 | -------------------------------------------------------------------------------- /_submodules/mmdetection/configs/ghm/README.md: -------------------------------------------------------------------------------- 1 | # Gradient Harmonized Single-stage Detector 2 | 3 | ## Introduction 4 | 5 | ``` 6 | @inproceedings{li2019gradient, 7 | title={Gradient Harmonized Single-stage Detector}, 8 | author={Li, Buyu and Liu, Yu and Wang, Xiaogang}, 9 | booktitle={AAAI Conference on Artificial Intelligence}, 10 | year={2019} 11 | } 12 | ``` 13 | 14 | ## Results and Models 15 | 16 | | Backbone | Style | Lr schd | Mem (GB) | Train time (s/iter) | Inf time (fps) | box AP | Download | 17 | | :-------------: | :-----: | :-----: | :------: | :-----------------: | :------------: | :----: | :------: | 18 | | R-50-FPN | pytorch | 1x | 3.9 | 0.500 | 9.4 | 36.9 | [model](https://open-mmlab.s3.ap-northeast-2.amazonaws.com/mmdetection/models/ghm/retinanet_ghm_r50_fpn_1x_20190608-b9aa5862.pth) | 19 | | R-101-FPN | pytorch | 1x | 5.8 | 0.625 | 8.5 | 39.0 | [model](https://open-mmlab.s3.ap-northeast-2.amazonaws.com/mmdetection/models/ghm/retinanet_ghm_r101_fpn_1x_20190608-b885b74a.pth) | 20 | | X-101-32x4d-FPN | pytorch | 1x | 7.0 | 0.818 | 7.6 | 40.5 | [model](https://open-mmlab.s3.ap-northeast-2.amazonaws.com/mmdetection/models/ghm/retinanet_ghm_x101_32x4d_fpn_1x_20190608-ed295d22.pth) | 21 | | X-101-64x4d-FPN | pytorch | 1x | 9.9 | 1.191 | 6.1 | 41.6 | [model](https://open-mmlab.s3.ap-northeast-2.amazonaws.com/mmdetection/models/ghm/retinanet_ghm_x101_64x4d_fpn_1x_20190608-7f2037ce.pth) | -------------------------------------------------------------------------------- /_submodules/mmdetection/configs/gn/README.md: -------------------------------------------------------------------------------- 1 | # Group Normalization 2 | 3 | ## Introduction 4 | 5 | ``` 6 | @inproceedings{wu2018group, 7 | title={Group Normalization}, 8 | author={Wu, Yuxin and He, Kaiming}, 9 | booktitle={Proceedings of the European Conference on Computer Vision (ECCV)}, 10 | year={2018} 11 | } 12 | ``` 13 | 14 | ## Results and Models 15 | 16 | | Backbone | model | Lr schd | Mem (GB) | Train time (s/iter) | Inf time (fps) | box AP | mask AP | Download | 17 | |:-------------:|:----------:|:-------:|:--------:|:-------------------:|:--------------:|:------:|:-------:|:--------:| 18 | | R-50-FPN (d) | Mask R-CNN | 2x | 7.2 | 0.806 | 5.4 | 39.8 | 36.1 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/gn/mask_rcnn_r50_fpn_gn_2x_20180113-86832cf2.pth) | 19 | | R-50-FPN (d) | Mask R-CNN | 3x | 7.2 | 0.806 | 5.4 | 40.1 | 36.4 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/gn/mask_rcnn_r50_fpn_gn_3x_20180113-8e82f48d.pth) | 20 | | R-101-FPN (d) | Mask R-CNN | 2x | 9.9 | 0.970 | 4.8 | 41.5 | 37.0 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/gn/mask_rcnn_r101_fpn_gn_2x_20180113-9598649c.pth) | 21 | | R-101-FPN (d) | Mask R-CNN | 3x | 9.9 | 0.970 | 4.8 | 41.6 | 37.3 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/gn/mask_rcnn_r101_fpn_gn_3x_20180113-a14ffb96.pth) | 22 | | R-50-FPN (c) | Mask R-CNN | 2x | 7.2 | 0.806 | 5.4 | 39.7 | 35.9 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/gn/mask_rcnn_r50_fpn_gn_contrib_2x_20180113-ec93305c.pth) | 23 | | R-50-FPN (c) | Mask R-CNN | 3x | 7.2 | 0.806 | 5.4 | 40.0 | 36.2 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/gn/mask_rcnn_r50_fpn_gn_contrib_3x_20180113-9d230cab.pth) | 24 | 25 | **Notes:** 26 | - (d) means pretrained model converted from Detectron, and (c) means the contributed model pretrained by [@thangvubk](https://github.com/thangvubk). 27 | - The `3x` schedule is epoch [28, 34, 36]. 28 | - **Memory, Train/Inf time is outdated.** -------------------------------------------------------------------------------- /_submodules/mmdetection/configs/grid_rcnn/README.md: -------------------------------------------------------------------------------- 1 | # Grid R-CNN 2 | 3 | ## Introduction 4 | 5 | ``` 6 | @inproceedings{lu2019grid, 7 | title={Grid r-cnn}, 8 | author={Lu, Xin and Li, Buyu and Yue, Yuxin and Li, Quanquan and Yan, Junjie}, 9 | booktitle={Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition}, 10 | year={2019} 11 | } 12 | 13 | @article{lu2019grid, 14 | title={Grid R-CNN Plus: Faster and Better}, 15 | author={Lu, Xin and Li, Buyu and Yue, Yuxin and Li, Quanquan and Yan, Junjie}, 16 | journal={arXiv preprint arXiv:1906.05688}, 17 | year={2019} 18 | } 19 | ``` 20 | 21 | ## Results and Models 22 | 23 | | Backbone | Lr schd | Mem (GB) | Train time (s/iter) | Inf time (fps) | box AP | Download | 24 | |:-----------:|:-------:|:--------:|:-------------------:|:--------------:|:------:|:--------:| 25 | | R-50 | 2x | 4.8 | 1.172 | 10.9 | 40.3 | [model](https://open-mmlab.s3.ap-northeast-2.amazonaws.com/mmdetection/models/grid_rcnn/grid_rcnn_gn_head_r50_fpn_2x_20190619-5b29cf9d.pth) | 26 | | R-101 | 2x | 6.7 | 1.214 | 10.0 | 41.7 | [model](https://open-mmlab.s3.ap-northeast-2.amazonaws.com/mmdetection/models/grid_rcnn/grid_rcnn_gn_head_r101_fpn_2x_20190619-a4b61645.pth) | 27 | | X-101-32x4d | 2x | 8.0 | 1.335 | 8.5 | 43.0 | [model](https://open-mmlab.s3.ap-northeast-2.amazonaws.com/mmdetection/models/grid_rcnn/grid_rcnn_gn_head_x101_32x4d_fpn_2x_20190619-0bbfd87a.pth) | 28 | | X-101-64x4d | 2x | 10.9 | 1.753 | 6.4 | 43.1 | [model](https://open-mmlab.s3.ap-northeast-2.amazonaws.com/mmdetection/models/grid_rcnn/grid_rcnn_gn_head_x101_64x4d_fpn_2x_20190619-8f4e20bb.pth) | 29 | 30 | **Notes:** 31 | - All models are trained with 8 GPUs instead of 32 GPUs in the original paper. 32 | - The warming up lasts for 1 epoch and `2x` here indicates 25 epochs. 33 | -------------------------------------------------------------------------------- /_submodules/mmdetection/configs/libra_rcnn/README.md: -------------------------------------------------------------------------------- 1 | # Libra R-CNN: Towards Balanced Learning for Object Detection 2 | 3 | ## Introduction 4 | 5 | We provide config files to reproduce the results in the CVPR 2019 paper [Libra R-CNN](https://arxiv.org/pdf/1904.02701.pdf). 6 | 7 | ``` 8 | @inproceedings{pang2019libra, 9 | title={Libra R-CNN: Towards Balanced Learning for Object Detection}, 10 | author={Pang, Jiangmiao and Chen, Kai and Shi, Jianping and Feng, Huajun and Ouyang, Wanli and Dahua Lin}, 11 | booktitle={IEEE Conference on Computer Vision and Pattern Recognition}, 12 | year={2019} 13 | } 14 | ``` 15 | 16 | ## Results and models 17 | 18 | The results on COCO 2017val are shown in the below table. (results on test-dev are usually slightly higher than val) 19 | 20 | | Architecture | Backbone | Style | Lr schd | Mem (GB) | Train time (s/iter) | Inf time (fps) | box AP | Download | 21 | |:---------:|:-------:|:-------:|:--------:|:-------------------:|:--------------:|:------:|:-------:|:--------:| 22 | | Faster R-CNN | R-50-FPN | pytorch | 1x | 4.2 | 0.375 | 12.0 | 38.5 | [model](https://open-mmlab.s3.ap-northeast-2.amazonaws.com/mmdetection/models/libra_rcnn/libra_faster_rcnn_r50_fpn_1x_20190610-bf0ea559.pth) | 23 | | Fast R-CNN | R-50-FPN | pytorch | 1x | 3.7 | 0.272 | 16.3 | 38.5 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/libra_rcnn/libra_fast_rcnn_r50_fpn_1x_20190525-a43f88b5.pth) | 24 | | Faster R-CNN | R-101-FPN | pytorch | 1x | 6.0 | 0.495 | 10.4 | 40.3 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/libra_rcnn/libra_faster_rcnn_r101_fpn_1x_20190525-94e94051.pth) | 25 | | Faster R-CNN | X-101-64x4d-FPN | pytorch | 1x | 10.1 | 1.050 | 6.8 | 42.7 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/libra_rcnn/libra_faster_rcnn_x101_64x4d_fpn_1x_20190525-359c134a.pth) | 26 | | RetinaNet | R-50-FPN | pytorch | 1x | 3.7 | 0.328 | 11.8 | 37.7 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/libra_rcnn/libra_retinanet_r50_fpn_1x_20190525-ead2a6bb.pth) | 27 | -------------------------------------------------------------------------------- /_submodules/mmdetection/configs/ms_rcnn/README.md: -------------------------------------------------------------------------------- 1 | # Mask Scoring R-CNN 2 | 3 | ## Introduction 4 | 5 | ``` 6 | @inproceedings{huang2019msrcnn, 7 | title={Mask Scoring R-CNN}, 8 | author={Zhaojin Huang and Lichao Huang and Yongchao Gong and Chang Huang and Xinggang Wang}, 9 | booktitle={IEEE Conference on Computer Vision and Pattern Recognition}, 10 | year={2019}, 11 | } 12 | ``` 13 | 14 | ## Results and Models 15 | 16 | | Backbone | style | Lr schd | Mem (GB) | Train time (s/iter) | Inf time (fps) | box AP | mask AP | Download | 17 | |:-------------:|:----------:|:-------:|:--------:|:-------------------:|:--------------:|:------:|:-------:|:--------:| 18 | | R-50-FPN | caffe | 1x | 4.3 | 0.537 | 10.1 | 37.4 | 35.5 | [model](https://open-mmlab.s3.ap-northeast-2.amazonaws.com/mmdetection/models/ms-rcnn/ms_rcnn_r50_caffe_fpn_1x_20190624-619934b5.pth) | 19 | | R-50-FPN | caffe | 2x | - | - | - | 38.2 | 35.9 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/ms-rcnn/ms_rcnn_r50_caffe_fpn_2x_20190525-a07be31e.pth) | 20 | | R-101-FPN | caffe | 1x | 6.2 | 0.682 | 9.1 | 39.8 | 37.2 | [model](https://open-mmlab.s3.ap-northeast-2.amazonaws.com/mmdetection/models/ms-rcnn/ms_rcnn_r101_caffe_fpn_1x_20190624-677a5548.pth) | 21 | | R-101-FPN | caffe | 2x | - | - | - | 40.7 | 37.8 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/ms-rcnn/ms_rcnn_r101_caffe_fpn_2x_20190525-4aee1528.pth) | 22 | | R-X101-32x4d | pytorch | 2x | 7.6 | 0.844 | 8.0 | 41.7 | 38.5 | [model](https://open-mmlab.s3.ap-northeast-2.amazonaws.com/mmdetection/models/ms-rcnn/ms_rcnn_x101_32x4d_fpn_2x_20190628-ab454d07.pth) | 23 | | R-X101-64x4d | pytorch | 1x | 10.5 | 1.214 | 6.4 | 42.0 | 39.1 | [model](https://open-mmlab.s3.ap-northeast-2.amazonaws.com/mmdetection/models/ms-rcnn/ms_rcnn_x101_64x4d_fpn_1x_20190628-dec32bda.pth) | 24 | | R-X101-64x4d | pytorch | 2x | - | - | - | 42.2 | 38.9 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/ms-rcnn/ms_rcnn_x101_64x4d_fpn_2x_20190525-c044c25a.pth) | 25 | -------------------------------------------------------------------------------- /_submodules/mmdetection/configs/pascal_voc/README.md: -------------------------------------------------------------------------------- 1 | ### SSD 2 | 3 | | Backbone | Size | Style | Lr schd | Mem (GB) | Train time (s/iter) | Inf time (fps) | box AP | Download | 4 | | :------: | :---: | :---: | :-----: | :------: | :-----------------: | :------------: | :----: | :------------------------------------------------------------------------------------------------------------------------------: | 5 | | VGG16 | 300 | caffe | 240e | 2.5 | 0.159 | 35.7 / 53.6 | 77.5 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/ssd300_voc_vgg16_caffe_240e_20190501-7160d09a.pth) | 6 | | VGG16 | 512 | caffe | 240e | 4.3 | 0.214 | 27.5 / 35.9 | 80.0 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/ssd512_voc_vgg16_caffe_240e_20190501-ff194be1.pth) | -------------------------------------------------------------------------------- /_submodules/mmdetection/configs/reppoints/reppoints.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanglianghua/GlobalTrack/0c9bd9649ce6006323787e7d6e6a1b88c19eaf80/_submodules/mmdetection/configs/reppoints/reppoints.png -------------------------------------------------------------------------------- /_submodules/mmdetection/configs/scratch/README.md: -------------------------------------------------------------------------------- 1 | # Rethinking ImageNet Pre-training 2 | 3 | ## Introduction 4 | 5 | ``` 6 | @article{he2018rethinking, 7 | title={Rethinking imagenet pre-training}, 8 | author={He, Kaiming and Girshick, Ross and Doll{\'a}r, Piotr}, 9 | journal={arXiv preprint arXiv:1811.08883}, 10 | year={2018} 11 | } 12 | ``` 13 | 14 | ## Results and Models 15 | 16 | | Model | Backbone | Style | Lr schd | box AP | mask AP | Download | 17 | |:------------:|:---------:|:-------:|:-------:|:------:|:-------:|:--------:| 18 | | Faster R-CNN | R-50-FPN | pytorch | 6x | 40.1 | - | [model](https://open-mmlab.s3.ap-northeast-2.amazonaws.com/mmdetection/models/scratch/scratch_faster_rcnn_r50_fpn_gn_6x_20190515-ff554978.pth) | 19 | | Mask R-CNN | R-50-FPN | pytorch | 6x | 41.0 | 37.4 | [model](https://s3.ap-northeast-2.amazonaws.com/open-mmlab/mmdetection/models/scratch/scratch_mask_rcnn_r50_fpn_gn_6x_20190515-96743f5e.pth) | 20 | 21 | Note: 22 | - The above models are trained with 16 GPUs. -------------------------------------------------------------------------------- /_submodules/mmdetection/configs/wider_face/README.md: -------------------------------------------------------------------------------- 1 | ## WIDER Face Dataset 2 | 3 | To use the WIDER Face dataset you need to download it 4 | and extract to the `data/WIDERFace` folder. Annotation in the VOC format 5 | can be found in this [repo](https://github.com/sovrasov/wider-face-pascal-voc-annotations.git). 6 | You should move the annotation files from `WIDER_train_annotations` and `WIDER_val_annotations` folders 7 | to the `Annotation` folders inside the corresponding directories `WIDER_train` and `WIDER_val`. 8 | Also annotation lists `val.txt` and `train.txt` should be copied to `data/WIDERFace` from `WIDER_train_annotations` and `WIDER_val_annotations`. 9 | The directory should be like this: 10 | 11 | ``` 12 | mmdetection 13 | ├── mmdet 14 | ├── tools 15 | ├── configs 16 | ├── data 17 | │ ├── WIDERFace 18 | │ │ ├── WIDER_train 19 | │ | │ ├──0--Parade 20 | │ | │ ├── ... 21 | │ | │ ├── Annotations 22 | │ │ ├── WIDER_val 23 | │ | │ ├──0--Parade 24 | │ | │ ├── ... 25 | │ | │ ├── Annotations 26 | │ │ ├── val.txt 27 | │ │ ├── train.txt 28 | 29 | ``` 30 | 31 | After that you can train the SSD300 on WIDER by launching training with the `ssd300_wider_face.py` config or 32 | create your own config based on the presented one. 33 | -------------------------------------------------------------------------------- /_submodules/mmdetection/demo/coco_test_12510.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanglianghua/GlobalTrack/0c9bd9649ce6006323787e7d6e6a1b88c19eaf80/_submodules/mmdetection/demo/coco_test_12510.jpg -------------------------------------------------------------------------------- /_submodules/mmdetection/demo/corruptions_sev_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanglianghua/GlobalTrack/0c9bd9649ce6006323787e7d6e6a1b88c19eaf80/_submodules/mmdetection/demo/corruptions_sev_3.png -------------------------------------------------------------------------------- /_submodules/mmdetection/demo/data_pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanglianghua/GlobalTrack/0c9bd9649ce6006323787e7d6e6a1b88c19eaf80/_submodules/mmdetection/demo/data_pipeline.png -------------------------------------------------------------------------------- /_submodules/mmdetection/demo/demo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanglianghua/GlobalTrack/0c9bd9649ce6006323787e7d6e6a1b88c19eaf80/_submodules/mmdetection/demo/demo.jpg -------------------------------------------------------------------------------- /_submodules/mmdetection/demo/loss_curve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanglianghua/GlobalTrack/0c9bd9649ce6006323787e7d6e6a1b88c19eaf80/_submodules/mmdetection/demo/loss_curve.png -------------------------------------------------------------------------------- /_submodules/mmdetection/demo/webcam_demo.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | import cv2 4 | import torch 5 | 6 | from mmdet.apis import inference_detector, init_detector, show_result 7 | 8 | 9 | def parse_args(): 10 | parser = argparse.ArgumentParser(description='MMDetection webcam demo') 11 | parser.add_argument('config', help='test config file path') 12 | parser.add_argument('checkpoint', help='checkpoint file') 13 | parser.add_argument('--device', type=int, default=0, help='CUDA device id') 14 | parser.add_argument( 15 | '--camera-id', type=int, default=0, help='camera device id') 16 | parser.add_argument( 17 | '--score-thr', type=float, default=0.5, help='bbox score threshold') 18 | args = parser.parse_args() 19 | return args 20 | 21 | 22 | def main(): 23 | args = parse_args() 24 | 25 | model = init_detector( 26 | args.config, args.checkpoint, device=torch.device('cuda', args.device)) 27 | 28 | camera = cv2.VideoCapture(args.camera_id) 29 | 30 | print('Press "Esc", "q" or "Q" to exit.') 31 | while True: 32 | ret_val, img = camera.read() 33 | result = inference_detector(model, img) 34 | 35 | ch = cv2.waitKey(1) 36 | if ch == 27 or ch == ord('q') or ch == ord('Q'): 37 | break 38 | 39 | show_result( 40 | img, result, model.CLASSES, score_thr=args.score_thr, wait_time=1) 41 | 42 | 43 | if __name__ == '__main__': 44 | main() 45 | -------------------------------------------------------------------------------- /_submodules/mmdetection/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG PYTORCH="1.1.0" 2 | ARG CUDA="10.0" 3 | ARG CUDNN="7.5" 4 | 5 | FROM pytorch/pytorch:${PYTORCH}-cuda${CUDA}-cudnn${CUDNN}-devel 6 | 7 | RUN apt-get update && apt-get install -y libglib2.0-0 libsm6 libxrender-dev libxext6 \ 8 | && apt-get clean \ 9 | && rm -rf /var/lib/apt/lists/* 10 | 11 | # Install mmdetection 12 | RUN conda install cython -y && conda clean --all 13 | RUN git clone https://github.com/open-mmlab/mmdetection.git /mmdetection 14 | WORKDIR /mmdetection 15 | RUN pip install --no-cache-dir -e . 16 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/__init__.py: -------------------------------------------------------------------------------- 1 | from .version import __version__, short_version 2 | 3 | __all__ = ['__version__', 'short_version'] 4 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/apis/__init__.py: -------------------------------------------------------------------------------- 1 | from .env import get_root_logger, init_dist, set_random_seed 2 | from .inference import (inference_detector, init_detector, show_result, 3 | show_result_pyplot) 4 | from .train import train_detector 5 | 6 | __all__ = [ 7 | 'init_dist', 'get_root_logger', 'set_random_seed', 'train_detector', 8 | 'init_detector', 'inference_detector', 'show_result', 'show_result_pyplot' 9 | ] 10 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/apis/env.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | import random 4 | import subprocess 5 | 6 | import numpy as np 7 | import torch 8 | import torch.distributed as dist 9 | import torch.multiprocessing as mp 10 | from mmcv.runner import get_dist_info 11 | 12 | 13 | def init_dist(launcher, backend='nccl', **kwargs): 14 | if mp.get_start_method(allow_none=True) is None: 15 | mp.set_start_method('spawn') 16 | if launcher == 'pytorch': 17 | _init_dist_pytorch(backend, **kwargs) 18 | elif launcher == 'mpi': 19 | _init_dist_mpi(backend, **kwargs) 20 | elif launcher == 'slurm': 21 | _init_dist_slurm(backend, **kwargs) 22 | else: 23 | raise ValueError('Invalid launcher type: {}'.format(launcher)) 24 | 25 | 26 | def _init_dist_pytorch(backend, **kwargs): 27 | # TODO: use local_rank instead of rank % num_gpus 28 | rank = int(os.environ['RANK']) 29 | num_gpus = torch.cuda.device_count() 30 | torch.cuda.set_device(rank % num_gpus) 31 | dist.init_process_group(backend=backend, **kwargs) 32 | 33 | 34 | def _init_dist_mpi(backend, **kwargs): 35 | raise NotImplementedError 36 | 37 | 38 | def _init_dist_slurm(backend, port=29500, **kwargs): 39 | proc_id = int(os.environ['SLURM_PROCID']) 40 | ntasks = int(os.environ['SLURM_NTASKS']) 41 | node_list = os.environ['SLURM_NODELIST'] 42 | num_gpus = torch.cuda.device_count() 43 | torch.cuda.set_device(proc_id % num_gpus) 44 | addr = subprocess.getoutput( 45 | 'scontrol show hostname {} | head -n1'.format(node_list)) 46 | os.environ['MASTER_PORT'] = str(port) 47 | os.environ['MASTER_ADDR'] = addr 48 | os.environ['WORLD_SIZE'] = str(ntasks) 49 | os.environ['RANK'] = str(proc_id) 50 | dist.init_process_group(backend=backend) 51 | 52 | 53 | def set_random_seed(seed): 54 | random.seed(seed) 55 | np.random.seed(seed) 56 | torch.manual_seed(seed) 57 | torch.cuda.manual_seed_all(seed) 58 | 59 | 60 | def get_root_logger(log_level=logging.INFO): 61 | logger = logging.getLogger() 62 | if not logger.hasHandlers(): 63 | logging.basicConfig( 64 | format='%(asctime)s - %(levelname)s - %(message)s', 65 | level=log_level) 66 | rank, _ = get_dist_info() 67 | if rank != 0: 68 | logger.setLevel('ERROR') 69 | return logger 70 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/__init__.py: -------------------------------------------------------------------------------- 1 | from .anchor import * # noqa: F401, F403 2 | from .bbox import * # noqa: F401, F403 3 | from .evaluation import * # noqa: F401, F403 4 | from .fp16 import * # noqa: F401, F403 5 | from .mask import * # noqa: F401, F403 6 | from .post_processing import * # noqa: F401, F403 7 | from .utils import * # noqa: F401, F403 8 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/anchor/__init__.py: -------------------------------------------------------------------------------- 1 | from .anchor_generator import AnchorGenerator 2 | from .anchor_target import anchor_inside_flags, anchor_target 3 | from .guided_anchor_target import ga_loc_target, ga_shape_target 4 | from .point_generator import PointGenerator 5 | from .point_target import point_target 6 | 7 | __all__ = [ 8 | 'AnchorGenerator', 'anchor_target', 'anchor_inside_flags', 'ga_loc_target', 9 | 'ga_shape_target', 'PointGenerator', 'point_target' 10 | ] 11 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/anchor/point_generator.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | 4 | class PointGenerator(object): 5 | 6 | def _meshgrid(self, x, y, row_major=True): 7 | xx = x.repeat(len(y)) 8 | yy = y.view(-1, 1).repeat(1, len(x)).view(-1) 9 | if row_major: 10 | return xx, yy 11 | else: 12 | return yy, xx 13 | 14 | def grid_points(self, featmap_size, stride=16, device='cuda'): 15 | feat_h, feat_w = featmap_size 16 | shift_x = torch.arange(0., feat_w, device=device) * stride 17 | shift_y = torch.arange(0., feat_h, device=device) * stride 18 | shift_xx, shift_yy = self._meshgrid(shift_x, shift_y) 19 | stride = shift_x.new_full((shift_xx.shape[0], ), stride) 20 | shifts = torch.stack([shift_xx, shift_yy, stride], dim=-1) 21 | all_points = shifts.to(device) 22 | return all_points 23 | 24 | def valid_flags(self, featmap_size, valid_size, device='cuda'): 25 | feat_h, feat_w = featmap_size 26 | valid_h, valid_w = valid_size 27 | assert valid_h <= feat_h and valid_w <= feat_w 28 | valid_x = torch.zeros(feat_w, dtype=torch.uint8, device=device) 29 | valid_y = torch.zeros(feat_h, dtype=torch.uint8, device=device) 30 | valid_x[:valid_w] = 1 31 | valid_y[:valid_h] = 1 32 | valid_xx, valid_yy = self._meshgrid(valid_x, valid_y) 33 | valid = valid_xx & valid_yy 34 | return valid 35 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/bbox/__init__.py: -------------------------------------------------------------------------------- 1 | from .assigners import AssignResult, BaseAssigner, MaxIoUAssigner 2 | from .bbox_target import bbox_target 3 | from .geometry import bbox_overlaps, bbox_areas 4 | from .samplers import (BaseSampler, CombinedSampler, 5 | InstanceBalancedPosSampler, IoUBalancedNegSampler, 6 | PseudoSampler, RandomSampler, SamplingResult) 7 | from .transforms import (bbox2delta, bbox2result, bbox2roi, bbox_flip, 8 | bbox_mapping, bbox_mapping_back, delta2bbox, 9 | distance2bbox, roi2bbox) 10 | 11 | from .assign_sampling import ( # isort:skip, avoid recursive imports 12 | assign_and_sample, build_assigner, build_sampler) 13 | 14 | __all__ = [ 15 | 'bbox_overlaps', 'bbox_areas', 'BaseAssigner', 'MaxIoUAssigner', 'AssignResult', 16 | 'BaseSampler', 'PseudoSampler', 'RandomSampler', 17 | 'InstanceBalancedPosSampler', 'IoUBalancedNegSampler', 'CombinedSampler', 18 | 'SamplingResult', 'build_assigner', 'build_sampler', 'assign_and_sample', 19 | 'bbox2delta', 'delta2bbox', 'bbox_flip', 'bbox_mapping', 20 | 'bbox_mapping_back', 'bbox2roi', 'roi2bbox', 'bbox2result', 21 | 'distance2bbox', 'bbox_target' 22 | ] 23 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/bbox/assign_sampling.py: -------------------------------------------------------------------------------- 1 | import mmcv 2 | 3 | from . import assigners, samplers 4 | 5 | 6 | def build_assigner(cfg, **kwargs): 7 | if isinstance(cfg, assigners.BaseAssigner): 8 | return cfg 9 | elif isinstance(cfg, dict): 10 | return mmcv.runner.obj_from_dict(cfg, assigners, default_args=kwargs) 11 | else: 12 | raise TypeError('Invalid type {} for building a sampler'.format( 13 | type(cfg))) 14 | 15 | 16 | def build_sampler(cfg, **kwargs): 17 | if isinstance(cfg, samplers.BaseSampler): 18 | return cfg 19 | elif isinstance(cfg, dict): 20 | return mmcv.runner.obj_from_dict(cfg, samplers, default_args=kwargs) 21 | else: 22 | raise TypeError('Invalid type {} for building a sampler'.format( 23 | type(cfg))) 24 | 25 | 26 | def assign_and_sample(bboxes, gt_bboxes, gt_bboxes_ignore, gt_labels, cfg): 27 | bbox_assigner = build_assigner(cfg.assigner) 28 | bbox_sampler = build_sampler(cfg.sampler) 29 | assign_result = bbox_assigner.assign(bboxes, gt_bboxes, gt_bboxes_ignore, 30 | gt_labels) 31 | sampling_result = bbox_sampler.sample(assign_result, bboxes, gt_bboxes, 32 | gt_labels) 33 | return assign_result, sampling_result 34 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/bbox/assigners/__init__.py: -------------------------------------------------------------------------------- 1 | from .approx_max_iou_assigner import ApproxMaxIoUAssigner 2 | from .assign_result import AssignResult 3 | from .base_assigner import BaseAssigner 4 | from .max_iou_assigner import MaxIoUAssigner 5 | from .point_assigner import PointAssigner 6 | 7 | __all__ = [ 8 | 'BaseAssigner', 'MaxIoUAssigner', 'ApproxMaxIoUAssigner', 'AssignResult', 9 | 'PointAssigner' 10 | ] 11 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/bbox/assigners/assign_result.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | 4 | class AssignResult(object): 5 | 6 | def __init__(self, num_gts, gt_inds, max_overlaps, labels=None): 7 | self.num_gts = num_gts 8 | self.gt_inds = gt_inds 9 | self.max_overlaps = max_overlaps 10 | self.labels = labels 11 | 12 | def add_gt_(self, gt_labels): 13 | self_inds = torch.arange( 14 | 1, len(gt_labels) + 1, dtype=torch.long, device=gt_labels.device) 15 | self.gt_inds = torch.cat([self_inds, self.gt_inds]) 16 | self.max_overlaps = torch.cat( 17 | [self.max_overlaps.new_ones(self.num_gts), self.max_overlaps]) 18 | if self.labels is not None: 19 | self.labels = torch.cat([gt_labels, self.labels]) 20 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/bbox/assigners/base_assigner.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | 3 | 4 | class BaseAssigner(metaclass=ABCMeta): 5 | 6 | @abstractmethod 7 | def assign(self, bboxes, gt_bboxes, gt_bboxes_ignore=None, gt_labels=None): 8 | pass 9 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/bbox/bbox_target.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from ..utils import multi_apply 4 | from .transforms import bbox2delta 5 | 6 | 7 | def bbox_target(pos_bboxes_list, 8 | neg_bboxes_list, 9 | pos_gt_bboxes_list, 10 | pos_gt_labels_list, 11 | cfg, 12 | reg_classes=1, 13 | target_means=[.0, .0, .0, .0], 14 | target_stds=[1.0, 1.0, 1.0, 1.0], 15 | concat=True): 16 | labels, label_weights, bbox_targets, bbox_weights = multi_apply( 17 | bbox_target_single, 18 | pos_bboxes_list, 19 | neg_bboxes_list, 20 | pos_gt_bboxes_list, 21 | pos_gt_labels_list, 22 | cfg=cfg, 23 | reg_classes=reg_classes, 24 | target_means=target_means, 25 | target_stds=target_stds) 26 | 27 | if concat: 28 | labels = torch.cat(labels, 0) 29 | label_weights = torch.cat(label_weights, 0) 30 | bbox_targets = torch.cat(bbox_targets, 0) 31 | bbox_weights = torch.cat(bbox_weights, 0) 32 | return labels, label_weights, bbox_targets, bbox_weights 33 | 34 | 35 | def bbox_target_single(pos_bboxes, 36 | neg_bboxes, 37 | pos_gt_bboxes, 38 | pos_gt_labels, 39 | cfg, 40 | reg_classes=1, 41 | target_means=[.0, .0, .0, .0], 42 | target_stds=[1.0, 1.0, 1.0, 1.0]): 43 | num_pos = pos_bboxes.size(0) 44 | num_neg = neg_bboxes.size(0) 45 | num_samples = num_pos + num_neg 46 | labels = pos_bboxes.new_zeros(num_samples, dtype=torch.long) 47 | label_weights = pos_bboxes.new_zeros(num_samples) 48 | bbox_targets = pos_bboxes.new_zeros(num_samples, 4) 49 | bbox_weights = pos_bboxes.new_zeros(num_samples, 4) 50 | if num_pos > 0: 51 | labels[:num_pos] = pos_gt_labels 52 | pos_weight = 1.0 if cfg.pos_weight <= 0 else cfg.pos_weight 53 | label_weights[:num_pos] = pos_weight 54 | pos_bbox_targets = bbox2delta(pos_bboxes, pos_gt_bboxes, target_means, 55 | target_stds) 56 | bbox_targets[:num_pos, :] = pos_bbox_targets 57 | bbox_weights[:num_pos, :] = 1 58 | if num_neg > 0: 59 | label_weights[-num_neg:] = 1.0 60 | 61 | return labels, label_weights, bbox_targets, bbox_weights 62 | 63 | 64 | def expand_target(bbox_targets, bbox_weights, labels, num_classes): 65 | bbox_targets_expand = bbox_targets.new_zeros( 66 | (bbox_targets.size(0), 4 * num_classes)) 67 | bbox_weights_expand = bbox_weights.new_zeros( 68 | (bbox_weights.size(0), 4 * num_classes)) 69 | for i in torch.nonzero(labels > 0).squeeze(-1): 70 | start, end = labels[i] * 4, (labels[i] + 1) * 4 71 | bbox_targets_expand[i, start:end] = bbox_targets[i, :] 72 | bbox_weights_expand[i, start:end] = bbox_weights[i, :] 73 | return bbox_targets_expand, bbox_weights_expand 74 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/bbox/geometry.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | 4 | def bbox_overlaps(bboxes1, bboxes2, mode='iou', is_aligned=False): 5 | """Calculate overlap between two set of bboxes. 6 | 7 | If ``is_aligned`` is ``False``, then calculate the ious between each bbox 8 | of bboxes1 and bboxes2, otherwise the ious between each aligned pair of 9 | bboxes1 and bboxes2. 10 | 11 | Args: 12 | bboxes1 (Tensor): shape (m, 4) 13 | bboxes2 (Tensor): shape (n, 4), if is_aligned is ``True``, then m and n 14 | must be equal. 15 | mode (str): "iou" (intersection over union) or iof (intersection over 16 | foreground). 17 | 18 | Returns: 19 | ious(Tensor): shape (m, n) if is_aligned == False else shape (m, 1) 20 | """ 21 | 22 | assert mode in ['iou', 'iof'] 23 | 24 | rows = bboxes1.size(0) 25 | cols = bboxes2.size(0) 26 | if is_aligned: 27 | assert rows == cols 28 | 29 | if rows * cols == 0: 30 | return bboxes1.new(rows, 1) if is_aligned else bboxes1.new(rows, cols) 31 | 32 | if is_aligned: 33 | lt = torch.max(bboxes1[:, :2], bboxes2[:, :2]) # [rows, 2] 34 | rb = torch.min(bboxes1[:, 2:], bboxes2[:, 2:]) # [rows, 2] 35 | 36 | wh = (rb - lt + 1).clamp(min=0) # [rows, 2] 37 | overlap = wh[:, 0] * wh[:, 1] 38 | area1 = (bboxes1[:, 2] - bboxes1[:, 0] + 1) * ( 39 | bboxes1[:, 3] - bboxes1[:, 1] + 1) 40 | 41 | if mode == 'iou': 42 | area2 = (bboxes2[:, 2] - bboxes2[:, 0] + 1) * ( 43 | bboxes2[:, 3] - bboxes2[:, 1] + 1) 44 | ious = overlap / (area1 + area2 - overlap) 45 | else: 46 | ious = overlap / area1 47 | else: 48 | lt = torch.max(bboxes1[:, None, :2], bboxes2[:, :2]) # [rows, cols, 2] 49 | rb = torch.min(bboxes1[:, None, 2:], bboxes2[:, 2:]) # [rows, cols, 2] 50 | 51 | wh = (rb - lt + 1).clamp(min=0) # [rows, cols, 2] 52 | overlap = wh[:, :, 0] * wh[:, :, 1] 53 | area1 = (bboxes1[:, 2] - bboxes1[:, 0] + 1) * ( 54 | bboxes1[:, 3] - bboxes1[:, 1] + 1) 55 | 56 | if mode == 'iou': 57 | area2 = (bboxes2[:, 2] - bboxes2[:, 0] + 1) * ( 58 | bboxes2[:, 3] - bboxes2[:, 1] + 1) 59 | ious = overlap / (area1[:, None] + area2 - overlap) 60 | else: 61 | ious = overlap / (area1[:, None]) 62 | 63 | return ious 64 | 65 | 66 | def bbox_areas(bboxes, keep_axis=False): 67 | x_min, y_min, x_max, y_max = bboxes[:, 0], bboxes[:, 1], bboxes[:, 2], bboxes[:, 3] 68 | areas = (y_max - y_min + 1) * (x_max - x_min + 1) 69 | if keep_axis: 70 | return areas[:, None] 71 | return areas 72 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/bbox/samplers/__init__.py: -------------------------------------------------------------------------------- 1 | from .base_sampler import BaseSampler 2 | from .combined_sampler import CombinedSampler 3 | from .instance_balanced_pos_sampler import InstanceBalancedPosSampler 4 | from .iou_balanced_neg_sampler import IoUBalancedNegSampler 5 | from .ohem_sampler import OHEMSampler 6 | from .pseudo_sampler import PseudoSampler 7 | from .random_sampler import RandomSampler 8 | from .sampling_result import SamplingResult 9 | 10 | __all__ = [ 11 | 'BaseSampler', 'PseudoSampler', 'RandomSampler', 12 | 'InstanceBalancedPosSampler', 'IoUBalancedNegSampler', 'CombinedSampler', 13 | 'OHEMSampler', 'SamplingResult' 14 | ] 15 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/bbox/samplers/base_sampler.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | 3 | import torch 4 | 5 | from .sampling_result import SamplingResult 6 | 7 | 8 | class BaseSampler(metaclass=ABCMeta): 9 | 10 | def __init__(self, 11 | num, 12 | pos_fraction, 13 | neg_pos_ub=-1, 14 | add_gt_as_proposals=True, 15 | **kwargs): 16 | self.num = num 17 | self.pos_fraction = pos_fraction 18 | self.neg_pos_ub = neg_pos_ub 19 | self.add_gt_as_proposals = add_gt_as_proposals 20 | self.pos_sampler = self 21 | self.neg_sampler = self 22 | 23 | @abstractmethod 24 | def _sample_pos(self, assign_result, num_expected, **kwargs): 25 | pass 26 | 27 | @abstractmethod 28 | def _sample_neg(self, assign_result, num_expected, **kwargs): 29 | pass 30 | 31 | def sample(self, 32 | assign_result, 33 | bboxes, 34 | gt_bboxes, 35 | gt_labels=None, 36 | **kwargs): 37 | """Sample positive and negative bboxes. 38 | 39 | This is a simple implementation of bbox sampling given candidates, 40 | assigning results and ground truth bboxes. 41 | 42 | Args: 43 | assign_result (:obj:`AssignResult`): Bbox assigning results. 44 | bboxes (Tensor): Boxes to be sampled from. 45 | gt_bboxes (Tensor): Ground truth bboxes. 46 | gt_labels (Tensor, optional): Class labels of ground truth bboxes. 47 | 48 | Returns: 49 | :obj:`SamplingResult`: Sampling result. 50 | """ 51 | bboxes = bboxes[:, :4] 52 | 53 | gt_flags = bboxes.new_zeros((bboxes.shape[0], ), dtype=torch.uint8) 54 | if self.add_gt_as_proposals: 55 | bboxes = torch.cat([gt_bboxes, bboxes], dim=0) 56 | assign_result.add_gt_(gt_labels) 57 | gt_ones = bboxes.new_ones(gt_bboxes.shape[0], dtype=torch.uint8) 58 | gt_flags = torch.cat([gt_ones, gt_flags]) 59 | 60 | num_expected_pos = int(self.num * self.pos_fraction) 61 | pos_inds = self.pos_sampler._sample_pos( 62 | assign_result, num_expected_pos, bboxes=bboxes, **kwargs) 63 | # We found that sampled indices have duplicated items occasionally. 64 | # (may be a bug of PyTorch) 65 | pos_inds = pos_inds.unique() 66 | num_sampled_pos = pos_inds.numel() 67 | num_expected_neg = self.num - num_sampled_pos 68 | if self.neg_pos_ub >= 0: 69 | _pos = max(1, num_sampled_pos) 70 | neg_upper_bound = int(self.neg_pos_ub * _pos) 71 | if num_expected_neg > neg_upper_bound: 72 | num_expected_neg = neg_upper_bound 73 | neg_inds = self.neg_sampler._sample_neg( 74 | assign_result, num_expected_neg, bboxes=bboxes, **kwargs) 75 | neg_inds = neg_inds.unique() 76 | 77 | return SamplingResult(pos_inds, neg_inds, bboxes, gt_bboxes, 78 | assign_result, gt_flags) 79 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/bbox/samplers/combined_sampler.py: -------------------------------------------------------------------------------- 1 | from ..assign_sampling import build_sampler 2 | from .base_sampler import BaseSampler 3 | 4 | 5 | class CombinedSampler(BaseSampler): 6 | 7 | def __init__(self, pos_sampler, neg_sampler, **kwargs): 8 | super(CombinedSampler, self).__init__(**kwargs) 9 | self.pos_sampler = build_sampler(pos_sampler, **kwargs) 10 | self.neg_sampler = build_sampler(neg_sampler, **kwargs) 11 | 12 | def _sample_pos(self, **kwargs): 13 | raise NotImplementedError 14 | 15 | def _sample_neg(self, **kwargs): 16 | raise NotImplementedError 17 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/bbox/samplers/instance_balanced_pos_sampler.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import torch 3 | 4 | from .random_sampler import RandomSampler 5 | 6 | 7 | class InstanceBalancedPosSampler(RandomSampler): 8 | 9 | def _sample_pos(self, assign_result, num_expected, **kwargs): 10 | pos_inds = torch.nonzero(assign_result.gt_inds > 0) 11 | if pos_inds.numel() != 0: 12 | pos_inds = pos_inds.squeeze(1) 13 | if pos_inds.numel() <= num_expected: 14 | return pos_inds 15 | else: 16 | unique_gt_inds = assign_result.gt_inds[pos_inds].unique() 17 | num_gts = len(unique_gt_inds) 18 | num_per_gt = int(round(num_expected / float(num_gts)) + 1) 19 | sampled_inds = [] 20 | for i in unique_gt_inds: 21 | inds = torch.nonzero(assign_result.gt_inds == i.item()) 22 | if inds.numel() != 0: 23 | inds = inds.squeeze(1) 24 | else: 25 | continue 26 | if len(inds) > num_per_gt: 27 | inds = self.random_choice(inds, num_per_gt) 28 | sampled_inds.append(inds) 29 | sampled_inds = torch.cat(sampled_inds) 30 | if len(sampled_inds) < num_expected: 31 | num_extra = num_expected - len(sampled_inds) 32 | extra_inds = np.array( 33 | list(set(pos_inds.cpu()) - set(sampled_inds.cpu()))) 34 | if len(extra_inds) > num_extra: 35 | extra_inds = self.random_choice(extra_inds, num_extra) 36 | extra_inds = torch.from_numpy(extra_inds).to( 37 | assign_result.gt_inds.device).long() 38 | sampled_inds = torch.cat([sampled_inds, extra_inds]) 39 | elif len(sampled_inds) > num_expected: 40 | sampled_inds = self.random_choice(sampled_inds, num_expected) 41 | return sampled_inds 42 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/bbox/samplers/pseudo_sampler.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from .base_sampler import BaseSampler 4 | from .sampling_result import SamplingResult 5 | 6 | 7 | class PseudoSampler(BaseSampler): 8 | 9 | def __init__(self, **kwargs): 10 | pass 11 | 12 | def _sample_pos(self, **kwargs): 13 | raise NotImplementedError 14 | 15 | def _sample_neg(self, **kwargs): 16 | raise NotImplementedError 17 | 18 | def sample(self, assign_result, bboxes, gt_bboxes, **kwargs): 19 | pos_inds = torch.nonzero( 20 | assign_result.gt_inds > 0).squeeze(-1).unique() 21 | neg_inds = torch.nonzero( 22 | assign_result.gt_inds == 0).squeeze(-1).unique() 23 | gt_flags = bboxes.new_zeros(bboxes.shape[0], dtype=torch.uint8) 24 | sampling_result = SamplingResult(pos_inds, neg_inds, bboxes, gt_bboxes, 25 | assign_result, gt_flags) 26 | return sampling_result 27 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/bbox/samplers/random_sampler.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import torch 3 | 4 | from .base_sampler import BaseSampler 5 | 6 | 7 | class RandomSampler(BaseSampler): 8 | 9 | def __init__(self, 10 | num, 11 | pos_fraction, 12 | neg_pos_ub=-1, 13 | add_gt_as_proposals=True, 14 | **kwargs): 15 | super(RandomSampler, self).__init__(num, pos_fraction, neg_pos_ub, 16 | add_gt_as_proposals) 17 | 18 | @staticmethod 19 | def random_choice(gallery, num): 20 | """Random select some elements from the gallery. 21 | 22 | It seems that Pytorch's implementation is slower than numpy so we use 23 | numpy to randperm the indices. 24 | """ 25 | assert len(gallery) >= num 26 | if isinstance(gallery, list): 27 | gallery = np.array(gallery) 28 | cands = np.arange(len(gallery)) 29 | np.random.shuffle(cands) 30 | rand_inds = cands[:num] 31 | if not isinstance(gallery, np.ndarray): 32 | rand_inds = torch.from_numpy(rand_inds).long().to(gallery.device) 33 | return gallery[rand_inds] 34 | 35 | def _sample_pos(self, assign_result, num_expected, **kwargs): 36 | """Randomly sample some positive samples.""" 37 | pos_inds = torch.nonzero(assign_result.gt_inds > 0) 38 | if pos_inds.numel() != 0: 39 | pos_inds = pos_inds.squeeze(1) 40 | if pos_inds.numel() <= num_expected: 41 | return pos_inds 42 | else: 43 | return self.random_choice(pos_inds, num_expected) 44 | 45 | def _sample_neg(self, assign_result, num_expected, **kwargs): 46 | """Randomly sample some negative samples.""" 47 | neg_inds = torch.nonzero(assign_result.gt_inds == 0) 48 | if neg_inds.numel() != 0: 49 | neg_inds = neg_inds.squeeze(1) 50 | if len(neg_inds) <= num_expected: 51 | return neg_inds 52 | else: 53 | return self.random_choice(neg_inds, num_expected) 54 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/bbox/samplers/sampling_result.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | 4 | class SamplingResult(object): 5 | 6 | def __init__(self, pos_inds, neg_inds, bboxes, gt_bboxes, assign_result, 7 | gt_flags): 8 | self.pos_inds = pos_inds 9 | self.neg_inds = neg_inds 10 | self.pos_bboxes = bboxes[pos_inds] 11 | self.neg_bboxes = bboxes[neg_inds] 12 | self.pos_is_gt = gt_flags[pos_inds] 13 | 14 | self.num_gts = gt_bboxes.shape[0] 15 | self.pos_assigned_gt_inds = assign_result.gt_inds[pos_inds] - 1 16 | self.pos_gt_bboxes = gt_bboxes[self.pos_assigned_gt_inds, :] 17 | if assign_result.labels is not None: 18 | self.pos_gt_labels = assign_result.labels[pos_inds] 19 | else: 20 | self.pos_gt_labels = None 21 | 22 | @property 23 | def bboxes(self): 24 | return torch.cat([self.pos_bboxes, self.neg_bboxes]) 25 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/evaluation/__init__.py: -------------------------------------------------------------------------------- 1 | from .class_names import (coco_classes, dataset_aliases, get_classes, 2 | imagenet_det_classes, imagenet_vid_classes, 3 | voc_classes) 4 | from .coco_utils import coco_eval, fast_eval_recall, results2json 5 | from .eval_hooks import (CocoDistEvalmAPHook, CocoDistEvalRecallHook, 6 | DistEvalHook, DistEvalmAPHook) 7 | from .mean_ap import average_precision, eval_map, print_map_summary 8 | from .recall import (eval_recalls, plot_iou_recall, plot_num_recall, 9 | print_recall_summary) 10 | 11 | __all__ = [ 12 | 'voc_classes', 'imagenet_det_classes', 'imagenet_vid_classes', 13 | 'coco_classes', 'dataset_aliases', 'get_classes', 'coco_eval', 14 | 'fast_eval_recall', 'results2json', 'DistEvalHook', 'DistEvalmAPHook', 15 | 'CocoDistEvalRecallHook', 'CocoDistEvalmAPHook', 'average_precision', 16 | 'eval_map', 'print_map_summary', 'eval_recalls', 'print_recall_summary', 17 | 'plot_num_recall', 'plot_iou_recall' 18 | ] 19 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/evaluation/bbox_overlaps.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def bbox_overlaps(bboxes1, bboxes2, mode='iou'): 5 | """Calculate the ious between each bbox of bboxes1 and bboxes2. 6 | 7 | Args: 8 | bboxes1(ndarray): shape (n, 4) 9 | bboxes2(ndarray): shape (k, 4) 10 | mode(str): iou (intersection over union) or iof (intersection 11 | over foreground) 12 | 13 | Returns: 14 | ious(ndarray): shape (n, k) 15 | """ 16 | 17 | assert mode in ['iou', 'iof'] 18 | 19 | bboxes1 = bboxes1.astype(np.float32) 20 | bboxes2 = bboxes2.astype(np.float32) 21 | rows = bboxes1.shape[0] 22 | cols = bboxes2.shape[0] 23 | ious = np.zeros((rows, cols), dtype=np.float32) 24 | if rows * cols == 0: 25 | return ious 26 | exchange = False 27 | if bboxes1.shape[0] > bboxes2.shape[0]: 28 | bboxes1, bboxes2 = bboxes2, bboxes1 29 | ious = np.zeros((cols, rows), dtype=np.float32) 30 | exchange = True 31 | area1 = (bboxes1[:, 2] - bboxes1[:, 0] + 1) * ( 32 | bboxes1[:, 3] - bboxes1[:, 1] + 1) 33 | area2 = (bboxes2[:, 2] - bboxes2[:, 0] + 1) * ( 34 | bboxes2[:, 3] - bboxes2[:, 1] + 1) 35 | for i in range(bboxes1.shape[0]): 36 | x_start = np.maximum(bboxes1[i, 0], bboxes2[:, 0]) 37 | y_start = np.maximum(bboxes1[i, 1], bboxes2[:, 1]) 38 | x_end = np.minimum(bboxes1[i, 2], bboxes2[:, 2]) 39 | y_end = np.minimum(bboxes1[i, 3], bboxes2[:, 3]) 40 | overlap = np.maximum(x_end - x_start + 1, 0) * np.maximum( 41 | y_end - y_start + 1, 0) 42 | if mode == 'iou': 43 | union = area1[i] + area2 - overlap 44 | else: 45 | union = area1[i] if not exchange else area2 46 | ious[i, :] = overlap / union 47 | if exchange: 48 | ious = ious.T 49 | return ious 50 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/fp16/__init__.py: -------------------------------------------------------------------------------- 1 | from .decorators import auto_fp16, force_fp32 2 | from .hooks import Fp16OptimizerHook, wrap_fp16_model 3 | 4 | __all__ = ['auto_fp16', 'force_fp32', 'Fp16OptimizerHook', 'wrap_fp16_model'] 5 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/fp16/utils.py: -------------------------------------------------------------------------------- 1 | from collections import abc 2 | 3 | import numpy as np 4 | import torch 5 | 6 | 7 | def cast_tensor_type(inputs, src_type, dst_type): 8 | if isinstance(inputs, torch.Tensor): 9 | return inputs.to(dst_type) 10 | elif isinstance(inputs, str): 11 | return inputs 12 | elif isinstance(inputs, np.ndarray): 13 | return inputs 14 | elif isinstance(inputs, abc.Mapping): 15 | return type(inputs)({ 16 | k: cast_tensor_type(v, src_type, dst_type) 17 | for k, v in inputs.items() 18 | }) 19 | elif isinstance(inputs, abc.Iterable): 20 | return type(inputs)( 21 | cast_tensor_type(item, src_type, dst_type) for item in inputs) 22 | else: 23 | return inputs 24 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/mask/__init__.py: -------------------------------------------------------------------------------- 1 | from .mask_target import mask_target 2 | from .utils import split_combined_polys 3 | 4 | __all__ = ['split_combined_polys', 'mask_target'] 5 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/mask/mask_target.py: -------------------------------------------------------------------------------- 1 | import mmcv 2 | import numpy as np 3 | import torch 4 | from torch.nn.modules.utils import _pair 5 | 6 | 7 | def mask_target(pos_proposals_list, pos_assigned_gt_inds_list, gt_masks_list, 8 | cfg): 9 | cfg_list = [cfg for _ in range(len(pos_proposals_list))] 10 | mask_targets = map(mask_target_single, pos_proposals_list, 11 | pos_assigned_gt_inds_list, gt_masks_list, cfg_list) 12 | mask_targets = torch.cat(list(mask_targets)) 13 | return mask_targets 14 | 15 | 16 | def mask_target_single(pos_proposals, pos_assigned_gt_inds, gt_masks, cfg): 17 | mask_size = _pair(cfg.mask_size) 18 | num_pos = pos_proposals.size(0) 19 | mask_targets = [] 20 | if num_pos > 0: 21 | proposals_np = pos_proposals.cpu().numpy() 22 | pos_assigned_gt_inds = pos_assigned_gt_inds.cpu().numpy() 23 | for i in range(num_pos): 24 | gt_mask = gt_masks[pos_assigned_gt_inds[i]] 25 | bbox = proposals_np[i, :].astype(np.int32) 26 | x1, y1, x2, y2 = bbox 27 | w = np.maximum(x2 - x1 + 1, 1) 28 | h = np.maximum(y2 - y1 + 1, 1) 29 | # mask is uint8 both before and after resizing 30 | # mask_size (h, w) to (w, h) 31 | target = mmcv.imresize(gt_mask[y1:y1 + h, x1:x1 + w], 32 | mask_size[::-1]) 33 | mask_targets.append(target) 34 | mask_targets = torch.from_numpy(np.stack(mask_targets)).float().to( 35 | pos_proposals.device) 36 | else: 37 | mask_targets = pos_proposals.new_zeros((0, ) + mask_size) 38 | return mask_targets 39 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/mask/utils.py: -------------------------------------------------------------------------------- 1 | import mmcv 2 | 3 | 4 | def split_combined_polys(polys, poly_lens, polys_per_mask): 5 | """Split the combined 1-D polys into masks. 6 | 7 | A mask is represented as a list of polys, and a poly is represented as 8 | a 1-D array. In dataset, all masks are concatenated into a single 1-D 9 | tensor. Here we need to split the tensor into original representations. 10 | 11 | Args: 12 | polys (list): a list (length = image num) of 1-D tensors 13 | poly_lens (list): a list (length = image num) of poly length 14 | polys_per_mask (list): a list (length = image num) of poly number 15 | of each mask 16 | 17 | Returns: 18 | list: a list (length = image num) of list (length = mask num) of 19 | list (length = poly num) of numpy array 20 | """ 21 | mask_polys_list = [] 22 | for img_id in range(len(polys)): 23 | polys_single = polys[img_id] 24 | polys_lens_single = poly_lens[img_id].tolist() 25 | polys_per_mask_single = polys_per_mask[img_id].tolist() 26 | 27 | split_polys = mmcv.slice_list(polys_single, polys_lens_single) 28 | mask_polys = mmcv.slice_list(split_polys, polys_per_mask_single) 29 | mask_polys_list.append(mask_polys) 30 | return mask_polys_list 31 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/post_processing/__init__.py: -------------------------------------------------------------------------------- 1 | from .bbox_nms import multiclass_nms 2 | from .merge_augs import (merge_aug_bboxes, merge_aug_masks, 3 | merge_aug_proposals, merge_aug_scores) 4 | 5 | __all__ = [ 6 | 'multiclass_nms', 'merge_aug_proposals', 'merge_aug_bboxes', 7 | 'merge_aug_scores', 'merge_aug_masks' 8 | ] 9 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/post_processing/bbox_nms.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from mmdet.ops.nms import nms_wrapper 4 | 5 | 6 | def multiclass_nms(multi_bboxes, 7 | multi_scores, 8 | score_thr, 9 | nms_cfg, 10 | max_num=-1, 11 | score_factors=None): 12 | """NMS for multi-class bboxes. 13 | 14 | Args: 15 | multi_bboxes (Tensor): shape (n, #class*4) or (n, 4) 16 | multi_scores (Tensor): shape (n, #class), where the 0th column 17 | contains scores of the background class, but this will be ignored. 18 | score_thr (float): bbox threshold, bboxes with scores lower than it 19 | will not be considered. 20 | nms_thr (float): NMS IoU threshold 21 | max_num (int): if there are more than max_num bboxes after NMS, 22 | only top max_num will be kept. 23 | score_factors (Tensor): The factors multiplied to scores before 24 | applying NMS 25 | 26 | Returns: 27 | tuple: (bboxes, labels), tensors of shape (k, 5) and (k, 1). Labels 28 | are 0-based. 29 | """ 30 | num_classes = multi_scores.shape[1] 31 | bboxes, labels = [], [] 32 | nms_cfg_ = nms_cfg.copy() 33 | nms_type = nms_cfg_.pop('type', 'nms') 34 | nms_op = getattr(nms_wrapper, nms_type) 35 | for i in range(1, num_classes): 36 | cls_inds = multi_scores[:, i] > score_thr 37 | if not cls_inds.any(): 38 | continue 39 | # get bboxes and scores of this class 40 | if multi_bboxes.shape[1] == 4: 41 | _bboxes = multi_bboxes[cls_inds, :] 42 | else: 43 | _bboxes = multi_bboxes[cls_inds, i * 4:(i + 1) * 4] 44 | _scores = multi_scores[cls_inds, i] 45 | if score_factors is not None: 46 | _scores *= score_factors[cls_inds] 47 | cls_dets = torch.cat([_bboxes, _scores[:, None]], dim=1) 48 | cls_dets, _ = nms_op(cls_dets, **nms_cfg_) 49 | cls_labels = multi_bboxes.new_full((cls_dets.shape[0], ), 50 | i - 1, 51 | dtype=torch.long) 52 | bboxes.append(cls_dets) 53 | labels.append(cls_labels) 54 | if bboxes: 55 | bboxes = torch.cat(bboxes) 56 | labels = torch.cat(labels) 57 | if bboxes.shape[0] > max_num: 58 | _, inds = bboxes[:, -1].sort(descending=True) 59 | inds = inds[:max_num] 60 | bboxes = bboxes[inds] 61 | labels = labels[inds] 62 | else: 63 | bboxes = multi_bboxes.new_zeros((0, 5)) 64 | labels = multi_bboxes.new_zeros((0, ), dtype=torch.long) 65 | 66 | return bboxes, labels 67 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .dist_utils import DistOptimizerHook, allreduce_grads 2 | from .misc import multi_apply, tensor2imgs, unmap 3 | 4 | __all__ = [ 5 | 'allreduce_grads', 'DistOptimizerHook', 'tensor2imgs', 'unmap', 6 | 'multi_apply' 7 | ] 8 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/utils/dist_utils.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | import torch.distributed as dist 4 | from mmcv.runner import OptimizerHook 5 | from torch._utils import (_flatten_dense_tensors, _take_tensors, 6 | _unflatten_dense_tensors) 7 | 8 | 9 | def _allreduce_coalesced(tensors, world_size, bucket_size_mb=-1): 10 | if bucket_size_mb > 0: 11 | bucket_size_bytes = bucket_size_mb * 1024 * 1024 12 | buckets = _take_tensors(tensors, bucket_size_bytes) 13 | else: 14 | buckets = OrderedDict() 15 | for tensor in tensors: 16 | tp = tensor.type() 17 | if tp not in buckets: 18 | buckets[tp] = [] 19 | buckets[tp].append(tensor) 20 | buckets = buckets.values() 21 | 22 | for bucket in buckets: 23 | flat_tensors = _flatten_dense_tensors(bucket) 24 | dist.all_reduce(flat_tensors) 25 | flat_tensors.div_(world_size) 26 | for tensor, synced in zip( 27 | bucket, _unflatten_dense_tensors(flat_tensors, bucket)): 28 | tensor.copy_(synced) 29 | 30 | 31 | def allreduce_grads(params, coalesce=True, bucket_size_mb=-1): 32 | grads = [ 33 | param.grad.data for param in params 34 | if param.requires_grad and param.grad is not None 35 | ] 36 | world_size = dist.get_world_size() 37 | if coalesce: 38 | _allreduce_coalesced(grads, world_size, bucket_size_mb) 39 | else: 40 | for tensor in grads: 41 | dist.all_reduce(tensor.div_(world_size)) 42 | 43 | 44 | class DistOptimizerHook(OptimizerHook): 45 | 46 | def __init__(self, grad_clip=None, coalesce=True, bucket_size_mb=-1): 47 | self.grad_clip = grad_clip 48 | self.coalesce = coalesce 49 | self.bucket_size_mb = bucket_size_mb 50 | 51 | def after_train_iter(self, runner): 52 | runner.optimizer.zero_grad() 53 | runner.outputs['loss'].backward() 54 | allreduce_grads(runner.model.parameters(), self.coalesce, 55 | self.bucket_size_mb) 56 | if self.grad_clip is not None: 57 | self.clip_grads(runner.model.parameters()) 58 | runner.optimizer.step() 59 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/core/utils/misc.py: -------------------------------------------------------------------------------- 1 | from functools import partial 2 | 3 | import mmcv 4 | import numpy as np 5 | from six.moves import map, zip 6 | 7 | 8 | def tensor2imgs(tensor, mean=(0, 0, 0), std=(1, 1, 1), to_rgb=True): 9 | num_imgs = tensor.size(0) 10 | mean = np.array(mean, dtype=np.float32) 11 | std = np.array(std, dtype=np.float32) 12 | imgs = [] 13 | for img_id in range(num_imgs): 14 | img = tensor[img_id, ...].cpu().numpy().transpose(1, 2, 0) 15 | img = mmcv.imdenormalize( 16 | img, mean, std, to_bgr=to_rgb).astype(np.uint8) 17 | imgs.append(np.ascontiguousarray(img)) 18 | return imgs 19 | 20 | 21 | def multi_apply(func, *args, **kwargs): 22 | pfunc = partial(func, **kwargs) if kwargs else func 23 | map_results = map(pfunc, *args) 24 | return tuple(map(list, zip(*map_results))) 25 | 26 | 27 | def unmap(data, count, inds, fill=0): 28 | """ Unmap a subset of item (data) back to the original set of items (of 29 | size count) """ 30 | if data.dim() == 1: 31 | ret = data.new_full((count, ), fill) 32 | ret[inds] = data 33 | else: 34 | new_size = (count, ) + data.size()[1:] 35 | ret = data.new_full(new_size, fill) 36 | ret[inds, :] = data 37 | return ret 38 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/datasets/__init__.py: -------------------------------------------------------------------------------- 1 | from .builder import build_dataset 2 | from .cityscapes import CityscapesDataset 3 | from .coco import CocoDataset 4 | from .custom import CustomDataset 5 | from .dataset_wrappers import ConcatDataset, RepeatDataset 6 | from .extra_aug import ExtraAugmentation 7 | from .loader import DistributedGroupSampler, GroupSampler, build_dataloader 8 | from .registry import DATASETS 9 | from .voc import VOCDataset 10 | from .wider_face import WIDERFaceDataset 11 | from .xml_style import XMLDataset 12 | 13 | __all__ = [ 14 | 'CustomDataset', 'XMLDataset', 'CocoDataset', 'VOCDataset', 15 | 'CityscapesDataset', 'GroupSampler', 'DistributedGroupSampler', 16 | 'build_dataloader', 'ConcatDataset', 'RepeatDataset', 'ExtraAugmentation', 17 | 'WIDERFaceDataset', 'DATASETS', 'build_dataset' 18 | ] 19 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/datasets/builder.py: -------------------------------------------------------------------------------- 1 | import copy 2 | 3 | from mmdet.utils import build_from_cfg 4 | from .dataset_wrappers import ConcatDataset, RepeatDataset 5 | from .registry import DATASETS 6 | 7 | 8 | def _concat_dataset(cfg, default_args=None): 9 | ann_files = cfg['ann_file'] 10 | img_prefixes = cfg.get('img_prefix', None) 11 | seg_prefixes = cfg.get('seg_prefixes', None) 12 | proposal_files = cfg.get('proposal_file', None) 13 | 14 | datasets = [] 15 | num_dset = len(ann_files) 16 | for i in range(num_dset): 17 | data_cfg = copy.deepcopy(cfg) 18 | data_cfg['ann_file'] = ann_files[i] 19 | if isinstance(img_prefixes, (list, tuple)): 20 | data_cfg['img_prefix'] = img_prefixes[i] 21 | if isinstance(seg_prefixes, (list, tuple)): 22 | data_cfg['seg_prefix'] = seg_prefixes[i] 23 | if isinstance(proposal_files, (list, tuple)): 24 | data_cfg['proposal_file'] = proposal_files[i] 25 | datasets.append(build_dataset(data_cfg, default_args)) 26 | 27 | return ConcatDataset(datasets) 28 | 29 | 30 | def build_dataset(cfg, default_args=None): 31 | if isinstance(cfg, (list, tuple)): 32 | dataset = ConcatDataset([build_dataset(c, default_args) for c in cfg]) 33 | elif cfg['type'] == 'RepeatDataset': 34 | dataset = RepeatDataset( 35 | build_dataset(cfg['dataset'], default_args), cfg['times']) 36 | elif isinstance(cfg['ann_file'], (list, tuple)): 37 | dataset = _concat_dataset(cfg, default_args) 38 | else: 39 | dataset = build_from_cfg(cfg, DATASETS, default_args) 40 | 41 | return dataset 42 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/datasets/cityscapes.py: -------------------------------------------------------------------------------- 1 | from .coco import CocoDataset 2 | from .registry import DATASETS 3 | 4 | 5 | @DATASETS.register_module 6 | class CityscapesDataset(CocoDataset): 7 | 8 | CLASSES = ('person', 'rider', 'car', 'truck', 'bus', 'train', 'motorcycle', 9 | 'bicycle') 10 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/datasets/dataset_wrappers.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from torch.utils.data.dataset import ConcatDataset as _ConcatDataset 3 | 4 | from .registry import DATASETS 5 | 6 | 7 | @DATASETS.register_module 8 | class ConcatDataset(_ConcatDataset): 9 | """A wrapper of concatenated dataset. 10 | 11 | Same as :obj:`torch.utils.data.dataset.ConcatDataset`, but 12 | concat the group flag for image aspect ratio. 13 | 14 | Args: 15 | datasets (list[:obj:`Dataset`]): A list of datasets. 16 | """ 17 | 18 | def __init__(self, datasets): 19 | super(ConcatDataset, self).__init__(datasets) 20 | self.CLASSES = datasets[0].CLASSES 21 | if hasattr(datasets[0], 'flag'): 22 | flags = [] 23 | for i in range(0, len(datasets)): 24 | flags.append(datasets[i].flag) 25 | self.flag = np.concatenate(flags) 26 | 27 | 28 | @DATASETS.register_module 29 | class RepeatDataset(object): 30 | """A wrapper of repeated dataset. 31 | 32 | The length of repeated dataset will be `times` larger than the original 33 | dataset. This is useful when the data loading time is long but the dataset 34 | is small. Using RepeatDataset can reduce the data loading time between 35 | epochs. 36 | 37 | Args: 38 | dataset (:obj:`Dataset`): The dataset to be repeated. 39 | times (int): Repeat times. 40 | """ 41 | 42 | def __init__(self, dataset, times): 43 | self.dataset = dataset 44 | self.times = times 45 | self.CLASSES = dataset.CLASSES 46 | if hasattr(self.dataset, 'flag'): 47 | self.flag = np.tile(self.dataset.flag, times) 48 | 49 | self._ori_len = len(self.dataset) 50 | 51 | def __getitem__(self, idx): 52 | return self.dataset[idx % self._ori_len] 53 | 54 | def __len__(self): 55 | return self.times * self._ori_len 56 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/datasets/loader/__init__.py: -------------------------------------------------------------------------------- 1 | from .build_loader import build_dataloader 2 | from .sampler import DistributedGroupSampler, GroupSampler 3 | 4 | __all__ = ['GroupSampler', 'DistributedGroupSampler', 'build_dataloader'] 5 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/datasets/loader/build_loader.py: -------------------------------------------------------------------------------- 1 | import platform 2 | from functools import partial 3 | 4 | from mmcv.parallel import collate 5 | from mmcv.runner import get_dist_info 6 | from torch.utils.data import DataLoader 7 | 8 | from .sampler import DistributedGroupSampler, DistributedSampler, GroupSampler 9 | 10 | if platform.system() != 'Windows': 11 | # https://github.com/pytorch/pytorch/issues/973 12 | import resource 13 | rlimit = resource.getrlimit(resource.RLIMIT_NOFILE) 14 | resource.setrlimit(resource.RLIMIT_NOFILE, (4096, rlimit[1])) 15 | 16 | 17 | def build_dataloader(dataset, 18 | imgs_per_gpu, 19 | workers_per_gpu, 20 | num_gpus=1, 21 | dist=True, 22 | **kwargs): 23 | shuffle = kwargs.get('shuffle', True) 24 | if dist: 25 | rank, world_size = get_dist_info() 26 | if shuffle: 27 | sampler = DistributedGroupSampler(dataset, imgs_per_gpu, 28 | world_size, rank) 29 | else: 30 | sampler = DistributedSampler( 31 | dataset, world_size, rank, shuffle=False) 32 | batch_size = imgs_per_gpu 33 | num_workers = workers_per_gpu 34 | else: 35 | sampler = GroupSampler(dataset, imgs_per_gpu) if shuffle else None 36 | batch_size = num_gpus * imgs_per_gpu 37 | num_workers = num_gpus * workers_per_gpu 38 | 39 | data_loader = DataLoader( 40 | dataset, 41 | batch_size=batch_size, 42 | sampler=sampler, 43 | num_workers=num_workers, 44 | collate_fn=partial(collate, samples_per_gpu=imgs_per_gpu), 45 | pin_memory=False, 46 | **kwargs) 47 | 48 | return data_loader 49 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/datasets/pipelines/__init__.py: -------------------------------------------------------------------------------- 1 | from .compose import Compose 2 | from .formating import (Collect, ImageToTensor, ToDataContainer, ToTensor, 3 | Transpose, to_tensor) 4 | from .loading import LoadAnnotations, LoadImageFromFile, LoadProposals 5 | from .test_aug import MultiScaleFlipAug 6 | from .transforms import (Albu, Expand, MinIoURandomCrop, Normalize, Pad, 7 | PhotoMetricDistortion, RandomCrop, RandomFlip, Resize, 8 | SegResizeFlipPadRescale) 9 | 10 | __all__ = [ 11 | 'Compose', 'to_tensor', 'ToTensor', 'ImageToTensor', 'ToDataContainer', 12 | 'Transpose', 'Collect', 'LoadAnnotations', 'LoadImageFromFile', 13 | 'LoadProposals', 'MultiScaleFlipAug', 'Resize', 'RandomFlip', 'Pad', 14 | 'RandomCrop', 'Normalize', 'SegResizeFlipPadRescale', 'MinIoURandomCrop', 15 | 'Expand', 'PhotoMetricDistortion', 'Albu' 16 | ] 17 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/datasets/pipelines/compose.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | from mmdet.utils import build_from_cfg 4 | from ..registry import PIPELINES 5 | 6 | 7 | @PIPELINES.register_module 8 | class Compose(object): 9 | 10 | def __init__(self, transforms): 11 | assert isinstance(transforms, collections.abc.Sequence) 12 | self.transforms = [] 13 | for transform in transforms: 14 | if isinstance(transform, dict): 15 | transform = build_from_cfg(transform, PIPELINES) 16 | self.transforms.append(transform) 17 | elif callable(transform): 18 | self.transforms.append(transform) 19 | else: 20 | raise TypeError('transform must be callable or a dict') 21 | 22 | def __call__(self, data): 23 | for t in self.transforms: 24 | data = t(data) 25 | if data is None: 26 | return None 27 | return data 28 | 29 | def __repr__(self): 30 | format_string = self.__class__.__name__ + '(' 31 | for t in self.transforms: 32 | format_string += '\n' 33 | format_string += ' {0}'.format(t) 34 | format_string += '\n)' 35 | return format_string 36 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/datasets/pipelines/test_aug.py: -------------------------------------------------------------------------------- 1 | import mmcv 2 | 3 | from ..registry import PIPELINES 4 | from .compose import Compose 5 | 6 | 7 | @PIPELINES.register_module 8 | class MultiScaleFlipAug(object): 9 | 10 | def __init__(self, transforms, img_scale, flip=False): 11 | self.transforms = Compose(transforms) 12 | self.img_scale = img_scale if isinstance(img_scale, 13 | list) else [img_scale] 14 | assert mmcv.is_list_of(self.img_scale, tuple) 15 | self.flip = flip 16 | 17 | def __call__(self, results): 18 | aug_data = [] 19 | flip_aug = [False, True] if self.flip else [False] 20 | for scale in self.img_scale: 21 | for flip in flip_aug: 22 | _results = results.copy() 23 | _results['scale'] = scale 24 | _results['flip'] = flip 25 | data = self.transforms(_results) 26 | aug_data.append(data) 27 | # list of dict to dict of list 28 | aug_data_dict = {key: [] for key in aug_data[0]} 29 | for data in aug_data: 30 | for key, val in data.items(): 31 | aug_data_dict[key].append(val) 32 | return aug_data_dict 33 | 34 | def __repr__(self): 35 | repr_str = self.__class__.__name__ 36 | repr_str += '(transforms={}, img_scale={}, flip={})'.format( 37 | self.transforms, self.img_scale, self.flip) 38 | return repr_str 39 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/datasets/registry.py: -------------------------------------------------------------------------------- 1 | from mmdet.utils import Registry 2 | 3 | DATASETS = Registry('dataset') 4 | PIPELINES = Registry('pipeline') 5 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/datasets/voc.py: -------------------------------------------------------------------------------- 1 | from .registry import DATASETS 2 | from .xml_style import XMLDataset 3 | 4 | 5 | @DATASETS.register_module 6 | class VOCDataset(XMLDataset): 7 | 8 | CLASSES = ('aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 9 | 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse', 10 | 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', 11 | 'tvmonitor') 12 | 13 | def __init__(self, **kwargs): 14 | super(VOCDataset, self).__init__(**kwargs) 15 | if 'VOC2007' in self.img_prefix: 16 | self.year = 2007 17 | elif 'VOC2012' in self.img_prefix: 18 | self.year = 2012 19 | else: 20 | raise ValueError('Cannot infer dataset year from img_prefix') 21 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/datasets/wider_face.py: -------------------------------------------------------------------------------- 1 | import os.path as osp 2 | import xml.etree.ElementTree as ET 3 | 4 | import mmcv 5 | 6 | from .registry import DATASETS 7 | from .xml_style import XMLDataset 8 | 9 | 10 | @DATASETS.register_module 11 | class WIDERFaceDataset(XMLDataset): 12 | """ 13 | Reader for the WIDER Face dataset in PASCAL VOC format. 14 | Conversion scripts can be found in 15 | https://github.com/sovrasov/wider-face-pascal-voc-annotations 16 | """ 17 | CLASSES = ('face', ) 18 | 19 | def __init__(self, **kwargs): 20 | super(WIDERFaceDataset, self).__init__(**kwargs) 21 | 22 | def load_annotations(self, ann_file): 23 | img_infos = [] 24 | img_ids = mmcv.list_from_file(ann_file) 25 | for img_id in img_ids: 26 | filename = '{}.jpg'.format(img_id) 27 | xml_path = osp.join(self.img_prefix, 'Annotations', 28 | '{}.xml'.format(img_id)) 29 | tree = ET.parse(xml_path) 30 | root = tree.getroot() 31 | size = root.find('size') 32 | width = int(size.find('width').text) 33 | height = int(size.find('height').text) 34 | folder = root.find('folder').text 35 | img_infos.append( 36 | dict( 37 | id=img_id, 38 | filename=osp.join(folder, filename), 39 | width=width, 40 | height=height)) 41 | 42 | return img_infos 43 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .anchor_heads import * # noqa: F401,F403 2 | from .backbones import * # noqa: F401,F403 3 | from .bbox_heads import * # noqa: F401,F403 4 | from .builder import (build_backbone, build_detector, build_head, build_loss, 5 | build_neck, build_roi_extractor, build_shared_head) 6 | from .detectors import * # noqa: F401,F403 7 | from .losses import * # noqa: F401,F403 8 | from .mask_heads import * # noqa: F401,F403 9 | from .necks import * # noqa: F401,F403 10 | from .registry import (BACKBONES, DETECTORS, HEADS, LOSSES, NECKS, 11 | ROI_EXTRACTORS, SHARED_HEADS) 12 | from .roi_extractors import * # noqa: F401,F403 13 | from .shared_heads import * # noqa: F401,F403 14 | 15 | __all__ = [ 16 | 'BACKBONES', 'NECKS', 'ROI_EXTRACTORS', 'SHARED_HEADS', 'HEADS', 'LOSSES', 17 | 'DETECTORS', 'build_backbone', 'build_neck', 'build_roi_extractor', 18 | 'build_shared_head', 'build_head', 'build_loss', 'build_detector' 19 | ] 20 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/anchor_heads/__init__.py: -------------------------------------------------------------------------------- 1 | from .anchor_head import AnchorHead 2 | from .fcos_head import FCOSHead 3 | from .fovea_head import FoveaHead 4 | from .ga_retina_head import GARetinaHead 5 | from .ga_rpn_head import GARPNHead 6 | from .guided_anchor_head import FeatureAdaption, GuidedAnchorHead 7 | from .reppoints_head import RepPointsHead 8 | from .retina_head import RetinaHead 9 | from .rpn_head import RPNHead 10 | from .ssd_head import SSDHead 11 | from .ttf_head import TTFHead 12 | 13 | __all__ = [ 14 | 'AnchorHead', 'GuidedAnchorHead', 'FeatureAdaption', 'RPNHead', 15 | 'GARPNHead', 'RetinaHead', 'GARetinaHead', 'SSDHead', 'FCOSHead', 16 | 'RepPointsHead', 'FoveaHead', 'TTFHead'] 17 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/backbones/__init__.py: -------------------------------------------------------------------------------- 1 | from .hrnet import HRNet 2 | from .resnet import ResNet, make_res_layer 3 | from .resnext import ResNeXt 4 | from .ssd_vgg import SSDVGG 5 | from .darknet import DarknetV3 6 | 7 | __all__ = ['ResNet', 'make_res_layer', 'ResNeXt', 'SSDVGG', 'HRNet', 'DarknetV3'] 8 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/bbox_heads/__init__.py: -------------------------------------------------------------------------------- 1 | from .bbox_head import BBoxHead 2 | from .convfc_bbox_head import ConvFCBBoxHead, SharedFCBBoxHead 3 | from .double_bbox_head import DoubleConvFCBBoxHead 4 | 5 | __all__ = [ 6 | 'BBoxHead', 'ConvFCBBoxHead', 'SharedFCBBoxHead', 'DoubleConvFCBBoxHead' 7 | ] 8 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/builder.py: -------------------------------------------------------------------------------- 1 | from torch import nn 2 | 3 | from mmdet.utils import build_from_cfg 4 | from .registry import (BACKBONES, DETECTORS, HEADS, LOSSES, NECKS, 5 | ROI_EXTRACTORS, SHARED_HEADS) 6 | 7 | 8 | def build(cfg, registry, default_args=None): 9 | if isinstance(cfg, list): 10 | modules = [ 11 | build_from_cfg(cfg_, registry, default_args) for cfg_ in cfg 12 | ] 13 | return nn.Sequential(*modules) 14 | else: 15 | return build_from_cfg(cfg, registry, default_args) 16 | 17 | 18 | def build_backbone(cfg): 19 | return build(cfg, BACKBONES) 20 | 21 | 22 | def build_neck(cfg): 23 | return build(cfg, NECKS) 24 | 25 | 26 | def build_roi_extractor(cfg): 27 | return build(cfg, ROI_EXTRACTORS) 28 | 29 | 30 | def build_shared_head(cfg): 31 | return build(cfg, SHARED_HEADS) 32 | 33 | 34 | def build_head(cfg): 35 | return build(cfg, HEADS) 36 | 37 | 38 | def build_loss(cfg): 39 | return build(cfg, LOSSES) 40 | 41 | 42 | def build_detector(cfg, train_cfg=None, test_cfg=None): 43 | return build(cfg, DETECTORS, dict(train_cfg=train_cfg, test_cfg=test_cfg)) 44 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/detectors/__init__.py: -------------------------------------------------------------------------------- 1 | from .base import BaseDetector 2 | from .cascade_rcnn import CascadeRCNN 3 | from .double_head_rcnn import DoubleHeadRCNN 4 | from .fast_rcnn import FastRCNN 5 | from .faster_rcnn import FasterRCNN 6 | from .fcos import FCOS 7 | from .fovea import FOVEA 8 | from .grid_rcnn import GridRCNN 9 | from .htc import HybridTaskCascade 10 | from .mask_rcnn import MaskRCNN 11 | from .mask_scoring_rcnn import MaskScoringRCNN 12 | from .reppoints_detector import RepPointsDetector 13 | from .retinanet import RetinaNet 14 | from .rpn import RPN 15 | from .single_stage import SingleStageDetector 16 | from .two_stage import TwoStageDetector 17 | from .ttfnet import TTFNet 18 | 19 | __all__ = [ 20 | 'BaseDetector', 'SingleStageDetector', 'TwoStageDetector', 'RPN', 21 | 'FastRCNN', 'FasterRCNN', 'MaskRCNN', 'CascadeRCNN', 'HybridTaskCascade', 22 | 'DoubleHeadRCNN', 'RetinaNet', 'FCOS', 'GridRCNN', 'MaskScoringRCNN', 23 | 'RepPointsDetector', 'FOVEA', 'TTFNet' 24 | ] 25 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/detectors/fast_rcnn.py: -------------------------------------------------------------------------------- 1 | from ..registry import DETECTORS 2 | from .two_stage import TwoStageDetector 3 | 4 | 5 | @DETECTORS.register_module 6 | class FastRCNN(TwoStageDetector): 7 | 8 | def __init__(self, 9 | backbone, 10 | bbox_roi_extractor, 11 | bbox_head, 12 | train_cfg, 13 | test_cfg, 14 | neck=None, 15 | shared_head=None, 16 | mask_roi_extractor=None, 17 | mask_head=None, 18 | pretrained=None): 19 | super(FastRCNN, self).__init__( 20 | backbone=backbone, 21 | neck=neck, 22 | shared_head=shared_head, 23 | bbox_roi_extractor=bbox_roi_extractor, 24 | bbox_head=bbox_head, 25 | train_cfg=train_cfg, 26 | test_cfg=test_cfg, 27 | mask_roi_extractor=mask_roi_extractor, 28 | mask_head=mask_head, 29 | pretrained=pretrained) 30 | 31 | def forward_test(self, imgs, img_metas, proposals, **kwargs): 32 | for var, name in [(imgs, 'imgs'), (img_metas, 'img_metas')]: 33 | if not isinstance(var, list): 34 | raise TypeError('{} must be a list, but got {}'.format( 35 | name, type(var))) 36 | 37 | num_augs = len(imgs) 38 | if num_augs != len(img_metas): 39 | raise ValueError( 40 | 'num of augmentations ({}) != num of image meta ({})'.format( 41 | len(imgs), len(img_metas))) 42 | # TODO: remove the restriction of imgs_per_gpu == 1 when prepared 43 | imgs_per_gpu = imgs[0].size(0) 44 | assert imgs_per_gpu == 1 45 | 46 | if num_augs == 1: 47 | return self.simple_test(imgs[0], img_metas[0], proposals[0], 48 | **kwargs) 49 | else: 50 | return self.aug_test(imgs, img_metas, proposals, **kwargs) 51 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/detectors/faster_rcnn.py: -------------------------------------------------------------------------------- 1 | from ..registry import DETECTORS 2 | from .two_stage import TwoStageDetector 3 | 4 | 5 | @DETECTORS.register_module 6 | class FasterRCNN(TwoStageDetector): 7 | 8 | def __init__(self, 9 | backbone, 10 | rpn_head, 11 | bbox_roi_extractor, 12 | bbox_head, 13 | train_cfg, 14 | test_cfg, 15 | neck=None, 16 | shared_head=None, 17 | pretrained=None): 18 | super(FasterRCNN, self).__init__( 19 | backbone=backbone, 20 | neck=neck, 21 | shared_head=shared_head, 22 | rpn_head=rpn_head, 23 | bbox_roi_extractor=bbox_roi_extractor, 24 | bbox_head=bbox_head, 25 | train_cfg=train_cfg, 26 | test_cfg=test_cfg, 27 | pretrained=pretrained) 28 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/detectors/fcos.py: -------------------------------------------------------------------------------- 1 | from ..registry import DETECTORS 2 | from .single_stage import SingleStageDetector 3 | 4 | 5 | @DETECTORS.register_module 6 | class FCOS(SingleStageDetector): 7 | 8 | def __init__(self, 9 | backbone, 10 | neck, 11 | bbox_head, 12 | train_cfg=None, 13 | test_cfg=None, 14 | pretrained=None): 15 | super(FCOS, self).__init__(backbone, neck, bbox_head, train_cfg, 16 | test_cfg, pretrained) 17 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/detectors/fovea.py: -------------------------------------------------------------------------------- 1 | from ..registry import DETECTORS 2 | from .single_stage import SingleStageDetector 3 | 4 | 5 | @DETECTORS.register_module 6 | class FOVEA(SingleStageDetector): 7 | 8 | def __init__(self, 9 | backbone, 10 | neck, 11 | bbox_head, 12 | train_cfg=None, 13 | test_cfg=None, 14 | pretrained=None): 15 | super(FOVEA, self).__init__(backbone, neck, bbox_head, train_cfg, 16 | test_cfg, pretrained) 17 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/detectors/mask_rcnn.py: -------------------------------------------------------------------------------- 1 | from ..registry import DETECTORS 2 | from .two_stage import TwoStageDetector 3 | 4 | 5 | @DETECTORS.register_module 6 | class MaskRCNN(TwoStageDetector): 7 | 8 | def __init__(self, 9 | backbone, 10 | rpn_head, 11 | bbox_roi_extractor, 12 | bbox_head, 13 | mask_roi_extractor, 14 | mask_head, 15 | train_cfg, 16 | test_cfg, 17 | neck=None, 18 | shared_head=None, 19 | pretrained=None): 20 | super(MaskRCNN, self).__init__( 21 | backbone=backbone, 22 | neck=neck, 23 | shared_head=shared_head, 24 | rpn_head=rpn_head, 25 | bbox_roi_extractor=bbox_roi_extractor, 26 | bbox_head=bbox_head, 27 | mask_roi_extractor=mask_roi_extractor, 28 | mask_head=mask_head, 29 | train_cfg=train_cfg, 30 | test_cfg=test_cfg, 31 | pretrained=pretrained) 32 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/detectors/retinanet.py: -------------------------------------------------------------------------------- 1 | from ..registry import DETECTORS 2 | from .single_stage import SingleStageDetector 3 | 4 | 5 | @DETECTORS.register_module 6 | class RetinaNet(SingleStageDetector): 7 | 8 | def __init__(self, 9 | backbone, 10 | neck, 11 | bbox_head, 12 | train_cfg=None, 13 | test_cfg=None, 14 | pretrained=None): 15 | super(RetinaNet, self).__init__(backbone, neck, bbox_head, train_cfg, 16 | test_cfg, pretrained) 17 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/detectors/single_stage.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | 3 | from mmdet.core import bbox2result 4 | from .. import builder 5 | from ..registry import DETECTORS 6 | from .base import BaseDetector 7 | 8 | 9 | @DETECTORS.register_module 10 | class SingleStageDetector(BaseDetector): 11 | """Base class for single-stage detectors. 12 | 13 | Single-stage detectors directly and densely predict bounding boxes on the 14 | output features of the backbone+neck. 15 | """ 16 | 17 | def __init__(self, 18 | backbone, 19 | neck=None, 20 | bbox_head=None, 21 | train_cfg=None, 22 | test_cfg=None, 23 | pretrained=None): 24 | super(SingleStageDetector, self).__init__() 25 | self.backbone = builder.build_backbone(backbone) 26 | if neck is not None: 27 | self.neck = builder.build_neck(neck) 28 | self.bbox_head = builder.build_head(bbox_head) 29 | self.train_cfg = train_cfg 30 | self.test_cfg = test_cfg 31 | self.init_weights(pretrained=pretrained) 32 | 33 | def init_weights(self, pretrained=None): 34 | super(SingleStageDetector, self).init_weights(pretrained) 35 | self.backbone.init_weights(pretrained=pretrained) 36 | if self.with_neck: 37 | if isinstance(self.neck, nn.Sequential): 38 | for m in self.neck: 39 | m.init_weights() 40 | else: 41 | self.neck.init_weights() 42 | self.bbox_head.init_weights() 43 | 44 | def extract_feat(self, img): 45 | """Directly extract features from the backbone+neck 46 | """ 47 | x = self.backbone(img) 48 | if self.with_neck: 49 | x = self.neck(x) 50 | return x 51 | 52 | def forward_dummy(self, img): 53 | """Used for computing network flops. 54 | 55 | See `mmedetection/tools/get_flops.py` 56 | """ 57 | x = self.extract_feat(img) 58 | outs = self.bbox_head(x) 59 | return outs 60 | 61 | def forward_train(self, 62 | img, 63 | img_metas, 64 | gt_bboxes, 65 | gt_labels, 66 | gt_bboxes_ignore=None): 67 | x = self.extract_feat(img) 68 | outs = self.bbox_head(x) 69 | loss_inputs = outs + (gt_bboxes, gt_labels, img_metas, self.train_cfg) 70 | losses = self.bbox_head.loss( 71 | *loss_inputs, gt_bboxes_ignore=gt_bboxes_ignore) 72 | return losses 73 | 74 | def simple_test(self, img, img_meta, rescale=False): 75 | x = self.extract_feat(img) 76 | outs = self.bbox_head(x) 77 | bbox_inputs = outs + (img_meta, self.test_cfg, rescale) 78 | bbox_list = self.bbox_head.get_bboxes(*bbox_inputs) 79 | bbox_results = [ 80 | bbox2result(det_bboxes, det_labels, self.bbox_head.num_classes) 81 | for det_bboxes, det_labels in bbox_list 82 | ] 83 | return bbox_results[0] 84 | 85 | def aug_test(self, imgs, img_metas, rescale=False): 86 | raise NotImplementedError 87 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/detectors/ttfnet.py: -------------------------------------------------------------------------------- 1 | from .single_stage import SingleStageDetector 2 | from ..registry import DETECTORS 3 | 4 | 5 | @DETECTORS.register_module 6 | class TTFNet(SingleStageDetector): 7 | 8 | def __init__(self, 9 | backbone, 10 | neck=None, 11 | bbox_head=None, 12 | train_cfg=None, 13 | test_cfg=None, 14 | pretrained=None): 15 | super(TTFNet, self).__init__(backbone, neck, bbox_head, train_cfg, 16 | test_cfg, pretrained) 17 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/losses/__init__.py: -------------------------------------------------------------------------------- 1 | from .accuracy import Accuracy, accuracy 2 | from .balanced_l1_loss import BalancedL1Loss, balanced_l1_loss 3 | from .cross_entropy_loss import (CrossEntropyLoss, binary_cross_entropy, 4 | cross_entropy, mask_cross_entropy) 5 | from .focal_loss import FocalLoss, sigmoid_focal_loss, ct_focal_loss 6 | from .ghm_loss import GHMC, GHMR 7 | from .iou_loss import BoundedIoULoss, IoULoss, bounded_iou_loss, iou_loss, giou_loss 8 | from .mse_loss import MSELoss, mse_loss 9 | from .smooth_l1_loss import SmoothL1Loss, smooth_l1_loss 10 | from .utils import reduce_loss, weight_reduce_loss, weighted_loss 11 | 12 | __all__ = [ 13 | 'accuracy', 'Accuracy', 'cross_entropy', 'binary_cross_entropy', 14 | 'mask_cross_entropy', 'CrossEntropyLoss', 'sigmoid_focal_loss', 15 | 'FocalLoss', 'smooth_l1_loss', 'SmoothL1Loss', 'balanced_l1_loss', 16 | 'BalancedL1Loss', 'mse_loss', 'MSELoss', 'iou_loss', 'bounded_iou_loss', 17 | 'IoULoss', 'BoundedIoULoss', 'GHMC', 'GHMR', 'reduce_loss', 18 | 'weight_reduce_loss', 'weighted_loss', 'ct_focal_loss', 'giou_loss' 19 | ] 20 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/losses/accuracy.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | 3 | 4 | def accuracy(pred, target, topk=1): 5 | assert isinstance(topk, (int, tuple)) 6 | if isinstance(topk, int): 7 | topk = (topk, ) 8 | return_single = True 9 | else: 10 | return_single = False 11 | 12 | maxk = max(topk) 13 | _, pred_label = pred.topk(maxk, dim=1) 14 | pred_label = pred_label.t() 15 | correct = pred_label.eq(target.view(1, -1).expand_as(pred_label)) 16 | 17 | res = [] 18 | for k in topk: 19 | correct_k = correct[:k].view(-1).float().sum(0, keepdim=True) 20 | res.append(correct_k.mul_(100.0 / pred.size(0))) 21 | return res[0] if return_single else res 22 | 23 | 24 | class Accuracy(nn.Module): 25 | 26 | def __init__(self, topk=(1, )): 27 | super().__init__() 28 | self.topk = topk 29 | 30 | def forward(self, pred, target): 31 | return accuracy(pred, target, self.topk) 32 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/losses/balanced_l1_loss.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import torch 3 | import torch.nn as nn 4 | 5 | from ..registry import LOSSES 6 | from .utils import weighted_loss 7 | 8 | 9 | @weighted_loss 10 | def balanced_l1_loss(pred, 11 | target, 12 | beta=1.0, 13 | alpha=0.5, 14 | gamma=1.5, 15 | reduction='mean'): 16 | assert beta > 0 17 | assert pred.size() == target.size() and target.numel() > 0 18 | 19 | diff = torch.abs(pred - target) 20 | b = np.e**(gamma / alpha) - 1 21 | loss = torch.where( 22 | diff < beta, alpha / b * 23 | (b * diff + 1) * torch.log(b * diff / beta + 1) - alpha * diff, 24 | gamma * diff + gamma / b - alpha * beta) 25 | 26 | return loss 27 | 28 | 29 | @LOSSES.register_module 30 | class BalancedL1Loss(nn.Module): 31 | """Balanced L1 Loss 32 | 33 | arXiv: https://arxiv.org/pdf/1904.02701.pdf (CVPR 2019) 34 | """ 35 | 36 | def __init__(self, 37 | alpha=0.5, 38 | gamma=1.5, 39 | beta=1.0, 40 | reduction='mean', 41 | loss_weight=1.0): 42 | super(BalancedL1Loss, self).__init__() 43 | self.alpha = alpha 44 | self.gamma = gamma 45 | self.beta = beta 46 | self.reduction = reduction 47 | self.loss_weight = loss_weight 48 | 49 | def forward(self, 50 | pred, 51 | target, 52 | weight=None, 53 | avg_factor=None, 54 | reduction_override=None, 55 | **kwargs): 56 | assert reduction_override in (None, 'none', 'mean', 'sum') 57 | reduction = ( 58 | reduction_override if reduction_override else self.reduction) 59 | loss_bbox = self.loss_weight * balanced_l1_loss( 60 | pred, 61 | target, 62 | weight, 63 | alpha=self.alpha, 64 | gamma=self.gamma, 65 | beta=self.beta, 66 | reduction=reduction, 67 | avg_factor=avg_factor, 68 | **kwargs) 69 | return loss_bbox 70 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/losses/mse_loss.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import torch.nn.functional as F 3 | 4 | from ..registry import LOSSES 5 | from .utils import weighted_loss 6 | 7 | mse_loss = weighted_loss(F.mse_loss) 8 | 9 | 10 | @LOSSES.register_module 11 | class MSELoss(nn.Module): 12 | 13 | def __init__(self, reduction='mean', loss_weight=1.0): 14 | super().__init__() 15 | self.reduction = reduction 16 | self.loss_weight = loss_weight 17 | 18 | def forward(self, pred, target, weight=None, avg_factor=None): 19 | loss = self.loss_weight * mse_loss( 20 | pred, 21 | target, 22 | weight, 23 | reduction=self.reduction, 24 | avg_factor=avg_factor) 25 | return loss 26 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/losses/smooth_l1_loss.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | 4 | from ..registry import LOSSES 5 | from .utils import weighted_loss 6 | 7 | 8 | @weighted_loss 9 | def smooth_l1_loss(pred, target, beta=1.0): 10 | assert beta > 0 11 | assert pred.size() == target.size() and target.numel() > 0 12 | diff = torch.abs(pred - target) 13 | loss = torch.where(diff < beta, 0.5 * diff * diff / beta, 14 | diff - 0.5 * beta) 15 | return loss 16 | 17 | 18 | @LOSSES.register_module 19 | class SmoothL1Loss(nn.Module): 20 | 21 | def __init__(self, beta=1.0, reduction='mean', loss_weight=1.0): 22 | super(SmoothL1Loss, self).__init__() 23 | self.beta = beta 24 | self.reduction = reduction 25 | self.loss_weight = loss_weight 26 | 27 | def forward(self, 28 | pred, 29 | target, 30 | weight=None, 31 | avg_factor=None, 32 | reduction_override=None, 33 | **kwargs): 34 | assert reduction_override in (None, 'none', 'mean', 'sum') 35 | reduction = ( 36 | reduction_override if reduction_override else self.reduction) 37 | loss_bbox = self.loss_weight * smooth_l1_loss( 38 | pred, 39 | target, 40 | weight, 41 | beta=self.beta, 42 | reduction=reduction, 43 | avg_factor=avg_factor, 44 | **kwargs) 45 | return loss_bbox 46 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/mask_heads/__init__.py: -------------------------------------------------------------------------------- 1 | from .fcn_mask_head import FCNMaskHead 2 | from .fused_semantic_head import FusedSemanticHead 3 | from .grid_head import GridHead 4 | from .htc_mask_head import HTCMaskHead 5 | from .maskiou_head import MaskIoUHead 6 | 7 | __all__ = [ 8 | 'FCNMaskHead', 'HTCMaskHead', 'FusedSemanticHead', 'GridHead', 9 | 'MaskIoUHead' 10 | ] 11 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/mask_heads/htc_mask_head.py: -------------------------------------------------------------------------------- 1 | from ..registry import HEADS 2 | from ..utils import ConvModule 3 | from .fcn_mask_head import FCNMaskHead 4 | 5 | 6 | @HEADS.register_module 7 | class HTCMaskHead(FCNMaskHead): 8 | 9 | def __init__(self, *args, **kwargs): 10 | super(HTCMaskHead, self).__init__(*args, **kwargs) 11 | self.conv_res = ConvModule( 12 | self.conv_out_channels, 13 | self.conv_out_channels, 14 | 1, 15 | conv_cfg=self.conv_cfg, 16 | norm_cfg=self.norm_cfg) 17 | 18 | def init_weights(self): 19 | super(HTCMaskHead, self).init_weights() 20 | self.conv_res.init_weights() 21 | 22 | def forward(self, x, res_feat=None, return_logits=True, return_feat=True): 23 | if res_feat is not None: 24 | res_feat = self.conv_res(res_feat) 25 | x = x + res_feat 26 | for conv in self.convs: 27 | x = conv(x) 28 | res_feat = x 29 | outs = [] 30 | if return_logits: 31 | x = self.upsample(x) 32 | if self.upsample_method == 'deconv': 33 | x = self.relu(x) 34 | mask_pred = self.conv_logits(x) 35 | outs.append(mask_pred) 36 | if return_feat: 37 | outs.append(res_feat) 38 | return outs if len(outs) > 1 else outs[0] 39 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/necks/__init__.py: -------------------------------------------------------------------------------- 1 | from .bfp import BFP 2 | from .fpn import FPN 3 | from .hrfpn import HRFPN 4 | 5 | __all__ = ['FPN', 'BFP', 'HRFPN'] 6 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/plugins/__init__.py: -------------------------------------------------------------------------------- 1 | from .generalized_attention import GeneralizedAttention 2 | from .non_local import NonLocal2D 3 | 4 | __all__ = ['NonLocal2D', 'GeneralizedAttention'] 5 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/registry.py: -------------------------------------------------------------------------------- 1 | from mmdet.utils import Registry 2 | 3 | BACKBONES = Registry('backbone') 4 | NECKS = Registry('neck') 5 | ROI_EXTRACTORS = Registry('roi_extractor') 6 | SHARED_HEADS = Registry('shared_head') 7 | HEADS = Registry('head') 8 | LOSSES = Registry('loss') 9 | DETECTORS = Registry('detector') 10 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/roi_extractors/__init__.py: -------------------------------------------------------------------------------- 1 | from .single_level import SingleRoIExtractor 2 | 3 | __all__ = ['SingleRoIExtractor'] 4 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/shared_heads/__init__.py: -------------------------------------------------------------------------------- 1 | from .res_layer import ResLayer 2 | 3 | __all__ = ['ResLayer'] 4 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/shared_heads/res_layer.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | import torch.nn as nn 4 | from mmcv.cnn import constant_init, kaiming_init 5 | from mmcv.runner import load_checkpoint 6 | 7 | from mmdet.core import auto_fp16 8 | from ..backbones import ResNet, make_res_layer 9 | from ..registry import SHARED_HEADS 10 | 11 | 12 | @SHARED_HEADS.register_module 13 | class ResLayer(nn.Module): 14 | 15 | def __init__(self, 16 | depth, 17 | stage=3, 18 | stride=2, 19 | dilation=1, 20 | style='pytorch', 21 | norm_cfg=dict(type='BN', requires_grad=True), 22 | norm_eval=True, 23 | with_cp=False, 24 | dcn=None): 25 | super(ResLayer, self).__init__() 26 | self.norm_eval = norm_eval 27 | self.norm_cfg = norm_cfg 28 | self.stage = stage 29 | self.fp16_enabled = False 30 | block, stage_blocks = ResNet.arch_settings[depth] 31 | stage_block = stage_blocks[stage] 32 | planes = 64 * 2**stage 33 | inplanes = 64 * 2**(stage - 1) * block.expansion 34 | 35 | res_layer = make_res_layer( 36 | block, 37 | inplanes, 38 | planes, 39 | stage_block, 40 | stride=stride, 41 | dilation=dilation, 42 | style=style, 43 | with_cp=with_cp, 44 | norm_cfg=self.norm_cfg, 45 | dcn=dcn) 46 | self.add_module('layer{}'.format(stage + 1), res_layer) 47 | 48 | def init_weights(self, pretrained=None): 49 | if isinstance(pretrained, str): 50 | logger = logging.getLogger() 51 | load_checkpoint(self, pretrained, strict=False, logger=logger) 52 | elif pretrained is None: 53 | for m in self.modules(): 54 | if isinstance(m, nn.Conv2d): 55 | kaiming_init(m) 56 | elif isinstance(m, nn.BatchNorm2d): 57 | constant_init(m, 1) 58 | else: 59 | raise TypeError('pretrained must be a str or None') 60 | 61 | @auto_fp16() 62 | def forward(self, x): 63 | res_layer = getattr(self, 'layer{}'.format(self.stage + 1)) 64 | out = res_layer(x) 65 | return out 66 | 67 | def train(self, mode=True): 68 | super(ResLayer, self).train(mode) 69 | if self.norm_eval: 70 | for m in self.modules(): 71 | if isinstance(m, nn.BatchNorm2d): 72 | m.eval() 73 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .conv_module import ConvModule, build_conv_layer 2 | from .conv_ws import ConvWS2d, conv_ws_2d 3 | from .norm import build_norm_layer 4 | from .scale import Scale 5 | from .weight_init import (bias_init_with_prob, kaiming_init, normal_init, 6 | uniform_init, xavier_init) 7 | 8 | __all__ = [ 9 | 'conv_ws_2d', 'ConvWS2d', 'build_conv_layer', 'ConvModule', 10 | 'build_norm_layer', 'xavier_init', 'normal_init', 'uniform_init', 11 | 'kaiming_init', 'bias_init_with_prob', 'Scale' 12 | ] 13 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/utils/conv_ws.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import torch.nn.functional as F 3 | 4 | 5 | def conv_ws_2d(input, 6 | weight, 7 | bias=None, 8 | stride=1, 9 | padding=0, 10 | dilation=1, 11 | groups=1, 12 | eps=1e-5): 13 | c_in = weight.size(0) 14 | weight_flat = weight.view(c_in, -1) 15 | mean = weight_flat.mean(dim=1, keepdim=True).view(c_in, 1, 1, 1) 16 | std = weight_flat.std(dim=1, keepdim=True).view(c_in, 1, 1, 1) 17 | weight = (weight - mean) / (std + eps) 18 | return F.conv2d(input, weight, bias, stride, padding, dilation, groups) 19 | 20 | 21 | class ConvWS2d(nn.Conv2d): 22 | 23 | def __init__(self, 24 | in_channels, 25 | out_channels, 26 | kernel_size, 27 | stride=1, 28 | padding=0, 29 | dilation=1, 30 | groups=1, 31 | bias=True, 32 | eps=1e-5): 33 | super(ConvWS2d, self).__init__( 34 | in_channels, 35 | out_channels, 36 | kernel_size, 37 | stride=stride, 38 | padding=padding, 39 | dilation=dilation, 40 | groups=groups, 41 | bias=bias) 42 | self.eps = eps 43 | 44 | def forward(self, x): 45 | return conv_ws_2d(x, self.weight, self.bias, self.stride, self.padding, 46 | self.dilation, self.groups, self.eps) 47 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/utils/norm.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | 3 | norm_cfg = { 4 | # format: layer_type: (abbreviation, module) 5 | 'BN': ('bn', nn.BatchNorm2d), 6 | 'SyncBN': ('bn', nn.SyncBatchNorm), 7 | 'GN': ('gn', nn.GroupNorm), 8 | # and potentially 'SN' 9 | } 10 | 11 | 12 | def build_norm_layer(cfg, num_features, postfix=''): 13 | """ Build normalization layer 14 | 15 | Args: 16 | cfg (dict): cfg should contain: 17 | type (str): identify norm layer type. 18 | layer args: args needed to instantiate a norm layer. 19 | requires_grad (bool): [optional] whether stop gradient updates 20 | num_features (int): number of channels from input. 21 | postfix (int, str): appended into norm abbreviation to 22 | create named layer. 23 | 24 | Returns: 25 | name (str): abbreviation + postfix 26 | layer (nn.Module): created norm layer 27 | """ 28 | assert isinstance(cfg, dict) and 'type' in cfg 29 | cfg_ = cfg.copy() 30 | 31 | layer_type = cfg_.pop('type') 32 | if layer_type not in norm_cfg: 33 | raise KeyError('Unrecognized norm type {}'.format(layer_type)) 34 | else: 35 | abbr, norm_layer = norm_cfg[layer_type] 36 | if norm_layer is None: 37 | raise NotImplementedError 38 | 39 | assert isinstance(postfix, (int, str)) 40 | name = abbr + str(postfix) 41 | 42 | requires_grad = cfg_.pop('requires_grad', True) 43 | cfg_.setdefault('eps', 1e-5) 44 | if layer_type != 'GN': 45 | layer = norm_layer(num_features, **cfg_) 46 | if layer_type == 'SyncBN': 47 | layer._specify_ddp_gpu_num(1) 48 | else: 49 | assert 'num_groups' in cfg_ 50 | layer = norm_layer(num_channels=num_features, **cfg_) 51 | 52 | for param in layer.parameters(): 53 | param.requires_grad = requires_grad 54 | 55 | return name, layer 56 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/utils/scale.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | 4 | 5 | class Scale(nn.Module): 6 | """ 7 | A learnable scale parameter 8 | """ 9 | 10 | def __init__(self, scale=1.0): 11 | super(Scale, self).__init__() 12 | self.scale = nn.Parameter(torch.tensor(scale, dtype=torch.float)) 13 | 14 | def forward(self, x): 15 | return x * self.scale 16 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/models/utils/weight_init.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import torch.nn as nn 3 | 4 | 5 | def xavier_init(module, gain=1, bias=0, distribution='normal'): 6 | assert distribution in ['uniform', 'normal'] 7 | if distribution == 'uniform': 8 | nn.init.xavier_uniform_(module.weight, gain=gain) 9 | else: 10 | nn.init.xavier_normal_(module.weight, gain=gain) 11 | if hasattr(module, 'bias'): 12 | nn.init.constant_(module.bias, bias) 13 | 14 | 15 | def normal_init(module, mean=0, std=1, bias=0): 16 | nn.init.normal_(module.weight, mean, std) 17 | if hasattr(module, 'bias'): 18 | nn.init.constant_(module.bias, bias) 19 | 20 | 21 | def uniform_init(module, a=0, b=1, bias=0): 22 | nn.init.uniform_(module.weight, a, b) 23 | if hasattr(module, 'bias'): 24 | nn.init.constant_(module.bias, bias) 25 | 26 | 27 | def kaiming_init(module, 28 | mode='fan_out', 29 | nonlinearity='relu', 30 | bias=0, 31 | distribution='normal'): 32 | assert distribution in ['uniform', 'normal'] 33 | if distribution == 'uniform': 34 | nn.init.kaiming_uniform_( 35 | module.weight, mode=mode, nonlinearity=nonlinearity) 36 | else: 37 | nn.init.kaiming_normal_( 38 | module.weight, mode=mode, nonlinearity=nonlinearity) 39 | if hasattr(module, 'bias'): 40 | nn.init.constant_(module.bias, bias) 41 | 42 | 43 | def bias_init_with_prob(prior_prob): 44 | """ initialize conv/fc bias value according to giving probablity""" 45 | bias_init = float(-np.log((1 - prior_prob) / prior_prob)) 46 | return bias_init 47 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/ops/__init__.py: -------------------------------------------------------------------------------- 1 | from .context_block import ContextBlock 2 | from .dcn import (DeformConv, DeformConvPack, DeformRoIPooling, 3 | DeformRoIPoolingPack, ModulatedDeformConv, 4 | ModulatedDeformConvPack, ModulatedDeformRoIPoolingPack, 5 | deform_conv, deform_roi_pooling, modulated_deform_conv) 6 | from .masked_conv import MaskedConv2d 7 | from .nms import nms, soft_nms 8 | from .roi_align import RoIAlign, roi_align 9 | from .roi_pool import RoIPool, roi_pool 10 | from .sigmoid_focal_loss import SigmoidFocalLoss, sigmoid_focal_loss 11 | 12 | __all__ = [ 13 | 'nms', 'soft_nms', 'RoIAlign', 'roi_align', 'RoIPool', 'roi_pool', 14 | 'DeformConv', 'DeformConvPack', 'DeformRoIPooling', 'DeformRoIPoolingPack', 15 | 'ModulatedDeformRoIPoolingPack', 'ModulatedDeformConv', 16 | 'ModulatedDeformConvPack', 'deform_conv', 'modulated_deform_conv', 17 | 'deform_roi_pooling', 'SigmoidFocalLoss', 'sigmoid_focal_loss', 18 | 'MaskedConv2d', 'ContextBlock' 19 | ] 20 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/ops/dcn/__init__.py: -------------------------------------------------------------------------------- 1 | from .deform_conv import (DeformConv, DeformConvPack, ModulatedDeformConv, 2 | ModulatedDeformConvPack, deform_conv, 3 | modulated_deform_conv) 4 | from .deform_pool import (DeformRoIPooling, DeformRoIPoolingPack, 5 | ModulatedDeformRoIPoolingPack, deform_roi_pooling) 6 | 7 | __all__ = [ 8 | 'DeformConv', 'DeformConvPack', 'ModulatedDeformConv', 9 | 'ModulatedDeformConvPack', 'DeformRoIPooling', 'DeformRoIPoolingPack', 10 | 'ModulatedDeformRoIPoolingPack', 'deform_conv', 'modulated_deform_conv', 11 | 'deform_roi_pooling' 12 | ] 13 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/ops/masked_conv/__init__.py: -------------------------------------------------------------------------------- 1 | from .masked_conv import MaskedConv2d, masked_conv2d 2 | 3 | __all__ = ['masked_conv2d', 'MaskedConv2d'] 4 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/ops/masked_conv/src/masked_conv2d_cuda.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | int MaskedIm2colForwardLaucher(const at::Tensor im, const int height, 7 | const int width, const int channels, 8 | const int kernel_h, const int kernel_w, 9 | const int pad_h, const int pad_w, 10 | const at::Tensor mask_h_idx, 11 | const at::Tensor mask_w_idx, const int mask_cnt, 12 | at::Tensor col); 13 | 14 | int MaskedCol2imForwardLaucher(const at::Tensor col, const int height, 15 | const int width, const int channels, 16 | const at::Tensor mask_h_idx, 17 | const at::Tensor mask_w_idx, const int mask_cnt, 18 | at::Tensor im); 19 | 20 | #define CHECK_CUDA(x) AT_CHECK(x.type().is_cuda(), #x, " must be a CUDAtensor ") 21 | #define CHECK_CONTIGUOUS(x) \ 22 | AT_CHECK(x.is_contiguous(), #x, " must be contiguous ") 23 | #define CHECK_INPUT(x) \ 24 | CHECK_CUDA(x); \ 25 | CHECK_CONTIGUOUS(x) 26 | 27 | int masked_im2col_forward_cuda(const at::Tensor im, const at::Tensor mask_h_idx, 28 | const at::Tensor mask_w_idx, const int kernel_h, 29 | const int kernel_w, const int pad_h, 30 | const int pad_w, at::Tensor col) { 31 | CHECK_INPUT(im); 32 | CHECK_INPUT(mask_h_idx); 33 | CHECK_INPUT(mask_w_idx); 34 | CHECK_INPUT(col); 35 | // im: (n, ic, h, w), kernel size (kh, kw) 36 | // kernel: (oc, ic * kh * kw), col: (kh * kw * ic, ow * oh) 37 | 38 | int channels = im.size(1); 39 | int height = im.size(2); 40 | int width = im.size(3); 41 | int mask_cnt = mask_h_idx.size(0); 42 | 43 | MaskedIm2colForwardLaucher(im, height, width, channels, kernel_h, kernel_w, 44 | pad_h, pad_w, mask_h_idx, mask_w_idx, mask_cnt, 45 | col); 46 | 47 | return 1; 48 | } 49 | 50 | int masked_col2im_forward_cuda(const at::Tensor col, 51 | const at::Tensor mask_h_idx, 52 | const at::Tensor mask_w_idx, int height, 53 | int width, int channels, at::Tensor im) { 54 | CHECK_INPUT(col); 55 | CHECK_INPUT(mask_h_idx); 56 | CHECK_INPUT(mask_w_idx); 57 | CHECK_INPUT(im); 58 | // im: (n, ic, h, w), kernel size (kh, kw) 59 | // kernel: (oc, ic * kh * kh), col: (kh * kw * ic, ow * oh) 60 | 61 | int mask_cnt = mask_h_idx.size(0); 62 | 63 | MaskedCol2imForwardLaucher(col, height, width, channels, mask_h_idx, 64 | mask_w_idx, mask_cnt, im); 65 | 66 | return 1; 67 | } 68 | 69 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 70 | m.def("masked_im2col_forward", &masked_im2col_forward_cuda, 71 | "masked_im2col forward (CUDA)"); 72 | m.def("masked_col2im_forward", &masked_col2im_forward_cuda, 73 | "masked_col2im forward (CUDA)"); 74 | } -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/ops/nms/__init__.py: -------------------------------------------------------------------------------- 1 | from .nms_wrapper import nms, soft_nms, simple_nms 2 | 3 | __all__ = ['nms', 'soft_nms', 'simple_nms'] 4 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/ops/nms/src/nms_cpu.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | #include 3 | 4 | template 5 | at::Tensor nms_cpu_kernel(const at::Tensor& dets, const float threshold) { 6 | AT_ASSERTM(!dets.type().is_cuda(), "dets must be a CPU tensor"); 7 | 8 | if (dets.numel() == 0) { 9 | return at::empty({0}, dets.options().dtype(at::kLong).device(at::kCPU)); 10 | } 11 | 12 | auto x1_t = dets.select(1, 0).contiguous(); 13 | auto y1_t = dets.select(1, 1).contiguous(); 14 | auto x2_t = dets.select(1, 2).contiguous(); 15 | auto y2_t = dets.select(1, 3).contiguous(); 16 | auto scores = dets.select(1, 4).contiguous(); 17 | 18 | at::Tensor areas_t = (x2_t - x1_t + 1) * (y2_t - y1_t + 1); 19 | 20 | auto order_t = std::get<1>(scores.sort(0, /* descending=*/true)); 21 | 22 | auto ndets = dets.size(0); 23 | at::Tensor suppressed_t = 24 | at::zeros({ndets}, dets.options().dtype(at::kByte).device(at::kCPU)); 25 | 26 | auto suppressed = suppressed_t.data(); 27 | auto order = order_t.data(); 28 | auto x1 = x1_t.data(); 29 | auto y1 = y1_t.data(); 30 | auto x2 = x2_t.data(); 31 | auto y2 = y2_t.data(); 32 | auto areas = areas_t.data(); 33 | 34 | for (int64_t _i = 0; _i < ndets; _i++) { 35 | auto i = order[_i]; 36 | if (suppressed[i] == 1) continue; 37 | auto ix1 = x1[i]; 38 | auto iy1 = y1[i]; 39 | auto ix2 = x2[i]; 40 | auto iy2 = y2[i]; 41 | auto iarea = areas[i]; 42 | 43 | for (int64_t _j = _i + 1; _j < ndets; _j++) { 44 | auto j = order[_j]; 45 | if (suppressed[j] == 1) continue; 46 | auto xx1 = std::max(ix1, x1[j]); 47 | auto yy1 = std::max(iy1, y1[j]); 48 | auto xx2 = std::min(ix2, x2[j]); 49 | auto yy2 = std::min(iy2, y2[j]); 50 | 51 | auto w = std::max(static_cast(0), xx2 - xx1 + 1); 52 | auto h = std::max(static_cast(0), yy2 - yy1 + 1); 53 | auto inter = w * h; 54 | auto ovr = inter / (iarea + areas[j] - inter); 55 | if (ovr >= threshold) suppressed[j] = 1; 56 | } 57 | } 58 | return at::nonzero(suppressed_t == 0).squeeze(1); 59 | } 60 | 61 | at::Tensor nms(const at::Tensor& dets, const float threshold) { 62 | at::Tensor result; 63 | AT_DISPATCH_FLOATING_TYPES(dets.scalar_type(), "nms", [&] { 64 | result = nms_cpu_kernel(dets, threshold); 65 | }); 66 | return result; 67 | } 68 | 69 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 70 | m.def("nms", &nms, "non-maximum suppression"); 71 | } -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/ops/nms/src/nms_cuda.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | #include 3 | 4 | #define CHECK_CUDA(x) AT_CHECK(x.type().is_cuda(), #x, " must be a CUDAtensor ") 5 | 6 | at::Tensor nms_cuda(const at::Tensor boxes, float nms_overlap_thresh); 7 | 8 | at::Tensor nms(const at::Tensor& dets, const float threshold) { 9 | CHECK_CUDA(dets); 10 | if (dets.numel() == 0) 11 | return at::empty({0}, dets.options().dtype(at::kLong).device(at::kCPU)); 12 | return nms_cuda(dets, threshold); 13 | } 14 | 15 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 16 | m.def("nms", &nms, "non-maximum suppression"); 17 | } -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/ops/roi_align/__init__.py: -------------------------------------------------------------------------------- 1 | from .roi_align import RoIAlign, roi_align 2 | 3 | __all__ = ['roi_align', 'RoIAlign'] 4 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/ops/roi_align/gradcheck.py: -------------------------------------------------------------------------------- 1 | import os.path as osp 2 | import sys 3 | 4 | import numpy as np 5 | import torch 6 | from torch.autograd import gradcheck 7 | 8 | sys.path.append(osp.abspath(osp.join(__file__, '../../'))) 9 | from roi_align import RoIAlign # noqa: E402, isort:skip 10 | 11 | feat_size = 15 12 | spatial_scale = 1.0 / 8 13 | img_size = feat_size / spatial_scale 14 | num_imgs = 2 15 | num_rois = 20 16 | 17 | batch_ind = np.random.randint(num_imgs, size=(num_rois, 1)) 18 | rois = np.random.rand(num_rois, 4) * img_size * 0.5 19 | rois[:, 2:] += img_size * 0.5 20 | rois = np.hstack((batch_ind, rois)) 21 | 22 | feat = torch.randn( 23 | num_imgs, 16, feat_size, feat_size, requires_grad=True, device='cuda:0') 24 | rois = torch.from_numpy(rois).float().cuda() 25 | inputs = (feat, rois) 26 | print('Gradcheck for roi align...') 27 | test = gradcheck(RoIAlign(3, spatial_scale), inputs, atol=1e-3, eps=1e-3) 28 | print(test) 29 | test = gradcheck(RoIAlign(3, spatial_scale, 2), inputs, atol=1e-3, eps=1e-3) 30 | print(test) 31 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/ops/roi_pool/__init__.py: -------------------------------------------------------------------------------- 1 | from .roi_pool import RoIPool, roi_pool 2 | 3 | __all__ = ['roi_pool', 'RoIPool'] 4 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/ops/roi_pool/gradcheck.py: -------------------------------------------------------------------------------- 1 | import os.path as osp 2 | import sys 3 | 4 | import torch 5 | from torch.autograd import gradcheck 6 | 7 | sys.path.append(osp.abspath(osp.join(__file__, '../../'))) 8 | from roi_pool import RoIPool # noqa: E402, isort:skip 9 | 10 | feat = torch.randn(4, 16, 15, 15, requires_grad=True).cuda() 11 | rois = torch.Tensor([[0, 0, 0, 50, 50], [0, 10, 30, 43, 55], 12 | [1, 67, 40, 110, 120]]).cuda() 13 | inputs = (feat, rois) 14 | print('Gradcheck for roi pooling...') 15 | test = gradcheck(RoIPool(4, 1.0 / 8), inputs, eps=1e-5, atol=1e-3) 16 | print(test) 17 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/ops/roi_pool/roi_pool.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | from torch.autograd import Function 4 | from torch.autograd.function import once_differentiable 5 | from torch.nn.modules.utils import _pair 6 | 7 | from . import roi_pool_cuda 8 | 9 | 10 | class RoIPoolFunction(Function): 11 | 12 | @staticmethod 13 | def forward(ctx, features, rois, out_size, spatial_scale): 14 | assert features.is_cuda 15 | out_h, out_w = _pair(out_size) 16 | assert isinstance(out_h, int) and isinstance(out_w, int) 17 | ctx.save_for_backward(rois) 18 | num_channels = features.size(1) 19 | num_rois = rois.size(0) 20 | out_size = (num_rois, num_channels, out_h, out_w) 21 | output = features.new_zeros(out_size) 22 | argmax = features.new_zeros(out_size, dtype=torch.int) 23 | roi_pool_cuda.forward(features, rois, out_h, out_w, spatial_scale, 24 | output, argmax) 25 | ctx.spatial_scale = spatial_scale 26 | ctx.feature_size = features.size() 27 | ctx.argmax = argmax 28 | 29 | return output 30 | 31 | @staticmethod 32 | @once_differentiable 33 | def backward(ctx, grad_output): 34 | assert grad_output.is_cuda 35 | spatial_scale = ctx.spatial_scale 36 | feature_size = ctx.feature_size 37 | argmax = ctx.argmax 38 | rois = ctx.saved_tensors[0] 39 | assert feature_size is not None 40 | 41 | grad_input = grad_rois = None 42 | if ctx.needs_input_grad[0]: 43 | grad_input = grad_output.new_zeros(feature_size) 44 | roi_pool_cuda.backward(grad_output.contiguous(), rois, argmax, 45 | spatial_scale, grad_input) 46 | 47 | return grad_input, grad_rois, None, None 48 | 49 | 50 | roi_pool = RoIPoolFunction.apply 51 | 52 | 53 | class RoIPool(nn.Module): 54 | 55 | def __init__(self, out_size, spatial_scale, use_torchvision=False): 56 | super(RoIPool, self).__init__() 57 | 58 | self.out_size = _pair(out_size) 59 | self.spatial_scale = float(spatial_scale) 60 | self.use_torchvision = use_torchvision 61 | 62 | def forward(self, features, rois): 63 | if self.use_torchvision: 64 | from torchvision.ops import roi_pool as tv_roi_pool 65 | return tv_roi_pool(features, rois, self.out_size, 66 | self.spatial_scale) 67 | else: 68 | return roi_pool(features, rois, self.out_size, self.spatial_scale) 69 | 70 | def __repr__(self): 71 | format_str = self.__class__.__name__ 72 | format_str += '(out_size={}, spatial_scale={}'.format( 73 | self.out_size, self.spatial_scale) 74 | format_str += ', use_torchvision={})'.format(self.use_torchvision) 75 | return format_str 76 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/ops/sigmoid_focal_loss/__init__.py: -------------------------------------------------------------------------------- 1 | from .sigmoid_focal_loss import SigmoidFocalLoss, sigmoid_focal_loss 2 | 3 | __all__ = ['SigmoidFocalLoss', 'sigmoid_focal_loss'] 4 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/ops/sigmoid_focal_loss/sigmoid_focal_loss.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | from torch.autograd import Function 3 | from torch.autograd.function import once_differentiable 4 | 5 | from . import sigmoid_focal_loss_cuda 6 | 7 | 8 | class SigmoidFocalLossFunction(Function): 9 | 10 | @staticmethod 11 | def forward(ctx, input, target, gamma=2.0, alpha=0.25): 12 | ctx.save_for_backward(input, target) 13 | num_classes = input.shape[1] 14 | ctx.num_classes = num_classes 15 | ctx.gamma = gamma 16 | ctx.alpha = alpha 17 | 18 | loss = sigmoid_focal_loss_cuda.forward(input, target, num_classes, 19 | gamma, alpha) 20 | return loss 21 | 22 | @staticmethod 23 | @once_differentiable 24 | def backward(ctx, d_loss): 25 | input, target = ctx.saved_tensors 26 | num_classes = ctx.num_classes 27 | gamma = ctx.gamma 28 | alpha = ctx.alpha 29 | d_loss = d_loss.contiguous() 30 | d_input = sigmoid_focal_loss_cuda.backward(input, target, d_loss, 31 | num_classes, gamma, alpha) 32 | return d_input, None, None, None, None 33 | 34 | 35 | sigmoid_focal_loss = SigmoidFocalLossFunction.apply 36 | 37 | 38 | # TODO: remove this module 39 | class SigmoidFocalLoss(nn.Module): 40 | 41 | def __init__(self, gamma, alpha): 42 | super(SigmoidFocalLoss, self).__init__() 43 | self.gamma = gamma 44 | self.alpha = alpha 45 | 46 | def forward(self, logits, targets): 47 | assert logits.is_cuda 48 | loss = sigmoid_focal_loss(logits, targets, self.gamma, self.alpha) 49 | return loss.sum() 50 | 51 | def __repr__(self): 52 | tmpstr = self.__class__.__name__ + '(gamma={}, alpha={})'.format( 53 | self.gamma, self.alpha) 54 | return tmpstr 55 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/ops/sigmoid_focal_loss/src/sigmoid_focal_loss.cpp: -------------------------------------------------------------------------------- 1 | // modify from 2 | // https://github.com/facebookresearch/maskrcnn-benchmark/blob/master/maskrcnn_benchmark/csrc/SigmoidFocalLoss.h 3 | #include 4 | 5 | at::Tensor SigmoidFocalLoss_forward_cuda(const at::Tensor &logits, 6 | const at::Tensor &targets, 7 | const int num_classes, 8 | const float gamma, const float alpha); 9 | 10 | at::Tensor SigmoidFocalLoss_backward_cuda(const at::Tensor &logits, 11 | const at::Tensor &targets, 12 | const at::Tensor &d_losses, 13 | const int num_classes, 14 | const float gamma, const float alpha); 15 | 16 | // Interface for Python 17 | at::Tensor SigmoidFocalLoss_forward(const at::Tensor &logits, 18 | const at::Tensor &targets, 19 | const int num_classes, const float gamma, 20 | const float alpha) { 21 | if (logits.type().is_cuda()) { 22 | return SigmoidFocalLoss_forward_cuda(logits, targets, num_classes, gamma, 23 | alpha); 24 | } 25 | AT_ERROR("SigmoidFocalLoss is not implemented on the CPU"); 26 | } 27 | 28 | at::Tensor SigmoidFocalLoss_backward(const at::Tensor &logits, 29 | const at::Tensor &targets, 30 | const at::Tensor &d_losses, 31 | const int num_classes, const float gamma, 32 | const float alpha) { 33 | if (logits.type().is_cuda()) { 34 | return SigmoidFocalLoss_backward_cuda(logits, targets, d_losses, 35 | num_classes, gamma, alpha); 36 | } 37 | AT_ERROR("SigmoidFocalLoss is not implemented on the CPU"); 38 | } 39 | 40 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 41 | m.def("forward", &SigmoidFocalLoss_forward, 42 | "SigmoidFocalLoss forward (CUDA)"); 43 | m.def("backward", &SigmoidFocalLoss_backward, 44 | "SigmoidFocalLoss backward (CUDA)"); 45 | } 46 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .flops_counter import get_model_complexity_info 2 | from .registry import Registry, build_from_cfg 3 | 4 | __all__ = ['Registry', 'build_from_cfg', 'get_model_complexity_info'] 5 | -------------------------------------------------------------------------------- /_submodules/mmdetection/mmdet/utils/registry.py: -------------------------------------------------------------------------------- 1 | import inspect 2 | 3 | import mmcv 4 | 5 | 6 | class Registry(object): 7 | 8 | def __init__(self, name): 9 | self._name = name 10 | self._module_dict = dict() 11 | 12 | def __repr__(self): 13 | format_str = self.__class__.__name__ + '(name={}, items={})'.format( 14 | self._name, list(self._module_dict.keys())) 15 | return format_str 16 | 17 | @property 18 | def name(self): 19 | return self._name 20 | 21 | @property 22 | def module_dict(self): 23 | return self._module_dict 24 | 25 | def get(self, key): 26 | return self._module_dict.get(key, None) 27 | 28 | def _register_module(self, module_class): 29 | """Register a module. 30 | 31 | Args: 32 | module (:obj:`nn.Module`): Module to be registered. 33 | """ 34 | if not inspect.isclass(module_class): 35 | raise TypeError('module must be a class, but got {}'.format( 36 | type(module_class))) 37 | module_name = module_class.__name__ 38 | if module_name in self._module_dict: 39 | raise KeyError('{} is already registered in {}'.format( 40 | module_name, self.name)) 41 | self._module_dict[module_name] = module_class 42 | 43 | def register_module(self, cls): 44 | self._register_module(cls) 45 | return cls 46 | 47 | 48 | def build_from_cfg(cfg, registry, default_args=None): 49 | """Build a module from config dict. 50 | 51 | Args: 52 | cfg (dict): Config dict. It should at least contain the key "type". 53 | registry (:obj:`Registry`): The registry to search the type from. 54 | default_args (dict, optional): Default initialization arguments. 55 | 56 | Returns: 57 | obj: The constructed object. 58 | """ 59 | assert isinstance(cfg, dict) and 'type' in cfg 60 | assert isinstance(default_args, dict) or default_args is None 61 | args = cfg.copy() 62 | obj_type = args.pop('type') 63 | if mmcv.is_str(obj_type): 64 | obj_cls = registry.get(obj_type) 65 | if obj_cls is None: 66 | raise KeyError('{} is not in the {} registry'.format( 67 | obj_type, registry.name)) 68 | elif inspect.isclass(obj_type): 69 | obj_cls = obj_type 70 | else: 71 | raise TypeError('type must be a str or valid type, but got {}'.format( 72 | type(obj_type))) 73 | if default_args is not None: 74 | for name, value in default_args.items(): 75 | args.setdefault(name, value) 76 | return obj_cls(**args) 77 | -------------------------------------------------------------------------------- /_submodules/mmdetection/pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | addopts = --xdoctest --xdoctest-style=auto 3 | norecursedirs = .git ignore build __pycache__ data docker docs .eggs 4 | 5 | filterwarnings= default 6 | ignore:.*No cfgstr given in Cacher constructor or call.*:Warning 7 | ignore:.*Define the __nice__ method for.*:Warning 8 | -------------------------------------------------------------------------------- /_submodules/mmdetection/requirements.txt: -------------------------------------------------------------------------------- 1 | mmcv>=0.2.10 2 | numpy 3 | matplotlib 4 | six 5 | terminaltables 6 | pycocotools 7 | torch>=1.1 8 | torchvision 9 | imagecorruptions 10 | albumentations>=0.3.2 -------------------------------------------------------------------------------- /_submodules/mmdetection/tests/requirements.txt: -------------------------------------------------------------------------------- 1 | isort 2 | flake8 3 | yapf 4 | pytest-cov 5 | codecov 6 | xdoctest >= 0.10.0 7 | -------------------------------------------------------------------------------- /_submodules/mmdetection/tests/test_utils.py: -------------------------------------------------------------------------------- 1 | import numpy.testing as npt 2 | 3 | from mmdet.utils.flops_counter import params_to_string 4 | 5 | 6 | def test_params_to_string(): 7 | npt.assert_equal(params_to_string(1e9), '1000.0 M') 8 | npt.assert_equal(params_to_string(2e5), '200.0 k') 9 | npt.assert_equal(params_to_string(3e-9), '3e-09') 10 | -------------------------------------------------------------------------------- /_submodules/mmdetection/tools/coco_eval.py: -------------------------------------------------------------------------------- 1 | from argparse import ArgumentParser 2 | 3 | from mmdet.core import coco_eval 4 | 5 | 6 | def main(): 7 | parser = ArgumentParser(description='COCO Evaluation') 8 | parser.add_argument('result', help='result file path') 9 | parser.add_argument('--ann', help='annotation file path') 10 | parser.add_argument( 11 | '--types', 12 | type=str, 13 | nargs='+', 14 | choices=['proposal_fast', 'proposal', 'bbox', 'segm', 'keypoint'], 15 | default=['bbox'], 16 | help='result types') 17 | parser.add_argument( 18 | '--max-dets', 19 | type=int, 20 | nargs='+', 21 | default=[100, 300, 1000], 22 | help='proposal numbers, only used for recall evaluation') 23 | args = parser.parse_args() 24 | coco_eval(args.result, args.types, args.ann, args.max_dets) 25 | 26 | 27 | if __name__ == '__main__': 28 | main() 29 | -------------------------------------------------------------------------------- /_submodules/mmdetection/tools/demo.py: -------------------------------------------------------------------------------- 1 | import mmdet.apis as apis 2 | import mmcv 3 | 4 | 5 | def faster_rcnn(): 6 | cfg_file = 'configs/faster_rcnn_r50_fpn_1x.py' 7 | ckp_file = '../../checkpoints/' \ 8 | 'faster_rcnn_r50_fpn_2x_20181010-443129e1.pth' 9 | model = apis.init_detector(cfg_file, ckp_file, device='cuda:0') 10 | 11 | img_file = '/home/lhhuang/data/VOCdevkit/VOC2007/JPEGImages/007663.jpg' 12 | img = mmcv.imread(img_file) 13 | result = apis.inference_detector(model, img) 14 | 15 | out_file = 'out.jpg' 16 | apis.show_result( 17 | img, result, model.CLASSES, 18 | show=False, out_file=out_file) 19 | 20 | 21 | def mask_rcnn(): 22 | cfg_file = 'configs/mask_rcnn_r50_fpn_1x.py' 23 | ckp_file = '../../checkpoints/' \ 24 | 'mask_rcnn_r50_fpn_1x_20181010-069fa190.pth' 25 | model = apis.init_detector(cfg_file, ckp_file, device='cuda:0') 26 | 27 | img_file = '/home/lhhuang/data/coco/val2017/000000397133.jpg' 28 | img = mmcv.imread(img_file) 29 | result = apis.inference_detector(model, img) 30 | 31 | out_file = 'out.jpg' 32 | apis.show_result( 33 | img, result, model.CLASSES, 34 | show=False, out_file=out_file) 35 | 36 | 37 | if __name__ == '__main__': 38 | mask_rcnn() 39 | -------------------------------------------------------------------------------- /_submodules/mmdetection/tools/dist_test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PYTHON=${PYTHON:-"python"} 4 | 5 | CONFIG=$1 6 | CHECKPOINT=$2 7 | GPUS=$3 8 | 9 | $PYTHON -m torch.distributed.launch --nproc_per_node=$GPUS \ 10 | $(dirname "$0")/test.py $CONFIG $CHECKPOINT --launcher pytorch ${@:4} 11 | -------------------------------------------------------------------------------- /_submodules/mmdetection/tools/dist_test_ttfnet.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PYTHON=${PYTHON:-"python"} 4 | 5 | CONFIG=$1 6 | CHECKPOINT=$2 7 | GPUS=$3 8 | 9 | $PYTHON -m torch.distributed.launch --nproc_per_node=$GPUS \ 10 | $(dirname "$0")/test.py $CONFIG $CHECKPOINT --launcher pytorch ${@:4} --out tmp.pkl --eval bbox 11 | -------------------------------------------------------------------------------- /_submodules/mmdetection/tools/dist_train.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PYTHON=${PYTHON:-"python"} 4 | 5 | CONFIG=$1 6 | GPUS=$2 7 | 8 | $PYTHON -m torch.distributed.launch --nproc_per_node=$GPUS \ 9 | $(dirname "$0")/train.py $CONFIG --launcher pytorch ${@:3} 10 | -------------------------------------------------------------------------------- /_submodules/mmdetection/tools/dist_train_ttfnet.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PYTHON=${PYTHON:-"python"} 4 | 5 | CONFIG=$1 6 | GPUS=$2 7 | 8 | $PYTHON -m torch.distributed.launch --nproc_per_node=$GPUS \ 9 | --master_port=$((RANDOM + 10000)) \ 10 | $(dirname "$0")/train.py $CONFIG --validate --launcher pytorch ${@:3} --autoscale-lr --gpus=$GPUS 11 | -------------------------------------------------------------------------------- /_submodules/mmdetection/tools/get_flops.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | from mmcv import Config 4 | 5 | from mmdet.models import build_detector 6 | from mmdet.utils import get_model_complexity_info 7 | 8 | 9 | def parse_args(): 10 | parser = argparse.ArgumentParser(description='Train a detector') 11 | parser.add_argument('config', help='train config file path') 12 | parser.add_argument( 13 | '--shape', 14 | type=int, 15 | nargs='+', 16 | default=[1280, 800], 17 | help='input image size') 18 | args = parser.parse_args() 19 | return args 20 | 21 | 22 | def main(): 23 | 24 | args = parse_args() 25 | 26 | if len(args.shape) == 1: 27 | input_shape = (3, args.shape[0], args.shape[0]) 28 | elif len(args.shape) == 2: 29 | input_shape = (3, ) + tuple(args.shape) 30 | else: 31 | raise ValueError('invalid input shape') 32 | 33 | cfg = Config.fromfile(args.config) 34 | model = build_detector( 35 | cfg.model, train_cfg=cfg.train_cfg, test_cfg=cfg.test_cfg).cuda() 36 | model.eval() 37 | 38 | if hasattr(model, 'forward_dummy'): 39 | model.forward = model.forward_dummy 40 | else: 41 | raise NotImplementedError( 42 | 'FLOPs counter is currently not currently supported with {}'. 43 | format(model.__class__.__name__)) 44 | 45 | flops, params = get_model_complexity_info(model, input_shape) 46 | split_line = '=' * 30 47 | print('{0}\nInput shape: {1}\nFlops: {2}\nParams: {3}\n{0}'.format( 48 | split_line, input_shape, flops, params)) 49 | 50 | 51 | if __name__ == '__main__': 52 | main() 53 | -------------------------------------------------------------------------------- /_submodules/mmdetection/tools/publish_model.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import subprocess 3 | 4 | import torch 5 | 6 | 7 | def parse_args(): 8 | parser = argparse.ArgumentParser( 9 | description='Process a checkpoint to be published') 10 | parser.add_argument('in_file', help='input checkpoint filename') 11 | parser.add_argument('out_file', help='output checkpoint filename') 12 | args = parser.parse_args() 13 | return args 14 | 15 | 16 | def process_checkpoint(in_file, out_file): 17 | checkpoint = torch.load(in_file, map_location='cpu') 18 | # remove optimizer for smaller file size 19 | if 'optimizer' in checkpoint: 20 | del checkpoint['optimizer'] 21 | # if it is necessary to remove some sensitive data in checkpoint['meta'], 22 | # add the code here. 23 | torch.save(checkpoint, out_file) 24 | sha = subprocess.check_output(['sha256sum', out_file]).decode() 25 | final_file = out_file.rstrip('.pth') + '-{}.pth'.format(sha[:8]) 26 | subprocess.Popen(['mv', out_file, final_file]) 27 | 28 | 29 | def main(): 30 | args = parse_args() 31 | process_checkpoint(args.in_file, args.out_file) 32 | 33 | 34 | if __name__ == '__main__': 35 | main() 36 | -------------------------------------------------------------------------------- /_submodules/mmdetection/tools/slurm_test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -x 4 | 5 | PARTITION=$1 6 | JOB_NAME=$2 7 | CONFIG=$3 8 | CHECKPOINT=$4 9 | GPUS=${GPUS:-8} 10 | GPUS_PER_NODE=${GPUS_PER_NODE:-8} 11 | CPUS_PER_TASK=${CPUS_PER_TASK:-5} 12 | PY_ARGS=${@:5} 13 | SRUN_ARGS=${SRUN_ARGS:-""} 14 | 15 | srun -p ${PARTITION} \ 16 | --job-name=${JOB_NAME} \ 17 | --gres=gpu:${GPUS_PER_NODE} \ 18 | --ntasks=${GPUS} \ 19 | --ntasks-per-node=${GPUS_PER_NODE} \ 20 | --cpus-per-task=${CPUS_PER_TASK} \ 21 | --kill-on-bad-exit=1 \ 22 | ${SRUN_ARGS} \ 23 | python -u tools/test.py ${CONFIG} ${CHECKPOINT} --launcher="slurm" ${PY_ARGS} 24 | -------------------------------------------------------------------------------- /_submodules/mmdetection/tools/slurm_train.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -x 4 | 5 | PARTITION=$1 6 | JOB_NAME=$2 7 | CONFIG=$3 8 | WORK_DIR=$4 9 | GPUS=${5:-8} 10 | GPUS_PER_NODE=${GPUS_PER_NODE:-8} 11 | CPUS_PER_TASK=${CPUS_PER_TASK:-5} 12 | SRUN_ARGS=${SRUN_ARGS:-""} 13 | PY_ARGS=${PY_ARGS:-"--validate"} 14 | 15 | srun -p ${PARTITION} \ 16 | --job-name=${JOB_NAME} \ 17 | --gres=gpu:${GPUS_PER_NODE} \ 18 | --ntasks=${GPUS} \ 19 | --ntasks-per-node=${GPUS_PER_NODE} \ 20 | --cpus-per-task=${CPUS_PER_TASK} \ 21 | --kill-on-bad-exit=1 \ 22 | ${SRUN_ARGS} \ 23 | python -u tools/train.py ${CONFIG} --work_dir=${WORK_DIR} --launcher="slurm" ${PY_ARGS} 24 | -------------------------------------------------------------------------------- /_submodules/mmdetection/tools/upgrade_model_version.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import re 3 | from collections import OrderedDict 4 | 5 | import torch 6 | 7 | 8 | def convert(in_file, out_file): 9 | """Convert keys in checkpoints. 10 | 11 | There can be some breaking changes during the development of mmdetection, 12 | and this tool is used for upgrading checkpoints trained with old versions 13 | to the latest one. 14 | """ 15 | checkpoint = torch.load(in_file) 16 | in_state_dict = checkpoint.pop('state_dict') 17 | out_state_dict = OrderedDict() 18 | for key, val in in_state_dict.items(): 19 | # Use ConvModule instead of nn.Conv2d in RetinaNet 20 | # cls_convs.0.weight -> cls_convs.0.conv.weight 21 | m = re.search(r'(cls_convs|reg_convs).\d.(weight|bias)', key) 22 | if m is not None: 23 | param = m.groups()[1] 24 | new_key = key.replace(param, 'conv.{}'.format(param)) 25 | out_state_dict[new_key] = val 26 | continue 27 | 28 | out_state_dict[key] = val 29 | checkpoint['state_dict'] = out_state_dict 30 | torch.save(checkpoint, out_file) 31 | 32 | 33 | def main(): 34 | parser = argparse.ArgumentParser(description='Upgrade model version') 35 | parser.add_argument('in_file', help='input checkpoint file') 36 | parser.add_argument('out_file', help='output checkpoint file') 37 | args = parser.parse_args() 38 | convert(args.in_file, args.out_file) 39 | 40 | 41 | if __name__ == '__main__': 42 | main() 43 | -------------------------------------------------------------------------------- /_submodules/mmdetection/tools/voc_eval.py: -------------------------------------------------------------------------------- 1 | from argparse import ArgumentParser 2 | 3 | import mmcv 4 | import numpy as np 5 | 6 | from mmdet import datasets 7 | from mmdet.core import eval_map 8 | 9 | 10 | def voc_eval(result_file, dataset, iou_thr=0.5): 11 | det_results = mmcv.load(result_file) 12 | gt_bboxes = [] 13 | gt_labels = [] 14 | gt_ignore = [] 15 | for i in range(len(dataset)): 16 | ann = dataset.get_ann_info(i) 17 | bboxes = ann['bboxes'] 18 | labels = ann['labels'] 19 | if 'bboxes_ignore' in ann: 20 | ignore = np.concatenate([ 21 | np.zeros(bboxes.shape[0], dtype=np.bool), 22 | np.ones(ann['bboxes_ignore'].shape[0], dtype=np.bool) 23 | ]) 24 | gt_ignore.append(ignore) 25 | bboxes = np.vstack([bboxes, ann['bboxes_ignore']]) 26 | labels = np.concatenate([labels, ann['labels_ignore']]) 27 | gt_bboxes.append(bboxes) 28 | gt_labels.append(labels) 29 | if not gt_ignore: 30 | gt_ignore = None 31 | if hasattr(dataset, 'year') and dataset.year == 2007: 32 | dataset_name = 'voc07' 33 | else: 34 | dataset_name = dataset.CLASSES 35 | eval_map( 36 | det_results, 37 | gt_bboxes, 38 | gt_labels, 39 | gt_ignore=gt_ignore, 40 | scale_ranges=None, 41 | iou_thr=iou_thr, 42 | dataset=dataset_name, 43 | print_summary=True) 44 | 45 | 46 | def main(): 47 | parser = ArgumentParser(description='VOC Evaluation') 48 | parser.add_argument('result', help='result file path') 49 | parser.add_argument('config', help='config file path') 50 | parser.add_argument( 51 | '--iou-thr', 52 | type=float, 53 | default=0.5, 54 | help='IoU threshold for evaluation') 55 | args = parser.parse_args() 56 | cfg = mmcv.Config.fromfile(args.config) 57 | test_dataset = mmcv.runner.obj_from_dict(cfg.data.test, datasets) 58 | voc_eval(args.result, test_dataset, args.iou_thr) 59 | 60 | 61 | if __name__ == '__main__': 62 | main() 63 | -------------------------------------------------------------------------------- /_submodules/neuron/.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | *.py[cod] 3 | log 4 | log_* 5 | /data 6 | __pycache__/ 7 | cache/ 8 | results/ 9 | reports/ 10 | screenshots/ 11 | screenshots*/ 12 | experiments/ 13 | *.egg-info/ 14 | work_dirs/ 15 | !.gitignore 16 | -------------------------------------------------------------------------------- /_submodules/neuron/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include neuron/data/datasets/uav123.json 2 | include neuron/data/datasets/lasot.json 3 | -------------------------------------------------------------------------------- /_submodules/neuron/configs/reid_baseline.yaml: -------------------------------------------------------------------------------- 1 | # common parameters 2 | experiment: ReID_baseline 3 | work_dir: work_dirs 4 | log_level: DEBUG 5 | train_echo: [loss, top1, top5, cmc_1, cmc_5] 6 | val_echo: [loss] 7 | use_gpu: &use_gpu true 8 | num_workers: &num_workers 48 9 | max_epochs: 120 10 | start_epoch: 0 11 | save_frequency: 1 12 | val_frequency: 5 13 | num_seqs: &num_seqs 9335 14 | num_train: &num_train 5000 15 | num_val: &num_val 4335 16 | base_dataset: &base_dataset 17 | type: GOT10k 18 | subset: train 19 | 20 | model: 21 | type: ReID_Baseline 22 | backbone: 23 | type: resnet50 24 | pretrained: true 25 | last_stride: 1 26 | num_classes: *num_train 27 | 28 | loss: 29 | type: ReID_Loss 30 | loss_cls: 31 | type: python.dict 32 | loss: 33 | type: LabelSmoothLoss 34 | num_classes: *num_train 35 | eps: 0.1 36 | calc_metrics: true 37 | weight: 1. 38 | loss_rank: 39 | type: python.dict 40 | loss: 41 | type: TripletLoss 42 | margin: 0.3 43 | normalize_feats: true 44 | calc_metrics: true 45 | weight: 1. 46 | 47 | param_grouper: 48 | type: ParamGrouper 49 | lr: 0.00035 50 | weight_decay: 0.0005 51 | special_lrs: 52 | bias: 0.00035 53 | special_wds: 54 | bias: 0.0005 55 | 56 | optimizer: 57 | type: torch.Adam 58 | lr: 0.00035 59 | weight_decay: 0.0005 60 | 61 | lr_scheduler: 62 | type: WarmupMultiStepLR 63 | steps: [40, 70] 64 | gamma: 0.1 65 | warmup_factor: 0.01 66 | warmup_iters: 10 67 | warmup_method: linear 68 | 69 | train_data: 70 | type: torch.DataLoader 71 | dataset: 72 | type: Seq2Instance 73 | seqs: 74 | type: Slice 75 | dataset: *base_dataset 76 | start: 0 77 | stop: *num_train 78 | transforms: 79 | type: ReID_Transforms 80 | train: true 81 | sampling_stride: 2 82 | sampler: 83 | type: RandomIdentitySampler 84 | num_identities: 16 85 | num_instances: 4 86 | batch_size: 64 87 | num_workers: *num_workers 88 | pin_memory: *use_gpu 89 | drop_last: true 90 | 91 | val_data: 92 | type: torch.DataLoader 93 | dataset: 94 | type: Seq2Instance 95 | seqs: 96 | type: Slice 97 | dataset: *base_dataset 98 | start: *num_train 99 | stop: *num_seqs 100 | transforms: 101 | type: ReID_Transforms 102 | train: false 103 | sampling_stride: 30 104 | sampler: 105 | type: RandomIdentitySampler 106 | num_identities: 16 107 | num_instances: 4 108 | batch_size: 64 109 | num_workers: *num_workers 110 | pin_memory: *use_gpu 111 | drop_last: false 112 | -------------------------------------------------------------------------------- /_submodules/neuron/configs/siamfc.yaml: -------------------------------------------------------------------------------- 1 | # common parameters 2 | experiment: SiamFC_baseline 3 | work_dir: 'work_dirs' 4 | log_level: DEBUG 5 | train_echo: [loss] 6 | val_echo: [loss] 7 | use_gpu: &use_gpu true 8 | num_workers: &num_workers 48 9 | max_epochs: 50 10 | start_epoch: 0 11 | save_frequency: 1 12 | val_frequency: 5 13 | exemplar_sz: &exemplar_sz 127 14 | instance_sz: &instance_sz 255 15 | context: &context 0.5 16 | out_stride: &out_stride 8 17 | 18 | model: 19 | type: TrackerSiamFC 20 | backbone: 21 | type: AlexNetV1 22 | out_layers: 'conv5' 23 | head: 24 | type: XCorr 25 | scale: 0.001 26 | learnable: false 27 | cfg: 28 | exemplar_sz: *exemplar_sz 29 | instance_sz: *instance_sz 30 | context: *context 31 | scale_num: 3 32 | scale_step: 1.0375 33 | scale_lr: 0.59 34 | scale_penalty: 0.9745 35 | window_influence: 0.176 36 | response_sz: 17 37 | response_up: 16 38 | out_stride: *out_stride 39 | 40 | loss: 41 | type: BalancedBCELoss 42 | neg_weight: 1.0 43 | 44 | optimizer: 45 | type: torch.SGD 46 | lr: 1.e-2 47 | weight_decay: 5.e-4 48 | momentum: 0.9 49 | 50 | lr_scheduler: 51 | type: torch.ExponentialLR 52 | gamma: 0.871 53 | 54 | train_data: 55 | type: torch.DataLoader 56 | dataset: 57 | type: Seq2Pair 58 | seqs: 59 | type: GOT10k 60 | subset: 'train' 61 | transforms: 62 | type: SiamFC_Transforms 63 | exemplar_sz: *exemplar_sz 64 | instance_sz: *instance_sz 65 | context: *context 66 | shift: 8 67 | out_stride: *out_stride 68 | response_sz: 15 69 | r_pos: 16 70 | r_neg: 0 71 | pairs_per_seq: 1 72 | max_distance: 100 73 | batch_size: 8 74 | shuffle: true 75 | num_workers: *num_workers 76 | pin_memory: *use_gpu 77 | drop_last: true 78 | 79 | val_data: 80 | type: torch.DataLoader 81 | dataset: 82 | type: Seq2Pair 83 | seqs: 84 | type: GOT10k 85 | subset: 'val' 86 | transforms: 87 | type: SiamFC_Transforms 88 | exemplar_sz: *exemplar_sz 89 | instance_sz: *instance_sz 90 | context: *context 91 | shift: 8 92 | out_stride: *out_stride 93 | response_sz: 15 94 | r_pos: 16 95 | r_neg: 0 96 | pairs_per_seq: 1 97 | max_distance: 100 98 | batch_size: 8 99 | shuffle: false 100 | num_workers: *num_workers 101 | pin_memory: *use_gpu 102 | drop_last: false 103 | 104 | test_data: 105 | type: OTB 106 | version: 2015 107 | 108 | evaluator: 109 | type: OTB_Eval 110 | nbins_iou: 101 111 | nbins_ce: 51 112 | visualize: false 113 | plot_curves: false 114 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanglianghua/GlobalTrack/0c9bd9649ce6006323787e7d6e6a1b88c19eaf80/_submodules/neuron/neuron/__init__.py -------------------------------------------------------------------------------- /_submodules/neuron/neuron/config/__init__.py: -------------------------------------------------------------------------------- 1 | from .config import * 2 | from .registry import * 3 | from . import _init_registry 4 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/config/_init_registry.py: -------------------------------------------------------------------------------- 1 | # register all modules in neuron 2 | from neuron.data import * 3 | from neuron.models import * 4 | from neuron.optim import * 5 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/data/__init__.py: -------------------------------------------------------------------------------- 1 | from .datasets import * 2 | from .transforms import * 3 | from .samplers import * 4 | from .evaluators import * 5 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/data/collate.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanglianghua/GlobalTrack/0c9bd9649ce6006323787e7d6e6a1b88c19eaf80/_submodules/neuron/neuron/data/collate.py -------------------------------------------------------------------------------- /_submodules/neuron/neuron/data/datasets/__init__.py: -------------------------------------------------------------------------------- 1 | # base classes 2 | from .dataset import * 3 | from .structure import * 4 | # sequence datasets (SOT + MOT + VID) 5 | from .otb import * 6 | from .vot import * 7 | from .dtb70 import * 8 | from .tcolor128 import * 9 | from .nfs import * 10 | from .uav123 import * 11 | from .oxuva import * 12 | from .got10k import * 13 | from .lasot import * 14 | from .trackingnet import * 15 | from .tlp import * 16 | from .visdrone import * 17 | from .pot import * 18 | from .mot import * 19 | from .imagenet import * 20 | # image datasets 21 | from .coco import * 22 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/data/datasets/dtb70.py: -------------------------------------------------------------------------------- 1 | import os.path as osp 2 | import glob 3 | import numpy as np 4 | 5 | import neuron.ops as ops 6 | from neuron.config import registry 7 | from .dataset import SeqDataset 8 | 9 | 10 | __all__ = ['DTB70'] 11 | 12 | 13 | @registry.register_module 14 | class DTB70(SeqDataset): 15 | """`DTB70 `_ Dataset. 16 | 17 | Publication: 18 | ``Visual object tracking for unmanned aerial vehicles: A benchmark and new motion models``, 19 | Y. Wu, J. Lim and M.-H. Yang, IEEE TPAMI 2015. 20 | 21 | Args: 22 | root_dir (string): Root directory of dataset where sequence 23 | folders exist. 24 | """ 25 | def __init__(self, root_dir=None): 26 | if root_dir is None: 27 | root_dir = osp.expanduser('~/data/DTB70') 28 | self.root_dir = root_dir 29 | 30 | # initialize the dataset 31 | super(DTB70, self).__init__( 32 | name='DTB70', 33 | root_dir=self.root_dir) 34 | 35 | def _construct_seq_dict(self, root_dir): 36 | # image and annotation paths 37 | anno_files = sorted(glob.glob( 38 | osp.join(root_dir, '*/groundtruth_rect.txt'))) 39 | seq_dirs = [osp.dirname(f) for f in anno_files] 40 | seq_names = [osp.basename(d) for d in seq_dirs] 41 | 42 | # construct seq_dict 43 | seq_dict = {} 44 | for s, seq_name in enumerate(seq_names): 45 | img_files = sorted(glob.glob( 46 | osp.join(seq_dirs[s], 'img/*.jpg'))) 47 | anno = np.loadtxt(anno_files[s], delimiter=',') 48 | anno[:, 2:] = anno[:, :2] + anno[:, 2:] - 1 49 | 50 | # meta information 51 | seq_len = len(img_files) 52 | img0 = ops.read_image(img_files[0]) 53 | meta = { 54 | 'width': img0.shape[1], 55 | 'height': img0.shape[0], 56 | 'frame_num': seq_len, 57 | 'target_num': 1, 58 | 'total_instances': seq_len} 59 | 60 | # update seq_dict 61 | seq_dict[seq_name] = { 62 | 'img_files': img_files, 63 | 'target': { 64 | 'anno': anno, 65 | 'meta': meta}} 66 | 67 | return seq_dict 68 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/data/datasets/pot.py: -------------------------------------------------------------------------------- 1 | import os.path as osp 2 | import glob 3 | import numpy as np 4 | 5 | import neuron.ops as ops 6 | from neuron.config import registry 7 | from .dataset import SeqDataset 8 | 9 | 10 | __all__ = ['POT'] 11 | 12 | 13 | @registry.register_module 14 | class POT(SeqDataset): 15 | """`POT `_ Dataset. 16 | 17 | Publication: 18 | ``Planar Object Tracking in the Wild: A Benchmark``, 19 | P. Liang, Y. Wu, H. Lu, L. Wang, C. Liao, and H. Ling, ICRA 2018. 20 | 21 | Args: 22 | root_dir (string): Root directory of dataset where sequence 23 | folders exist. 24 | """ 25 | def __init__(self, root_dir=None): 26 | if root_dir is None: 27 | root_dir = osp.expanduser('~/data/POT') 28 | self.root_dir = root_dir 29 | 30 | # initialize the dataset 31 | super(POT, self).__init__( 32 | name='POT', 33 | root_dir=root_dir) 34 | 35 | def _construct_seq_dict(self, root_dir): 36 | # image and annotation paths 37 | seq_dirs = sorted(glob.glob( 38 | osp.join(root_dir, '*/*_*/'))) 39 | seq_dirs = [d[:-1] for d in seq_dirs] 40 | seq_names = [osp.basename(d) for d in seq_dirs] 41 | anno_files = [osp.join( 42 | root_dir, 'annotation/annotation/{}_gt_points.txt'.format(n)) 43 | for n in seq_names] 44 | 45 | # construct seq_dict 46 | seq_dict = {} 47 | for s, seq_name in enumerate(seq_names): 48 | if s % 50 == 0 or s + 1 == len(seq_names): 49 | ops.sys_print('Processing sequence [%d/%d]: %s...' % ( 50 | s + 1, len(seq_names), seq_name)) 51 | 52 | img_files = sorted(glob.glob( 53 | osp.join(seq_dirs[s], '*.jpg'))) 54 | anno = np.loadtxt(anno_files[s]) 55 | 56 | n = min(len(img_files), len(anno)) 57 | assert n > 0 58 | img_files = img_files[:n] 59 | anno = anno[:n] 60 | 61 | # meta information 62 | seq_len = len(img_files) 63 | img0 = ops.read_image(img_files[0]) 64 | meta = { 65 | 'width': img0.shape[1], 66 | 'height': img0.shape[0], 67 | 'frame_num': seq_len, 68 | 'target_num': 1, 69 | 'total_instances': seq_len} 70 | 71 | # update seq_dict 72 | seq_dict[seq_name] = { 73 | 'img_files': img_files, 74 | 'target': { 75 | 'anno': anno, 76 | 'meta': meta}} 77 | 78 | return seq_dict 79 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/data/datasets/tlp.py: -------------------------------------------------------------------------------- 1 | import os.path as osp 2 | import glob 3 | import numpy as np 4 | 5 | import neuron.ops as ops 6 | from neuron.config import registry 7 | from .dataset import SeqDataset 8 | 9 | 10 | __all__ = ['TLP'] 11 | 12 | 13 | @registry.register_module 14 | class TLP(SeqDataset): 15 | """`TLP `_ Dataset. 16 | 17 | Publication: 18 | ``Long-term Visual Object Tracking Benchmark``, 19 | Moudgil Abhinav and Gandhi Vineet, ACCV 2018. 20 | 21 | Args: 22 | root_dir (string): Root directory of dataset where sequence 23 | folders exist. 24 | """ 25 | def __init__(self, root_dir=None): 26 | if root_dir is None: 27 | root_dir = osp.expanduser('~/data/TLP') 28 | self.root_dir = root_dir 29 | 30 | # initialize the dataset 31 | super(TLP, self).__init__( 32 | name='TLP', 33 | root_dir=self.root_dir) 34 | 35 | def _construct_seq_dict(self, root_dir): 36 | # image and annotation paths 37 | anno_files = sorted(glob.glob( 38 | osp.join(root_dir, '*/groundtruth_rect.txt'))) 39 | seq_dirs = [osp.dirname(f) for f in anno_files] 40 | seq_names = [osp.basename(d) for d in seq_dirs] 41 | 42 | # construct seq_dict 43 | seq_dict = {} 44 | for s, seq_name in enumerate(seq_names): 45 | img_files = sorted(glob.glob( 46 | osp.join(seq_dirs[s], 'img/*.jpg'))) 47 | anno = np.loadtxt(anno_files[s], delimiter=',') 48 | 49 | # parse annotations 50 | frames, bboxes, losts = anno[:, 0], anno[:, 1:5], anno[:, 5] 51 | assert np.all(frames == np.arange(len(frames)) + 1) 52 | bboxes[:, 2:] = bboxes[:, :2] + bboxes[:, 2:] - 1 53 | 54 | # meta information 55 | seq_len = len(img_files) 56 | img0 = ops.read_image(img_files[0]) 57 | meta = { 58 | 'width': img0.shape[1], 59 | 'height': img0.shape[0], 60 | 'frame_num': seq_len, 61 | 'target_num': 1, 62 | 'total_instances': seq_len, 63 | 'absence': losts} 64 | 65 | # update seq_dict 66 | seq_dict[seq_name] = { 67 | 'img_files': img_files, 68 | 'target': { 69 | 'anno': bboxes, 70 | 'meta': meta}} 71 | 72 | return seq_dict 73 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/data/evaluators/__init__.py: -------------------------------------------------------------------------------- 1 | from .evaluator import Evaluator 2 | from .otb_eval import * 3 | from .vot_eval import * 4 | from .got10k_eval import * 5 | from .oxuva_eval import * 6 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/data/evaluators/evaluator.py: -------------------------------------------------------------------------------- 1 | import abc 2 | 3 | 4 | class Evaluator(object): 5 | __metaclass__ = abc.ABCMeta 6 | 7 | @abc.abstractmethod 8 | def run(self, model, visualize=False): 9 | raise NotImplementedError 10 | 11 | @abc.abstractmethod 12 | def report(self, model_names): 13 | raise NotImplementedError 14 | 15 | @abc.abstractmethod 16 | def show(self, model_names): 17 | raise NotImplementedError 18 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/data/parallel.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanglianghua/GlobalTrack/0c9bd9649ce6006323787e7d6e6a1b88c19eaf80/_submodules/neuron/neuron/data/parallel.py -------------------------------------------------------------------------------- /_submodules/neuron/neuron/data/samplers/__init__.py: -------------------------------------------------------------------------------- 1 | from .samplers import * 2 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/data/samplers/samplers.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import copy 3 | import random 4 | from collections import defaultdict 5 | from torch.utils.data import Sampler 6 | 7 | from neuron.config import registry 8 | 9 | 10 | __all__ = ['RandomIdentitySampler'] 11 | 12 | 13 | @registry.register_module 14 | class RandomIdentitySampler(Sampler): 15 | 16 | def __init__(self, dataset, num_identities, num_instances): 17 | self.dataset = dataset 18 | self.num_identities = num_identities 19 | self.num_instances = num_instances 20 | self.index_dict = defaultdict(list) 21 | for i, (_, val) in enumerate(dataset.ins_dict.items()): 22 | ins_id = val['target']['ins_id'] 23 | self.index_dict[ins_id].append(i) 24 | self.ins_ids = list(self.index_dict.keys()) 25 | 26 | # estimate length (samples in an epochs) 27 | self.length = 0 28 | for ins_id in self.ins_ids: 29 | n = len(self.index_dict[ins_id]) 30 | if n < self.num_instances: 31 | n = self.num_instances 32 | self.length += n - n % self.num_instances 33 | 34 | def __iter__(self): 35 | # construct batch indices for each ins_id 36 | batch_index_dict = defaultdict(list) 37 | for ins_id in self.ins_ids: 38 | indices = copy.deepcopy(self.index_dict[ins_id]) 39 | if len(indices) < self.num_instances: 40 | indices = np.random.choice( 41 | indices, size=self.num_instances, replace=True) 42 | random.shuffle(indices) 43 | 44 | batch_indices = [] 45 | for index in indices: 46 | batch_indices.append(index) 47 | if len(batch_indices) == self.num_instances: 48 | batch_index_dict[ins_id].append(batch_indices) 49 | batch_indices = [] 50 | 51 | # construct the final sample indices 52 | rest_ids = copy.deepcopy(self.ins_ids) 53 | final_indices = [] 54 | while len(rest_ids) >= self.num_identities: 55 | selected = random.sample(rest_ids, self.num_identities) 56 | for ins_id in selected: 57 | batch_indices = batch_index_dict[ins_id].pop(0) 58 | final_indices.extend(batch_indices) 59 | if len(batch_index_dict[ins_id]) == 0: 60 | rest_ids.remove(ins_id) 61 | 62 | # update length (samples in an epoch) 63 | self.length = len(final_indices) 64 | 65 | return iter(final_indices) 66 | 67 | def __len__(self): 68 | return self.length 69 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/data/transforms/__init__.py: -------------------------------------------------------------------------------- 1 | from .pair_transforms import * 2 | from .img_transforms import * 3 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/data/transforms/img_transforms/__init__.py: -------------------------------------------------------------------------------- 1 | from .reid_transforms import * 2 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/data/transforms/pair_transforms/__init__.py: -------------------------------------------------------------------------------- 1 | from .siamfc_transforms import * 2 | from .mmdet_transforms import * 3 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/engine/__init__.py: -------------------------------------------------------------------------------- 1 | from .logger import * 2 | from .meter import * 3 | from .trainer import * 4 | from .inference import * 5 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/engine/inference.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanglianghua/GlobalTrack/0c9bd9649ce6006323787e7d6e6a1b88c19eaf80/_submodules/neuron/neuron/engine/inference.py -------------------------------------------------------------------------------- /_submodules/neuron/neuron/engine/logger.py: -------------------------------------------------------------------------------- 1 | import os.path as osp 2 | import logging 3 | import sys 4 | from tensorboardX import SummaryWriter 5 | 6 | 7 | class Logger(object): 8 | LOG_LEVELS = { 9 | 'CRITICAL': logging.CRITICAL, 10 | 'ERROR': logging.ERROR, 11 | 'WARNING': logging.WARNING, 12 | 'INFO': logging.INFO, 13 | 'DEBUG': logging.DEBUG, 14 | 'NOTSET': logging.NOTSET} 15 | 16 | def __init__(self, log_dir, run_name, **kwargs): 17 | # console and file logger 18 | log_level = kwargs.pop('log_level', logging.DEBUG) 19 | if isinstance(log_level, str): 20 | log_level = self.LOG_LEVELS[log_level.upper()] 21 | fmt = logging.Formatter( 22 | '%(asctime)s %(levelname)s: %(message)s') 23 | self._logger = logging.getLogger(run_name) 24 | self._logger.setLevel(log_level) 25 | # console handler 26 | ch = logging.StreamHandler(stream=sys.stdout) 27 | ch.setLevel(log_level) 28 | ch.setFormatter(logging.Formatter('%(levelname)s: %(message)s')) 29 | self._logger.addHandler(ch) 30 | # file logger 31 | log_file = osp.join(log_dir, run_name + '.log') 32 | fh = logging.FileHandler(log_file) 33 | fh.setLevel(log_level) 34 | fh.setFormatter(logging.Formatter( 35 | '%(asctime)s %(levelname)s: %(message)s')) 36 | self._logger.addHandler(fh) 37 | 38 | # summary writer 39 | self._writer = SummaryWriter(logdir=log_dir) 40 | 41 | def log(self, msg, level=logging.INFO): 42 | self._logger.log(level, msg) 43 | 44 | def __getattr__(self, name): 45 | try: 46 | return object.__getattribute__(self, name) 47 | except AttributeError: 48 | if name in dir(self._writer): 49 | return object.__getattribute__(self._writer, name) 50 | elif name in dir(self._logger): 51 | object.__getattribute__(self._logger, name) 52 | else: 53 | raise AttributeError( 54 | '\'{}\' has no attribute \'{}\''.format( 55 | self.__class__.__name__, name)) 56 | 57 | def close(self): 58 | self._logger.close() 59 | self._writer.close() 60 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/engine/meter.py: -------------------------------------------------------------------------------- 1 | import addict 2 | 3 | 4 | __all__ = ['Meter'] 5 | 6 | 7 | class _AverageMeter(object): 8 | 9 | def __init__(self): 10 | self.val = 0 11 | self.avg = 0 12 | self.sum = 0 13 | self.count = 0 14 | 15 | def update(self, val): 16 | self.val = val 17 | self.sum += val 18 | self.count += 1 19 | self.avg = self.sum / self.count 20 | 21 | def reset(self): 22 | self.val = 0 23 | self.avg = 0 24 | self.sum = 0 25 | self.count = 0 26 | 27 | def __repr__(self): 28 | return '{:.3f}'.format(self.avg) 29 | 30 | 31 | class Meter(addict.Dict): 32 | 33 | def update(self, metrics): 34 | for k, v in metrics.items(): 35 | if k in self.keys(): 36 | self.__getitem__(k).update(v) 37 | else: 38 | meter = _AverageMeter() 39 | meter.update(v) 40 | self.__setitem__(k, meter) 41 | 42 | def reset(self): 43 | for k in self.keys(): 44 | self.__getitem__(k).reset() 45 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/models/__init__.py: -------------------------------------------------------------------------------- 1 | # network modules 2 | from .backbones import * 3 | from .heads import * 4 | from .losses import * 5 | from .metrics import * 6 | # computer vision models 7 | from .model import Model 8 | from .trackers import * 9 | from .reid import * 10 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/models/backbones/__init__.py: -------------------------------------------------------------------------------- 1 | from .backbone import Backbone 2 | from .alexnet import * 3 | from .resnet import * 4 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/models/backbones/backbone.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import abc 3 | 4 | 5 | class Backbone(nn.Module): 6 | __metaclass__ = abc.ABCMeta 7 | 8 | @abc.abstractproperty 9 | def out_channels(self): 10 | raise NotImplementedError 11 | 12 | @abc.abstractproperty 13 | def out_stride(self): 14 | raise NotImplementedError 15 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/models/heads/__init__.py: -------------------------------------------------------------------------------- 1 | from .xcorr import * 2 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/models/heads/xcorr.py: -------------------------------------------------------------------------------- 1 | import numbers 2 | import torch 3 | import torch.nn as nn 4 | from collections import OrderedDict 5 | 6 | from neuron.config import registry 7 | from neuron import ops 8 | 9 | 10 | __all__ = ['XCorr'] 11 | 12 | 13 | @registry.register_module 14 | class XCorr(nn.Module): 15 | 16 | def __init__(self, scale=0.001, learnable=False): 17 | assert isinstance(scale, (numbers.Number, list)) 18 | if isinstance(scale, numbers.Number): 19 | scale = [scale] 20 | super(XCorr, self).__init__() 21 | 22 | # store logarithm of scale to avoid explosion during training 23 | self.scale = nn.Parameter(torch.Tensor(scale).log()) 24 | if not learnable: 25 | self.scale.requires_grad = False 26 | 27 | def forward(self, z, x): 28 | assert isinstance(z, (torch.Tensor, OrderedDict)) 29 | scale = self.scale.exp() 30 | 31 | if isinstance(z, torch.Tensor): 32 | assert len(scale) == 1 33 | out = scale * ops.fast_xcorr(z, x) 34 | elif isinstance(z, OrderedDict): 35 | if len(scale) == 1: 36 | scale = scale.expand(len(z)) 37 | assert len(scale) == len(z) 38 | out = sum([scale[i] * ops.fast_xcorr(z[k], x[k]) 39 | for i, k in enumerate(z)]) 40 | return out 41 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/models/losses/__init__.py: -------------------------------------------------------------------------------- 1 | from .losses import * 2 | from .multi_task_losses import * 3 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/models/metrics/__init__.py: -------------------------------------------------------------------------------- 1 | from .metrics import * 2 | from .multi_task_metrics import * 3 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/models/metrics/metrics.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | import neuron.ops as ops 6 | from neuron.config import registry 7 | 8 | 9 | @registry.register_module 10 | class Precision(nn.Module): 11 | 12 | def forward(self, scores, labels): 13 | return ops.topk_precision(scores, labels) 14 | 15 | 16 | @registry.register_module 17 | class R1_mAP(nn.Module): 18 | 19 | def __init__(self, normalize_feats=False): 20 | super(R1_mAP, self).__init__() 21 | self.normalize_feats = normalize_feats 22 | 23 | def forward(self, feats, labels): 24 | if self.normalize_feats: 25 | feats = F.normalize(feats, dim=1, p=2) 26 | dist_mat = ops.euclidean(feats, feats, sqrt=False) 27 | return ops.r1_map(dist_mat, labels) 28 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/models/metrics/multi_task_metrics.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | 4 | import neuron.ops as ops 5 | from neuron.config import registry 6 | 7 | 8 | @registry.register_module 9 | class ReID_Metric(nn.Module): 10 | 11 | def __init__(self, metric_cls, metric_rank): 12 | super(ReID_Metric, self).__init__() 13 | self.metric_cls = metric_cls 14 | self.metric_rank = metric_rank 15 | 16 | def forward(self, *args): 17 | if len(args) == 2: 18 | scores = None 19 | feats, labels = args 20 | elif len(args) == 3: 21 | scores, feats, labels = args 22 | else: 23 | raise ValueError('Expected to have 2 or 3 inputs,' 24 | 'but got {}'.format(len(args))) 25 | 26 | metrics = self.metric_rank(feats, labels) 27 | if scores is not None: 28 | metrics.update(self.metric_cls(scores, labels)) 29 | 30 | return metrics 31 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/models/model.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import abc 3 | 4 | 5 | class Model(nn.Module): 6 | __metaclass__ = abc.ABCMeta 7 | 8 | @abc.abstractmethod 9 | def forward_train(self, train_batch): 10 | raise NotImplementedError 11 | 12 | @abc.abstractmethod 13 | def forward_val(self, val_batch): 14 | raise NotImplementedError 15 | 16 | @abc.abstractmethod 17 | def forward_test(self, test_data, visualize=False): 18 | raise NotImplementedError 19 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/models/reid/__init__.py: -------------------------------------------------------------------------------- 1 | from .reid_baseline import * 2 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/models/reid/reid_baseline.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | 3 | import neuron.ops as ops 4 | from neuron.config import registry 5 | from neuron.models.model import Model 6 | 7 | 8 | __all__ = ['ReID_Baseline'] 9 | 10 | 11 | @registry.register_module 12 | class ReID_Baseline(Model): 13 | 14 | def __init__(self, backbone, num_classes): 15 | super(ReID_Baseline, self).__init__() 16 | 17 | # build network 18 | self.backbone = backbone 19 | self.pool = nn.AdaptiveAvgPool2d(1) 20 | self.neck = nn.BatchNorm1d(backbone.out_channels) 21 | self.neck.bias.requires_grad_(False) # no shift 22 | self.classifier = nn.Linear( 23 | backbone.out_channels, num_classes, bias=False) 24 | self.num_classes = num_classes 25 | 26 | # initialize weights 27 | self.neck.apply(ops.kaiming_init) 28 | self.classifier.apply(ops.classifier_init) 29 | 30 | def forward(self, x, training=None): 31 | x = self.pool(self.backbone(x)).view(len(x), -1) 32 | x_neck = self.neck(x) 33 | 34 | if training is None: 35 | training = self.training 36 | if training: 37 | scores = self.classifier(x_neck) 38 | return scores, x 39 | else: 40 | return x_neck 41 | 42 | def forward_train(self, img, target): 43 | scores, feats = self.forward(img, training=True) 44 | return scores, feats, target['label'] 45 | 46 | def forward_val(self, img, target): 47 | feats = self.forward(img, training=False) 48 | return feats, target['label'] 49 | 50 | def forward_test(self, img, target): 51 | feats = self.forward(img, training=False) 52 | return feats, target['label'] 53 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/models/trackers/__init__.py: -------------------------------------------------------------------------------- 1 | from .tracker import * 2 | from ._dummy import * 3 | from .siamfc import * 4 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/models/trackers/_dummy.py: -------------------------------------------------------------------------------- 1 | from neuron.config import registry 2 | from .tracker import Tracker, OxUvA_Tracker 3 | 4 | 5 | __all__ = ['DummyTracker', 'DummyOxUvA_Tracker'] 6 | 7 | 8 | @registry.register_module 9 | class DummyTracker(Tracker): 10 | 11 | def __init__(self): 12 | super(DummyTracker, self).__init__( 13 | name='Dummy', is_deterministic=True, input_type='file') 14 | 15 | def init(self, img, init_bbox): 16 | self.bbox = init_bbox 17 | 18 | def update(self, img): 19 | return self.bbox 20 | 21 | 22 | @registry.register_module 23 | class DummyOxUvA_Tracker(OxUvA_Tracker): 24 | 25 | def __init__(self): 26 | super(DummyOxUvA_Tracker, self).__init__( 27 | name='Dummy', is_deterministic=True, input_type='file') 28 | 29 | def init(self, img, init_bbox): 30 | self.bbox = init_bbox 31 | 32 | def update(self, img): 33 | return self.bbox, 1.0, True 34 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/ops/__init__.py: -------------------------------------------------------------------------------- 1 | from .ops import * 2 | from .image import * 3 | from .io import * 4 | from .transforms import * 5 | from .losses import * 6 | from .metrics import * 7 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/ops/io.py: -------------------------------------------------------------------------------- 1 | import time 2 | import sys 3 | import os 4 | import os.path as osp 5 | import zipfile 6 | import shutil 7 | if sys.version_info.major == 2: 8 | from urllib import urlretrieve 9 | else: 10 | from urllib.request import urlretrieve 11 | 12 | 13 | def download(url, filename): 14 | r"""Download a file from the internet. 15 | 16 | Args: 17 | url (string): URL of the internet file. 18 | filename (string): Path to store the downloaded file. 19 | """ 20 | dirname = osp.dirname(filename) 21 | if not osp.exists(dirname): 22 | os.makedirs(dirname) 23 | return urlretrieve(url, filename, _reporthook) 24 | 25 | 26 | def _reporthook(count, block_size, total_size): 27 | global start_time 28 | if count == 0: 29 | start_time = time.time() 30 | return 31 | duration = time.time() - start_time 32 | progress_size = int(count * block_size) 33 | speed = int(progress_size / (1024 * duration)) 34 | percent = int(count * block_size * 100 / total_size) 35 | sys.stdout.write("\r...%d%%, %d MB, %d KB/s, %d seconds passed" % 36 | (percent, progress_size / (1024 * 1024), speed, duration)) 37 | sys.stdout.flush() 38 | 39 | 40 | def extract(filename, extract_dir): 41 | r"""Extract a zip file. 42 | 43 | Args: 44 | filename (string): Path of the zip file. 45 | extract_dir (string): Directory to store the extracted results. 46 | """ 47 | if osp.splitext(filename)[1] == '.zip': 48 | if not osp.isdir(extract_dir): 49 | os.makedirs(extract_dir) 50 | with zipfile.ZipFile(filename) as z: 51 | z.extractall(extract_dir) 52 | else: 53 | raise ValueError( 54 | 'Expected the extention to be .zip, ' 55 | 'but got {} instead'.format(osp.splitext(filename)[1])) 56 | 57 | 58 | def compress(dirname, save_file): 59 | """Compress a folder to a zip file. 60 | 61 | Arguments: 62 | dirname {string} -- Directory of all files to be compressed. 63 | save_file {string} -- Path to store the zip file. 64 | """ 65 | shutil.make_archive(save_file, 'zip', dirname) 66 | 67 | 68 | def sys_print(*args, **kwargs): 69 | args = tuple(str(u) for u in args) 70 | sys.stdout.write(' '.join(args), **kwargs) 71 | sys.stdout.write('\n') 72 | sys.stdout.flush() 73 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/optim/__init__.py: -------------------------------------------------------------------------------- 1 | from .param_grouper import * 2 | from .lr_scheduler import * 3 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/optim/lr_scheduler.py: -------------------------------------------------------------------------------- 1 | from torch.optim.lr_scheduler import _LRScheduler 2 | from bisect import bisect_right 3 | 4 | from neuron.config import registry 5 | 6 | 7 | __all__ = ['WarmupMultiStepLR'] 8 | 9 | 10 | @registry.register_module 11 | class WarmupMultiStepLR(_LRScheduler): 12 | 13 | def __init__(self, 14 | optimizer, 15 | steps, 16 | gamma, 17 | warmup_factor, 18 | warmup_iters, 19 | warmup_method, 20 | last_epoch=-1): 21 | if steps != sorted(steps): 22 | raise ValueError( 23 | 'Steps should be a list of increasing integers,' 24 | ' but got {}'.format(steps)) 25 | assert warmup_method in ['constant', 'linear'] 26 | self.steps = steps 27 | self.gamma = gamma 28 | self.warmup_factor = warmup_factor 29 | self.warmup_iters = warmup_iters 30 | self.warmup_method = warmup_method 31 | super(WarmupMultiStepLR, self).__init__(optimizer, last_epoch) 32 | 33 | def get_lr(self): 34 | warmup_factor = 1 35 | if self.last_epoch < self.warmup_iters: 36 | if self.warmup_method == 'constant': 37 | warmup_factor = self.warmup_factor 38 | elif self.warmup_method == 'linear': 39 | alpha = self.last_epoch / self.warmup_iters 40 | warmup_factor = self.warmup_factor * (1 - alpha) + alpha 41 | return [base_lr * warmup_factor * self.gamma ** \ 42 | bisect_right(self.steps, self.last_epoch) 43 | for base_lr in self.base_lrs] 44 | -------------------------------------------------------------------------------- /_submodules/neuron/neuron/optim/param_grouper.py: -------------------------------------------------------------------------------- 1 | from neuron.config import registry 2 | 3 | 4 | __all__ = ['ParamGrouper'] 5 | 6 | 7 | @registry.register_module 8 | class ParamGrouper(object): 9 | 10 | def __init__(self, lr, weight_decay, special_lrs={}, 11 | special_wds={}): 12 | self.base_lr = lr 13 | self.base_wd = weight_decay 14 | self.special_lrs = special_lrs 15 | self.special_wds = special_wds 16 | 17 | def __call__(self, *modules): 18 | # collect all parameters and their names 19 | named_params = [] 20 | for m in modules: 21 | named_params += list(m.named_parameters()) 22 | 23 | # build param_groups 24 | param_groups = [] 25 | for name, params in named_params: 26 | if not params.requires_grad: 27 | continue 28 | 29 | # learning rate 30 | lr_keys = [key for key in self.special_lrs if name in key] 31 | if len(lr_keys) == 0: 32 | lr = self.base_lr 33 | elif len(lr_keys) == 1: 34 | lr = self.special_lrs[lr_keys[0]] 35 | else: 36 | raise ValueError( 37 | 'The lr group of parameter {} is ambiguous since it' 38 | 'has multiple matches in special_lrs'.format(name)) 39 | 40 | # weight decay 41 | wd_keys = [key for key in self.special_wds if name in key] 42 | if len(wd_keys) == 0: 43 | wd = self.base_wd 44 | elif len(wd_keys) == 1: 45 | wd = self.special_wds[wd_keys[0]] 46 | else: 47 | raise ValueError( 48 | 'The wd group of parameter {} is ambiguous since it' 49 | 'has multiple matches in special_wds'.format(name)) 50 | 51 | # append to param_groups 52 | param_groups += [{'params': [params], 53 | 'lr': lr, 54 | 'weight_decay': wd}] 55 | 56 | return param_groups 57 | -------------------------------------------------------------------------------- /_submodules/neuron/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | 4 | setup(name='neuron', 5 | version='0.1.0', 6 | description='Computer vision neuron', 7 | author='Lianghua Huang', 8 | author_email='lianghua.huang.cs@gmail.com', 9 | url='https://github.com/huanglianghua/neuron', 10 | license='MIT', 11 | packages=find_packages(), 12 | include_package_data=True) 13 | -------------------------------------------------------------------------------- /_submodules/neuron/tests/test_config.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import os 3 | 4 | import neuron.data as data 5 | from neuron.config import Config, registry 6 | 7 | 8 | class TestConfig(unittest.TestCase): 9 | 10 | def test_config(self): 11 | cfg = Config({'param1': 1}, param2=2, param3={'param4': 4}) 12 | 13 | # check saving and loading 14 | for ext in ['.json', '.yaml', '.yml']: 15 | cfg_file = 'config' + ext 16 | cfg.dump(cfg_file) 17 | new_cfg = Config.load(cfg_file) 18 | os.remove(cfg_file) 19 | self.assertEqual(cfg, new_cfg) 20 | 21 | # check copying and merging 22 | new_cfg = cfg.deepcopy() 23 | self.assertNotEqual(id(cfg), id(new_cfg)) 24 | new_cfg.update({'param1': 10}) 25 | self.assertEqual(cfg.merge_from(new_cfg), new_cfg) 26 | self.assertEqual(cfg.merge_to(new_cfg), cfg) 27 | 28 | # check freezing and defrosting 29 | cfg.freeze() 30 | self.assertTrue(cfg.is_frozen) 31 | cfg.defrost() 32 | self.assertFalse(cfg.is_frozen) 33 | 34 | def test_registry(self): 35 | # check building modules 36 | cfg = Config(type='torch.Conv2d', in_channels=3, 37 | out_channels=64, kernel_size=3, padding=1) 38 | module = registry.build(cfg) 39 | 40 | # check building with submodules 41 | cfg = Config( 42 | type='Seq2Pair', 43 | seqs=Config(type='OTB', version=2015), 44 | pairs_per_seq=10, 45 | max_distance=300) 46 | module = registry.build(cfg) 47 | 48 | 49 | if __name__ == '__main__': 50 | unittest.main() 51 | -------------------------------------------------------------------------------- /_submodules/neuron/tests/test_datasets/test_seq_datasets.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import random 3 | 4 | import neuron.ops as ops 5 | from neuron.data.datasets import * 6 | 7 | 8 | class TestSeqDatasets(unittest.TestCase): 9 | 10 | def setUp(self): 11 | self.visualize = False 12 | 13 | def test_seq_datasets(self): 14 | datasets = [ 15 | OTB(version=2015), 16 | VOT(version=2019, anno_type='rect'), 17 | DTB70(), 18 | TColor128(), 19 | NfS(fps=30), 20 | NfS(fps=240), 21 | UAV123(version='UAV123'), 22 | UAV123(version='UAV20L'), 23 | OxUvA(subset='dev'), 24 | OxUvA(subset='test'), 25 | GOT10k(subset='train'), 26 | GOT10k(subset='test'), 27 | LaSOT(subset='train'), 28 | LaSOT(subset='test'), 29 | TrackingNet(subset='train'), 30 | TrackingNet(subset='test'), 31 | VisDroneSOT(subset='train'), 32 | VisDroneSOT(subset='test'), 33 | POT(), 34 | MOT(version=2016, subset='train'), 35 | ImageNetVID(subset=['train', 'val']), 36 | VisDroneVID(subset=['train', 'val'])] 37 | for dataset in datasets: 38 | self._check_dataset(dataset) 39 | 40 | def _check_dataset(self, dataset): 41 | seq_num = len(dataset) 42 | if seq_num == 0: 43 | ops.sys_print('Warning: {} dataset is empty, ' 44 | 'skip test...'.format(dataset.name)) 45 | return 46 | self.assertGreater(seq_num, 0) 47 | ops.sys_print('{} contains {} sequences'.format( 48 | dataset.name, seq_num)) 49 | 50 | # sanity check 51 | inds = random.sample(range(seq_num), min(seq_num, 10)) 52 | for i in inds: 53 | img_files, target = dataset[i] 54 | anno, meta = target['anno'], target['meta'] 55 | if anno.shape[0] == 1: 56 | continue # test sets 57 | if anno.shape[1] in [4, 8]: 58 | self.assertEqual(len(img_files), len(anno)) 59 | else: 60 | self.assertGreaterEqual( 61 | len(img_files) - 1, anno[:, 0].max()) 62 | 63 | # visualization 64 | if self.visualize: 65 | img_files, target = random.choice(dataset) 66 | anno = target['anno'] 67 | 68 | for f, img_file in enumerate(img_files): 69 | if f >= anno.shape[0]: 70 | break # test sets 71 | if anno.shape[1] == 9: 72 | bboxes = anno[anno[:, 0] == f, 2:6] 73 | elif anno.shape[1] == 8: 74 | break # TODO: points are not supported yet 75 | else: 76 | bboxes = anno[f, :] 77 | img = ops.read_image(img_file) 78 | ops.show_image(img, bboxes, delay=1) 79 | 80 | 81 | if __name__ == '__main__': 82 | unittest.main() 83 | -------------------------------------------------------------------------------- /_submodules/neuron/tests/test_evaluators/test_seq_evaluators.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from neuron.models.trackers import DummyTracker, DummyOxUvA_Tracker 4 | from neuron.data.evaluators import * 5 | 6 | 7 | class TestSeqEvaluators(unittest.TestCase): 8 | 9 | def setUp(self): 10 | self.tracker = DummyTracker() 11 | self.oxuva_tracker = DummyOxUvA_Tracker() 12 | self.visualize = False 13 | 14 | def test_otb_eval(self): 15 | evaluators = [ 16 | EvaluatorOTB(version=2013), 17 | EvaluatorOTB(version=2015), 18 | EvaluatorDTB70(), 19 | EvaluatorNfS(fps=30), 20 | EvaluatorNfS(fps=240), 21 | EvaluatorTColor128(), 22 | EvaluatorUAV123(version='UAV123'), 23 | EvaluatorUAV123(version='UAV20L'), 24 | EvaluatorLaSOT(), 25 | EvaluatorVisDrone(subset='val')] 26 | for e in evaluators: 27 | e.run(self.tracker, visualize=self.visualize) 28 | e.report(self.tracker.name) 29 | 30 | def test_vot_eval(self): 31 | evaluators = [ 32 | EvaluatorVOT(version=2018), 33 | EvaluatorVOT(version=2019)] 34 | for e in evaluators: 35 | e.run(self.tracker, visualize=self.visualize) 36 | e.report(self.tracker.name) 37 | 38 | def test_got10k_eval(self): 39 | evaluators = [ 40 | EvaluatorGOT10k(subset='val'), 41 | EvaluatorGOT10k(subset='test')] 42 | for e in evaluators: 43 | e.run(self.tracker, visualize=self.visualize) 44 | e.report(self.tracker.name) 45 | 46 | def test_oxuva_eval(self): 47 | evaluators = [ 48 | EvaluatorOxUvA(subset='dev'), 49 | EvaluatorOxUvA(subset='test')] 50 | for e in evaluators: 51 | e.run(self.oxuva_tracker, visualize=self.visualize) 52 | 53 | 54 | if __name__ == '__main__': 55 | unittest.main() 56 | -------------------------------------------------------------------------------- /_submodules/neuron/tests/test_models/test_backbones.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import torch 3 | import time 4 | 5 | import neuron.ops as ops 6 | from neuron.models.backbones import * 7 | 8 | 9 | class TestBackbones(unittest.TestCase): 10 | 11 | def setUp(self): 12 | cuda = torch.cuda.is_available() 13 | self.device = torch.device('cuda' if cuda else 'cpu') 14 | self.input = torch.rand((2, 3, 640, 384)).to(self.device) 15 | # initialize GPUs 16 | _ = AlexNetV1(out_layers='conv5').to(self.device)(self.input) 17 | 18 | def test_alexnet(self): 19 | alexnets = [ 20 | AlexNetV1(out_layers='conv5'), 21 | AlexNetV2(out_layers=['conv4', 'conv5']), 22 | AlexNetV3(out_layers=['conv5'])] 23 | for net in alexnets: 24 | self._check_net(net.to(self.device)) 25 | 26 | def test_resnet(self): 27 | resnets = [ 28 | resnet18(pretrained=True, last_stride=1), 29 | resnet34(pretrained=True, last_stride=1), 30 | resnet50(pretrained=True, last_stride=2), 31 | resnet101(pretrained=False, last_stride=2), 32 | resnet152(pretrained=False, last_stride=2)] 33 | for net in resnets: 34 | self._check_net(net.to(self.device)) 35 | 36 | def _check_net(self, net): 37 | begin = time.time() 38 | out = net(self.input) 39 | end = time.time() 40 | 41 | # preserve the last-layer output 42 | if isinstance(out, dict): 43 | key = list(out.keys())[-1] 44 | out = out[key] 45 | elif isinstance(out, list): 46 | out = out[-1] 47 | 48 | # print inference information 49 | ops.sys_print('[{}] input: {} output: {} stride: {} ' 50 | 'speed: {:.1f} fps'.format( 51 | net.__class__.__name__, 52 | tuple(self.input.shape), 53 | tuple(out.shape), 54 | net.out_stride, 55 | 1. / (end - begin))) 56 | 57 | 58 | if __name__ == '__main__': 59 | unittest.main() 60 | -------------------------------------------------------------------------------- /_submodules/neuron/tests/test_models/test_heads.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import torch 3 | import time 4 | 5 | import neuron.ops as ops 6 | import neuron.models as models 7 | 8 | 9 | class TestHeads(unittest.TestCase): 10 | 11 | def setUp(self): 12 | cuda = torch.cuda.is_available() 13 | self.device = torch.device('cuda' if cuda else 'cpu') 14 | self.z = torch.rand(2, 3, 127, 127).to(self.device) 15 | self.x = torch.rand(2, 3, 255, 255).to(self.device) 16 | 17 | def test_xcorr(self): 18 | backbone = models.AlexNetV1() 19 | heads = [ 20 | models.XCorr(scale=0.001, learnable=False), 21 | models.XCorr(scale=0.001, learnable=True), 22 | models.XCorr(scale=[0.001], learnable=False), 23 | models.XCorr(scale=[0.001], learnable=True)] 24 | for head in heads: 25 | ops.sys_print(head.scale.exp()) 26 | self._check_xcorr_head( 27 | backbone.to(self.device), 28 | head.to(self.device)) 29 | 30 | def _check_xcorr_head(self, backbone, head): 31 | begin = time.time() 32 | out = head(backbone(self.z), backbone(self.x)) 33 | end = time.time() 34 | 35 | # print inference information 36 | ops.sys_print('[{}] z: {} x: {} output: {} time: {:.5f}s'.format( 37 | head.__class__.__name__, 38 | tuple(self.z.shape), 39 | tuple(self.x.shape), 40 | tuple(out.shape), 41 | end - begin)) 42 | 43 | 44 | if __name__ == '__main__': 45 | unittest.main() 46 | -------------------------------------------------------------------------------- /_submodules/neuron/tests/test_ops/test_metrics.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | import unittest 4 | import numpy as np 5 | 6 | import neuron.ops as ops 7 | 8 | 9 | class TestMetrics(unittest.TestCase): 10 | 11 | def test_iou(self): 12 | r1 = np.random.rand(1000, 4) * 100 13 | r2 = np.random.rand(1000, 4) * 100 14 | r1[:, 2:] += r1[:, :2] - 1 15 | r2[:, 2:] += r2[:, :2] - 1 16 | 17 | for bound in [None, (50, 100), (100, 200)]: 18 | o1 = ops.rect_iou(r1, r2, bound=bound) 19 | o2 = ops.poly_iou(r1, r2, bound=bound) 20 | self.assertTrue((o1 - o2).max() < 1e-12) 21 | 22 | p1 = self._to_corner(r1) 23 | p2 = self._to_corner(r2) 24 | o3 = ops.poly_iou(p1, p2, bound=bound) 25 | self.assertTrue((o1 - o3).max() < 1e-12) 26 | 27 | def _to_corner(self, rects): 28 | rects = rects.copy() 29 | rects[:, 2:] += 1 30 | x1, y1, x2, y2 = rects.T 31 | return np.array([x1, y1, x1, y2, x2, y2, x2, y1]).T 32 | 33 | 34 | if __name__ == '__main__': 35 | unittest.main() 36 | -------------------------------------------------------------------------------- /_submodules/neuron/tests/test_transforms/test_instance_transforms.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import numpy as np 3 | 4 | import neuron.data as data 5 | import neuron.ops as ops 6 | 7 | 8 | class TestInstanceTransforms(unittest.TestCase): 9 | 10 | def setUp(self): 11 | self.seqs = data.OTB(version=2015) 12 | self.visualize = False 13 | 14 | def test_siamfc_transforms(self): 15 | transforms = data.ReID_Transforms() 16 | dataset = data.Seq2Instance(self.seqs, transforms=transforms) 17 | 18 | inds = np.random.choice(len(dataset), 10) 19 | for i in inds: 20 | img, target = dataset[i] 21 | img = 255. * (img - img.min()) / (img.max() - img.min()) 22 | img = img.permute(1, 2, 0).numpy().astype(np.uint8) 23 | if self.visualize: 24 | ops.sys_print('Label: %d' % target['label'].item()) 25 | ops.show_image(img, target['bbox'], delay=0) 26 | 27 | 28 | if __name__ == '__main__': 29 | unittest.main() 30 | -------------------------------------------------------------------------------- /_submodules/neuron/tests/test_transforms/test_pair_transforms.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import numpy as np 3 | 4 | import neuron.data as data 5 | import neuron.ops as ops 6 | 7 | 8 | class TestPairTransforms(unittest.TestCase): 9 | 10 | def setUp(self): 11 | self.seqs = data.OTB(version=2015) 12 | self.visualize = False 13 | 14 | def test_siamfc_transforms(self): 15 | transforms = data.SiamFC_Transforms() 16 | dataset = data.Seq2Pair(self.seqs, transforms=transforms) 17 | indices = np.random.choice(len(dataset), 10) 18 | for i in indices: 19 | img_z, img_x, target = dataset[i] 20 | img_z = img_z.permute(1, 2, 0).numpy().astype(np.uint8) 21 | img_x = img_x.permute(1, 2, 0).numpy().astype(np.uint8) 22 | target = target.squeeze(0).numpy().astype(np.float32) 23 | if self.visualize: 24 | ops.show_image(img_z, fig=1, delay=1) 25 | ops.show_image(img_x, fig=2, delay=1) 26 | ops.show_image(target, fig=3, delay=0) 27 | 28 | def test_mmdet_transforms(self): 29 | for transforms in [ 30 | data.BasicPairTransforms(), 31 | data.ExtraPairTransforms()]: 32 | dataset = data.Seq2Pair(self.seqs, transforms=transforms) 33 | indices = np.random.choice(len(dataset), 10) 34 | for i in indices: 35 | item = dataset[i] 36 | img_z = ops.stretch_color(item['img_z'].permute(1, 2, 0).numpy()) 37 | img_x = ops.stretch_color(item['img_x'].permute(1, 2, 0).numpy()) 38 | bboxes_z = item['gt_bboxes_z'][0].numpy() 39 | bboxes_x = item['gt_bboxes_x'][0].numpy() 40 | if self.visualize: 41 | ops.show_image(img_z, bboxes_z, fig=1, delay=1) 42 | ops.show_image(img_x, bboxes_x, fig=2, delay=0) 43 | 44 | 45 | if __name__ == '__main__': 46 | unittest.main() 47 | -------------------------------------------------------------------------------- /_submodules/neuron/tools/test.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanglianghua/GlobalTrack/0c9bd9649ce6006323787e7d6e6a1b88c19eaf80/_submodules/neuron/tools/test.py -------------------------------------------------------------------------------- /_submodules/neuron/tools/train.py: -------------------------------------------------------------------------------- 1 | from neuron.config import Config 2 | from neuron.engine import Trainer 3 | 4 | 5 | if __name__ == '__main__': 6 | config_file = 'configs/reid_baseline.yaml' 7 | cfg = Config.load(config_file) 8 | 9 | trainer = Trainer(cfg) 10 | trainer.train() 11 | trainer.test() 12 | -------------------------------------------------------------------------------- /datasets/__init__.py: -------------------------------------------------------------------------------- 1 | from .wrappers import * 2 | -------------------------------------------------------------------------------- /imgs/figure2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huanglianghua/GlobalTrack/0c9bd9649ce6006323787e7d6e6a1b88c19eaf80/imgs/figure2.jpg -------------------------------------------------------------------------------- /modules/__init__.py: -------------------------------------------------------------------------------- 1 | from .modulators import * 2 | from .qg_rpn import * 3 | from .qg_rcnn import * 4 | -------------------------------------------------------------------------------- /tests/test_datasets.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import numpy as np 3 | 4 | import _init_paths 5 | import neuron.ops as ops 6 | from datasets import * 7 | from mmcv.parallel import DataContainer as DC 8 | 9 | 10 | class TestDatasets(unittest.TestCase): 11 | 12 | def setUp(self): 13 | self.visualize = False 14 | 15 | def test_pair_wrapper(self): 16 | dataset = PairWrapper(base_transforms='extra_partial') 17 | indices = np.random.choice(len(dataset), 10) 18 | for i in indices: 19 | item = dataset[i] 20 | 21 | # check keys 22 | keys = [ 23 | 'img_z', 24 | 'img_x', 25 | 'img_meta_z', 26 | 'img_meta_x', 27 | 'gt_bboxes_z', 28 | 'gt_bboxes_x'] 29 | self.assertTrue(all([k in item for k in keys])) 30 | 31 | # check data types 32 | for _, v in item.items(): 33 | self.assertTrue(isinstance(v, DC)) 34 | 35 | # check sizes 36 | self.assertEqual( 37 | len(item['gt_bboxes_z'].data), 38 | len(item['gt_bboxes_x'].data)) 39 | if 'gt_labels' in item: 40 | self.assertEqual( 41 | len(item['gt_bboxes_x'].data), 42 | len(item['gt_labels'].data)) 43 | 44 | # visualize pair 45 | if self.visualize: 46 | ops.sys_print('Item index:', i) 47 | self._show_image( 48 | item['img_z'].data, item['gt_bboxes_z'].data, 49 | fig=0, delay=1) 50 | self._show_image( 51 | item['img_x'].data, item['gt_bboxes_x'].data, 52 | fig=1, delay=0) 53 | 54 | def _show_image(self, img, bboxes, fig, delay): 55 | img = 255. * (img - img.min()) / (img.max() - img.min()) 56 | img = img.permute(1, 2, 0).cpu().numpy().astype(np.uint8) 57 | bboxes = bboxes.cpu().numpy() 58 | ops.show_image(img, bboxes, fig=fig, delay=delay) 59 | 60 | 61 | if __name__ == '__main__': 62 | unittest.main() 63 | -------------------------------------------------------------------------------- /tests/test_modules.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import torch 3 | 4 | import _init_paths 5 | from mmcv import Config 6 | from mmdet.models import build_detector 7 | from mmdet.datasets import build_dataset 8 | from mmdet.datasets import build_dataloader 9 | from mmcv.parallel import MMDataParallel 10 | 11 | 12 | class TestModules(unittest.TestCase): 13 | 14 | def test_qg_rpn(self): 15 | # build configurations 16 | cfg_file = 'configs/qg_rpn_r50_fpn.py' 17 | cfg = Config.fromfile(cfg_file) 18 | cfg.gpus = 1 19 | 20 | # load state_dict 21 | ckp_file = 'checkpoints/qg_rpn_r50_fpn_2x_20181010-88a4a471.pth' 22 | checkpoint = torch.load(ckp_file, map_location='cpu') 23 | state_dict = checkpoint['state_dict'] 24 | 25 | # build model 26 | model = build_detector( 27 | cfg.model, 28 | train_cfg=cfg.train_cfg, 29 | test_cfg=cfg.test_cfg) 30 | model.load_state_dict(state_dict) 31 | model = MMDataParallel(model, device_ids=range(cfg.gpus)).cuda() 32 | 33 | # build dataloader 34 | dataset = build_dataset(cfg.data.train) 35 | dataloader = build_dataloader( 36 | dataset, 37 | cfg.data.imgs_per_gpu, 38 | cfg.data.workers_per_gpu, 39 | cfg.gpus, 40 | shuffle=False, 41 | dist=False) 42 | 43 | # run a forward pass 44 | batch = next(iter(dataloader)) 45 | losses = model(**batch) 46 | 47 | def test_qg_rcnn(self): 48 | # build configuration 49 | cfg_file = 'configs/qg_rcnn_r50_fpn.py' 50 | cfg = Config.fromfile(cfg_file) 51 | cfg.gpus = 1 52 | 53 | # load state_dict 54 | ckp_file = 'checkpoints/qg_rcnn_r50_fpn_2x_20181010-443129e1.pth' 55 | checkpoint = torch.load(ckp_file, map_location='cpu') 56 | state_dict = checkpoint['state_dict'] 57 | 58 | # build model 59 | model = build_detector( 60 | cfg.model, 61 | train_cfg=cfg.train_cfg, 62 | test_cfg=cfg.test_cfg) 63 | model.load_state_dict(state_dict) 64 | model = MMDataParallel(model, device_ids=range(cfg.gpus)) 65 | 66 | # build dataloader 67 | dataset = build_dataset(cfg.data.train) 68 | dataloader = build_dataloader( 69 | dataset, 70 | cfg.data.imgs_per_gpu, 71 | cfg.data.workers_per_gpu, 72 | cfg.gpus, 73 | shuffle=False, 74 | dist=False) 75 | 76 | # run a forward pass 77 | batch = next(iter(dataloader)) 78 | losses = model(**batch) 79 | 80 | 81 | if __name__ == '__main__': 82 | unittest.main() 83 | -------------------------------------------------------------------------------- /tests/test_trackers.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import _init_paths 4 | import neuron.data as data 5 | from trackers import * 6 | 7 | 8 | class TestTrackers(unittest.TestCase): 9 | 10 | def setUp(self): 11 | self.evaluator = data.EvaluatorOTB(version=2015) 12 | self.visualize = False 13 | 14 | def test_global_track(self): 15 | # settings 16 | cfg_files = [ 17 | 'configs/qg_rpn_r50_fpn.py', 18 | 'configs/qg_rcnn_r50_fpn.py', 19 | 'configs/qg_rpn_r18_fpn.py'] 20 | ckp_files = [ 21 | 'checkpoints/qg_rpn_r50_fpn_coco_got10k_lasot.pth', 22 | 'checkpoints/qg_rcnn_r50_fpn_coco_got10k_lasot.pth', 23 | 'work_dirs/qg_rpn_r18_fpn/epoch_12.pth'] 24 | transforms = data.BasicPairTransforms(train=False) 25 | 26 | # run evaluation over different settings 27 | for cfg_file, ckp_file in zip(cfg_files, ckp_files): 28 | tracker = GlobalTrack(cfg_file, ckp_file, transforms) 29 | self.evaluator.run(tracker, visualize=self.visualize) 30 | self.evaluator.report(tracker.name) 31 | 32 | 33 | if __name__ == '__main__': 34 | unittest.main() 35 | -------------------------------------------------------------------------------- /tools/dist_train_qg_rcnn.sh: -------------------------------------------------------------------------------- 1 | # baseline 2 | python -m torch.distributed.launch --nproc_per_node=4 tools/train_qg_rcnn.py \ 3 | --launcher pytorch --load_from checkpoints/qg_rcnn_r50_fpn_2x_20181010-443129e1.pth \ 4 | --base_dataset "coco_train" --sampling_prob "1" \ 5 | --gpus 4 --work_dir work_dirs/qg_rcnn_r50_fpn_baseline 6 | 7 | # COCO+GOT+LaSOT 8 | python -m torch.distributed.launch --nproc_per_node=4 tools/train_qg_rcnn.py \ 9 | --launcher pytorch --load_from work_dirs/qg_rcnn_r50_fpn_baseline/epoch_12.pth \ 10 | --base_dataset "coco_train,got10k_train,lasot_train" --sampling_prob "0.4,0.4,0.2" \ 11 | --gpus 4 --work_dir work_dirs/qg_rcnn_r50_fpn_coco_got10k_lasot 12 | -------------------------------------------------------------------------------- /tools/test_global_track.py: -------------------------------------------------------------------------------- 1 | import _init_paths 2 | import neuron.data as data 3 | from trackers import * 4 | 5 | 6 | if __name__ == '__main__': 7 | cfg_file = 'configs/qg_rcnn_r50_fpn.py' 8 | ckp_file = 'checkpoints/qg_rcnn_r50_fpn_coco_got10k_lasot.pth' 9 | transforms = data.BasicPairTransforms(train=False) 10 | tracker = GlobalTrack( 11 | cfg_file, ckp_file, transforms, 12 | name_suffix='qg_rcnn_r50_fpn') 13 | evaluators = [ 14 | data.EvaluatorOTB(version=2015), 15 | data.EvaluatorLaSOT(frame_stride=10), 16 | data.EvaluatorGOT10k(subset='test'), 17 | data.EvaluatorTLP()] 18 | for e in evaluators: 19 | e.run(tracker, visualize=False) 20 | e.report(tracker.name) 21 | -------------------------------------------------------------------------------- /trackers/__init__.py: -------------------------------------------------------------------------------- 1 | from .global_track import * 2 | -------------------------------------------------------------------------------- /trackers/global_track.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import numpy as np 3 | 4 | from neuron.models import Tracker 5 | from mmcv import Config 6 | from mmcv.runner import load_checkpoint 7 | from mmdet.models import build_detector 8 | from mmdet.core import wrap_fp16_model 9 | 10 | 11 | __all__ = ['GlobalTrack'] 12 | 13 | 14 | class GlobalTrack(Tracker): 15 | 16 | def __init__(self, cfg_file, ckp_file, transforms, name_suffix=''): 17 | name = 'GlobalTrack' 18 | if name_suffix: 19 | name += '_' + name_suffix 20 | super(GlobalTrack, self).__init__( 21 | name=name, is_deterministic=True) 22 | self.transforms = transforms 23 | 24 | # build config 25 | cfg = Config.fromfile(cfg_file) 26 | if cfg.get('cudnn_benchmark', False): 27 | torch.backends.cudnn.benchmark = True 28 | cfg.model.pretrained = None 29 | self.cfg = cfg 30 | 31 | # build model 32 | model = build_detector( 33 | cfg.model, train_cfg=None, test_cfg=cfg.test_cfg) 34 | fp16_cfg = cfg.get('fp16', None) 35 | if fp16_cfg is not None: 36 | wrap_fp16_model(model) 37 | checkpoint = load_checkpoint( 38 | model, ckp_file, map_location='cpu') 39 | model.CLASSES = ('object', ) 40 | 41 | # GPU usage 42 | cuda = torch.cuda.is_available() 43 | self.device = torch.device('cuda:0' if cuda else 'cpu') 44 | self.model = model.to(self.device) 45 | 46 | @torch.no_grad() 47 | def init(self, img, bbox): 48 | self.model.eval() 49 | 50 | # prepare query data 51 | img_meta = {'ori_shape': img.shape} 52 | bboxes = np.expand_dims(bbox, axis=0) 53 | img, img_meta, bboxes = \ 54 | self.transforms._process_query(img, img_meta, bboxes) 55 | img = img.unsqueeze(0).contiguous().to( 56 | self.device, non_blocking=True) 57 | bboxes = bboxes.to(self.device, non_blocking=True) 58 | 59 | # initialize the modulator 60 | self.model._process_query(img, [bboxes]) 61 | 62 | @torch.no_grad() 63 | def update(self, img, **kwargs): 64 | self.model.eval() 65 | 66 | # prepare gallary data 67 | img_meta = {'ori_shape': img.shape} 68 | img, img_meta, _ = \ 69 | self.transforms._process_gallary(img, img_meta, None) 70 | img = img.unsqueeze(0).contiguous().to( 71 | self.device, non_blocking=True) 72 | 73 | # get detections 74 | results = self.model._process_gallary( 75 | img, [img_meta], rescale=True, **kwargs) 76 | 77 | if not kwargs.get('return_all', False): 78 | # return the top-1 detection 79 | max_ind = results[:, -1].argmax() 80 | return results[max_ind, :4] 81 | else: 82 | # return all detections 83 | return results 84 | --------------------------------------------------------------------------------