├── .DS_Store ├── GETTING_STARTED.md ├── MODEL_ZOO.md ├── README.md ├── configs ├── Base-AGW.yml ├── Base-MGN.yml ├── Base-Strongerbaseline.yml ├── Base-bagtricks.yml ├── DukeMTMC │ ├── AGW_R101-ibn.yml │ ├── AGW_R50-ibn.yml │ ├── AGW_R50.yml │ ├── AGW_S50.yml │ ├── bagtricks_R101-ibn.yml │ ├── bagtricks_R50-ibn.yml │ ├── bagtricks_R50.yml │ ├── bagtricks_S50.yml │ ├── mgn_R50-ibn.yml │ ├── sbs_R101-ibn.yml │ ├── sbs_R50-ibn.yml │ ├── sbs_R50.yml │ └── sbs_S50.yml ├── MSMT17 │ ├── AGW_R101-ibn.yml │ ├── AGW_R50-ibn.yml │ ├── AGW_R50.yml │ ├── AGW_S50.yml │ ├── bagtricks_R101-ibn.yml │ ├── bagtricks_R50-ibn.yml │ ├── bagtricks_R50.yml │ ├── bagtricks_S50.yml │ ├── mgn_R50-ibn.yml │ ├── mgn_R50.yml │ ├── sbs_R101-ibn.yml │ ├── sbs_R50-ibn.yml │ ├── sbs_R50.yml │ └── sbs_S50.yml └── Market1501 │ ├── AGW_R101-ibn.yml │ ├── AGW_R50-ibn.yml │ ├── AGW_R50.yml │ ├── AGW_S50.yml │ ├── bagtricks_R101-ibn.yml │ ├── bagtricks_R50-ibn.yml │ ├── bagtricks_R50.yml │ ├── bagtricks_S50.yml │ ├── mgn_R50-ibn.yml │ ├── sbs_R101-ibn.yml │ ├── sbs_R50-ibn.yml │ ├── sbs_R50.yml │ └── sbs_S50.yml ├── demo ├── README.md ├── demo.py ├── plot_roc_with_pickle.py ├── predictor.py ├── run_demo.sh └── visualize_result.py ├── fastreid ├── __init__.py ├── __pycache__ │ └── __init__.cpython-36.pyc ├── config │ ├── .defaults.py.swp │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── config.cpython-36.pyc │ │ └── defaults.cpython-36.pyc │ ├── config.py │ └── defaults.py ├── data │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── build.cpython-36.pyc │ │ ├── common.cpython-36.pyc │ │ └── data_utils.cpython-36.pyc │ ├── build.py │ ├── common.py │ ├── data_utils.py │ ├── datasets │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-36.pyc │ │ │ ├── bases.cpython-36.pyc │ │ │ ├── cuhk03.cpython-36.pyc │ │ │ ├── dukemtmcreid.cpython-36.pyc │ │ │ ├── market1501.cpython-36.pyc │ │ │ ├── msmt17.cpython-36.pyc │ │ │ ├── vehicleid.cpython-36.pyc │ │ │ ├── veri.cpython-36.pyc │ │ │ └── veriwild.cpython-36.pyc │ │ ├── bases.py │ │ ├── cuhk03.py │ │ ├── dukemtmcreid.py │ │ ├── market1501.py │ │ ├── msmt17.py │ │ ├── vehicleid.py │ │ ├── veri.py │ │ └── veriwild.py │ ├── samplers │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-36.pyc │ │ │ ├── data_sampler.cpython-36.pyc │ │ │ └── triplet_sampler.cpython-36.pyc │ │ ├── data_sampler.py │ │ └── triplet_sampler.py │ └── transforms │ │ ├── __init__.py │ │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── autoaugment.cpython-36.pyc │ │ ├── build.cpython-36.pyc │ │ ├── functional.cpython-36.pyc │ │ └── transforms.cpython-36.pyc │ │ ├── autoaugment.py │ │ ├── build.py │ │ ├── functional.py │ │ └── transforms.py ├── engine │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── defaults.cpython-36.pyc │ │ ├── hooks.cpython-36.pyc │ │ └── train_loop.cpython-36.pyc │ ├── defaults.py │ ├── hooks.py │ └── train_loop.py ├── evaluation │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── evaluator.cpython-36.pyc │ │ ├── query_expansion.cpython-36.pyc │ │ ├── rank.cpython-36.pyc │ │ ├── reid_evaluation.cpython-36.pyc │ │ ├── rerank.cpython-36.pyc │ │ ├── roc.cpython-36.pyc │ │ └── testing.cpython-36.pyc │ ├── evaluator.py │ ├── query_expansion.py │ ├── rank.py │ ├── rank_cylib │ │ ├── Makefile │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ └── __init__.cpython-36.pyc │ │ ├── rank_cy.c │ │ ├── rank_cy.cpython-36m-x86_64-linux-gnu.so │ │ ├── rank_cy.pyx │ │ ├── setup.py │ │ └── test_cython.py │ ├── reid_evaluation.py │ ├── rerank.py │ ├── roc.py │ └── testing.py ├── export │ ├── __init__.py │ ├── tensorflow_export.py │ └── tf_modeling.py ├── layers │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── activation.cpython-36.pyc │ │ ├── arcface.cpython-36.pyc │ │ ├── attention.cpython-36.pyc │ │ ├── batch_drop.cpython-36.pyc │ │ ├── batch_norm.cpython-36.pyc │ │ ├── circle.cpython-36.pyc │ │ ├── context_block.cpython-36.pyc │ │ ├── frn.cpython-36.pyc │ │ ├── gem_pool.cpython-36.pyc │ │ ├── non_local.cpython-36.pyc │ │ ├── se_layer.cpython-36.pyc │ │ └── splat.cpython-36.pyc │ ├── activation.py │ ├── arcface.py │ ├── attention.py │ ├── batch_drop.py │ ├── batch_norm.py │ ├── circle.py │ ├── context_block.py │ ├── frn.py │ ├── gem_pool.py │ ├── non_local.py │ ├── se_layer.py │ ├── splat.py │ └── sync_bn │ │ ├── __init__.py │ │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── batchnorm.cpython-36.pyc │ │ ├── comm.cpython-36.pyc │ │ └── replicate.cpython-36.pyc │ │ ├── batchnorm.py │ │ ├── batchnorm_reimpl.py │ │ ├── comm.py │ │ ├── replicate.py │ │ └── unittest.py ├── modeling │ ├── __init__.py │ ├── __pycache__ │ │ └── __init__.cpython-36.pyc │ ├── backbones │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-36.pyc │ │ │ ├── build.cpython-36.pyc │ │ │ ├── osnet.cpython-36.pyc │ │ │ ├── resnest.cpython-36.pyc │ │ │ ├── resnet.cpython-36.pyc │ │ │ └── resnext.cpython-36.pyc │ │ ├── build.py │ │ ├── osnet.py │ │ ├── resnest.py │ │ ├── resnet.py │ │ └── resnext.py │ ├── heads │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-36.pyc │ │ │ ├── bnneck_head.cpython-36.pyc │ │ │ ├── build.cpython-36.pyc │ │ │ └── linear_head.cpython-36.pyc │ │ ├── bnneck_head.py │ │ ├── build.py │ │ ├── linear_head.py │ │ └── reduction_head.py │ ├── losses │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-36.pyc │ │ │ ├── build_losses.cpython-36.pyc │ │ │ ├── cross_entroy_loss.cpython-36.pyc │ │ │ ├── focal_loss.cpython-36.pyc │ │ │ └── metric_loss.cpython-36.pyc │ │ ├── build_losses.py │ │ ├── center_loss.py │ │ ├── cross_entroy_loss.py │ │ ├── focal_loss.py │ │ └── metric_loss.py │ └── meta_arch │ │ ├── __init__.py │ │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── baseline.cpython-36.pyc │ │ └── build.cpython-36.pyc │ │ ├── baseline.py │ │ ├── build.py │ │ └── mgn.py ├── solver │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── build.cpython-36.pyc │ │ └── lr_scheduler.cpython-36.pyc │ ├── build.py │ ├── lr_scheduler.py │ └── optim │ │ ├── __init__.py │ │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── lamb.cpython-36.pyc │ │ ├── lookahead.cpython-36.pyc │ │ ├── novograd.cpython-36.pyc │ │ ├── over9000.cpython-36.pyc │ │ ├── radam.cpython-36.pyc │ │ ├── ralamb.cpython-36.pyc │ │ ├── ranger.cpython-36.pyc │ │ └── swa.cpython-36.pyc │ │ ├── lamb.py │ │ ├── lookahead.py │ │ ├── novograd.py │ │ ├── over9000.py │ │ ├── radam.py │ │ ├── ralamb.py │ │ ├── ranger.py │ │ └── swa.py └── utils │ ├── __init__.py │ ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── checkpoint.cpython-36.pyc │ ├── comm.cpython-36.pyc │ ├── events.cpython-36.pyc │ ├── file_io.cpython-36.pyc │ ├── history_buffer.cpython-36.pyc │ ├── logger.cpython-36.pyc │ ├── one_hot.cpython-36.pyc │ ├── precision_bn.cpython-36.pyc │ ├── registry.cpython-36.pyc │ ├── timer.cpython-36.pyc │ └── weight_init.cpython-36.pyc │ ├── checkpoint.py │ ├── comm.py │ ├── events.py │ ├── file_io.py │ ├── history_buffer.py │ ├── logger.py │ ├── one_hot.py │ ├── precision_bn.py │ ├── registry.py │ ├── summary.py │ ├── timer.py │ ├── visualizer.py │ └── weight_init.py ├── projects ├── .gitkeep ├── PartialReID │ ├── configs │ │ ├── .partial_market.yml.swn │ │ ├── .partial_market.yml.swo │ │ ├── .partial_market.yml.swp │ │ └── partial_market.yml │ ├── partialreid │ │ ├── .dsr_head.py.swo │ │ ├── .dsr_head.py.swp │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-36.pyc │ │ │ ├── config.cpython-36.pyc │ │ │ ├── dsr_distance.cpython-36.pyc │ │ │ ├── dsr_evaluation.cpython-36.pyc │ │ │ ├── dsr_head.cpython-36.pyc │ │ │ ├── partial_dataset.cpython-36.pyc │ │ │ └── partialbaseline.cpython-36.pyc │ │ ├── config.py │ │ ├── dsr_distance.py │ │ ├── dsr_evaluation.py │ │ ├── dsr_head.py │ │ ├── partial_dataset.py │ │ └── partialbaseline.py │ └── train_net.py └── README.md ├── tests ├── __init__.py ├── dataset_test.py ├── interp_test.py ├── lr_scheduler_test.py ├── model_test.py └── sampler_test.py └── tools ├── export2tf.py └── train_net.py /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/.DS_Store -------------------------------------------------------------------------------- /GETTING_STARTED.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Fastreid 2 | 3 | ## Prepare pretrained model 4 | 5 | If you use origin ResNet, you do not need to do anything. But if you want to use ResNet_ibn, you need to download pretrain model in [here](https://drive.google.com/open?id=1thS2B8UOSBi_cJX6zRy6YYRwz_nVFI_S). And then you can put it in `~/.cache/torch/checkpoints` or anywhere you like. 6 | 7 | Then you should set the pretrain model path in `configs/Base-bagtricks.yml`. 8 | 9 | ## Compile with cython to accelerate evalution 10 | 11 | ```bash 12 | cd fastreid/evaluation/rank_cylib; make all 13 | ``` 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DSR in FastReID 2 | **Deep Spatial Feature Reconstruction for Partial Person Re-identification** 3 | 4 | Lingxiao He, Xingyu Liao 5 | 6 | [[`CVPR2018`](http://openaccess.thecvf.com/content_cvpr_2018/papers/He_Deep_Spatial_Feature_CVPR_2018_paper.pdf)] [[`BibTeX`](#CitingDSR)] 7 | 8 | **Foreground-aware Pyramid Reconstruction for Alignment-free Occluded Person Re-identification** 9 | 10 | Lingxiao He, Xingyu Liao 11 | 12 | [[`ICCV2019`](http://openaccess.thecvf.com/content_ICCV_2019/papers/He_Foreground-Aware_Pyramid_Reconstruction_for_Alignment-Free_Occluded_Person_Re-Identification_ICCV_2019_paper.pdf)] [[`BibTeX`](#CitingFPR)] 13 | 14 | ## Installation 15 | 16 | First install FastReID, and then put Partial Datasets in directory datasets. The whole framework of FastReID-DSR is 17 |
18 | 19 |
20 | 21 | and the detail you can refer to 22 | ## Datasets 23 | 24 | The datasets can find in [Google Drive](https://drive.google.com/file/d/1p7Jvo-RJhU_B6hf9eAhIEFNhvrzM5cdh/view?usp=sharing) 25 | 26 | PartialREID---gallery: 300 images of 60 ids, query: 300 images of 60 ids 27 | 28 | PartialiLIDS---gallery: 119 images of 119 ids, query: 119 images of 119 ids 29 | 30 | OccludedREID---gallery: 1,000 images of 200 ids, query: 1,000 images of 200 ids 31 | 32 | ## Training and Evaluation 33 | 34 | To train a model, run: 35 | ```bash 36 | python3 projects/PartialReID/train_net.py --config-file 37 | ``` 38 | 39 | For example, to train the re-id network with IBN-ResNet-50 Backbone 40 | one should execute: 41 | ```bash 42 | CUDA_VISIBLE_DEVICES='0,1,2,3' python3 projects/PartialReID/train_net.py --config-file 'projects/PartialReID/configs/partial_market.yml' 43 | ``` 44 | 45 | ## Results 46 | 47 | | Method | PartialREID | OccludedREID | PartialiLIDS | 48 | |:--:|:--:|:--:|:--:| 49 | | | Rank@1 (mAP)| Rank@1 (mAP)| Rank@1 (mAP)| 50 | | DSR (CVPR’18) |73.7(68.1) |72.8(62.8)|64.3(58.1)| 51 | | FPR (ICCV'19) | 81.0(76.6)|78.3(68.0)|68.1(61.8)| 52 | | FastReID-DSR | 82.7(76.8)|81.6(70.9)|73.1(79.8) | 53 | 54 | ## Citing DSR and Citing FPR 55 | 56 | If you use DSR or FPR, please use the following BibTeX entry. 57 | 58 | ``` 59 | @inproceedings{he2018deep, 60 | title={Deep spatial feature reconstruction for partial person re-identification: Alignment-free approach}, 61 | author={He, Lingxiao and Liang, Jian and Li, Haiqing and Sun, Zhenan}, 62 | booktitle={IEEE Conference on Computer Vision and Pattern Recognition (CVPR)}, 63 | year={2018} 64 | } 65 | @inproceedings{he2019foreground, 66 | title={Foreground-aware Pyramid Reconstruction for Alignment-free Occluded Person Re-identification}, 67 | author={He, Lingxiao and Wang, Yinggang and Liu, Wu and Zhao, He and Sun, Zhenan and Feng, Jiashi}, 68 | booktitle={IEEE International Conference on Computer Vision (ICCV)}, 69 | year={2019} 70 | } 71 | ``` 72 | -------------------------------------------------------------------------------- /configs/Base-AGW.yml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: 'Baseline' 3 | 4 | BACKBONE: 5 | NAME: "build_resnet_backbone" 6 | DEPTH: 50 7 | LAST_STRIDE: 1 8 | WITH_NL: True 9 | PRETRAIN: True 10 | 11 | HEADS: 12 | NAME: "BNneckHead" 13 | POOL_LAYER: "gempool" 14 | NECK_FEAT: "before" 15 | CLS_LAYER: "linear" 16 | NUM_CLASSES: 702 17 | 18 | LOSSES: 19 | NAME: ("CrossEntropyLoss", "TripletLoss") 20 | CE: 21 | EPSILON: 0.1 22 | SCALE: 1.0 23 | 24 | TRI: 25 | MARGIN: 0.0 26 | HARD_MINING: False 27 | USE_COSINE_DIST: False 28 | SCALE: 1.0 29 | 30 | DATASETS: 31 | NAMES: ("DukeMTMC",) 32 | TESTS: ("DukeMTMC",) 33 | 34 | INPUT: 35 | SIZE_TRAIN: [256, 128] 36 | SIZE_TEST: [256, 128] 37 | REA: 38 | ENABLED: True 39 | PROB: 0.5 40 | MEAN: [123.675, 116.28, 103.53] 41 | DO_PAD: True 42 | 43 | DATALOADER: 44 | PK_SAMPLER: True 45 | NUM_INSTANCE: 4 46 | NUM_WORKERS: 16 47 | 48 | SOLVER: 49 | OPT: "Adam" 50 | MAX_ITER: 24000 51 | BASE_LR: 0.00035 52 | BIAS_LR_FACTOR: 2. 53 | WEIGHT_DECAY: 0.0005 54 | WEIGHT_DECAY_BIAS: 0.0005 55 | IMS_PER_BATCH: 64 56 | 57 | STEPS: [8000, 18000] 58 | GAMMA: 0.1 59 | 60 | WARMUP_FACTOR: 0.01 61 | WARMUP_ITERS: 2000 62 | 63 | LOG_PERIOD: 200 64 | CHECKPOINT_PERIOD: 6000 65 | 66 | TEST: 67 | EVAL_PERIOD: 2000 68 | IMS_PER_BATCH: 256 69 | 70 | CUDNN_BENCHMARK: True 71 | 72 | -------------------------------------------------------------------------------- /configs/Base-MGN.yml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: 'MGN' 3 | 4 | OPEN_LAYERS: ["b1_pool", "b1_head", "b2_pool", "b2_head", "b21_pool", "b21_head", "b22_pool", "b22_head", 5 | "b3_pool", "b3_head", "b31_pool", "b31_head", "b32_pool", "b32_head", "b33_pool", "b33_head"] 6 | 7 | BACKBONE: 8 | NAME: "build_resnet_backbone" 9 | NORM: "BN" 10 | DEPTH: 50 11 | LAST_STRIDE: 1 12 | WITH_IBN: False 13 | WITH_NL: False 14 | PRETRAIN: True 15 | 16 | HEADS: 17 | NAME: "BNneckHead" 18 | NORM: "BN" 19 | NECK_FEAT: "after" 20 | CLS_LAYER: "circle" 21 | POOL_LAYER: "gempool" 22 | IN_FEAT: 256 23 | SCALE: 64 24 | MARGIN: 0.35 25 | 26 | LOSSES: 27 | NAME: ("CrossEntropyLoss", "TripletLoss",) 28 | CE: 29 | EPSILON: 0.1 30 | SCALE: 0.125 31 | 32 | TRI: 33 | MARGIN: 0.0 34 | HARD_MINING: True 35 | NORM_FEAT: False 36 | USE_COSINE_DIST: False 37 | SCALE: 0.20 38 | 39 | DATASETS: 40 | NAMES: ("DukeMTMC",) 41 | TESTS: ("DukeMTMC",) 42 | 43 | INPUT: 44 | SIZE_TRAIN: [384, 128] 45 | SIZE_TEST: [384, 128] 46 | DO_AUTOAUG: True 47 | REA: 48 | ENABLED: True 49 | PROB: 0.5 50 | MEAN: [123.675, 116.28, 103.53] 51 | DO_PAD: True 52 | 53 | DATALOADER: 54 | PK_SAMPLER: True 55 | NUM_INSTANCE: 16 56 | NUM_WORKERS: 16 57 | 58 | SOLVER: 59 | OPT: "Adam" 60 | MAX_ITER: 18000 61 | BASE_LR: 0.00035 62 | BIAS_LR_FACTOR: 2. 63 | WEIGHT_DECAY: 0.0005 64 | WEIGHT_DECAY_BIAS: 0.0 65 | IMS_PER_BATCH: 64 66 | 67 | SCHED: "DelayedCosineAnnealingLR" 68 | 69 | DELAY_ITERS: 9000 70 | ETA_MIN_LR: 0.00000077 71 | 72 | WARMUP_FACTOR: 0.01 73 | WARMUP_ITERS: 2000 74 | 75 | FREEZE_ITERS: 2000 76 | 77 | LOG_PERIOD: 200 78 | CHECKPOINT_PERIOD: 6000 79 | 80 | TEST: 81 | EVAL_PERIOD: 2000 82 | IMS_PER_BATCH: 256 83 | PRECISE_BN: 84 | ENABLED: False 85 | DATASET: 'DukeMTMC' 86 | 87 | CUDNN_BENCHMARK: True 88 | 89 | -------------------------------------------------------------------------------- /configs/Base-Strongerbaseline.yml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: 'Baseline' 3 | 4 | OPEN_LAYERS: ["heads"] 5 | 6 | BACKBONE: 7 | NAME: "build_resnet_backbone" 8 | NORM: "BN" 9 | DEPTH: 50 10 | LAST_STRIDE: 1 11 | WITH_IBN: False 12 | WITH_NL: True 13 | PRETRAIN: True 14 | 15 | HEADS: 16 | NAME: "BNneckHead" 17 | NORM: "BN" 18 | NECK_FEAT: "after" 19 | CLS_LAYER: "circle" 20 | POOL_LAYER: "gempool" 21 | SCALE: 64 22 | MARGIN: 0.35 23 | 24 | LOSSES: 25 | NAME: ("CrossEntropyLoss", "TripletLoss",) 26 | CE: 27 | EPSILON: 0.1 28 | SCALE: 1.0 29 | 30 | TRI: 31 | MARGIN: 0.0 32 | HARD_MINING: True 33 | NORM_FEAT: False 34 | USE_COSINE_DIST: False 35 | SCALE: 1.0 36 | 37 | DATASETS: 38 | NAMES: ("DukeMTMC",) 39 | TESTS: ("DukeMTMC",) 40 | 41 | INPUT: 42 | SIZE_TRAIN: [384, 128] 43 | SIZE_TEST: [384, 128] 44 | DO_AUTOAUG: True 45 | REA: 46 | ENABLED: True 47 | PROB: 0.5 48 | MEAN: [123.675, 116.28, 103.53] 49 | DO_PAD: True 50 | 51 | DATALOADER: 52 | PK_SAMPLER: True 53 | NUM_INSTANCE: 16 54 | NUM_WORKERS: 16 55 | 56 | SOLVER: 57 | OPT: "Adam" 58 | MAX_ITER: 18000 59 | BASE_LR: 0.00035 60 | BIAS_LR_FACTOR: 1. 61 | WEIGHT_DECAY: 0.0005 62 | WEIGHT_DECAY_BIAS: 0.0005 63 | IMS_PER_BATCH: 64 64 | 65 | SCHED: "DelayedCosineAnnealingLR" 66 | 67 | DELAY_ITERS: 9000 68 | ETA_MIN_LR: 0.00000077 69 | 70 | WARMUP_FACTOR: 0.01 71 | WARMUP_ITERS: 2000 72 | 73 | FREEZE_ITERS: 2000 74 | 75 | LOG_PERIOD: 200 76 | CHECKPOINT_PERIOD: 6000 77 | 78 | TEST: 79 | EVAL_PERIOD: 2000 80 | IMS_PER_BATCH: 256 81 | PRECISE_BN: 82 | ENABLED: False 83 | DATASET: 'DukeMTMC' 84 | 85 | CUDNN_BENCHMARK: True 86 | 87 | -------------------------------------------------------------------------------- /configs/Base-bagtricks.yml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: "Baseline" 3 | 4 | BACKBONE: 5 | NAME: "build_resnet_backbone" 6 | NORM: "BN" 7 | DEPTH: 50 8 | LAST_STRIDE: 1 9 | WITH_IBN: False 10 | PRETRAIN: True 11 | 12 | HEADS: 13 | NAME: "BNneckHead" 14 | NORM: "BN" 15 | NECK_FEAT: "before" 16 | CLS_LAYER: "linear" 17 | 18 | LOSSES: 19 | NAME: ("CrossEntropyLoss", "TripletLoss", ) 20 | 21 | CE: 22 | EPSILON: 0.1 23 | SCALE: 1. 24 | 25 | TRI: 26 | MARGIN: 0.3 27 | HARD_MINING: True 28 | USE_COSINE_DIST: False 29 | SCALE: 1. 30 | 31 | DATASETS: 32 | NAMES: ("DukeMTMC",) 33 | TESTS: ("DukeMTMC",) 34 | 35 | INPUT: 36 | SIZE_TRAIN: [256, 128] 37 | SIZE_TEST: [256, 128] 38 | REA: 39 | ENABLED: True 40 | PROB: 0.5 41 | MEAN: [123.675, 116.28, 103.53] 42 | DO_PAD: True 43 | 44 | 45 | DATALOADER: 46 | PK_SAMPLER: True 47 | NUM_INSTANCE: 4 48 | NUM_WORKERS: 16 49 | 50 | SOLVER: 51 | OPT: "Adam" 52 | MAX_ITER: 24000 53 | BASE_LR: 0.00035 54 | BIAS_LR_FACTOR: 2. 55 | WEIGHT_DECAY: 0.0005 56 | WEIGHT_DECAY_BIAS: 0.0005 57 | IMS_PER_BATCH: 64 58 | 59 | STEPS: [8000, 18000] 60 | GAMMA: 0.1 61 | 62 | WARMUP_FACTOR: 0.01 63 | WARMUP_ITERS: 2000 64 | 65 | LOG_PERIOD: 200 66 | CHECKPOINT_PERIOD: 2000 67 | 68 | TEST: 69 | EVAL_PERIOD: 2000 70 | IMS_PER_BATCH: 256 71 | 72 | CUDNN_BENCHMARK: True 73 | 74 | -------------------------------------------------------------------------------- /configs/DukeMTMC/AGW_R101-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-AGW.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | NAME: "build_resnet_backbone" 6 | DEPTH: 101 7 | WITH_IBN: True 8 | PRETRAIN_PATH: "/home/liaoxingyu2/lxy/.cache/torch/checkpoints/resnet101_ibn_a.pth.tar" 9 | 10 | HEADS: 11 | NUM_CLASSES: 702 12 | 13 | DATASETS: 14 | NAMES: ("DukeMTMC",) 15 | TESTS: ("DukeMTMC",) 16 | 17 | OUTPUT_DIR: "logs/dukemtmc/agw_R101-ibn" 18 | -------------------------------------------------------------------------------- /configs/DukeMTMC/AGW_R50-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-AGW.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | NAME: "build_resnet_backbone" 6 | WITH_IBN: True 7 | PRETRAIN_PATH: "/home/liaoxingyu2/lxy/.cache/torch/checkpoints/resnet50_ibn_a.pth.tar" 8 | 9 | HEADS: 10 | NUM_CLASSES: 702 11 | 12 | DATASETS: 13 | NAMES: ("DukeMTMC",) 14 | TESTS: ("DukeMTMC",) 15 | 16 | OUTPUT_DIR: "logs/dukemtmc/agw_R50-ibn" 17 | -------------------------------------------------------------------------------- /configs/DukeMTMC/AGW_R50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-AGW.yml" 2 | 3 | MODEL: 4 | HEADS: 5 | NUM_CLASSES: 702 6 | 7 | 8 | DATASETS: 9 | NAMES: ("DukeMTMC",) 10 | TESTS: ("DukeMTMC",) 11 | 12 | OUTPUT_DIR: "logs/dukemtmc/agw_R50" 13 | -------------------------------------------------------------------------------- /configs/DukeMTMC/AGW_S50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-AGW.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | NAME: "build_resnest_backbone" 6 | 7 | HEADS: 8 | NUM_CLASSES: 702 9 | 10 | LOSSES: 11 | TRI: 12 | MARGIN: 0.3 13 | 14 | DATASETS: 15 | NAMES: ("DukeMTMC",) 16 | TESTS: ("DukeMTMC",) 17 | 18 | OUTPUT_DIR: "logs/dukemtmc/agw_S50" 19 | -------------------------------------------------------------------------------- /configs/DukeMTMC/bagtricks_R101-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-bagtricks.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | DEPTH: 101 6 | WITH_IBN: True 7 | PRETRAIN_PATH: "/export/home/lxy/.cache/torch/checkpoints/resnet101_ibn_a.pth.tar" 8 | 9 | HEADS: 10 | NUM_CLASSES: 702 11 | 12 | DATASETS: 13 | NAMES: ("DukeMTMC",) 14 | TESTS: ("DukeMTMC",) 15 | 16 | OUTPUT_DIR: "logs/dukemtmc/bagtricks_R101-ibn" 17 | -------------------------------------------------------------------------------- /configs/DukeMTMC/bagtricks_R50-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-bagtricks.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | WITH_IBN: True 6 | PRETRAIN_PATH: "/home/liaoxingyu2/lxy/.cache/torch/checkpoints/resnet50_ibn_a.pth.tar" 7 | 8 | HEADS: 9 | NUM_CLASSES: 702 10 | 11 | DATASETS: 12 | NAMES: ("DukeMTMC",) 13 | TESTS: ("DukeMTMC",) 14 | 15 | OUTPUT_DIR: "logs/dukemtmc/bagtricks_R50-ibn" 16 | -------------------------------------------------------------------------------- /configs/DukeMTMC/bagtricks_R50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-bagtricks.yml" 2 | 3 | MODEL: 4 | HEADS: 5 | NUM_CLASSES: 702 6 | 7 | 8 | DATASETS: 9 | NAMES: ("DukeMTMC",) 10 | TESTS: ("DukeMTMC",) 11 | 12 | OUTPUT_DIR: "logs/dukemtmc/bagtricks_R50" 13 | -------------------------------------------------------------------------------- /configs/DukeMTMC/bagtricks_S50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-bagtricks.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | NAME: "build_resnest_backbone" 6 | 7 | HEADS: 8 | NUM_CLASSES: 702 9 | 10 | DATASETS: 11 | NAMES: ("DukeMTMC",) 12 | TESTS: ("DukeMTMC",) 13 | 14 | OUTPUT_DIR: "logs/dukemtmc/bagtricks_S50" 15 | -------------------------------------------------------------------------------- /configs/DukeMTMC/mgn_R50-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-MGN.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | PRETRAIN_PATH: "/home/liaoxingyu2/lxy/.cache/torch/checkpoints/resnet50_ibn_a.pth.tar" 6 | HEADS: 7 | NUM_CLASSES: 702 8 | 9 | DATASETS: 10 | NAMES: ("DukeMTMC",) 11 | TESTS: ("DukeMTMC",) 12 | 13 | 14 | OUTPUT_DIR: "logs/dukemtmc/mgn_R50-ibn" 15 | -------------------------------------------------------------------------------- /configs/DukeMTMC/sbs_R101-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-Strongerbaseline.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | DEPTH: 101 6 | WITH_IBN: True 7 | PRETRAIN_PATH: "/export/home/lxy/.cache/torch/checkpoints/resnet101_ibn_a.pth.tar" 8 | 9 | HEADS: 10 | NUM_CLASSES: 702 11 | 12 | DATASETS: 13 | NAMES: ("DukeMTMC",) 14 | TESTS: ("DukeMTMC",) 15 | 16 | TEST: 17 | PRECISE_BN: 18 | DATASET: 'DukeMTMC' 19 | 20 | OUTPUT_DIR: "logs/dukemtmc/sbs-R101-ibn" 21 | -------------------------------------------------------------------------------- /configs/DukeMTMC/sbs_R50-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-Strongerbaseline.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | WITH_IBN: True 6 | PRETRAIN_PATH: "/export/home/lxy/.cache/torch/checkpoints/resnet50_ibn_a.pth.tar" 7 | 8 | HEADS: 9 | NUM_CLASSES: 702 10 | 11 | DATASETS: 12 | NAMES: ("DukeMTMC",) 13 | TESTS: ("DukeMTMC",) 14 | 15 | TEST: 16 | EVAL_PERIOD: 2000 17 | PRECISE_BN: 18 | DATASET: 'DukeMTMC' 19 | 20 | OUTPUT_DIR: "logs/dukemtmc/sbs_R50-ibn" 21 | -------------------------------------------------------------------------------- /configs/DukeMTMC/sbs_R50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-Strongerbaseline.yml" 2 | 3 | MODEL: 4 | HEADS: 5 | NUM_CLASSES: 702 6 | 7 | DATASETS: 8 | NAMES: ("DukeMTMC",) 9 | TESTS: ("DukeMTMC",) 10 | 11 | TEST: 12 | PRECISE_BN: 13 | DATASET: 'DukeMTMC' 14 | 15 | OUTPUT_DIR: "logs/dukemtmc/sbs_R50" 16 | -------------------------------------------------------------------------------- /configs/DukeMTMC/sbs_S50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-Strongerbaseline.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | NAME: "build_resnest_backbone" 6 | 7 | HEADS: 8 | NUM_CLASSES: 702 9 | 10 | LOSSES: 11 | TRI: 12 | MARGIN: 0.3 13 | 14 | DATASETS: 15 | NAMES: ("DukeMTMC",) 16 | TESTS: ("DukeMTMC",) 17 | 18 | TEST: 19 | PRECISE_BN: 20 | DATASET: 'DukeMTMC' 21 | 22 | OUTPUT_DIR: "logs/dukemtmc/sbs_S50" 23 | -------------------------------------------------------------------------------- /configs/MSMT17/AGW_R101-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-AGW.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | DEPTH: 101 6 | WITH_IBN: True 7 | PRETRAIN_PATH: "/home/liaoxingyu2/lxy/.cache/torch/checkpoints/resnet101_ibn_a.pth.tar" 8 | 9 | HEADS: 10 | NUM_CLASSES: 1041 11 | 12 | DATASETS: 13 | NAMES: ("MSMT17",) 14 | TESTS: ("MSMT17",) 15 | 16 | SOLVER: 17 | MAX_ITER: 42000 18 | STEPS: [19000, 33000] 19 | WARMUP_ITERS: 4700 20 | 21 | CHECKPOINT_PERIOD: 5000 22 | 23 | TEST: 24 | EVAL_PERIOD: 5000 25 | 26 | OUTPUT_DIR: "logs/msmt17/agw_R101-ibn" 27 | -------------------------------------------------------------------------------- /configs/MSMT17/AGW_R50-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-AGW.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | WITH_IBN: True 6 | PRETRAIN_PATH: "/export/home/lxy/.cache/torch/checkpoints/resnet50_ibn_a.pth.tar" 7 | 8 | HEADS: 9 | NUM_CLASSES: 1041 10 | 11 | DATASETS: 12 | NAMES: ("MSMT17",) 13 | TESTS: ("MSMT17",) 14 | 15 | SOLVER: 16 | MAX_ITER: 42000 17 | STEPS: [19000, 33000] 18 | WARMUP_ITERS: 4700 19 | 20 | CHECKPOINT_PERIOD: 5000 21 | 22 | TEST: 23 | EVAL_PERIOD: 5000 24 | 25 | OUTPUT_DIR: "logs/msmt17/agw_R50-ibn" 26 | -------------------------------------------------------------------------------- /configs/MSMT17/AGW_R50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-AGW.yml" 2 | 3 | MODEL: 4 | HEADS: 5 | NUM_CLASSES: 1041 6 | 7 | DATASETS: 8 | NAMES: ("MSMT17",) 9 | TESTS: ("MSMT17",) 10 | 11 | SOLVER: 12 | MAX_ITER: 42000 13 | STEPS: [19000, 33000] 14 | WARMUP_ITERS: 4700 15 | 16 | CHECKPOINT_PERIOD: 5000 17 | 18 | TEST: 19 | EVAL_PERIOD: 5000 20 | 21 | OUTPUT_DIR: "logs/msmt17/agw_R50" 22 | -------------------------------------------------------------------------------- /configs/MSMT17/AGW_S50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-AGW.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | NAME: "build_resnest_backbone" 6 | 7 | HEADS: 8 | NUM_CLASSES: 1041 9 | 10 | LOSSES: 11 | TRI: 12 | MARGIN: 0.3 13 | 14 | DATASETS: 15 | NAMES: ("MSMT17",) 16 | TESTS: ("MSMT17",) 17 | 18 | SOLVER: 19 | MAX_ITER: 42000 20 | STEPS: [19000, 33000] 21 | WARMUP_ITERS: 4700 22 | 23 | CHECKPOINT_PERIOD: 5000 24 | 25 | TEST: 26 | EVAL_PERIOD: 5000 27 | 28 | OUTPUT_DIR: "logs/msmt17/agw_S50" 29 | -------------------------------------------------------------------------------- /configs/MSMT17/bagtricks_R101-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-bagtricks.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | DEPTH: 101 6 | WITH_IBN: True 7 | PRETRAIN_PATH: "/export/home/lxy/.cache/torch/checkpoints/resnet101_ibn_a.pth.tar" 8 | 9 | HEADS: 10 | NUM_CLASSES: 1041 11 | 12 | SOLVER: 13 | MAX_ITER: 42000 14 | STEPS: [19000, 33000] 15 | WARMUP_ITERS: 4700 16 | CHECKPOINT_PERIOD: 5000 17 | 18 | DATASETS: 19 | NAMES: ("MSMT17",) 20 | TESTS: ("MSMT17",) 21 | 22 | TEST: 23 | EVAL_PERIOD: 5000 24 | 25 | OUTPUT_DIR: "logs/msmt17/bagtricks_R101-ibn" 26 | 27 | -------------------------------------------------------------------------------- /configs/MSMT17/bagtricks_R50-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-bagtricks.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | WITH_IBN: True 6 | PRETRAIN_PATH: "/export/home/lxy/.cache/torch/checkpoints/resnet50_ibn_a.pth.tar" 7 | 8 | HEADS: 9 | NUM_CLASSES: 1041 10 | 11 | SOLVER: 12 | MAX_ITER: 42000 13 | STEPS: [19000, 33000] 14 | WARMUP_ITERS: 4700 15 | CHECKPOINT_PERIOD: 5000 16 | 17 | DATASETS: 18 | NAMES: ("MSMT17",) 19 | TESTS: ("MSMT17",) 20 | 21 | TEST: 22 | EVAL_PERIOD: 5000 23 | 24 | OUTPUT_DIR: "logs/msmt17/bagtricks_R50-ibn" 25 | 26 | -------------------------------------------------------------------------------- /configs/MSMT17/bagtricks_R50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-bagtricks.yml" 2 | 3 | MODEL: 4 | HEADS: 5 | NUM_CLASSES: 1041 6 | 7 | SOLVER: 8 | MAX_ITER: 42000 9 | STEPS: [19000, 33000] 10 | WARMUP_ITERS: 4700 11 | CHECKPOINT_PERIOD: 5000 12 | 13 | DATASETS: 14 | NAMES: ("MSMT17",) 15 | TESTS: ("MSMT17",) 16 | 17 | TEST: 18 | EVAL_PERIOD: 5000 19 | 20 | OUTPUT_DIR: "logs/msmt17/bagtricks_R50" 21 | -------------------------------------------------------------------------------- /configs/MSMT17/bagtricks_S50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-bagtricks.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | NAME: "build_resnest_backbone" 6 | 7 | HEADS: 8 | NUM_CLASSES: 1041 9 | 10 | SOLVER: 11 | MAX_ITER: 42000 12 | STEPS: [19000, 33000] 13 | WARMUP_ITERS: 4700 14 | CHECKPOINT_PERIOD: 5000 15 | 16 | DATASETS: 17 | NAMES: ("MSMT17",) 18 | TESTS: ("MSMT17",) 19 | 20 | TEST: 21 | EVAL_PERIOD: 5000 22 | 23 | OUTPUT_DIR: "logs/msmt17/bagtricks_S50" 24 | 25 | -------------------------------------------------------------------------------- /configs/MSMT17/mgn_R50-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-MGN.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | WITH_IBN: True 6 | PRETRAIN_PATH: "/home/liaoxingyu2/lxy/.cache/torch/checkpoints/resnet50_ibn_a.pth.tar" 7 | 8 | HEADS: 9 | NUM_CLASSES: 1041 10 | 11 | DATASETS: 12 | NAMES: ("MSMT17",) 13 | TESTS: ("MSMT17",) 14 | 15 | SOLVER: 16 | MAX_ITER: 28000 17 | DELAY_ITERS: 14000 18 | WARMUP_ITERS: 4700 19 | FREEZE_ITERS: 4700 20 | 21 | TEST: 22 | EVAL_PERIOD: 5000 23 | PRECISE_BN: 24 | DATASET: 'MSMT17' 25 | 26 | OUTPUT_DIR: "logs/msmt17/mgn_R50-ibn" 27 | -------------------------------------------------------------------------------- /configs/MSMT17/mgn_R50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-MGN.yml" 2 | 3 | MODEL: 4 | HEADS: 5 | NUM_CLASSES: 1041 6 | 7 | DATASETS: 8 | NAMES: ("MSMT17",) 9 | TESTS: ("MSMT17",) 10 | 11 | SOLVER: 12 | MAX_ITER: 28000 13 | DELAY_ITERS: 14000 14 | WARMUP_ITERS: 4700 15 | FREEZE_ITERS: 4700 16 | 17 | TEST: 18 | EVAL_PERIOD: 5000 19 | PRECISE_BN: 20 | DATASET: 'MSMT17' 21 | 22 | OUTPUT_DIR: "logs/msmt17/mgn_R50" 23 | -------------------------------------------------------------------------------- /configs/MSMT17/sbs_R101-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-Strongerbaseline.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | DEPTH: 101 6 | WITH_IBN: True 7 | PRETRAIN_PATH: "/export/home/lxy/.cache/torch/checkpoints/resnet101_ibn_a.pth.tar" 8 | 9 | HEADS: 10 | NUM_CLASSES: 1041 11 | 12 | DATASETS: 13 | NAMES: ("MSMT17",) 14 | TESTS: ("MSMT17",) 15 | 16 | SOLVER: 17 | MAX_ITER: 28000 18 | DELAY_ITERS: 14000 19 | WARMUP_ITERS: 4700 20 | FREEZE_ITERS: 4700 21 | 22 | TEST: 23 | EVAL_PERIOD: 5000 24 | PRECISE_BN: 25 | DATASET: 'MSMT17' 26 | 27 | OUTPUT_DIR: "logs/msmt17/sbs-R101-ibn" 28 | -------------------------------------------------------------------------------- /configs/MSMT17/sbs_R50-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-Strongerbaseline.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | WITH_IBN: True 6 | PRETRAIN_PATH: "/export/home/lxy/.cache/torch/checkpoints/resnet50_ibn_a.pth.tar" 7 | 8 | HEADS: 9 | NUM_CLASSES: 1041 10 | 11 | DATASETS: 12 | NAMES: ("MSMT17",) 13 | TESTS: ("MSMT17",) 14 | 15 | SOLVER: 16 | MAX_ITER: 28000 17 | DELAY_ITERS: 14000 18 | WARMUP_ITERS: 4700 19 | FREEZE_ITERS: 4700 20 | 21 | TEST: 22 | EVAL_PERIOD: 5000 23 | PRECISE_BN: 24 | DATASET: 'MSMT17' 25 | 26 | OUTPUT_DIR: "logs/msmt17/sbs_R50-ibn" 27 | -------------------------------------------------------------------------------- /configs/MSMT17/sbs_R50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-Strongerbaseline.yml" 2 | 3 | MODEL: 4 | HEADS: 5 | NUM_CLASSES: 1041 6 | 7 | DATASETS: 8 | NAMES: ("MSMT17",) 9 | TESTS: ("MSMT17",) 10 | 11 | SOLVER: 12 | MAX_ITER: 28000 13 | DELAY_ITERS: 14000 14 | WARMUP_ITERS: 4700 15 | FREEZE_ITERS: 4700 16 | 17 | TEST: 18 | EVAL_PERIOD: 5000 19 | PRECISE_BN: 20 | DATASET: 'MSMT17' 21 | 22 | OUTPUT_DIR: "logs/msmt17/sbs_R50" 23 | -------------------------------------------------------------------------------- /configs/MSMT17/sbs_S50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-Strongerbaseline.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | NAME: "build_resnest_backbone" 6 | 7 | HEADS: 8 | NUM_CLASSES: 1041 9 | 10 | LOSSES: 11 | TRI: 12 | MARGIN: 0.3 13 | 14 | DATASETS: 15 | NAMES: ("MSMT17",) 16 | TESTS: ("MSMT17",) 17 | 18 | SOLVER: 19 | MAX_ITER: 28000 20 | DELAY_ITERS: 14000 21 | WARMUP_ITERS: 4700 22 | FREEZE_ITERS: 4700 23 | 24 | TEST: 25 | EVAL_PERIOD: 5000 26 | PRECISE_BN: 27 | DATASET: 'MSMT17' 28 | 29 | OUTPUT_DIR: "logs/msmt17/sbs_S50" 30 | -------------------------------------------------------------------------------- /configs/Market1501/AGW_R101-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-AGW.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | NAME: "build_resnet_backbone" 6 | DEPTH: 101 7 | WITH_IBN: True 8 | PRETRAIN_PATH: "/export/home/lxy/.cache/torch/checkpoints/resnet101_ibn_a.pth.tar" 9 | 10 | HEADS: 11 | NUM_CLASSES: 751 12 | 13 | DATASETS: 14 | NAMES: ("Market1501",) 15 | TESTS: ("Market1501",) 16 | 17 | OUTPUT_DIR: "logs/market1501/agw_R101-ibn" 18 | -------------------------------------------------------------------------------- /configs/Market1501/AGW_R50-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-AGW.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | NAME: "build_resnet_backbone" 6 | WITH_IBN: True 7 | PRETRAIN_PATH: "/home/liaoxingyu2/lxy/.cache/torch/checkpoints/resnet50_ibn_a.pth.tar" 8 | 9 | HEADS: 10 | NUM_CLASSES: 751 11 | 12 | 13 | DATASETS: 14 | NAMES: ("Market1501",) 15 | TESTS: ("Market1501",) 16 | 17 | OUTPUT_DIR: "logs/market1501/agw_R50-ibn" 18 | -------------------------------------------------------------------------------- /configs/Market1501/AGW_R50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-AGW.yml" 2 | 3 | MODEL: 4 | HEADS: 5 | NUM_CLASSES: 751 6 | 7 | 8 | DATASETS: 9 | NAMES: ("Market1501",) 10 | TESTS: ("Market1501",) 11 | 12 | OUTPUT_DIR: "logs/market1501/agw_R50" 13 | -------------------------------------------------------------------------------- /configs/Market1501/AGW_S50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-AGW.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | NAME: "build_resnest_backbone" 6 | 7 | HEADS: 8 | NECK_FEAT: "before" 9 | NUM_CLASSES: 751 10 | 11 | LOSSES: 12 | TRI: 13 | MARGIN: 0.3 14 | 15 | DATASETS: 16 | NAMES: ("Market1501",) 17 | TESTS: ("Market1501",) 18 | 19 | OUTPUT_DIR: "logs/market1501/agw_S50" 20 | -------------------------------------------------------------------------------- /configs/Market1501/bagtricks_R101-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-bagtricks.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | DEPTH: 101 6 | WITH_IBN: True 7 | PRETRAIN_PATH: "/home/liaoxingyu2/lxy/.cache/torch/checkpoints/resnet101_ibn_a.pth.tar" 8 | 9 | HEADS: 10 | NUM_CLASSES: 751 11 | 12 | 13 | DATASETS: 14 | NAMES: ("Market1501",) 15 | TESTS: ("Market1501",) 16 | 17 | OUTPUT_DIR: "logs/market1501/bagtricks_R101-ibn" 18 | -------------------------------------------------------------------------------- /configs/Market1501/bagtricks_R50-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-bagtricks.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | WITH_IBN: True 6 | PRETRAIN_PATH: "/home/liaoxingyu2/lxy/.cache/torch/checkpoints/resnet50_ibn_a.pth.tar" 7 | 8 | HEADS: 9 | NUM_CLASSES: 751 10 | 11 | 12 | DATASETS: 13 | NAMES: ("Market1501",) 14 | TESTS: ("Market1501",) 15 | 16 | OUTPUT_DIR: "logs/market1501/bagtricks_R50-ibn" 17 | -------------------------------------------------------------------------------- /configs/Market1501/bagtricks_R50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-bagtricks.yml" 2 | 3 | MODEL: 4 | HEADS: 5 | NUM_CLASSES: 751 6 | 7 | 8 | DATASETS: 9 | NAMES: ("Market1501",) 10 | TESTS: ("Market1501",) 11 | 12 | 13 | OUTPUT_DIR: "logs/market1501/bagtricks_R50" 14 | -------------------------------------------------------------------------------- /configs/Market1501/bagtricks_S50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-bagtricks.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | NAME: "build_resnest_backbone" 6 | 7 | HEADS: 8 | NUM_CLASSES: 751 9 | 10 | 11 | DATASETS: 12 | NAMES: ("Market1501",) 13 | TESTS: ("Market1501",) 14 | 15 | OUTPUT_DIR: "logs/market1501/bagtricks_S50" 16 | -------------------------------------------------------------------------------- /configs/Market1501/mgn_R50-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-MGN.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | PRETRAIN_PATH: "/home/liaoxingyu2/lxy/.cache/torch/checkpoints/resnet50_ibn_a.pth.tar" 6 | HEADS: 7 | NUM_CLASSES: 751 8 | 9 | DATASETS: 10 | NAMES: ("Market1501",) 11 | TESTS: ("Market1501",) 12 | 13 | 14 | OUTPUT_DIR: "logs/market/mgn_R50-ibn" 15 | -------------------------------------------------------------------------------- /configs/Market1501/sbs_R101-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-Strongerbaseline.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | DEPTH: 101 6 | WITH_IBN: True 7 | PRETRAIN_PATH: "/home/liaoxingyu2/lxy/.cache/torch/checkpoints/resnet101_ibn_a.pth.tar" 8 | 9 | HEADS: 10 | NUM_CLASSES: 751 11 | 12 | DATASETS: 13 | NAMES: ("Market1501",) 14 | TESTS: ("Market1501",) 15 | 16 | TEST: 17 | PRECISE_BN: 18 | DATASET: 'Market1501' 19 | 20 | OUTPUT_DIR: "logs/market1501/sbs-R101-ibn" 21 | -------------------------------------------------------------------------------- /configs/Market1501/sbs_R50-ibn.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-Strongerbaseline.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | WITH_IBN: True 6 | PRETRAIN_PATH: "/home/liaoxingyu2/lxy/.cache/torch/checkpoints/resnet50_ibn_a.pth.tar" 7 | 8 | HEADS: 9 | NUM_CLASSES: 751 10 | 11 | DATASETS: 12 | NAMES: ("Market1501",) 13 | TESTS: ("Market1501",) 14 | 15 | TEST: 16 | EVAL_PERIOD: 2000 17 | PRECISE_BN: 18 | DATASET: 'Market1501' 19 | 20 | OUTPUT_DIR: "logs/market1501/sbs_R50-ibn" 21 | -------------------------------------------------------------------------------- /configs/Market1501/sbs_R50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-Strongerbaseline.yml" 2 | 3 | MODEL: 4 | HEADS: 5 | NUM_CLASSES: 751 6 | 7 | DATASETS: 8 | NAMES: ("Market1501",) 9 | TESTS: ("Market1501",) 10 | 11 | TEST: 12 | PRECISE_BN: 13 | DATASET: 'Market1501' 14 | 15 | OUTPUT_DIR: "logs/market1501/sbs_R50" 16 | -------------------------------------------------------------------------------- /configs/Market1501/sbs_S50.yml: -------------------------------------------------------------------------------- 1 | _BASE_: "../Base-Strongerbaseline.yml" 2 | 3 | MODEL: 4 | BACKBONE: 5 | NAME: "build_resnest_backbone" 6 | 7 | HEADS: 8 | NUM_CLASSES: 751 9 | 10 | LOSSES: 11 | TRI: 12 | MARGIN: 0.3 13 | 14 | DATASETS: 15 | NAMES: ("Market1501",) 16 | TESTS: ("Market1501",) 17 | 18 | TEST: 19 | PRECISE_BN: 20 | DATASET: 'Market1501' 21 | 22 | OUTPUT_DIR: "logs/market1501/sbs_S50" 23 | -------------------------------------------------------------------------------- /demo/README.md: -------------------------------------------------------------------------------- 1 | # FastReID Demo 2 | 3 | We provide a command line tool to run a simple demo of builtin models. 4 | 5 | You can run this command to get cosine similarites between different images 6 | 7 | ```bash 8 | cd demo/ 9 | sh run_demo.sh 10 | ``` -------------------------------------------------------------------------------- /demo/demo.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | import argparse 8 | import glob 9 | import os 10 | import sys 11 | 12 | import cv2 13 | import numpy as np 14 | import tqdm 15 | from torch.backends import cudnn 16 | 17 | sys.path.append('..') 18 | 19 | from fastreid.config import get_cfg 20 | from predictor import FeatureExtractionDemo 21 | 22 | cudnn.benchmark = True 23 | 24 | 25 | def setup_cfg(args): 26 | # load config from file and command-line arguments 27 | cfg = get_cfg() 28 | cfg.merge_from_file(args.config_file) 29 | cfg.merge_from_list(args.opts) 30 | cfg.freeze() 31 | return cfg 32 | 33 | 34 | def get_parser(): 35 | parser = argparse.ArgumentParser(description="Feature extraction with reid models") 36 | parser.add_argument( 37 | "--config-file", 38 | metavar="FILE", 39 | help="path to config file", 40 | ) 41 | parser.add_argument( 42 | '--device', 43 | default='cuda: 1', 44 | help='CUDA device to use' 45 | ) 46 | parser.add_argument( 47 | '--parallel', 48 | action='store_true', 49 | help='If use multiprocess for feature extraction.' 50 | ) 51 | parser.add_argument( 52 | "--input", 53 | nargs="+", 54 | help="A list of space separated input images; " 55 | "or a single glob pattern such as 'directory/*.jpg'", 56 | ) 57 | parser.add_argument( 58 | "--opts", 59 | help="Modify config options using the command-line 'KEY VALUE' pairs", 60 | default=[], 61 | nargs=argparse.REMAINDER, 62 | ) 63 | return parser 64 | 65 | 66 | if __name__ == '__main__': 67 | args = get_parser().parse_args() 68 | cfg = setup_cfg(args) 69 | demo = FeatureExtractionDemo(cfg, device=args.device, parallel=args.parallel) 70 | 71 | feats = [] 72 | if args.input: 73 | if len(args.input) == 1: 74 | args.input = glob.glob(os.path.expanduser(args.input[0])) 75 | assert args.input, "The input path(s) was not found" 76 | for path in tqdm.tqdm(args.input): 77 | img = cv2.imread(path) 78 | feat = demo.run_on_image(img) 79 | feats.append(feat.numpy()) 80 | 81 | cos_sim = np.dot(feats[0], feats[1].T).item() 82 | 83 | print('cosine similarity of the first two images is {:.4f}'.format(cos_sim)) 84 | -------------------------------------------------------------------------------- /demo/plot_roc_with_pickle.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: xingyu liao 4 | @contact: liaoxingyu5@jd.com 5 | """ 6 | 7 | import matplotlib.pyplot as plt 8 | import sys 9 | 10 | sys.path.append('.') 11 | from fastreid.utils.visualizer import Visualizer 12 | 13 | if __name__ == "__main__": 14 | baseline_res = Visualizer.load_roc_info("logs/duke_vis/roc_info.pickle") 15 | mgn_res = Visualizer.load_roc_info("logs/mgn_duke_vis/roc_info.pickle") 16 | 17 | fig = Visualizer.plot_roc_curve(baseline_res['fpr'], baseline_res['tpr'], name='baseline') 18 | Visualizer.plot_roc_curve(mgn_res['fpr'], mgn_res['tpr'], name='mgn', fig=fig) 19 | plt.savefig('roc.jpg') 20 | 21 | fig = Visualizer.plot_distribution(baseline_res['pos'], baseline_res['neg'], name='baseline') 22 | Visualizer.plot_distribution(mgn_res['pos'], mgn_res['neg'], name='mgn', fig=fig) 23 | plt.savefig('dist.jpg') 24 | -------------------------------------------------------------------------------- /demo/run_demo.sh: -------------------------------------------------------------------------------- 1 | python demo/visualize_result.py --config-file 'logs/dukemtmc/mgn_R50-ibn/config.yaml' \ 2 | --parallel --vis-label --dataset-name 'DukeMTMC' --output 'logs/mgn_duke_vis' \ 3 | --opts MODEL.WEIGHTS "logs/dukemtmc/mgn_R50-ibn/model_final.pth" 4 | -------------------------------------------------------------------------------- /fastreid/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | 8 | __version__ = "0.1.0" -------------------------------------------------------------------------------- /fastreid/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/config/.defaults.py.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/config/.defaults.py.swp -------------------------------------------------------------------------------- /fastreid/config/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: l1aoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from .config import CfgNode, get_cfg 8 | from .defaults import _C as cfg 9 | -------------------------------------------------------------------------------- /fastreid/config/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/config/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/config/__pycache__/config.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/config/__pycache__/config.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/config/__pycache__/defaults.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/config/__pycache__/defaults.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: sherlock 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from .build import build_reid_train_loader, build_reid_test_loader 8 | from .build import data_prefetcher 9 | -------------------------------------------------------------------------------- /fastreid/data/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/__pycache__/build.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/__pycache__/build.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/__pycache__/common.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/__pycache__/common.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/__pycache__/data_utils.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/__pycache__/data_utils.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/build.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: l1aoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | import torch 8 | from torch._six import container_abcs, string_classes, int_classes 9 | from torch.utils.data import DataLoader 10 | 11 | from . import samplers 12 | from .common import CommDataset, data_prefetcher 13 | from .datasets import DATASET_REGISTRY 14 | from .transforms import build_transforms 15 | import pdb 16 | 17 | def build_reid_train_loader(cfg): 18 | train_transforms = build_transforms(cfg, is_train=True) 19 | 20 | train_items = list() 21 | for d in cfg.DATASETS.NAMES: 22 | #print(combineall=cfg.DATASETS.COMBINEALL) 23 | # pdb.set_trace() 24 | dataset = DATASET_REGISTRY.get(d)(combineall=cfg.DATASETS.COMBINEALL) 25 | dataset.show_train() 26 | train_items.extend(dataset.train) 27 | 28 | train_set = CommDataset(train_items, train_transforms, relabel=True) 29 | 30 | num_workers = cfg.DATALOADER.NUM_WORKERS 31 | batch_size = cfg.SOLVER.IMS_PER_BATCH 32 | num_instance = cfg.DATALOADER.NUM_INSTANCE 33 | 34 | if cfg.DATALOADER.PK_SAMPLER: 35 | data_sampler = samplers.RandomIdentitySampler(train_set.img_items, batch_size, num_instance) 36 | else: 37 | data_sampler = samplers.TrainingSampler(len(train_set)) 38 | batch_sampler = torch.utils.data.sampler.BatchSampler(data_sampler, batch_size, True) 39 | 40 | train_loader = torch.utils.data.DataLoader( 41 | train_set, 42 | num_workers=num_workers, 43 | batch_sampler=batch_sampler, 44 | collate_fn=fast_batch_collator, 45 | ) 46 | return data_prefetcher(cfg, train_loader) 47 | 48 | 49 | def build_reid_test_loader(cfg, dataset_name): 50 | test_transforms = build_transforms(cfg, is_train=False) 51 | 52 | dataset = DATASET_REGISTRY.get(dataset_name)() 53 | dataset.show_test() 54 | test_items = dataset.query + dataset.gallery 55 | 56 | test_set = CommDataset(test_items, test_transforms, relabel=False) 57 | 58 | num_workers = cfg.DATALOADER.NUM_WORKERS 59 | batch_size = cfg.TEST.IMS_PER_BATCH 60 | data_sampler = samplers.InferenceSampler(len(test_set)) 61 | batch_sampler = torch.utils.data.BatchSampler(data_sampler, batch_size, False) 62 | test_loader = DataLoader( 63 | test_set, 64 | batch_sampler=batch_sampler, 65 | num_workers=num_workers, 66 | collate_fn=fast_batch_collator) 67 | return data_prefetcher(cfg, test_loader), len(dataset.query) 68 | 69 | 70 | def trivial_batch_collator(batch): 71 | """ 72 | A batch collator that does nothing. 73 | """ 74 | return batch 75 | 76 | 77 | def fast_batch_collator(batched_inputs): 78 | """ 79 | A simple batch collator for most common reid tasks 80 | """ 81 | elem = batched_inputs[0] 82 | if isinstance(elem, torch.Tensor): 83 | out = torch.zeros((len(batched_inputs), *elem.size()), dtype=elem.dtype) 84 | for i, tensor in enumerate(batched_inputs): 85 | out[i] += tensor 86 | return out 87 | 88 | elif isinstance(elem, container_abcs.Mapping): 89 | return {key: fast_batch_collator([d[key] for d in batched_inputs]) for key in elem} 90 | 91 | elif isinstance(elem, float): 92 | return torch.tensor(batched_inputs, dtype=torch.float64) 93 | elif isinstance(elem, int_classes): 94 | return torch.tensor(batched_inputs) 95 | elif isinstance(elem, string_classes): 96 | return batched_inputs 97 | -------------------------------------------------------------------------------- /fastreid/data/common.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | import torch 8 | from torch.utils.data import Dataset 9 | 10 | from .data_utils import read_image 11 | 12 | 13 | class CommDataset(Dataset): 14 | """Image Person ReID Dataset""" 15 | 16 | def __init__(self, img_items, transform=None, relabel=True): 17 | self.transform = transform 18 | self.relabel = relabel 19 | 20 | self.pid_dict = {} 21 | if self.relabel: 22 | self.img_items = [] 23 | pids = set() 24 | for i, item in enumerate(img_items): 25 | pid = self.get_pids(item[0], item[1]) 26 | self.img_items.append((item[0], pid, item[2])) # replace pid 27 | pids.add(pid) 28 | self.pids = pids 29 | self.pid_dict = dict([(p, i) for i, p in enumerate(self.pids)]) 30 | else: 31 | self.img_items = img_items 32 | 33 | def __len__(self): 34 | return len(self.img_items) 35 | 36 | def __getitem__(self, index): 37 | img_path, pid, camid = self.img_items[index] 38 | img = read_image(img_path) 39 | if self.transform is not None: 40 | img = self.transform(img) 41 | if self.relabel: 42 | pid = self.pid_dict[pid] 43 | return { 44 | 'images': img, 45 | 'targets': pid, 46 | 'camid': camid, 47 | 'img_path': img_path 48 | } 49 | 50 | @staticmethod 51 | def get_pids(file_path, pid): 52 | """ Suitable for muilti-dataset training """ 53 | if 'cuhk03' in file_path: 54 | prefix = 'cuhk' 55 | else: 56 | prefix = file_path.split('/')[1] 57 | return prefix + '_' + str(pid) 58 | 59 | def update_pid_dict(self, pid_dict): 60 | self.pid_dict = pid_dict 61 | 62 | 63 | class data_prefetcher(): 64 | def __init__(self, cfg, loader): 65 | self.loader = loader 66 | self.loader_iter = iter(loader) 67 | 68 | # normalize 69 | assert len(cfg.MODEL.PIXEL_MEAN) == len(cfg.MODEL.PIXEL_STD) 70 | num_channels = len(cfg.MODEL.PIXEL_MEAN) 71 | self.mean = torch.tensor(cfg.MODEL.PIXEL_MEAN).view(1, num_channels, 1, 1) 72 | self.std = torch.tensor(cfg.MODEL.PIXEL_STD).view(1, num_channels, 1, 1) 73 | 74 | self.preload() 75 | 76 | def reset(self): 77 | self.loader_iter = iter(self.loader) 78 | self.preload() 79 | 80 | def preload(self): 81 | try: 82 | self.next_inputs = next(self.loader_iter) 83 | except StopIteration: 84 | self.next_inputs = None 85 | return 86 | 87 | self.next_inputs["images"].sub_(self.mean).div_(self.std) 88 | 89 | def next(self): 90 | inputs = self.next_inputs 91 | self.preload() 92 | return inputs 93 | -------------------------------------------------------------------------------- /fastreid/data/data_utils.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | import numpy as np 7 | from PIL import Image, ImageOps 8 | 9 | from fastreid.utils.file_io import PathManager 10 | 11 | 12 | def read_image(file_name, format=None): 13 | """ 14 | Read an image into the given format. 15 | Will apply rotation and flipping if the image has such exif information. 16 | Args: 17 | file_name (str): image file path 18 | format (str): one of the supported image modes in PIL, or "BGR" 19 | Returns: 20 | image (np.ndarray): an HWC image 21 | """ 22 | with PathManager.open(file_name, "rb") as f: 23 | image = Image.open(f) 24 | 25 | # capture and ignore this bug: https://github.com/python-pillow/Pillow/issues/3973 26 | try: 27 | image = ImageOps.exif_transpose(image) 28 | except Exception: 29 | pass 30 | 31 | if format is not None: 32 | # PIL only supports RGB, so convert to RGB and flip channels over below 33 | conversion_format = format 34 | if format == "BGR": 35 | conversion_format = "RGB" 36 | image = image.convert(conversion_format) 37 | image = np.asarray(image) 38 | if format == "BGR": 39 | # flip channels if needed 40 | image = image[:, :, ::-1] 41 | # PIL squeezes out the channel dimension for "L", so make it HWC 42 | if format == "L": 43 | image = np.expand_dims(image, -1) 44 | image = Image.fromarray(image) 45 | return image 46 | -------------------------------------------------------------------------------- /fastreid/data/datasets/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from ...utils.registry import Registry 8 | 9 | DATASET_REGISTRY = Registry("DATASET") 10 | DATASET_REGISTRY.__doc__ = """ 11 | Registry for datasets 12 | It must returns an instance of :class:`Backbone`. 13 | """ 14 | 15 | from .cuhk03 import CUHK03 16 | from .dukemtmcreid import DukeMTMC 17 | from .market1501 import Market1501 18 | from .msmt17 import MSMT17 19 | from .veri import VeRi 20 | from .vehicleid import VehicleID, SmallVehicleID, MediumVehicleID, LargeVehicleID 21 | from .veriwild import VeRiWild, SmallVeRiWild, MediumVeRiWild, LargeVeRiWild 22 | -------------------------------------------------------------------------------- /fastreid/data/datasets/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/datasets/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/datasets/__pycache__/bases.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/datasets/__pycache__/bases.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/datasets/__pycache__/cuhk03.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/datasets/__pycache__/cuhk03.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/datasets/__pycache__/dukemtmcreid.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/datasets/__pycache__/dukemtmcreid.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/datasets/__pycache__/market1501.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/datasets/__pycache__/market1501.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/datasets/__pycache__/msmt17.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/datasets/__pycache__/msmt17.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/datasets/__pycache__/vehicleid.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/datasets/__pycache__/vehicleid.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/datasets/__pycache__/veri.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/datasets/__pycache__/veri.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/datasets/__pycache__/veriwild.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/datasets/__pycache__/veriwild.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/datasets/dukemtmcreid.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: liaoxingyu2@jd.com 5 | """ 6 | 7 | import glob 8 | import os.path as osp 9 | import re 10 | 11 | from .bases import ImageDataset 12 | from ..datasets import DATASET_REGISTRY 13 | 14 | 15 | @DATASET_REGISTRY.register() 16 | class DukeMTMC(ImageDataset): 17 | """DukeMTMC-reID. 18 | 19 | Reference: 20 | - Ristani et al. Performance Measures and a Data Set for Multi-Target, Multi-Camera Tracking. ECCVW 2016. 21 | - Zheng et al. Unlabeled Samples Generated by GAN Improve the Person Re-identification Baseline in vitro. ICCV 2017. 22 | 23 | URL: ``_ 24 | 25 | Dataset statistics: 26 | - identities: 1404 (train + query). 27 | - images:16522 (train) + 2228 (query) + 17661 (gallery). 28 | - cameras: 8. 29 | """ 30 | dataset_dir = 'DukeMTMC-reID' 31 | dataset_url = 'http://vision.cs.duke.edu/DukeMTMC/data/misc/DukeMTMC-reID.zip' 32 | 33 | def __init__(self, root='datasets', **kwargs): 34 | # self.root = osp.abspath(osp.expanduser(root)) 35 | self.root = root 36 | self.dataset_dir = osp.join(self.root, self.dataset_dir) 37 | self.train_dir = osp.join(self.dataset_dir, 'bounding_box_train') 38 | self.query_dir = osp.join(self.dataset_dir, 'query') 39 | self.gallery_dir = osp.join(self.dataset_dir, 'bounding_box_test') 40 | 41 | required_files = [ 42 | self.dataset_dir, 43 | self.train_dir, 44 | self.query_dir, 45 | self.gallery_dir, 46 | ] 47 | self.check_before_run(required_files) 48 | 49 | train = self.process_dir(self.train_dir) 50 | query = self.process_dir(self.query_dir) 51 | gallery = self.process_dir(self.gallery_dir) 52 | 53 | super(DukeMTMC, self).__init__(train, query, gallery, **kwargs) 54 | 55 | def process_dir(self, dir_path): 56 | img_paths = glob.glob(osp.join(dir_path, '*.jpg')) 57 | pattern = re.compile(r'([-\d]+)_c(\d)') 58 | 59 | data = [] 60 | for img_path in img_paths: 61 | pid, camid = map(int, pattern.search(img_path).groups()) 62 | assert 1 <= camid <= 8 63 | camid -= 1 # index starts from 0 64 | data.append((img_path, pid, camid)) 65 | 66 | return data 67 | -------------------------------------------------------------------------------- /fastreid/data/datasets/market1501.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: sherlock 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | import glob 8 | import os.path as osp 9 | import re 10 | import warnings 11 | 12 | from .bases import ImageDataset 13 | from ..datasets import DATASET_REGISTRY 14 | 15 | 16 | @DATASET_REGISTRY.register() 17 | class Market1501(ImageDataset): 18 | """Market1501. 19 | 20 | Reference: 21 | Zheng et al. Scalable Person Re-identification: A Benchmark. ICCV 2015. 22 | 23 | URL: ``_ 24 | 25 | Dataset statistics: 26 | - identities: 1501 (+1 for background). 27 | - images: 12936 (train) + 3368 (query) + 15913 (gallery). 28 | """ 29 | _junk_pids = [0, -1] 30 | dataset_dir = '' 31 | dataset_url = 'http://188.138.127.15:81/Datasets/Market-1501-v15.09.15.zip' 32 | 33 | def __init__(self, root='datasets', market1501_500k=False, **kwargs): 34 | # self.root = osp.abspath(osp.expanduser(root)) 35 | self.root = root 36 | self.dataset_dir = osp.join(self.root, self.dataset_dir) 37 | 38 | # allow alternative directory structure 39 | self.data_dir = self.dataset_dir 40 | data_dir = osp.join(self.data_dir, 'Market-1501-v15.09.15') 41 | if osp.isdir(data_dir): 42 | self.data_dir = data_dir 43 | else: 44 | warnings.warn('The current data structure is deprecated. Please ' 45 | 'put data folders such as "bounding_box_train" under ' 46 | '"Market-1501-v15.09.15".') 47 | 48 | self.train_dir = osp.join(self.data_dir, 'bounding_box_train') 49 | self.query_dir = osp.join(self.data_dir, 'query') 50 | self.gallery_dir = osp.join(self.data_dir, 'bounding_box_test') 51 | self.extra_gallery_dir = osp.join(self.data_dir, 'images') 52 | self.market1501_500k = market1501_500k 53 | 54 | required_files = [ 55 | self.data_dir, 56 | self.train_dir, 57 | self.query_dir, 58 | self.gallery_dir, 59 | ] 60 | if self.market1501_500k: 61 | required_files.append(self.extra_gallery_dir) 62 | self.check_before_run(required_files) 63 | 64 | train = self.process_dir(self.train_dir) 65 | query = self.process_dir(self.query_dir) 66 | gallery = self.process_dir(self.gallery_dir) 67 | if self.market1501_500k: 68 | gallery += self.process_dir(self.extra_gallery_dir) 69 | 70 | super(Market1501, self).__init__(train, query, gallery, **kwargs) 71 | 72 | def process_dir(self, dir_path): 73 | img_paths = glob.glob(osp.join(dir_path, '*.jpg')) 74 | pattern = re.compile(r'([-\d]+)_c(\d)') 75 | 76 | data = [] 77 | for img_path in img_paths: 78 | pid, camid = map(int, pattern.search(img_path).groups()) 79 | if pid == -1: 80 | continue # junk images are just ignored 81 | assert 0 <= pid <= 1501 # pid == 0 means background 82 | assert 1 <= camid <= 6 83 | camid -= 1 # index starts from 0 84 | data.append((img_path, pid, camid)) 85 | 86 | return data 87 | -------------------------------------------------------------------------------- /fastreid/data/datasets/msmt17.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: l1aoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | import sys 8 | import os 9 | import os.path as osp 10 | 11 | from .bases import ImageDataset 12 | from ..datasets import DATASET_REGISTRY 13 | ##### Log ##### 14 | # 22.01.2019 15 | # - add v2 16 | # - v1 and v2 differ in dir names 17 | # - note that faces in v2 are blurred 18 | TRAIN_DIR_KEY = 'train_dir' 19 | TEST_DIR_KEY = 'test_dir' 20 | VERSION_DICT = { 21 | 'MSMT17_V1': { 22 | TRAIN_DIR_KEY: 'train', 23 | TEST_DIR_KEY: 'test', 24 | }, 25 | 'MSMT17_V2': { 26 | TRAIN_DIR_KEY: 'mask_train_v2', 27 | TEST_DIR_KEY: 'mask_test_v2', 28 | } 29 | } 30 | 31 | 32 | @DATASET_REGISTRY.register() 33 | class MSMT17(ImageDataset): 34 | """MSMT17. 35 | Reference: 36 | Wei et al. Person Transfer GAN to Bridge Domain Gap for Person Re-Identification. CVPR 2018. 37 | URL: ``_ 38 | 39 | Dataset statistics: 40 | - identities: 4101. 41 | - images: 32621 (train) + 11659 (query) + 82161 (gallery). 42 | - cameras: 15. 43 | """ 44 | # dataset_dir = 'MSMT17_V2' 45 | dataset_url = None 46 | 47 | def __init__(self, root='datasets', **kwargs): 48 | self.root = root 49 | self.dataset_dir = self.root 50 | 51 | has_main_dir = False 52 | for main_dir in VERSION_DICT: 53 | if osp.exists(osp.join(self.dataset_dir, main_dir)): 54 | train_dir = VERSION_DICT[main_dir][TRAIN_DIR_KEY] 55 | test_dir = VERSION_DICT[main_dir][TEST_DIR_KEY] 56 | has_main_dir = True 57 | break 58 | assert has_main_dir, 'Dataset folder not found' 59 | 60 | self.train_dir = osp.join(self.dataset_dir, main_dir, train_dir) 61 | self.test_dir = osp.join(self.dataset_dir, main_dir, test_dir) 62 | self.list_train_path = osp.join(self.dataset_dir, main_dir, 'list_train.txt') 63 | self.list_val_path = osp.join(self.dataset_dir, main_dir, 'list_val.txt') 64 | self.list_query_path = osp.join(self.dataset_dir, main_dir, 'list_query.txt') 65 | self.list_gallery_path = osp.join(self.dataset_dir, main_dir, 'list_gallery.txt') 66 | 67 | required_files = [ 68 | self.dataset_dir, 69 | self.train_dir, 70 | self.test_dir 71 | ] 72 | self.check_before_run(required_files) 73 | 74 | train = self.process_dir(self.train_dir, self.list_train_path) 75 | val = self.process_dir(self.train_dir, self.list_val_path) 76 | query = self.process_dir(self.test_dir, self.list_query_path) 77 | gallery = self.process_dir(self.test_dir, self.list_gallery_path) 78 | 79 | num_train_pids = self.get_num_pids(train) 80 | query_tmp = [] 81 | for img_path, pid, camid in query: 82 | query_tmp.append((img_path, pid+num_train_pids, camid)) 83 | del query 84 | query = query_tmp 85 | 86 | gallery_temp = [] 87 | for img_path, pid, camid in gallery: 88 | gallery_temp.append((img_path, pid+num_train_pids, camid)) 89 | del gallery 90 | gallery = gallery_temp 91 | 92 | # Note: to fairly compare with published methods on the conventional ReID setting, 93 | # do not add val images to the training set. 94 | if 'combineall' in kwargs and kwargs['combineall']: 95 | train += val 96 | 97 | super(MSMT17, self).__init__(train, query, gallery, **kwargs) 98 | 99 | def process_dir(self, dir_path, list_path): 100 | with open(list_path, 'r') as txt: 101 | lines = txt.readlines() 102 | 103 | data = [] 104 | 105 | for img_idx, img_info in enumerate(lines): 106 | img_path, pid = img_info.split(' ') 107 | pid = int(pid) # no need to relabel 108 | camid = int(img_path.split('_')[2]) - 1 # index starts from 0 109 | img_path = osp.join(dir_path, img_path) 110 | data.append((img_path, pid, camid)) 111 | 112 | return data -------------------------------------------------------------------------------- /fastreid/data/datasets/vehicleid.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: Jinkai Zheng 4 | @contact: 1315673509@qq.com 5 | """ 6 | 7 | import os.path as osp 8 | import random 9 | 10 | from .bases import ImageDataset 11 | from ..datasets import DATASET_REGISTRY 12 | 13 | 14 | @DATASET_REGISTRY.register() 15 | class VehicleID(ImageDataset): 16 | """VehicleID. 17 | 18 | Reference: 19 | Liu et al. Deep relative distance learning: Tell the difference between similar vehicles. CVPR 2016. 20 | 21 | URL: ``_ 22 | 23 | Train dataset statistics: 24 | - identities: 13164. 25 | - images: 113346. 26 | """ 27 | dataset_dir = 'vehicleid' 28 | 29 | def __init__(self, root='datasets', test_list='', **kwargs): 30 | self.dataset_dir = osp.join(root, self.dataset_dir) 31 | 32 | self.image_dir = osp.join(self.dataset_dir, 'image') 33 | self.train_list = osp.join(self.dataset_dir, 'train_test_split/train_list.txt') 34 | if test_list: 35 | self.test_list = test_list 36 | else: 37 | self.test_list = osp.join(self.dataset_dir, 'train_test_split/test_list_13164.txt') 38 | 39 | required_files = [ 40 | self.dataset_dir, 41 | self.image_dir, 42 | self.train_list, 43 | self.test_list, 44 | ] 45 | self.check_before_run(required_files) 46 | 47 | train = self.process_dir(self.train_list, is_train=True) 48 | query, gallery = self.process_dir(self.test_list, is_train=False) 49 | 50 | super(VehicleID, self).__init__(train, query, gallery, **kwargs) 51 | 52 | def process_dir(self, list_file, is_train=True): 53 | img_list_lines = open(list_file, 'r').readlines() 54 | 55 | dataset = [] 56 | for idx, line in enumerate(img_list_lines): 57 | line = line.strip() 58 | vid = line.split(' ')[1] 59 | imgid = line.split(' ')[0] 60 | img_path = osp.join(self.image_dir, imgid + '.jpg') 61 | dataset.append((img_path, int(vid), int(imgid))) 62 | 63 | random.shuffle(dataset) 64 | vid_container = set() 65 | if is_train: 66 | return dataset 67 | else: 68 | query = [] 69 | gallery = [] 70 | for sample in dataset: 71 | if sample[1] not in vid_container: 72 | vid_container.add(sample[1]) 73 | gallery.append(sample) 74 | else: 75 | query.append(sample) 76 | 77 | return query, gallery 78 | 79 | 80 | @DATASET_REGISTRY.register() 81 | class SmallVehicleID(VehicleID): 82 | """VehicleID. 83 | Small test dataset statistics: 84 | - identities: 800. 85 | - images: 6493. 86 | """ 87 | 88 | def __init__(self, root='datasets', **kwargs): 89 | self.dataset_dir = osp.join(root, self.dataset_dir) 90 | self.test_list = osp.join(self.dataset_dir, 'train_test_split/test_list_800.txt') 91 | 92 | super(SmallVehicleID, self).__init__(root, self.test_list, **kwargs) 93 | 94 | 95 | @DATASET_REGISTRY.register() 96 | class MediumVehicleID(VehicleID): 97 | """VehicleID. 98 | Medium test dataset statistics: 99 | - identities: 1600. 100 | - images: 13377. 101 | """ 102 | 103 | def __init__(self, root='datasets', **kwargs): 104 | self.dataset_dir = osp.join(root, self.dataset_dir) 105 | self.test_list = osp.join(self.dataset_dir, 'train_test_split/test_list_1600.txt') 106 | 107 | super(MediumVehicleID, self).__init__(root, self.test_list, **kwargs) 108 | 109 | 110 | @DATASET_REGISTRY.register() 111 | class LargeVehicleID(VehicleID): 112 | """VehicleID. 113 | Large test dataset statistics: 114 | - identities: 2400. 115 | - images: 19777. 116 | """ 117 | 118 | def __init__(self, root='datasets', **kwargs): 119 | self.dataset_dir = osp.join(root, self.dataset_dir) 120 | self.test_list = osp.join(self.dataset_dir, 'train_test_split/test_list_2400.txt') 121 | 122 | super(LargeVehicleID, self).__init__(root, self.test_list, **kwargs) 123 | -------------------------------------------------------------------------------- /fastreid/data/datasets/veri.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: Jinkai Zheng 4 | @contact: 1315673509@qq.com 5 | """ 6 | 7 | import glob 8 | import os.path as osp 9 | import re 10 | 11 | from .bases import ImageDataset 12 | from ..datasets import DATASET_REGISTRY 13 | 14 | 15 | @DATASET_REGISTRY.register() 16 | class VeRi(ImageDataset): 17 | """VeRi. 18 | 19 | Reference: 20 | Liu et al. A Deep Learning based Approach for Progressive Vehicle Re-Identification. ECCV 2016. 21 | 22 | URL: ``_ 23 | 24 | Dataset statistics: 25 | - identities: 775. 26 | - images: 37778 (train) + 1678 (query) + 11579 (gallery). 27 | """ 28 | dataset_dir = 'veri' 29 | 30 | def __init__(self, root='datasets', **kwargs): 31 | self.dataset_dir = osp.join(root, self.dataset_dir) 32 | 33 | self.train_dir = osp.join(self.dataset_dir, 'image_train') 34 | self.query_dir = osp.join(self.dataset_dir, 'image_query') 35 | self.gallery_dir = osp.join(self.dataset_dir, 'image_test') 36 | 37 | required_files = [ 38 | self.dataset_dir, 39 | self.train_dir, 40 | self.query_dir, 41 | self.gallery_dir, 42 | ] 43 | self.check_before_run(required_files) 44 | 45 | train = self.process_dir(self.train_dir) 46 | query = self.process_dir(self.query_dir) 47 | gallery = self.process_dir(self.gallery_dir) 48 | 49 | super(VeRi, self).__init__(train, query, gallery, **kwargs) 50 | 51 | def process_dir(self, dir_path): 52 | img_paths = glob.glob(osp.join(dir_path, '*.jpg')) 53 | pattern = re.compile(r'([\d]+)_c(\d\d\d)') 54 | 55 | data = [] 56 | for img_path in img_paths: 57 | pid, camid = map(int, pattern.search(img_path).groups()) 58 | if pid == -1: continue # junk images are just ignored 59 | assert 1 <= pid <= 776 60 | assert 1 <= camid <= 20 61 | camid -= 1 # index starts from 0 62 | data.append((img_path, pid, camid)) 63 | 64 | return data 65 | -------------------------------------------------------------------------------- /fastreid/data/samplers/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from .triplet_sampler import RandomIdentitySampler 8 | from .data_sampler import TrainingSampler, InferenceSampler 9 | -------------------------------------------------------------------------------- /fastreid/data/samplers/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/samplers/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/samplers/__pycache__/data_sampler.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/samplers/__pycache__/data_sampler.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/samplers/__pycache__/triplet_sampler.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/samplers/__pycache__/triplet_sampler.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/samplers/data_sampler.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: l1aoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | import itertools 7 | from typing import Optional 8 | 9 | import numpy as np 10 | from torch.utils.data import Sampler 11 | 12 | 13 | class TrainingSampler(Sampler): 14 | """ 15 | In training, we only care about the "infinite stream" of training data. 16 | So this sampler produces an infinite stream of indices and 17 | all workers cooperate to correctly shuffle the indices and sample different indices. 18 | The samplers in each worker effectively produces `indices[worker_id::num_workers]` 19 | where `indices` is an infinite stream of indices consisting of 20 | `shuffle(range(size)) + shuffle(range(size)) + ...` (if shuffle is True) 21 | or `range(size) + range(size) + ...` (if shuffle is False) 22 | """ 23 | 24 | def __init__(self, size: int, shuffle: bool = True, seed: Optional[int] = None): 25 | """ 26 | Args: 27 | size (int): the total number of data of the underlying dataset to sample from 28 | shuffle (bool): whether to shuffle the indices or not 29 | seed (int): the initial seed of the shuffle. Must be the same 30 | across all workers. If None, will use a random seed shared 31 | among workers (require synchronization among all workers). 32 | """ 33 | self._size = size 34 | assert size > 0 35 | self._shuffle = shuffle 36 | if seed is None: 37 | seed = np.random.randint(2 ** 31) 38 | self._seed = int(seed) 39 | 40 | def __iter__(self): 41 | yield from itertools.islice(self._infinite_indices(), 0, None, 1) 42 | 43 | def _infinite_indices(self): 44 | np.random.seed(self._seed) 45 | while True: 46 | if self._shuffle: 47 | yield from np.random.permutation(self._size) 48 | else: 49 | yield from np.arange(self._size) 50 | 51 | 52 | class InferenceSampler(Sampler): 53 | """ 54 | Produce indices for inference. 55 | Inference needs to run on the __exact__ set of samples, 56 | therefore when the total number of samples is not divisible by the number of workers, 57 | this sampler produces different number of samples on different workers. 58 | """ 59 | 60 | def __init__(self, size: int): 61 | """ 62 | Args: 63 | size (int): the total number of data of the underlying dataset to sample from 64 | """ 65 | self._size = size 66 | assert size > 0 67 | 68 | begin = 0 69 | end = self._size 70 | self._local_indices = range(begin, end) 71 | 72 | def __iter__(self): 73 | yield from self._local_indices 74 | 75 | def __len__(self): 76 | return len(self._local_indices) -------------------------------------------------------------------------------- /fastreid/data/samplers/triplet_sampler.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: liaoxingyu2@jd.com 5 | """ 6 | 7 | import random 8 | from collections import defaultdict 9 | 10 | import numpy as np 11 | import torch 12 | from torch.utils.data.sampler import Sampler 13 | 14 | 15 | def No_index(a, b): 16 | assert isinstance(a, list) 17 | return [i for i, j in enumerate(a) if j != b] 18 | 19 | 20 | class RandomIdentitySampler(Sampler): 21 | def __init__(self, data_source, batch_size, num_instances=4): 22 | self.data_source = data_source 23 | self.batch_size = batch_size 24 | self.num_instances = num_instances 25 | self.num_pids_per_batch = batch_size // self.num_instances 26 | 27 | self.index_pid = defaultdict(list) 28 | self.pid_cam = defaultdict(list) 29 | self.pid_index = defaultdict(list) 30 | 31 | for index, info in enumerate(data_source): 32 | pid = info[1] 33 | camid = info[2] 34 | self.index_pid[index] = pid 35 | self.pid_cam[pid].append(camid) 36 | self.pid_index[pid].append(index) 37 | 38 | self.pids = list(self.pid_index.keys()) 39 | self.num_identities = len(self.pids) 40 | 41 | self._seed = 0 42 | self._shuffle = True 43 | 44 | def __iter__(self): 45 | indices = self._infinite_indices() 46 | for kid in indices: 47 | i = random.choice(self.pid_index[self.pids[kid]]) 48 | _, i_pid, i_cam = self.data_source[i] 49 | ret = [i] 50 | pid_i = self.index_pid[i] 51 | cams = self.pid_cam[pid_i] 52 | index = self.pid_index[pid_i] 53 | select_cams = No_index(cams, i_cam) 54 | 55 | if select_cams: 56 | if len(select_cams) >= self.num_instances: 57 | cam_indexes = np.random.choice(select_cams, size=self.num_instances - 1, replace=False) 58 | else: 59 | cam_indexes = np.random.choice(select_cams, size=self.num_instances - 1, replace=True) 60 | for kk in cam_indexes: 61 | ret.append(index[kk]) 62 | else: 63 | select_indexes = No_index(index, i) 64 | if not select_indexes: 65 | # only one image for this identity 66 | ind_indexes = [0] * (self.num_instances - 1) 67 | elif len(select_indexes) >= self.num_instances: 68 | ind_indexes = np.random.choice(select_indexes, size=self.num_instances - 1, replace=False) 69 | else: 70 | ind_indexes = np.random.choice(select_indexes, size=self.num_instances - 1, replace=True) 71 | 72 | for kk in ind_indexes: 73 | ret.append(index[kk]) 74 | yield from ret 75 | 76 | def _infinite_indices(self): 77 | np.random.seed(self._seed) 78 | while True: 79 | if self._shuffle: 80 | identities = np.random.permutation(self.num_identities) 81 | else: 82 | identities = np.arange(self.num_identities) 83 | drop_indices = self.num_identities % self.num_pids_per_batch 84 | if drop_indices == 0: 85 | yield from identities 86 | yield from identities[:-drop_indices] 87 | 88 | -------------------------------------------------------------------------------- /fastreid/data/transforms/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: sherlock 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | 8 | from .build import build_transforms 9 | from .transforms import * 10 | from .autoaugment import * 11 | -------------------------------------------------------------------------------- /fastreid/data/transforms/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/transforms/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/transforms/__pycache__/autoaugment.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/transforms/__pycache__/autoaugment.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/transforms/__pycache__/build.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/transforms/__pycache__/build.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/transforms/__pycache__/functional.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/transforms/__pycache__/functional.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/transforms/__pycache__/transforms.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/data/transforms/__pycache__/transforms.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/data/transforms/build.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | import torchvision.transforms as T 8 | 9 | from .transforms import * 10 | from .autoaugment import * 11 | 12 | 13 | def build_transforms(cfg, is_train=True): 14 | res = [] 15 | 16 | if is_train: 17 | size_train = cfg.INPUT.SIZE_TRAIN 18 | 19 | # augmix augmentation 20 | do_augmix = cfg.INPUT.DO_AUGMIX 21 | 22 | # auto augmentation 23 | do_autoaug = cfg.INPUT.DO_AUTOAUG 24 | total_iter = cfg.SOLVER.MAX_ITER 25 | 26 | # horizontal filp 27 | do_flip = cfg.INPUT.DO_FLIP 28 | flip_prob = cfg.INPUT.FLIP_PROB 29 | 30 | # padding 31 | do_pad = cfg.INPUT.DO_PAD 32 | padding = cfg.INPUT.PADDING 33 | padding_mode = cfg.INPUT.PADDING_MODE 34 | 35 | # color jitter 36 | do_cj = cfg.INPUT.DO_CJ 37 | 38 | # random erasing 39 | do_rea = cfg.INPUT.REA.ENABLED 40 | rea_prob = cfg.INPUT.REA.PROB 41 | rea_mean = cfg.INPUT.REA.MEAN 42 | # random patch 43 | do_rpt = cfg.INPUT.RPT.ENABLED 44 | rpt_prob = cfg.INPUT.RPT.PROB 45 | 46 | if do_autoaug: 47 | res.append(ImageNetPolicy(total_iter)) 48 | res.append(T.Resize(size_train, interpolation=3)) 49 | if do_flip: 50 | res.append(T.RandomHorizontalFlip(p=flip_prob)) 51 | if do_pad: 52 | res.extend([T.Pad(padding, padding_mode=padding_mode), 53 | T.RandomCrop(size_train)]) 54 | if do_cj: 55 | res.append(T.ColorJitter(brightness=0.1, contrast=0.1, saturation=0.1, hue=0)) 56 | if do_augmix: 57 | res.append(AugMix()) 58 | if do_rea: 59 | res.append(RandomErasing(probability=rea_prob, mean=rea_mean)) 60 | if do_rpt: 61 | res.append(RandomPatch(prob_happen=rpt_prob)) 62 | else: 63 | size_test = cfg.INPUT.SIZE_TEST 64 | res.append(T.Resize(size_test, interpolation=3)) 65 | res.append(ToTensor()) 66 | return T.Compose(res) 67 | -------------------------------------------------------------------------------- /fastreid/engine/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | from .train_loop import * 7 | 8 | __all__ = [k for k in globals().keys() if not k.startswith("_")] 9 | 10 | 11 | # prefer to let hooks and defaults live in separate namespaces (therefore not in __all__) 12 | # but still make them available here 13 | from .hooks import * 14 | from .defaults import * 15 | -------------------------------------------------------------------------------- /fastreid/engine/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/engine/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/engine/__pycache__/defaults.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/engine/__pycache__/defaults.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/engine/__pycache__/hooks.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/engine/__pycache__/hooks.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/engine/__pycache__/train_loop.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/engine/__pycache__/train_loop.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/evaluation/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 2 | from .evaluator import DatasetEvaluator, inference_context, inference_on_dataset 3 | from .rank import evaluate_rank 4 | from .reid_evaluation import ReidEvaluator 5 | from .testing import print_csv_format, verify_results 6 | 7 | __all__ = [k for k in globals().keys() if not k.startswith("_")] 8 | -------------------------------------------------------------------------------- /fastreid/evaluation/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/evaluation/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/evaluation/__pycache__/evaluator.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/evaluation/__pycache__/evaluator.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/evaluation/__pycache__/query_expansion.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/evaluation/__pycache__/query_expansion.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/evaluation/__pycache__/rank.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/evaluation/__pycache__/rank.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/evaluation/__pycache__/reid_evaluation.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/evaluation/__pycache__/reid_evaluation.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/evaluation/__pycache__/rerank.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/evaluation/__pycache__/rerank.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/evaluation/__pycache__/roc.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/evaluation/__pycache__/roc.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/evaluation/__pycache__/testing.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/evaluation/__pycache__/testing.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/evaluation/query_expansion.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: xingyu liao 4 | @contact: liaoxingyu5@jd.com 5 | """ 6 | 7 | # based on 8 | # https://github.com/PyRetri/PyRetri/blob/master/pyretri/index/re_ranker/re_ranker_impl/query_expansion.py 9 | 10 | import numpy as np 11 | import torch 12 | import torch.nn.functional as F 13 | 14 | 15 | def aqe(query_feat: torch.tensor, gallery_feat: torch.tensor, 16 | qe_times: int = 1, qe_k: int = 10, alpha: float = 3.0): 17 | """ 18 | Combining the retrieved topk nearest neighbors with the original query and doing another retrieval. 19 | c.f. https://www.robots.ox.ac.uk/~vgg/publications/papers/chum07b.pdf 20 | Args : 21 | query_feat (torch.tensor): 22 | gallery_feat (torch.tensor): 23 | qe_times (int): number of query expansion times. 24 | qe_k (int): number of the neighbors to be combined. 25 | alpha (float): 26 | """ 27 | num_query = query_feat.shape[0] 28 | all_feat = torch.cat((query_feat, gallery_feat), dim=0) 29 | norm_feat = F.normalize(all_feat, p=2, dim=1) 30 | 31 | all_feat = all_feat.numpy() 32 | for i in range(qe_times): 33 | all_feat_list = [] 34 | sims = torch.mm(norm_feat, norm_feat.t()) 35 | sims = sims.data.cpu().numpy() 36 | for sim in sims: 37 | init_rank = np.argpartition(-sim, range(1, qe_k + 1)) 38 | weights = sim[init_rank[:qe_k]].reshape((-1, 1)) 39 | weights = np.power(weights, alpha) 40 | all_feat_list.append(np.mean(all_feat[init_rank[:qe_k], :] * weights, axis=0)) 41 | all_feat = np.stack(all_feat_list, axis=0) 42 | norm_feat = F.normalize(torch.from_numpy(all_feat), p=2, dim=1) 43 | 44 | query_feat = torch.from_numpy(all_feat[:num_query]) 45 | gallery_feat = torch.from_numpy(all_feat[num_query:]) 46 | return query_feat, gallery_feat 47 | -------------------------------------------------------------------------------- /fastreid/evaluation/rank_cylib/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | python3 setup.py build_ext --inplace 3 | rm -rf build 4 | clean: 5 | rm -rf build 6 | rm -f rank_cy.c *.so 7 | -------------------------------------------------------------------------------- /fastreid/evaluation/rank_cylib/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ -------------------------------------------------------------------------------- /fastreid/evaluation/rank_cylib/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/evaluation/rank_cylib/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/evaluation/rank_cylib/rank_cy.cpython-36m-x86_64-linux-gnu.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/evaluation/rank_cylib/rank_cy.cpython-36m-x86_64-linux-gnu.so -------------------------------------------------------------------------------- /fastreid/evaluation/rank_cylib/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | from distutils.extension import Extension 3 | 4 | import numpy as np 5 | from Cython.Build import cythonize 6 | 7 | 8 | def numpy_include(): 9 | try: 10 | numpy_include = np.get_include() 11 | except AttributeError: 12 | numpy_include = np.get_numpy_include() 13 | return numpy_include 14 | 15 | 16 | ext_modules = [ 17 | Extension( 18 | 'rank_cy', 19 | ['rank_cy.pyx'], 20 | include_dirs=[numpy_include()], 21 | ) 22 | ] 23 | 24 | setup( 25 | name='Cython-based reid evaluation code', 26 | ext_modules=cythonize(ext_modules) 27 | ) 28 | -------------------------------------------------------------------------------- /fastreid/evaluation/rank_cylib/test_cython.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import numpy as np 3 | import timeit 4 | import os.path as osp 5 | 6 | 7 | sys.path.insert(0, osp.dirname(osp.abspath(__file__)) + '/../../..') 8 | 9 | """ 10 | Test the speed of cython-based evaluation code. The speed improvements 11 | can be much bigger when using the real reid data, which contains a larger 12 | amount of query and gallery images. 13 | Note: you might encounter the following error: 14 | 'AssertionError: Error: all query identities do not appear in gallery'. 15 | This is normal because the inputs are random numbers. Just try again. 16 | """ 17 | 18 | print('*** Compare running time ***') 19 | 20 | setup = ''' 21 | import sys 22 | import os.path as osp 23 | import numpy as np 24 | sys.path.insert(0, osp.dirname(osp.abspath(__file__)) + '/../../..') 25 | from fastreid import evaluation 26 | num_q = 30 27 | num_g = 300 28 | max_rank = 5 29 | distmat = np.random.rand(num_q, num_g) * 20 30 | q_pids = np.random.randint(0, num_q, size=num_q) 31 | g_pids = np.random.randint(0, num_g, size=num_g) 32 | q_camids = np.random.randint(0, 5, size=num_q) 33 | g_camids = np.random.randint(0, 5, size=num_g) 34 | ''' 35 | 36 | # print('=> Using market1501\'s metric') 37 | # pytime = timeit.timeit( 38 | # 'evaluation.evaluate_rank(distmat, q_pids, g_pids, q_camids, g_camids, max_rank, use_cython=False)', 39 | # setup=setup, 40 | # number=20 41 | # ) 42 | # cytime = timeit.timeit( 43 | # 'evaluation.evaluate_rank(distmat, q_pids, g_pids, q_camids, g_camids, max_rank, use_cython=True)', 44 | # setup=setup, 45 | # number=20 46 | # ) 47 | # print('Python time: {} s'.format(pytime)) 48 | # print('Cython time: {} s'.format(cytime)) 49 | # print('Cython is {} times faster than python\n'.format(pytime / cytime)) 50 | # 51 | # print('=> Using cuhk03\'s metric') 52 | # pytime = timeit.timeit( 53 | # 'evaluation.evaluate_rank(distmat, q_pids, g_pids, q_camids, g_camids, max_rank, use_metric_cuhk03=True, use_cython=False)', 54 | # setup=setup, 55 | # number=20 56 | # ) 57 | # cytime = timeit.timeit( 58 | # 'evaluation.evaluate_rank(distmat, q_pids, g_pids, q_camids, g_camids, max_rank, use_metric_cuhk03=True, use_cython=True)', 59 | # setup=setup, 60 | # number=20 61 | # ) 62 | # print('Python time: {} s'.format(pytime)) 63 | # print('Cython time: {} s'.format(cytime)) 64 | # print('Cython is {} times faster than python\n'.format(pytime / cytime)) 65 | 66 | from fastreid.evaluation import evaluate_rank 67 | print("=> Check precision") 68 | num_q = 30 69 | num_g = 300 70 | max_rank = 5 71 | distmat = np.random.rand(num_q, num_g) * 20 72 | q_pids = np.random.randint(0, num_q, size=num_q) 73 | g_pids = np.random.randint(0, num_g, size=num_g) 74 | q_camids = np.random.randint(0, 5, size=num_q) 75 | g_camids = np.random.randint(0, 5, size=num_g) 76 | cmc, mAP, mINP = evaluate_rank(distmat, q_pids, g_pids, q_camids, g_camids, max_rank, use_cython=False) 77 | print("Python:\nmAP = {} \ncmc = {}\nmINP = {}".format(mAP, cmc, mINP)) 78 | cmc, mAP, mINP = evaluate_rank(distmat, q_pids, g_pids, q_camids, g_camids, max_rank, use_cython=True) 79 | print("Cython:\nmAP = {} \ncmc = {}\nmINP = {}".format(mAP, cmc, mINP)) 80 | -------------------------------------------------------------------------------- /fastreid/evaluation/reid_evaluation.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | import copy 7 | import logging 8 | from collections import OrderedDict 9 | 10 | import numpy as np 11 | import torch 12 | import torch.nn.functional as F 13 | 14 | from .evaluator import DatasetEvaluator 15 | from .query_expansion import aqe 16 | from .rank import evaluate_rank 17 | from .roc import evaluate_roc 18 | from .rerank import re_ranking 19 | 20 | logger = logging.getLogger(__name__) 21 | 22 | 23 | class ReidEvaluator(DatasetEvaluator): 24 | def __init__(self, cfg, num_query, output_dir=None): 25 | self.cfg = cfg 26 | self._num_query = num_query 27 | self._output_dir = output_dir 28 | 29 | self.features = [] 30 | self.pids = [] 31 | self.camids = [] 32 | 33 | def reset(self): 34 | self.features = [] 35 | self.pids = [] 36 | self.camids = [] 37 | 38 | def process(self, outputs): 39 | self.features.append(outputs[0].cpu()) 40 | self.pids.extend(outputs[1].cpu().numpy()) 41 | self.camids.extend(outputs[2].cpu().numpy()) 42 | 43 | @staticmethod 44 | def cal_dist(metric: str, query_feat: torch.tensor, gallery_feat: torch.tensor): 45 | assert metric in ["cosine", "euclidean"], "must choose from [cosine, euclidean], but got {}".format(metric) 46 | if metric == "cosine": 47 | query_feat = F.normalize(query_feat, dim=1) 48 | gallery_feat = F.normalize(gallery_feat, dim=1) 49 | dist = 1 - torch.mm(query_feat, gallery_feat.t()) 50 | else: 51 | m, n = query_feat.size(0), gallery_feat.size(0) 52 | xx = torch.pow(query_feat, 2).sum(1, keepdim=True).expand(m, n) 53 | yy = torch.pow(gallery_feat, 2).sum(1, keepdim=True).expand(n, m).t() 54 | dist = xx + yy 55 | dist.addmm_(1, -2, query_feat, gallery_feat.t()) 56 | dist = dist.clamp(min=1e-12).sqrt() # for numerical stability 57 | return dist.cpu().numpy() 58 | 59 | def evaluate(self): 60 | features = torch.cat(self.features, dim=0) 61 | 62 | # query feature, person ids and camera ids 63 | query_features = features[:self._num_query] 64 | query_pids = np.asarray(self.pids[:self._num_query]) 65 | query_camids = np.asarray(self.camids[:self._num_query]) 66 | 67 | # gallery features, person ids and camera ids 68 | gallery_features = features[self._num_query:] 69 | gallery_pids = np.asarray(self.pids[self._num_query:]) 70 | gallery_camids = np.asarray(self.camids[self._num_query:]) 71 | 72 | self._results = OrderedDict() 73 | 74 | if self.cfg.TEST.AQE.ENABLED: 75 | logger.info("Test with AQE setting") 76 | qe_time = self.cfg.TEST.AQE.QE_TIME 77 | qe_k = self.cfg.TEST.AQE.QE_K 78 | alpha = self.cfg.TEST.AQE.ALPHA 79 | query_features, gallery_features = aqe(query_features, gallery_features, qe_time, qe_k, alpha) 80 | 81 | dist = self.cal_dist(self.cfg.TEST.METRIC, query_features, gallery_features) 82 | 83 | if self.cfg.TEST.RERANK.ENABLED: 84 | logger.info("Test with rerank setting") 85 | k1 = self.cfg.TEST.RERANK.K1 86 | k2 = self.cfg.TEST.RERANK.K2 87 | lambda_value = self.cfg.TEST.RERANK.LAMBDA 88 | q_q_dist = self.cal_dist(self.cfg.TEST.METRIC, query_features, query_features) 89 | g_g_dist = self.cal_dist(self.cfg.TEST.METRIC, gallery_features, gallery_features) 90 | dist = re_ranking(dist, q_q_dist, g_g_dist, k1, k2, lambda_value) 91 | 92 | cmc, all_AP, all_INP = evaluate_rank(dist, query_pids, gallery_pids, query_camids, gallery_camids) 93 | mAP = np.mean(all_AP) 94 | mINP = np.mean(all_INP) 95 | for r in [1, 5, 10]: 96 | self._results['Rank-{}'.format(r)] = cmc[r - 1] 97 | self._results['mAP'] = mAP 98 | self._results['mINP'] = mINP 99 | 100 | tprs = evaluate_roc(dist, query_pids, gallery_pids, query_camids, gallery_camids) 101 | fprs = [1e-4, 1e-3, 1e-2] 102 | for i in range(len(fprs)): 103 | self._results["TPR@FPR={}".format(fprs[i])] = tprs[i] 104 | return copy.deepcopy(self._results) 105 | -------------------------------------------------------------------------------- /fastreid/evaluation/rerank.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | # based on: 4 | # https://github.com/zhunzhong07/person-re-ranking 5 | 6 | __all__ = ['re_ranking'] 7 | 8 | import numpy as np 9 | 10 | 11 | def re_ranking(q_g_dist, q_q_dist, g_g_dist, k1: int = 20, k2: int = 6, lambda_value: float = 0.3): 12 | original_dist = np.concatenate( 13 | [np.concatenate([q_q_dist, q_g_dist], axis=1), 14 | np.concatenate([q_g_dist.T, g_g_dist], axis=1)], 15 | axis=0) 16 | original_dist = np.power(original_dist, 2).astype(np.float32) 17 | original_dist = np.transpose(1. * original_dist / np.max(original_dist, axis=0)) 18 | V = np.zeros_like(original_dist).astype(np.float32) 19 | initial_rank = np.argsort(original_dist).astype(np.int32) 20 | 21 | query_num = q_g_dist.shape[0] 22 | gallery_num = q_g_dist.shape[0] + q_g_dist.shape[1] 23 | all_num = gallery_num 24 | 25 | for i in range(all_num): 26 | # k-reciprocal neighbors 27 | forward_k_neigh_index = initial_rank[i, :k1 + 1] 28 | backward_k_neigh_index = initial_rank[forward_k_neigh_index, :k1 + 1] 29 | fi = np.where(backward_k_neigh_index == i)[0] 30 | k_reciprocal_index = forward_k_neigh_index[fi] 31 | k_reciprocal_expansion_index = k_reciprocal_index 32 | for j in range(len(k_reciprocal_index)): 33 | candidate = k_reciprocal_index[j] 34 | candidate_forward_k_neigh_index = initial_rank[candidate, 35 | :int(np.around(k1 / 2.)) + 1] 36 | candidate_backward_k_neigh_index = initial_rank[candidate_forward_k_neigh_index, 37 | :int(np.around(k1 / 2.)) + 1] 38 | fi_candidate = np.where(candidate_backward_k_neigh_index == candidate)[0] 39 | candidate_k_reciprocal_index = candidate_forward_k_neigh_index[fi_candidate] 40 | if len(np.intersect1d(candidate_k_reciprocal_index, k_reciprocal_index)) > 2. / 3 * len( 41 | candidate_k_reciprocal_index): 42 | k_reciprocal_expansion_index = np.append(k_reciprocal_expansion_index, candidate_k_reciprocal_index) 43 | 44 | k_reciprocal_expansion_index = np.unique(k_reciprocal_expansion_index) 45 | weight = np.exp(-original_dist[i, k_reciprocal_expansion_index]) 46 | V[i, k_reciprocal_expansion_index] = 1. * weight / np.sum(weight) 47 | original_dist = original_dist[:query_num, ] 48 | if k2 != 1: 49 | V_qe = np.zeros_like(V, dtype=np.float32) 50 | for i in range(all_num): 51 | V_qe[i, :] = np.mean(V[initial_rank[i, :k2], :], axis=0) 52 | V = V_qe 53 | del V_qe 54 | del initial_rank 55 | invIndex = [] 56 | for i in range(gallery_num): 57 | invIndex.append(np.where(V[:, i] != 0)[0]) 58 | 59 | jaccard_dist = np.zeros_like(original_dist, dtype=np.float32) 60 | 61 | for i in range(query_num): 62 | temp_min = np.zeros(shape=[1, gallery_num], dtype=np.float32) 63 | indNonZero = np.where(V[i, :] != 0)[0] 64 | indImages = [invIndex[ind] for ind in indNonZero] 65 | for j in range(len(indNonZero)): 66 | temp_min[0, indImages[j]] = temp_min[0, indImages[j]] + np.minimum(V[i, indNonZero[j]], 67 | V[indImages[j], indNonZero[j]]) 68 | jaccard_dist[i] = 1 - temp_min / (2. - temp_min) 69 | 70 | final_dist = jaccard_dist * (1 - lambda_value) + original_dist * lambda_value 71 | del original_dist, V, jaccard_dist 72 | final_dist = final_dist[:query_num, query_num:] 73 | return final_dist 74 | -------------------------------------------------------------------------------- /fastreid/evaluation/roc.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: l1aoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | import numpy as np 8 | from sklearn import metrics 9 | 10 | 11 | def evaluate_roc(distmat, q_pids, g_pids, q_camids, g_camids): 12 | r"""Evaluation with ROC curve. 13 | Key: for each query identity, its gallery images from the same camera view are discarded. 14 | 15 | Args: 16 | distmat (np.ndarray): cosine distance matrix 17 | """ 18 | num_q, num_g = distmat.shape 19 | 20 | indices = np.argsort(distmat, axis=1) 21 | matches = (g_pids[indices] == q_pids[:, np.newaxis]).astype(np.int32) 22 | 23 | pos = [] 24 | neg = [] 25 | for q_idx in range(num_q): 26 | # get query pid and camid 27 | q_pid = q_pids[q_idx] 28 | q_camid = q_camids[q_idx] 29 | 30 | # Remove gallery samples that have the same pid and camid with query 31 | order = indices[q_idx] 32 | remove = (g_pids[order] == q_pid) & (g_camids[order] == q_camid) 33 | keep = np.invert(remove) 34 | cmc = matches[q_idx][keep] 35 | sort_idx = order[keep] 36 | 37 | q_dist = distmat[q_idx] 38 | ind_pos = np.where(cmc == 1)[0] 39 | pos.extend(q_dist[sort_idx[ind_pos]]) 40 | 41 | ind_neg = np.where(cmc == 0)[0] 42 | neg.extend(q_dist[sort_idx[ind_neg]]) 43 | 44 | scores = np.hstack((pos, neg)) 45 | 46 | labels = np.hstack((np.zeros(len(pos)), np.ones(len(neg)))) 47 | fpr, tpr, thresholds = metrics.roc_curve(labels, scores) 48 | tprs = [] 49 | for i in [1e-4, 1e-3, 1e-2]: 50 | ind = np.argmin(np.abs(fpr-i)) 51 | tprs.append(tpr[ind]) 52 | return tprs 53 | -------------------------------------------------------------------------------- /fastreid/evaluation/testing.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 2 | import logging 3 | import pprint 4 | import sys 5 | from collections import Mapping, OrderedDict 6 | 7 | import numpy as np 8 | 9 | 10 | def print_csv_format(results): 11 | """ 12 | Print main metrics in a format similar to Detectron, 13 | so that they are easy to copypaste into a spreadsheet. 14 | Args: 15 | results (OrderedDict[dict]): task_name -> {metric -> score} 16 | """ 17 | assert isinstance(results, OrderedDict), results # unordered results cannot be properly printed 18 | logger = logging.getLogger(__name__) 19 | for task, res in results.items(): 20 | logger.info("Task: {}".format(task)) 21 | logger.info("{:.1%}".format(res)) 22 | 23 | 24 | def verify_results(cfg, results): 25 | """ 26 | Args: 27 | results (OrderedDict[dict]): task_name -> {metric -> score} 28 | Returns: 29 | bool: whether the verification succeeds or not 30 | """ 31 | expected_results = cfg.TEST.EXPECTED_RESULTS 32 | if not len(expected_results): 33 | return True 34 | 35 | ok = True 36 | for task, metric, expected, tolerance in expected_results: 37 | actual = results[task][metric] 38 | if not np.isfinite(actual): 39 | ok = False 40 | diff = abs(actual - expected) 41 | if diff > tolerance: 42 | ok = False 43 | 44 | logger = logging.getLogger(__name__) 45 | if not ok: 46 | logger.error("Result verification failed!") 47 | logger.error("Expected Results: " + str(expected_results)) 48 | logger.error("Actual Results: " + pprint.pformat(results)) 49 | 50 | sys.exit(1) 51 | else: 52 | logger.info("Results verification passed.") 53 | return ok 54 | 55 | 56 | def flatten_results_dict(results): 57 | """ 58 | Expand a hierarchical dict of scalars into a flat dict of scalars. 59 | If results[k1][k2][k3] = v, the returned dict will have the entry 60 | {"k1/k2/k3": v}. 61 | Args: 62 | results (dict): 63 | """ 64 | r = {} 65 | for k, v in results.items(): 66 | if isinstance(v, Mapping): 67 | v = flatten_results_dict(v) 68 | for kk, vv in v.items(): 69 | r[k + "/" + kk] = vv 70 | else: 71 | r[k] = v 72 | return r 73 | -------------------------------------------------------------------------------- /fastreid/export/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ -------------------------------------------------------------------------------- /fastreid/export/tf_modeling.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: l1aoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | from torch import nn 7 | from ..modeling.backbones import build_backbone 8 | from ..modeling.heads import build_reid_heads 9 | 10 | 11 | class TfMetaArch(nn.Module): 12 | def __init__(self, cfg): 13 | super().__init__() 14 | self.backbone = build_backbone(cfg) 15 | self.heads = build_reid_heads(cfg) 16 | 17 | def forward(self, x): 18 | global_feat = self.backbone(x) 19 | pred_features = self.heads(global_feat) 20 | return pred_features 21 | -------------------------------------------------------------------------------- /fastreid/layers/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | from torch import nn 7 | 8 | from .batch_drop import BatchDrop 9 | from .attention import * 10 | from .batch_norm import * 11 | from .context_block import ContextBlock 12 | from .non_local import Non_local 13 | from .se_layer import SELayer 14 | from .frn import FRN, TLU 15 | from .activation import * 16 | from .gem_pool import GeneralizedMeanPoolingP 17 | from .arcface import Arcface 18 | from .circle import Circle 19 | from .splat import SplAtConv2d 20 | 21 | 22 | class Flatten(nn.Module): 23 | def forward(self, input): 24 | return input.view(input.size(0), -1) 25 | -------------------------------------------------------------------------------- /fastreid/layers/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/layers/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/layers/__pycache__/activation.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/layers/__pycache__/activation.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/layers/__pycache__/arcface.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/layers/__pycache__/arcface.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/layers/__pycache__/attention.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/layers/__pycache__/attention.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/layers/__pycache__/batch_drop.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/layers/__pycache__/batch_drop.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/layers/__pycache__/batch_norm.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/layers/__pycache__/batch_norm.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/layers/__pycache__/circle.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/layers/__pycache__/circle.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/layers/__pycache__/context_block.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/layers/__pycache__/context_block.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/layers/__pycache__/frn.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/layers/__pycache__/frn.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/layers/__pycache__/gem_pool.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/layers/__pycache__/gem_pool.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/layers/__pycache__/non_local.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/layers/__pycache__/non_local.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/layers/__pycache__/se_layer.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/layers/__pycache__/se_layer.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/layers/__pycache__/splat.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/layers/__pycache__/splat.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/layers/activation.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: xingyu liao 4 | @contact: liaoxingyu5@jd.com 5 | """ 6 | 7 | import math 8 | 9 | import torch 10 | import torch.nn as nn 11 | import torch.nn.functional as F 12 | 13 | __all__ = [ 14 | 'Mish', 15 | 'Swish', 16 | 'MemoryEfficientSwish', 17 | 'GELU'] 18 | 19 | 20 | class Mish(nn.Module): 21 | def __init__(self): 22 | super().__init__() 23 | 24 | def forward(self, x): 25 | # inlining this saves 1 second per epoch (V100 GPU) vs having a temp x and then returning x(!) 26 | return x * (torch.tanh(F.softplus(x))) 27 | 28 | 29 | class Swish(nn.Module): 30 | def forward(self, x): 31 | return x * torch.sigmoid(x) 32 | 33 | 34 | class SwishImplementation(torch.autograd.Function): 35 | @staticmethod 36 | def forward(ctx, i): 37 | result = i * torch.sigmoid(i) 38 | ctx.save_for_backward(i) 39 | return result 40 | 41 | @staticmethod 42 | def backward(ctx, grad_output): 43 | i = ctx.saved_variables[0] 44 | sigmoid_i = torch.sigmoid(i) 45 | return grad_output * (sigmoid_i * (1 + i * (1 - sigmoid_i))) 46 | 47 | 48 | class MemoryEfficientSwish(nn.Module): 49 | def forward(self, x): 50 | return SwishImplementation.apply(x) 51 | 52 | 53 | class GELU(nn.Module): 54 | """ 55 | Paper Section 3.4, last paragraph notice that BERT used the GELU instead of RELU 56 | """ 57 | 58 | def forward(self, x): 59 | return 0.5 * x * (1 + torch.tanh(math.sqrt(2 / math.pi) * (x + 0.044715 * torch.pow(x, 3)))) 60 | -------------------------------------------------------------------------------- /fastreid/layers/arcface.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | import math 8 | 9 | import torch 10 | import torch.nn as nn 11 | import torch.nn.functional as F 12 | from torch.nn import Parameter 13 | 14 | from fastreid.utils.one_hot import one_hot 15 | 16 | 17 | class Arcface(nn.Module): 18 | def __init__(self, cfg, in_feat): 19 | super().__init__() 20 | self._num_classes = cfg.MODEL.HEADS.NUM_CLASSES 21 | self._s = cfg.MODEL.HEADS.SCALE 22 | self._m = cfg.MODEL.HEADS.MARGIN 23 | 24 | self.weight = Parameter(torch.Tensor(self._num_classes, in_feat)) 25 | self.reset_parameters() 26 | 27 | def reset_parameters(self): 28 | nn.init.kaiming_uniform_(self.weight, a=math.sqrt(5)) 29 | 30 | def forward(self, features, targets): 31 | # get cos(theta) 32 | cosine = F.linear(F.normalize(features), F.normalize(self.weight)) 33 | 34 | # add margin 35 | theta = torch.acos(torch.clamp(cosine, -1.0 + 1e-7, 1.0 - 1e-7)) 36 | 37 | phi = torch.cos(theta + self._m) 38 | 39 | # --------------------------- convert label to one-hot --------------------------- 40 | targets = one_hot(targets, self._num_classes) 41 | pred_class_logits = targets * phi + (1.0 - targets) * cosine 42 | 43 | # logits re-scale 44 | pred_class_logits *= self._s 45 | 46 | return pred_class_logits 47 | -------------------------------------------------------------------------------- /fastreid/layers/batch_drop.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | import random 8 | 9 | from torch import nn 10 | 11 | 12 | class BatchDrop(nn.Module): 13 | """ref: https://github.com/daizuozhuo/batch-dropblock-network/blob/master/models/networks.py 14 | batch drop mask 15 | """ 16 | 17 | def __init__(self, h_ratio, w_ratio): 18 | super(BatchDrop, self).__init__() 19 | self.h_ratio = h_ratio 20 | self.w_ratio = w_ratio 21 | 22 | def forward(self, x): 23 | if self.training: 24 | h, w = x.size()[-2:] 25 | rh = round(self.h_ratio * h) 26 | rw = round(self.w_ratio * w) 27 | sx = random.randint(0, h - rh) 28 | sy = random.randint(0, w - rw) 29 | mask = x.new_ones(x.size()) 30 | mask[:, :, sx:sx + rh, sy:sy + rw] = 0 31 | x = x * mask 32 | return x 33 | -------------------------------------------------------------------------------- /fastreid/layers/circle.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | import math 8 | 9 | import torch 10 | import torch.nn as nn 11 | import torch.nn.functional as F 12 | from torch.nn import Parameter 13 | 14 | from fastreid.utils.one_hot import one_hot 15 | 16 | 17 | class Circle(nn.Module): 18 | def __init__(self, cfg, in_feat): 19 | super().__init__() 20 | self._num_classes = cfg.MODEL.HEADS.NUM_CLASSES 21 | self._s = cfg.MODEL.HEADS.SCALE 22 | self._m = cfg.MODEL.HEADS.MARGIN 23 | 24 | self.weight = Parameter(torch.Tensor(self._num_classes, in_feat)) 25 | self.reset_parameters() 26 | 27 | def reset_parameters(self): 28 | nn.init.kaiming_uniform_(self.weight, a=math.sqrt(5)) 29 | 30 | def forward(self, features, targets): 31 | sim_mat = F.linear(F.normalize(features), F.normalize(self.weight)) 32 | alpha_p = F.relu(-sim_mat.detach() + 1 + self._m) 33 | alpha_n = F.relu(sim_mat.detach() + self._m) 34 | delta_p = 1 - self._m 35 | delta_n = self._m 36 | 37 | s_p = self._s * alpha_p * (sim_mat - delta_p) 38 | s_n = self._s * alpha_n * (sim_mat - delta_n) 39 | 40 | targets = one_hot(targets, self._num_classes) 41 | 42 | pred_class_logits = targets * s_p + (1.0 - targets) * s_n 43 | 44 | return pred_class_logits 45 | -------------------------------------------------------------------------------- /fastreid/layers/gem_pool.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: l1aoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | import torch 8 | import torch.nn.functional as F 9 | from torch import nn 10 | 11 | 12 | class GeneralizedMeanPooling(nn.Module): 13 | r"""Applies a 2D power-average adaptive pooling over an input signal composed of several input planes. 14 | The function computed is: :math:`f(X) = pow(sum(pow(X, p)), 1/p)` 15 | - At p = infinity, one gets Max Pooling 16 | - At p = 1, one gets Average Pooling 17 | The output is of size H x W, for any input size. 18 | The number of output features is equal to the number of input planes. 19 | Args: 20 | output_size: the target output size of the image of the form H x W. 21 | Can be a tuple (H, W) or a single H for a square image H x H 22 | H and W can be either a ``int``, or ``None`` which means the size will 23 | be the same as that of the input. 24 | """ 25 | 26 | def __init__(self, norm, output_size=1, eps=1e-6): 27 | super(GeneralizedMeanPooling, self).__init__() 28 | assert norm > 0 29 | self.p = float(norm) 30 | self.output_size = output_size 31 | self.eps = eps 32 | 33 | def forward(self, x): 34 | x = x.clamp(min=self.eps).pow(self.p) 35 | return torch.nn.functional.adaptive_avg_pool2d(x, self.output_size).pow(1. / self.p) 36 | 37 | def __repr__(self): 38 | return self.__class__.__name__ + '(' \ 39 | + str(self.p) + ', ' \ 40 | + 'output_size=' + str(self.output_size) + ')' 41 | 42 | 43 | class GeneralizedMeanPoolingP(GeneralizedMeanPooling): 44 | """ Same, but norm is trainable 45 | """ 46 | 47 | def __init__(self, norm=3, output_size=1, eps=1e-6): 48 | super(GeneralizedMeanPoolingP, self).__init__(norm, output_size, eps) 49 | self.p = nn.Parameter(torch.ones(1) * norm) 50 | -------------------------------------------------------------------------------- /fastreid/layers/non_local.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | 4 | import torch 5 | from torch import nn 6 | from .batch_norm import get_norm 7 | 8 | 9 | class Non_local(nn.Module): 10 | def __init__(self, in_channels, bn_norm, num_splits, reduc_ratio=2): 11 | super(Non_local, self).__init__() 12 | 13 | self.in_channels = in_channels 14 | self.inter_channels = reduc_ratio // reduc_ratio 15 | 16 | self.g = nn.Conv2d(in_channels=self.in_channels, out_channels=self.inter_channels, 17 | kernel_size=1, stride=1, padding=0) 18 | 19 | self.W = nn.Sequential( 20 | nn.Conv2d(in_channels=self.inter_channels, out_channels=self.in_channels, 21 | kernel_size=1, stride=1, padding=0), 22 | get_norm(bn_norm, self.in_channels, num_splits), 23 | ) 24 | nn.init.constant_(self.W[1].weight, 0.0) 25 | nn.init.constant_(self.W[1].bias, 0.0) 26 | 27 | self.theta = nn.Conv2d(in_channels=self.in_channels, out_channels=self.inter_channels, 28 | kernel_size=1, stride=1, padding=0) 29 | 30 | self.phi = nn.Conv2d(in_channels=self.in_channels, out_channels=self.inter_channels, 31 | kernel_size=1, stride=1, padding=0) 32 | 33 | def forward(self, x): 34 | ''' 35 | :param x: (b, t, h, w) 36 | :return x: (b, t, h, w) 37 | ''' 38 | batch_size = x.size(0) 39 | g_x = self.g(x).view(batch_size, self.inter_channels, -1) 40 | g_x = g_x.permute(0, 2, 1) 41 | 42 | theta_x = self.theta(x).view(batch_size, self.inter_channels, -1) 43 | theta_x = theta_x.permute(0, 2, 1) 44 | phi_x = self.phi(x).view(batch_size, self.inter_channels, -1) 45 | f = torch.matmul(theta_x, phi_x) 46 | N = f.size(-1) 47 | f_div_C = f / N 48 | 49 | y = torch.matmul(f_div_C, g_x) 50 | y = y.permute(0, 2, 1).contiguous() 51 | y = y.view(batch_size, self.inter_channels, *x.size()[2:]) 52 | W_y = self.W(y) 53 | z = W_y + x 54 | return z 55 | -------------------------------------------------------------------------------- /fastreid/layers/se_layer.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from torch import nn 8 | 9 | 10 | class SELayer(nn.Module): 11 | def __init__(self, channel, reduction=16): 12 | super(SELayer, self).__init__() 13 | self.avg_pool = nn.AdaptiveAvgPool2d(1) 14 | self.fc = nn.Sequential( 15 | nn.Linear(channel, int(channel / reduction), bias=False), 16 | nn.ReLU(inplace=True), 17 | nn.Linear(int(channel / reduction), channel, bias=False), 18 | nn.Sigmoid() 19 | ) 20 | 21 | def forward(self, x): 22 | b, c, _, _ = x.size() 23 | y = self.avg_pool(x).view(b, c) 24 | y = self.fc(y).view(b, c, 1, 1) 25 | return x * y.expand_as(x) 26 | -------------------------------------------------------------------------------- /fastreid/layers/splat.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: xingyu liao 4 | @contact: liaoxingyu5@jd.com 5 | """ 6 | 7 | import torch 8 | import torch.nn.functional as F 9 | from torch import nn 10 | from torch.nn import Conv2d, ReLU 11 | from torch.nn.modules.utils import _pair 12 | from fastreid.layers import get_norm 13 | 14 | 15 | class SplAtConv2d(nn.Module): 16 | """Split-Attention Conv2d 17 | """ 18 | 19 | def __init__(self, in_channels, channels, kernel_size, stride=(1, 1), padding=(0, 0), 20 | dilation=(1, 1), groups=1, bias=True, 21 | radix=2, reduction_factor=4, 22 | rectify=False, rectify_avg=False, norm_layer=None, num_splits=1, 23 | dropblock_prob=0.0, **kwargs): 24 | super(SplAtConv2d, self).__init__() 25 | padding = _pair(padding) 26 | self.rectify = rectify and (padding[0] > 0 or padding[1] > 0) 27 | self.rectify_avg = rectify_avg 28 | inter_channels = max(in_channels * radix // reduction_factor, 32) 29 | self.radix = radix 30 | self.cardinality = groups 31 | self.channels = channels 32 | self.dropblock_prob = dropblock_prob 33 | if self.rectify: 34 | from rfconv import RFConv2d 35 | self.conv = RFConv2d(in_channels, channels * radix, kernel_size, stride, padding, dilation, 36 | groups=groups * radix, bias=bias, average_mode=rectify_avg, **kwargs) 37 | else: 38 | self.conv = Conv2d(in_channels, channels * radix, kernel_size, stride, padding, dilation, 39 | groups=groups * radix, bias=bias, **kwargs) 40 | self.use_bn = norm_layer is not None 41 | if self.use_bn: 42 | self.bn0 = get_norm(norm_layer, channels * radix, num_splits) 43 | self.relu = ReLU(inplace=True) 44 | self.fc1 = Conv2d(channels, inter_channels, 1, groups=self.cardinality) 45 | if self.use_bn: 46 | self.bn1 = get_norm(norm_layer, inter_channels, num_splits) 47 | self.fc2 = Conv2d(inter_channels, channels * radix, 1, groups=self.cardinality) 48 | 49 | self.rsoftmax = rSoftMax(radix, groups) 50 | 51 | def forward(self, x): 52 | x = self.conv(x) 53 | if self.use_bn: 54 | x = self.bn0(x) 55 | if self.dropblock_prob > 0.0: 56 | x = self.dropblock(x) 57 | x = self.relu(x) 58 | 59 | batch, rchannel = x.shape[:2] 60 | if self.radix > 1: 61 | splited = torch.split(x, rchannel // self.radix, dim=1) 62 | gap = sum(splited) 63 | else: 64 | gap = x 65 | gap = F.adaptive_avg_pool2d(gap, 1) 66 | gap = self.fc1(gap) 67 | 68 | if self.use_bn: 69 | gap = self.bn1(gap) 70 | gap = self.relu(gap) 71 | 72 | atten = self.fc2(gap) 73 | atten = self.rsoftmax(atten).view(batch, -1, 1, 1) 74 | 75 | if self.radix > 1: 76 | attens = torch.split(atten, rchannel // self.radix, dim=1) 77 | out = sum([att * split for (att, split) in zip(attens, splited)]) 78 | else: 79 | out = atten * x 80 | return out.contiguous() 81 | 82 | 83 | class rSoftMax(nn.Module): 84 | def __init__(self, radix, cardinality): 85 | super().__init__() 86 | self.radix = radix 87 | self.cardinality = cardinality 88 | 89 | def forward(self, x): 90 | batch = x.size(0) 91 | if self.radix > 1: 92 | x = x.view(batch, self.cardinality, self.radix, -1).transpose(1, 2) 93 | x = F.softmax(x, dim=1) 94 | x = x.reshape(batch, -1) 95 | else: 96 | x = torch.sigmoid(x) 97 | return x 98 | -------------------------------------------------------------------------------- /fastreid/layers/sync_bn/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # File : __init__.py 3 | # Author : Jiayuan Mao 4 | # Email : maojiayuan@gmail.com 5 | # Date : 27/01/2018 6 | # 7 | # This file is part of Synchronized-BatchNorm-PyTorch. 8 | # https://github.com/vacancy/Synchronized-BatchNorm-PyTorch 9 | # Distributed under MIT License. 10 | 11 | from .batchnorm import SynchronizedBatchNorm1d, SynchronizedBatchNorm2d, SynchronizedBatchNorm3d 12 | from .batchnorm import patch_sync_batchnorm, convert_model 13 | from .replicate import DataParallelWithCallback, patch_replication_callback 14 | -------------------------------------------------------------------------------- /fastreid/layers/sync_bn/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/layers/sync_bn/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/layers/sync_bn/__pycache__/batchnorm.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/layers/sync_bn/__pycache__/batchnorm.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/layers/sync_bn/__pycache__/comm.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/layers/sync_bn/__pycache__/comm.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/layers/sync_bn/__pycache__/replicate.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/layers/sync_bn/__pycache__/replicate.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/layers/sync_bn/batchnorm_reimpl.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # File : batchnorm_reimpl.py 4 | # Author : acgtyrant 5 | # Date : 11/01/2018 6 | # 7 | # This file is part of Synchronized-BatchNorm-PyTorch. 8 | # https://github.com/vacancy/Synchronized-BatchNorm-PyTorch 9 | # Distributed under MIT License. 10 | 11 | import torch 12 | import torch.nn as nn 13 | import torch.nn.init as init 14 | 15 | __all__ = ['BatchNorm2dReimpl'] 16 | 17 | 18 | class BatchNorm2dReimpl(nn.Module): 19 | """ 20 | A re-implementation of batch normalization, used for testing the numerical 21 | stability. 22 | 23 | Author: acgtyrant 24 | See also: 25 | https://github.com/vacancy/Synchronized-BatchNorm-PyTorch/issues/14 26 | """ 27 | def __init__(self, num_features, eps=1e-5, momentum=0.1): 28 | super().__init__() 29 | 30 | self.num_features = num_features 31 | self.eps = eps 32 | self.momentum = momentum 33 | self.weight = nn.Parameter(torch.empty(num_features)) 34 | self.bias = nn.Parameter(torch.empty(num_features)) 35 | self.register_buffer('running_mean', torch.zeros(num_features)) 36 | self.register_buffer('running_var', torch.ones(num_features)) 37 | self.reset_parameters() 38 | 39 | def reset_running_stats(self): 40 | self.running_mean.zero_() 41 | self.running_var.fill_(1) 42 | 43 | def reset_parameters(self): 44 | self.reset_running_stats() 45 | init.uniform_(self.weight) 46 | init.zeros_(self.bias) 47 | 48 | def forward(self, input_): 49 | batchsize, channels, height, width = input_.size() 50 | numel = batchsize * height * width 51 | input_ = input_.permute(1, 0, 2, 3).contiguous().view(channels, numel) 52 | sum_ = input_.sum(1) 53 | sum_of_square = input_.pow(2).sum(1) 54 | mean = sum_ / numel 55 | sumvar = sum_of_square - sum_ * mean 56 | 57 | self.running_mean = ( 58 | (1 - self.momentum) * self.running_mean 59 | + self.momentum * mean.detach() 60 | ) 61 | unbias_var = sumvar / (numel - 1) 62 | self.running_var = ( 63 | (1 - self.momentum) * self.running_var 64 | + self.momentum * unbias_var.detach() 65 | ) 66 | 67 | bias_var = sumvar / numel 68 | inv_std = 1 / (bias_var + self.eps).pow(0.5) 69 | output = ( 70 | (input_ - mean.unsqueeze(1)) * inv_std.unsqueeze(1) * 71 | self.weight.unsqueeze(1) + self.bias.unsqueeze(1)) 72 | 73 | return output.view(channels, batchsize, height, width).permute(1, 0, 2, 3).contiguous() 74 | 75 | -------------------------------------------------------------------------------- /fastreid/layers/sync_bn/replicate.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # File : replicate.py 3 | # Author : Jiayuan Mao 4 | # Email : maojiayuan@gmail.com 5 | # Date : 27/01/2018 6 | # 7 | # This file is part of Synchronized-BatchNorm-PyTorch. 8 | # https://github.com/vacancy/Synchronized-BatchNorm-PyTorch 9 | # Distributed under MIT License. 10 | 11 | import functools 12 | 13 | from torch.nn.parallel.data_parallel import DataParallel 14 | 15 | __all__ = [ 16 | 'CallbackContext', 17 | 'execute_replication_callbacks', 18 | 'DataParallelWithCallback', 19 | 'patch_replication_callback' 20 | ] 21 | 22 | 23 | class CallbackContext(object): 24 | pass 25 | 26 | 27 | def execute_replication_callbacks(modules): 28 | """ 29 | Execute an replication callback `__data_parallel_replicate__` on each module created by original replication. 30 | 31 | The callback will be invoked with arguments `__data_parallel_replicate__(ctx, copy_id)` 32 | 33 | Note that, as all modules are isomorphism, we assign each sub-module with a context 34 | (shared among multiple copies of this module on different devices). 35 | Through this context, different copies can share some information. 36 | 37 | We guarantee that the callback on the master copy (the first copy) will be called ahead of calling the callback 38 | of any slave copies. 39 | """ 40 | master_copy = modules[0] 41 | nr_modules = len(list(master_copy.modules())) 42 | ctxs = [CallbackContext() for _ in range(nr_modules)] 43 | 44 | for i, module in enumerate(modules): 45 | for j, m in enumerate(module.modules()): 46 | if hasattr(m, '__data_parallel_replicate__'): 47 | m.__data_parallel_replicate__(ctxs[j], i) 48 | 49 | 50 | class DataParallelWithCallback(DataParallel): 51 | """ 52 | Data Parallel with a replication callback. 53 | 54 | An replication callback `__data_parallel_replicate__` of each module will be invoked after being created by 55 | original `replicate` function. 56 | The callback will be invoked with arguments `__data_parallel_replicate__(ctx, copy_id)` 57 | 58 | Examples: 59 | > sync_bn = SynchronizedBatchNorm1d(10, eps=1e-5, affine=False) 60 | > sync_bn = DataParallelWithCallback(sync_bn, device_ids=[0, 1]) 61 | # sync_bn.__data_parallel_replicate__ will be invoked. 62 | """ 63 | 64 | def replicate(self, module, device_ids): 65 | modules = super(DataParallelWithCallback, self).replicate(module, device_ids) 66 | execute_replication_callbacks(modules) 67 | return modules 68 | 69 | 70 | def patch_replication_callback(data_parallel): 71 | """ 72 | Monkey-patch an existing `DataParallel` object. Add the replication callback. 73 | Useful when you have customized `DataParallel` implementation. 74 | 75 | Examples: 76 | > sync_bn = SynchronizedBatchNorm1d(10, eps=1e-5, affine=False) 77 | > sync_bn = DataParallel(sync_bn, device_ids=[0, 1]) 78 | > patch_replication_callback(sync_bn) 79 | # this is equivalent to 80 | > sync_bn = SynchronizedBatchNorm1d(10, eps=1e-5, affine=False) 81 | > sync_bn = DataParallelWithCallback(sync_bn, device_ids=[0, 1]) 82 | """ 83 | 84 | assert isinstance(data_parallel, DataParallel) 85 | 86 | old_replicate = data_parallel.replicate 87 | 88 | @functools.wraps(old_replicate) 89 | def new_replicate(module, device_ids): 90 | modules = old_replicate(module, device_ids) 91 | execute_replication_callbacks(modules) 92 | return modules 93 | 94 | data_parallel.replicate = new_replicate 95 | -------------------------------------------------------------------------------- /fastreid/layers/sync_bn/unittest.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # File : unittest.py 3 | # Author : Jiayuan Mao 4 | # Email : maojiayuan@gmail.com 5 | # Date : 27/01/2018 6 | # 7 | # This file is part of Synchronized-BatchNorm-PyTorch. 8 | # https://github.com/vacancy/Synchronized-BatchNorm-PyTorch 9 | # Distributed under MIT License. 10 | 11 | import unittest 12 | import torch 13 | 14 | 15 | class TorchTestCase(unittest.TestCase): 16 | def assertTensorClose(self, x, y): 17 | adiff = float((x - y).abs().max()) 18 | if (y == 0).all(): 19 | rdiff = 'NaN' 20 | else: 21 | rdiff = float((adiff / y).abs().max()) 22 | 23 | message = ( 24 | 'Tensor close check failed\n' 25 | 'adiff={}\n' 26 | 'rdiff={}\n' 27 | ).format(adiff, rdiff) 28 | self.assertTrue(torch.allclose(x, y), message) 29 | 30 | -------------------------------------------------------------------------------- /fastreid/modeling/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: sherlock 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from .meta_arch import build_model 8 | -------------------------------------------------------------------------------- /fastreid/modeling/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/backbones/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from .build import build_backbone, BACKBONE_REGISTRY 8 | 9 | from .resnet import build_resnet_backbone 10 | from .osnet import build_osnet_backbone 11 | from .resnest import build_resnest_backbone 12 | from .resnext import build_resnext_backbone -------------------------------------------------------------------------------- /fastreid/modeling/backbones/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/backbones/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/backbones/__pycache__/build.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/backbones/__pycache__/build.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/backbones/__pycache__/osnet.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/backbones/__pycache__/osnet.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/backbones/__pycache__/resnest.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/backbones/__pycache__/resnest.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/backbones/__pycache__/resnet.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/backbones/__pycache__/resnet.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/backbones/__pycache__/resnext.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/backbones/__pycache__/resnext.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/backbones/build.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from ...utils.registry import Registry 8 | 9 | BACKBONE_REGISTRY = Registry("BACKBONE") 10 | BACKBONE_REGISTRY.__doc__ = """ 11 | Registry for backbones, which extract feature maps from images 12 | The registered object must be a callable that accepts two arguments: 13 | 1. A :class:`detectron2.config.CfgNode` 14 | 2. A :class:`detectron2.layers.ShapeSpec`, which contains the input shape specification. 15 | It must returns an instance of :class:`Backbone`. 16 | """ 17 | 18 | 19 | def build_backbone(cfg): 20 | """ 21 | Build a backbone from `cfg.MODEL.BACKBONE.NAME`. 22 | Returns: 23 | an instance of :class:`Backbone` 24 | """ 25 | 26 | backbone_name = cfg.MODEL.BACKBONE.NAME 27 | backbone = BACKBONE_REGISTRY.get(backbone_name)(cfg) 28 | return backbone 29 | -------------------------------------------------------------------------------- /fastreid/modeling/heads/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from .build import REID_HEADS_REGISTRY, build_reid_heads 8 | 9 | # import all the meta_arch, so they will be registered 10 | from .linear_head import LinearHead 11 | from .bnneck_head import BNneckHead 12 | -------------------------------------------------------------------------------- /fastreid/modeling/heads/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/heads/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/heads/__pycache__/bnneck_head.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/heads/__pycache__/bnneck_head.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/heads/__pycache__/build.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/heads/__pycache__/build.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/heads/__pycache__/linear_head.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/heads/__pycache__/linear_head.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/heads/bnneck_head.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from fastreid.layers import * 8 | from fastreid.utils.weight_init import weights_init_kaiming, weights_init_classifier 9 | from .build import REID_HEADS_REGISTRY 10 | 11 | 12 | @REID_HEADS_REGISTRY.register() 13 | class BNneckHead(nn.Module): 14 | def __init__(self, cfg, in_feat, num_classes, pool_layer=nn.AdaptiveAvgPool2d(1)): 15 | super().__init__() 16 | self.neck_feat = cfg.MODEL.HEADS.NECK_FEAT 17 | self.pool_layer = pool_layer 18 | 19 | self.bnneck = get_norm(cfg.MODEL.HEADS.NORM, in_feat, cfg.MODEL.HEADS.NORM_SPLIT, bias_freeze=True) 20 | self.bnneck.apply(weights_init_kaiming) 21 | 22 | # identity classification layer 23 | if cfg.MODEL.HEADS.CLS_LAYER == 'linear': 24 | self.classifier = nn.Linear(in_feat, num_classes, bias=False) 25 | self.classifier.apply(weights_init_classifier) 26 | elif cfg.MODEL.HEADS.CLS_LAYER == 'arcface': 27 | self.classifier = Arcface(cfg, in_feat) 28 | elif cfg.MODEL.HEADS.CLS_LAYER == 'circle': 29 | self.classifier = Circle(cfg, in_feat) 30 | else: 31 | self.classifier = nn.Linear(in_feat, num_classes, bias=False) 32 | self.classifier.apply(weights_init_classifier) 33 | 34 | def forward(self, features, targets=None): 35 | """ 36 | See :class:`ReIDHeads.forward`. 37 | """ 38 | global_feat = self.pool_layer(features) 39 | bn_feat = self.bnneck(global_feat) 40 | bn_feat = Flatten()(bn_feat) 41 | # Evaluation 42 | if not self.training: 43 | return bn_feat 44 | # Training 45 | try: 46 | pred_class_logits = self.classifier(bn_feat) 47 | except TypeError: 48 | pred_class_logits = self.classifier(bn_feat, targets) 49 | 50 | if self.neck_feat == "before": 51 | feat = Flatten()(global_feat) 52 | elif self.neck_feat == "after": 53 | feat = bn_feat 54 | else: 55 | raise KeyError("MODEL.HEADS.NECK_FEAT value is invalid, must choose from ('after' & 'before')") 56 | return pred_class_logits, feat, targets 57 | -------------------------------------------------------------------------------- /fastreid/modeling/heads/build.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from ...utils.registry import Registry 8 | 9 | REID_HEADS_REGISTRY = Registry("HEADS") 10 | REID_HEADS_REGISTRY.__doc__ = """ 11 | Registry for ROI heads in a generalized R-CNN model. 12 | ROIHeads take feature maps and region proposals, and 13 | perform per-region computation. 14 | The registered object will be called with `obj(cfg, input_shape)`. 15 | The call is expected to return an :class:`ROIHeads`. 16 | """ 17 | 18 | 19 | def build_reid_heads(cfg, in_feat, num_classes, pool_layer): 20 | """ 21 | Build REIDHeads defined by `cfg.MODEL.REID_HEADS.NAME`. 22 | """ 23 | head = cfg.MODEL.HEADS.NAME 24 | return REID_HEADS_REGISTRY.get(head)(cfg, in_feat, num_classes, pool_layer) 25 | -------------------------------------------------------------------------------- /fastreid/modeling/heads/linear_head.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from fastreid.layers import * 8 | from .build import REID_HEADS_REGISTRY 9 | 10 | 11 | @REID_HEADS_REGISTRY.register() 12 | class LinearHead(nn.Module): 13 | def __init__(self, cfg, in_feat, num_classes, pool_layer=nn.AdaptiveAvgPool2d(1)): 14 | super().__init__() 15 | self.pool_layer = pool_layer 16 | 17 | # identity classification layer 18 | if cfg.MODEL.HEADS.CLS_LAYER == 'linear': 19 | self.classifier = nn.Linear(in_feat, num_classes, bias=False) 20 | elif cfg.MODEL.HEADS.CLS_LAYER == 'arcface': 21 | self.classifier = Arcface(cfg, in_feat) 22 | elif cfg.MODEL.HEADS.CLS_LAYER == 'circle': 23 | self.classifier = Circle(cfg, in_feat) 24 | else: 25 | self.classifier = nn.Linear(in_feat, num_classes, bias=False) 26 | 27 | def forward(self, features, targets=None): 28 | """ 29 | See :class:`ReIDHeads.forward`. 30 | """ 31 | global_feat = self.pool_layer(features) 32 | global_feat = Flatten()(global_feat) 33 | if not self.training: 34 | return global_feat 35 | # training 36 | try: 37 | pred_class_logits = self.classifier(global_feat) 38 | except TypeError: 39 | pred_class_logits = self.classifier(global_feat, targets) 40 | return pred_class_logits, global_feat, targets 41 | -------------------------------------------------------------------------------- /fastreid/modeling/heads/reduction_head.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from fastreid.layers import * 8 | from fastreid.utils.weight_init import weights_init_kaiming 9 | from .build import REID_HEADS_REGISTRY 10 | 11 | 12 | @REID_HEADS_REGISTRY.register() 13 | class ReductionHead(nn.Module): 14 | def __init__(self, cfg, in_feat, num_classes, pool_layer=nn.AdaptiveAvgPool2d(1)): 15 | super().__init__() 16 | 17 | reduction_dim = cfg.MODEL.HEADS.REDUCTION_DIM 18 | 19 | self.pool_layer = pool_layer 20 | 21 | self.bottleneck = nn.Sequential( 22 | nn.Conv2d(in_feat, reduction_dim, 1, 1, bias=False), 23 | get_norm(cfg.MODEL.HEADS.NORM, reduction_dim, cfg.MODEL.HEADS.NORM_SPLIT, bias_freeze=True), 24 | nn.LeakyReLU(0.1), 25 | nn.Dropout2d(0.5), 26 | ) 27 | self.bnneck = get_norm(cfg.MODEL.HEADS.NORM, reduction_dim, cfg.MODEL.HEADS.NORM_SPLIT, bias_freeze=True) 28 | 29 | self.bottleneck.apply(weights_init_kaiming) 30 | self.bnneck.apply(weights_init_kaiming) 31 | 32 | # identity classification layer 33 | if cfg.MODEL.HEADS.CLS_LAYER == 'linear': 34 | self.classifier = nn.Linear(reduction_dim, num_classes, bias=False) 35 | elif cfg.MODEL.HEADS.CLS_LAYER == 'arcface': 36 | self.classifier = Arcface(cfg, reduction_dim) 37 | elif cfg.MODEL.HEADS.CLS_LAYER == 'circle': 38 | self.classifier = Circle(cfg, reduction_dim) 39 | else: 40 | self.classifier = nn.Linear(reduction_dim, num_classes, bias=False) 41 | 42 | def forward(self, features, targets=None): 43 | """ 44 | See :class:`ReIDHeads.forward`. 45 | """ 46 | global_feat = self.pool_layer(features) 47 | global_feat = self.bottleneck(global_feat) 48 | bn_feat = self.bnneck(global_feat) 49 | bn_feat = Flatten()(bn_feat) 50 | # Evaluation 51 | if not self.training: 52 | return bn_feat 53 | # Training 54 | try: 55 | pred_class_logits = self.classifier(bn_feat) 56 | except TypeError: 57 | pred_class_logits = self.classifier(bn_feat, targets) 58 | 59 | if self.neck_feat == "before": 60 | feat = Flatten()(global_feat) 61 | elif self.neck_feat == "after": 62 | feat = bn_feat 63 | else: 64 | raise KeyError("MODEL.HEADS.NECK_FEAT value is invalid, must choose from ('after' & 'before')") 65 | return pred_class_logits, feat, targets 66 | -------------------------------------------------------------------------------- /fastreid/modeling/losses/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: l1aoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from .build_losses import reid_losses 8 | from .cross_entroy_loss import CrossEntropyLoss 9 | from .focal_loss import FocalLoss 10 | from .metric_loss import * 11 | -------------------------------------------------------------------------------- /fastreid/modeling/losses/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/losses/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/losses/__pycache__/build_losses.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/losses/__pycache__/build_losses.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/losses/__pycache__/cross_entroy_loss.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/losses/__pycache__/cross_entroy_loss.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/losses/__pycache__/focal_loss.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/losses/__pycache__/focal_loss.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/losses/__pycache__/metric_loss.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/losses/__pycache__/metric_loss.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/losses/build_losses.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: xingyu liao 4 | @contact: liaoxingyu5@jd.com 5 | """ 6 | 7 | from .. import losses as Loss 8 | 9 | 10 | def reid_losses(cfg, pred_class_logits, global_features, gt_classes, prefix='') -> dict: 11 | loss_dict = {} 12 | for loss_name in cfg.MODEL.LOSSES.NAME: 13 | loss = getattr(Loss, loss_name)(cfg)(pred_class_logits, global_features, gt_classes) 14 | loss_dict.update(loss) 15 | # rename 16 | named_loss_dict = {} 17 | for name in loss_dict.keys(): 18 | named_loss_dict[prefix + name] = loss_dict[name] 19 | del loss_dict 20 | return named_loss_dict 21 | -------------------------------------------------------------------------------- /fastreid/modeling/losses/center_loss.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | import torch 7 | from torch import nn 8 | 9 | 10 | class CenterLoss(nn.Module): 11 | """Center loss. 12 | Reference: 13 | Wen et al. A Discriminative Feature Learning Approach for Deep Face Recognition. ECCV 2016. 14 | Args: 15 | num_classes (int): number of classes. 16 | feat_dim (int): feature dimension. 17 | """ 18 | 19 | def __init__(self, num_classes=751, feat_dim=2048, use_gpu=True): 20 | super(CenterLoss, self).__init__() 21 | self.num_classes,self.feat_dim = num_classes, feat_dim 22 | 23 | if use_gpu: self.centers = nn.Parameter(torch.randn(self.num_classes, self.feat_dim).cuda()) 24 | else: self.centers = nn.Parameter(torch.randn(self.num_classes, self.feat_dim)) 25 | 26 | def forward(self, x, labels): 27 | """ 28 | Args: 29 | x: feature matrix with shape (batch_size, feat_dim). 30 | labels: ground truth labels with shape (num_classes). 31 | """ 32 | assert x.size(0) == labels.size(0), "features.size(0) is not equal to labels.size(0)" 33 | 34 | batch_size = x.size(0) 35 | distmat = torch.pow(x, 2).sum(dim=1, keepdim=True).expand(batch_size, self.num_classes) + \ 36 | torch.pow(self.centers, 2).sum(dim=1, keepdim=True).expand(self.num_classes, batch_size).t() 37 | distmat.addmm_(1, -2, x, self.centers.t()) 38 | 39 | classes = torch.arange(self.num_classes).long() 40 | classes = classes.to(x.device) 41 | labels = labels.unsqueeze(1).expand(batch_size, self.num_classes) 42 | mask = labels.eq(classes.expand(batch_size, self.num_classes)) 43 | 44 | dist = distmat * mask.float() 45 | loss = dist.clamp(min=1e-12, max=1e+12).sum() / batch_size 46 | return loss 47 | -------------------------------------------------------------------------------- /fastreid/modeling/losses/cross_entroy_loss.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: l1aoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | import torch 7 | import torch.nn.functional as F 8 | 9 | from fastreid.utils.events import get_event_storage 10 | 11 | 12 | class CrossEntropyLoss(object): 13 | """ 14 | A class that stores information and compute losses about outputs of a Baseline head. 15 | """ 16 | 17 | def __init__(self, cfg): 18 | self._num_classes = cfg.MODEL.HEADS.NUM_CLASSES 19 | self._eps = cfg.MODEL.LOSSES.CE.EPSILON 20 | self._alpha = cfg.MODEL.LOSSES.CE.ALPHA 21 | self._scale = cfg.MODEL.LOSSES.CE.SCALE 22 | 23 | self._topk = (1,) 24 | 25 | def _log_accuracy(self, pred_class_logits, gt_classes): 26 | """ 27 | Log the accuracy metrics to EventStorage. 28 | """ 29 | bsz = pred_class_logits.size(0) 30 | maxk = max(self._topk) 31 | _, pred_class = pred_class_logits.topk(maxk, 1, True, True) 32 | pred_class = pred_class.t() 33 | correct = pred_class.eq(gt_classes.view(1, -1).expand_as(pred_class)) 34 | 35 | ret = [] 36 | for k in self._topk: 37 | correct_k = correct[:k].view(-1).float().sum(dim=0, keepdim=True) 38 | ret.append(correct_k.mul_(1. / bsz)) 39 | 40 | storage = get_event_storage() 41 | storage.put_scalar("cls_accuracy", ret[0]) 42 | 43 | def __call__(self, pred_class_logits, _, gt_classes): 44 | """ 45 | Compute the softmax cross entropy loss for box classification. 46 | Returns: 47 | scalar Tensor 48 | """ 49 | self._log_accuracy(pred_class_logits, gt_classes) 50 | if self._eps >= 0: 51 | smooth_param = self._eps 52 | else: 53 | # adaptive lsr 54 | soft_label = F.softmax(pred_class_logits, dim=1) 55 | smooth_param = self._alpha * soft_label[torch.arange(soft_label.size(0)), gt_classes].unsqueeze(1) 56 | 57 | log_probs = F.log_softmax(pred_class_logits, dim=1) 58 | with torch.no_grad(): 59 | targets = torch.ones_like(log_probs) 60 | targets *= smooth_param / (self._num_classes - 1) 61 | targets.scatter_(1, gt_classes.data.unsqueeze(1), (1 - smooth_param)) 62 | 63 | loss = (-targets * log_probs).mean(0).sum() 64 | return { 65 | "loss_cls": loss * self._scale, 66 | } 67 | -------------------------------------------------------------------------------- /fastreid/modeling/losses/focal_loss.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: xingyu liao 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | import torch 8 | import torch.nn.functional as F 9 | 10 | from fastreid.utils.one_hot import one_hot 11 | 12 | 13 | # based on: 14 | # https://github.com/kornia/kornia/blob/master/kornia/losses/focal.py 15 | 16 | def focal_loss( 17 | input: torch.Tensor, 18 | target: torch.Tensor, 19 | alpha: float, 20 | gamma: float = 2.0, 21 | reduction: str = 'mean', ) -> torch.Tensor: 22 | r"""Function that computes Focal loss. 23 | See :class:`fastreid.modeling.losses.FocalLoss` for details. 24 | """ 25 | if not torch.is_tensor(input): 26 | raise TypeError("Input type is not a torch.Tensor. Got {}" 27 | .format(type(input))) 28 | 29 | if not len(input.shape) >= 2: 30 | raise ValueError("Invalid input shape, we expect BxCx*. Got: {}" 31 | .format(input.shape)) 32 | 33 | if input.size(0) != target.size(0): 34 | raise ValueError('Expected input batch_size ({}) to match target batch_size ({}).' 35 | .format(input.size(0), target.size(0))) 36 | 37 | n = input.size(0) 38 | out_size = (n,) + input.size()[2:] 39 | if target.size()[1:] != input.size()[2:]: 40 | raise ValueError('Expected target size {}, got {}'.format( 41 | out_size, target.size())) 42 | 43 | if not input.device == target.device: 44 | raise ValueError( 45 | "input and target must be in the same device. Got: {}".format( 46 | input.device, target.device)) 47 | 48 | # compute softmax over the classes axis 49 | input_soft = F.softmax(input, dim=1) 50 | 51 | # create the labels one hot tensor 52 | target_one_hot = one_hot( 53 | target, num_classes=input.shape[1], 54 | dtype=input.dtype) 55 | 56 | # compute the actual focal loss 57 | weight = torch.pow(-input_soft + 1., gamma) 58 | 59 | focal = -alpha * weight * torch.log(input_soft) 60 | loss_tmp = torch.sum(target_one_hot * focal, dim=1) 61 | 62 | if reduction == 'none': 63 | loss = loss_tmp 64 | elif reduction == 'mean': 65 | loss = torch.mean(loss_tmp) 66 | elif reduction == 'sum': 67 | loss = torch.sum(loss_tmp) 68 | else: 69 | raise NotImplementedError("Invalid reduction mode: {}" 70 | .format(reduction)) 71 | return loss 72 | 73 | 74 | class FocalLoss(object): 75 | r"""Criterion that computes Focal loss. 76 | According to [1], the Focal loss is computed as follows: 77 | .. math:: 78 | \text{FL}(p_t) = -\alpha_t (1 - p_t)^{\gamma} \, \text{log}(p_t) 79 | where: 80 | - :math:`p_t` is the model's estimated probability for each class. 81 | Arguments: 82 | alpha (float): Weighting factor :math:`\alpha \in [0, 1]`. 83 | gamma (float): Focusing parameter :math:`\gamma >= 0`. 84 | reduction (str, optional): Specifies the reduction to apply to the 85 | output: ‘none’ | ‘mean’ | ‘sum’. ‘none’: no reduction will be applied, 86 | ‘mean’: the sum of the output will be divided by the number of elements 87 | in the output, ‘sum’: the output will be summed. Default: ‘none’. 88 | Shape: 89 | - Input: :math:`(N, C, *)` where C = number of classes. 90 | - Target: :math:`(N, *)` where each value is 91 | :math:`0 ≤ targets[i] ≤ C−1`. 92 | Examples: 93 | >>> N = 5 # num_classes 94 | >>> loss = FocalLoss(cfg) 95 | >>> input = torch.randn(1, N, 3, 5, requires_grad=True) 96 | >>> target = torch.empty(1, 3, 5, dtype=torch.long).random_(N) 97 | >>> output = loss(input, target) 98 | >>> output.backward() 99 | References: 100 | [1] https://arxiv.org/abs/1708.02002 101 | """ 102 | 103 | # def __init__(self, alpha: float, gamma: float = 2.0, 104 | # reduction: str = 'none') -> None: 105 | def __init__(self, cfg): 106 | self._alpha: float = cfg.MODEL.LOSSES.FL.ALPHA 107 | self._gamma: float = cfg.MODEL.LOSSES.FL.GAMMA 108 | self._scale: float = cfg.MODEL.LOSSES.FL.SCALE 109 | 110 | def __call__(self, pred_class_logits: torch.Tensor, _, gt_classes: torch.Tensor) -> dict: 111 | loss = focal_loss(pred_class_logits, gt_classes, self._alpha, self._gamma) 112 | return { 113 | 'loss_focal': loss * self._scale, 114 | } 115 | -------------------------------------------------------------------------------- /fastreid/modeling/meta_arch/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from .build import META_ARCH_REGISTRY, build_model 8 | 9 | 10 | # import all the meta_arch, so they will be registered 11 | from .baseline import Baseline 12 | -------------------------------------------------------------------------------- /fastreid/modeling/meta_arch/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/meta_arch/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/meta_arch/__pycache__/baseline.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/meta_arch/__pycache__/baseline.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/meta_arch/__pycache__/build.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/modeling/meta_arch/__pycache__/build.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/modeling/meta_arch/baseline.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from torch import nn 8 | 9 | from fastreid.layers import GeneralizedMeanPoolingP 10 | from fastreid.modeling.backbones import build_backbone 11 | from fastreid.modeling.heads import build_reid_heads 12 | from fastreid.modeling.losses import reid_losses 13 | from .build import META_ARCH_REGISTRY 14 | 15 | 16 | @META_ARCH_REGISTRY.register() 17 | class Baseline(nn.Module): 18 | def __init__(self, cfg): 19 | super().__init__() 20 | self._cfg = cfg 21 | # backbone 22 | self.backbone = build_backbone(cfg) 23 | 24 | # head 25 | if cfg.MODEL.HEADS.POOL_LAYER == 'avgpool': 26 | pool_layer = nn.AdaptiveAvgPool2d(1) 27 | elif cfg.MODEL.HEADS.POOL_LAYER == 'maxpool': 28 | pool_layer = nn.AdaptiveMaxPool2d(1) 29 | elif cfg.MODEL.HEADS.POOL_LAYER == 'gempool': 30 | pool_layer = GeneralizedMeanPoolingP() 31 | else: 32 | pool_layer = nn.Identity() 33 | 34 | in_feat = cfg.MODEL.HEADS.IN_FEAT 35 | num_classes = cfg.MODEL.HEADS.NUM_CLASSES 36 | self.heads = build_reid_heads(cfg, in_feat, num_classes, pool_layer) 37 | 38 | def forward(self, inputs): 39 | images = inputs["images"] 40 | 41 | if not self.training: 42 | pred_feat = self.inference(images) 43 | try: 44 | return pred_feat, inputs["targets"], inputs["camid"] 45 | except KeyError: 46 | return pred_feat 47 | 48 | targets = inputs["targets"] 49 | # training 50 | features = self.backbone(images) # (bs, 2048, 16, 8) 51 | return self.heads(features, targets) 52 | 53 | def inference(self, images): 54 | assert not self.training 55 | features = self.backbone(images) # (bs, 2048, 16, 8) 56 | pred_feat = self.heads(features) 57 | return pred_feat 58 | 59 | def losses(self, outputs): 60 | logits, feat, targets = outputs 61 | return reid_losses(self._cfg, logits, feat, targets) 62 | -------------------------------------------------------------------------------- /fastreid/modeling/meta_arch/build.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from ...utils.registry import Registry 8 | 9 | META_ARCH_REGISTRY = Registry("META_ARCH") # noqa F401 isort:skip 10 | META_ARCH_REGISTRY.__doc__ = """ 11 | Registry for meta-architectures, i.e. the whole model. 12 | The registered object will be called with `obj(cfg)` 13 | and expected to return a `nn.Module` object. 14 | """ 15 | 16 | 17 | def build_model(cfg): 18 | """ 19 | Build the whole model architecture, defined by ``cfg.MODEL.META_ARCHITECTURE``. 20 | Note that it does not load any weights from ``cfg``. 21 | """ 22 | meta_arch = cfg.MODEL.META_ARCHITECTURE 23 | return META_ARCH_REGISTRY.get(meta_arch)(cfg) 24 | -------------------------------------------------------------------------------- /fastreid/solver/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | 8 | from .build import build_lr_scheduler, build_optimizer -------------------------------------------------------------------------------- /fastreid/solver/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/solver/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/solver/__pycache__/build.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/solver/__pycache__/build.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/solver/__pycache__/lr_scheduler.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/solver/__pycache__/lr_scheduler.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/solver/build.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from . import lr_scheduler 8 | from . import optim 9 | 10 | 11 | def build_optimizer(cfg, model): 12 | params = [] 13 | for key, value in model.named_parameters(): 14 | if not value.requires_grad: 15 | continue 16 | lr = cfg.SOLVER.BASE_LR 17 | weight_decay = cfg.SOLVER.WEIGHT_DECAY 18 | if "heads" in key: 19 | lr *= cfg.SOLVER.HEADS_LR_FACTOR 20 | if "bias" in key: 21 | lr *= cfg.SOLVER.BIAS_LR_FACTOR 22 | weight_decay = cfg.SOLVER.WEIGHT_DECAY_BIAS 23 | params += [{"params": [value], "lr": lr, "weight_decay": weight_decay}] 24 | 25 | solver_opt = cfg.SOLVER.OPT 26 | if hasattr(optim, solver_opt): 27 | if solver_opt == "SGD": 28 | opt_fns = getattr(optim, solver_opt)(params, momentum=cfg.SOLVER.MOMENTUM) 29 | else: 30 | opt_fns = getattr(optim, solver_opt)(params) 31 | else: 32 | raise NameError("optimizer {} not support".format(cfg.SOLVER.OPT)) 33 | return opt_fns 34 | 35 | 36 | def build_lr_scheduler(cfg, optimizer): 37 | scheduler_args = { 38 | "optimizer": optimizer, 39 | 40 | # warmup options 41 | "warmup_factor": cfg.SOLVER.WARMUP_FACTOR, 42 | "warmup_iters": cfg.SOLVER.WARMUP_ITERS, 43 | "warmup_method": cfg.SOLVER.WARMUP_METHOD, 44 | 45 | # multi-step lr scheduler options 46 | "milestones": cfg.SOLVER.STEPS, 47 | "gamma": cfg.SOLVER.GAMMA, 48 | 49 | # cosine annealing lr scheduler options 50 | "max_iters": cfg.SOLVER.MAX_ITER, 51 | "delay_iters": cfg.SOLVER.DELAY_ITERS, 52 | "eta_min_lr": cfg.SOLVER.ETA_MIN_LR, 53 | 54 | } 55 | return getattr(lr_scheduler, cfg.SOLVER.SCHED)(**scheduler_args) 56 | -------------------------------------------------------------------------------- /fastreid/solver/optim/__init__.py: -------------------------------------------------------------------------------- 1 | from .lamb import Lamb 2 | from .lookahead import Lookahead, LookaheadAdam 3 | from .novograd import Novograd 4 | from .over9000 import Over9000, RangerLars 5 | from .radam import RAdam, PlainRAdam, AdamW 6 | from .ralamb import Ralamb 7 | from .ranger import Ranger 8 | from .swa import SWA 9 | 10 | from torch.optim import * 11 | -------------------------------------------------------------------------------- /fastreid/solver/optim/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/solver/optim/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/solver/optim/__pycache__/lamb.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/solver/optim/__pycache__/lamb.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/solver/optim/__pycache__/lookahead.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/solver/optim/__pycache__/lookahead.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/solver/optim/__pycache__/novograd.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/solver/optim/__pycache__/novograd.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/solver/optim/__pycache__/over9000.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/solver/optim/__pycache__/over9000.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/solver/optim/__pycache__/radam.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/solver/optim/__pycache__/radam.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/solver/optim/__pycache__/ralamb.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/solver/optim/__pycache__/ralamb.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/solver/optim/__pycache__/ranger.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/solver/optim/__pycache__/ranger.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/solver/optim/__pycache__/swa.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/solver/optim/__pycache__/swa.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/solver/optim/over9000.py: -------------------------------------------------------------------------------- 1 | #### 2 | # CODE TAKEN FROM https://github.com/mgrankin/over9000 3 | #### 4 | 5 | from .lookahead import Lookahead 6 | from .ralamb import Ralamb 7 | 8 | 9 | # RAdam + LARS + LookAHead 10 | 11 | # Lookahead implementation from https://github.com/lonePatient/lookahead_pytorch/blob/master/optimizer.py 12 | # RAdam + LARS implementation from https://gist.github.com/redknightlois/c4023d393eb8f92bb44b2ab582d7ec20 13 | 14 | def Over9000(params, alpha=0.5, k=6, *args, **kwargs): 15 | ralamb = Ralamb(params, *args, **kwargs) 16 | return Lookahead(ralamb, alpha, k) 17 | 18 | 19 | RangerLars = Over9000 20 | -------------------------------------------------------------------------------- /fastreid/solver/optim/ralamb.py: -------------------------------------------------------------------------------- 1 | #### 2 | # CODE TAKEN FROM https://github.com/mgrankin/over9000 3 | #### 4 | 5 | import torch, math 6 | from torch.optim.optimizer import Optimizer 7 | 8 | # RAdam + LARS 9 | class Ralamb(Optimizer): 10 | 11 | def __init__(self, params, lr=1e-3, betas=(0.9, 0.999), eps=1e-8, weight_decay=0): 12 | defaults = dict(lr=lr, betas=betas, eps=eps, weight_decay=weight_decay) 13 | self.buffer = [[None, None, None] for ind in range(10)] 14 | super(Ralamb, self).__init__(params, defaults) 15 | 16 | def __setstate__(self, state): 17 | super(Ralamb, self).__setstate__(state) 18 | 19 | def step(self, closure=None): 20 | 21 | loss = None 22 | if closure is not None: 23 | loss = closure() 24 | 25 | for group in self.param_groups: 26 | 27 | for p in group['params']: 28 | if p.grad is None: 29 | continue 30 | grad = p.grad.data.float() 31 | if grad.is_sparse: 32 | raise RuntimeError('Ralamb does not support sparse gradients') 33 | 34 | p_data_fp32 = p.data.float() 35 | 36 | state = self.state[p] 37 | 38 | if len(state) == 0: 39 | state['step'] = 0 40 | state['exp_avg'] = torch.zeros_like(p_data_fp32) 41 | state['exp_avg_sq'] = torch.zeros_like(p_data_fp32) 42 | else: 43 | state['exp_avg'] = state['exp_avg'].type_as(p_data_fp32) 44 | state['exp_avg_sq'] = state['exp_avg_sq'].type_as(p_data_fp32) 45 | 46 | exp_avg, exp_avg_sq = state['exp_avg'], state['exp_avg_sq'] 47 | beta1, beta2 = group['betas'] 48 | 49 | # Decay the first and second moment running average coefficient 50 | # m_t 51 | exp_avg.mul_(beta1).add_(1 - beta1, grad) 52 | # v_t 53 | exp_avg_sq.mul_(beta2).addcmul_(1 - beta2, grad, grad) 54 | 55 | state['step'] += 1 56 | buffered = self.buffer[int(state['step'] % 10)] 57 | 58 | if state['step'] == buffered[0]: 59 | N_sma, radam_step_size = buffered[1], buffered[2] 60 | else: 61 | buffered[0] = state['step'] 62 | beta2_t = beta2 ** state['step'] 63 | N_sma_max = 2 / (1 - beta2) - 1 64 | N_sma = N_sma_max - 2 * state['step'] * beta2_t / (1 - beta2_t) 65 | buffered[1] = N_sma 66 | 67 | # more conservative since it's an approximated value 68 | if N_sma >= 5: 69 | radam_step_size = math.sqrt((1 - beta2_t) * (N_sma - 4) / (N_sma_max - 4) * (N_sma - 2) / N_sma * N_sma_max / (N_sma_max - 2)) / (1 - beta1 ** state['step']) 70 | else: 71 | radam_step_size = 1.0 / (1 - beta1 ** state['step']) 72 | buffered[2] = radam_step_size 73 | 74 | if group['weight_decay'] != 0: 75 | p_data_fp32.add_(-group['weight_decay'] * group['lr'], p_data_fp32) 76 | 77 | # more conservative since it's an approximated value 78 | radam_step = p_data_fp32.clone() 79 | if N_sma >= 5: 80 | denom = exp_avg_sq.sqrt().add_(group['eps']) 81 | radam_step.addcdiv_(-radam_step_size * group['lr'], exp_avg, denom) 82 | else: 83 | radam_step.add_(-radam_step_size * group['lr'], exp_avg) 84 | 85 | radam_norm = radam_step.pow(2).sum().sqrt() 86 | weight_norm = p.data.pow(2).sum().sqrt().clamp(0, 10) 87 | if weight_norm == 0 or radam_norm == 0: 88 | trust_ratio = 1 89 | else: 90 | trust_ratio = weight_norm / radam_norm 91 | 92 | state['weight_norm'] = weight_norm 93 | state['adam_norm'] = radam_norm 94 | state['trust_ratio'] = trust_ratio 95 | 96 | if N_sma >= 5: 97 | p_data_fp32.addcdiv_(-radam_step_size * group['lr'] * trust_ratio, exp_avg, denom) 98 | else: 99 | p_data_fp32.add_(-radam_step_size * group['lr'] * trust_ratio, exp_avg) 100 | 101 | p.data.copy_(p_data_fp32) 102 | 103 | return loss -------------------------------------------------------------------------------- /fastreid/utils/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: sherlock 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | -------------------------------------------------------------------------------- /fastreid/utils/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/utils/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/utils/__pycache__/checkpoint.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/utils/__pycache__/checkpoint.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/utils/__pycache__/comm.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/utils/__pycache__/comm.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/utils/__pycache__/events.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/utils/__pycache__/events.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/utils/__pycache__/file_io.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/utils/__pycache__/file_io.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/utils/__pycache__/history_buffer.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/utils/__pycache__/history_buffer.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/utils/__pycache__/logger.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/utils/__pycache__/logger.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/utils/__pycache__/one_hot.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/utils/__pycache__/one_hot.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/utils/__pycache__/precision_bn.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/utils/__pycache__/precision_bn.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/utils/__pycache__/registry.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/utils/__pycache__/registry.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/utils/__pycache__/timer.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/utils/__pycache__/timer.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/utils/__pycache__/weight_init.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/fastreid/utils/__pycache__/weight_init.cpython-36.pyc -------------------------------------------------------------------------------- /fastreid/utils/history_buffer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 3 | 4 | import numpy as np 5 | from typing import List, Tuple 6 | 7 | 8 | class HistoryBuffer: 9 | """ 10 | Track a series of scalar values and provide access to smoothed values over a 11 | window or the global average of the series. 12 | """ 13 | 14 | def __init__(self, max_length: int = 1000000): 15 | """ 16 | Args: 17 | max_length: maximal number of values that can be stored in the 18 | buffer. When the capacity of the buffer is exhausted, old 19 | values will be removed. 20 | """ 21 | self._max_length: int = max_length 22 | self._data: List[Tuple[float, float]] = [] # (value, iteration) pairs 23 | self._count: int = 0 24 | self._global_avg: float = 0 25 | 26 | def update(self, value: float, iteration: float = None): 27 | """ 28 | Add a new scalar value produced at certain iteration. If the length 29 | of the buffer exceeds self._max_length, the oldest element will be 30 | removed from the buffer. 31 | """ 32 | if iteration is None: 33 | iteration = self._count 34 | if len(self._data) == self._max_length: 35 | self._data.pop(0) 36 | self._data.append((value, iteration)) 37 | 38 | self._count += 1 39 | self._global_avg += (value - self._global_avg) / self._count 40 | 41 | def latest(self): 42 | """ 43 | Return the latest scalar value added to the buffer. 44 | """ 45 | return self._data[-1][0] 46 | 47 | def median(self, window_size: int): 48 | """ 49 | Return the median of the latest `window_size` values in the buffer. 50 | """ 51 | return np.median([x[0] for x in self._data[-window_size:]]) 52 | 53 | def avg(self, window_size: int): 54 | """ 55 | Return the mean of the latest `window_size` values in the buffer. 56 | """ 57 | return np.mean([x[0] for x in self._data[-window_size:]]) 58 | 59 | def global_avg(self): 60 | """ 61 | Return the mean of all the elements in the buffer. Note that this 62 | includes those getting removed due to limited buffer storage. 63 | """ 64 | return self._global_avg 65 | 66 | def values(self): 67 | """ 68 | Returns: 69 | list[(number, iteration)]: content of the current buffer. 70 | """ 71 | return self._data 72 | -------------------------------------------------------------------------------- /fastreid/utils/one_hot.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: xingyu liao 4 | @contact: liaoxingyu5@jd.com 5 | """ 6 | 7 | from typing import Optional 8 | 9 | import torch 10 | 11 | 12 | # based on: 13 | # https://github.com/kornia/kornia/blob/master/kornia/utils/one_hot.py 14 | 15 | 16 | def one_hot(labels: torch.Tensor, 17 | num_classes: int, 18 | dtype: Optional[torch.dtype] = None, ) -> torch.Tensor: 19 | # eps: Optional[float] = 1e-6) -> torch.Tensor: 20 | r"""Converts an integer label x-D tensor to a one-hot (x+1)-D tensor. 21 | Args: 22 | labels (torch.Tensor) : tensor with labels of shape :math:`(N, *)`, 23 | where N is batch size. Each value is an integer 24 | representing correct classification. 25 | num_classes (int): number of classes in labels. 26 | device (Optional[torch.device]): the desired device of returned tensor. 27 | Default: if None, uses the current device for the default tensor type 28 | (see torch.set_default_tensor_type()). device will be the CPU for CPU 29 | tensor types and the current CUDA device for CUDA tensor types. 30 | dtype (Optional[torch.dtype]): the desired data type of returned 31 | tensor. Default: if None, infers data type from values. 32 | Returns: 33 | torch.Tensor: the labels in one hot tensor of shape :math:`(N, C, *)`, 34 | Examples:: 35 | >>> labels = torch.LongTensor([[[0, 1], [2, 0]]]) 36 | >>> one_hot(labels, num_classes=3) 37 | tensor([[[[1., 0.], 38 | [0., 1.]], 39 | [[0., 1.], 40 | [0., 0.]], 41 | [[0., 0.], 42 | [1., 0.]]]] 43 | """ 44 | if not torch.is_tensor(labels): 45 | raise TypeError("Input labels type is not a torch.Tensor. Got {}" 46 | .format(type(labels))) 47 | if not labels.dtype == torch.int64: 48 | raise ValueError( 49 | "labels must be of the same dtype torch.int64. Got: {}".format( 50 | labels.dtype)) 51 | if num_classes < 1: 52 | raise ValueError("The number of classes must be bigger than one." 53 | " Got: {}".format(num_classes)) 54 | device = labels.device 55 | shape = labels.shape 56 | one_hot = torch.zeros(shape[0], num_classes, *shape[1:], 57 | device=device, dtype=dtype) 58 | return one_hot.scatter_(1, labels.unsqueeze(1), 1.0) 59 | -------------------------------------------------------------------------------- /fastreid/utils/precision_bn.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | import itertools 8 | 9 | import torch 10 | 11 | BN_MODULE_TYPES = ( 12 | torch.nn.BatchNorm1d, 13 | torch.nn.BatchNorm2d, 14 | torch.nn.BatchNorm3d, 15 | torch.nn.SyncBatchNorm, 16 | ) 17 | 18 | 19 | @torch.no_grad() 20 | def update_bn_stats(model, data_loader, num_iters: int = 200): 21 | """ 22 | Recompute and update the batch norm stats to make them more precise. During 23 | training both BN stats and the weight are changing after every iteration, so 24 | the running average can not precisely reflect the actual stats of the 25 | current model. 26 | In this function, the BN stats are recomputed with fixed weights, to make 27 | the running average more precise. Specifically, it computes the true average 28 | of per-batch mean/variance instead of the running average. 29 | Args: 30 | model (nn.Module): the model whose bn stats will be recomputed. 31 | Note that: 32 | 1. This function will not alter the training mode of the given model. 33 | Users are responsible for setting the layers that needs 34 | precise-BN to training mode, prior to calling this function. 35 | 2. Be careful if your models contain other stateful layers in 36 | addition to BN, i.e. layers whose state can change in forward 37 | iterations. This function will alter their state. If you wish 38 | them unchanged, you need to either pass in a submodule without 39 | those layers, or backup the states. 40 | data_loader (iterator): an iterator. Produce data as inputs to the model. 41 | num_iters (int): number of iterations to compute the stats. 42 | """ 43 | bn_layers = get_bn_modules(model) 44 | if len(bn_layers) == 0: 45 | return 46 | 47 | # In order to make the running stats only reflect the current batch, the 48 | # momentum is disabled. 49 | # bn.running_mean = (1 - momentum) * bn.running_mean + momentum * batch_mean 50 | # Setting the momentum to 1.0 to compute the stats without momentum. 51 | momentum_actual = [bn.momentum for bn in bn_layers] 52 | for bn in bn_layers: 53 | bn.momentum = 1.0 54 | 55 | # Note that running_var actually means "running average of variance" 56 | running_mean = [torch.zeros_like(bn.running_mean) for bn in bn_layers] 57 | running_var = [torch.zeros_like(bn.running_var) for bn in bn_layers] 58 | 59 | for ind, inputs in enumerate(itertools.islice(data_loader, num_iters)): 60 | # Change targets to zero to avoid error in 61 | # circle(arcface) loss which will use targets in forward 62 | inputs['targets'].zero_() 63 | with torch.no_grad(): # No need to backward 64 | model(inputs) 65 | for i, bn in enumerate(bn_layers): 66 | # Accumulates the bn stats. 67 | running_mean[i] += (bn.running_mean - running_mean[i]) / (ind + 1) 68 | running_var[i] += (bn.running_var - running_var[i]) / (ind + 1) 69 | # We compute the "average of variance" across iterations. 70 | assert ind == num_iters - 1, ( 71 | "update_bn_stats is meant to run for {} iterations, " 72 | "but the dataloader stops at {} iterations.".format(num_iters, ind) 73 | ) 74 | 75 | for i, bn in enumerate(bn_layers): 76 | # Sets the precise bn stats. 77 | bn.running_mean = running_mean[i] 78 | bn.running_var = running_var[i] 79 | bn.momentum = momentum_actual[i] 80 | 81 | 82 | def get_bn_modules(model): 83 | """ 84 | Find all BatchNorm (BN) modules that are in training mode. See 85 | fvcore.precise_bn.BN_MODULE_TYPES for a list of all modules that are 86 | included in this search. 87 | Args: 88 | model (nn.Module): a model possibly containing BN modules. 89 | Returns: 90 | list[nn.Module]: all BN modules in the model. 91 | """ 92 | # Finds all the bn layers. 93 | bn_layers = [ 94 | m for m in model.modules() if m.training and isinstance(m, BN_MODULE_TYPES) 95 | ] 96 | return bn_layers 97 | -------------------------------------------------------------------------------- /fastreid/utils/registry.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved 3 | 4 | from typing import Dict, Optional 5 | 6 | 7 | class Registry(object): 8 | """ 9 | The registry that provides name -> object mapping, to support third-party 10 | users' custom modules. 11 | To create a registry (e.g. a backbone registry): 12 | .. code-block:: python 13 | BACKBONE_REGISTRY = Registry('BACKBONE') 14 | To register an object: 15 | .. code-block:: python 16 | @BACKBONE_REGISTRY.register() 17 | class MyBackbone(): 18 | ... 19 | Or: 20 | .. code-block:: python 21 | BACKBONE_REGISTRY.register(MyBackbone) 22 | """ 23 | 24 | def __init__(self, name: str) -> None: 25 | """ 26 | Args: 27 | name (str): the name of this registry 28 | """ 29 | self._name: str = name 30 | self._obj_map: Dict[str, object] = {} 31 | 32 | def _do_register(self, name: str, obj: object) -> None: 33 | assert ( 34 | name not in self._obj_map 35 | ), "An object named '{}' was already registered in '{}' registry!".format( 36 | name, self._name 37 | ) 38 | self._obj_map[name] = obj 39 | 40 | def register(self, obj: object = None) -> Optional[object]: 41 | """ 42 | Register the given object under the the name `obj.__name__`. 43 | Can be used as either a decorator or not. See docstring of this class for usage. 44 | """ 45 | if obj is None: 46 | # used as a decorator 47 | def deco(func_or_class: object) -> object: 48 | name = func_or_class.__name__ # pyre-ignore 49 | self._do_register(name, func_or_class) 50 | return func_or_class 51 | 52 | return deco 53 | 54 | # used as a function call 55 | name = obj.__name__ # pyre-ignore 56 | self._do_register(name, obj) 57 | 58 | def get(self, name: str) -> object: 59 | ret = self._obj_map.get(name) 60 | if ret is None: 61 | raise KeyError( 62 | "No object named '{}' found in '{}' registry!".format( 63 | name, self._name 64 | ) 65 | ) 66 | return ret 67 | -------------------------------------------------------------------------------- /fastreid/utils/timer.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. 2 | # -*- coding: utf-8 -*- 3 | 4 | from time import perf_counter 5 | from typing import Optional 6 | 7 | 8 | class Timer: 9 | """ 10 | A timer which computes the time elapsed since the start/reset of the timer. 11 | """ 12 | 13 | def __init__(self): 14 | self.reset() 15 | 16 | def reset(self): 17 | """ 18 | Reset the timer. 19 | """ 20 | self._start = perf_counter() 21 | self._paused: Optional[float] = None 22 | self._total_paused = 0 23 | self._count_start = 1 24 | 25 | def pause(self): 26 | """ 27 | Pause the timer. 28 | """ 29 | if self._paused is not None: 30 | raise ValueError("Trying to pause a Timer that is already paused!") 31 | self._paused = perf_counter() 32 | 33 | def is_paused(self) -> bool: 34 | """ 35 | Returns: 36 | bool: whether the timer is currently paused 37 | """ 38 | return self._paused is not None 39 | 40 | def resume(self): 41 | """ 42 | Resume the timer. 43 | """ 44 | if self._paused is None: 45 | raise ValueError("Trying to resume a Timer that is not paused!") 46 | self._total_paused += perf_counter() - self._paused 47 | self._paused = None 48 | self._count_start += 1 49 | 50 | def seconds(self) -> float: 51 | """ 52 | Returns: 53 | (float): the total number of seconds since the start/reset of the 54 | timer, excluding the time when the timer is paused. 55 | """ 56 | if self._paused is not None: 57 | end_time: float = self._paused # type: ignore 58 | else: 59 | end_time = perf_counter() 60 | return end_time - self._start - self._total_paused 61 | 62 | def avg_seconds(self) -> float: 63 | """ 64 | Returns: 65 | (float): the average number of seconds between every start/reset and 66 | pause. 67 | """ 68 | return self.seconds() / self._count_start 69 | -------------------------------------------------------------------------------- /fastreid/utils/weight_init.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: xingyu liao 4 | @contact: liaoxingyu5@jd.com 5 | """ 6 | 7 | from torch import nn 8 | 9 | __all__ = [ 10 | 'weights_init_classifier', 11 | 'weights_init_kaiming', 12 | ] 13 | 14 | 15 | def weights_init_kaiming(m): 16 | classname = m.__class__.__name__ 17 | if classname.find('Linear') != -1: 18 | nn.init.normal_(m.weight, 0, 0.01) 19 | if m.bias is not None: 20 | nn.init.constant_(m.bias, 0.0) 21 | elif classname.find('Conv') != -1: 22 | nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu') 23 | if m.bias is not None: 24 | nn.init.constant_(m.bias, 0.0) 25 | elif classname.find('BatchNorm') != -1: 26 | if m.affine: 27 | nn.init.normal_(m.weight, 1.0, 0.02) 28 | nn.init.constant_(m.bias, 0.0) 29 | 30 | 31 | def weights_init_classifier(m): 32 | classname = m.__class__.__name__ 33 | if classname.find('Linear') != -1: 34 | nn.init.normal_(m.weight, std=0.001) 35 | if m.bias is not None: 36 | nn.init.constant_(m.bias, 0.0) 37 | -------------------------------------------------------------------------------- /projects/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/projects/.gitkeep -------------------------------------------------------------------------------- /projects/PartialReID/configs/.partial_market.yml.swn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/projects/PartialReID/configs/.partial_market.yml.swn -------------------------------------------------------------------------------- /projects/PartialReID/configs/.partial_market.yml.swo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/projects/PartialReID/configs/.partial_market.yml.swo -------------------------------------------------------------------------------- /projects/PartialReID/configs/.partial_market.yml.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/projects/PartialReID/configs/.partial_market.yml.swp -------------------------------------------------------------------------------- /projects/PartialReID/configs/partial_market.yml: -------------------------------------------------------------------------------- 1 | MODEL: 2 | META_ARCHITECTURE: 'PartialBaseline' 3 | 4 | BACKBONE: 5 | NAME: "build_resnet_backbone" 6 | DEPTH: 50 7 | LAST_STRIDE: 1 8 | WITH_IBN: True 9 | PRETRAIN_PATH: "/home/helingxiao3/.cache/torch/checkpoints/resnet50_ibn_a.pth.tar" 10 | 11 | HEADS: 12 | NAME: "DSRHead" 13 | 14 | LOSSES: 15 | NAME: ("CrossEntropyLoss", "TripletLoss") 16 | CE: 17 | EPSILON: 0.1 18 | SCALE: 1.0 19 | TRI: 20 | MARGIN: 0.3 21 | SCALE: 1. 22 | USE_COSINE_DIST: False 23 | 24 | DATASETS: 25 | NAMES: ("Market1501",) 26 | TESTS: ("PartialREID","PartialiLIDS","OccludedREID",) 27 | 28 | INPUT: 29 | SIZE_TRAIN: [384, 128] 30 | SIZE_TEST: [384, 128] 31 | REA: 32 | ENABLED: False 33 | PROB: 0.5 34 | MEAN: [123.675, 116.28, 103.53] 35 | DO_PAD: False 36 | 37 | 38 | DATALOADER: 39 | PK_SAMPLER: True 40 | NUM_INSTANCE: 4 41 | NUM_WORKERS: 16 42 | 43 | SOLVER: 44 | OPT: "Adam" 45 | MAX_ITER: 6000 46 | BASE_LR: 0.00035 47 | BIAS_LR_FACTOR: 2. 48 | WEIGHT_DECAY: 0.0005 49 | WEIGHT_DECAY_BIAS: 0.0 50 | IMS_PER_BATCH: 64 51 | 52 | STEPS: [3000, 5000] 53 | GAMMA: 0.1 54 | 55 | WARMUP_FACTOR: 0.01 56 | WARMUP_ITERS: 600 57 | 58 | LOG_PERIOD: 200 59 | CHECKPOINT_PERIOD: 2000 60 | 61 | TEST: 62 | EVAL_PERIOD: 1000 63 | IMS_PER_BATCH: 512 64 | PRECISE_BN: 65 | ENABLED: False 66 | DATASET: 'PartialREID' 67 | CUDNN_BENCHMARK: True 68 | 69 | OUTPUT_DIR: "logs/test_partial" 70 | -------------------------------------------------------------------------------- /projects/PartialReID/partialreid/.dsr_head.py.swo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/projects/PartialReID/partialreid/.dsr_head.py.swo -------------------------------------------------------------------------------- /projects/PartialReID/partialreid/.dsr_head.py.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/projects/PartialReID/partialreid/.dsr_head.py.swp -------------------------------------------------------------------------------- /projects/PartialReID/partialreid/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: xingyu liao 4 | @contact: liaoxingyu5@jd.com 5 | """ 6 | 7 | from .partial_dataset import * 8 | from .partialbaseline import PartialBaseline 9 | from .dsr_head import DSRHead 10 | from .config import add_partialreid_config 11 | from .dsr_evaluation import DsrEvaluator 12 | -------------------------------------------------------------------------------- /projects/PartialReID/partialreid/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/projects/PartialReID/partialreid/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /projects/PartialReID/partialreid/__pycache__/config.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/projects/PartialReID/partialreid/__pycache__/config.cpython-36.pyc -------------------------------------------------------------------------------- /projects/PartialReID/partialreid/__pycache__/dsr_distance.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/projects/PartialReID/partialreid/__pycache__/dsr_distance.cpython-36.pyc -------------------------------------------------------------------------------- /projects/PartialReID/partialreid/__pycache__/dsr_evaluation.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/projects/PartialReID/partialreid/__pycache__/dsr_evaluation.cpython-36.pyc -------------------------------------------------------------------------------- /projects/PartialReID/partialreid/__pycache__/dsr_head.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/projects/PartialReID/partialreid/__pycache__/dsr_head.cpython-36.pyc -------------------------------------------------------------------------------- /projects/PartialReID/partialreid/__pycache__/partial_dataset.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/projects/PartialReID/partialreid/__pycache__/partial_dataset.cpython-36.pyc -------------------------------------------------------------------------------- /projects/PartialReID/partialreid/__pycache__/partialbaseline.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDAI-CV/Partial-Person-ReID/fb94dbfbec1105bbc22a442702bc6e385427d416/projects/PartialReID/partialreid/__pycache__/partialbaseline.cpython-36.pyc -------------------------------------------------------------------------------- /projects/PartialReID/partialreid/config.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: l1aoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from fastreid.config import CfgNode as CN 8 | 9 | 10 | def add_partialreid_config(cfg): 11 | _C = cfg 12 | 13 | _C.TEST.DSR = CN() 14 | _C.TEST.DSR.ENABLED = True 15 | _C.TEST.DSR.LAMB = 0.5 16 | 17 | -------------------------------------------------------------------------------- /projects/PartialReID/partialreid/dsr_distance.py: -------------------------------------------------------------------------------- 1 | """Numpy version of euclidean distance, etc. 2 | Notice the input/output shape of methods, so that you can better understand 3 | the meaning of these methods.""" 4 | 5 | import torch 6 | import numpy as np 7 | 8 | 9 | def normalize(nparray, order=2, axis=0): 10 | """Normalize a N-D numpy array along the specified axis.""" 11 | norm = np.linalg.norm(nparray, ord=order, axis=axis, keepdims=True) 12 | return nparray / (norm + np.finfo(np.float32).eps) 13 | 14 | 15 | def normalize1(nparray, order=2, axis=0): 16 | """Normalize a N-D numpy array along the specified axis.""" 17 | 18 | for i in range(0, len(nparray)): 19 | temp = nparray[i, ::].T 20 | temp = temp / (np.linalg.norm(temp, ord=order, axis=axis, keepdims=True) + np.finfo(np.float32).eps) 21 | nparray[i, ::] = temp.T 22 | return nparray # / (norm + np.finfo(np.float32).eps) 23 | 24 | 25 | def compute_dist(array1, array2, type='euclidean'): 26 | """Compute the euclidean or cosine distance of all pairs. 27 | Args: 28 | array1: numpy array with shape [m1, n] 29 | array2: numpy array with shape [m2, n] 30 | type: one of ['cosine', 'euclidean'] 31 | Returns: 32 | numpy array with shape [m1, m2] 33 | """ 34 | assert type in ['cosine', 'euclidean'] 35 | if type == 'cosine': 36 | array1 = normalize(array1, axis=1) 37 | array2 = normalize(array2, axis=1) 38 | dist = np.matmul(array1, array2.T) 39 | return dist 40 | else: 41 | # shape [m1, 1] 42 | square1 = np.sum(np.square(array1), axis=1)[..., np.newaxis] 43 | # shape [1, m2] 44 | square2 = np.sum(np.square(array2), axis=1)[np.newaxis, ...] 45 | squared_dist = - 2 * np.matmul(array1, array2.T) + square1 + square2 46 | squared_dist[squared_dist < 0] = 0 47 | dist = np.sqrt(squared_dist) 48 | return dist 49 | 50 | 51 | def get_dsr_dist(array1, array2, distmat, scores): 52 | """ Compute the sptial feature reconstruction of all pairs 53 | array: [M, N, C] M: the number of query, N: the number of spatial feature, C: the dimension of each spatial feature 54 | array2: [M, N, C] M: the number of gallery 55 | :return: 56 | numpy array with shape [m1, m2] 57 | """ 58 | dist = 100 * torch.ones(len(array1), len(array2)) 59 | dist = dist.cuda() 60 | kappa = 0.001 61 | index = np.argsort(distmat,axis=1) 62 | T = kappa * torch.eye(110) 63 | T = T.cuda() 64 | M = [] 65 | for i in range(0, len(array2)): 66 | g = array2[i] 67 | g = torch.FloatTensor(g) 68 | g = g.view(g.size(0), g.size(1)) 69 | g = g.cuda() 70 | Proj_M1 = torch.matmul(torch.inverse(torch.matmul(g.t(), g) + T), g.t()) 71 | Proj_M1 = Proj_M1.cpu().numpy() 72 | M.append(Proj_M1) 73 | for i in range(0, len(array1)): 74 | q = torch.FloatTensor(array1[i]) 75 | q = q.view(q.size(0), q.size(1)) 76 | q = q.cuda() 77 | #pdb.set_trace() 78 | for j in range(0, 100): 79 | g = array2[index[i,j]] 80 | g = torch.FloatTensor(g) 81 | g = g.view(g.size(0), g.size(1)) 82 | g = g.cuda() 83 | #Proj_M = torch.matmul(torch.inverse(torch.matmul(g.t(), g) + T), g.t()) 84 | Proj_M = torch.FloatTensor(M[index[i,j]]) 85 | Proj_M = Proj_M.cuda() 86 | a = torch.matmul(g, torch.matmul(Proj_M, q)) - q 87 | dist[i, index[i,j]] = ((torch.pow(a, 2).sum(0).sqrt())*scores[i]).sum() 88 | dist = dist.cpu() 89 | dist = dist.numpy() 90 | 91 | 92 | return dist 93 | -------------------------------------------------------------------------------- /projects/PartialReID/partialreid/partial_dataset.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | @author: lingxiao he 5 | @contact: helingxiao3@jd.com 6 | """ 7 | 8 | import glob 9 | import os 10 | import os.path as osp 11 | import re 12 | 13 | from fastreid.data.datasets import DATASET_REGISTRY 14 | from fastreid.data.datasets.bases import ImageDataset 15 | 16 | __all__ = ['PartialREID', 'PartialiLIDS', 'OccludedREID'] 17 | 18 | 19 | def process_test(query_path, gallery_path): 20 | query_img_paths = glob.glob(os.path.join(query_path, '*.jpg')) 21 | gallery_img_paths = glob.glob(os.path.join(gallery_path, '*.jpg')) 22 | query_paths = [] 23 | pattern = re.compile(r'([-\d]+)_(\d*)') 24 | for img_path in query_img_paths: 25 | pid, camid = map(int, pattern.search(img_path).groups()) 26 | query_paths.append([img_path, pid, camid]) 27 | gallery_paths = [] 28 | for img_path in gallery_img_paths: 29 | pid, camid = map(int, pattern.search(img_path).groups()) 30 | gallery_paths.append([img_path, pid, camid]) 31 | return query_paths, gallery_paths 32 | 33 | 34 | @DATASET_REGISTRY.register() 35 | class PartialREID(ImageDataset): 36 | def __init__(self, root='datasets', ): 37 | self.root = root 38 | 39 | self.query_dir = osp.join(self.root, 'Partial_REID/partial_body_images') 40 | self.gallery_dir = osp.join(self.root, 'Partial_REID/whole_body_images') 41 | query, gallery = process_test(self.query_dir, self.gallery_dir) 42 | 43 | ImageDataset.__init__(self, [], query, gallery) 44 | 45 | 46 | @DATASET_REGISTRY.register() 47 | class PartialiLIDS(ImageDataset): 48 | def __init__(self, root='datasets', ): 49 | self.root = root 50 | 51 | self.query_dir = osp.join(self.root, 'PartialiLIDS/query') 52 | self.gallery_dir = osp.join(self.root, 'PartialiLIDS/gallery') 53 | query, gallery = process_test(self.query_dir, self.gallery_dir) 54 | 55 | ImageDataset.__init__(self, [], query, gallery) 56 | 57 | 58 | @DATASET_REGISTRY.register() 59 | class OccludedREID(ImageDataset): 60 | def __init__(self, root='datasets', ): 61 | self.root = root 62 | 63 | self.query_dir = osp.join(self.root, 'OccludedREID/query') 64 | self.gallery_dir = osp.join(self.root, 'OccludedREID/gallery') 65 | query, gallery = process_test(self.query_dir, self.gallery_dir) 66 | 67 | ImageDataset.__init__(self, [], query, gallery) 68 | -------------------------------------------------------------------------------- /projects/PartialReID/partialreid/partialbaseline.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @authorr: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | from fastreid.modeling.losses import reid_losses 8 | from fastreid.modeling.meta_arch import Baseline 9 | from fastreid.modeling.meta_arch.build import META_ARCH_REGISTRY 10 | 11 | 12 | @META_ARCH_REGISTRY.register() 13 | class PartialBaseline(Baseline): 14 | def losses(self, outputs): 15 | pred_logits, global_feat, fore_pred_logits, fore_feat, targets = outputs 16 | loss_dict = {} 17 | loss_dict.update(reid_losses(self._cfg, pred_logits, global_feat, targets, 'avg_branch')) 18 | loss_dict.update(reid_losses(self._cfg, fore_pred_logits, fore_feat, targets, 'fore_branch')) 19 | return loss_dict 20 | -------------------------------------------------------------------------------- /projects/PartialReID/train_net.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: sherlock 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | import os 8 | import logging 9 | import sys 10 | 11 | sys.path.append('.') 12 | 13 | from torch import nn 14 | 15 | from fastreid.config import get_cfg 16 | from fastreid.engine import DefaultTrainer, default_argument_parser, default_setup 17 | from fastreid.utils.checkpoint import Checkpointer 18 | from fastreid.engine import hooks 19 | 20 | from partialreid import * 21 | 22 | 23 | class Trainer(DefaultTrainer): 24 | @classmethod 25 | def build_evaluator(cls, cfg, num_query, output_folder=None): 26 | if output_folder is None: 27 | output_folder = os.path.join(cfg.OUTPUT_DIR, "inference") 28 | return DsrEvaluator(cfg, num_query) 29 | 30 | 31 | def setup(args): 32 | """ 33 | Create configs and perform basic setups. 34 | """ 35 | cfg = get_cfg() 36 | add_partialreid_config(cfg) 37 | cfg.merge_from_file(args.config_file) 38 | cfg.merge_from_list(args.opts) 39 | cfg.freeze() 40 | default_setup(cfg, args) 41 | return cfg 42 | 43 | 44 | def main(args): 45 | cfg = setup(args) 46 | 47 | logger = logging.getLogger('fastreid.' + __name__) 48 | if args.eval_only: 49 | cfg.defrost() 50 | cfg.MODEL.BACKBONE.PRETRAIN = False 51 | model = Trainer.build_model(cfg) 52 | model = nn.DataParallel(model) 53 | model = model.cuda() 54 | 55 | Checkpointer(model, save_dir=cfg.OUTPUT_DIR).load(cfg.MODEL.WEIGHTS) # load trained model 56 | if cfg.TEST.PRECISE_BN.ENABLED and hooks.get_bn_modules(model): 57 | prebn_cfg = cfg.clone() 58 | prebn_cfg.DATALOADER.NUM_WORKERS = 0 # save some memory and time for PreciseBN 59 | prebn_cfg.DATASETS.NAMES = tuple([cfg.TEST.PRECISE_BN.DATASET]) # set dataset name for PreciseBN 60 | logger.info("Prepare precise BN dataset") 61 | hooks.PreciseBN( 62 | # Run at the same freq as (but before) evaluation. 63 | model, 64 | # Build a new data loader to not affect training 65 | Trainer.build_train_loader(prebn_cfg), 66 | cfg.TEST.PRECISE_BN.NUM_ITER, 67 | ).update_stats() 68 | res = Trainer.test(cfg, model) 69 | return res 70 | 71 | trainer = Trainer(cfg) 72 | trainer.resume_or_load(resume=args.resume) 73 | return trainer.train() 74 | 75 | 76 | if __name__ == "__main__": 77 | args = default_argument_parser().parse_args() 78 | print("Command Line Args:", args) 79 | main(args) 80 | -------------------------------------------------------------------------------- /projects/README.md: -------------------------------------------------------------------------------- 1 | ## Multi-domain Results 2 | 3 | R34-ibn Backbone / SGD / 15 domain datasets / gempooling 4 | | Method | DukeMTMC unseen| Market1501 seen| MSMT17 seen| 5 | |:--:|:--:|:--:|:--:| 6 | | Baseline |77.33(61.46) |96.14(89.12)|80.44(55.04)| 7 | | Baseline + Camera-aware | 80.12(63.90)|96.56(89.43)|81.43(56.33)| 8 | ***************************************************** 9 | R34-ibn Backbone / SGD / 14 domain datasets / gempooling 10 | | Method | DukeMTMC unseen| Market1501 unseen| MSMT17 | 11 | |:--:|:--:|:--:|:--:| 12 | | Baseline |77.33(60.98) |89.43(72.03)|79.90(54.47)| 13 | | Baseline + Camera-aware | 79.44(62.63)|90.08(73.52)|81.30(55.99)| 14 | 15 | 16 | 17 | ***************************************************** 18 | SGD / 14 domain datasets + bjz / gempooling 19 | | Backbone |PartialREID unseen| OccludedREID unseen | PartialiLIDS unseen| DukeMTMC unseen| Market1501 unseen| MSMT17 seen | bjzCrowd seen | bjzBlack seen| 20 | |:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:| 21 | | R34_ibn |83.67(83.55) |92.44(94.59)|93.40(90.16)| 79.71(65.12)| 90.94(75.43)| 82.18(57.60)| 83.56(85.97)| 42.62(43.70)| 22 | | R101_ibn |86.33(82.98)|88.24(92.17)|92.40(89.63)| 80.25(65.12)| 91.36(77.16)| 83.93(61.90)| -| -| 23 | 24 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: sherlock 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | -------------------------------------------------------------------------------- /tests/dataset_test.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: liaoxingyu 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | import sys 8 | sys.path.append('.') 9 | from data import get_dataloader 10 | from config import cfg 11 | import argparse 12 | from data.datasets import init_dataset 13 | # cfg.DATALOADER.SAMPLER = 'triplet' 14 | cfg.DATASETS.NAMES = ("market1501", "dukemtmc", "cuhk03", "msmt17",) 15 | 16 | 17 | if __name__ == '__main__': 18 | parser = argparse.ArgumentParser(description="ReID Baseline Training") 19 | parser.add_argument( 20 | '-cfg', "--config_file", 21 | default="", 22 | metavar="FILE", 23 | help="path to config file", 24 | type=str 25 | ) 26 | # parser.add_argument("--local_rank", type=int, default=0) 27 | parser.add_argument("opts", help="Modify config options using the command-line", default=None, 28 | nargs=argparse.REMAINDER) 29 | args = parser.parse_args() 30 | cfg.merge_from_list(args.opts) 31 | 32 | # dataset = init_dataset('msmt17', combineall=True) 33 | get_dataloader(cfg) 34 | # tng_dataloader, val_dataloader, num_classes, num_query = get_dataloader(cfg) 35 | # def get_ex(): return open_image('datasets/beijingStation/query/000245_c10s2_1561732033722.000000.jpg') 36 | # im = get_ex() 37 | # print(data.train_ds[0]) 38 | # print(data.test_ds[0]) 39 | # a = next(iter(data.train_dl)) 40 | # from IPython import embed; embed() 41 | # from ipdb import set_trace; set_trace() 42 | # im.apply_tfms(crop_pad(size=(300, 300))) 43 | -------------------------------------------------------------------------------- /tests/interp_test.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from fastai.vision import * 3 | from fastai.basic_data import * 4 | from fastai.layers import * 5 | 6 | import sys 7 | sys.path.append('.') 8 | from engine.interpreter import ReidInterpretation 9 | 10 | from data import get_data_bunch 11 | from modeling import build_model 12 | from config import cfg 13 | cfg.DATASETS.NAMES = ('market1501',) 14 | cfg.DATASETS.TEST_NAMES = 'market1501' 15 | cfg.MODEL.BACKBONE = 'resnet50' 16 | 17 | data_bunch, test_labels, num_query = get_data_bunch(cfg) 18 | 19 | model = build_model(cfg, 10) 20 | model.load_params_wo_fc(torch.load('logs/2019.8.14/market/baseline/models/model_149.pth')['model']) 21 | learn = Learner(data_bunch, model) 22 | 23 | feats, _ = learn.get_preds(DatasetType.Test, activ=Lambda(lambda x: x)) -------------------------------------------------------------------------------- /tests/lr_scheduler_test.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import unittest 3 | 4 | import torch 5 | from torch import nn 6 | 7 | sys.path.append('.') 8 | from solver.lr_scheduler import WarmupMultiStepLR 9 | from solver.build import make_optimizer 10 | from config import cfg 11 | 12 | 13 | class MyTestCase(unittest.TestCase): 14 | def test_something(self): 15 | net = nn.Linear(10, 10) 16 | optimizer = make_optimizer(cfg, net) 17 | lr_scheduler = WarmupMultiStepLR(optimizer, [20, 40], warmup_iters=10) 18 | for i in range(50): 19 | lr_scheduler.step() 20 | for j in range(3): 21 | print(i, lr_scheduler.get_lr()[0]) 22 | optimizer.step() 23 | 24 | 25 | if __name__ == '__main__': 26 | unittest.main() 27 | -------------------------------------------------------------------------------- /tests/model_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import torch 4 | 5 | import sys 6 | sys.path.append('.') 7 | from fastreid.config import cfg 8 | from fastreid.modeling.backbones import build_resnet_backbone 9 | from fastreid.modeling.backbones.resnet_ibn_a import se_resnet101_ibn_a 10 | from torch import nn 11 | 12 | 13 | class MyTestCase(unittest.TestCase): 14 | def test_se_resnet101(self): 15 | cfg.MODEL.BACKBONE.NAME = 'resnet101' 16 | cfg.MODEL.BACKBONE.DEPTH = 101 17 | cfg.MODEL.BACKBONE.WITH_IBN = True 18 | cfg.MODEL.BACKBONE.WITH_SE = True 19 | cfg.MODEL.BACKBONE.PRETRAIN_PATH = '/export/home/lxy/.cache/torch/checkpoints/se_resnet101_ibn_a.pth.tar' 20 | 21 | net1 = build_resnet_backbone(cfg) 22 | net1.cuda() 23 | net2 = nn.DataParallel(se_resnet101_ibn_a()) 24 | res = net2.load_state_dict(torch.load(cfg.MODEL.BACKBONE.PRETRAIN_PATH)['state_dict'], strict=False) 25 | net2.cuda() 26 | x = torch.randn(10, 3, 256, 128).cuda() 27 | y1 = net1(x) 28 | y2 = net2(x) 29 | assert y1.sum() == y2.sum(), 'train mode problem' 30 | net1.eval() 31 | net2.eval() 32 | y1 = net1(x) 33 | y2 = net2(x) 34 | assert y1.sum() == y2.sum(), 'eval mode problem' 35 | 36 | 37 | if __name__ == '__main__': 38 | unittest.main() 39 | -------------------------------------------------------------------------------- /tests/sampler_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import sys 3 | sys.path.append('.') 4 | from fastreid.data.samplers import TrainingSampler 5 | 6 | 7 | class SamplerTestCase(unittest.TestCase): 8 | def test_training_sampler(self): 9 | sampler = TrainingSampler(5) 10 | for i in sampler: 11 | from ipdb import set_trace; set_trace() 12 | print(i) 13 | 14 | 15 | if __name__ == '__main__': 16 | unittest.main() 17 | -------------------------------------------------------------------------------- /tools/export2tf.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: sherlock 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | import sys 8 | 9 | import torch 10 | sys.path.append('../..') 11 | from fastreid.config import get_cfg 12 | from fastreid.engine import default_argument_parser, default_setup 13 | from fastreid.modeling.meta_arch import build_model 14 | from fastreid.export.tensorflow_export import export_tf_reid_model 15 | from fastreid.export.tf_modeling import TfMetaArch 16 | 17 | 18 | def setup(args): 19 | """ 20 | Create configs and perform basic setups. 21 | """ 22 | cfg = get_cfg() 23 | # cfg.merge_from_file(args.config_file) 24 | cfg.merge_from_list(args.opts) 25 | cfg.freeze() 26 | default_setup(cfg, args) 27 | return cfg 28 | 29 | 30 | if __name__ == "__main__": 31 | args = default_argument_parser().parse_args() 32 | print("Command Line Args:", args) 33 | cfg = setup(args) 34 | cfg.defrost() 35 | cfg.MODEL.BACKBONE.NAME = "build_resnet_backbone" 36 | cfg.MODEL.BACKBONE.DEPTH = 50 37 | cfg.MODEL.BACKBONE.LAST_STRIDE = 1 38 | # If use IBN block in backbone 39 | cfg.MODEL.BACKBONE.WITH_IBN = False 40 | cfg.MODEL.BACKBONE.PRETRAIN = False 41 | 42 | from torchvision.models import resnet50 43 | # model = TfMetaArch(cfg) 44 | model = resnet50(pretrained=False) 45 | # model.load_params_wo_fc(torch.load('logs/bjstation/res50_baseline_v0.4/ckpts/model_epoch80.pth')) 46 | model.eval() 47 | dummy_inputs = torch.randn(1, 3, 256, 128) 48 | export_tf_reid_model(model, dummy_inputs, 'reid_tf.pb') 49 | -------------------------------------------------------------------------------- /tools/train_net.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | """ 3 | @author: sherlock 4 | @contact: sherlockliao01@gmail.com 5 | """ 6 | 7 | import os 8 | import logging 9 | import sys 10 | 11 | sys.path.append('.') 12 | 13 | from torch import nn 14 | 15 | from fastreid.config import get_cfg 16 | from fastreid.engine import DefaultTrainer, default_argument_parser, default_setup 17 | from fastreid.utils.checkpoint import Checkpointer 18 | from fastreid.engine import hooks 19 | from fastreid.evaluation import ReidEvaluator 20 | 21 | 22 | class Trainer(DefaultTrainer): 23 | @classmethod 24 | def build_evaluator(cls, cfg, num_query, output_folder=None): 25 | if output_folder is None: 26 | output_folder = os.path.join(cfg.OUTPUT_DIR, "inference") 27 | return ReidEvaluator(cfg, num_query) 28 | 29 | 30 | def setup(args): 31 | """ 32 | Create configs and perform basic setups. 33 | """ 34 | cfg = get_cfg() 35 | cfg.merge_from_file(args.config_file) 36 | cfg.merge_from_list(args.opts) 37 | cfg.freeze() 38 | default_setup(cfg, args) 39 | return cfg 40 | 41 | 42 | def main(args): 43 | cfg = setup(args) 44 | 45 | logger = logging.getLogger('fastreid.' + __name__) 46 | if args.eval_only: 47 | cfg.defrost() 48 | cfg.MODEL.BACKBONE.PRETRAIN = False 49 | model = Trainer.build_model(cfg) 50 | model = nn.DataParallel(model) 51 | model = model.cuda() 52 | 53 | Checkpointer(model, save_dir=cfg.OUTPUT_DIR).load(cfg.MODEL.WEIGHTS) # load trained model 54 | if cfg.TEST.PRECISE_BN.ENABLED and hooks.get_bn_modules(model): 55 | prebn_cfg = cfg.clone() 56 | prebn_cfg.DATALOADER.NUM_WORKERS = 0 # save some memory and time for PreciseBN 57 | prebn_cfg.DATASETS.NAMES = tuple([cfg.TEST.PRECISE_BN.DATASET]) # set dataset name for PreciseBN 58 | logger.info("Prepare precise BN dataset") 59 | hooks.PreciseBN( 60 | # Run at the same freq as (but before) evaluation. 61 | model, 62 | # Build a new data loader to not affect training 63 | Trainer.build_train_loader(prebn_cfg), 64 | cfg.TEST.PRECISE_BN.NUM_ITER, 65 | ).update_stats() 66 | res = Trainer.test(cfg, model) 67 | return res 68 | 69 | trainer = Trainer(cfg) 70 | trainer.resume_or_load(resume=args.resume) 71 | return trainer.train() 72 | 73 | 74 | if __name__ == "__main__": 75 | args = default_argument_parser().parse_args() 76 | print("Command Line Args:", args) 77 | main(args) 78 | --------------------------------------------------------------------------------