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