├── LICENSE ├── README.md ├── experiments ├── DaSiamRPN │ ├── LICENSE │ └── README.md ├── LightTrack │ ├── LICENSE │ ├── LightTrack.yaml │ └── README.md ├── Ocean │ ├── LICENSE │ ├── Ocean_UAV123.yaml │ └── README.md ├── README.md ├── SESiamFC │ ├── LICENSE │ ├── README.md │ └── config.yaml ├── SiamAPN++ │ ├── README.md │ └── config.yaml ├── SiamAPN │ ├── README.md │ └── config.yaml ├── SiamBAN │ ├── LICENSE │ ├── README.md │ └── config.yaml ├── SiamCAR │ ├── README.md │ └── config.yaml ├── SiamDW_FCIncep22 │ ├── LICENSE │ ├── README.md │ └── SiamFCIncep22_VOT.yaml ├── SiamDW_FCNext22 │ ├── LICENSE │ ├── README.md │ └── SiamFCNext22_VOT.yaml ├── SiamDW_FCRes22 │ ├── LICENSE │ ├── README.md │ └── SiamFCRes22_VOT.yaml ├── SiamDW_RPNRes22 │ ├── LICENSE │ ├── README.md │ └── SiamRPNRes22_VOT.yaml ├── SiamFC++ │ ├── LICENSE │ ├── README.md │ └── siamfcpp_googlenet.yaml ├── SiamGAT │ ├── README.md │ └── config.yaml ├── SiamMask │ ├── LICENSE │ ├── README.md │ ├── config.yaml │ └── convert_model.py ├── SiamRPN++_alex │ ├── LICENSE │ ├── README.md │ └── config.yaml ├── SiamRPN++_mobilev2 │ ├── LICENSE │ ├── README.md │ └── config.yaml ├── SiamRPN++_r50 │ ├── LICENSE │ ├── README.md │ └── config.yaml └── UpdateNet │ └── README.md ├── figures ├── Attributes.pdf ├── Attributes.png ├── DTB70.zip ├── Normalized Precision and FPS.pdf ├── Normalized Precision and FPS.png ├── Precision and FPS.pdf ├── Precision and FPS.png ├── Success and FPS.pdf ├── Success and FPS.png ├── UAV123@10fps.zip ├── UAV20L.zip ├── UAVDT.zip ├── UAVTrack112.zip └── VisDrone2020.zip ├── pipelines ├── dasiamrpn_pipeline.py ├── lighttrack_pipeline.py ├── ocean_pipeline.py ├── pipeline_builder.py ├── sesiamfc_pipeline.py ├── siamapn_pipeline.py ├── siamapnpp_pipeline.py ├── siamban_pipeline.py ├── siamcar_pipeline.py ├── siamdw_fc_pipeline.py ├── siamdw_rpn_pipeline.py ├── siamfcpp_pipeline.py ├── siamgat_pipeline.py ├── siammask_pipeline.py ├── siamrpn_pipeline.py └── updatenet_pipeline.py ├── results ├── DTB70.zip ├── DarkTrack2021.zip ├── NAT2021.zip ├── UAV123_10fps.zip ├── UAV123_20L.zip ├── UAVDT.zip ├── UAVDark135.zip ├── UAVTrack112.zip └── VisDrone-2020SOT-test.zip ├── snot ├── core │ ├── __init__.py │ ├── config.py │ ├── config_adapn.py │ ├── config_apn.py │ ├── config_ban.py │ ├── config_car.py │ ├── config_fcpp.py │ ├── config_gat.py │ └── xcorr.py ├── datasets │ ├── __init__.py │ ├── darktrack.py │ ├── dataset.py │ ├── dtb.py │ ├── uav.py │ ├── uav10fps.py │ ├── uav20l.py │ ├── uavdark.py │ ├── uavdt.py │ ├── v4r.py │ ├── video.py │ └── visdrone.py ├── models │ ├── adapn │ │ ├── anchortarget.py │ │ └── utile.py │ ├── adsiamapn_model.py │ ├── apn │ │ ├── anchortarget.py │ │ └── utile.py │ ├── backbone │ │ ├── __init__.py │ │ ├── alexnet.py │ │ ├── googlenet.py │ │ ├── googlenet_ou.py │ │ ├── mobile_v2.py │ │ └── resnet_atrous.py │ ├── dasiamrpn_model.py │ ├── dw │ │ ├── backbones.py │ │ ├── connect.py │ │ ├── modules.py │ │ ├── siamfc.py │ │ └── siamrpn.py │ ├── fcpp │ │ ├── engine │ │ │ ├── __init__.py │ │ │ ├── builder.py │ │ │ └── tester │ │ │ │ ├── __init__.py │ │ │ │ ├── builder.py │ │ │ │ ├── tester_base.py │ │ │ │ └── tester_impl │ │ │ │ ├── __init__.py │ │ │ │ ├── uav.py │ │ │ │ └── utils │ │ │ │ ├── __init__.py │ │ │ │ └── benchmark_helper.py │ │ ├── model │ │ │ ├── __init__.py │ │ │ ├── backbone │ │ │ │ ├── __init__.py │ │ │ │ ├── backbone_base.py │ │ │ │ ├── backbone_impl │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── alexnet_bn.py │ │ │ │ │ └── googlenet.py │ │ │ │ └── builder.py │ │ │ ├── builder.py │ │ │ ├── common_opr │ │ │ │ ├── common_block.py │ │ │ │ └── common_loss.py │ │ │ ├── loss │ │ │ │ ├── __init__.py │ │ │ │ ├── builder.py │ │ │ │ ├── loss_base.py │ │ │ │ └── loss_impl │ │ │ │ │ └── __init__.py │ │ │ ├── module_base.py │ │ │ ├── task_head │ │ │ │ ├── __init__.py │ │ │ │ ├── builder.py │ │ │ │ ├── taskhead_base.py │ │ │ │ └── taskhead_impl │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── track_head.py │ │ │ ├── task_model │ │ │ │ ├── __init__.py │ │ │ │ ├── builder.py │ │ │ │ ├── taskmodel_base.py │ │ │ │ └── taskmodel_impl │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── siamese_track.py │ │ │ └── utils │ │ │ │ └── load_state.py │ │ └── pipeline │ │ │ ├── __init__.py │ │ │ ├── builder.py │ │ │ ├── pipeline_base.py │ │ │ ├── tracker_impl │ │ │ ├── __init__.py │ │ │ ├── siamfcpp_lt_track.py │ │ │ ├── siamfcpp_online_track.py │ │ │ ├── siamfcpp_osdet.py │ │ │ ├── siamfcpp_track.py │ │ │ └── siamfcpp_track_multi_temp.py │ │ │ └── utils │ │ │ ├── __init__.py │ │ │ ├── bbox.py │ │ │ ├── crop.py │ │ │ ├── misc.py │ │ │ └── online_classifier │ │ │ ├── __init__.py │ │ │ ├── base_classifier.py │ │ │ ├── optim.py │ │ │ └── utils │ │ │ ├── __init__.py │ │ │ ├── attention.py │ │ │ ├── augmentation.py │ │ │ ├── complex.py │ │ │ ├── dcf.py │ │ │ ├── fourier.py │ │ │ ├── operation.py │ │ │ ├── optimization.py │ │ │ ├── plotting.py │ │ │ ├── preprocessing.py │ │ │ ├── tensordict.py │ │ │ └── tensorlist.py │ ├── head │ │ ├── __init__.py │ │ ├── ban.py │ │ ├── car.py │ │ ├── mask.py │ │ └── rpn.py │ ├── lighttrack │ │ ├── __init__.py │ │ ├── backbone │ │ │ ├── __init__.py │ │ │ ├── childnet.py │ │ │ ├── models │ │ │ │ ├── __init__.py │ │ │ │ ├── builder.py │ │ │ │ ├── hbuilder.py │ │ │ │ ├── hypernet.py │ │ │ │ ├── model.py │ │ │ │ ├── resunit.py │ │ │ │ ├── units.py │ │ │ │ └── utils.py │ │ │ └── supernet.py │ │ ├── connect.py │ │ ├── models.py │ │ ├── submodels.py │ │ ├── super_connect.py │ │ ├── super_model.py │ │ └── super_model_DP.py │ ├── lighttrack_model.py │ ├── model_builder.py │ ├── neck │ │ ├── __init__.py │ │ └── neck.py │ ├── ocean │ │ ├── backbones.py │ │ ├── connect.py │ │ ├── modules.py │ │ └── ocean.py │ ├── ocean_model.py │ ├── se │ │ ├── connectors.py │ │ ├── feature_extractors.py │ │ ├── se_resnet.py │ │ ├── sesn │ │ │ ├── ses_basis.py │ │ │ └── ses_conv.py │ │ └── siam_fc.py │ ├── sesiam_model.py │ ├── siamapn_model.py │ ├── siamban_model.py │ ├── siamcar_model.py │ ├── siamdw_model.py │ ├── siamgat_model.py │ ├── updatenet_siam_model.py │ └── updatenet_upd_model.py ├── trackers │ ├── adsiamapn_tracker.py │ ├── base_tracker.py │ ├── dasiamrpn_tracker.py │ ├── lighttrack_tracker.py │ ├── ocean_tracker.py │ ├── sesiam_fc_tracker.py │ ├── siamapn_tracker.py │ ├── siamban_tracker.py │ ├── siamcar_tracker.py │ ├── siamdw_fc_tracker.py │ ├── siamdw_rpn_tracker.py │ ├── siamgat_tracker.py │ ├── siammask_tracker.py │ ├── siamrpn_tracker.py │ ├── siamrpnlt_tracker.py │ ├── tracker_builder.py │ ├── tracker_builder_ban.py │ └── updatenet_tracker.py └── utils │ ├── anchor.py │ ├── bbox.py │ ├── evaluation │ ├── __init__.py │ └── ope_benchmark.py │ ├── misc.py │ ├── model_load.py │ ├── statistics.py │ ├── utils_ad.py │ ├── utils_dw.py │ ├── utils_fcpp │ ├── __init__.py │ ├── image.py │ ├── misc.py │ ├── path.py │ └── torch_module.py │ ├── utils_lighttrack.py │ ├── utils_ocean.py │ ├── utils_se.py │ ├── utils_upd.py │ └── visualization │ ├── __init__.py │ ├── draw_success_precision.py │ └── draw_utils.py └── tools ├── eval.py ├── test.py ├── test.sh ├── test_dasiamrpn.py ├── test_lighttrack.py ├── test_ocean.py ├── test_sesiamfc.py ├── test_siamapn++.py ├── test_siamapn.py ├── test_siamban.py ├── test_siamcar.py ├── test_siamdw_fc.py ├── test_siamdw_rpn.py ├── test_siamfc++.py ├── test_siamgat.py ├── test_siammask.py ├── test_siamrpn++.py └── test_updatenet.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Intelligent Vision for Robotics in Complex Environment 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /experiments/DaSiamRPN/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Qiang Wang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /experiments/DaSiamRPN/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: DaSiamRPN] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of DaSiamRPN can be found at: [SiamRPNBIG.model](https://pan.baidu.com/s/176hwPPl8tOiUU2kCggmHPQ?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/foolwood/DaSiamRPN . -------------------------------------------------------------------------------- /experiments/LightTrack/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Multimedia Research 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /experiments/LightTrack/LightTrack.yaml: -------------------------------------------------------------------------------- 1 | TEST: 2 | VOT2019: # LightTrack Mobile (EAO 0.333) 3 | penalty_k: 0.007 4 | lr: 0.616 5 | window_influence: 0.225 6 | small_sz: 256 7 | big_sz: 288 8 | ratio: 1 -------------------------------------------------------------------------------- /experiments/LightTrack/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: LightTrack] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of LightTrack can be found at: [model.pth](https://pan.baidu.com/s/1W6OcCIkW1q6sbC7kndsHqA?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/researchmm/LightTrack . -------------------------------------------------------------------------------- /experiments/Ocean/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 eccv2020 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /experiments/Ocean/Ocean_UAV123.yaml: -------------------------------------------------------------------------------- 1 | TEST: 2 | UAV123: 3 | penalty_k: 0.08 4 | lr: 0.305 5 | window_influence: 0.44 6 | small_sz: 127 7 | big_sz: 287 8 | 9 | -------------------------------------------------------------------------------- /experiments/Ocean/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: Ocean] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of Ocean can be found at: [model.pth](https://pan.baidu.com/s/1Zcnw0lUb0E_WPWyW0bsknw?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/researchmm/TracKit . -------------------------------------------------------------------------------- /experiments/SESiamFC/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Ivan Sosnovik, Artem Moskalev 4 | Copyright (c) 2020 Ivan Sosnovik, Michał Szmaja 5 | Copyright (c) 2018 Microsoft (Houwen Peng, Zhipeng Zhang) 6 | 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. -------------------------------------------------------------------------------- /experiments/SESiamFC/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: SE-SiamFC] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of SE-SiamFC can be found at: [model.pth](https://pan.baidu.com/s/1ZLblL9h3v32MeNH0uIDQpA?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/isosnovik/SiamSE . -------------------------------------------------------------------------------- /experiments/SESiamFC/config.yaml: -------------------------------------------------------------------------------- 1 | MODEL: "SESiamFCResNet22" 2 | TRACKER: 3 | OTB2013: # 0.6814 4 | scale_step: 1.145 5 | scale_lr: 0.08 6 | scale_penalty: 1.0 7 | w_influence: 0.3 8 | OTB2015: # 0.6608 9 | scale_step: 1.1633 10 | scale_lr: 0.171 11 | scale_penalty: 0.9995 12 | w_influence: 0.251 13 | VOT2016: # 0.3636 (eao) 14 | scale_step: 1.105 15 | scale_lr: 0.43 16 | scale_penalty: 1.0 17 | w_influence: 0.3 18 | VOT2017: # 0.2701 (eao) 19 | scale_step: 1.0633 20 | scale_lr: 0.349 21 | scale_penalty: 0.9725 22 | w_influence: 0.224 -------------------------------------------------------------------------------- /experiments/SiamAPN++/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: SiamAPN++] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of SiamAPN++ can be found at: [model.pth](https://pan.baidu.com/s/1tbemYlshgtx8kjer4j4_HQ?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/vision4robotics/SiamAPN . -------------------------------------------------------------------------------- /experiments/SiamAPN++/config.yaml: -------------------------------------------------------------------------------- 1 | META_ARC: "ADSiamAPN_alexnet" 2 | 3 | BACKBONE: 4 | TYPE: "alexnet" 5 | PRETRAINED: 'alexnet-bn.pth' 6 | TRAIN_LAYERS: ['layer3','layer4','layer5'] 7 | TRAIN_EPOCH: 10 8 | LAYERS_LR: 0.1 9 | 10 | TRACK: 11 | TYPE: 'ADSiamAPNtracker' 12 | EXEMPLAR_SIZE: 127 13 | INSTANCE_SIZE: 287 14 | CONTEXT_AMOUNT: 0.5 15 | STRIDE: 8 16 | w1: 1.2 17 | w2: 1.3 18 | w3: 1.1 19 | 20 | TRAIN: 21 | EPOCH: 50 22 | START_EPOCH: 0 23 | epochthrelod: 0 24 | SEARCH_SIZE: 287 25 | BATCH_SIZE: 220 26 | NUM_GPU: 2 27 | BASE_LR: 0.005 28 | RESUME: '' 29 | WEIGHT_DECAY : 0.0001 30 | PRETRAINED: '' 31 | OUTPUT_SIZE: 21 32 | NUM_WORKERS: 7 33 | LOC_WEIGHT: 2.2 34 | CLS_WEIGHT: 1.0 35 | SHAPE_WEIGHT: 1.8 36 | w1: 1.2 37 | w2: 1.3 38 | w3: 1.1 39 | w4: 1.5 40 | w5: 1.0 41 | 42 | POS_NUM : 16 43 | TOTAL_NUM : 64 44 | NEG_NUM : 16 45 | LARGER: 1.0 46 | range : 1.0 47 | LR: 48 | TYPE: 'log' 49 | KWARGS: 50 | start_lr: 0.01 51 | end_lr: 0.0005 52 | 53 | LR_WARMUP: 54 | TYPE: 'step' 55 | EPOCH: 5 56 | KWARGS: 57 | start_lr: 0.005 58 | end_lr: 0.01 59 | step: 1 60 | 61 | DATASET: 62 | NAMES: 63 | - 'VID' 64 | - 'COCO' 65 | - 'GOT' 66 | - 'YOUTUBEBB' 67 | 68 | 69 | TEMPLATE: 70 | SHIFT: 4 71 | SCALE: 0.05 72 | BLUR: 0.0 73 | FLIP: 0.0 74 | COLOR: 1.0 75 | 76 | SEARCH: 77 | SHIFT: 64 78 | SCALE: 0.18 79 | BLUR: 0.2 80 | FLIP: 0.0 81 | COLOR: 1.0 82 | 83 | NEG: 0.05 84 | GRAY: 0.0 85 | -------------------------------------------------------------------------------- /experiments/SiamAPN/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: SiamAPN] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of SiamAPN can be found at: [model.pth](https://pan.baidu.com/s/1rtlxVnWHjWHrNfIJqI6dNw?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/vision4robotics/SiamAPN . -------------------------------------------------------------------------------- /experiments/SiamAPN/config.yaml: -------------------------------------------------------------------------------- 1 | META_ARC: "SiamAPN_alexnet" 2 | 3 | BACKBONE: 4 | TYPE: "alexnet" 5 | PRETRAINED: 'alexnet-bn.pth' 6 | TRAIN_LAYERS: ['layer3','layer4','layer5'] 7 | TRAIN_EPOCH: 10 8 | LAYERS_LR: 0.1 9 | 10 | TRACK: 11 | TYPE: 'SiamAPNtracker' 12 | EXEMPLAR_SIZE: 127 13 | INSTANCE_SIZE: 287 14 | CONTEXT_AMOUNT: 0.5 15 | STRIDE: 8 16 | PENALTY_K: 0.08 17 | LR: 0.302 18 | w1: 1.18 19 | w2: 1.0 20 | w3: 1.0 21 | 22 | TRAIN: 23 | EPOCH: 50 24 | START_EPOCH: 0 25 | BATCH_SIZE: 124 26 | NUM_GPU: 2 27 | BASE_LR: 0.005 28 | RESUME: '' 29 | WEIGHT_DECAY : 0.0001 30 | PRETRAINED: '' 31 | OUTPUT_SIZE: 21 32 | NUM_WORKERS: 8 33 | LOC_WEIGHT: 1.0 34 | CLS_WEIGHT: 1.0 35 | SHAPE_WEIGHT: 1.0 36 | w1: 1.2 37 | w2: 1.0 38 | w3: 1.0 39 | w4: 1.0 40 | w5: 1.0 41 | POS_NUM : 16 42 | TOTAL_NUM : 64 43 | NEG_NUM : 16 44 | LARGER: 1.0 45 | range : 1.0 46 | LR: 47 | TYPE: 'log' 48 | KWARGS: 49 | start_lr: 0.01 50 | end_lr: 0.0005 51 | 52 | LR_WARMUP: 53 | TYPE: 'step' 54 | EPOCH: 5 55 | KWARGS: 56 | start_lr: 0.005 57 | end_lr: 0.01 58 | step: 1 59 | 60 | DATASET: 61 | NAMES: 62 | - 'VID' 63 | - 'COCO' 64 | - 'GOT' 65 | - 'YOUTUBEBB' 66 | 67 | 68 | TEMPLATE: 69 | SHIFT: 4 70 | SCALE: 0.05 71 | BLUR: 0.0 72 | FLIP: 0.0 73 | COLOR: 1.0 74 | 75 | SEARCH: 76 | SHIFT: 64 77 | SCALE: 0.18 78 | BLUR: 0.2 79 | FLIP: 0.0 80 | COLOR: 1.0 81 | 82 | NEG: 0.05 83 | GRAY: 0.0 84 | -------------------------------------------------------------------------------- /experiments/SiamBAN/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: SiamBAN] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of SiamBAN can be found at: [model.pth](https://pan.baidu.com/s/14bHbGZd4R9q4ye2HjCkOVw?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/hqucv/siamban . -------------------------------------------------------------------------------- /experiments/SiamBAN/config.yaml: -------------------------------------------------------------------------------- 1 | META_ARC: "siamban_r50_l234" 2 | 3 | BACKBONE: 4 | TYPE: "resnet50" 5 | KWARGS: 6 | used_layers: [2, 3, 4] 7 | PRETRAINED: 'pretrained_models/resnet50.model' 8 | TRAIN_LAYERS: ['layer2', 'layer3', 'layer4'] 9 | TRAIN_EPOCH: 10 10 | LAYERS_LR: 0.1 11 | 12 | ADJUST: 13 | ADJUST: True 14 | TYPE: "AdjustAllLayer" 15 | KWARGS: 16 | in_channels: [512, 1024, 2048] 17 | out_channels: [256, 256, 256] 18 | 19 | BAN: 20 | BAN: True 21 | TYPE: 'MultiBAN' 22 | KWARGS: 23 | in_channels: [256, 256, 256] 24 | cls_out_channels: 2 # if use sigmoid cls, cls_out_channel = 1 else 2 25 | weighted: True 26 | 27 | POINT: 28 | STRIDE: 8 29 | 30 | TRACK: 31 | TYPE: 'SiamBANTracker' 32 | WINDOW_INFLUENCE: 0.4632532824922313 # VOT2018 33 | PENALTY_K: 0.08513642556896711 # VOT2018 34 | LR: 0.44418184746462425 # VOT2018 35 | # WINDOW_INFLUENCE: 0.334450048565355 # VOT2019 36 | # PENALTY_K: 0.0012159181005195463 # VOT2019 37 | # LR: 0.46386814967815493 # VOT2019 38 | EXEMPLAR_SIZE: 127 39 | INSTANCE_SIZE: 255 40 | BASE_SIZE: 8 41 | CONTEXT_AMOUNT: 0.5 42 | 43 | TRAIN: 44 | EPOCH: 20 45 | START_EPOCH: 0 # 0 or resume checkpoint 46 | BATCH_SIZE: 28 47 | BASE_LR: 0.005 48 | CLS_WEIGHT: 1.0 49 | LOC_WEIGHT: 1.0 50 | RESUME: '' # '' or 'snapshot/checkpoint_e.pth' 51 | 52 | LR: 53 | TYPE: 'log' 54 | KWARGS: 55 | start_lr: 0.005 56 | end_lr: 0.00005 57 | LR_WARMUP: 58 | TYPE: 'step' 59 | EPOCH: 5 60 | KWARGS: 61 | start_lr: 0.001 62 | end_lr: 0.005 63 | step: 1 64 | 65 | DATASET: 66 | NAMES: 67 | - 'VID' 68 | - 'YOUTUBEBB' 69 | - 'COCO' 70 | - 'DET' 71 | - 'GOT10K' 72 | - 'LASOT' 73 | 74 | VIDEOS_PER_EPOCH: 1000000 75 | 76 | TEMPLATE: 77 | SHIFT: 4 78 | SCALE: 0.05 79 | BLUR: 0.0 80 | FLIP: 0.0 81 | COLOR: 1.0 82 | 83 | SEARCH: 84 | SHIFT: 64 85 | SCALE: 0.18 86 | BLUR: 0.2 87 | FLIP: 0.0 88 | COLOR: 1.0 89 | 90 | NEG: 0.2 91 | GRAY: 0.0 92 | -------------------------------------------------------------------------------- /experiments/SiamCAR/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: SiamCAR] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of SiamCAR can be found at: [model.pth](https://pan.baidu.com/s/1ncwRdQeXbGj6xJwUuehzew?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/ohhhyeahhh/SiamCAR . -------------------------------------------------------------------------------- /experiments/SiamCAR/config.yaml: -------------------------------------------------------------------------------- 1 | META_ARC: "siamcar_r50" 2 | 3 | BACKBONE: 4 | TYPE: "resnet50" 5 | KWARGS: 6 | used_layers: [2, 3, 4] 7 | PRETRAINED: '' 8 | TRAIN_LAYERS: ['layer2','layer3','layer4'] 9 | TRAIN_EPOCH: 10 10 | LAYERS_LR: 0.1 11 | 12 | ADJUST: 13 | ADJUST: true 14 | TYPE: "AdjustAllLayer" 15 | KWARGS: 16 | in_channels: [512, 1024, 2048] 17 | out_channels: [256, 256, 256] 18 | 19 | 20 | TRACK: 21 | TYPE: 'SiamCARTracker' 22 | PENALTY_K: 0.04 23 | WINDOW_INFLUENCE: 0.44 24 | LR: 0.33 25 | EXEMPLAR_SIZE: 127 26 | INSTANCE_SIZE: 255 27 | CONTEXT_AMOUNT: 0.5 28 | STRIDE: 8 29 | 30 | TRAIN: 31 | EPOCH: 20 32 | START_EPOCH: 0 33 | BATCH_SIZE: 80 # 32 34 | BASE_LR: 0.005 35 | CLS_WEIGHT: 1.0 36 | LOC_WEIGHT: 3.0 37 | CEN_WEIGHT: 1.0 38 | RESUME: '' 39 | NUM_CLASSES: 2 40 | NUM_CONVS: 4 41 | PRIOR_PROB: 0.01 42 | OUTPUT_SIZE: 25 # 31 43 | 44 | LR: 45 | TYPE: 'log' 46 | KWARGS: 47 | start_lr: 0.005 48 | end_lr: 0.0005 49 | LR_WARMUP: 50 | TYPE: 'step' 51 | EPOCH: 5 52 | KWARGS: 53 | start_lr: 0.001 54 | end_lr: 0.005 55 | step: 1 56 | 57 | DATASET: 58 | NAMES: 59 | - 'VID' #dataset++ 60 | 61 | 62 | TEMPLATE: 63 | SHIFT: 4 64 | SCALE: 0.05 65 | BLUR: 0.0 66 | FLIP: 0.0 67 | COLOR: 1.0 68 | 69 | SEARCH: 70 | SHIFT: 64 71 | SCALE: 0.18 72 | BLUR: 0.2 73 | FLIP: 0.0 74 | COLOR: 1.0 75 | 76 | NEG: 0.0 77 | GRAY: 0.0 78 | -------------------------------------------------------------------------------- /experiments/SiamDW_FCIncep22/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 cvpr2019 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /experiments/SiamDW_FCIncep22/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: SiamFC+_CI] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of SiamFC+_CI (SiamDW: FC + CIResInception-22) can be found at: [model.pth](https://pan.baidu.com/s/1YQe9C09slrjP513l4E0Grw?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/researchmm/SiamDW and https://github.com/researchmm/TracKit . -------------------------------------------------------------------------------- /experiments/SiamDW_FCIncep22/SiamFCIncep22_VOT.yaml: -------------------------------------------------------------------------------- 1 | TEST: 2 | VOT2015: 3 | scale_step: 1.1755 4 | scale_lr: 0.3407 5 | scale_penalty: 0.9807 6 | w_influence: 0.3254 7 | VOT2016: 8 | scale_step: 1.1859 9 | scale_lr: 0.5921 10 | scale_penalty: 0.9359 11 | w_influence: 0.2616 12 | VOT2017: 13 | scale_step: 1.1679 14 | scale_lr: 0.6782 15 | scale_penalty: 0.9285 16 | w_influence: 0.2566 -------------------------------------------------------------------------------- /experiments/SiamDW_FCNext22/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 cvpr2019 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /experiments/SiamDW_FCNext22/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: SiamFC+_CX] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of SiamFC+_CX (SiamDW: FC + CIResNeXt-22) can be found at: [model.pth](https://pan.baidu.com/s/1yJOZjSHQze5o4fpZncrEwA?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/researchmm/SiamDW and https://github.com/researchmm/TracKit . -------------------------------------------------------------------------------- /experiments/SiamDW_FCNext22/SiamFCNext22_VOT.yaml: -------------------------------------------------------------------------------- 1 | TEST: 2 | VOT2015: 3 | scale_step: 1.1849 4 | scale_lr: 0.3373 5 | scale_penalty: 0.9417 6 | w_influence: 0.2518 7 | instance_size: 263 8 | VOT2016: 9 | scale_step: 1.1561 10 | scale_lr: 0.1615 11 | scale_penalty: 0.9593 12 | w_influence: 0.2548 13 | instance_size: 263 14 | VOT2017: 15 | scale_step: 1.1531 16 | scale_lr: 0.5706 17 | scale_penalty: 0.9489 18 | w_influence: 0.2581 19 | instance_size: 255 20 | -------------------------------------------------------------------------------- /experiments/SiamDW_FCRes22/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 cvpr2019 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /experiments/SiamDW_FCRes22/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: SiamFC+_CR] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of SiamFC+_CR (SiamDW: FC + CIResNet-22) can be found at: [model.pth](https://pan.baidu.com/s/1ohyG6CkWSJC94BqWEewuxQ?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/researchmm/SiamDW and https://github.com/researchmm/TracKit . -------------------------------------------------------------------------------- /experiments/SiamDW_FCRes22/SiamFCRes22_VOT.yaml: -------------------------------------------------------------------------------- 1 | TEST: 2 | VOT2015: 3 | scale_step: 1.1190 4 | scale_lr: 0.4373 5 | scale_penalty: 0.9811 6 | w_influence: 0.2569 7 | VOT2016: 8 | scale_step: 1.1535 9 | scale_lr: 0.4596 10 | scale_penalty: 0.9259 11 | w_influence: 0.3309 12 | VOT2017: 13 | scale_step: 1.1466 14 | scale_lr: 0.2061 15 | scale_penalty: 0.9994 16 | w_influence: 0.3242 -------------------------------------------------------------------------------- /experiments/SiamDW_RPNRes22/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 cvpr2019 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /experiments/SiamDW_RPNRes22/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: SiamRPN+_CR] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of SiamRPN+_CR (SiamDW: RPN + CIResNet-22) can be found at: [model.pth](https://pan.baidu.com/s/1KYOdcOmWFPzNEZWtzNsg2A?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/researchmm/SiamDW and https://github.com/researchmm/TracKit . -------------------------------------------------------------------------------- /experiments/SiamDW_RPNRes22/SiamRPNRes22_VOT.yaml: -------------------------------------------------------------------------------- 1 | TEST: 2 | VOT2015: 3 | penalty_k: 0.8950 4 | lr: 0.6540 5 | window_influence: 0.3700 6 | VOT2016: 7 | penalty_k: 0.7110 8 | lr: 0.7010 9 | window_influence: 0.3550 10 | VOT2017: 11 | penalty_k: 0.038 12 | lr: 0.388 13 | window_influence: 0.347 14 | -------------------------------------------------------------------------------- /experiments/SiamFC++/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 MegviiDetection 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /experiments/SiamFC++/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: SiamFC++] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of SiamFC++ can be found at: [siamfcpp-googlenet.pkl](https://pan.baidu.com/s/17Kf3p-xNM9oSLGjTkN-7rw?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/MegviiDetection/video_analyst . -------------------------------------------------------------------------------- /experiments/SiamFC++/siamfcpp_googlenet.yaml: -------------------------------------------------------------------------------- 1 | test: 2 | track: 3 | exp_name: &TEST_NAME "siamfcpp_googlenet" 4 | exp_save: &TEST_SAVE "logs" 5 | model: 6 | backbone: 7 | name: "Inception3" 8 | Inception3: 9 | crop_pad: 4 10 | pruned: True 11 | losses: 12 | names: [] 13 | task_head: 14 | name: "DenseboxHead" 15 | DenseboxHead: 16 | total_stride: 8 17 | score_size: &SCORE_SIZE_TEST 19 18 | x_size: &X_SIZE_TEST 303 19 | num_conv3x3: &NUM_CONV3x3 2 20 | head_conv_bn: [False, False] 21 | task_model: 22 | name: "SiamTrack" 23 | SiamTrack: 24 | pretrain_model_path: "./experiments/SiamFC++_google/siamfcpp-googlenet.pkl" 25 | pipeline: 26 | name: "SiamFCppTracker" 27 | SiamFCppTracker: 28 | test_lr: 0.5222592132697174 29 | window_influence: 0.2414722810296582 30 | penalty_k: 0.0730171190610408 31 | x_size: *X_SIZE_TEST 32 | num_conv3x3: *NUM_CONV3x3 33 | tester: 34 | names: ["UAVTester",] 35 | UAVTester: 36 | exp_name: *TEST_NAME 37 | exp_save: *TEST_SAVE 38 | device_num: 1 39 | subsets: [""] 40 | -------------------------------------------------------------------------------- /experiments/SiamGAT/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: SiamGAT] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of SiamGAT can be found at: [model.pth](https://pan.baidu.com/s/1EqBAqX_0tA_OaL--eRLHgQ?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/ohhhyeahhh/SiamGAT . -------------------------------------------------------------------------------- /experiments/SiamGAT/config.yaml: -------------------------------------------------------------------------------- 1 | META_ARC: "siamgat_googlenet" 2 | 3 | BACKBONE: 4 | TYPE: "googlenet_ou" 5 | PRETRAINED: 'pretrained_models/inception_v3.pth' 6 | TRAIN_LAYERS: ['Mixed_5b','Mixed_5c','Mixed_5d', 'Mixed_6a', 'Mixed_6b', 'Mixed_6c', 'Mixed_6d', 'Mixed_6e', 'channel_reduce'] 7 | CHANNEL_REDUCE_LAYERS: ['channel_reduce'] 8 | TRAIN_EPOCH: 10 9 | CROP_PAD: 4 10 | LAYERS_LR: 0.1 11 | 12 | TRACK: 13 | TYPE: 'SiamGATTracker' 14 | EXEMPLAR_SIZE: 127 15 | INSTANCE_SIZE: 287 16 | SCORE_SIZE: 25 17 | CONTEXT_AMOUNT: 0.5 18 | STRIDE: 8 19 | OFFSET: 45 20 | 21 | TRAIN: 22 | EPOCH: 20 23 | START_EPOCH: 0 24 | SEARCH_SIZE: 287 25 | BATCH_SIZE: 76 26 | CLS_WEIGHT: 1.0 27 | LOC_WEIGHT: 3.0 28 | CEN_WEIGHT: 1.0 29 | RESUME: '' 30 | PRETRAINED: '' 31 | NUM_CLASSES: 2 32 | NUM_CONVS: 4 33 | PRIOR_PROB: 0.01 34 | OUTPUT_SIZE: 25 35 | ATTENTION: True 36 | 37 | LR: 38 | TYPE: 'log' 39 | KWARGS: 40 | start_lr: 0.01 41 | end_lr: 0.0005 42 | LR_WARMUP: 43 | TYPE: 'step' 44 | EPOCH: 5 45 | KWARGS: 46 | start_lr: 0.005 47 | end_lr: 0.01 48 | step: 1 49 | 50 | DATASET: 51 | NAMES: 52 | - 'VID' 53 | - 'YOUTUBEBB' 54 | - 'COCO' 55 | - 'DET' 56 | - 'GOT' 57 | 58 | VIDEOS_PER_EPOCH: 800000 59 | 60 | TEMPLATE: 61 | SHIFT: 4 62 | SCALE: 0.05 63 | BLUR: 0.0 64 | FLIP: 0.0 65 | COLOR: 1.0 66 | 67 | SEARCH: 68 | SHIFT: 64 69 | SCALE: 0.18 70 | BLUR: 0.2 71 | FLIP: 0.0 72 | COLOR: 1.0 73 | 74 | NEG: 0.2 75 | GRAY: 0.0 76 | -------------------------------------------------------------------------------- /experiments/SiamMask/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: SiamMask] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of SiamMask can be found at: [model.pth](https://pan.baidu.com/s/1IB27d6xOpTLPx47rqjJOgg?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/foolwood/SiamMask and https://github.com/STVIR/pysot . -------------------------------------------------------------------------------- /experiments/SiamMask/config.yaml: -------------------------------------------------------------------------------- 1 | META_ARC: "siamrpn_r50_l234_dwxcorr" 2 | 3 | BACKBONE: 4 | TYPE: "resnet50" 5 | KWARGS: 6 | used_layers: [0, 1, 2, 3] 7 | 8 | ADJUST: 9 | ADJUST: true 10 | TYPE: "AdjustAllLayer" 11 | KWARGS: 12 | in_channels: [1024] 13 | out_channels: [256] 14 | 15 | RPN: 16 | TYPE: 'DepthwiseRPN' 17 | KWARGS: 18 | anchor_num: 5 19 | in_channels: 256 20 | out_channels: 256 21 | 22 | MASK: 23 | MASK: True 24 | TYPE: 'MaskCorr' 25 | KWARGS: 26 | in_channels: 256 27 | hidden: 256 28 | out_channels: 3969 29 | 30 | REFINE: 31 | REFINE: True 32 | TYPE: 'Refine' 33 | 34 | ANCHOR: 35 | STRIDE: 8 36 | RATIOS: [0.33, 0.5, 1, 2, 3] 37 | SCALES: [8] 38 | ANCHOR_NUM: 5 39 | 40 | TRACK: 41 | TYPE: 'SiamMaskTracker' 42 | PENALTY_K: 0.10 43 | WINDOW_INFLUENCE: 0.41 44 | LR: 0.32 45 | EXEMPLAR_SIZE: 127 46 | INSTANCE_SIZE: 255 47 | BASE_SIZE: 8 48 | CONTEXT_AMOUNT: 0.5 49 | MASK_THERSHOLD: 0.15 50 | -------------------------------------------------------------------------------- /experiments/SiamMask/convert_model.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from collections import OrderedDict 3 | 4 | model = torch.load('SiamMask_VOT_LD.pth', map_location=lambda storage, loc: storage) 5 | 6 | new_model = OrderedDict() 7 | 8 | for k, v in model.items(): 9 | if k.startswith('features.features'): 10 | k = k.replace('features.features', 'backbone') 11 | elif k.startswith('features'): 12 | k = k.replace('features', 'neck') 13 | elif k.startswith('rpn_model'): 14 | k = k.replace('rpn_model', 'rpn_head') 15 | elif k.startswith('mask_model'): 16 | k = k.replace('mask_model.mask', 'mask_head') 17 | elif k.startswith('refine_model'): 18 | k = k.replace('refine_model', 'refine_head') 19 | new_model[k] = v 20 | 21 | torch.save(new_model, 'model.pth') 22 | -------------------------------------------------------------------------------- /experiments/SiamRPN++_alex/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: SiamRPN++_A] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of SiamRPN++_A (SiamRPN++: AlexNet) can be found at: [model.pth](https://pan.baidu.com/s/1bbgmBAAh2U7_XgogQdskYg?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/STVIR/pysot . -------------------------------------------------------------------------------- /experiments/SiamRPN++_alex/config.yaml: -------------------------------------------------------------------------------- 1 | META_ARC: "siamrpn_alex_dwxcorr" 2 | 3 | BACKBONE: 4 | TYPE: "alexnetlegacy" 5 | KWARGS: 6 | width_mult: 1.0 7 | 8 | ADJUST: 9 | ADJUST: False 10 | 11 | RPN: 12 | TYPE: 'DepthwiseRPN' 13 | KWARGS: 14 | anchor_num: 5 15 | in_channels: 256 16 | out_channels: 256 17 | 18 | MASK: 19 | MASK: False 20 | 21 | ANCHOR: 22 | STRIDE: 8 23 | RATIOS: [0.33, 0.5, 1, 2, 3] 24 | SCALES: [8] 25 | ANCHOR_NUM: 5 26 | 27 | TRACK: 28 | TYPE: 'SiamRPNTracker' 29 | PENALTY_K: 0.16 30 | WINDOW_INFLUENCE: 0.40 31 | LR: 0.30 32 | EXEMPLAR_SIZE: 127 33 | INSTANCE_SIZE: 287 34 | BASE_SIZE: 0 35 | CONTEXT_AMOUNT: 0.5 36 | -------------------------------------------------------------------------------- /experiments/SiamRPN++_mobilev2/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: SiamRPN++_M] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of SiamRPN++_M (SiamRPN++: MobileNetV2) can be found at: [model.pth](https://pan.baidu.com/s/1kycg8HF_yimK4vwINTiUiQ?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/STVIR/pysot . -------------------------------------------------------------------------------- /experiments/SiamRPN++_mobilev2/config.yaml: -------------------------------------------------------------------------------- 1 | META_ARC: "siamrpn_mobilev2_l234_dwxcorr" 2 | 3 | BACKBONE: 4 | TYPE: "mobilenetv2" 5 | KWARGS: 6 | used_layers: [3, 5, 7] 7 | width_mult: 1.4 8 | 9 | ADJUST: 10 | ADJUST: true 11 | TYPE: "AdjustAllLayer" 12 | KWARGS: 13 | in_channels: [44, 134, 448] 14 | out_channels: [256, 256, 256] 15 | 16 | RPN: 17 | TYPE: 'MultiRPN' 18 | KWARGS: 19 | anchor_num: 5 20 | in_channels: [256, 256, 256] 21 | weighted: False 22 | 23 | MASK: 24 | MASK: False 25 | 26 | ANCHOR: 27 | STRIDE: 8 28 | RATIOS: [0.33, 0.5, 1, 2, 3] 29 | SCALES: [8] 30 | ANCHOR_NUM: 5 31 | 32 | TRACK: 33 | TYPE: 'SiamRPNTracker' 34 | PENALTY_K: 0.04 35 | WINDOW_INFLUENCE: 0.4 36 | LR: 0.5 37 | EXEMPLAR_SIZE: 127 38 | INSTANCE_SIZE: 255 39 | BASE_SIZE: 8 40 | CONTEXT_AMOUNT: 0.5 41 | -------------------------------------------------------------------------------- /experiments/SiamRPN++_r50/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: SiamRPN++_R] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of SiamRPN++_R (SiamRPN++: ResNet-50) can be found at: [model.pth](https://pan.baidu.com/s/1irzmN194B3pn1IBJuOCp8Q?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/STVIR/pysot . -------------------------------------------------------------------------------- /experiments/SiamRPN++_r50/config.yaml: -------------------------------------------------------------------------------- 1 | META_ARC: "siamrpn_r50_l234_dwxcorr" 2 | 3 | BACKBONE: 4 | TYPE: "resnet50" 5 | KWARGS: 6 | used_layers: [2, 3, 4] 7 | 8 | ADJUST: 9 | ADJUST: true 10 | TYPE: "AdjustAllLayer" 11 | KWARGS: 12 | in_channels: [512, 1024, 2048] 13 | out_channels: [256, 256, 256] 14 | 15 | RPN: 16 | TYPE: 'MultiRPN' 17 | KWARGS: 18 | anchor_num: 5 19 | in_channels: [256, 256, 256] 20 | weighted: true 21 | 22 | MASK: 23 | MASK: false 24 | 25 | ANCHOR: 26 | STRIDE: 8 27 | RATIOS: [0.33, 0.5, 1, 2, 3] 28 | SCALES: [8] 29 | ANCHOR_NUM: 5 30 | 31 | TRACK: 32 | TYPE: 'SiamRPNTracker' 33 | PENALTY_K: 0.05 34 | WINDOW_INFLUENCE: 0.42 35 | LR: 0.38 36 | EXEMPLAR_SIZE: 127 37 | INSTANCE_SIZE: 255 38 | BASE_SIZE: 8 39 | CONTEXT_AMOUNT: 0.5 40 | -------------------------------------------------------------------------------- /experiments/UpdateNet/README.md: -------------------------------------------------------------------------------- 1 | # [SiameseTracking4UAV: UpdateNet] 2 | 3 | ## Model prepare 4 | 5 | Before your own test, please download the pretrained model put it into this folder. 6 | The model of UpdateNet (based on DaSiamRPN) can be found at: [vot2018.pth.tar](https://pan.baidu.com/s/1C1RbqvkQH_6ccM8yk4KvJg?pwd=siam)(code:siam) and [SiamRPNBIG.model](https://pan.baidu.com/s/176hwPPl8tOiUU2kCggmHPQ?pwd=siam)(code:siam). 7 | You can also download it from official code site: https://github.com/zhanglichao/updatenet and https://github.com/foolwood/DaSiamRPN . -------------------------------------------------------------------------------- /figures/Attributes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/figures/Attributes.pdf -------------------------------------------------------------------------------- /figures/Attributes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/figures/Attributes.png -------------------------------------------------------------------------------- /figures/DTB70.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/figures/DTB70.zip -------------------------------------------------------------------------------- /figures/Normalized Precision and FPS.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/figures/Normalized Precision and FPS.pdf -------------------------------------------------------------------------------- /figures/Normalized Precision and FPS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/figures/Normalized Precision and FPS.png -------------------------------------------------------------------------------- /figures/Precision and FPS.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/figures/Precision and FPS.pdf -------------------------------------------------------------------------------- /figures/Precision and FPS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/figures/Precision and FPS.png -------------------------------------------------------------------------------- /figures/Success and FPS.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/figures/Success and FPS.pdf -------------------------------------------------------------------------------- /figures/Success and FPS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/figures/Success and FPS.png -------------------------------------------------------------------------------- /figures/UAV123@10fps.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/figures/UAV123@10fps.zip -------------------------------------------------------------------------------- /figures/UAV20L.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/figures/UAV20L.zip -------------------------------------------------------------------------------- /figures/UAVDT.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/figures/UAVDT.zip -------------------------------------------------------------------------------- /figures/UAVTrack112.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/figures/UAVTrack112.zip -------------------------------------------------------------------------------- /figures/VisDrone2020.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/figures/VisDrone2020.zip -------------------------------------------------------------------------------- /pipelines/dasiamrpn_pipeline.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import numpy as np 7 | import torch 8 | 9 | from snot.models.dasiamrpn_model import SiamRPNBIG 10 | from snot.trackers.dasiamrpn_tracker import SiamRPN_init, SiamRPN_track 11 | from snot.utils.bbox import get_axis_aligned_bbox 12 | 13 | 14 | class DaSiamRPNPipeline(): 15 | def __init__(self, args): 16 | super(DaSiamRPNPipeline, self).__init__() 17 | if not args.snapshot: 18 | args.snapshot = './experiments/DaSiamRPN/SiamRPNBIG.model' 19 | 20 | self.net = SiamRPNBIG() 21 | self.net.load_state_dict(torch.load(args.snapshot)) 22 | self.net.eval().cuda() 23 | 24 | def init(self, img, gt_bbox): 25 | cx, cy, w, h = get_axis_aligned_bbox(np.array(gt_bbox)) 26 | gt_bbox_ = [cx-(w-1)/2, cy-(h-1)/2, w, h] 27 | target_pos = np.array([cx, cy]) 28 | target_sz = np.array([w, h]) 29 | self.state = SiamRPN_init(img, target_pos, target_sz, self.net) 30 | pred_bbox = gt_bbox_ 31 | 32 | return pred_bbox 33 | 34 | def track(self, img): 35 | self.state = SiamRPN_track(self.state, img) 36 | target_pos=self.state['target_pos'] 37 | target_sz=self.state['target_sz'] 38 | pred_bbox=np.array([target_pos[0]-target_sz[0]/2, target_pos[1]-target_sz[1]/2, target_sz[0], target_sz[1]]) 39 | 40 | return pred_bbox 41 | 42 | -------------------------------------------------------------------------------- /pipelines/lighttrack_pipeline.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import numpy as np 7 | 8 | from easydict import EasyDict as edict 9 | from snot.models import lighttrack_model as models 10 | from snot.trackers.lighttrack_tracker import Lighttrack 11 | from snot.utils.bbox import get_axis_aligned_bbox 12 | from snot.utils.model_load import load_pretrain 13 | 14 | 15 | class LightTrackPipeline(): 16 | def __init__(self, args): 17 | super(LightTrackPipeline, self).__init__() 18 | if not args.arch: 19 | args.arch = 'LightTrackM_Subnet' 20 | if not args.snapshot: 21 | args.snapshot = './experiments/LightTrack/model.pth' 22 | if not args.path_name: 23 | args.path_name = 'back_04502514044521042540+cls_211000022+reg_100000111_ops_32' 24 | 25 | self.info = edict() 26 | self.info.arch = args.arch 27 | self.info.dataset = args.dataset 28 | self.info.epoch_test = args.epoch_test 29 | self.info.stride = args.stride 30 | self.net = models.__dict__[args.arch](args.path_name, stride=self.info.stride) 31 | self.net = load_pretrain(self.net, args.snapshot) 32 | self.net.eval() 33 | self.net = self.net.cuda() 34 | self.tracker = Lighttrack(self.info, even=args.even) 35 | 36 | self.hp = {'LightTrackM_Subnet':{'penalty_k': 0.007, 'lr': 0.616, 'window_influence': 0.225, 'small_sz': 256, 'big_sz': 288, 'ratio': 1}} 37 | 38 | def init(self, img, gt_bbox): 39 | cx, cy, w, h = get_axis_aligned_bbox(np.array(gt_bbox)) 40 | gt_bbox_ = [cx-(w-1)/2, cy-(h-1)/2, w, h] 41 | target_pos = np.array([cx, cy]) 42 | target_sz = np.array([w, h]) 43 | self.state = self.tracker.init(img, target_pos, target_sz, self.net, self.hp[self.info.arch]) 44 | pred_bbox = gt_bbox_ 45 | 46 | return pred_bbox 47 | 48 | def track(self, img): 49 | self.state = self.tracker.track(self.state, img) 50 | target_pos=self.state['target_pos'] 51 | target_sz=self.state['target_sz'] 52 | pred_bbox=np.array([target_pos[0]-target_sz[0]/2, target_pos[1]-target_sz[1]/2, target_sz[0], target_sz[1]]) 53 | 54 | return pred_bbox 55 | 56 | -------------------------------------------------------------------------------- /pipelines/ocean_pipeline.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import numpy as np 7 | 8 | from easydict import EasyDict as edict 9 | from snot.models import ocean_model as models 10 | from snot.trackers.ocean_tracker import Ocean 11 | from snot.utils.bbox import get_axis_aligned_bbox 12 | from snot.utils.model_load import load_pretrain 13 | 14 | 15 | class OceanPipeline(): 16 | def __init__(self, args): 17 | super(OceanPipeline, self).__init__() 18 | if not args.arch: 19 | args.arch = 'Ocean' 20 | if not args.snapshot: 21 | args.snapshot = './experiments/Ocean/model.pth' 22 | 23 | self.net = models.__dict__[args.arch](align=args.align, online=args.online) 24 | self.net = load_pretrain(self.net, args.snapshot) 25 | self.net.eval() 26 | self.net = self.net.cuda() 27 | self.info = edict() 28 | self.info.arch = args.arch 29 | self.info.TRT = 'TRT' in args.arch 30 | self.info.dataset = args.dataset 31 | self.info.align = args.align 32 | self.info.online = args.online 33 | self.info.epoch_test = args.epoch_test 34 | self.tracker = Ocean(self.info) 35 | 36 | self.hp = {'Ocean':{'penalty_k': 0.08, 'lr': 0.305, 'window_influence': 0.44, 'small_sz': 127, 'big_sz': 287}} 37 | 38 | def init(self, img, gt_bbox): 39 | cx, cy, w, h = get_axis_aligned_bbox(np.array(gt_bbox)) 40 | gt_bbox_ = [cx-(w-1)/2, cy-(h-1)/2, w, h] 41 | target_pos = np.array([cx, cy]) 42 | target_sz = np.array([w, h]) 43 | self.state = self.tracker.init(img, target_pos, target_sz, self.net, self.hp[self.info.arch]) 44 | pred_bbox = gt_bbox_ 45 | 46 | return pred_bbox 47 | 48 | def track(self, img): 49 | self.state = self.tracker.track(self.state, img) 50 | target_pos=self.state['target_pos'] 51 | target_sz=self.state['target_sz'] 52 | pred_bbox=np.array([target_pos[0]-target_sz[0]/2, target_pos[1]-target_sz[1]/2, target_sz[0], target_sz[1]]) 53 | 54 | return pred_bbox 55 | 56 | -------------------------------------------------------------------------------- /pipelines/pipeline_builder.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | 7 | from snot.pipelines.dasiamrpn_pipeline import DaSiamRPNPipeline 8 | from snot.pipelines.lighttrack_pipeline import LightTrackPipeline 9 | from snot.pipelines.ocean_pipeline import OceanPipeline 10 | from snot.pipelines.sesiamfc_pipeline import SESiamFCPipeline 11 | from snot.pipelines.siamapn_pipeline import SiamAPNPipeline 12 | from snot.pipelines.siamapnpp_pipeline import SiamAPNppPipeline 13 | from snot.pipelines.siamban_pipeline import SiamBANPipeline 14 | from snot.pipelines.siamcar_pipeline import SiamCARPipeline 15 | from snot.pipelines.siamdw_fc_pipeline import SiamDWFCPipeline 16 | from snot.pipelines.siamfcpp_pipeline import SiamFCppPipeline 17 | from snot.pipelines.siamgat_pipeline import SiamGATPipeline 18 | from snot.pipelines.siammask_pipeline import SiamMaskPipeline 19 | from snot.pipelines.siamdw_rpn_pipeline import SiamDWRPNPipeline 20 | from snot.pipelines.siamrpn_pipeline import SiamRPNppPipeline 21 | from snot.pipelines.updatenet_pipeline import UpdateNetPipeline 22 | 23 | TRACKS = { 24 | 'DaSiamRPN': DaSiamRPNPipeline, 25 | 'LightTrack': LightTrackPipeline, 26 | 'Ocean': OceanPipeline, 27 | 'SESiamFC': SESiamFCPipeline, 28 | 'SiamAPN': SiamAPNPipeline, 29 | 'SiamAPN++': SiamAPNppPipeline, 30 | 'SiamBAN': SiamBANPipeline, 31 | 'SiamCAR': SiamCARPipeline, 32 | 'SiamFC+': SiamDWFCPipeline, 33 | 'SiamFC++': SiamFCppPipeline, 34 | 'SiamGAT': SiamGATPipeline, 35 | 'SiamMask': SiamMaskPipeline, 36 | 'SiamRPN+': SiamDWRPNPipeline, 37 | 'SiamRPN++': SiamRPNppPipeline, 38 | 'UpdateNet': UpdateNetPipeline 39 | } 40 | 41 | def build_pipeline(args): 42 | return TRACKS[args.trackername.split('_')[0]](args) -------------------------------------------------------------------------------- /pipelines/sesiamfc_pipeline.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import numpy as np 7 | 8 | import yaml 9 | from snot.models import sesiam_model as models 10 | from snot.trackers.sesiam_fc_tracker import SESiamFCTracker 11 | from snot.utils.bbox import get_axis_aligned_bbox 12 | from snot.utils.model_load import load_pretrain 13 | 14 | 15 | class SESiamFCPipeline(): 16 | def __init__(self, args): 17 | super(SESiamFCPipeline, self).__init__() 18 | if not args.config: 19 | args.config = './experiments/SESiamFC/config.yaml' 20 | if not args.snapshot: 21 | args.snapshot = './experiments/SESiamFC/model.pth' 22 | 23 | with open(args.config) as f: 24 | tracker_config = yaml.load(f.read()) 25 | self.net = models.__dict__[tracker_config['MODEL']](padding_mode='constant') 26 | self.net = load_pretrain(self.net, args.snapshot) 27 | self.net = self.net.eval().cuda() 28 | tracker_config = tracker_config['TRACKER']['VOT2017'] 29 | self.tracker = SESiamFCTracker(self.net, **tracker_config) 30 | 31 | def init(self, img, gt_bbox): 32 | cx, cy, w, h = get_axis_aligned_bbox(np.array(gt_bbox)) 33 | gt_bbox_ = [cx-(w-1)/2, cy-(h-1)/2, w, h] 34 | target_pos = np.array([cx, cy]) 35 | target_sz = np.array([w, h]) 36 | self.state = self.tracker.init(img, target_pos, target_sz) 37 | pred_bbox = gt_bbox_ 38 | 39 | return pred_bbox 40 | 41 | def track(self, img): 42 | target_pos, target_sz = self.tracker.track(img) 43 | pred_bbox=np.array([target_pos[0]-target_sz[0]/2, target_pos[1]-target_sz[1]/2, target_sz[0], target_sz[1]]) 44 | 45 | return pred_bbox 46 | 47 | -------------------------------------------------------------------------------- /pipelines/siamapn_pipeline.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import numpy as np 7 | 8 | from snot.core.config_apn import cfg 9 | from snot.models.siamapn_model import ModelBuilderAPN 10 | from snot.trackers.siamapn_tracker import SiamAPNTracker 11 | from snot.utils.bbox import get_axis_aligned_bbox 12 | from snot.utils.model_load import load_pretrain 13 | 14 | 15 | class SiamAPNPipeline(): 16 | def __init__(self, args): 17 | super(SiamAPNPipeline, self).__init__() 18 | if not args.config: 19 | args.config = './experiments/SiamAPN/config.yaml' 20 | if not args.snapshot: 21 | args.snapshot = './experiments/SiamAPN/model.pth' 22 | 23 | cfg.merge_from_file(args.config) 24 | self.model = ModelBuilderAPN() 25 | self.model = load_pretrain(self.model, args.snapshot).cuda().eval() 26 | self.tracker = SiamAPNTracker(self.model) 27 | 28 | def init(self, img, gt_bbox): 29 | cx, cy, w, h = get_axis_aligned_bbox(np.array(gt_bbox)) 30 | gt_bbox_ = [cx-(w-1)/2, cy-(h-1)/2, w, h] 31 | self.tracker.init(img, gt_bbox_) 32 | pred_bbox = gt_bbox_ 33 | 34 | return pred_bbox 35 | 36 | def track(self, img): 37 | outputs = self.tracker.track(img) 38 | pred_bbox = outputs['bbox'] 39 | 40 | return pred_bbox 41 | 42 | -------------------------------------------------------------------------------- /pipelines/siamapnpp_pipeline.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import numpy as np 7 | 8 | from snot.core.config_adapn import cfg 9 | from snot.models.adsiamapn_model import ModelBuilderADAPN 10 | from snot.trackers.adsiamapn_tracker import ADSiamAPNTracker 11 | from snot.utils.bbox import get_axis_aligned_bbox 12 | from snot.utils.model_load import load_pretrain 13 | 14 | 15 | class SiamAPNppPipeline(): 16 | def __init__(self, args): 17 | super(SiamAPNppPipeline, self).__init__() 18 | if not args.config: 19 | args.config = './experiments/SiamAPN++/config.yaml' 20 | if not args.snapshot: 21 | args.snapshot = './experiments/SiamAPN++/model.pth' 22 | 23 | cfg.merge_from_file(args.config) 24 | self.model = ModelBuilderADAPN() 25 | self.model = load_pretrain(self.model, args.snapshot).cuda().eval() 26 | self.tracker = ADSiamAPNTracker(self.model) 27 | 28 | def init(self, img, gt_bbox): 29 | cx, cy, w, h = get_axis_aligned_bbox(np.array(gt_bbox)) 30 | gt_bbox_ = [cx-(w-1)/2, cy-(h-1)/2, w, h] 31 | self.tracker.init(img, gt_bbox_) 32 | pred_bbox = gt_bbox_ 33 | 34 | return pred_bbox 35 | 36 | def track(self, img): 37 | outputs = self.tracker.track(img) 38 | pred_bbox = outputs['bbox'] 39 | 40 | return pred_bbox 41 | 42 | -------------------------------------------------------------------------------- /pipelines/siamban_pipeline.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import numpy as np 7 | 8 | from snot.core.config_ban import cfg 9 | from snot.models.siamban_model import ModelBuilderBAN 10 | from snot.trackers.tracker_builder_ban import build_tracker_ban 11 | from snot.utils.bbox import get_axis_aligned_bbox 12 | from snot.utils.model_load import load_pretrain 13 | 14 | 15 | class SiamBANPipeline(): 16 | def __init__(self, args): 17 | super(SiamBANPipeline, self).__init__() 18 | if not args.config: 19 | args.config = './experiments/SiamBAN/config.yaml' 20 | if not args.snapshot: 21 | args.snapshot = './experiments/SiamBAN/model.pth' 22 | 23 | cfg.merge_from_file(args.config) 24 | self.model = ModelBuilderBAN() 25 | self.model = load_pretrain(self.model, args.snapshot).cuda().eval() 26 | self.tracker = build_tracker_ban(self.model) 27 | 28 | def init(self, img, gt_bbox): 29 | cx, cy, w, h = get_axis_aligned_bbox(np.array(gt_bbox)) 30 | gt_bbox_ = [cx-(w-1)/2, cy-(h-1)/2, w, h] 31 | self.tracker.init(img, gt_bbox_) 32 | pred_bbox = gt_bbox_ 33 | 34 | return pred_bbox 35 | 36 | def track(self, img): 37 | outputs = self.tracker.track(img) 38 | pred_bbox = outputs['bbox'] 39 | 40 | return pred_bbox 41 | 42 | -------------------------------------------------------------------------------- /pipelines/siamcar_pipeline.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import numpy as np 7 | 8 | from snot.core.config_car import cfg 9 | from snot.models.siamcar_model import ModelBuilderCAR 10 | from snot.trackers.siamcar_tracker import SiamCARTracker 11 | from snot.utils.bbox import get_axis_aligned_bbox 12 | from snot.utils.model_load import load_pretrain 13 | 14 | 15 | class SiamCARPipeline(): 16 | def __init__(self, args): 17 | super(SiamCARPipeline, self).__init__() 18 | if not args.config: 19 | args.config = './experiments/SiamCAR/config.yaml' 20 | if not args.snapshot: 21 | args.snapshot = './experiments/SiamCAR/model.pth' 22 | 23 | cfg.merge_from_file(args.config) 24 | self.model = ModelBuilderCAR() 25 | self.model = load_pretrain(self.model, args.snapshot).cuda().eval() 26 | self.tracker = SiamCARTracker(self.model, cfg.TRACK) 27 | 28 | self.hp = {'lr': 0.4, 'penalty_k': 0.2, 'window_lr': 0.3} 29 | 30 | def init(self, img, gt_bbox): 31 | cx, cy, w, h = get_axis_aligned_bbox(np.array(gt_bbox)) 32 | gt_bbox_ = [cx-(w-1)/2, cy-(h-1)/2, w, h] 33 | self.tracker.init(img, gt_bbox_) 34 | pred_bbox = gt_bbox_ 35 | 36 | return pred_bbox 37 | 38 | def track(self, img): 39 | outputs = self.tracker.track(img, self.hp) 40 | pred_bbox = outputs['bbox'] 41 | 42 | return pred_bbox 43 | 44 | -------------------------------------------------------------------------------- /pipelines/siamdw_fc_pipeline.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import numpy as np 7 | 8 | from easydict import EasyDict as edict 9 | from snot.models import siamdw_model as models 10 | from snot.trackers.siamdw_fc_tracker import SiamFC 11 | from snot.utils.bbox import get_axis_aligned_bbox 12 | from snot.utils.model_load import load_pretrain 13 | 14 | 15 | class SiamDWFCPipeline(): 16 | def __init__(self, args): 17 | super(SiamDWFCPipeline, self).__init__() 18 | if not args.arch: 19 | args.arch = 'SiamFCRes22' 20 | if not args.snapshot: 21 | args.snapshot = './experiments/SiamDW_FCRes22/model.pth' 22 | 23 | self.net = models.__dict__[args.arch]() 24 | self.net = load_pretrain(self.net, args.snapshot) 25 | self.net.eval() 26 | self.net = self.net.cuda() 27 | self.info = edict() 28 | self.info.arch = args.arch 29 | self.info.dataset = args.dataset 30 | self.info.epoch_test = args.epoch_test 31 | self.tracker = SiamFC(self.info) 32 | 33 | self.hp = {'SiamFCIncep22':{'scale_step': 1.1679, 'scale_lr': 0.6782, 'scale_penalty': 0.9285, 'w_influence': 0.2566}, 34 | 'SiamFCNext22':{'scale_step': 1.1531, 'scale_lr': 0.5706, 'scale_penalty': 0.9489, 'w_influence': 0.2581, 'instance_size':255}, 35 | 'SiamFCRes22':{'scale_step': 1.1466, 'scale_lr': 0.2061, 'scale_penalty': 0.9994, 'w_influence': 0.3242}} 36 | 37 | def init(self, img, gt_bbox): 38 | cx, cy, w, h = get_axis_aligned_bbox(np.array(gt_bbox)) 39 | gt_bbox_ = [cx-(w-1)/2, cy-(h-1)/2, w, h] 40 | target_pos = np.array([cx, cy]) 41 | target_sz = np.array([w, h]) 42 | self.state = self.tracker.init(img, target_pos, target_sz, self.net, self.hp[self.info.arch]) 43 | pred_bbox = gt_bbox_ 44 | 45 | return pred_bbox 46 | 47 | def track(self, img): 48 | self.state = self.tracker.track(self.state, img) 49 | target_pos=self.state['target_pos'] 50 | target_sz=self.state['target_sz'] 51 | pred_bbox=np.array([target_pos[0]-target_sz[0]/2, target_pos[1]-target_sz[1]/2, target_sz[0], target_sz[1]]) 52 | 53 | return pred_bbox 54 | 55 | -------------------------------------------------------------------------------- /pipelines/siamdw_rpn_pipeline.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import numpy as np 7 | 8 | from easydict import EasyDict as edict 9 | from snot.models import siamdw_model as models 10 | from snot.trackers.siamdw_rpn_tracker import SiamRPN 11 | from snot.utils.bbox import get_axis_aligned_bbox 12 | from snot.utils.model_load import load_pretrain 13 | 14 | 15 | class SiamDWRPNPipeline(): 16 | def __init__(self, args): 17 | super(SiamDWRPNPipeline, self).__init__() 18 | if not args.arch: 19 | args.arch = 'SiamRPNRes22' 20 | if not args.snapshot: 21 | args.snapshot = './experiments/SiamDW_RPNRes22/model.pth' 22 | 23 | self.net = models.__dict__[args.arch](anchors_nums=args.anchor_nums, cls_type=args.cls_type) 24 | self.net = load_pretrain(self.net, args.snapshot) 25 | self.net.eval() 26 | self.net = self.net.cuda() 27 | self.info = edict() 28 | self.info.arch = args.arch 29 | self.info.cls_type = args.cls_type 30 | self.info.dataset = args.dataset 31 | self.info.epoch_test = args.epoch_test 32 | self.tracker = SiamRPN(self.info) 33 | 34 | self.hp = {'SiamRPNRes22':{'penalty_k': 0.038, 'lr': 0.388, 'window_influence': 0.347}} 35 | 36 | def init(self, img, gt_bbox): 37 | cx, cy, w, h = get_axis_aligned_bbox(np.array(gt_bbox)) 38 | gt_bbox_ = [cx-(w-1)/2, cy-(h-1)/2, w, h] 39 | target_pos = np.array([cx, cy]) 40 | target_sz = np.array([w, h]) 41 | self.state = self.tracker.init(img, target_pos, target_sz, self.net, self.hp[self.info.arch]) 42 | pred_bbox = gt_bbox_ 43 | 44 | return pred_bbox 45 | 46 | def track(self, img): 47 | self.state = self.tracker.track(self.state, img) 48 | target_pos=self.state['target_pos'] 49 | target_sz=self.state['target_sz'] 50 | pred_bbox=np.array([target_pos[0]-target_sz[0]/2, target_pos[1]-target_sz[1]/2, target_sz[0], target_sz[1]]) 51 | 52 | return pred_bbox 53 | 54 | -------------------------------------------------------------------------------- /pipelines/siamfcpp_pipeline.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import numpy as np 7 | 8 | from snot.core.config_fcpp import cfg 9 | from snot.core.config_fcpp import specify_task 10 | from snot.models.fcpp.engine.builder import build as tester_builder 11 | from snot.models.fcpp.model import builder as model_builder 12 | from snot.models.fcpp.pipeline import builder as pipeline_builder 13 | from snot.utils.bbox import get_axis_aligned_bbox 14 | 15 | 16 | class SiamFCppPipeline(): 17 | def __init__(self, args): 18 | super(SiamFCppPipeline, self).__init__() 19 | if not args.config: 20 | args.config = './experiments/SiamFC++/siamfcpp_googlenet.yaml' 21 | if not args.config: 22 | args.snapshot = './experiments/SiamFC++/siamfcpp-googlenet.pkl' 23 | 24 | cfg.merge_from_file(args.config) 25 | cfg['test']['track']['model']['task_model']['SiamTrack']['pretrain_model_path'] = args.snapshot 26 | task, task_cfg = specify_task(cfg['test']) 27 | task_cfg.freeze() 28 | self.model = model_builder.build("track", task_cfg.model) 29 | self.pipeline = pipeline_builder.build("track", task_cfg.pipeline, self.model) 30 | self.tester = tester_builder("track", task_cfg.tester, "tester", self.pipeline)[0] 31 | 32 | def init(self, img, gt_bbox): 33 | cx, cy, w, h = get_axis_aligned_bbox(np.array(gt_bbox)) 34 | gt_bbox_ = [cx-(w-1)/2, cy-(h-1)/2, w, h] 35 | self.tester.init(img, gt_bbox) 36 | pred_bbox = gt_bbox_ 37 | 38 | return pred_bbox 39 | 40 | def track(self, img): 41 | pred_bbox = self.tester.track(img) 42 | 43 | return pred_bbox 44 | 45 | -------------------------------------------------------------------------------- /pipelines/siamgat_pipeline.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import numpy as np 7 | 8 | from snot.core.config_gat import cfg 9 | from snot.models.siamgat_model import ModelBuilderGAT 10 | from snot.trackers.siamgat_tracker import SiamGATTracker 11 | from snot.utils.bbox import get_axis_aligned_bbox 12 | from snot.utils.model_load import load_pretrain 13 | 14 | 15 | class SiamGATPipeline(): 16 | def __init__(self, args): 17 | super(SiamGATPipeline, self).__init__() 18 | if not args.config: 19 | args.config = './experiments/SiamGAT/config.yaml' 20 | if not args.snapshot: 21 | args.snapshot = './experiments/SiamGAT/model.pth' 22 | 23 | cfg.merge_from_file(args.config) 24 | self.model = ModelBuilderGAT() 25 | self.model = load_pretrain(self.model, args.snapshot).cuda().eval() 26 | self.tracker = SiamGATTracker(self.model) 27 | 28 | cfg.TRACK.LR = 0.24 29 | cfg.TRACK.PENALTY_K = 0.04 30 | cfg.TRACK.WINDOW_INFLUENCE = 0.04 31 | 32 | def init(self, img, gt_bbox): 33 | cx, cy, w, h = get_axis_aligned_bbox(np.array(gt_bbox)) 34 | gt_bbox_ = [cx-(w-1)/2, cy-(h-1)/2, w, h] 35 | self.tracker.init(img, gt_bbox_) 36 | pred_bbox = gt_bbox_ 37 | 38 | return pred_bbox 39 | 40 | def track(self, img): 41 | outputs = self.tracker.track(img) 42 | pred_bbox = outputs['bbox'] 43 | 44 | return pred_bbox 45 | 46 | -------------------------------------------------------------------------------- /pipelines/siammask_pipeline.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import numpy as np 7 | 8 | from snot.core.config import cfg 9 | from snot.models.model_builder import ModelBuilder 10 | from snot.trackers.tracker_builder import build_tracker 11 | from snot.utils.bbox import get_axis_aligned_bbox 12 | from snot.utils.model_load import load_pretrain 13 | 14 | 15 | class SiamMaskPipeline(): 16 | def __init__(self, args): 17 | super(SiamMaskPipeline, self).__init__() 18 | if not args.config: 19 | args.config = './experiments/SiamMask_r50/config.yaml' 20 | if not args.snapshot: 21 | args.snapshot = './experiments/SiamMask_r50/model.pth' 22 | 23 | cfg.merge_from_file(args.config) 24 | self.model = ModelBuilder() 25 | self.model = load_pretrain(self.model, args.snapshot).cuda().eval() 26 | self.tracker = build_tracker(self.model) 27 | 28 | def init(self, img, gt_bbox): 29 | cx, cy, w, h = get_axis_aligned_bbox(np.array(gt_bbox)) 30 | gt_bbox_ = [cx-(w-1)/2, cy-(h-1)/2, w, h] 31 | self.tracker.init(img, gt_bbox_) 32 | pred_bbox = gt_bbox_ 33 | 34 | return pred_bbox 35 | 36 | def track(self, img): 37 | outputs = self.tracker.track(img) 38 | pred_bbox = outputs['bbox'] 39 | 40 | return pred_bbox 41 | 42 | -------------------------------------------------------------------------------- /pipelines/siamrpn_pipeline.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import numpy as np 7 | 8 | from snot.core.config import cfg 9 | from snot.models.model_builder import ModelBuilder 10 | from snot.trackers.tracker_builder import build_tracker 11 | from snot.utils.bbox import get_axis_aligned_bbox 12 | from snot.utils.model_load import load_pretrain 13 | 14 | 15 | class SiamRPNppPipeline(): 16 | def __init__(self, args): 17 | super(SiamRPNppPipeline, self).__init__() 18 | if not args.config: 19 | args.config = './experiments/SiamRPN_alex/config.yaml' 20 | if not args.snapshot: 21 | args.snapshot = './experiments/SiamRPN_alex/model.pth' 22 | 23 | cfg.merge_from_file(args.config) 24 | self.model = ModelBuilder() 25 | self.model = load_pretrain(self.model, args.snapshot).cuda().eval() 26 | self.tracker = build_tracker(self.model) 27 | 28 | def init(self, img, gt_bbox): 29 | cx, cy, w, h = get_axis_aligned_bbox(np.array(gt_bbox)) 30 | gt_bbox_ = [cx-(w-1)/2, cy-(h-1)/2, w, h] 31 | self.tracker.init(img, gt_bbox_) 32 | pred_bbox = gt_bbox_ 33 | 34 | return pred_bbox 35 | 36 | def track(self, img): 37 | outputs = self.tracker.track(img) 38 | pred_bbox = outputs['bbox'] 39 | 40 | return pred_bbox 41 | 42 | -------------------------------------------------------------------------------- /pipelines/updatenet_pipeline.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import numpy as np 7 | import torch 8 | 9 | from snot.models.updatenet_siam_model import SiamRPNBIG 10 | from snot.models.updatenet_upd_model import UpdateResNet 11 | from snot.trackers.updatenet_tracker import SiamRPN_init, SiamRPN_track_upd 12 | from snot.utils.bbox import get_axis_aligned_bbox 13 | 14 | 15 | class UpdateNetPipeline(): 16 | def __init__(self, args): 17 | super(UpdateNetPipeline, self).__init__() 18 | if not args.snapshot: 19 | args.snapshot = './experiments/UpdateNet/SiamRPNBIG.model' 20 | if not args.update: 21 | args.update = './experiments/UpdateNet/vot2018.pth.tar' 22 | 23 | self.net = SiamRPNBIG() 24 | self.net.load_state_dict(torch.load(args.snapshot)) 25 | self.net.eval().cuda() 26 | self.updatenet = UpdateResNet() 27 | self.updatenet.load_state_dict(torch.load(args.update)['state_dict']) 28 | self.updatenet.eval().cuda() 29 | 30 | def init(self, img, gt_bbox): 31 | cx, cy, w, h = get_axis_aligned_bbox(np.array(gt_bbox)) 32 | gt_bbox_ = [cx-(w-1)/2, cy-(h-1)/2, w, h] 33 | target_pos = np.array([cx, cy]) 34 | target_sz = np.array([w, h]) 35 | self.state = SiamRPN_init(img, target_pos, target_sz, self.net) 36 | pred_bbox = gt_bbox_ 37 | 38 | return pred_bbox 39 | 40 | def track(self, img): 41 | self.state = SiamRPN_track_upd(self.state, img, self.updatenet) 42 | target_pos=self.state['target_pos'] 43 | target_sz=self.state['target_sz'] 44 | pred_bbox=np.array([target_pos[0]-target_sz[0]/2, target_pos[1]-target_sz[1]/2, target_sz[0], target_sz[1]]) 45 | 46 | return pred_bbox 47 | 48 | -------------------------------------------------------------------------------- /results/DTB70.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/results/DTB70.zip -------------------------------------------------------------------------------- /results/DarkTrack2021.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/results/DarkTrack2021.zip -------------------------------------------------------------------------------- /results/NAT2021.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/results/NAT2021.zip -------------------------------------------------------------------------------- /results/UAV123_10fps.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/results/UAV123_10fps.zip -------------------------------------------------------------------------------- /results/UAV123_20L.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/results/UAV123_20L.zip -------------------------------------------------------------------------------- /results/UAVDT.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/results/UAVDT.zip -------------------------------------------------------------------------------- /results/UAVDark135.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/results/UAVDark135.zip -------------------------------------------------------------------------------- /results/UAVTrack112.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/results/UAVTrack112.zip -------------------------------------------------------------------------------- /results/VisDrone-2020SOT-test.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/results/VisDrone-2020SOT-test.zip -------------------------------------------------------------------------------- /snot/core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/snot/core/__init__.py -------------------------------------------------------------------------------- /snot/core/config_fcpp.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | from yacs.config import CfgNode 3 | 4 | from snot.models.fcpp.engine.tester.builder import get_config as get_tester_cfg 5 | from snot.models.fcpp.model.builder import get_config as get_model_cfg 6 | from snot.models.fcpp.pipeline.builder import get_config as get_pipeline_cfg 7 | 8 | cfg = CfgNode() # root_cfg 9 | task_list = ["track",] 10 | default_str = "unknown" 11 | cfg["task_name"] = default_str 12 | 13 | # default configuration for test 14 | cfg["test"] = CfgNode() 15 | test_cfg = cfg["test"] 16 | for task in task_list: 17 | test_cfg[task] = CfgNode() 18 | test_cfg[task]["exp_name"] = default_str 19 | test_cfg[task]["exp_save"] = default_str 20 | test_cfg[task]["model"] = get_model_cfg(task_list)[task] 21 | test_cfg[task]["pipeline"] = get_pipeline_cfg(task_list)[task] 22 | test_cfg[task]["tester"] = get_tester_cfg(task_list)[task] 23 | 24 | 25 | 26 | def specify_task(cfg: CfgNode) -> Union[str, CfgNode]: 27 | r""" 28 | get task's short name from config, and specify task config 29 | 30 | Args: 31 | cfg (CfgNode): config 32 | 33 | Returns: 34 | short task name, task-specified cfg 35 | """ 36 | for task in task_list: 37 | if cfg[task]['exp_name'] != default_str: 38 | return task, cfg[task] 39 | assert False, "unknown task!" 40 | -------------------------------------------------------------------------------- /snot/core/xcorr.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import torch 7 | import torch.nn.functional as F 8 | 9 | 10 | def xcorr_slow(x, kernel): 11 | """for loop to calculate cross correlation, slow version 12 | """ 13 | batch = x.size()[0] 14 | out = [] 15 | for i in range(batch): 16 | px = x[i] 17 | pk = kernel[i] 18 | px = px.view(1, -1, px.size()[1], px.size()[2]) 19 | pk = pk.view(1, -1, pk.size()[1], pk.size()[2]) 20 | po = F.conv2d(px, pk) 21 | out.append(po) 22 | out = torch.cat(out, 0) 23 | return out 24 | 25 | 26 | def xcorr_fast(x, kernel): 27 | """group conv2d to calculate cross correlation, fast version 28 | """ 29 | batch = kernel.size()[0] 30 | pk = kernel.view(-1, x.size()[1], kernel.size()[2], kernel.size()[3]) 31 | px = x.view(1, -1, x.size()[2], x.size()[3]) 32 | po = F.conv2d(px, pk, groups=batch) 33 | po = po.view(batch, -1, po.size()[2], po.size()[3]) 34 | return po 35 | 36 | 37 | def xcorr_depthwise(x, kernel): 38 | """depthwise cross correlation 39 | """ 40 | batch = kernel.size(0) 41 | channel = kernel.size(1) 42 | x = x.view(1, batch*channel, x.size(2), x.size(3)) 43 | kernel = kernel.view(batch*channel, 1, kernel.size(2), kernel.size(3)) 44 | out = F.conv2d(x, kernel, groups=batch*channel) 45 | out = out.view(batch, channel, out.size(2), out.size(3)) 46 | return out 47 | -------------------------------------------------------------------------------- /snot/datasets/__init__.py: -------------------------------------------------------------------------------- 1 | from .uav10fps import UAV10Dataset 2 | from .uav20l import UAV20Dataset 3 | from .dtb import DTBDataset 4 | from .uavdt import UAVDTDataset 5 | from .visdrone import VISDRONEDDataset 6 | from .v4r import V4RDataset 7 | from .uavdark import UAVDARKDataset 8 | from .darktrack import DARKTRACKDataset 9 | 10 | 11 | datapath = { 12 | 'UAV10':'/Dataset/UAV123_10fps', 13 | 'UAV20':'/Dataset/UAV123_20L', 14 | 'DTB70':'/Dataset/DTB70', 15 | 'UAVDT':'/Dataset/UAVDT', 16 | 'VISDRONED2018':'/Dataset/VisDrone-SOT2018-test', 17 | 'VISDRONED2019':'/Dataset/VisDrone-SOT2019-test', 18 | 'VISDRONED2020':'/Dataset/VisDrone-SOT2020-test', 19 | 'UAVTrack112':'/Dataset/UAVTrack112', 20 | 'UAVDark135':'/Dataset/UAVDark135', 21 | 'DarkTrack2021':'/Dataset/DarkTrack2021', 22 | 'NAT2021':'/Dataset/NAT2021' 23 | } 24 | 25 | class DatasetFactory(object): 26 | @staticmethod 27 | def create_dataset(**kwargs): 28 | 29 | assert 'name' in kwargs, "should provide dataset name" 30 | name = kwargs['name'] 31 | if 'UAV10' in name: 32 | dataset = UAV10Dataset(**kwargs) 33 | elif 'UAV20' in name: 34 | dataset = UAV20Dataset(**kwargs) 35 | elif 'DTB70' in name: 36 | dataset = DTBDataset(**kwargs) 37 | elif 'UAVDT' in name: 38 | dataset = UAVDTDataset(**kwargs) 39 | elif 'VISDRONED' in name: 40 | dataset = VISDRONEDDataset(**kwargs) 41 | elif 'UAVTrack112' in name: 42 | dataset = V4RDataset(**kwargs) 43 | elif 'UAVDark' in name: 44 | dataset = UAVDARKDataset(**kwargs) 45 | elif 'DarkTrack2021' in name: 46 | dataset = DARKTRACKDataset(**kwargs) 47 | elif 'NAT2021' in name: 48 | dataset = DARKTRACKDataset(**kwargs) 49 | 50 | else: 51 | raise Exception("unknow dataset {}".format(kwargs['name'])) 52 | return dataset 53 | -------------------------------------------------------------------------------- /snot/datasets/dataset.py: -------------------------------------------------------------------------------- 1 | from tqdm import tqdm 2 | 3 | class Dataset(object): 4 | def __init__(self, name, dataset_root): 5 | self.name = name 6 | self.dataset_root = dataset_root 7 | self.videos = None 8 | 9 | def __getitem__(self, idx): 10 | if isinstance(idx, str): 11 | return self.videos[idx] 12 | elif isinstance(idx, int): 13 | return self.videos[sorted(list(self.videos.keys()))[idx]] 14 | 15 | def __len__(self): 16 | return len(self.videos) 17 | 18 | def __iter__(self): 19 | keys = sorted(list(self.videos.keys())) 20 | for key in keys: 21 | yield self.videos[key] 22 | 23 | def set_tracker(self, path, tracker_names): 24 | """ 25 | Args: 26 | path: path to tracker results, 27 | tracker_names: list of tracker name 28 | """ 29 | self.tracker_path = path 30 | self.tracker_names = tracker_names 31 | # for video in tqdm(self.videos.values(), 32 | # desc='loading tacker result', ncols=100): 33 | # video.load_tracker(path, tracker_names) 34 | -------------------------------------------------------------------------------- /snot/datasets/uav.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | 4 | from tqdm import tqdm 5 | from glob import glob 6 | 7 | from .dataset import Dataset 8 | from .video import Video 9 | 10 | class UAVVideo(Video): 11 | """ 12 | Args: 13 | name: video name 14 | root: dataset root 15 | video_dir: video directory 16 | init_rect: init rectangle 17 | img_names: image names 18 | gt_rect: groundtruth rectangle 19 | attr: attribute of video 20 | """ 21 | def __init__(self, name, root, video_dir, init_rect, img_names, 22 | gt_rect, attr, load_img=False): 23 | super(UAVVideo, self).__init__(name, root, video_dir, 24 | init_rect, img_names, gt_rect, attr, load_img) 25 | 26 | 27 | class UAVDataset(Dataset): 28 | """ 29 | Args: 30 | name: dataset name, should be 'UAV123', 'UAV20L' 31 | dataset_root: dataset root 32 | load_img: wether to load all imgs 33 | """ 34 | def __init__(self, name, dataset_root, load_img=False): 35 | super(UAVDataset, self).__init__(name, dataset_root) 36 | with open(os.path.join(dataset_root, name+'.json'), 'r') as f: 37 | meta_data = json.load(f) 38 | 39 | # load videos 40 | pbar = tqdm(meta_data.keys(), desc='loading '+name, ncols=100) 41 | self.videos = {} 42 | for video in pbar: 43 | pbar.set_postfix_str(video) 44 | self.videos[video] = UAVVideo(video, 45 | dataset_root, 46 | meta_data[video]['video_dir'], 47 | meta_data[video]['init_rect'], 48 | meta_data[video]['img_names'], 49 | meta_data[video]['gt_rect'], 50 | meta_data[video]['attr']) 51 | 52 | # set attr 53 | attr = [] 54 | for x in self.videos.values(): 55 | attr += x.attr 56 | attr = set(attr) 57 | self.attr = {} 58 | self.attr['ALL'] = list(self.videos.keys()) 59 | for x in attr: 60 | self.attr[x] = [] 61 | for k, v in self.videos.items(): 62 | for attr_ in v.attr: 63 | self.attr[attr_].append(k) 64 | 65 | -------------------------------------------------------------------------------- /snot/models/adsiamapn_model.py: -------------------------------------------------------------------------------- 1 | # Parts of this code come from https://github.com/vision4robotics/SiamAPN 2 | from __future__ import absolute_import 3 | from __future__ import division 4 | from __future__ import print_function 5 | from __future__ import unicode_literals 6 | 7 | import torch.nn as nn 8 | 9 | from snot.core.config_adapn import cfg 10 | from snot.models.backbone.alexnet import AlexNet_apn 11 | from snot.models.adapn.utile import ADAPN,clsandloc_adapn 12 | from snot.models.adapn.anchortarget import AnchorTarget3_adapn 13 | 14 | 15 | class ModelBuilderADAPN(nn.Module): 16 | def __init__(self): 17 | super(ModelBuilderADAPN, self).__init__() 18 | 19 | self.backbone = AlexNet_apn().cuda() 20 | self.grader=ADAPN(cfg).cuda() 21 | self.new=clsandloc_adapn(cfg).cuda() 22 | self.fin2=AnchorTarget3_adapn() 23 | 24 | def template(self, z): 25 | 26 | zf = self.backbone(z) 27 | self.zf=zf 28 | 29 | def track(self, x): 30 | 31 | xf = self.backbone(x) 32 | xff,ress=self.grader(xf,self.zf) 33 | 34 | self.ranchors=xff 35 | 36 | cls1,cls2,cls3,loc =self.new(xf,self.zf,ress) 37 | 38 | return { 39 | 'cls1': cls1, 40 | 'cls2': cls2, 41 | 'cls3': cls3, 42 | 'loc': loc 43 | } 44 | -------------------------------------------------------------------------------- /snot/models/backbone/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | from snot.models.backbone.alexnet import alexnetlegacy, alexnet 7 | from snot.models.backbone.mobile_v2 import mobilenetv2 8 | from snot.models.backbone.resnet_atrous import resnet18, resnet34, resnet50 9 | from snot.models.backbone.googlenet import Inception3 10 | from snot.models.backbone.googlenet_ou import Inception3_ou 11 | 12 | BACKBONES = { 13 | 'alexnetlegacy': alexnetlegacy, 14 | 'mobilenetv2': mobilenetv2, 15 | 'resnet18': resnet18, 16 | 'resnet34': resnet34, 17 | 'resnet50': resnet50, 18 | 'alexnet': alexnet, 19 | 'googlenet': Inception3, 20 | 'googlenet_ou': Inception3_ou, 21 | } 22 | 23 | 24 | def get_backbone(name, **kwargs): 25 | return BACKBONES[name](**kwargs) 26 | -------------------------------------------------------------------------------- /snot/models/dasiamrpn_model.py: -------------------------------------------------------------------------------- 1 | # Parts of this code come from https://github.com/foolwood/DaSiamRPN 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | 6 | class SiamRPN(nn.Module): 7 | def __init__(self, size=2, feature_out=512, anchor=5): 8 | configs = [3, 96, 256, 384, 384, 256] 9 | configs = list(map(lambda x: 3 if x==3 else x*size, configs)) 10 | feat_in = configs[-1] 11 | super(SiamRPN, self).__init__() 12 | self.featureExtract = nn.Sequential( 13 | nn.Conv2d(configs[0], configs[1] , kernel_size=11, stride=2), 14 | nn.BatchNorm2d(configs[1]), 15 | nn.MaxPool2d(kernel_size=3, stride=2), 16 | nn.ReLU(inplace=True), 17 | nn.Conv2d(configs[1], configs[2], kernel_size=5), 18 | nn.BatchNorm2d(configs[2]), 19 | nn.MaxPool2d(kernel_size=3, stride=2), 20 | nn.ReLU(inplace=True), 21 | nn.Conv2d(configs[2], configs[3], kernel_size=3), 22 | nn.BatchNorm2d(configs[3]), 23 | nn.ReLU(inplace=True), 24 | nn.Conv2d(configs[3], configs[4], kernel_size=3), 25 | nn.BatchNorm2d(configs[4]), 26 | nn.ReLU(inplace=True), 27 | nn.Conv2d(configs[4], configs[5], kernel_size=3), 28 | nn.BatchNorm2d(configs[5]), 29 | ) 30 | 31 | self.anchor = anchor 32 | self.feature_out = feature_out 33 | 34 | self.conv_r1 = nn.Conv2d(feat_in, feature_out*4*anchor, 3) 35 | self.conv_r2 = nn.Conv2d(feat_in, feature_out, 3) 36 | self.conv_cls1 = nn.Conv2d(feat_in, feature_out*2*anchor, 3) 37 | self.conv_cls2 = nn.Conv2d(feat_in, feature_out, 3) 38 | self.regress_adjust = nn.Conv2d(4*anchor, 4*anchor, 1) 39 | 40 | self.r1_kernel = [] 41 | self.cls1_kernel = [] 42 | 43 | self.cfg = {} 44 | 45 | def forward(self, x): 46 | x_f = self.featureExtract(x) 47 | return self.regress_adjust(F.conv2d(self.conv_r2(x_f), self.r1_kernel)), \ 48 | F.conv2d(self.conv_cls2(x_f), self.cls1_kernel) 49 | 50 | def temple(self, z): 51 | z_f = self.featureExtract(z) 52 | r1_kernel_raw = self.conv_r1(z_f) 53 | cls1_kernel_raw = self.conv_cls1(z_f) 54 | kernel_size = r1_kernel_raw.data.size()[-1] 55 | self.r1_kernel = r1_kernel_raw.view(self.anchor*4, self.feature_out, kernel_size, kernel_size) 56 | self.cls1_kernel = cls1_kernel_raw.view(self.anchor*2, self.feature_out, kernel_size, kernel_size) 57 | 58 | 59 | class SiamRPNBIG(SiamRPN): 60 | def __init__(self): 61 | super(SiamRPNBIG, self).__init__(size=2) 62 | self.cfg = {'lr':0.295, 'window_influence': 0.42, 'penalty_k': 0.055, 'instance_size': 271, 'adaptive': True} # 0.383 63 | 64 | 65 | class SiamRPNvot(SiamRPN): 66 | def __init__(self): 67 | super(SiamRPNvot, self).__init__(size=1, feature_out=256) 68 | self.cfg = {'lr':0.45, 'window_influence': 0.44, 'penalty_k': 0.04, 'instance_size': 271, 'adaptive': False} # 0.355 69 | 70 | 71 | class SiamRPNotb(SiamRPN): 72 | def __init__(self): 73 | super(SiamRPNotb, self).__init__(size=1, feature_out=256) 74 | self.cfg = {'lr': 0.30, 'window_influence': 0.40, 'penalty_k': 0.22, 'instance_size': 271, 'adaptive': False} # 0.655 75 | -------------------------------------------------------------------------------- /snot/models/dw/connect.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import torch.nn as nn 7 | import torch.nn.functional as F 8 | 9 | 10 | class Corr_Up(nn.Module): 11 | """ 12 | SiamFC head 13 | """ 14 | def __init__(self): 15 | super(Corr_Up, self).__init__() 16 | 17 | def _conv2d_group(self, x, kernel): 18 | batch = x.size()[0] 19 | pk = kernel.view(-1, x.size()[1], kernel.size()[2], kernel.size()[3]) 20 | px = x.view(1, -1, x.size()[2], x.size()[3]) 21 | po = F.conv2d(px, pk, groups=batch) 22 | po = po.view(batch, -1, po.size()[2], po.size()[3]) 23 | return po 24 | 25 | def forward(self, z_f, x_f): 26 | if not self.training: 27 | return 0.1 * F.conv2d(x_f, z_f) 28 | else: 29 | return 0.1 * self._conv2d_group(x_f, z_f) 30 | 31 | 32 | class RPN_Up(nn.Module): 33 | """ 34 | For SiamRPN 35 | """ 36 | def __init__(self, anchor_nums=5, inchannels=256, outchannels=256, cls_type='thicker'): 37 | super(RPN_Up, self).__init__() 38 | 39 | self.anchor_nums = anchor_nums 40 | self.inchannels = inchannels 41 | self.outchannels = outchannels 42 | 43 | if cls_type == 'thinner': self.cls_channel = self.anchor_nums 44 | elif cls_type == 'thicker': self.cls_channel = self.anchor_nums * 2 45 | else: raise ValueError('not implemented cls/loss type') 46 | 47 | self.reg_channel = 4 * self.anchor_nums 48 | 49 | self.template_cls = nn.Conv2d(self.inchannels, self.outchannels * self.cls_channel, kernel_size=3) 50 | self.template_reg = nn.Conv2d(self.inchannels, self.outchannels * self.reg_channel, kernel_size=3) 51 | 52 | self.search_cls = nn.Conv2d(self.inchannels, self.outchannels, kernel_size=3) 53 | self.search_reg = nn.Conv2d(self.inchannels, self.outchannels, kernel_size=3) 54 | self.adjust = nn.Conv2d(self.reg_channel, self.reg_channel, kernel_size=1) 55 | 56 | 57 | def _conv2d_group(self, x, kernel): 58 | batch = kernel.size()[0] 59 | pk = kernel.view(-1, x.size()[1], kernel.size()[2], kernel.size()[3]) 60 | px = x.view(1, -1, x.size()[2], x.size()[3]) 61 | po = F.conv2d(px, pk, groups=batch) 62 | po = po.view(batch, -1, po.size()[2], po.size()[3]) 63 | return po 64 | 65 | 66 | def forward(self, z_f, x_f): 67 | cls_kernel = self.template_cls(z_f) 68 | reg_kernel = self.template_reg(z_f) 69 | 70 | cls_feature = self.search_cls(x_f) 71 | loc_feature = self.search_reg(x_f) 72 | 73 | _, _, s_cls, _ = cls_kernel.size() 74 | _, _, s_reg, _ = reg_kernel.size() 75 | 76 | pred_cls = self._conv2d_group(cls_feature, cls_kernel) 77 | pred_reg = self.adjust(self._conv2d_group(loc_feature, reg_kernel)) 78 | 79 | return pred_cls, pred_reg 80 | -------------------------------------------------------------------------------- /snot/models/dw/siamfc.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import torch 7 | import torch.nn as nn 8 | from torch.autograd import Variable 9 | 10 | 11 | class SiamFC_(nn.Module): 12 | def __init__(self): 13 | super(SiamFC_, self).__init__() 14 | self.features = None 15 | self.connect_model = None 16 | self.zf = None # for online tracking 17 | self.criterion = nn.BCEWithLogitsLoss() 18 | 19 | def feature_extractor(self, x): 20 | return self.features(x) 21 | 22 | def connector(self, template_feature, search_feature): 23 | pred_score = self.connect_model(template_feature, search_feature) 24 | return pred_score 25 | 26 | def _cls_loss(self, pred, label, select): 27 | if len(select.size()) == 0: return 0 28 | pred = torch.index_select(pred, 0, select) 29 | label = torch.index_select(label, 0, select) 30 | return self.criterion(pred, label) # the same as tf version 31 | 32 | def _weighted_BCE(self, pred, label): 33 | pred = pred.view(-1) 34 | label = label.view(-1) 35 | pos = Variable(label.data.eq(1).nonzero().squeeze()).cuda() 36 | neg = Variable(label.data.eq(0).nonzero().squeeze()).cuda() 37 | 38 | loss_pos = self._cls_loss(pred, label, pos) 39 | loss_neg = self._cls_loss(pred, label, neg) 40 | return loss_pos * 0.5 + loss_neg * 0.5 41 | 42 | def template(self, z): 43 | self.zf = self.feature_extractor(z) 44 | 45 | def track(self, x): 46 | xf = self.feature_extractor(x) 47 | score = self.connector(self.zf, xf) 48 | return score 49 | 50 | def forward(self, template, search, label=None): 51 | zf = self.feature_extractor(template) 52 | xf = self.feature_extractor(search) 53 | score = self.connector(zf, xf) 54 | if self.training: 55 | return self._weighted_BCE(score, label) 56 | else: 57 | raise ValueError('forward is only used for training.') 58 | -------------------------------------------------------------------------------- /snot/models/fcpp/engine/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | -------------------------------------------------------------------------------- /snot/models/fcpp/engine/builder.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | from yacs.config import CfgNode 3 | 4 | from .tester import builder as tester_builder 5 | 6 | TASK_ENGINE_BUILDERS = dict(tester=tester_builder) 7 | 8 | 9 | def build(task: str, cfg: CfgNode, engine_type: str, *args, **kwargs): 10 | """ 11 | Builder function for trainer/tester 12 | engine_type: trainer or tester 13 | """ 14 | if engine_type in TASK_ENGINE_BUILDERS: 15 | engine = TASK_ENGINE_BUILDERS[engine_type].build(task, cfg, *args, **kwargs) 16 | return engine 17 | else: 18 | raise ValueError("Invalid engine_type: %s" % engine_type) 19 | -------------------------------------------------------------------------------- /snot/models/fcpp/engine/tester/__init__.py: -------------------------------------------------------------------------------- 1 | from .tester_impl import * # noqa 2 | -------------------------------------------------------------------------------- /snot/models/fcpp/engine/tester/builder.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | from typing import Dict, List 3 | 4 | from yacs.config import CfgNode 5 | 6 | from snot.models.fcpp.pipeline.pipeline_base import PipelineBase 7 | from snot.utils.utils_fcpp import merge_cfg_into_hps 8 | 9 | from .tester_base import TASK_TESTERS 10 | 11 | 12 | def build(task: str, cfg: CfgNode, pipeline: PipelineBase): 13 | r""" 14 | Builder function. 15 | 16 | Arguments 17 | --------- 18 | task: str 19 | builder task name (track|vos) 20 | cfg: CfgNode 21 | buidler configuration, 22 | node nams: tester 23 | 24 | Returns 25 | ------- 26 | TesterBase 27 | tester built by builder 28 | """ 29 | assert task in TASK_TESTERS, "no tester for task {}".format(task) 30 | MODULES = TASK_TESTERS[task] 31 | 32 | names = cfg.names 33 | testers = [] 34 | # tester for multiple experiments 35 | for name in names: 36 | tester = MODULES[name](pipeline) 37 | hps = tester.get_hps() 38 | hps = merge_cfg_into_hps(cfg[name], hps) 39 | tester.set_hps(hps) 40 | tester.update_params() 41 | testers.append(tester) 42 | return testers 43 | 44 | 45 | def get_config(task_list: List) -> Dict[str, CfgNode]: 46 | r""" 47 | Get available component list config 48 | 49 | Returns 50 | ------- 51 | Dict[str, CfgNode] 52 | config with list of available components 53 | """ 54 | cfg_dict = {name: CfgNode() for name in task_list} 55 | 56 | for cfg_name, MODULES in TASK_TESTERS.items(): 57 | cfg = cfg_dict[cfg_name] 58 | cfg["names"] = [] 59 | for name in MODULES: 60 | cfg["names"].append(name) 61 | cfg[name] = CfgNode() 62 | tester = MODULES[name] 63 | hps = tester.default_hyper_params 64 | for hp_name in hps: 65 | cfg[name][hp_name] = hps[hp_name] 66 | return cfg_dict 67 | -------------------------------------------------------------------------------- /snot/models/fcpp/engine/tester/tester_base.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | import os 3 | import random 4 | from copy import deepcopy 5 | from typing import Dict 6 | 7 | import numpy as np 8 | 9 | import torch 10 | 11 | from snot.models.fcpp.pipeline.pipeline_base import PipelineBase 12 | from snot.utils.utils_fcpp import Registry 13 | 14 | TRACK_TESTERS = Registry('TRACK_TESTERS') 15 | 16 | TASK_TESTERS = dict(track=TRACK_TESTERS) 17 | 18 | 19 | class TesterBase: 20 | r""" 21 | Tester base class (e.g. procedure defined for tracker / segmenter / etc.) 22 | Interface descriptions: 23 | init(im, state): 24 | update(im): 25 | """ 26 | # Define your default hyper-parameters here in your sub-class. 27 | default_hyper_params = dict( 28 | exp_name="", 29 | exp_save="", 30 | random_seed=12345, 31 | ) 32 | 33 | def __init__(self, pipeline: PipelineBase): 34 | """ 35 | Parameters 36 | ---------- 37 | pipeline : PipelineBase 38 | Pipeline to be tested 39 | """ 40 | self._hyper_params = deepcopy( 41 | self.default_hyper_params) # mapping-like object 42 | self._state = dict() # pipeline state 43 | self._pipeline = pipeline 44 | 45 | def get_hps(self) -> dict(): 46 | r""" 47 | Getter function for hyper-parameters 48 | 49 | Returns 50 | ------- 51 | dict 52 | hyper-parameters 53 | """ 54 | return self._hyper_params 55 | 56 | def set_hps(self, hps: dict()) -> None: 57 | r""" 58 | Set hyper-parameters 59 | 60 | Arguments 61 | --------- 62 | hps: dict 63 | dict of hyper-parameters, the keys must in self.__hyper_params__ 64 | """ 65 | for key in hps: 66 | if key not in self._hyper_params: 67 | raise KeyError 68 | self._hyper_params[key] = hps[key] 69 | 70 | def set_pipeline(self, pipeline: PipelineBase): 71 | r"""Setter for underlying pipeline 72 | """ 73 | self._pipeline = pipeline 74 | 75 | def update_params(self): 76 | r""" 77 | an interface for update params 78 | """ 79 | def test(self) -> Dict: 80 | r""" 81 | an interface to start testing 82 | Returns 83 | ------- 84 | Dict 85 | result object which need to contain the key "main_performance" in case of hyper-parameter optimization 86 | """ 87 | def set_random_seed(self): 88 | seed = self._hyper_params["random_seed"] 89 | random.seed(seed) 90 | os.environ['PYTHONHASHSEED'] = str(seed) 91 | np.random.seed(seed) 92 | torch.manual_seed(seed) 93 | -------------------------------------------------------------------------------- /snot/models/fcpp/engine/tester/tester_impl/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import glob 3 | from os.path import basename, dirname, isfile 4 | 5 | modules = glob.glob(dirname(__file__) + "/*.py") 6 | __all__ = [ 7 | basename(f)[:-3] for f in modules if isfile(f) 8 | and not f.endswith("__init__.py") and not f.endswith("utils.py") 9 | ] 10 | -------------------------------------------------------------------------------- /snot/models/fcpp/engine/tester/tester_impl/uav.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | import copy 3 | 4 | import torch 5 | 6 | from ..tester_base import TRACK_TESTERS, TesterBase 7 | from .utils.benchmark_helper import PipelineTracker 8 | 9 | 10 | @TRACK_TESTERS.register 11 | class UAVTester(TesterBase): 12 | r"""UAV tester 13 | """ 14 | extra_hyper_params = dict( 15 | device_num=1, 16 | data_root="", 17 | subsets=["UAV123"], # (UAV123|UAV20L) 18 | ) 19 | 20 | def __init__(self, *args, **kwargs): 21 | super(UAVTester, self).__init__(*args, **kwargs) 22 | # self._experiment = None 23 | 24 | def update_params(self): 25 | # set device state 26 | num_gpu = self._hyper_params["device_num"] 27 | if num_gpu > 0: 28 | all_devs = [torch.device("cuda:%d" % i) for i in range(num_gpu)] 29 | else: 30 | all_devs = [torch.device("cpu")] 31 | self._state["all_devs"] = all_devs 32 | 33 | def init(self, img, gt_bbox): 34 | tracker_name = self._hyper_params["exp_name"] 35 | for subset in self._hyper_params["subsets"]: 36 | self._pipeline.set_device(1) 37 | self.pipeline_tracker = PipelineTracker(tracker_name, self._pipeline) 38 | self.pipeline_tracker.init(img, gt_bbox) 39 | 40 | def track(self, img): 41 | boxes = self.pipeline_tracker.update(img) 42 | return boxes 43 | 44 | UAVTester.default_hyper_params = copy.deepcopy(UAVTester.default_hyper_params) 45 | UAVTester.default_hyper_params.update(UAVTester.extra_hyper_params) 46 | -------------------------------------------------------------------------------- /snot/models/fcpp/engine/tester/tester_impl/utils/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | -------------------------------------------------------------------------------- /snot/models/fcpp/engine/tester/tester_impl/utils/benchmark_helper.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | import numpy as np 3 | 4 | from snot.models.fcpp.pipeline.pipeline_base import PipelineBase 5 | 6 | 7 | class PipelineTracker(object): 8 | def __init__(self, 9 | name: str, 10 | pipeline: PipelineBase, 11 | is_deterministic: bool = True): 12 | """Helper tracker for comptability with 13 | 14 | Parameters 15 | ---------- 16 | name : str 17 | [description] 18 | pipeline : PipelineBase 19 | [description] 20 | is_deterministic : bool, optional 21 | [description], by default False 22 | """ 23 | self.name = name 24 | self.is_deterministic = is_deterministic 25 | self.pipeline = pipeline 26 | 27 | def init(self, image: np.array, box): 28 | """Initialize pipeline tracker 29 | 30 | Parameters 31 | ---------- 32 | image : np.array 33 | image of the first frame 34 | box : np.array or List 35 | tracking bbox on the first frame 36 | formate: (x, y, w, h) 37 | """ 38 | self.pipeline.init(image, box) 39 | 40 | def update(self, image: np.array): 41 | """Perform tracking 42 | 43 | Parameters 44 | ---------- 45 | image : np.array 46 | image of the current frame 47 | 48 | Returns 49 | ------- 50 | np.array 51 | tracking bbox 52 | formate: (x, y, w, h) 53 | """ 54 | return self.pipeline.update(image) 55 | 56 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/backbone/__init__.py: -------------------------------------------------------------------------------- 1 | from .backbone_impl import * # noqa 2 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/backbone/backbone_base.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | from snot.utils.utils_fcpp import Registry 3 | 4 | TRACK_BACKBONES = Registry('TRACK_BACKBONES') 5 | 6 | TASK_BACKBONES = dict(track=TRACK_BACKBONES) 7 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/backbone/backbone_impl/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import glob 3 | from os.path import basename, dirname, isfile 4 | 5 | modules = glob.glob(dirname(__file__) + "/*.py") 6 | modules = [m for m in modules if not m.endswith(('_bak.py')) 7 | ] # filter file with name ending with '_bak' (debugging) 8 | __all__ = [ 9 | basename(f)[:-3] for f in modules if isfile(f) 10 | and not f.endswith("__init__.py") and not f.endswith("utils.py") 11 | ] 12 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/backbone/backbone_impl/alexnet_bn.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | 3 | import torch.nn as nn 4 | 5 | from snot.models.fcpp.model.backbone.backbone_base import (TRACK_BACKBONES) 6 | from snot.models.fcpp.model.common_opr.common_block import conv_bn_relu 7 | from snot.models.fcpp.model.module_base import ModuleBase 8 | 9 | 10 | @TRACK_BACKBONES.register 11 | class AlexNet(ModuleBase): 12 | r""" 13 | AlexNet 14 | 15 | Hyper-parameters 16 | ---------------- 17 | pretrain_model_path: string 18 | Path to pretrained backbone parameter file, 19 | Parameter to be loaded in _update_params_ 20 | """ 21 | default_hyper_params = {"pretrain_model_path": ""} 22 | 23 | def __init__(self): 24 | super(AlexNet, self).__init__() 25 | self.conv1 = conv_bn_relu(3, 96, stride=2, kszie=11, pad=0) 26 | self.pool1 = nn.MaxPool2d(3, 2, 0, ceil_mode=True) 27 | self.conv2 = conv_bn_relu(96, 256, 1, 5, 0) 28 | self.pool2 = nn.MaxPool2d(3, 2, 0, ceil_mode=True) 29 | self.conv3 = conv_bn_relu(256, 384, 1, 3, 0) 30 | self.conv4 = conv_bn_relu(384, 384, 1, 3, 0) 31 | self.conv5 = conv_bn_relu(384, 256, 1, 3, 0, has_relu=False) 32 | 33 | def forward(self, x): 34 | x = self.conv1(x) 35 | x = self.pool1(x) 36 | x = self.conv2(x) 37 | x = self.pool2(x) 38 | x = self.conv3(x) 39 | x = self.conv4(x) 40 | x = self.conv5(x) 41 | return x 42 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/backbone/builder.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | from typing import Dict, List 3 | 4 | from yacs.config import CfgNode 5 | 6 | from snot.utils.utils_fcpp import merge_cfg_into_hps 7 | 8 | from .backbone_base import TASK_BACKBONES 9 | 10 | 11 | def build(task: str, cfg: CfgNode, basemodel=None): 12 | r""" 13 | Builder function. 14 | 15 | Arguments 16 | --------- 17 | task: str 18 | builder task name (track|vos) 19 | cfg: CfgNode 20 | buidler configuration 21 | 22 | basemodel: 23 | warp backbone into encoder if not None 24 | 25 | Returns 26 | ------- 27 | torch.nn.Module 28 | module built by builder 29 | """ 30 | modules = TASK_BACKBONES[task] 31 | 32 | 33 | name = cfg.name 34 | assert name in modules, "backbone {} not registered for {}!".format(name, task) 35 | 36 | if basemodel: 37 | module = modules[name](basemodel) 38 | else: 39 | module = modules[name]() 40 | 41 | hps = module.get_hps() 42 | hps = merge_cfg_into_hps(cfg[name], hps) 43 | module.set_hps(hps) 44 | module.update_params() 45 | return module 46 | 47 | 48 | def get_config(task_list: List) -> Dict[str, CfgNode]: 49 | r""" 50 | Get available component list config 51 | 52 | Returns 53 | ------- 54 | Dict[str, CfgNode] 55 | config with list of available components 56 | """ 57 | cfg_dict = {task: CfgNode() for task in task_list} 58 | for cfg_name, module in TASK_BACKBONES.items(): 59 | cfg = cfg_dict[cfg_name] 60 | cfg["name"] = "unknown" 61 | for name in module: 62 | cfg[name] = CfgNode() 63 | backbone = module[name] 64 | hps = backbone.default_hyper_params 65 | for hp_name in hps: 66 | cfg[name][hp_name] = hps[hp_name] 67 | return cfg_dict 68 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/builder.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | from typing import Dict, List 3 | 4 | from loguru import logger 5 | from yacs.config import CfgNode 6 | 7 | from .backbone import builder as backbone_builder 8 | from .loss import builder as loss_builder 9 | from .task_head import builder as head_builder 10 | from .task_model import builder as task_builder 11 | 12 | 13 | def build(task: str, cfg: CfgNode): 14 | r""" 15 | Builder function. 16 | 17 | Arguments 18 | --------- 19 | task: str 20 | builder task name (track|vos) 21 | cfg: CfgNode 22 | node name: model 23 | 24 | Returns 25 | ------- 26 | torch.nn.Module 27 | module built by builder 28 | """ 29 | if task == "track": 30 | backbone = backbone_builder.build(task, cfg.backbone) 31 | head = head_builder.build(task, cfg.task_head) 32 | losses = loss_builder.build(task, cfg.losses) 33 | task_model = task_builder.build(task, cfg.task_model, backbone, head, losses) 34 | 35 | else: 36 | logger.error("model for task {} has not been implemented".format(task)) 37 | exit(-1) 38 | 39 | return task_model 40 | 41 | 42 | def get_config(task_list: List) -> Dict[str, CfgNode]: 43 | r""" 44 | Get available component list config 45 | 46 | Returns 47 | ------- 48 | Dict[str, CfgNode] 49 | config with list of available components 50 | """ 51 | cfg_dict = {task: CfgNode() for task in task_list} 52 | 53 | for task in cfg_dict: 54 | cfg = cfg_dict[task] 55 | cfg["backbone"] = backbone_builder.get_config(task_list)[task] 56 | cfg["task_head"] = head_builder.get_config(task_list)[task] 57 | cfg["losses"] = loss_builder.get_config(task_list)[task] 58 | cfg["task_model"] = task_builder.get_config(task_list)[task] 59 | cfg["use_sync_bn"] = False 60 | 61 | return cfg_dict 62 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/loss/__init__.py: -------------------------------------------------------------------------------- 1 | from .loss_impl import * # noqa 2 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/loss/builder.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | from collections import OrderedDict 3 | from typing import Dict, List 4 | 5 | from yacs.config import CfgNode 6 | 7 | from snot.models.fcpp.model.loss.loss_base import TASK_LOSSES 8 | from snot.utils.utils_fcpp import merge_cfg_into_hps 9 | 10 | 11 | def build(task: str, cfg: CfgNode): 12 | MODULES = TASK_LOSSES[task] 13 | 14 | names = cfg.names 15 | loss_dict = OrderedDict() 16 | for name in names: 17 | assert name in MODULES, "loss {} not registered for {}!".format( 18 | name, task) 19 | module = MODULES[name]() 20 | hps = module.get_hps() 21 | hps = merge_cfg_into_hps(cfg[name], hps) 22 | module.set_hps(hps) 23 | module.update_params() 24 | loss_dict[cfg[name].name] = module 25 | 26 | return loss_dict 27 | 28 | 29 | def get_config(task_list: List) -> Dict[str, CfgNode]: 30 | cfg_dict = {name: CfgNode() for name in task_list} 31 | 32 | for cfg_name, modules in TASK_LOSSES.items(): 33 | cfg = cfg_dict[cfg_name] 34 | cfg["names"] = list() 35 | for name in modules: 36 | cfg[name] = CfgNode() 37 | backbone = modules[name] 38 | hps = backbone.default_hyper_params 39 | for hp_name in hps: 40 | cfg[name][hp_name] = hps[hp_name] 41 | return cfg_dict 42 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/loss/loss_base.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | from snot.utils.utils_fcpp import Registry 3 | 4 | TRACK_LOSSES = Registry('TRACK_LOSSES') 5 | 6 | TASK_LOSSES = dict( track=TRACK_LOSSES) 7 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/loss/loss_impl/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import glob 3 | from os.path import basename, dirname, isfile 4 | 5 | modules = glob.glob(dirname(__file__) + "/*.py") 6 | modules = [m for m in modules if not m.endswith(('_bak.py')) 7 | ] # filter file with name ending with '_bak' (debugging) 8 | __all__ = [ 9 | basename(f)[:-3] for f in modules if isfile(f) 10 | and not f.endswith("__init__.py") and not f.endswith("utils.py") 11 | ] 12 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/module_base.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | from copy import deepcopy 3 | 4 | from loguru import logger 5 | 6 | import torch 7 | from torch import nn 8 | 9 | from snot.utils.utils_fcpp import md5sum 10 | 11 | from .utils.load_state import (filter_reused_missing_keys, 12 | get_missing_parameters_message, 13 | get_unexpected_parameters_message) 14 | 15 | 16 | class ModuleBase(nn.Module): 17 | r""" 18 | Module/component base class 19 | """ 20 | # Define your default hyper-parameters here in your sub-class. 21 | default_hyper_params = dict(pretrain_model_path="") 22 | 23 | def __init__(self): 24 | super(ModuleBase, self).__init__() 25 | self._hyper_params = deepcopy(self.default_hyper_params) 26 | 27 | def get_hps(self) -> dict(): 28 | r""" 29 | Getter function for hyper-parameters 30 | 31 | Returns 32 | ------- 33 | dict 34 | hyper-parameters 35 | """ 36 | return self._hyper_params 37 | 38 | def set_hps(self, hps: dict()) -> None: 39 | r""" 40 | Set hyper-parameters 41 | 42 | Arguments 43 | --------- 44 | hps: dict 45 | dict of hyper-parameters, the keys must in self.__hyper_params__ 46 | """ 47 | for key in hps: 48 | if key not in self._hyper_params: 49 | raise KeyError 50 | self._hyper_params[key] = hps[key] 51 | 52 | def update_params(self): 53 | model_file = self._hyper_params.get("pretrain_model_path", "") 54 | if model_file != "": 55 | state_dict = torch.load(model_file, 56 | map_location=torch.device("cpu")) 57 | if "model_state_dict" in state_dict: 58 | state_dict = state_dict["model_state_dict"] 59 | self.load_model_param(state_dict) 60 | logger.info( 61 | "Load pretrained {} parameters from: {} whose md5sum is {}". 62 | format(self.__class__.__name__, model_file, md5sum(model_file))) 63 | 64 | def load_model_param(self, checkpoint_state_dict): 65 | model_state_dict = self.state_dict() 66 | for k in list(checkpoint_state_dict.keys()): 67 | if k in model_state_dict: 68 | shape_model = tuple(model_state_dict[k].shape) 69 | shape_checkpoint = tuple(checkpoint_state_dict[k].shape) 70 | if shape_model != shape_checkpoint: 71 | logger.warning( 72 | "'{}' has shape {} in the checkpoint but {} in the " 73 | "model! Skipped.".format(k, shape_checkpoint, 74 | shape_model)) 75 | checkpoint_state_dict.pop(k) 76 | # pyre-ignore 77 | incompatible = self.load_state_dict(checkpoint_state_dict, strict=False) 78 | if incompatible.missing_keys: 79 | missing_keys = filter_reused_missing_keys(self, 80 | incompatible.missing_keys) 81 | if missing_keys: 82 | logger.warning(get_missing_parameters_message(missing_keys)) 83 | if incompatible.unexpected_keys: 84 | logger.warning( 85 | get_unexpected_parameters_message(incompatible.unexpected_keys)) 86 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/task_head/__init__.py: -------------------------------------------------------------------------------- 1 | from .taskhead_impl import * # noqa 2 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/task_head/builder.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | from typing import Dict, List 3 | 4 | from yacs.config import CfgNode 5 | 6 | from snot.models.fcpp.model.task_head.taskhead_base import TASK_HEADS 7 | from snot.utils.utils_fcpp import merge_cfg_into_hps 8 | 9 | 10 | def build(task: str, cfg: CfgNode): 11 | r""" 12 | Builder function. 13 | 14 | Arguments 15 | --------- 16 | task: str 17 | builder task name (track|vos) 18 | cfg: CfgNode 19 | buidler configuration 20 | 21 | Returns 22 | ------- 23 | torch.nn.Module 24 | module built by builder 25 | """ 26 | 27 | head_modules = TASK_HEADS[task] 28 | 29 | name = cfg.name 30 | head_module = head_modules[name]() 31 | hps = head_module.get_hps() 32 | hps = merge_cfg_into_hps(cfg[name], hps) 33 | head_module.set_hps(hps) 34 | head_module.update_params() 35 | 36 | return head_module 37 | 38 | 39 | def get_config(task_list: List) -> Dict[str, CfgNode]: 40 | r""" 41 | Get available component list config 42 | 43 | Returns 44 | ------- 45 | Dict[str, CfgNode] 46 | config with list of available components 47 | """ 48 | cfg_dict = {task: CfgNode() for task in task_list} 49 | for cfg_name, module in TASK_HEADS.items(): 50 | cfg = cfg_dict[cfg_name] 51 | cfg["name"] = "unknown" 52 | for name in module: 53 | cfg[name] = CfgNode() 54 | task_model = module[name] 55 | hps = task_model.default_hyper_params 56 | for hp_name in hps: 57 | cfg[name][hp_name] = hps[hp_name] 58 | return cfg_dict 59 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/task_head/taskhead_base.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | from snot.utils.utils_fcpp import Registry 3 | 4 | TRACK_HEADS = Registry('TRACK_HEADS') 5 | 6 | TASK_HEADS = dict(track=TRACK_HEADS) 7 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/task_head/taskhead_impl/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import glob 3 | from os.path import basename, dirname, isfile 4 | 5 | modules = glob.glob(dirname(__file__) + "/*.py") 6 | modules = [m for m in modules if not m.endswith(('_bak.py')) 7 | ] # filter file with name ending with '_bak' (debugging) 8 | __all__ = [ 9 | basename(f)[:-3] for f in modules if isfile(f) 10 | and not f.endswith("__init__.py") and not f.endswith("utils.py") 11 | ] 12 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/task_model/__init__.py: -------------------------------------------------------------------------------- 1 | from .taskmodel_impl import * # noqa 2 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/task_model/builder.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | from typing import Dict, List 3 | 4 | from yacs.config import CfgNode 5 | 6 | from snot.models.fcpp.model.module_base import ModuleBase 7 | from snot.models.fcpp.model.task_model.taskmodel_base import TASK_TASKMODELS 8 | from snot.utils.utils_fcpp import merge_cfg_into_hps 9 | 10 | 11 | def build(task: str, 12 | cfg: CfgNode, 13 | backbone: ModuleBase, 14 | head: ModuleBase, 15 | loss: ModuleBase = None): 16 | r""" 17 | Builder function. 18 | 19 | Arguments 20 | --------- 21 | task: str 22 | builder task name 23 | cfg: CfgNode 24 | buidler configuration 25 | backbone: torch.nn.Module 26 | backbone used by task module. 27 | head: torch.nn.Module 28 | head network used by task module. 29 | loss: torch.nn.Module 30 | criterion module used by task module (for training). None in case other than training. 31 | 32 | Returns 33 | ------- 34 | torch.nn.Module 35 | task module built by builder 36 | """ 37 | task_modules = TASK_TASKMODELS[task] 38 | 39 | name = cfg.name 40 | task_module = task_modules[name](backbone, head, loss) 41 | hps = task_module.get_hps() 42 | hps = merge_cfg_into_hps(cfg[name], hps) 43 | task_module.set_hps(hps) 44 | task_module.update_params() 45 | return task_module 46 | 47 | 48 | def get_config(task_list: List) -> Dict[str, CfgNode]: 49 | """ 50 | Get available component list config 51 | 52 | Returns 53 | ------- 54 | Dict[str, CfgNode] 55 | config with list of available components 56 | """ 57 | cfg_dict = {task: CfgNode() for task in task_list} 58 | for cfg_name, task_module in TASK_TASKMODELS.items(): 59 | cfg = cfg_dict[cfg_name] 60 | cfg["name"] = "unknown" 61 | for name in task_module: 62 | cfg[name] = CfgNode() 63 | task_model = task_module[name] 64 | hps = task_model.default_hyper_params 65 | for hp_name in hps: 66 | cfg[name][hp_name] = hps[hp_name] 67 | return cfg_dict 68 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/task_model/taskmodel_base.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | from snot.utils.utils_fcpp import Registry 3 | 4 | TRACK_TASKMODELS = Registry('TRACK_TASKMODELS') 5 | 6 | TASK_TASKMODELS = dict(track=TRACK_TASKMODELS) 7 | -------------------------------------------------------------------------------- /snot/models/fcpp/model/task_model/taskmodel_impl/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import glob 3 | from os.path import basename, dirname, isfile 4 | 5 | modules = glob.glob(dirname(__file__) + "/*.py") 6 | modules = [m for m in modules if not m.endswith(('_bak.py')) 7 | ] # filter file with name ending with '_bak' (debugging) 8 | __all__ = [ 9 | basename(f)[:-3] for f in modules if isfile(f) 10 | and not f.endswith("__init__.py") and not f.endswith("utils.py") 11 | ] 12 | -------------------------------------------------------------------------------- /snot/models/fcpp/pipeline/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | from .tracker_impl import * # noqa 3 | -------------------------------------------------------------------------------- /snot/models/fcpp/pipeline/builder.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | from typing import Dict, List 3 | 4 | from loguru import logger 5 | from yacs.config import CfgNode 6 | 7 | from snot.models.fcpp.model.module_base import ModuleBase 8 | from snot.models.fcpp.pipeline.pipeline_base import PIPELINES 9 | from snot.utils.utils_fcpp import merge_cfg_into_hps 10 | 11 | 12 | def build( 13 | task: str, 14 | cfg: CfgNode, 15 | model: ModuleBase = None, 16 | segmenter: ModuleBase = None, 17 | tracker: ModuleBase = None, 18 | ): 19 | r""" 20 | Builder function. 21 | 22 | Arguments 23 | --------- 24 | task: str 25 | task name 26 | cfg: CfgNode 27 | buidler configuration 28 | model: ModuleBase 29 | model instance for siamfcpp 30 | segmenter: ModuleBase 31 | segmenter instance for tracker 32 | tracker: ModuleBase 33 | model instance for tracker 34 | 35 | Returns 36 | ------- 37 | torch.nn.Module 38 | module built by builder 39 | """ 40 | assert task in PIPELINES, "no pipeline for task {}".format(task) 41 | pipelines = PIPELINES[task] 42 | pipeline_name = cfg.name 43 | 44 | pipeline = pipelines[pipeline_name](model) 45 | hps = pipeline.get_hps() 46 | hps = merge_cfg_into_hps(cfg[pipeline_name], hps) 47 | pipeline.set_hps(hps) 48 | pipeline.update_params() 49 | 50 | return pipeline 51 | 52 | 53 | def get_config(task_list: List) -> Dict[str, CfgNode]: 54 | """ 55 | Get available component list config 56 | 57 | Returns 58 | ------- 59 | Dict[str, CfgNode] 60 | config with list of available components 61 | """ 62 | cfg_dict = {name: CfgNode() for name in task_list} 63 | for cfg_name, task_module in PIPELINES.items(): 64 | cfg = cfg_dict[cfg_name] 65 | cfg["name"] = "unknown" 66 | for name in task_module: 67 | cfg[name] = CfgNode() 68 | task_model = task_module[name] 69 | hps = task_model.default_hyper_params 70 | for hp_name in hps: 71 | cfg[name][hp_name] = hps[hp_name] 72 | return cfg_dict 73 | -------------------------------------------------------------------------------- /snot/models/fcpp/pipeline/pipeline_base.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | from copy import deepcopy 3 | 4 | from snot.models.fcpp.model.module_base import ModuleBase 5 | from snot.utils.utils_fcpp import Registry 6 | 7 | TRACK_PIPELINES = Registry('TRACK_PIPELINES') 8 | 9 | PIPELINES = dict(track=TRACK_PIPELINES) 10 | 11 | 12 | class PipelineBase: 13 | r""" 14 | Pipeline base class (e.g. procedure defined for tracker / segmentor / etc.) 15 | Interface descriptions: 16 | init(im, state): 17 | update(im): 18 | """ 19 | # Define your default hyper-parameters here in your sub-class. 20 | default_hyper_params = dict() 21 | 22 | def __init__(self, model: ModuleBase): 23 | self._hyper_params = deepcopy( 24 | self.default_hyper_params) # mapping-like object 25 | self._state = dict() # pipeline state 26 | self._model = model 27 | 28 | def get_hps(self) -> dict(): 29 | r""" 30 | Getter function for hyper-parameters 31 | 32 | Returns 33 | ------- 34 | dict 35 | hyper-parameters 36 | """ 37 | return self._hyper_params 38 | 39 | def set_hps(self, hps: dict()) -> None: 40 | r""" 41 | Set hyper-parameters 42 | 43 | Arguments 44 | --------- 45 | hps: dict 46 | dict of hyper-parameters, the keys must in self.__hyper_params__ 47 | """ 48 | for key in hps: 49 | if key not in self._hyper_params: 50 | raise KeyError 51 | self._hyper_params[key] = hps[key] 52 | 53 | def update_params(self): 54 | r""" 55 | an interface for update params 56 | """ 57 | def init(self, im, state): 58 | r""" 59 | an interface for pipeline initialization (e.g. template feature extraction) 60 | default implementation: record initial state & do nothing 61 | 62 | Arguments 63 | --------- 64 | im: numpy.array 65 | initial frame image 66 | state: 67 | initial state (usually depending on task) (e.g. bbox for track / mask for vos) 68 | """ 69 | self._state['state'] = state 70 | 71 | def update(self, im): 72 | r""" 73 | an interface for pipeline update 74 | (e.g. output target bbox for current frame given the frame and previous target bbox) 75 | default implementation: return previous target state (initial state) 76 | 77 | Arguments 78 | --------- 79 | im: numpy.array 80 | current frame 81 | 82 | Returns 83 | ------- 84 | state 85 | predicted sstate (usually depending on task) (e.g. bbox for track / mask for vos) 86 | """ 87 | state = self._state['state'] 88 | return state 89 | -------------------------------------------------------------------------------- /snot/models/fcpp/pipeline/tracker_impl/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import glob 3 | from os.path import basename, dirname, isfile 4 | 5 | modules = glob.glob(dirname(__file__) + "/*.py") 6 | modules = [m for m in modules if not m.endswith(('_bak.py')) 7 | ] # filter file with name ending with '_bak' (debugging) 8 | __all__ = [ 9 | basename(f)[:-3] for f in modules if isfile(f) 10 | and not f.endswith("__init__.py") and not f.endswith("utils.py") 11 | ] 12 | -------------------------------------------------------------------------------- /snot/models/fcpp/pipeline/utils/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | 3 | from .bbox import (clip_bbox, cxywh2xywh, cxywh2xyxy, xywh2cxywh, xywh2xyxy, 4 | xyxy2cxywh, xyxy2xywh, cxy_wh_2_rect) 5 | from .crop import get_axis_aligned_bbox, get_crop, get_subwindow_tracking 6 | from .misc import imarray_to_tensor, tensor_to_numpy 7 | 8 | __all__ = [ 9 | clip_bbox, cxy_wh_2_rect, cxywh2xywh, cxywh2xyxy, xywh2cxywh, xywh2cxywh, 10 | xyxy2cxywh, xyxy2xywh, xywh2xyxy, get_axis_aligned_bbox, get_crop, 11 | get_subwindow_tracking, imarray_to_tensor, tensor_to_numpy 12 | ] 13 | -------------------------------------------------------------------------------- /snot/models/fcpp/pipeline/utils/misc.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | 3 | import numpy as np 4 | 5 | import torch 6 | 7 | 8 | def imarray_to_tensor(arr): 9 | r""" 10 | Transpose & convert from numpy.array to torch.Tensor 11 | :param arr: numpy.array, (H, W, C) 12 | :return: torch.Tensor, (1, C, H, W) 13 | """ 14 | arr = np.ascontiguousarray( 15 | arr.transpose(2, 0, 1)[np.newaxis, ...], np.float32) 16 | return torch.from_numpy(arr) 17 | 18 | 19 | def tensor_to_imarray(t): 20 | r""" 21 | Perform naive detach / cpu / numpy process and then transpose 22 | cast dtype to np.uint8 23 | :param t: torch.Tensor, (1, C, H, W) 24 | :return: numpy.array, (H, W, C) 25 | """ 26 | arr = t.detach().cpu().numpy().astype(np.uint8) 27 | if arr.ndim == 4: 28 | arr = arr[0] 29 | return arr.transpose(1, 2, 0) 30 | 31 | 32 | def tensor_to_numpy(t): 33 | r""" 34 | Perform naive detach / cpu / numpy process. 35 | :param t: torch.Tensor, (N, C, H, W) 36 | :return: numpy.array, (N, C, H, W) 37 | """ 38 | arr = t.detach().cpu().numpy() 39 | return arr 40 | -------------------------------------------------------------------------------- /snot/models/fcpp/pipeline/utils/online_classifier/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/snot/models/fcpp/pipeline/utils/online_classifier/__init__.py -------------------------------------------------------------------------------- /snot/models/fcpp/pipeline/utils/online_classifier/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .tensordict import TensorDict 2 | from .tensorlist import TensorList 3 | 4 | __all__ = [TensorDict, TensorList] 5 | -------------------------------------------------------------------------------- /snot/models/fcpp/pipeline/utils/online_classifier/utils/attention.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def normalize(score): 5 | score = (score - np.min(score)) / (np.max(score) - np.min(score)) 6 | return score 7 | 8 | 9 | def normfun(x, mu, sigma): 10 | pdf = np.exp(-((x - mu)**2) / (2 * sigma**2)) 11 | return pdf 12 | 13 | 14 | def generate_xy_attention(center, size): 15 | 16 | a = np.linspace(-size // 2 + 1, size // 2, size) 17 | x = -normfun(a, center[1], 10).reshape((size, 1)) + 2 18 | y = -normfun(a, center[0], 10).reshape((1, size)) + 2 19 | z = normalize(1. / np.dot(np.abs(x), np.abs(y))) 20 | return z 21 | 22 | 23 | if __name__ == '__main__': 24 | generate_xy_attention([0, 0], 31) 25 | -------------------------------------------------------------------------------- /snot/models/fcpp/pipeline/utils/online_classifier/utils/operation.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn.functional as F 3 | 4 | from .tensorlist import tensor_operation 5 | 6 | 7 | @tensor_operation 8 | def conv2d(input: torch.Tensor, 9 | weight: torch.Tensor, 10 | bias: torch.Tensor = None, 11 | stride=1, 12 | padding=0, 13 | dilation=1, 14 | groups=1, 15 | mode=None): 16 | """Standard conv2d. Returns the input if weight=None.""" 17 | 18 | if weight is None: 19 | return input 20 | 21 | ind = None 22 | if mode is not None: 23 | if padding != 0: 24 | raise ValueError('Cannot input both padding and mode.') 25 | if mode == 'same': 26 | padding = (weight.shape[2] // 2, weight.shape[3] // 2) 27 | if weight.shape[2] % 2 == 0 or weight.shape[3] % 2 == 0: 28 | ind = (slice(-1) if weight.shape[2] % 2 == 0 else slice(None), 29 | slice(-1) if weight.shape[3] % 2 == 0 else slice(None)) 30 | elif mode == 'valid': 31 | padding = (0, 0) 32 | elif mode == 'full': 33 | padding = (weight.shape[2] - 1, weight.shape[3] - 1) 34 | else: 35 | raise ValueError('Unknown mode for padding.') 36 | 37 | out = F.conv2d(input, 38 | weight, 39 | bias=bias, 40 | stride=stride, 41 | padding=padding, 42 | dilation=dilation, 43 | groups=groups) 44 | if ind is None: 45 | return out 46 | return out[:, :, ind[0], ind[1]] 47 | 48 | 49 | @tensor_operation 50 | def conv1x1(input: torch.Tensor, weight: torch.Tensor): 51 | """Do a convolution with a 1x1 kernel weights. Implemented with matmul, which can be faster than using conv.""" 52 | 53 | if weight is None: 54 | return input 55 | 56 | return torch.matmul(weight.view(weight.shape[0], weight.shape[1]), 57 | input.view(input.shape[0], input.shape[1], 58 | -1)).view(input.shape[0], weight.shape[0], 59 | input.shape[2], input.shape[3]) 60 | 61 | 62 | @tensor_operation 63 | def spatial_attention(input: torch.Tensor, dim: int = 0, keepdim: bool = True): 64 | return torch.sigmoid(torch.mean(input, dim, keepdim)) 65 | 66 | 67 | @tensor_operation 68 | def adaptive_avg_pool2d(input: torch.Tensor, shape): 69 | return F.adaptive_avg_pool2d(input, shape) 70 | 71 | 72 | @tensor_operation 73 | def sigmoid(input: torch.Tensor): 74 | return torch.sigmoid(input) 75 | 76 | 77 | @tensor_operation 78 | def softmax(input: torch.Tensor): 79 | x_shape = input.size() 80 | return F.softmax(input.reshape(x_shape[0], -1), dim=1).reshape(x_shape) 81 | 82 | 83 | @tensor_operation 84 | def matmul(a: torch.Tensor, b: torch.Tensor): 85 | return a * b.expand_as(a) 86 | -------------------------------------------------------------------------------- /snot/models/fcpp/pipeline/utils/online_classifier/utils/plotting.py: -------------------------------------------------------------------------------- 1 | import matplotlib 2 | 3 | # matplotlib.use('TkAgg') # disabled as Import Error with tk interactive framework 4 | # TODO: verify if this matplotlib backend is necessary 5 | import matplotlib.pyplot as plt 6 | import numpy as np 7 | 8 | import torch 9 | 10 | 11 | def show_tensor(a: torch.Tensor, fig_num=None, title=None): 12 | """Display a 2D tensor. 13 | args: 14 | fig_num: Figure number. 15 | title: Title of figure. 16 | """ 17 | a_np = a.squeeze().cpu().clone().detach().numpy() 18 | if a_np.ndim == 3: 19 | a_np = np.transpose(a_np, (1, 2, 0)) 20 | plt.figure(fig_num) 21 | plt.tight_layout() 22 | plt.cla() 23 | plt.imshow(a_np) 24 | plt.axis('off') 25 | plt.axis('equal') 26 | if title is not None: 27 | plt.title(title) 28 | plt.draw() 29 | plt.pause(0.001) 30 | 31 | 32 | def plot_graph(a: torch.Tensor, fig_num=None, title=None): 33 | """Plot graph. Data is a 1D tensor. 34 | args: 35 | fig_num: Figure number. 36 | title: Title of figure. 37 | """ 38 | a_np = a.squeeze().cpu().clone().detach().numpy() 39 | if a_np.ndim > 1: 40 | raise ValueError 41 | plt.figure(fig_num) 42 | # plt.tight_layout() 43 | plt.cla() 44 | plt.plot(a_np) 45 | if title is not None: 46 | plt.title(title) 47 | plt.draw() 48 | plt.pause(0.001) 49 | -------------------------------------------------------------------------------- /snot/models/fcpp/pipeline/utils/online_classifier/utils/preprocessing.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | import torch 4 | import torch.nn.functional as F 5 | 6 | 7 | def numpy_to_torch(a: np.ndarray): 8 | return torch.from_numpy(a).float().permute(2, 0, 1).unsqueeze(0) 9 | 10 | 11 | def torch_to_numpy(a: torch.Tensor): 12 | return a.squeeze(0).permute(1, 2, 0).numpy() 13 | 14 | 15 | def sample_patch(im: torch.Tensor, 16 | pos: torch.Tensor, 17 | sample_sz: torch.Tensor, 18 | output_sz: torch.Tensor = None): 19 | """Sample an image patch. 20 | 21 | args: 22 | im: Image 23 | pos: center position of crop 24 | sample_sz: size to crop 25 | output_sz: size to resize to 26 | """ 27 | 28 | # copy and convert 29 | posl = pos.long().clone() 30 | 31 | # Compute pre-downsampling factor 32 | if output_sz is not None: 33 | resize_factor = torch.min(sample_sz.float() / output_sz.float()).item() 34 | df = int(max(int(resize_factor - 0.1), 1)) 35 | else: 36 | df = int(1) 37 | 38 | sz = sample_sz.float() / df # new size 39 | 40 | # Do downsampling 41 | if df > 1: 42 | os = posl % df # offset 43 | posl = (posl - os) / df # new position 44 | im2 = im[..., os[0].item()::df, os[1].item()::df] # downsample 45 | else: 46 | im2 = im 47 | 48 | # compute size to crop 49 | szl = torch.max(sz.round(), torch.Tensor([2])).long() 50 | 51 | # Extract top and bottom coordinates 52 | tl = posl - (szl - 1) / 2 53 | br = posl + szl / 2 54 | 55 | # Get image patch 56 | im_patch = F.pad(im2, (-tl[1].item(), br[1].item() - im2.shape[3] + 1, 57 | -tl[0].item(), br[0].item() - im2.shape[2] + 1), 58 | 'replicate') 59 | 60 | if output_sz is None or (im_patch.shape[-2] == output_sz[0] 61 | and im_patch.shape[-1] == output_sz[1]): 62 | return im_patch 63 | 64 | # Resample 65 | im_patch = F.interpolate(im_patch, 66 | output_sz.long().tolist(), 67 | mode='bilinear') 68 | 69 | return im_patch 70 | -------------------------------------------------------------------------------- /snot/models/fcpp/pipeline/utils/online_classifier/utils/tensordict.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | import torch 4 | 5 | 6 | class TensorDict(OrderedDict): 7 | """Container mainly used for dicts of torch tensors. Extends OrderedDict with pytorch functionality.""" 8 | def concat(self, other): 9 | """Concatenates two dicts without copying internal data.""" 10 | return TensorDict(self, **other) 11 | 12 | def copy(self): 13 | return TensorDict(super(TensorDict, self).copy()) 14 | 15 | def __getattr__(self, name): 16 | if not hasattr(torch.Tensor, name): 17 | raise AttributeError( 18 | '\'TensorDict\' object has not attribute \'{}\''.format(name)) 19 | 20 | def apply_attr(*args, **kwargs): 21 | return TensorDict({ 22 | n: getattr(e, name)(*args, **kwargs) if hasattr(e, name) else e 23 | for n, e in self.items() 24 | }) 25 | 26 | return apply_attr 27 | 28 | def attribute(self, attr: str, *args): 29 | return TensorDict({n: getattr(e, attr, *args) for n, e in self.items()}) 30 | 31 | def apply(self, fn, *args, **kwargs): 32 | return TensorDict({n: fn(e, *args, **kwargs) for n, e in self.items()}) 33 | 34 | @staticmethod 35 | def _iterable(a): 36 | return isinstance(a, (TensorDict, list)) 37 | -------------------------------------------------------------------------------- /snot/models/head/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | from snot.models.head.mask import MaskCorr, Refine 7 | from snot.models.head.rpn import UPChannelRPN, DepthwiseRPN, MultiRPN 8 | from snot.models.head.ban import UPChannelBAN, DepthwiseBAN, MultiBAN 9 | 10 | RPNS = { 11 | 'UPChannelRPN': UPChannelRPN, 12 | 'DepthwiseRPN': DepthwiseRPN, 13 | 'MultiRPN': MultiRPN 14 | } 15 | 16 | MASKS = { 17 | 'MaskCorr': MaskCorr, 18 | } 19 | 20 | REFINE = { 21 | 'Refine': Refine, 22 | } 23 | 24 | BANS = { 25 | 'UPChannelBAN': UPChannelBAN, 26 | 'DepthwiseBAN': DepthwiseBAN, 27 | 'MultiBAN': MultiBAN 28 | } 29 | 30 | 31 | def get_rpn_head(name, **kwargs): 32 | return RPNS[name](**kwargs) 33 | 34 | 35 | def get_mask_head(name, **kwargs): 36 | return MASKS[name](**kwargs) 37 | 38 | 39 | def get_refine_head(name): 40 | return REFINE[name]() 41 | 42 | 43 | def get_ban_head(name, **kwargs): 44 | return BANS[name](**kwargs) 45 | -------------------------------------------------------------------------------- /snot/models/head/car.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import torch 7 | from torch import nn 8 | import math 9 | 10 | 11 | class CAR(torch.nn.Module): 12 | def __init__(self, cfg, in_channels): 13 | """ 14 | Arguments: 15 | in_channels (int): number of channels of the input feature 16 | """ 17 | super(CAR, self).__init__() 18 | # TODO: Implement the sigmoid version first. 19 | num_classes = cfg.TRAIN.NUM_CLASSES 20 | 21 | cls_tower = [] 22 | bbox_tower = [] 23 | for i in range(cfg.TRAIN.NUM_CONVS): 24 | cls_tower.append( 25 | nn.Conv2d( 26 | in_channels, 27 | in_channels, 28 | kernel_size=3, 29 | stride=1, 30 | padding=1 31 | ) 32 | ) 33 | cls_tower.append(nn.GroupNorm(32, in_channels)) 34 | cls_tower.append(nn.ReLU()) 35 | bbox_tower.append( 36 | nn.Conv2d( 37 | in_channels, 38 | in_channels, 39 | kernel_size=3, 40 | stride=1, 41 | padding=1 42 | ) 43 | ) 44 | bbox_tower.append(nn.GroupNorm(32, in_channels)) 45 | bbox_tower.append(nn.ReLU()) 46 | 47 | self.add_module('cls_tower', nn.Sequential(*cls_tower)) 48 | self.add_module('bbox_tower', nn.Sequential(*bbox_tower)) 49 | self.cls_logits = nn.Conv2d( 50 | in_channels, num_classes, kernel_size=3, stride=1, 51 | padding=1 52 | ) 53 | self.bbox_pred = nn.Conv2d( 54 | in_channels, 4, kernel_size=3, stride=1, 55 | padding=1 56 | ) 57 | self.centerness = nn.Conv2d( 58 | in_channels, 1, kernel_size=3, stride=1, 59 | padding=1 60 | ) 61 | 62 | # initialization 63 | for modules in [self.cls_tower, self.bbox_tower, 64 | self.cls_logits, self.bbox_pred, 65 | self.centerness]: 66 | for l in modules.modules(): 67 | if isinstance(l, nn.Conv2d): 68 | torch.nn.init.normal_(l.weight, std=0.01) 69 | torch.nn.init.constant_(l.bias, 0) 70 | 71 | # initialize the bias for focal loss 72 | prior_prob = cfg.TRAIN.PRIOR_PROB 73 | bias_value = -math.log((1 - prior_prob) / prior_prob) 74 | torch.nn.init.constant_(self.cls_logits.bias, bias_value) 75 | 76 | def forward(self, x): 77 | cls_tower = self.cls_tower(x) 78 | logits = self.cls_logits(cls_tower) 79 | centerness = self.centerness(cls_tower) 80 | bbox_reg = torch.exp(self.bbox_pred(self.bbox_tower(x))) 81 | 82 | return logits, bbox_reg, centerness 83 | 84 | 85 | class Scale(nn.Module): 86 | def __init__(self, init_value=1.0): 87 | super(Scale, self).__init__() 88 | self.scale = nn.Parameter(torch.FloatTensor([init_value])) 89 | 90 | def forward(self, input): 91 | return input * self.scale 92 | -------------------------------------------------------------------------------- /snot/models/lighttrack/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vision4robotics/SiameseTracking4UAV/2b9bdc4b666967a0316fad1c109bbd9ddb98f003/snot/models/lighttrack/__init__.py -------------------------------------------------------------------------------- /snot/models/lighttrack/backbone/__init__.py: -------------------------------------------------------------------------------- 1 | from .supernet import build_supernet, build_supernet_DP 2 | from .childnet import build_subnet 3 | -------------------------------------------------------------------------------- /snot/models/lighttrack/backbone/childnet.py: -------------------------------------------------------------------------------- 1 | import os 2 | import logging 3 | import torch 4 | from collections import OrderedDict 5 | from snot.models.lighttrack.backbone.models import _gen_childnet 6 | 7 | 8 | def build_subnet(path_backbone, ops=None): 9 | arch_list = path_backbone 10 | 11 | arch_def = [ 12 | # stage 0, 112x112 in 13 | ['ds_r1_k3_s1_e1_c16_se0.25'], 14 | # stage 1, 112x112 in 15 | ['ir_r1_k3_s2_e4_c24_se0.25', 'ir_r1_k3_s1_e4_c24_se0.25', 16 | 'ir_r1_k3_s1_e4_c24_se0.25', 'ir_r1_k3_s1_e4_c24_se0.25'], 17 | # stage 2, 56x56 in 18 | ['ir_r1_k5_s2_e4_c40_se0.25', 'ir_r1_k5_s1_e4_c40_se0.25', 19 | 'ir_r1_k5_s2_e4_c40_se0.25', 'ir_r1_k5_s2_e4_c40_se0.25'], 20 | # stage 3, 28x28 in 21 | ['ir_r1_k3_s2_e6_c80_se0.25', 'ir_r1_k3_s1_e4_c80_se0.25', 22 | 'ir_r1_k3_s1_e4_c80_se0.25', 'ir_r1_k3_s1_e4_c80_se0.25'], 23 | # stage 4, 14x14in 24 | ['ir_r1_k3_s1_e6_c96_se0.25', 'ir_r1_k3_s1_e6_c96_se0.25', 25 | 'ir_r1_k3_s1_e6_c96_se0.25', 'ir_r1_k3_s1_e6_c96_se0.25'], 26 | # stage 5, 14x14in 27 | ['ir_r1_k5_s2_e6_c192_se0.25', 'ir_r1_k5_s1_e6_c192_se0.25', 28 | 'ir_r1_k5_s2_e6_c192_se0.25', 'ir_r1_k5_s2_e6_c192_se0.25'], 29 | # stage 6, 7x7 in 30 | ['cn_r1_k1_s1_c320_se0.25'], 31 | ] 32 | 33 | model = _gen_childnet( 34 | arch_list, 35 | arch_def, 36 | num_classes=1000, 37 | drop_rate=0, 38 | drop_path_rate=0, 39 | global_pool='avg', 40 | bn_momentum=None, 41 | bn_eps=None, 42 | pool_bn=False, 43 | zero_gamma=False, 44 | ops=ops) 45 | 46 | return model 47 | 48 | 49 | def resume_checkpoint(model, checkpoint_path, ema=True): 50 | """2020.11.5 Modified from timm""" 51 | other_state = {} 52 | resume_epoch = None 53 | if os.path.isfile(checkpoint_path): 54 | checkpoint = torch.load(checkpoint_path, map_location='cpu') 55 | state_dict_name = 'state_dict_ema' if ema else 'state_dict' 56 | if isinstance(checkpoint, dict) and state_dict_name in checkpoint: 57 | new_state_dict = OrderedDict() 58 | for k, v in checkpoint[state_dict_name].items(): 59 | name = k[7:] if k.startswith('module') else k 60 | new_state_dict[name] = v 61 | try: 62 | model.load_state_dict(new_state_dict, strict=True) 63 | except: 64 | model.load_state_dict(new_state_dict, strict=False) 65 | print('strict = %s' % False) 66 | if 'optimizer' in checkpoint: 67 | other_state['optimizer'] = checkpoint['optimizer'] 68 | if 'amp' in checkpoint: 69 | other_state['amp'] = checkpoint['amp'] 70 | if 'epoch' in checkpoint: 71 | resume_epoch = checkpoint['epoch'] 72 | if 'version' in checkpoint and checkpoint['version'] > 1: 73 | resume_epoch += 1 # start at the next epoch, old checkpoints incremented before save 74 | logging.info("Loaded checkpoint '{}' (epoch {})".format(checkpoint_path, checkpoint['epoch'])) 75 | else: 76 | model.load_state_dict(checkpoint) 77 | logging.info("Loaded checkpoint '{}'".format(checkpoint_path)) 78 | return other_state, resume_epoch 79 | else: 80 | logging.error("No checkpoint found at '{}'".format(checkpoint_path)) 81 | raise FileNotFoundError() 82 | -------------------------------------------------------------------------------- /snot/models/lighttrack/backbone/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .hypernet import _gen_supernet 2 | from .model import _gen_childnet 3 | -------------------------------------------------------------------------------- /snot/models/lighttrack/backbone/models/resunit.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | 6 | def conv3x3(in_planes, out_planes, stride=1): 7 | "3x3 convolution with padding" 8 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, 9 | padding=1, bias=True) 10 | 11 | 12 | class BasicBlock(nn.Module): 13 | expansion = 1 14 | 15 | def __init__(self, inplanes, planes, stride=1, downsample=None): 16 | super(BasicBlock, self).__init__() 17 | self.conv1 = conv3x3(inplanes, planes, stride) 18 | self.bn1 = nn.BatchNorm2d(planes) 19 | self.relu = nn.ReLU(inplace=True) 20 | self.conv2 = conv3x3(planes, planes) 21 | self.bn2 = nn.BatchNorm2d(planes) 22 | self.downsample = downsample 23 | self.stride = stride 24 | 25 | def forward(self, x): 26 | residual = x 27 | 28 | out = self.conv1(x) 29 | out = self.bn1(out) 30 | out = self.relu(out) 31 | 32 | out = self.conv2(out) 33 | out = self.bn2(out) 34 | 35 | if self.downsample is not None: 36 | residual = self.downsample(x) 37 | 38 | out += residual 39 | out = self.relu(out) 40 | 41 | return out 42 | 43 | 44 | class Bottleneck(nn.Module): 45 | 46 | def __init__(self, inplanes, planes, stride=1, expansion=4): 47 | super(Bottleneck, self).__init__() 48 | planes = int(planes / expansion) 49 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=True) 50 | self.bn1 = nn.BatchNorm2d(planes) 51 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, 52 | padding=1, bias=True) 53 | self.bn2 = nn.BatchNorm2d(planes) 54 | self.conv3 = nn.Conv2d(planes, planes * expansion, kernel_size=1, bias=True) 55 | self.bn3 = nn.BatchNorm2d(planes * expansion) 56 | self.relu = nn.ReLU(inplace=True) 57 | self.stride = stride 58 | self.expansion = expansion 59 | if inplanes != planes * self.expansion: 60 | self.downsample = nn.Sequential( 61 | nn.Conv2d(inplanes, planes * self.expansion, 62 | kernel_size=1, stride=stride, bias=True), 63 | nn.BatchNorm2d(planes * self.expansion), 64 | ) 65 | else: 66 | self.downsample = None 67 | 68 | def forward(self, x): 69 | residual = x 70 | 71 | out = self.conv1(x) 72 | out = self.bn1(out) 73 | out = self.relu(out) 74 | 75 | out = self.conv2(out) 76 | out = self.bn2(out) 77 | out = self.relu(out) 78 | 79 | out = self.conv3(out) 80 | out = self.bn3(out) 81 | 82 | if self.downsample is not None: 83 | residual = self.downsample(x) 84 | 85 | out += residual 86 | out = self.relu(out) 87 | 88 | return out 89 | 90 | 91 | def get_Bottleneck(in_c, out_c, stride): 92 | return Bottleneck(in_c, out_c, stride=stride) 93 | 94 | 95 | def get_BasicBlock(in_c, out_c, stride): 96 | return BasicBlock(in_c, out_c, stride=stride) 97 | -------------------------------------------------------------------------------- /snot/models/lighttrack/backbone/supernet.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import torch 3 | from snot.models.lighttrack.backbone.models.hypernet import _gen_supernet 4 | 5 | 6 | def set_seed(): 7 | seed = 42 8 | torch.manual_seed(seed) 9 | torch.cuda.manual_seed_all(seed) 10 | np.random.seed(seed) 11 | torch.backends.cudnn.deterministic = True 12 | torch.backends.cudnn.benchmark = False 13 | 14 | 15 | def build_supernet(flops_maximum=600): 16 | set_seed() 17 | model, sta_num, size_factor = _gen_supernet( 18 | flops_minimum=0, 19 | flops_maximum=flops_maximum, 20 | num_classes=1000, 21 | drop_rate=0.0, 22 | global_pool='avg', 23 | resunit=False, 24 | dil_conv=False, 25 | slice=4) 26 | 27 | return model, sta_num 28 | 29 | 30 | def build_supernet_DP(flops_maximum=600): 31 | """Backbone with Dynamic output position""" 32 | set_seed() 33 | model, sta_num, size_factor = _gen_supernet( 34 | flops_minimum=0, 35 | flops_maximum=flops_maximum, 36 | DP=True, 37 | num_classes=1000, 38 | drop_rate=0.0, 39 | global_pool='avg', 40 | resunit=False, 41 | dil_conv=False, 42 | slice=4) 43 | 44 | return model, sta_num 45 | 46 | 47 | if __name__ == '__main__': 48 | _, sta_num = build_supernet(flops_maximum=600) 49 | print(sta_num) 50 | -------------------------------------------------------------------------------- /snot/models/lighttrack/connect.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | 6 | def pixel_corr(z, x): 7 | """Pixel-wise correlation (implementation by for-loop and convolution) 8 | The speed is slower because the for-loop""" 9 | size = z.size() # (bs, c, hz, wz) 10 | CORR = [] 11 | for i in range(len(x)): 12 | ker = z[i:i + 1] # (1, c, hz, wz) 13 | fea = x[i:i + 1] # (1, c, hx, wx) 14 | ker = ker.view(size[1], size[2] * size[3]).transpose(0, 1) # (hz * wz, c) 15 | ker = ker.unsqueeze(2).unsqueeze(3) # (hz * wz, c, 1, 1) 16 | co = F.conv2d(fea, ker.contiguous()) # (1, hz * wz, hx, wx) 17 | CORR.append(co) 18 | corr = torch.cat(CORR, 0) # (bs, hz * wz, hx, wx) 19 | return corr 20 | 21 | 22 | def pixel_corr_mat(z, x): 23 | """Pixel-wise correlation (implementation by matrix multiplication) 24 | The speed is faster because the computation is vectorized""" 25 | b, c, h, w = x.size() 26 | z_mat = z.view((b, c, -1)).transpose(1, 2) # (b, hz * wz, c) 27 | x_mat = x.view((b, c, -1)) # (b, c, hx * wx) 28 | return torch.matmul(z_mat, x_mat).view((b, -1, h, w)) # (b, hz * wz, hx * wx) --> (b, hz * wz, hx, wx) 29 | 30 | 31 | class CAModule(nn.Module): 32 | """Channel attention module""" 33 | 34 | def __init__(self, channels=64, reduction=1): 35 | super(CAModule, self).__init__() 36 | self.avg_pool = nn.AdaptiveAvgPool2d(1) 37 | self.fc1 = nn.Conv2d(channels, channels // reduction, kernel_size=1, 38 | padding=0) 39 | self.relu = nn.ReLU(inplace=True) 40 | self.fc2 = nn.Conv2d(channels // reduction, channels, kernel_size=1, 41 | padding=0) 42 | self.sigmoid = nn.Sigmoid() 43 | 44 | def forward(self, x): 45 | module_input = x 46 | x = self.avg_pool(x) 47 | x = self.fc1(x) 48 | x = self.relu(x) 49 | x = self.fc2(x) 50 | x = self.sigmoid(x) 51 | return module_input * x 52 | 53 | 54 | class PWCA(nn.Module): 55 | """ 56 | Pointwise Correlation & Channel Attention 57 | """ 58 | 59 | def __init__(self, num_channel, cat=False, CA=True, matrix=False): 60 | super(PWCA, self).__init__() 61 | self.cat = cat 62 | self.CA = CA 63 | self.matrix = matrix 64 | if self.CA: 65 | self.CA_layer = CAModule(channels=num_channel) 66 | 67 | def forward(self, z, x): 68 | z11 = z[0] 69 | x11 = x[0] 70 | # pixel-wise correlation 71 | if self.matrix: 72 | corr = pixel_corr_mat(z11, x11) 73 | else: 74 | corr = pixel_corr(z11, x11) 75 | if self.CA: 76 | # channel attention 77 | opt = self.CA_layer(corr) 78 | if self.cat: 79 | return torch.cat([opt, x11], dim=1) 80 | else: 81 | return opt 82 | else: 83 | return corr 84 | -------------------------------------------------------------------------------- /snot/models/model_builder.py: -------------------------------------------------------------------------------- 1 | # Parts of this code come from https://github.com/STVIR/pysot 2 | from __future__ import absolute_import 3 | from __future__ import division 4 | from __future__ import print_function 5 | from __future__ import unicode_literals 6 | 7 | import torch.nn as nn 8 | 9 | from snot.core.config import cfg 10 | from snot.models.backbone import get_backbone 11 | from snot.models.head import get_rpn_head, get_mask_head, get_refine_head 12 | from snot.models.neck import get_neck 13 | 14 | 15 | class ModelBuilder(nn.Module): 16 | def __init__(self): 17 | super(ModelBuilder, self).__init__() 18 | 19 | # build backbone 20 | self.backbone = get_backbone(cfg.BACKBONE.TYPE, 21 | **cfg.BACKBONE.KWARGS) 22 | 23 | # build adjust layer 24 | if cfg.ADJUST.ADJUST: 25 | self.neck = get_neck(cfg.ADJUST.TYPE, 26 | **cfg.ADJUST.KWARGS) 27 | 28 | # build rpn head 29 | self.rpn_head = get_rpn_head(cfg.RPN.TYPE, 30 | **cfg.RPN.KWARGS) 31 | 32 | # build mask head 33 | if cfg.MASK.MASK: 34 | self.mask_head = get_mask_head(cfg.MASK.TYPE, 35 | **cfg.MASK.KWARGS) 36 | 37 | if cfg.REFINE.REFINE: 38 | self.refine_head = get_refine_head(cfg.REFINE.TYPE) 39 | 40 | def template(self, z): 41 | zf = self.backbone(z) 42 | if cfg.MASK.MASK: 43 | zf = zf[-1] 44 | if cfg.ADJUST.ADJUST: 45 | zf = self.neck(zf) 46 | self.zf = zf 47 | 48 | def track(self, x): 49 | xf = self.backbone(x) 50 | if cfg.MASK.MASK: 51 | self.xf = xf[:-1] 52 | xf = xf[-1] 53 | if cfg.ADJUST.ADJUST: 54 | xf = self.neck(xf) 55 | cls, loc = self.rpn_head(self.zf, xf) 56 | if cfg.MASK.MASK: 57 | mask, self.mask_corr_feature = self.mask_head(self.zf, xf) 58 | return { 59 | 'cls': cls, 60 | 'loc': loc, 61 | 'mask': mask if cfg.MASK.MASK else None 62 | } 63 | 64 | def mask_refine(self, pos): 65 | return self.refine_head(self.xf, self.mask_corr_feature, pos) 66 | -------------------------------------------------------------------------------- /snot/models/neck/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | from snot.models.neck.neck import AdjustLayer, AdjustAllLayer, BAN_AdjustLayer, BAN_AdjustAllLayer 7 | 8 | NECKS = { 9 | 'AdjustLayer': AdjustLayer, 10 | 'AdjustAllLayer': AdjustAllLayer 11 | } 12 | 13 | def get_neck(name, **kwargs): 14 | return NECKS[name](**kwargs) 15 | 16 | BAN_NECKS = { 17 | 'AdjustLayer': BAN_AdjustLayer, 18 | 'AdjustAllLayer': BAN_AdjustAllLayer 19 | } 20 | 21 | def get_ban_neck(name, **kwargs): 22 | return BAN_NECKS[name](**kwargs) 23 | -------------------------------------------------------------------------------- /snot/models/neck/neck.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import torch.nn as nn 7 | 8 | 9 | class AdjustLayer(nn.Module): 10 | def __init__(self, in_channels, out_channels, center_size=7): 11 | super(AdjustLayer, self).__init__() 12 | self.downsample = nn.Sequential( 13 | nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False), 14 | nn.BatchNorm2d(out_channels), 15 | ) 16 | self.center_size = center_size 17 | 18 | def forward(self, x): 19 | x = self.downsample(x) 20 | if x.size(3) < 20: 21 | l = (x.size(3) - self.center_size) // 2 22 | r = l + self.center_size 23 | x = x[:, :, l:r, l:r] 24 | return x 25 | 26 | 27 | class AdjustAllLayer(nn.Module): 28 | def __init__(self, in_channels, out_channels, center_size=7): 29 | super(AdjustAllLayer, self).__init__() 30 | self.num = len(out_channels) 31 | if self.num == 1: 32 | self.downsample = AdjustLayer(in_channels[0], 33 | out_channels[0], 34 | center_size) 35 | else: 36 | for i in range(self.num): 37 | self.add_module('downsample'+str(i+2), 38 | AdjustLayer(in_channels[i], 39 | out_channels[i], 40 | center_size)) 41 | 42 | def forward(self, features): 43 | if self.num == 1: 44 | return self.downsample(features) 45 | else: 46 | out = [] 47 | for i in range(self.num): 48 | adj_layer = getattr(self, 'downsample'+str(i+2)) 49 | out.append(adj_layer(features[i])) 50 | return out 51 | 52 | 53 | class BAN_AdjustLayer(nn.Module): 54 | def __init__(self, in_channels, out_channels): 55 | super(BAN_AdjustLayer, self).__init__() 56 | self.downsample = nn.Sequential( 57 | nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False), 58 | nn.BatchNorm2d(out_channels), 59 | ) 60 | 61 | def forward(self, x): 62 | x = self.downsample(x) 63 | if x.size(3) < 20: 64 | l = 4 65 | r = l + 7 66 | x = x[:, :, l:r, l:r] 67 | return x 68 | 69 | 70 | class BAN_AdjustAllLayer(nn.Module): 71 | def __init__(self, in_channels, out_channels): 72 | super(BAN_AdjustAllLayer, self).__init__() 73 | self.num = len(out_channels) 74 | if self.num == 1: 75 | self.downsample = AdjustLayer(in_channels[0], out_channels[0]) 76 | else: 77 | for i in range(self.num): 78 | self.add_module('downsample'+str(i+2), 79 | AdjustLayer(in_channels[i], out_channels[i])) 80 | 81 | def forward(self, features): 82 | if self.num == 1: 83 | return self.downsample(features) 84 | else: 85 | out = [] 86 | for i in range(self.num): 87 | adj_layer = getattr(self, 'downsample'+str(i+2)) 88 | out.append(adj_layer(features[i])) 89 | return out 90 | -------------------------------------------------------------------------------- /snot/models/ocean/backbones.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | from snot.models.ocean.modules import Bottleneck, ResNet_plus2, Bottleneck_BIG_CI, ResNet 3 | 4 | eps = 1e-5 5 | # --------------------- 6 | # For Ocean and Ocean+ 7 | # --------------------- 8 | class ResNet50(nn.Module): 9 | def __init__(self, used_layers=[2, 3, 4], online=False): 10 | super(ResNet50, self).__init__() 11 | self.features = ResNet_plus2(Bottleneck, [3, 4, 6, 3], used_layers=used_layers, online=online) 12 | 13 | def forward(self, x, online=False): 14 | if not online: 15 | x_stages, x = self.features(x, online=online) 16 | return x_stages, x 17 | else: 18 | x = self.features(x, online=online) 19 | return x 20 | 21 | # --------------------- 22 | # For SiamDW 23 | # --------------------- 24 | class ResNet22W(nn.Module): 25 | """ 26 | ResNet22W: double 3*3 layer (only) channels in residual blob 27 | """ 28 | def __init__(self): 29 | super(ResNet22W, self).__init__() 30 | self.features = ResNet(Bottleneck_BIG_CI, [3, 4], [True, False], [False, True], firstchannels=64, channels=[64, 128]) 31 | self.feature_size = 512 32 | 33 | def forward(self, x): 34 | x = self.features(x) 35 | 36 | return x 37 | -------------------------------------------------------------------------------- /snot/models/ocean_model.py: -------------------------------------------------------------------------------- 1 | # Parts of this code come from https://github.com/researchmm/TracKit 2 | from snot.models.ocean.ocean import Ocean_ 3 | from snot.models.ocean.connect import box_tower, AdjustLayer 4 | from snot.models.ocean.backbones import ResNet50 5 | 6 | 7 | class Ocean(Ocean_): 8 | def __init__(self, align=False, online=False): 9 | super(Ocean, self).__init__() 10 | self.features = ResNet50(used_layers=[3], online=online) # in param 11 | self.neck = AdjustLayer(in_channels=1024, out_channels=256) 12 | self.connect_model = box_tower(inchannels=256, outchannels=256, towernum=4) 13 | self.align_head = None 14 | -------------------------------------------------------------------------------- /snot/models/se/connectors.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | from snot.models.se.sesn.ses_conv import ses_max_projection 6 | 7 | 8 | class ScaleHead(nn.Module): 9 | 10 | def __init__(self, out_scale=0.1, scales=[1], head='corr'): 11 | super().__init__() 12 | self.out_scale = out_scale 13 | self.scales = scales 14 | self.head = head 15 | print('| using scales:', scales) 16 | 17 | if self.head == 'corr': 18 | self.corr_func = self._fast_xcorr 19 | print('| using ordinary correlation') 20 | if self.head == 'greedypw': 21 | self.scalepooling = self.pw_maxpooling 22 | self.corr_func = self._fast_corr_scale 23 | print('| using greedypw correlation') 24 | 25 | def forward(self, z, x): 26 | z = ses_max_projection(z) 27 | x = ses_max_projection(x) 28 | pooled, heatmaps = self.corr_func(z, x) 29 | return pooled * self.out_scale, heatmaps 30 | 31 | def pw_maxpooling(self, x, scale_dim=1): 32 | n_scales = x.shape[scale_dim] 33 | n_c = x.shape[0] 34 | raveled = x.view(n_c, n_scales, -1) 35 | zero_batch_max = raveled.max(dim=-1).values[0] 36 | 37 | pooled = x.max(dim=1, keepdim=True).values 38 | return pooled 39 | 40 | def _fast_corr_scale(self, z, x): 41 | scale = self.scales 42 | outsize_h = x.shape[-2] - z.shape[-2] + 1 43 | outsize_w = x.shape[-1] - z.shape[-1] + 1 44 | 45 | output = torch.zeros(x.shape[0], len(scale), outsize_h, outsize_w, device=x.device) 46 | for i, each_scale in enumerate(scale): 47 | x_rescale = self.rescale4d(x, each_scale) 48 | y_rescale, _ = self._fast_xcorr(z, x_rescale) 49 | output[:, i, ...] = self.rescale4d( 50 | y_rescale, outsize_w / y_rescale.shape[-1]).squeeze(1) 51 | 52 | out = self.scalepooling(output) 53 | return out, output 54 | 55 | def _fast_xcorr(self, z, x): 56 | nz = z.size(0) 57 | nx, c, h, w = x.size() 58 | x = x.view(-1, nz * c, h, w) 59 | out = F.conv2d(x, z, groups=nz) 60 | out = out.view(nx, -1, out.size(-2), out.size(-1)) 61 | output_heatmaps = torch.empty_like(out) 62 | return out, output_heatmaps 63 | 64 | def rescale4d(self, x, scale, mode='bicubic', padding_mode='constant'): 65 | if mode == 'nearest': 66 | align_corners = None 67 | else: 68 | align_corners = True 69 | 70 | if scale == 1: 71 | return x 72 | 73 | return F.interpolate(x, scale_factor=scale, mode=mode, align_corners=align_corners) 74 | -------------------------------------------------------------------------------- /snot/models/se/sesn/ses_basis.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import torch 3 | import torch.nn.functional as F 4 | 5 | 6 | def hermite_poly(X, n): 7 | """Hermite polynomial of order n calculated at X 8 | Args: 9 | n: int >= 0 10 | X: np.array 11 | 12 | Output: 13 | Y: array of shape X.shape 14 | """ 15 | coeff = [0] * n + [1] 16 | func = np.polynomial.hermite_e.hermeval(X, coeff) 17 | return func 18 | 19 | 20 | def onescale_grid_hermite_gaussian(size, scale, max_order=None): 21 | max_order = max_order or size - 1 22 | X = np.linspace(-(size // 2), size // 2, size) 23 | Y = np.linspace(-(size // 2), size // 2, size) 24 | order_y, order_x = np.indices([max_order + 1, max_order + 1]) 25 | 26 | G = np.exp(-X**2 / (2 * scale**2)) / scale 27 | 28 | basis_x = [G * hermite_poly(X / scale, n) for n in order_x.ravel()] 29 | basis_y = [G * hermite_poly(Y / scale, n) for n in order_y.ravel()] 30 | basis_x = torch.Tensor(np.stack(basis_x)) 31 | basis_y = torch.Tensor(np.stack(basis_y)) 32 | basis = torch.bmm(basis_x[:, :, None], basis_y[:, None, :]) 33 | return basis 34 | 35 | 36 | def steerable_A(size, scales, effective_size, **kwargs): 37 | max_order = effective_size - 1 38 | max_scale = max(scales) 39 | basis_tensors = [] 40 | for scale in scales: 41 | size_before_pad = int(size * scale / max_scale) // 2 * 2 + 1 42 | basis = onescale_grid_hermite_gaussian(size_before_pad, scale, max_order) 43 | basis = basis[None, :, :, :] 44 | pad_size = (size - size_before_pad) // 2 45 | basis = F.pad(basis, [pad_size] * 4)[0] 46 | basis_tensors.append(basis) 47 | return torch.stack(basis_tensors, 1) 48 | 49 | 50 | def normalize_basis_by_min_scale(basis): 51 | norm = basis.pow(2).sum([2, 3], keepdim=True).sqrt()[:, [0]] 52 | return basis / norm 53 | -------------------------------------------------------------------------------- /snot/models/se/siam_fc.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | from torch.autograd import Variable 4 | 5 | 6 | class SiamFC(nn.Module): 7 | def __init__(self): 8 | super(SiamFC, self).__init__() 9 | self.features = None 10 | self.connect_model = None 11 | self.zf = None 12 | self.criterion = nn.BCEWithLogitsLoss() 13 | 14 | def template(self, z): 15 | self.zf = self.features(z) 16 | 17 | def _cls_loss(self, pred, label, select): 18 | if len(select.size()) == 0: 19 | return 0 20 | pred = torch.index_select(pred, 0, select) 21 | label = torch.index_select(label, 0, select) 22 | return self.criterion(pred, label) 23 | 24 | def _weighted_BCE(self, pred, label): 25 | pred = pred.view(-1) 26 | label = label.view(-1) 27 | pos = Variable(label.data.eq(1).nonzero().squeeze()).cuda() 28 | neg = Variable(label.data.eq(0).nonzero().squeeze()).cuda() 29 | 30 | loss_pos = self._cls_loss(pred, label, pos) 31 | loss_neg = self._cls_loss(pred, label, neg) 32 | return loss_pos * 0.5 + loss_neg * 0.5 33 | 34 | def track(self, x): 35 | xf = self.features(x) 36 | score, activations = self.connect_model(self.zf, xf) 37 | return score, activations 38 | 39 | def forward(self, template, search, label=None): 40 | zf = self.features(template) 41 | xf = self.features(search) 42 | score, _ = self.connect_model(zf, xf) 43 | if self.training: 44 | return self._weighted_BCE(score, label) 45 | else: 46 | raise ValueError('forward is only used for training.') 47 | -------------------------------------------------------------------------------- /snot/models/sesiam_model.py: -------------------------------------------------------------------------------- 1 | # Parts of this code come from https://github.com/isosnovik/SiamSE 2 | from snot.models.se.siam_fc import SiamFC 3 | from snot.models.se.feature_extractors import SEResNet22FeatureExtractor 4 | from snot.models.se.connectors import ScaleHead 5 | 6 | 7 | class SESiamFCResNet22(SiamFC): 8 | def __init__(self, padding_mode='circular', **kwargs): 9 | super().__init__(**kwargs) 10 | print('| using {} padding'.format(padding_mode)) 11 | 12 | self.features = SEResNet22FeatureExtractor(scales=[0.9 * 1.4**i for i in range(3)], 13 | pool=[False, True], 14 | interscale=[True, False], 15 | kernel_sizes=[9, 5, 5], 16 | padding_mode=padding_mode) 17 | 18 | scales_head = [1 / 1.2, 1.0, 1.2] 19 | self.connect_model = ScaleHead(scales=scales_head, head='corr') 20 | -------------------------------------------------------------------------------- /snot/models/siamapn_model.py: -------------------------------------------------------------------------------- 1 | # Parts of this code come from https://github.com/vision4robotics/SiamAPN 2 | from __future__ import absolute_import 3 | from __future__ import division 4 | from __future__ import print_function 5 | from __future__ import unicode_literals 6 | 7 | import torch.nn as nn 8 | 9 | from snot.core.config_apn import cfg 10 | from snot.models.backbone.alexnet import AlexNet_apn 11 | from snot.models.apn.utile import APN,clsandloc_apn 12 | from snot.models.apn.anchortarget import AnchorTarget3_apn 13 | 14 | 15 | class ModelBuilderAPN(nn.Module): 16 | def __init__(self): 17 | super(ModelBuilderAPN, self).__init__() 18 | 19 | self.backbone = AlexNet_apn().cuda() 20 | self.grader=APN(cfg).cuda() 21 | self.new=clsandloc_apn(cfg).cuda() 22 | self.fin2=AnchorTarget3_apn() 23 | 24 | def template(self, z): 25 | 26 | zf1,zf = self.backbone(z) 27 | self.zf=zf 28 | self.zf1=zf1 29 | 30 | def track(self, x): 31 | 32 | xf1,xf = self.backbone(x) 33 | xff,ress=self.grader(xf1,self.zf1) 34 | 35 | self.ranchors=xff 36 | 37 | cls1,cls2,cls3,loc =self.new(xf,self.zf,ress) 38 | 39 | return { 40 | 'cls1': cls1, 41 | 'cls2': cls2, 42 | 'cls3': cls3, 43 | 'loc': loc 44 | } 45 | -------------------------------------------------------------------------------- /snot/models/siamban_model.py: -------------------------------------------------------------------------------- 1 | # Parts of this code come from https://github.com/hqucv/siamban 2 | from __future__ import absolute_import 3 | from __future__ import division 4 | from __future__ import print_function 5 | from __future__ import unicode_literals 6 | 7 | import torch.nn as nn 8 | 9 | from snot.core.config_ban import cfg 10 | from snot.models.backbone import get_backbone 11 | from snot.models.head import get_ban_head 12 | from snot.models.neck import get_ban_neck 13 | 14 | 15 | class ModelBuilderBAN(nn.Module): 16 | def __init__(self): 17 | super(ModelBuilderBAN, self).__init__() 18 | 19 | # build backbone 20 | self.backbone = get_backbone(cfg.BACKBONE.TYPE, 21 | **cfg.BACKBONE.KWARGS) 22 | 23 | # build adjust layer 24 | if cfg.ADJUST.ADJUST: 25 | self.neck = get_ban_neck(cfg.ADJUST.TYPE, 26 | **cfg.ADJUST.KWARGS) 27 | 28 | # build ban head 29 | if cfg.BAN.BAN: 30 | self.head = get_ban_head(cfg.BAN.TYPE, 31 | **cfg.BAN.KWARGS) 32 | 33 | def template(self, z): 34 | zf = self.backbone(z) 35 | if cfg.ADJUST.ADJUST: 36 | zf = self.neck(zf) 37 | self.zf = zf 38 | 39 | def track(self, x): 40 | xf = self.backbone(x) 41 | if cfg.ADJUST.ADJUST: 42 | xf = self.neck(xf) 43 | cls, loc = self.head(self.zf, xf) 44 | return { 45 | 'cls': cls, 46 | 'loc': loc 47 | } 48 | -------------------------------------------------------------------------------- /snot/models/siamcar_model.py: -------------------------------------------------------------------------------- 1 | # Parts of this code come from https://github.com/ohhhyeahhh/SiamCAR 2 | from __future__ import absolute_import 3 | from __future__ import division 4 | from __future__ import print_function 5 | from __future__ import unicode_literals 6 | 7 | import torch 8 | import torch.nn as nn 9 | 10 | from snot.core.config_car import cfg 11 | from snot.models.backbone import get_backbone 12 | from snot.models.head.car import CAR 13 | from snot.models.neck import get_neck 14 | from snot.core.xcorr import xcorr_depthwise 15 | 16 | class ModelBuilderCAR(nn.Module): 17 | def __init__(self): 18 | super(ModelBuilderCAR, self).__init__() 19 | 20 | # build backbone 21 | self.backbone = get_backbone(cfg.BACKBONE.TYPE, 22 | **cfg.BACKBONE.KWARGS) 23 | 24 | # build adjust layer 25 | if cfg.ADJUST.ADJUST: 26 | self.neck = get_neck(cfg.ADJUST.TYPE, 27 | **cfg.ADJUST.KWARGS) 28 | 29 | # build car head 30 | self.car_head = CAR(cfg, 256) 31 | 32 | # build response map 33 | self.xcorr_depthwise = xcorr_depthwise 34 | 35 | self.down = nn.ConvTranspose2d(256 * 3, 256, 1, 1) 36 | 37 | def template(self, z): 38 | zf = self.backbone(z) 39 | if cfg.ADJUST.ADJUST: 40 | zf = self.neck(zf) 41 | self.zf = zf 42 | 43 | def track(self, x): 44 | xf = self.backbone(x) 45 | if cfg.ADJUST.ADJUST: 46 | xf = self.neck(xf) 47 | 48 | features = self.xcorr_depthwise(xf[0],self.zf[0]) 49 | for i in range(len(xf)-1): 50 | features_new = self.xcorr_depthwise(xf[i+1],self.zf[i+1]) 51 | features = torch.cat([features,features_new],1) 52 | features = self.down(features) 53 | 54 | cls, loc, cen = self.car_head(features) 55 | return { 56 | 'cls': cls, 57 | 'loc': loc, 58 | 'cen': cen 59 | } 60 | -------------------------------------------------------------------------------- /snot/models/siamdw_model.py: -------------------------------------------------------------------------------- 1 | # Parts of this code come from https://github.com/researchmm/SiamDW and https://github.com/researchmm/TracKit 2 | from __future__ import absolute_import 3 | from __future__ import division 4 | from __future__ import print_function 5 | from __future__ import unicode_literals 6 | 7 | from snot.models.dw.siamfc import SiamFC_ 8 | from snot.models.dw.siamrpn import SiamRPN_ 9 | from snot.models.dw.connect import Corr_Up, RPN_Up 10 | from snot.models.dw.backbones import ResNet22, Incep22, ResNeXt22, ResNet22W 11 | 12 | 13 | class SiamFCRes22(SiamFC_): 14 | def __init__(self, **kwargs): 15 | super(SiamFCRes22, self).__init__(**kwargs) 16 | self.features = ResNet22() 17 | self.connect_model = Corr_Up() 18 | 19 | 20 | class SiamFCIncep22(SiamFC_): 21 | def __init__(self, **kwargs): 22 | super(SiamFCIncep22, self).__init__(**kwargs) 23 | self.features = Incep22() 24 | self.connect_model = Corr_Up() 25 | 26 | 27 | class SiamFCNext22(SiamFC_): 28 | def __init__(self, **kwargs): 29 | super(SiamFCNext22, self).__init__(**kwargs) 30 | self.features = ResNeXt22() 31 | self.connect_model = Corr_Up() 32 | 33 | 34 | class SiamFCRes22W(SiamFC_): 35 | def __init__(self, **kwargs): 36 | super(SiamFCRes22W, self).__init__(**kwargs) 37 | self.features = ResNet22W() 38 | self.connect_model = Corr_Up() 39 | 40 | 41 | class SiamRPNRes22(SiamRPN_): 42 | def __init__(self, **kwargs): 43 | super(SiamRPNRes22, self).__init__(**kwargs) 44 | self.features = ResNet22() 45 | inchannels = self.features.feature_size 46 | 47 | if self.cls_type == 'thinner': outchannels = 256 48 | elif self.cls_type == 'thicker': outchannels = 512 49 | else: raise ValueError('not implemented loss/cls type') 50 | 51 | self.connect_model = RPN_Up(anchor_nums=self.anchor_nums, 52 | inchannels=inchannels, 53 | outchannels=outchannels, 54 | cls_type = self.cls_type) 55 | -------------------------------------------------------------------------------- /snot/models/siamgat_model.py: -------------------------------------------------------------------------------- 1 | # Parts of this code come from https://github.com/ohhhyeahhh/SiamGAT 2 | from __future__ import absolute_import 3 | from __future__ import division 4 | from __future__ import print_function 5 | from __future__ import unicode_literals 6 | 7 | import torch 8 | import torch.nn as nn 9 | import torch.nn.functional as F 10 | 11 | from snot.core.config_gat import cfg 12 | from snot.models.backbone import get_backbone 13 | from snot.models.head.car import CAR 14 | 15 | 16 | class Graph_Attention_Union(nn.Module): 17 | def __init__(self, in_channel, out_channel): 18 | super(Graph_Attention_Union, self).__init__() 19 | 20 | # search region nodes linear transformation 21 | self.support = nn.Conv2d(in_channel, in_channel, 1, 1) 22 | 23 | # target template nodes linear transformation 24 | self.query = nn.Conv2d(in_channel, in_channel, 1, 1) 25 | 26 | # linear transformation for message passing 27 | self.g = nn.Sequential( 28 | nn.Conv2d(in_channel, in_channel, 1, 1), 29 | nn.BatchNorm2d(in_channel), 30 | nn.ReLU(inplace=True), 31 | ) 32 | 33 | # aggregated feature 34 | self.fi = nn.Sequential( 35 | nn.Conv2d(in_channel*2, out_channel, 1, 1), 36 | nn.BatchNorm2d(out_channel), 37 | nn.ReLU(inplace=True), 38 | ) 39 | 40 | def forward(self, zf, xf): 41 | # linear transformation 42 | xf_trans = self.query(xf) 43 | zf_trans = self.support(zf) 44 | 45 | # linear transformation for message passing 46 | xf_g = self.g(xf) 47 | zf_g = self.g(zf) 48 | 49 | # calculate similarity 50 | shape_x = xf_trans.shape 51 | shape_z = zf_trans.shape 52 | 53 | zf_trans_plain = zf_trans.view(-1, shape_z[1], shape_z[2] * shape_z[3]) 54 | zf_g_plain = zf_g.view(-1, shape_z[1], shape_z[2] * shape_z[3]).permute(0, 2, 1) 55 | xf_trans_plain = xf_trans.view(-1, shape_x[1], shape_x[2] * shape_x[3]).permute(0, 2, 1) 56 | 57 | similar = torch.matmul(xf_trans_plain, zf_trans_plain) 58 | similar = F.softmax(similar, dim=2) 59 | 60 | embedding = torch.matmul(similar, zf_g_plain).permute(0, 2, 1) 61 | embedding = embedding.view(-1, shape_x[1], shape_x[2], shape_x[3]) 62 | 63 | # aggregated feature 64 | output = torch.cat([embedding, xf_g], 1) 65 | output = self.fi(output) 66 | return output 67 | 68 | 69 | class ModelBuilderGAT(nn.Module): 70 | def __init__(self): 71 | super(ModelBuilderGAT, self).__init__() 72 | 73 | # build backbone 74 | self.backbone = get_backbone(cfg.BACKBONE.TYPE, 75 | **cfg.BACKBONE.KWARGS) 76 | 77 | # build car head 78 | self.car_head = CAR(cfg, 256) 79 | 80 | # build response map 81 | self.attention = Graph_Attention_Union(256, 256) 82 | 83 | def template(self, z, roi): 84 | zf = self.backbone(z, roi) 85 | self.zf = zf 86 | 87 | def track(self, x): 88 | xf = self.backbone(x) 89 | 90 | features = self.attention(self.zf, xf) 91 | 92 | cls, loc, cen = self.car_head(features) 93 | return { 94 | 'cls': cls, 95 | 'loc': loc, 96 | 'cen': cen 97 | } 98 | -------------------------------------------------------------------------------- /snot/models/updatenet_siam_model.py: -------------------------------------------------------------------------------- 1 | # Parts of this code come from https://github.com/zhanglichao/updatenet 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | 6 | class SiamRPNBIG(nn.Module): 7 | def __init__(self, feat_in=512, feature_out=512, anchor=5): 8 | super(SiamRPNBIG, self).__init__() 9 | self.anchor = anchor 10 | self.feature_out = feature_out 11 | self.featureExtract = nn.Sequential( 12 | nn.Conv2d(3, 192, 11, stride=2), 13 | nn.BatchNorm2d(192), 14 | nn.ReLU(inplace=True), 15 | nn.MaxPool2d(3, stride=2), 16 | nn.Conv2d(192, 512, 5), 17 | nn.BatchNorm2d(512), 18 | nn.ReLU(inplace=True), 19 | nn.MaxPool2d(3, stride=2), 20 | nn.Conv2d(512, 768, 3), 21 | nn.BatchNorm2d(768), 22 | nn.ReLU(inplace=True), 23 | nn.Conv2d(768, 768, 3), 24 | nn.BatchNorm2d(768), 25 | nn.ReLU(inplace=True), 26 | nn.Conv2d(768, 512, 3), 27 | nn.BatchNorm2d(512), 28 | ) 29 | self.conv_r1 = nn.Conv2d(feat_in, feature_out*4*anchor, 3) 30 | self.conv_r2 = nn.Conv2d(feat_in, feature_out, 3) 31 | self.conv_cls1 = nn.Conv2d(feat_in, feature_out*2*anchor, 3) 32 | self.conv_cls2 = nn.Conv2d(feat_in, feature_out, 3) 33 | self.regress_adjust = nn.Conv2d(4*anchor, 4*anchor, 1) 34 | 35 | self.r1_kernel = [] 36 | self.cls1_kernel = [] 37 | 38 | def forward(self, x): 39 | x_f = self.featureExtract(x) 40 | return self.regress_adjust(F.conv2d(self.conv_r2(x_f), self.r1_kernel)), \ 41 | F.conv2d(self.conv_cls2(x_f), self.cls1_kernel) 42 | 43 | def featextract(self, x): 44 | x_f = self.featureExtract(x) 45 | return x_f 46 | 47 | def kernel(self, z_f): 48 | r1_kernel_raw = self.conv_r1(z_f) 49 | cls1_kernel_raw = self.conv_cls1(z_f) 50 | kernel_size = r1_kernel_raw.data.size()[-1] 51 | self.r1_kernel = r1_kernel_raw.view(self.anchor*4, self.feature_out, kernel_size, kernel_size) 52 | self.cls1_kernel = cls1_kernel_raw.view(self.anchor*2, self.feature_out, kernel_size, kernel_size) 53 | 54 | def temple(self, z): 55 | z_f = self.featureExtract(z) 56 | r1_kernel_raw = self.conv_r1(z_f) 57 | cls1_kernel_raw = self.conv_cls1(z_f) 58 | kernel_size = r1_kernel_raw.data.size()[-1] 59 | self.r1_kernel = r1_kernel_raw.view(self.anchor*4, self.feature_out, kernel_size, kernel_size) 60 | self.cls1_kernel = cls1_kernel_raw.view(self.anchor*2, self.feature_out, kernel_size, kernel_size) 61 | -------------------------------------------------------------------------------- /snot/models/updatenet_upd_model.py: -------------------------------------------------------------------------------- 1 | # Parts of this code come from https://github.com/zhanglichao/updatenet 2 | import torch.nn as nn 3 | 4 | class UpdateResNet256(nn.Module): 5 | def __init__(self, config=None): 6 | super(UpdateResNet256, self).__init__() 7 | self.update = nn.Sequential( 8 | nn.Conv2d(768, 96, 1), 9 | nn.ReLU(inplace=True), 10 | nn.Conv2d(96, 256, 1), 11 | ) 12 | def forward(self, x, x0): 13 | #t = torch.cat((x, y, z), 0) 14 | # x0 is residual 15 | response = self.update(x) 16 | response += x0 17 | return response 18 | 19 | 20 | if __name__ == '__main__': 21 | 22 | # network test 23 | net = UpdateResNet256() 24 | net.eval() 25 | 26 | class UpdateResNet(nn.Module): 27 | def __init__(self, config=None): 28 | super(UpdateResNet, self).__init__() 29 | self.update = nn.Sequential( 30 | nn.Conv2d(1536, 192, 1), 31 | nn.ReLU(inplace=True), 32 | nn.Conv2d(192, 512, 1), 33 | ) 34 | def forward(self, x, x0): 35 | #t = torch.cat((x, y, z), 0) 36 | # x0 is residual 37 | response = self.update(x) 38 | response += x0 39 | return response 40 | 41 | 42 | if __name__ == '__main__': 43 | 44 | # network test 45 | net = UpdateResNet() 46 | net.eval() 47 | 48 | 49 | class UpdateNet(nn.Module): 50 | def __init__(self, config=None): 51 | super(UpdateNet, self).__init__() 52 | self.update = nn.Sequential( 53 | nn.Conv2d(768, 96, 1), 54 | nn.ReLU(inplace=True), 55 | nn.Conv2d(96, 256, 1), 56 | #nn.LocalResponseNorm(size=5, alpha=0.0001, beta=0.75, k=1), 57 | ) 58 | def forward(self, x): 59 | #t = torch.cat((x, y, z), 0) 60 | response = self.update(x) 61 | return response 62 | 63 | 64 | if __name__ == '__main__': 65 | 66 | # network test 67 | net = UpdateNet() 68 | net.eval() 69 | -------------------------------------------------------------------------------- /snot/trackers/tracker_builder.py: -------------------------------------------------------------------------------- 1 | # Parts of this code come from https://github.com/STVIR/pysot 2 | from __future__ import absolute_import 3 | from __future__ import division 4 | from __future__ import print_function 5 | from __future__ import unicode_literals 6 | 7 | from snot.core.config import cfg 8 | from snot.trackers.siamrpn_tracker import SiamRPNTracker 9 | from snot.trackers.siammask_tracker import SiamMaskTracker 10 | from snot.trackers.siamrpnlt_tracker import SiamRPNLTTracker 11 | 12 | TRACKS = { 13 | 'SiamRPNTracker': SiamRPNTracker, 14 | 'SiamMaskTracker': SiamMaskTracker, 15 | 'SiamRPNLTTracker': SiamRPNLTTracker 16 | } 17 | 18 | 19 | def build_tracker(model): 20 | return TRACKS[cfg.TRACK.TYPE](model) 21 | -------------------------------------------------------------------------------- /snot/trackers/tracker_builder_ban.py: -------------------------------------------------------------------------------- 1 | # Parts of this code come from https://github.com/hqucv/siamban 2 | from __future__ import absolute_import 3 | from __future__ import division 4 | from __future__ import print_function 5 | from __future__ import unicode_literals 6 | 7 | from snot.core.config_ban import cfg 8 | from snot.trackers.siamban_tracker import SiamBANTracker 9 | 10 | TRACKS = { 11 | 'SiamBANTracker': SiamBANTracker 12 | } 13 | 14 | 15 | def build_tracker_ban(model): 16 | return TRACKS[cfg.TRACK.TYPE](model) 17 | -------------------------------------------------------------------------------- /snot/utils/anchor.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import math 7 | 8 | import numpy as np 9 | 10 | from snot.utils.bbox import corner2center, center2corner 11 | 12 | 13 | class Anchors: 14 | """ 15 | This class generate anchors. 16 | """ 17 | def __init__(self, stride, ratios, scales, image_center=0, size=0): 18 | self.stride = stride 19 | self.ratios = ratios 20 | self.scales = scales 21 | self.image_center = image_center 22 | self.size = size 23 | 24 | self.anchor_num = len(self.scales) * len(self.ratios) 25 | 26 | self.anchors = None 27 | 28 | self.generate_anchors() 29 | 30 | def generate_anchors(self): 31 | """ 32 | generate anchors based on predefined configuration 33 | """ 34 | self.anchors = np.zeros((self.anchor_num, 4), dtype=np.float32) 35 | size = self.stride * self.stride 36 | count = 0 37 | for r in self.ratios: 38 | ws = int(math.sqrt(size*1. / r)) 39 | hs = int(ws * r) 40 | 41 | for s in self.scales: 42 | w = ws * s 43 | h = hs * s 44 | self.anchors[count][:] = [-w*0.5, -h*0.5, w*0.5, h*0.5][:] 45 | count += 1 46 | 47 | def generate_all_anchors(self, im_c, size): 48 | """ 49 | im_c: image center 50 | size: image size 51 | """ 52 | if self.image_center == im_c and self.size == size: 53 | return False 54 | self.image_center = im_c 55 | self.size = size 56 | 57 | a0x = im_c - size // 2 * self.stride 58 | ori = np.array([a0x] * 4, dtype=np.float32) 59 | zero_anchors = self.anchors + ori 60 | 61 | x1 = zero_anchors[:, 0] 62 | y1 = zero_anchors[:, 1] 63 | x2 = zero_anchors[:, 2] 64 | y2 = zero_anchors[:, 3] 65 | 66 | x1, y1, x2, y2 = map(lambda x: x.reshape(self.anchor_num, 1, 1), 67 | [x1, y1, x2, y2]) 68 | cx, cy, w, h = corner2center([x1, y1, x2, y2]) 69 | 70 | disp_x = np.arange(0, size).reshape(1, 1, -1) * self.stride 71 | disp_y = np.arange(0, size).reshape(1, -1, 1) * self.stride 72 | 73 | cx = cx + disp_x 74 | cy = cy + disp_y 75 | 76 | # broadcast 77 | zero = np.zeros((self.anchor_num, size, size), dtype=np.float32) 78 | cx, cy, w, h = map(lambda x: x + zero, [cx, cy, w, h]) 79 | x1, y1, x2, y2 = center2corner([cx, cy, w, h]) 80 | 81 | self.all_anchors = (np.stack([x1, y1, x2, y2]).astype(np.float32), 82 | np.stack([cx, cy, w, h]).astype(np.float32)) 83 | return True 84 | -------------------------------------------------------------------------------- /snot/utils/evaluation/__init__.py: -------------------------------------------------------------------------------- 1 | from .ope_benchmark import OPEBenchmark 2 | -------------------------------------------------------------------------------- /snot/utils/misc.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import os 7 | 8 | from colorama import Fore, Style 9 | 10 | __all__ = ['commit', 'describe'] 11 | 12 | 13 | def _exec(cmd): 14 | f = os.popen(cmd, 'r', 1) 15 | return f.read().strip() 16 | 17 | 18 | def _bold(s): 19 | return "\033[1m%s\033[0m" % s 20 | 21 | 22 | def _color(s): 23 | # return f'{Fore.RED}{s}{Style.RESET_ALL}' 24 | return "{}{}{}".format(Fore.RED,s,Style.RESET_ALL) 25 | 26 | 27 | def _describe(model, lines=None, spaces=0): 28 | head = " " * spaces 29 | for name, p in model.named_parameters(): 30 | if '.' in name: 31 | continue 32 | if p.requires_grad: 33 | name = _color(name) 34 | line = "{head}- {name}".format(head=head, name=name) 35 | lines.append(line) 36 | 37 | for name, m in model.named_children(): 38 | space_num = len(name) + spaces + 1 39 | if m.training: 40 | name = _color(name) 41 | line = "{head}.{name} ({type})".format( 42 | head=head, 43 | name=name, 44 | type=m.__class__.__name__) 45 | lines.append(line) 46 | _describe(m, lines, space_num) 47 | 48 | 49 | def commit(): 50 | root = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../')) 51 | cmd = "cd {}; git log | head -n1 | awk '{{print $2}}'".format(root) 52 | commit = _exec(cmd) 53 | cmd = "cd {}; git log --oneline | head -n1".format(root) 54 | commit_log = _exec(cmd) 55 | return "commit : {}\n log : {}".format(commit, commit_log) 56 | 57 | 58 | def describe(net, name=None): 59 | num = 0 60 | lines = [] 61 | if name is not None: 62 | lines.append(name) 63 | num = len(name) 64 | _describe(net, lines, num) 65 | return "\n".join(lines) 66 | 67 | 68 | def bbox_clip(x, min_value, max_value): 69 | new_x = max(min_value, min(x, max_value)) 70 | return new_x 71 | -------------------------------------------------------------------------------- /snot/utils/model_load.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import division 3 | from __future__ import print_function 4 | from __future__ import unicode_literals 5 | 6 | import logging 7 | 8 | import torch 9 | 10 | 11 | logger = logging.getLogger('global') 12 | 13 | 14 | def check_keys(model, pretrained_state_dict): 15 | ckpt_keys = set(pretrained_state_dict.keys()) 16 | model_keys = set(model.state_dict().keys()) 17 | used_pretrained_keys = model_keys & ckpt_keys 18 | unused_pretrained_keys = ckpt_keys - model_keys 19 | missing_keys = model_keys - ckpt_keys 20 | # filter 'num_batches_tracked' 21 | missing_keys = [x for x in missing_keys 22 | if not x.endswith('num_batches_tracked')] 23 | if len(missing_keys) > 0: 24 | logger.info('[Warning] missing keys: {}'.format(missing_keys)) 25 | logger.info('missing keys:{}'.format(len(missing_keys))) 26 | if len(unused_pretrained_keys) > 0: 27 | logger.info('[Warning] unused_pretrained_keys: {}'.format( 28 | unused_pretrained_keys)) 29 | logger.info('unused checkpoint keys:{}'.format( 30 | len(unused_pretrained_keys))) 31 | logger.info('used keys:{}'.format(len(used_pretrained_keys))) 32 | assert len(used_pretrained_keys) > 0, \ 33 | 'load NONE from pretrained checkpoint' 34 | return True 35 | 36 | 37 | def remove_prefix(state_dict, prefix): 38 | ''' Old style model is stored with all names of parameters 39 | share common prefix 'module.' ''' 40 | logger.info('remove prefix \'{}\''.format(prefix)) 41 | f = lambda x: x.split(prefix, 1)[-1] if x.startswith(prefix) else x 42 | return {f(key): value for key, value in state_dict.items()} 43 | 44 | 45 | def load_pretrain(model, pretrained_path): 46 | logger.info('load pretrained model from {}'.format(pretrained_path)) 47 | device = torch.cuda.current_device() 48 | pretrained_dict = torch.load(pretrained_path, 49 | map_location=lambda storage, loc: storage.cuda(device)) 50 | if "state_dict" in pretrained_dict.keys(): 51 | pretrained_dict = remove_prefix(pretrained_dict['state_dict'], 52 | 'module.') 53 | else: 54 | pretrained_dict = remove_prefix(pretrained_dict, 'module.') 55 | 56 | try: 57 | check_keys(model, pretrained_dict) 58 | except: 59 | logger.info('[Warning]: using pretrain as features.\ 60 | Adding "features." as prefix') 61 | new_dict = {} 62 | for k, v in pretrained_dict.items(): 63 | k = 'features.' + k 64 | new_dict[k] = v 65 | pretrained_dict = new_dict 66 | check_keys(model, pretrained_dict) 67 | model.load_state_dict(pretrained_dict, strict=False) 68 | return model 69 | 70 | 71 | def restore_from(model, optimizer, ckpt_path): 72 | device = torch.cuda.current_device() 73 | ckpt = torch.load(ckpt_path, 74 | map_location=lambda storage, loc: storage.cuda(device)) 75 | epoch = ckpt['epoch'] 76 | 77 | ckpt_model_dict = remove_prefix(ckpt['state_dict'], 'module.') 78 | check_keys(model, ckpt_model_dict) 79 | model.load_state_dict(ckpt_model_dict, strict=False) 80 | 81 | check_keys(optimizer, ckpt['optimizer']) 82 | optimizer.load_state_dict(ckpt['optimizer']) 83 | return model, optimizer, epoch 84 | -------------------------------------------------------------------------------- /snot/utils/statistics.py: -------------------------------------------------------------------------------- 1 | """ 2 | @author fangyi.zhang@vipl.ict.ac.cn 3 | """ 4 | import numpy as np 5 | 6 | def overlap_ratio(rect1, rect2): 7 | '''Compute overlap ratio between two rects 8 | Args 9 | rect:2d array of N x [x,y,w,h] 10 | Return: 11 | iou 12 | ''' 13 | # if rect1.ndim==1: 14 | # rect1 = rect1[np.newaxis, :] 15 | # if rect2.ndim==1: 16 | # rect2 = rect2[np.newaxis, :] 17 | left = np.maximum(rect1[:,0], rect2[:,0]) 18 | right = np.minimum(rect1[:,0]+rect1[:,2], rect2[:,0]+rect2[:,2]) 19 | top = np.maximum(rect1[:,1], rect2[:,1]) 20 | bottom = np.minimum(rect1[:,1]+rect1[:,3], rect2[:,1]+rect2[:,3]) 21 | 22 | intersect = np.maximum(0,right - left) * np.maximum(0,bottom - top) 23 | union = rect1[:,2]*rect1[:,3] + rect2[:,2]*rect2[:,3] - intersect 24 | iou = intersect / union 25 | iou = np.maximum(np.minimum(1, iou), 0) 26 | return iou 27 | 28 | def success_overlap(gt_bb, result_bb, n_frame): 29 | thresholds_overlap = np.arange(0, 1.05, 0.05) 30 | success = np.zeros(len(thresholds_overlap)) 31 | iou = np.ones(len(gt_bb)) * (-1) 32 | # mask = np.sum(gt_bb > 0, axis=1) == 4 #TODO check all dataset 33 | mask = np.sum(gt_bb[:, 2:] > 0, axis=1) == 2 34 | iou[mask] = overlap_ratio(gt_bb[mask], result_bb[mask]) 35 | for i in range(len(thresholds_overlap)): 36 | success[i] = np.sum(iou > thresholds_overlap[i]) / float(n_frame) 37 | return success 38 | 39 | def success_error(gt_center, result_center, thresholds, n_frame): 40 | # n_frame = len(gt_center) 41 | success = np.zeros(len(thresholds)) 42 | dist = np.ones(len(gt_center)) * (-1) 43 | mask = np.sum(gt_center > 0, axis=1) == 2 44 | dist[mask] = np.sqrt(np.sum( 45 | np.power(gt_center[mask] - result_center[mask], 2), axis=1)) 46 | for i in range(len(thresholds)): 47 | success[i] = np.sum(dist <= thresholds[i]) / float(n_frame) 48 | return success 49 | 50 | 51 | -------------------------------------------------------------------------------- /snot/utils/utils_ad.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import torch 3 | import numpy as np 4 | 5 | 6 | def to_numpy(tensor): 7 | if torch.is_tensor(tensor): 8 | return tensor.cpu().numpy() 9 | elif type(tensor).__module__ != 'numpy': 10 | raise ValueError("Cannot convert {} to numpy array" 11 | .format(type(tensor))) 12 | return tensor 13 | 14 | 15 | def to_torch(ndarray): 16 | if type(ndarray).__module__ == 'numpy': 17 | return torch.from_numpy(ndarray) 18 | elif not torch.is_tensor(ndarray): 19 | raise ValueError("Cannot convert {} to torch tensor" 20 | .format(type(ndarray))) 21 | return ndarray 22 | 23 | 24 | def im_to_numpy(img): 25 | img = to_numpy(img) 26 | img = np.transpose(img, (1, 2, 0)) # H*W*C 27 | return img 28 | 29 | 30 | def im_to_torch(img): 31 | img = np.transpose(img, (2, 0, 1)) # C*H*W 32 | img = to_torch(img).float() 33 | return img 34 | 35 | 36 | def torch_to_img(img): 37 | img = to_numpy(torch.squeeze(img, 0)) 38 | img = np.transpose(img, (1, 2, 0)) # H*W*C 39 | return img 40 | 41 | 42 | def get_subwindow_tracking(im, pos, model_sz, original_sz, avg_chans, out_mode='torch', new=False): 43 | 44 | if isinstance(pos, float): 45 | pos = [pos, pos] 46 | sz = original_sz 47 | im_sz = im.shape 48 | c = (original_sz+1) / 2 49 | context_xmin = round(pos[0] - c) # floor(pos(2) - sz(2) / 2); 50 | context_xmax = context_xmin + sz - 1 51 | context_ymin = round(pos[1] - c) # floor(pos(1) - sz(1) / 2); 52 | context_ymax = context_ymin + sz - 1 53 | left_pad = int(max(0., -context_xmin)) 54 | top_pad = int(max(0., -context_ymin)) 55 | right_pad = int(max(0., context_xmax - im_sz[1] + 1)) 56 | bottom_pad = int(max(0., context_ymax - im_sz[0] + 1)) 57 | 58 | context_xmin = context_xmin + left_pad 59 | context_xmax = context_xmax + left_pad 60 | context_ymin = context_ymin + top_pad 61 | context_ymax = context_ymax + top_pad 62 | 63 | # zzp: a more easy speed version 64 | r, c, k = im.shape 65 | if any([top_pad, bottom_pad, left_pad, right_pad]): 66 | te_im = np.zeros((r + top_pad + bottom_pad, c + left_pad + right_pad, k), np.uint8) # 0 is better than 1 initialization 67 | te_im[top_pad:top_pad + r, left_pad:left_pad + c, :] = im 68 | if top_pad: 69 | te_im[0:top_pad, left_pad:left_pad + c, :] = avg_chans 70 | if bottom_pad: 71 | te_im[r + top_pad:, left_pad:left_pad + c, :] = avg_chans 72 | if left_pad: 73 | te_im[:, 0:left_pad, :] = avg_chans 74 | if right_pad: 75 | te_im[:, c + left_pad:, :] = avg_chans 76 | im_patch_original = te_im[int(context_ymin):int(context_ymax + 1), int(context_xmin):int(context_xmax + 1), :] 77 | else: 78 | im_patch_original = im[int(context_ymin):int(context_ymax + 1), int(context_xmin):int(context_xmax + 1), :] 79 | 80 | if not np.array_equal(model_sz, original_sz): 81 | im_patch = cv2.resize(im_patch_original, (model_sz, model_sz)) # zzp: use cv to get a better speed 82 | else: 83 | im_patch = im_patch_original 84 | 85 | return im_to_torch(im_patch) if out_mode in 'torch' else im_patch 86 | -------------------------------------------------------------------------------- /snot/utils/utils_fcpp/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | from .image import load_image 3 | from .misc import Registry, Timer, load_cfg, md5sum, merge_cfg_into_hps 4 | from .path import complete_path_wt_root_in_cfg, ensure_dir 5 | from .torch_module import (average_gradients, convert_numpy_to_tensor, 6 | convert_tensor_to_numpy, move_data_to_device, 7 | unwrap_model) 8 | 9 | __all__ = [ 10 | load_image, Registry, Timer, load_cfg, md5sum, merge_cfg_into_hps, 11 | complete_path_wt_root_in_cfg, ensure_dir, average_gradients, 12 | convert_numpy_to_tensor, convert_tensor_to_numpy, move_data_to_device, 13 | unwrap_model 14 | ] 15 | -------------------------------------------------------------------------------- /snot/utils/utils_fcpp/image.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import glob 3 | import os 4 | import os.path as osp 5 | 6 | import cv2 7 | import numpy as np 8 | from loguru import logger 9 | from PIL import Image 10 | 11 | _RETRY_NUM = 10 12 | 13 | 14 | def load_image(img_file: str) -> np.array: 15 | """Image loader used by data module (e.g. image sampler) 16 | 17 | Parameters 18 | ---------- 19 | img_file: str 20 | path to image file 21 | Returns 22 | ------- 23 | np.array 24 | loaded image 25 | 26 | Raises 27 | ------ 28 | FileExistsError 29 | invalid image file 30 | RuntimeError 31 | unloadable image file 32 | """ 33 | if not osp.isfile(img_file): 34 | logger.info("Image file %s does not exist." % img_file) 35 | # read with OpenCV 36 | img = cv2.imread(img_file, cv2.IMREAD_COLOR) 37 | if img is None: 38 | # retrying 39 | for ith in range(_RETRY_NUM): 40 | logger.info("cv2 retrying (counter: %d) to load image file: %s" % 41 | (ith + 1, img_file)) 42 | img = cv2.imread(img_file, cv2.IMREAD_COLOR) 43 | if img is not None: 44 | break 45 | # read with PIL 46 | if img is None: 47 | logger.info("PIL used in loading image file: %s" % img_file) 48 | img = Image.open(img_file) 49 | img = np.array(img) 50 | img = img[:, :, [2, 1, 0]] # RGB -> BGR 51 | if img is None: 52 | logger.info("Fail to load Image file %s" % img_file) 53 | 54 | return img 55 | 56 | 57 | class ImageFileVideoStream: 58 | r"""Adaptor class to be compatible with VideoStream object 59 | Accept seperate video frames 60 | """ 61 | def __init__(self, video_dir, init_counter=0): 62 | self._state = dict() 63 | self._state["video_dir"] = video_dir 64 | self._state["frame_files"] = sorted(glob.glob(video_dir)) 65 | self._state["video_length"] = len(self._state["frame_files"]) 66 | self._state["counter"] = init_counter # 0 67 | 68 | def isOpened(self, ): 69 | return (self._state["counter"] < self._state["video_length"]) 70 | 71 | def read(self, ): 72 | frame_idx = self._state["counter"] 73 | frame_file = self._state["frame_files"][frame_idx] 74 | frame_img = load_image(frame_file) 75 | self._state["counter"] += 1 76 | return frame_idx, frame_img 77 | 78 | def release(self, ): 79 | self._state["counter"] = 0 80 | 81 | 82 | class ImageFileVideoWriter: 83 | r"""Adaptor class to be compatible with VideoWriter object 84 | Accept seperate video frames 85 | """ 86 | def __init__(self, video_dir): 87 | self._state = dict() 88 | self._state["video_dir"] = video_dir 89 | self._state["counter"] = 0 90 | logger.info("Frame results will be dumped at: {}".format(video_dir)) 91 | 92 | def write(self, im): 93 | frame_idx = self._state["counter"] 94 | frame_file = osp.join(self._state["video_dir"], 95 | "{:06d}.jpg".format(frame_idx)) 96 | if not osp.exists(self._state["video_dir"]): 97 | os.makedirs(self._state["video_dir"]) 98 | cv2.imwrite(frame_file, im) 99 | self._state["counter"] += 1 100 | 101 | def release(self, ): 102 | self._state["counter"] = 0 103 | -------------------------------------------------------------------------------- /snot/utils/utils_fcpp/path.py: -------------------------------------------------------------------------------- 1 | import os 2 | import os.path as osp 3 | 4 | from yacs.config import CfgNode 5 | 6 | 7 | def ensure_dir(dir_path: str): 8 | r""" 9 | Ensure the existence of path (i.e. mkdir -p) 10 | Arguments 11 | --------- 12 | dir_path: str 13 | path to be ensured 14 | """ 15 | if osp.exists(dir_path): 16 | return 17 | else: 18 | os.makedirs(dir_path) 19 | 20 | 21 | def complete_path_wt_root_in_cfg( 22 | cfg: CfgNode, 23 | root_dir: str, 24 | ): 25 | r""" 26 | Arguments 27 | --------- 28 | cfg: CfgNode 29 | yacs configuration object to be completed 30 | root_dir: str 31 | root path 32 | """ 33 | if isinstance(cfg, CfgNode): 34 | for k in cfg: 35 | cfg[k] = complete_path_wt_root_in_cfg(cfg[k], root_dir) 36 | elif isinstance(cfg, str) and len(cfg) > 0: 37 | realpath = osp.join(root_dir, cfg) 38 | if osp.exists(realpath): 39 | cfg = realpath 40 | # print(realpath) 41 | 42 | return cfg 43 | -------------------------------------------------------------------------------- /snot/utils/utils_fcpp/torch_module.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -* 2 | import collections.abc 3 | import re 4 | from typing import Dict 5 | 6 | import numpy as np 7 | 8 | import torch 9 | import torch.distributed as dist 10 | from torch import nn 11 | 12 | np_str_obj_array_pattern = re.compile(r"[aO]") 13 | default_collate_err_msg_format = ( 14 | "default_collator: inputs must contain numpy arrays, numbers, " 15 | "Unicode strings, bytes, dicts or lists; found {}") 16 | 17 | 18 | def move_data_to_device(data_dict: Dict, dev: torch.device): 19 | for k in data_dict: 20 | data_dict[k] = data_dict[k].to(dev) 21 | 22 | return data_dict 23 | 24 | 25 | def unwrap_model(model): 26 | r""" unwrap nn.dataparallel wrapped module for model serialization """ 27 | return model.module if isinstance( 28 | model, 29 | (nn.DataParallel, nn.parallel.DistributedDataParallel)) else model 30 | 31 | 32 | def convert_numpy_to_tensor(raw_data): 33 | r""" 34 | convert numpy array dict or list to torch.Tensor 35 | """ 36 | elem_type = type(raw_data) 37 | if (elem_type.__module__ == "numpy" and elem_type.__name__ != "str_" 38 | and elem_type.__name__ != "string_"): 39 | return torch.from_numpy(raw_data).float() 40 | elif isinstance(raw_data, collections.abc.Mapping): 41 | data = {key: convert_numpy_to_tensor(raw_data[key]) for key in raw_data} 42 | if 'image' in data: 43 | data['image'] = data['image'].permute(2, 0, 1) 44 | return data 45 | elif isinstance(raw_data, collections.abc.Sequence): 46 | return [convert_numpy_to_tensor(data) for data in raw_data] 47 | else: 48 | return raw_data 49 | 50 | 51 | def convert_tensor_to_numpy(raw_data): 52 | r""" 53 | convert numpy array dict or list to torch.Tensor 54 | """ 55 | if isinstance(raw_data, torch.Tensor): 56 | return raw_data.cpu().numpy() 57 | elif isinstance(raw_data, collections.abc.Mapping): 58 | data = {key: convert_tensor_to_numpy(raw_data[key]) for key in raw_data} 59 | if 'image' in data: 60 | data['image'] = data['image'].transpose(1, 2, 0).astype(np.uint8) 61 | return data 62 | elif isinstance(raw_data, collections.abc.Sequence): 63 | return [convert_tensor_to_numpy(data) for data in raw_data] 64 | 65 | 66 | def average_gradients(model): 67 | r""" Gradient averaging. 68 | from https://pytorch.org/tutorials/intermediate/dist_tuto.html 69 | to be called after _loss.backward()_ and before _optimizer.step()_ 70 | """ 71 | size = float(dist.get_world_size()) 72 | for param in model.parameters(): 73 | dist.all_reduce(param.grad.data, op=dist.reduce_op.SUM) 74 | param.grad.data /= size 75 | -------------------------------------------------------------------------------- /snot/utils/utils_upd.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import torch 3 | import numpy as np 4 | 5 | 6 | def to_numpy(tensor): 7 | if torch.is_tensor(tensor): 8 | return tensor.cpu().numpy() 9 | elif type(tensor).__module__ != 'numpy': 10 | raise ValueError("Cannot convert {} to numpy array" 11 | .format(type(tensor))) 12 | return tensor 13 | 14 | 15 | def to_torch(ndarray): 16 | if type(ndarray).__module__ == 'numpy': 17 | return torch.from_numpy(ndarray) 18 | elif not torch.is_tensor(ndarray): 19 | raise ValueError("Cannot convert {} to torch tensor" 20 | .format(type(ndarray))) 21 | return ndarray 22 | 23 | 24 | def im_to_numpy(img): 25 | img = to_numpy(img) 26 | img = np.transpose(img, (1, 2, 0)) # H*W*C 27 | return img 28 | 29 | 30 | def im_to_torch(img): 31 | img = np.transpose(img, (2, 0, 1)) # C*H*W 32 | img = to_torch(img).float() 33 | return img 34 | 35 | 36 | def torch_to_img(img): 37 | img = to_numpy(torch.squeeze(img, 0)) 38 | img = np.transpose(img, (1, 2, 0)) # H*W*C 39 | return img 40 | 41 | 42 | def get_subwindow_tracking(im, pos, model_sz, original_sz, avg_chans, out_mode='torch', new=False): 43 | 44 | if isinstance(pos, float): 45 | pos = [pos, pos] 46 | sz = original_sz 47 | im_sz = im.shape 48 | c = (original_sz+1) / 2 49 | context_xmin = round(pos[0] - c) # floor(pos(2) - sz(2) / 2); 50 | context_xmax = context_xmin + sz - 1 51 | context_ymin = round(pos[1] - c) # floor(pos(1) - sz(1) / 2); 52 | context_ymax = context_ymin + sz - 1 53 | left_pad = int(max(0., -context_xmin)) 54 | top_pad = int(max(0., -context_ymin)) 55 | right_pad = int(max(0., context_xmax - im_sz[1] + 1)) 56 | bottom_pad = int(max(0., context_ymax - im_sz[0] + 1)) 57 | 58 | context_xmin = context_xmin + left_pad 59 | context_xmax = context_xmax + left_pad 60 | context_ymin = context_ymin + top_pad 61 | context_ymax = context_ymax + top_pad 62 | 63 | # zzp: a more easy speed version 64 | r, c, k = im.shape 65 | if any([top_pad, bottom_pad, left_pad, right_pad]): 66 | te_im = np.zeros((r + top_pad + bottom_pad, c + left_pad + right_pad, k), np.uint8) # 0 is better than 1 initialization 67 | te_im[top_pad:top_pad + r, left_pad:left_pad + c, :] = im 68 | if top_pad: 69 | te_im[0:top_pad, left_pad:left_pad + c, :] = avg_chans 70 | if bottom_pad: 71 | te_im[r + top_pad:, left_pad:left_pad + c, :] = avg_chans 72 | if left_pad: 73 | te_im[:, 0:left_pad, :] = avg_chans 74 | if right_pad: 75 | te_im[:, c + left_pad:, :] = avg_chans 76 | im_patch_original = te_im[int(context_ymin):int(context_ymax + 1), int(context_xmin):int(context_xmax + 1), :] 77 | else: 78 | im_patch_original = im[int(context_ymin):int(context_ymax + 1), int(context_xmin):int(context_xmax + 1), :] 79 | 80 | if not np.array_equal(model_sz, original_sz): 81 | im_patch = cv2.resize(im_patch_original, (model_sz, model_sz)) # zzp: use cv to get a better speed 82 | else: 83 | im_patch = im_patch_original 84 | 85 | return im_to_torch(im_patch) if out_mode in 'torch' else im_patch 86 | -------------------------------------------------------------------------------- /snot/utils/visualization/__init__.py: -------------------------------------------------------------------------------- 1 | from .draw_success_precision import draw_success_precision 2 | -------------------------------------------------------------------------------- /snot/utils/visualization/draw_utils.py: -------------------------------------------------------------------------------- 1 | 2 | COLOR = ((1, 0, 0), 3 | (0, 1, 0), 4 | (1, 0, 1), 5 | (1, 1, 0), 6 | (0 , 162/255, 232/255), 7 | (0.5, 0.5, 0.5), 8 | (0, 0, 1), 9 | (0, 1, 1), 10 | (136/255, 0 , 21/255), 11 | (255/255, 127/255, 39/255), 12 | (0, 0, 0)) 13 | 14 | LINE_STYLE = ['-', '--', ':', '-', '--', ':', '-', '--', ':', '-'] 15 | 16 | MARKER_STYLE = ['o', 'v', '<', '*', 'D', 'x', '.', 'x', '<', '.'] 17 | -------------------------------------------------------------------------------- /tools/eval.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import argparse 4 | sys.path.append("./") 5 | 6 | from glob import glob 7 | from tqdm import tqdm 8 | from multiprocessing import Pool 9 | from snot.datasets import * 10 | from snot.utils.evaluation import OPEBenchmark 11 | from snot.utils.visualization import draw_success_precision 12 | 13 | 14 | parser = argparse.ArgumentParser(description='Single Object Tracking Evaluation') 15 | parser.add_argument('--datasetpath', default='',type=str, help='dataset root directory') 16 | parser.add_argument('--dataset', default='',type=str, help='dataset name') 17 | parser.add_argument('--tracker_result_dir',default='', type=str, help='tracker result root') 18 | parser.add_argument('--tracker_path', default='.', type=str) 19 | parser.add_argument('--tracker_prefix',default='', type=str) 20 | parser.add_argument('--vis', default='',dest='vis', action='store_true') 21 | parser.add_argument('--show_video_level', default='',dest='show_video_level', action='store_true') 22 | parser.add_argument('--num', default=1, type=int, help='number of processes to eval') 23 | args = parser.parse_args() 24 | 25 | 26 | def main(): 27 | tracker_dir = os.path.join(args.tracker_path, args.dataset) 28 | trackers = glob(os.path.join(args.tracker_path, 29 | args.dataset, 30 | args.tracker_prefix)) 31 | trackers = [x.split('/')[-1] for x in trackers] 32 | 33 | root = args.dataset_dir + args.dataset 34 | 35 | assert len(trackers) > 0 36 | args.num = min(args.num, len(trackers)) 37 | 38 | if 'UAV10' in args.dataset: 39 | dataset = UAV10Dataset(args.dataset, root) 40 | elif 'UAV20' in args.dataset: 41 | dataset = UAV20Dataset(args.dataset, root) 42 | elif 'DTB70' in args.dataset: 43 | dataset = DTBDataset(args.dataset, root) 44 | elif 'UAVDT' in args.dataset: 45 | dataset = UAVDTDataset(args.dataset, root) 46 | elif 'VISDRONED' in args.dataset: 47 | dataset = VISDRONEDDataset(args.dataset, root) 48 | elif 'UAVTrack112' in args.dataset: 49 | dataset = V4RDataset(args.dataset, root) 50 | elif 'UAVDark135' in args.dataset: 51 | dataset = UAVDARKDataset(args.dataset, root) 52 | elif 'DarkTrack2021' in args.dataset: 53 | dataset = DARKTRACKDataset(args.dataset, root) 54 | elif 'NAT2021' in args.dataset: 55 | dataset = DARKTRACKDataset(args.dataset, root) 56 | 57 | 58 | dataset.set_tracker(tracker_dir, trackers) 59 | benchmark = OPEBenchmark(dataset) 60 | success_ret = {} 61 | with Pool(processes=args.num) as pool: 62 | for ret in tqdm(pool.imap_unordered(benchmark.eval_success, 63 | trackers), desc='eval success', total=len(trackers), ncols=18): 64 | success_ret.update(ret) 65 | precision_ret = {} 66 | with Pool(processes=args.num) as pool: 67 | for ret in tqdm(pool.imap_unordered(benchmark.eval_precision, 68 | trackers), desc='eval precision', total=len(trackers), ncols=18): 69 | precision_ret.update(ret) 70 | benchmark.show_result(success_ret, precision_ret, 71 | show_video_level=args.show_video_level) 72 | if args.vis: 73 | for attr, videos in dataset.attr.items(): 74 | draw_success_precision(success_ret, 75 | name=dataset.name, 76 | videos=videos, 77 | attr=attr, 78 | precision_ret=precision_ret) 79 | 80 | if __name__ == '__main__': 81 | main() --------------------------------------------------------------------------------