├── LICENSE ├── README.md ├── configs ├── _base_ │ ├── datasets │ │ ├── cityscapes_half_512x512.py │ │ ├── gta_to_cityscapes_512x512.py │ │ ├── stepuda_gta_to_cityscapes_512x512.py │ │ ├── uda_gta_to_cityscapes_512x512.py │ │ ├── uda_gta_to_cityscapes_640x640.py │ │ └── uda_synthia_to_cityscapes_512x512.py │ ├── default_runtime.py │ ├── models │ │ ├── beit_base.py │ │ ├── beit_large.py │ │ ├── daformer_aspp_mitb5.py │ │ ├── daformer_conv1_mitb5.py │ │ ├── daformer_isa_mitb5.py │ │ ├── daformer_r101.py │ │ ├── daformer_sepaspp_bottleneck_mitb5.py │ │ ├── daformer_sepaspp_mitb5.py │ │ ├── daformer_sepaspp_modified_mitb5.py │ │ ├── danet_r50-d8.py │ │ ├── deeplabv2_r50-d8.py │ │ ├── deeplabv2red_r101-d8.py │ │ ├── deeplabv2red_r50-d8.py │ │ ├── deeplabv3plus_r50-d8.py │ │ ├── isanet_r50-d8.py │ │ ├── pspnet_r101-d8.py │ │ ├── segformer.py │ │ ├── segformer_b5.py │ │ ├── segformer_r101.py │ │ ├── swin_base_patch4_window12.py │ │ ├── swin_base_patch4_window7.py │ │ ├── upernet_beit.py │ │ ├── upernet_ch256_mit.py │ │ ├── upernet_mit.py │ │ ├── upernet_r101.py │ │ └── upernet_swin.py │ ├── schedules │ │ ├── adamw.py │ │ ├── poly10.py │ │ └── poly10warm.py │ └── uda │ │ ├── dacs.py │ │ ├── dacs_a999_fdthings.py │ │ ├── dacs_fd.py │ │ ├── dacs_fdthings.py │ │ └── nesterov.py ├── fst_d │ ├── gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_beit_base_s0_step3.py │ ├── gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_mitb5_s0_step3.py │ ├── gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_pspnet_s0_step3.py │ ├── gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_r101_s0_step3.py │ ├── gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_r50_s0_step3.py │ └── gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_swin_s0_step3.py └── fst_w │ └── stepstep_gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_wider_differentdata_r101_s0_step3.py ├── mmseg ├── __init__.py ├── apis │ ├── __init__.py │ ├── inference.py │ ├── test.py │ └── train.py ├── core │ ├── __init__.py │ ├── ddp_wrapper.py │ ├── evaluation │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-38.pyc │ │ │ ├── class_names.cpython-38.pyc │ │ │ ├── eval_hooks.cpython-38.pyc │ │ │ └── metrics.cpython-38.pyc │ │ ├── class_names.py │ │ ├── eval_hooks.py │ │ └── metrics.py │ ├── seg │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-38.pyc │ │ │ └── builder.cpython-38.pyc │ │ ├── builder.py │ │ └── sampler │ │ │ ├── __init__.py │ │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-38.pyc │ │ │ ├── base_pixel_sampler.cpython-38.pyc │ │ │ └── ohem_pixel_sampler.cpython-38.pyc │ │ │ ├── base_pixel_sampler.py │ │ │ └── ohem_pixel_sampler.py │ └── utils │ │ ├── __init__.py │ │ ├── __pycache__ │ │ ├── __init__.cpython-38.pyc │ │ └── misc.cpython-38.pyc │ │ └── misc.py ├── datasets │ ├── __init__.py │ ├── builder.py │ ├── cityscapes.py │ ├── custom.py │ ├── dataset_wrappers.py │ ├── gta.py │ ├── gta_custom.py │ ├── pipelines │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-38.pyc │ │ │ ├── compose.cpython-38.pyc │ │ │ ├── formating.cpython-38.pyc │ │ │ ├── loading.cpython-38.pyc │ │ │ ├── test_time_aug.cpython-38.pyc │ │ │ └── transforms.cpython-38.pyc │ │ ├── compose.py │ │ ├── formating.py │ │ ├── loading.py │ │ ├── test_time_aug.py │ │ └── transforms.py │ ├── step_uda_dataset.py │ ├── synthia.py │ └── uda_dataset.py ├── models │ ├── __init__.py │ ├── backbones │ │ ├── __init__.py │ │ ├── beit.py │ │ ├── mix_transformer.py │ │ ├── resnest.py │ │ ├── resnet.py │ │ └── resnext.py │ ├── builder.py │ ├── decode_heads │ │ ├── daformer_proto_head.py │ │ ├── sep_aspp_head.py │ │ └── uper_head.py │ ├── losses │ │ ├── __init__.py │ │ ├── __pycache__ │ │ │ ├── __init__.cpython-38.pyc │ │ │ ├── accuracy.cpython-38.pyc │ │ │ ├── cross_entropy_loss.cpython-38.pyc │ │ │ └── utils.cpython-38.pyc │ │ ├── accuracy.py │ │ ├── cross_entropy_loss.py │ │ └── utils.py │ ├── necks │ │ ├── __init__.py │ │ ├── featurepyramid.py │ │ └── segformer_adapter.py │ ├── segmentors │ │ ├── __init__.py │ │ ├── base.py │ │ └── encoder_decoder.py │ ├── uda │ │ ├── __init__.py │ │ ├── dacs.py │ │ ├── fst_d.py │ │ ├── fst_w.py │ │ ├── source_only.py │ │ └── uda_decorator.py │ └── utils │ │ ├── __init__.py │ │ ├── __pycache__ │ │ ├── __init__.cpython-38.pyc │ │ ├── ckpt_convert.cpython-38.pyc │ │ ├── dacs_transforms.cpython-38.pyc │ │ ├── embed.cpython-38.pyc │ │ ├── make_divisible.cpython-38.pyc │ │ ├── res_layer.cpython-38.pyc │ │ ├── self_attention_block.cpython-38.pyc │ │ ├── shape_convert.cpython-38.pyc │ │ └── visualization.cpython-38.pyc │ │ ├── ckpt_convert.py │ │ ├── dacs_transforms.py │ │ ├── embed.py │ │ ├── make_divisible.py │ │ ├── res_layer.py │ │ ├── self_attention_block.py │ │ ├── shape_convert.py │ │ └── visualization.py ├── utils │ ├── __init__.py │ ├── collect_env.py │ ├── logger.py │ └── utils.py └── version.py ├── run_experiments.py ├── semi_seg ├── .gitignore ├── LICENSE ├── data │ └── splits │ │ ├── cityscapes │ │ ├── 186 │ │ │ ├── labeled.txt │ │ │ └── unlabeled.txt │ │ ├── 372 │ │ │ ├── labeled.txt │ │ │ └── unlabeled.txt │ │ ├── 744 │ │ │ ├── labeled.txt │ │ │ └── unlabeled.txt │ │ ├── 1488 │ │ │ ├── labeled.txt │ │ │ └── unlabeled.txt │ │ └── val.txt │ │ └── pascal │ │ ├── 92 │ │ ├── labeled.txt │ │ └── unlabeled.txt │ │ ├── 183 │ │ ├── labeled.txt │ │ └── unlabeled.txt │ │ ├── 366 │ │ ├── labeled.txt │ │ └── unlabeled.txt │ │ ├── 662 │ │ ├── labeled.txt │ │ └── unlabeled.txt │ │ ├── 732 │ │ ├── labeled.txt │ │ └── unlabeled.txt │ │ ├── 1323 │ │ ├── labeled.txt │ │ └── unlabeled.txt │ │ ├── 1464 │ │ ├── labeled.txt │ │ └── unlabeled.txt │ │ ├── 2646 │ │ ├── labeled.txt │ │ └── unlabeled.txt │ │ ├── 5291 │ │ ├── labeled.txt │ │ └── unlabeled.txt │ │ └── val.txt ├── eval.py ├── experiments │ ├── cityscapes │ │ └── 372 │ │ │ ├── mt │ │ │ ├── config.yaml │ │ │ ├── eval.sh │ │ │ └── train.sh │ │ │ └── mt_fst │ │ │ ├── config.yaml │ │ │ ├── eval.sh │ │ │ └── train.sh │ └── pascal │ │ └── 662 │ │ ├── cutmix │ │ ├── config.yaml │ │ └── train.sh │ │ ├── cutmix_fst │ │ ├── config.yaml │ │ └── train.sh │ │ ├── mt │ │ ├── config.yaml │ │ └── train.sh │ │ ├── mt_fst │ │ ├── config.yaml │ │ └── train.sh │ │ ├── psp_mt │ │ ├── config.yaml │ │ └── train.sh │ │ ├── psp_mt_fst │ │ ├── config.yaml │ │ └── train.sh │ │ ├── v2_mt │ │ ├── config.yaml │ │ └── train.sh │ │ └── v2_mt_fst │ │ ├── config.yaml │ │ └── train.sh ├── fst │ ├── __init__.py │ ├── dataset │ │ ├── __init__.py │ │ ├── augmentation.py │ │ ├── base.py │ │ ├── builder.py │ │ ├── cityscapes.py │ │ ├── pascal_voc.py │ │ └── sampler.py │ ├── models │ │ ├── __init__.py │ │ ├── base.py │ │ ├── decoder.py │ │ ├── model_helper.py │ │ └── resnet.py │ └── utils │ │ ├── __init__.py │ │ ├── dist_helper.py │ │ ├── loss_helper.py │ │ ├── lr_helper.py │ │ └── utils.py ├── requirements.txt ├── train_semi.py └── train_sup.py ├── test.sh ├── tools ├── __init__.py ├── analyze_logs.py ├── beit_convert.py ├── convert_datasets │ ├── cityscapes.py │ ├── gta.py │ └── synthia.py ├── download_checkpoints.sh ├── get_param_count.py ├── print_config.py ├── publish_model.py ├── swin_convert.py ├── test.py └── train.py └── train.sh /configs/_base_/datasets/cityscapes_half_512x512.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | # Modifications: Half image resolution 3 | 4 | # dataset settings 5 | dataset_type = 'CityscapesDataset' 6 | data_root = 'data/cityscapes/' 7 | img_norm_cfg = dict( 8 | mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True) 9 | crop_size = (512, 512) 10 | train_pipeline = [ 11 | dict(type='LoadImageFromFile'), 12 | dict(type='LoadAnnotations'), 13 | dict(type='Resize', img_scale=(1024, 512)), 14 | dict(type='RandomCrop', crop_size=crop_size, cat_max_ratio=0.75), 15 | dict(type='RandomFlip', prob=0.5), 16 | dict(type='PhotoMetricDistortion'), 17 | dict(type='Normalize', **img_norm_cfg), 18 | dict(type='Pad', size=crop_size, pad_val=0, seg_pad_val=255), 19 | dict(type='DefaultFormatBundle'), 20 | dict(type='Collect', keys=['img', 'gt_semantic_seg']), 21 | ] 22 | test_pipeline = [ 23 | dict(type='LoadImageFromFile'), 24 | dict( 25 | type='MultiScaleFlipAug', 26 | img_scale=(1024, 512), 27 | # MultiScaleFlipAug is disabled by not providing img_ratios and 28 | # setting flip=False 29 | # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75], 30 | flip=False, 31 | transforms=[ 32 | dict(type='Resize', keep_ratio=True), 33 | dict(type='RandomFlip'), 34 | dict(type='Normalize', **img_norm_cfg), 35 | dict(type='ImageToTensor', keys=['img']), 36 | dict(type='Collect', keys=['img']), 37 | ]) 38 | ] 39 | data = dict( 40 | samples_per_gpu=2, 41 | workers_per_gpu=4, 42 | train=dict( 43 | type=dataset_type, 44 | data_root=data_root, 45 | img_dir='leftImg8bit/train', 46 | ann_dir='gtFine/train', 47 | pipeline=train_pipeline), 48 | val=dict( 49 | type=dataset_type, 50 | data_root=data_root, 51 | img_dir='leftImg8bit/val', 52 | ann_dir='gtFine/val', 53 | pipeline=test_pipeline), 54 | test=dict( 55 | type=dataset_type, 56 | data_root=data_root, 57 | img_dir='leftImg8bit/val', 58 | ann_dir='gtFine/val', 59 | pipeline=test_pipeline)) 60 | -------------------------------------------------------------------------------- /configs/_base_/datasets/gta_to_cityscapes_512x512.py: -------------------------------------------------------------------------------- 1 | # dataset settings 2 | dataset_type = 'CityscapesDataset' 3 | data_root = 'data/cityscapes/' 4 | img_norm_cfg = dict( 5 | mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True) 6 | crop_size = (512, 512) 7 | train_pipeline = [ 8 | dict(type='LoadImageFromFile'), 9 | dict(type='LoadAnnotations'), 10 | dict(type='Resize', img_scale=(1280, 720)), 11 | dict(type='RandomCrop', crop_size=crop_size, cat_max_ratio=0.75), 12 | dict(type='RandomFlip', prob=0.5), 13 | dict(type='PhotoMetricDistortion'), 14 | dict(type='Normalize', **img_norm_cfg), 15 | dict(type='Pad', size=crop_size, pad_val=0, seg_pad_val=255), 16 | dict(type='DefaultFormatBundle'), 17 | dict(type='Collect', keys=['img', 'gt_semantic_seg']), 18 | ] 19 | test_pipeline = [ 20 | dict(type='LoadImageFromFile'), 21 | dict( 22 | type='MultiScaleFlipAug', 23 | img_scale=(1024, 512), 24 | # MultiScaleFlipAug is disabled by not providing img_ratios and 25 | # setting flip=False 26 | # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75], 27 | flip=False, 28 | transforms=[ 29 | dict(type='Resize', keep_ratio=True), 30 | dict(type='RandomFlip'), 31 | dict(type='Normalize', **img_norm_cfg), 32 | dict(type='ImageToTensor', keys=['img']), 33 | dict(type='Collect', keys=['img']), 34 | ]) 35 | ] 36 | data = dict( 37 | samples_per_gpu=2, 38 | workers_per_gpu=4, 39 | train=dict( 40 | type='GTADataset', 41 | data_root='data/gta/', 42 | img_dir='images', 43 | ann_dir='labels', 44 | pipeline=train_pipeline), 45 | val=dict( 46 | type='CityscapesDataset', 47 | data_root='data/cityscapes/', 48 | img_dir='leftImg8bit/val', 49 | ann_dir='gtFine/val', 50 | pipeline=test_pipeline), 51 | test=dict( 52 | type='CityscapesDataset', 53 | data_root='data/cityscapes/', 54 | img_dir='leftImg8bit/val', 55 | ann_dir='gtFine/val', 56 | pipeline=test_pipeline)) 57 | -------------------------------------------------------------------------------- /configs/_base_/datasets/stepuda_gta_to_cityscapes_512x512.py: -------------------------------------------------------------------------------- 1 | # dataset settings 2 | dataset_type = 'CityscapesDataset' 3 | data_root = 'data/cityscapes/' 4 | img_norm_cfg = dict( 5 | mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True) 6 | crop_size = (512, 512) 7 | gta_train_pipeline = [ 8 | dict(type='LoadImageFromFile'), 9 | dict(type='LoadAnnotations'), 10 | dict(type='Resize', img_scale=(1280, 720)), 11 | dict(type='RandomCrop', crop_size=crop_size, cat_max_ratio=0.75), 12 | dict(type='RandomFlip', prob=0.5), 13 | # dict(type='PhotoMetricDistortion'), # is applied later in dacs.py 14 | dict(type='Normalize', **img_norm_cfg), 15 | dict(type='Pad', size=crop_size, pad_val=0, seg_pad_val=255), 16 | dict(type='DefaultFormatBundle'), 17 | dict(type='Collect', keys=['img', 'gt_semantic_seg']), 18 | ] 19 | cityscapes_train_pipeline = [ 20 | dict(type='LoadImageFromFile'), 21 | dict(type='LoadAnnotations'), 22 | dict(type='Resize', img_scale=(1024, 512)), 23 | dict(type='RandomCrop', crop_size=crop_size), 24 | dict(type='RandomFlip', prob=0.5), 25 | # dict(type='PhotoMetricDistortion'), # is applied later in dacs.py 26 | dict(type='Normalize', **img_norm_cfg), 27 | dict(type='Pad', size=crop_size, pad_val=0, seg_pad_val=255), 28 | dict(type='DefaultFormatBundle'), 29 | dict(type='Collect', keys=['img', 'gt_semantic_seg']), 30 | ] 31 | test_pipeline = [ 32 | dict(type='LoadImageFromFile'), 33 | dict( 34 | type='MultiScaleFlipAug', 35 | img_scale=(1024, 512), 36 | # MultiScaleFlipAug is disabled by not providing img_ratios and 37 | # setting flip=False 38 | # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75], 39 | flip=False, 40 | transforms=[ 41 | dict(type='Resize', keep_ratio=True), 42 | dict(type='RandomFlip'), 43 | dict(type='Normalize', **img_norm_cfg), 44 | dict(type='ImageToTensor', keys=['img']), 45 | dict(type='Collect', keys=['img']), 46 | ]) 47 | ] 48 | data = dict( 49 | samples_per_gpu=2, 50 | workers_per_gpu=4, 51 | train=dict( 52 | type='StepUDADataset', # StepUDA Dataset 53 | source=dict( 54 | type='GTADataset', 55 | data_root='s3://SI-Team-Dev/public_dataset/gta', 56 | img_dir='images', 57 | ann_dir='labels', 58 | split_file='s3://SI-Team-Dev/public_dataset/gta/gta.txt', 59 | pipeline=gta_train_pipeline), 60 | target=dict( 61 | type='CityscapesDataset', 62 | data_root='s3://SI-Team-Dev/public_dataset/cityscapes', 63 | img_dir='leftImg8bit/train', 64 | ann_dir='gtFine/train', 65 | split_file='s3://SI-Team-Dev/public_dataset/cityscapes/train.txt', 66 | pipeline=cityscapes_train_pipeline)), 67 | val=dict( 68 | type='CityscapesDataset', 69 | data_root='s3://SI-Team-Dev/public_dataset/cityscapes', 70 | img_dir='leftImg8bit/val', 71 | ann_dir='gtFine/val', 72 | split_file='s3://SI-Team-Dev/public_dataset/cityscapes/val.txt', 73 | pipeline=test_pipeline), 74 | test=dict( 75 | type='CityscapesDataset', 76 | data_root='s3://SI-Team-Dev/public_dataset/cityscapes', 77 | img_dir='leftImg8bit/val', 78 | ann_dir='gtFine/val', 79 | split_file='s3://SI-Team-Dev/public_dataset/cityscapes/val.txt', 80 | pipeline=test_pipeline)) 81 | -------------------------------------------------------------------------------- /configs/_base_/datasets/uda_gta_to_cityscapes_512x512.py: -------------------------------------------------------------------------------- 1 | # dataset settings 2 | dataset_type = 'CityscapesDataset' 3 | data_root = 'data/cityscapes/' 4 | img_norm_cfg = dict( 5 | mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True) 6 | crop_size = (512, 512) 7 | gta_train_pipeline = [ 8 | dict(type='LoadImageFromFile'), 9 | dict(type='LoadAnnotations'), 10 | dict(type='Resize', img_scale=(1280, 720)), 11 | dict(type='RandomCrop', crop_size=crop_size, cat_max_ratio=0.75), 12 | dict(type='RandomFlip', prob=0.5), 13 | # dict(type='PhotoMetricDistortion'), # is applied later in dacs.py 14 | dict(type='Normalize', **img_norm_cfg), 15 | dict(type='Pad', size=crop_size, pad_val=0, seg_pad_val=255), 16 | dict(type='DefaultFormatBundle'), 17 | dict(type='Collect', keys=['img', 'gt_semantic_seg']), 18 | ] 19 | cityscapes_train_pipeline = [ 20 | dict(type='LoadImageFromFile'), 21 | dict(type='LoadAnnotations'), 22 | dict(type='Resize', img_scale=(1024, 512)), 23 | dict(type='RandomCrop', crop_size=crop_size), 24 | dict(type='RandomFlip', prob=0.5), 25 | # dict(type='PhotoMetricDistortion'), # is applied later in dacs.py 26 | dict(type='Normalize', **img_norm_cfg), 27 | dict(type='Pad', size=crop_size, pad_val=0, seg_pad_val=255), 28 | dict(type='DefaultFormatBundle'), 29 | dict(type='Collect', keys=['img', 'gt_semantic_seg']), 30 | ] 31 | test_pipeline = [ 32 | dict(type='LoadImageFromFile'), 33 | dict( 34 | type='MultiScaleFlipAug', 35 | img_scale=(1024, 512), 36 | # MultiScaleFlipAug is disabled by not providing img_ratios and 37 | # setting flip=False 38 | # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75], 39 | flip=False, 40 | transforms=[ 41 | dict(type='Resize', keep_ratio=True), 42 | dict(type='RandomFlip'), 43 | dict(type='Normalize', **img_norm_cfg), 44 | dict(type='ImageToTensor', keys=['img']), 45 | dict(type='Collect', keys=['img']), 46 | ]) 47 | ] 48 | data = dict( 49 | samples_per_gpu=2, 50 | workers_per_gpu=4, 51 | train=dict( 52 | type='UDADataset', 53 | source=dict( 54 | type='GTADataset', 55 | data_root='s3://SI-Team-Dev/public_dataset/gta', 56 | img_dir='images', 57 | ann_dir='labels', 58 | split_file='s3://SI-Team-Dev/public_dataset/gta/gta.txt', 59 | pipeline=gta_train_pipeline), 60 | target=dict( 61 | type='CityscapesDataset', 62 | data_root='s3://SI-Team-Dev/public_dataset/cityscapes', 63 | img_dir='leftImg8bit/train', 64 | ann_dir='gtFine/train', 65 | split_file='s3://SI-Team-Dev/public_dataset/cityscapes/train.txt', 66 | pipeline=cityscapes_train_pipeline)), 67 | val=dict( 68 | type='CityscapesDataset', 69 | data_root='s3://SI-Team-Dev/public_dataset/cityscapes', 70 | img_dir='leftImg8bit/val', 71 | ann_dir='gtFine/val', 72 | split_file='s3://SI-Team-Dev/public_dataset/cityscapes/val.txt', 73 | pipeline=test_pipeline), 74 | test=dict( 75 | type='CityscapesDataset', 76 | data_root='s3://SI-Team-Dev/public_dataset/cityscapes', 77 | img_dir='leftImg8bit/val', 78 | ann_dir='gtFine/val', 79 | split_file='s3://SI-Team-Dev/public_dataset/cityscapes/val.txt', 80 | pipeline=test_pipeline)) 81 | -------------------------------------------------------------------------------- /configs/_base_/datasets/uda_gta_to_cityscapes_640x640.py: -------------------------------------------------------------------------------- 1 | # dataset settings 2 | dataset_type = 'CityscapesDataset' 3 | data_root = 'data/cityscapes/' 4 | img_norm_cfg = dict( 5 | mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True) 6 | crop_size = (640, 640) 7 | gta_train_pipeline = [ 8 | dict(type='LoadImageFromFile'), 9 | dict(type='LoadAnnotations'), 10 | dict(type='Resize', img_scale=(1280, 720)), 11 | dict(type='RandomCrop', crop_size=crop_size, cat_max_ratio=0.75), 12 | dict(type='RandomFlip', prob=0.5), 13 | # dict(type='PhotoMetricDistortion'), # is applied later in dacs.py 14 | dict(type='Normalize', **img_norm_cfg), 15 | dict(type='Pad', size=crop_size, pad_val=0, seg_pad_val=255), 16 | dict(type='DefaultFormatBundle'), 17 | dict(type='Collect', keys=['img', 'gt_semantic_seg']), 18 | ] 19 | cityscapes_train_pipeline = [ 20 | dict(type='LoadImageFromFile'), 21 | dict(type='LoadAnnotations'), 22 | dict(type='Resize', img_scale=(1280, 640)), # -> (1280, 640) 23 | dict(type='RandomCrop', crop_size=crop_size), 24 | dict(type='RandomFlip', prob=0.5), 25 | # dict(type='PhotoMetricDistortion'), # is applied later in dacs.py 26 | dict(type='Normalize', **img_norm_cfg), 27 | dict(type='Pad', size=crop_size, pad_val=0, seg_pad_val=255), 28 | dict(type='DefaultFormatBundle'), 29 | dict(type='Collect', keys=['img', 'gt_semantic_seg']), 30 | ] 31 | test_pipeline = [ 32 | dict(type='LoadImageFromFile'), 33 | dict( 34 | type='MultiScaleFlipAug', 35 | img_scale=(1280, 640), 36 | # MultiScaleFlipAug is disabled by not providing img_ratios and 37 | # setting flip=False 38 | # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75], 39 | flip=False, 40 | transforms=[ 41 | dict(type='Resize', keep_ratio=True), 42 | dict(type='RandomFlip'), 43 | dict(type='Normalize', **img_norm_cfg), 44 | dict(type='ImageToTensor', keys=['img']), 45 | dict(type='Collect', keys=['img']), 46 | ]) 47 | ] 48 | data = dict( 49 | samples_per_gpu=2, 50 | workers_per_gpu=4, 51 | train=dict( 52 | type='UDADataset', 53 | source=dict( 54 | type='GTADataset', 55 | data_root='s3://SI-Team-Dev/public_dataset/gta', 56 | img_dir='images', 57 | ann_dir='labels', 58 | split_file='s3://SI-Team-Dev/public_dataset/gta/gta.txt', 59 | pipeline=gta_train_pipeline), 60 | target=dict( 61 | type='CityscapesDataset', 62 | data_root='s3://SI-Team-Dev/public_dataset/cityscapes', 63 | img_dir='leftImg8bit/train', 64 | ann_dir='gtFine/train', 65 | split_file='s3://SI-Team-Dev/public_dataset/cityscapes/train.txt', 66 | pipeline=cityscapes_train_pipeline)), 67 | val=dict( 68 | type='CityscapesDataset', 69 | data_root='s3://SI-Team-Dev/public_dataset/cityscapes', 70 | img_dir='leftImg8bit/val', 71 | ann_dir='gtFine/val', 72 | split_file='s3://SI-Team-Dev/public_dataset/cityscapes/val.txt', 73 | pipeline=test_pipeline), 74 | test=dict( 75 | type='CityscapesDataset', 76 | data_root='s3://SI-Team-Dev/public_dataset/cityscapes', 77 | img_dir='leftImg8bit/val', 78 | ann_dir='gtFine/val', 79 | split_file='s3://SI-Team-Dev/public_dataset/cityscapes/val.txt', 80 | pipeline=test_pipeline)) 81 | -------------------------------------------------------------------------------- /configs/_base_/datasets/uda_synthia_to_cityscapes_512x512.py: -------------------------------------------------------------------------------- 1 | # dataset settings 2 | dataset_type = 'CityscapesDataset' 3 | data_root = 'data/cityscapes/' 4 | img_norm_cfg = dict( 5 | mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True) 6 | crop_size = (512, 512) 7 | synthia_train_pipeline = [ 8 | dict(type='LoadImageFromFile'), 9 | dict(type='LoadAnnotations'), 10 | dict(type='Resize', img_scale=(1280, 760)), 11 | dict(type='RandomCrop', crop_size=crop_size, cat_max_ratio=0.75), 12 | dict(type='RandomFlip', prob=0.5), 13 | # dict(type='PhotoMetricDistortion'), # is applied later in dacs.py 14 | dict(type='Normalize', **img_norm_cfg), 15 | dict(type='Pad', size=crop_size, pad_val=0, seg_pad_val=255), 16 | dict(type='DefaultFormatBundle'), 17 | dict(type='Collect', keys=['img', 'gt_semantic_seg']), 18 | ] 19 | cityscapes_train_pipeline = [ 20 | dict(type='LoadImageFromFile'), 21 | dict(type='LoadAnnotations'), 22 | dict(type='Resize', img_scale=(1024, 512)), 23 | dict(type='RandomCrop', crop_size=crop_size), 24 | dict(type='RandomFlip', prob=0.5), 25 | # dict(type='PhotoMetricDistortion'), # is applied later in dacs.py 26 | dict(type='Normalize', **img_norm_cfg), 27 | dict(type='Pad', size=crop_size, pad_val=0, seg_pad_val=255), 28 | dict(type='DefaultFormatBundle'), 29 | dict(type='Collect', keys=['img', 'gt_semantic_seg']), 30 | ] 31 | test_pipeline = [ 32 | dict(type='LoadImageFromFile'), 33 | dict( 34 | type='MultiScaleFlipAug', 35 | img_scale=(1024, 512), 36 | # MultiScaleFlipAug is disabled by not providing img_ratios and 37 | # setting flip=False 38 | # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75], 39 | flip=False, 40 | transforms=[ 41 | dict(type='Resize', keep_ratio=True), 42 | dict(type='RandomFlip'), 43 | dict(type='Normalize', **img_norm_cfg), 44 | dict(type='ImageToTensor', keys=['img']), 45 | dict(type='Collect', keys=['img']), 46 | ]) 47 | ] 48 | data = dict( 49 | samples_per_gpu=2, 50 | workers_per_gpu=4, 51 | train=dict( 52 | type='UDADataset', 53 | source=dict( 54 | type='SynthiaDataset', 55 | data_root='s3://SI-Team-Dev/public_dataset/synthia', 56 | img_dir='RGB', 57 | ann_dir='GT/LABELS', 58 | split_file='s3://SI-Team-Dev/public_dataset/synthia/synthia.txt', 59 | pipeline=synthia_train_pipeline), 60 | target=dict( 61 | type='CityscapesDataset', 62 | data_root='s3://SI-Team-Dev/public_dataset/cityscapes', 63 | img_dir='leftImg8bit/train', 64 | ann_dir='gtFine/train', 65 | split_file='s3://SI-Team-Dev/public_dataset/cityscapes/train.txt', 66 | pipeline=cityscapes_train_pipeline)), 67 | val=dict( 68 | type='CityscapesDataset', 69 | data_root='s3://SI-Team-Dev/public_dataset/cityscapes', 70 | img_dir='leftImg8bit/val', 71 | ann_dir='gtFine/val', 72 | split_file='s3://SI-Team-Dev/public_dataset/cityscapes/val.txt', 73 | pipeline=test_pipeline), 74 | test=dict( 75 | type='CityscapesDataset', 76 | data_root='s3://SI-Team-Dev/public_dataset/cityscapes', 77 | img_dir='leftImg8bit/val', 78 | ann_dir='gtFine/val', 79 | split_file='s3://SI-Team-Dev/public_dataset/cityscapes/val.txt', 80 | pipeline=test_pipeline)) 81 | -------------------------------------------------------------------------------- /configs/_base_/default_runtime.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | 3 | # yapf:disable 4 | log_config = dict( 5 | interval=50, 6 | hooks=[ 7 | dict(type='TextLoggerHook', by_epoch=False), 8 | # dict(type='TensorboardLoggerHook') 9 | ]) 10 | # yapf:enable 11 | dist_params = dict(backend='nccl') 12 | log_level = 'INFO' 13 | load_from = None 14 | resume_from = None 15 | workflow = [('train', 1)] 16 | cudnn_benchmark = True 17 | -------------------------------------------------------------------------------- /configs/_base_/models/beit_base.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../../_base_/models/upernet_beit.py' 3 | ] 4 | 5 | model = dict( 6 | pretrained='pretrained/beit_base_patch16_224_pt22k_ft22k.pth', 7 | test_cfg=dict(mode='slide', crop_size=(640, 640), stride=(426, 426)) 8 | ) 9 | 10 | -------------------------------------------------------------------------------- /configs/_base_/models/beit_large.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../../_base_/models/upernet_beit.py' 3 | ] 4 | 5 | model = dict( 6 | pretrained='pretrained/beit_large_patch16_224_pt22k_ft22k.pth', 7 | backbone=dict( 8 | type='BEiT', 9 | embed_dims=1024, 10 | num_layers=24, 11 | num_heads=16, 12 | mlp_ratio=4, 13 | qv_bias=True, 14 | init_values=1e-6, 15 | drop_path_rate=0.2, 16 | out_indices=[7, 11, 15, 23]), 17 | neck=dict(embed_dim=1024, rescales=[4, 2, 1, 0.5]), 18 | decode_head=dict( 19 | in_channels=[1024, 1024, 1024, 1024], num_classes=19, channels=1024), 20 | auxiliary_head=dict(in_channels=1024, num_classes=19), 21 | test_cfg=dict(mode='slide', crop_size=(640, 640), stride=(426, 426))) 22 | -------------------------------------------------------------------------------- /configs/_base_/models/daformer_aspp_mitb5.py: -------------------------------------------------------------------------------- 1 | # DAFormer w/o DSC in Tab. 7 2 | 3 | _base_ = ['daformer_conv1_mitb5.py'] 4 | 5 | norm_cfg = dict(type='BN', requires_grad=True) 6 | model = dict( 7 | decode_head=dict( 8 | decoder_params=dict( 9 | fusion_cfg=dict( 10 | _delete_=True, 11 | type='aspp', 12 | sep=False, 13 | dilations=(1, 6, 12, 18), 14 | pool=False, 15 | act_cfg=dict(type='ReLU'), 16 | norm_cfg=norm_cfg)))) 17 | -------------------------------------------------------------------------------- /configs/_base_/models/daformer_conv1_mitb5.py: -------------------------------------------------------------------------------- 1 | # This is the same as SegFormer but with 256 embed_dims 2 | # SegF. with C_e=256 in Tab. 7 3 | 4 | # model settings 5 | norm_cfg = dict(type='BN', requires_grad=True) 6 | find_unused_parameters = True 7 | model = dict( 8 | type='EncoderDecoder', 9 | pretrained='pretrained/mit_b5.pth', 10 | backbone=dict(type='mit_b5', style='pytorch'), 11 | decode_head=dict( 12 | type='DAFormerHead', 13 | in_channels=[64, 128, 320, 512], 14 | in_index=[0, 1, 2, 3], 15 | channels=256, 16 | dropout_ratio=0.1, 17 | num_classes=19, 18 | norm_cfg=norm_cfg, 19 | align_corners=False, 20 | decoder_params=dict( 21 | embed_dims=256, 22 | embed_cfg=dict(type='mlp', act_cfg=None, norm_cfg=None), 23 | embed_neck_cfg=dict(type='mlp', act_cfg=None, norm_cfg=None), 24 | fusion_cfg=dict( 25 | type='conv', 26 | kernel_size=1, 27 | act_cfg=dict(type='ReLU'), 28 | norm_cfg=norm_cfg), 29 | ), 30 | loss_decode=dict( 31 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 32 | # model training and testing settings 33 | train_cfg=dict(), 34 | test_cfg=dict(mode='whole')) 35 | -------------------------------------------------------------------------------- /configs/_base_/models/daformer_isa_mitb5.py: -------------------------------------------------------------------------------- 1 | # ISA Fusion in Tab. 7 2 | 3 | _base_ = ['daformer_conv1_mitb5.py'] 4 | 5 | norm_cfg = dict(type='BN', requires_grad=True) 6 | model = dict( 7 | decode_head=dict( 8 | decoder_params=dict( 9 | fusion_cfg=dict( 10 | _delete_=True, 11 | type='isa', 12 | isa_channels=256, 13 | key_query_num_convs=1, 14 | down_factor=(8, 8), 15 | act_cfg=dict(type='ReLU'), 16 | norm_cfg=norm_cfg)))) 17 | -------------------------------------------------------------------------------- /configs/_base_/models/daformer_r101.py: -------------------------------------------------------------------------------- 1 | _base_ = ['../../_base_/models/daformer_sepaspp_mitb5.py'] 2 | 3 | # model settings 4 | norm_cfg = dict(type='BN', requires_grad=True) 5 | find_unused_parameters = True 6 | model = dict( 7 | type='EncoderDecoder', 8 | # pretrained='open-mmlab://resnet101_v1c', 9 | pretrained='pretrained/resnet101_v1c-e67eebb6.pth', 10 | backbone=dict( 11 | type='ResNetV1c', 12 | depth=101, 13 | num_stages=4, 14 | out_indices=(0, 1, 2, 3), 15 | dilations=(1, 1, 2, 4), 16 | strides=(1, 2, 1, 1), 17 | norm_cfg=norm_cfg, 18 | norm_eval=False, 19 | style='pytorch', 20 | contract_dilation=True), 21 | # model training and testing settings 22 | decode_head=dict( 23 | in_channels=[256, 512, 1024, 2048], 24 | decoder_params=dict( 25 | fusion_cfg=dict( 26 | _delete_=True, 27 | type='aspp', 28 | sep=True, 29 | dilations=(1, 6, 12, 18), 30 | pool=False, 31 | act_cfg=dict(type='ReLU'), 32 | norm_cfg=norm_cfg))), 33 | train_cfg=dict(), 34 | test_cfg=dict(mode='whole')) 35 | -------------------------------------------------------------------------------- /configs/_base_/models/daformer_sepaspp_bottleneck_mitb5.py: -------------------------------------------------------------------------------- 1 | # Context only at F4 in Tab. 7 2 | 3 | _base_ = ['daformer_conv1_mitb5.py'] 4 | 5 | norm_cfg = dict(type='BN', requires_grad=True) 6 | model = dict( 7 | neck=dict(type='SegFormerAdapter', scales=[8]), 8 | decode_head=dict( 9 | decoder_params=dict( 10 | embed_neck_cfg=dict( 11 | _delete_=True, 12 | type='rawconv_and_aspp', 13 | kernel_size=1, 14 | sep=True, 15 | dilations=(1, 6, 12, 18), 16 | pool=False, 17 | act_cfg=dict(type='ReLU'), 18 | norm_cfg=norm_cfg)))) 19 | -------------------------------------------------------------------------------- /configs/_base_/models/daformer_sepaspp_mitb5.py: -------------------------------------------------------------------------------- 1 | # DAFormer (with context-aware feature fusion) in Tab. 7 2 | 3 | _base_ = ['daformer_conv1_mitb5.py'] 4 | 5 | norm_cfg = dict(type='BN', requires_grad=True) 6 | model = dict( 7 | decode_head=dict( 8 | decoder_params=dict( 9 | fusion_cfg=dict( 10 | _delete_=True, 11 | type='aspp', 12 | sep=True, 13 | dilations=(1, 6, 12, 18), 14 | pool=False, 15 | act_cfg=dict(type='ReLU'), 16 | norm_cfg=norm_cfg)))) 17 | -------------------------------------------------------------------------------- /configs/_base_/models/daformer_sepaspp_modified_mitb5.py: -------------------------------------------------------------------------------- 1 | # Test modification 2 | 3 | # This is the same as SegFormer but with 256 embed_dims 4 | # SegF. with C_e=256 in Tab. 7 5 | 6 | # model settings 7 | norm_cfg = dict(type='BN', requires_grad=True) 8 | find_unused_parameters = True 9 | model = dict( 10 | type='EncoderDecoder', 11 | pretrained='pretrained/mit_b5.pth', 12 | backbone=dict(type='mit_b5', style='pytorch'), 13 | decode_head=dict( 14 | type='DAFormer_proto_Head', 15 | in_channels=[64, 128, 320, 512], 16 | in_index=[0, 1, 2, 3], 17 | channels=256, 18 | dropout_ratio=0.1, 19 | num_classes=19, 20 | norm_cfg=norm_cfg, 21 | align_corners=False, 22 | decoder_params=dict( 23 | embed_dims=256, 24 | embed_cfg=dict(type='mlp', act_cfg=None, norm_cfg=None), 25 | embed_neck_cfg=dict(type='mlp', act_cfg=None, norm_cfg=None), 26 | fusion_cfg=dict( 27 | type='conv', 28 | kernel_size=1, 29 | act_cfg=dict(type='ReLU'), 30 | norm_cfg=norm_cfg), 31 | ), 32 | loss_decode=dict( 33 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 34 | # model training and testing settings 35 | train_cfg=dict(), 36 | test_cfg=dict(mode='whole')) 37 | -------------------------------------------------------------------------------- /configs/_base_/models/danet_r50-d8.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | # Modifications: 3 | # - BN instead of SyncBN 4 | # - Removed auxiliary decoder 5 | 6 | # model settings 7 | norm_cfg = dict(type='BN', requires_grad=True) 8 | model = dict( 9 | type='EncoderDecoder', 10 | pretrained='open-mmlab://resnet50_v1c', 11 | backbone=dict( 12 | type='ResNetV1c', 13 | depth=50, 14 | num_stages=4, 15 | out_indices=(0, 1, 2, 3), 16 | dilations=(1, 1, 2, 4), 17 | strides=(1, 2, 1, 1), 18 | norm_cfg=norm_cfg, 19 | norm_eval=False, 20 | style='pytorch', 21 | contract_dilation=True), 22 | decode_head=dict( 23 | type='DAHead', 24 | in_channels=2048, 25 | in_index=3, 26 | channels=512, 27 | pam_channels=64, 28 | dropout_ratio=0.1, 29 | num_classes=19, 30 | norm_cfg=norm_cfg, 31 | align_corners=False, 32 | loss_decode=dict( 33 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 34 | # model training and testing settings 35 | train_cfg=dict(), 36 | test_cfg=dict(mode='whole')) 37 | -------------------------------------------------------------------------------- /configs/_base_/models/deeplabv2_r50-d8.py: -------------------------------------------------------------------------------- 1 | # model settings 2 | norm_cfg = dict(type='BN', requires_grad=True) 3 | model = dict( 4 | type='EncoderDecoder', 5 | pretrained='pretrained/resnet50_v1c-2cccc1ad.pth', 6 | backbone=dict( 7 | type='ResNetV1c', 8 | depth=50, 9 | num_stages=4, 10 | out_indices=(0, 1, 2, 3), 11 | dilations=(1, 1, 2, 4), 12 | strides=(1, 2, 1, 1), 13 | norm_cfg=norm_cfg, 14 | norm_eval=False, 15 | style='pytorch', 16 | contract_dilation=True), 17 | decode_head=dict( 18 | type='DLV2Head', 19 | in_channels=2048, 20 | in_index=3, 21 | dilations=(6, 12, 18, 24), 22 | num_classes=19, 23 | align_corners=False, 24 | init_cfg=dict( 25 | type='Normal', std=0.01, override=dict(name='aspp_modules')), 26 | loss_decode=dict( 27 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 28 | # model training and testing settings 29 | train_cfg=dict(), 30 | test_cfg=dict(mode='whole')) 31 | -------------------------------------------------------------------------------- /configs/_base_/models/deeplabv2red_r101-d8.py: -------------------------------------------------------------------------------- 1 | _base_ = ['deeplabv2_r50-d8.py'] 2 | # Previous UDA methods only use the dilation rates 6 and 12 for DeepLabV2. 3 | # This might be a bit hidden as it is caused by a return statement WITHIN 4 | # a loop over the dilation rates: 5 | # https://github.com/wasidennis/AdaptSegNet/blob/fca9ff0f09dab45d44bf6d26091377ac66607028/model/deeplab.py#L116 6 | norm_cfg = dict(type='BN', requires_grad=True) 7 | model = dict( 8 | pretrained='pretrained/resnet101_v1c-e67eebb6.pth', 9 | backbone=dict( 10 | type='ResNetV1c', 11 | depth=101, 12 | num_stages=4, 13 | out_indices=(0, 1, 2, 3), 14 | dilations=(1, 1, 2, 4), 15 | strides=(1, 2, 1, 1), 16 | norm_cfg=norm_cfg, 17 | norm_eval=False, 18 | style='pytorch', 19 | contract_dilation=True), 20 | decode_head=dict(dilations=(6, 12))) -------------------------------------------------------------------------------- /configs/_base_/models/deeplabv2red_r50-d8.py: -------------------------------------------------------------------------------- 1 | _base_ = ['deeplabv2_r50-d8.py'] 2 | # Previous UDA methods only use the dilation rates 6 and 12 for DeepLabV2. 3 | # This might be a bit hidden as it is caused by a return statement WITHIN 4 | # a loop over the dilation rates: 5 | # https://github.com/wasidennis/AdaptSegNet/blob/fca9ff0f09dab45d44bf6d26091377ac66607028/model/deeplab.py#L116 6 | model = dict(decode_head=dict(dilations=(6, 12))) 7 | -------------------------------------------------------------------------------- /configs/_base_/models/deeplabv3plus_r50-d8.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | # Modifications: 3 | # - BN instead of SyncBN 4 | # - Removed auxiliary decoder 5 | 6 | # model settings 7 | norm_cfg = dict(type='BN', requires_grad=True) 8 | model = dict( 9 | type='EncoderDecoder', 10 | # pretrained='pretrained/resnet50_v1c', 11 | pretrained='pretrained/resnet50_v1c-2cccc1ad.pth', 12 | backbone=dict( 13 | type='ResNetV1c', 14 | depth=50, 15 | num_stages=4, 16 | out_indices=(0, 1, 2, 3), 17 | dilations=(1, 1, 2, 4), 18 | strides=(1, 2, 1, 1), 19 | norm_cfg=norm_cfg, 20 | norm_eval=False, 21 | style='pytorch', 22 | contract_dilation=True), 23 | decode_head=dict( 24 | type='DepthwiseSeparableASPPHead', 25 | in_channels=2048, 26 | in_index=3, 27 | channels=512, 28 | dilations=(1, 12, 24, 36), 29 | c1_in_channels=256, 30 | c1_channels=48, 31 | dropout_ratio=0.1, 32 | num_classes=19, 33 | norm_cfg=norm_cfg, 34 | align_corners=False, 35 | loss_decode=dict( 36 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 37 | # model training and testing settings 38 | train_cfg=dict(), 39 | test_cfg=dict(mode='whole')) 40 | -------------------------------------------------------------------------------- /configs/_base_/models/isanet_r50-d8.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | # Modifications: 3 | # - BN instead of SyncBN 4 | # - Removed auxiliary decoder 5 | 6 | # model settings 7 | norm_cfg = dict(type='BN', requires_grad=True) 8 | model = dict( 9 | type='EncoderDecoder', 10 | pretrained='open-mmlab://resnet50_v1c', 11 | backbone=dict( 12 | type='ResNetV1c', 13 | depth=50, 14 | num_stages=4, 15 | out_indices=(0, 1, 2, 3), 16 | dilations=(1, 1, 2, 4), 17 | strides=(1, 2, 1, 1), 18 | norm_cfg=norm_cfg, 19 | norm_eval=False, 20 | style='pytorch', 21 | contract_dilation=True), 22 | decode_head=dict( 23 | type='ISAHead', 24 | in_channels=2048, 25 | in_index=3, 26 | channels=512, 27 | isa_channels=256, 28 | down_factor=(8, 8), 29 | dropout_ratio=0.1, 30 | num_classes=19, 31 | norm_cfg=norm_cfg, 32 | align_corners=False, 33 | loss_decode=dict( 34 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 35 | # model training and testing settings 36 | train_cfg=dict(), 37 | test_cfg=dict(mode='whole')) 38 | -------------------------------------------------------------------------------- /configs/_base_/models/pspnet_r101-d8.py: -------------------------------------------------------------------------------- 1 | norm_cfg = dict(type='BN', requires_grad=True) 2 | 3 | model = dict( 4 | type='EncoderDecoder', 5 | pretrained='pretrained/resnet101_v1c-e67eebb6.pth', 6 | backbone=dict( 7 | type='ResNetV1c', 8 | depth=101, 9 | num_stages=4, 10 | out_indices=(0, 1, 2, 3), 11 | dilations=(1, 1, 2, 4), 12 | strides=(1, 2, 1, 1), 13 | norm_cfg=norm_cfg, 14 | norm_eval=False, 15 | style='pytorch', 16 | contract_dilation=True), 17 | decode_head=dict( 18 | type='PSPHead', 19 | in_channels=2048, 20 | in_index=3, 21 | channels=512, 22 | pool_scales=(1, 2, 3, 6), 23 | dropout_ratio=0.1, 24 | num_classes=19, 25 | norm_cfg=norm_cfg, 26 | align_corners=False, 27 | loss_decode=dict( 28 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 29 | train_cfg=dict(), 30 | test_cfg=dict(mode='whole') 31 | ) -------------------------------------------------------------------------------- /configs/_base_/models/segformer.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/NVlabs/SegFormer 2 | # Modifications: BN instead of SyncBN 3 | 4 | # model settings 5 | norm_cfg = dict(type='BN', requires_grad=True) 6 | find_unused_parameters = True 7 | model = dict( 8 | type='EncoderDecoder', 9 | pretrained=None, 10 | backbone=dict(type='IMTRv21_5', style='pytorch'), 11 | decode_head=dict( 12 | type='SegFormerHead', 13 | in_channels=[64, 128, 320, 512], 14 | in_index=[0, 1, 2, 3], 15 | channels=128, 16 | dropout_ratio=0.1, 17 | num_classes=19, 18 | norm_cfg=norm_cfg, 19 | align_corners=False, 20 | decoder_params=dict(), 21 | loss_decode=dict( 22 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 23 | # model training and testing settings 24 | train_cfg=dict(), 25 | test_cfg=dict(mode='whole')) 26 | -------------------------------------------------------------------------------- /configs/_base_/models/segformer_b5.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/NVlabs/SegFormer 2 | # Modifications: BN instead of SyncBN 3 | 4 | _base_ = ['../../_base_/models/segformer.py'] 5 | 6 | # model settings 7 | norm_cfg = dict(type='BN', requires_grad=True) 8 | find_unused_parameters = True 9 | model = dict( 10 | type='EncoderDecoder', 11 | pretrained='pretrained/mit_b5.pth', 12 | backbone=dict(type='mit_b5', style='pytorch'), 13 | decode_head=dict( 14 | type='SegFormerHead', 15 | in_channels=[64, 128, 320, 512], 16 | in_index=[0, 1, 2, 3], 17 | channels=128, 18 | dropout_ratio=0.1, 19 | num_classes=19, 20 | norm_cfg=norm_cfg, 21 | align_corners=False, 22 | decoder_params=dict(embed_dim=768, conv_kernel_size=1), 23 | loss_decode=dict( 24 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 25 | # model training and testing settings 26 | train_cfg=dict(), 27 | test_cfg=dict(mode='whole')) 28 | -------------------------------------------------------------------------------- /configs/_base_/models/segformer_r101.py: -------------------------------------------------------------------------------- 1 | _base_ = ['../../_base_/models/segformer.py'] 2 | 3 | # model settings 4 | norm_cfg = dict(type='BN', requires_grad=True) 5 | find_unused_parameters = True 6 | model = dict( 7 | type='EncoderDecoder', 8 | pretrained='pretrained/resnet101_v1c-e67eebb6.pth', 9 | backbone=dict( 10 | type='ResNetV1c', 11 | depth=101, 12 | num_stages=4, 13 | out_indices=(0, 1, 2, 3), 14 | dilations=(1, 1, 2, 4), 15 | strides=(1, 2, 1, 1), 16 | norm_cfg=norm_cfg, 17 | norm_eval=False, 18 | style='pytorch', 19 | contract_dilation=True), 20 | decode_head=dict( 21 | type='SegFormerHead', 22 | in_channels=[256, 512, 1024, 2048], 23 | in_index=[0, 1, 2, 3], 24 | channels=128, 25 | dropout_ratio=0.1, 26 | num_classes=19, 27 | norm_cfg=norm_cfg, 28 | align_corners=False, 29 | decoder_params=dict(embed_dim=768, conv_kernel_size=1), 30 | loss_decode=dict( 31 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 32 | # model training and testing settings 33 | train_cfg=dict(), 34 | test_cfg=dict(mode='whole')) 35 | -------------------------------------------------------------------------------- /configs/_base_/models/swin_base_patch4_window12.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../../_base_/models/upernet_swin.py', 3 | ] 4 | 5 | # checkpoint_file = 'https://download.openmmlab.com/mmsegmentation/v0.5/pretrain/swin/swin_base_patch4_window12_384_22k_20220317-e5c09f74.pth' # noqa 6 | 7 | # checkpoint_file = 'pretrained/swin_base_patch4_window12_384_22k_20220317-e5c09f74.pth' 8 | checkpoint_file = 'pretrained/swin_base_patch4_window12_384.pth' 9 | model = dict( 10 | backbone=dict( 11 | init_cfg=dict(type='Pretrained', checkpoint=checkpoint_file), 12 | pretrain_img_size=384, 13 | embed_dims=128, 14 | depths=[2, 2, 18, 2], 15 | num_heads=[4, 8, 16, 32], 16 | window_size=12, 17 | use_abs_pos_embed=False, 18 | drop_path_rate=0.3, 19 | patch_norm=True), 20 | decode_head=dict(in_channels=[128, 256, 512, 1024], num_classes=19), 21 | auxiliary_head=dict(in_channels=512, num_classes=19)) 22 | -------------------------------------------------------------------------------- /configs/_base_/models/swin_base_patch4_window7.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../../_base_/models/upernet_swin.py', 3 | ] 4 | 5 | # checkpoint_file = 'https://download.openmmlab.com/mmsegmentation/v0.5/pretrain/swin/swin_base_patch4_window12_384_22k_20220317-e5c09f74.pth' # noqa 6 | 7 | checkpoint_file = 'https://download.openmmlab.com/mmsegmentation/v0.5/pretrain/swin/swin_large_patch4_window7_224_22k_20220308-d5bdebaf.pth' # noqa 8 | # checkpoint_file = 'pretrained/swin_base_patch4_window12_384.pth' 9 | 10 | model = dict( 11 | type='EncoderDecoder', 12 | pretrained=checkpoint_file, 13 | backbone=dict( 14 | _delete_=True, 15 | type='SwinTransformer', 16 | embed_dims=192, 17 | depths=[2, 2, 18, 2], 18 | num_heads=[6, 12, 24, 48], 19 | window_size=7, 20 | mlp_ratio=4, 21 | qkv_bias=True, 22 | qk_scale=None, 23 | drop_rate=0., 24 | attn_drop_rate=0., 25 | drop_path_rate=0.3, 26 | use_abs_pos_embed=False, 27 | patch_norm=True, 28 | out_indices=(0, 1, 2, 3)), 29 | decode_head=dict(in_channels=[192, 384, 768, 1536], num_classes=19), 30 | auxiliary_head=dict(in_channels=768, num_classes=19)) -------------------------------------------------------------------------------- /configs/_base_/models/upernet_beit.py: -------------------------------------------------------------------------------- 1 | norm_cfg = dict(type='BN', requires_grad=True) 2 | model = dict( 3 | type='EncoderDecoder', 4 | pretrained=None, 5 | backbone=dict( 6 | type='BEiT', 7 | img_size=(640, 640), 8 | patch_size=16, 9 | in_channels=3, 10 | embed_dims=768, 11 | num_layers=12, 12 | num_heads=12, 13 | mlp_ratio=4, 14 | out_indices=(3, 5, 7, 11), 15 | qv_bias=True, 16 | attn_drop_rate=0.0, 17 | drop_path_rate=0.1, 18 | norm_cfg=dict(type='LN', eps=1e-6), 19 | act_cfg=dict(type='GELU'), 20 | norm_eval=False, 21 | init_values=0.1), 22 | neck=dict( 23 | type='Feature2Pyramid', 24 | embed_dim=768, 25 | rescales=[4, 2, 1, 0.5], 26 | norm_cfg=norm_cfg), 27 | decode_head=dict( 28 | type='UPerHead', 29 | in_channels=[768, 768, 768, 768], 30 | in_index=[0, 1, 2, 3], 31 | pool_scales=(1, 2, 3, 6), 32 | channels=768, 33 | dropout_ratio=0.1, 34 | num_classes=19, 35 | norm_cfg=norm_cfg, 36 | align_corners=False, 37 | loss_decode=dict( 38 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 39 | auxiliary_head=dict( 40 | type='FCNHead', 41 | in_channels=768, 42 | in_index=2, 43 | channels=256, 44 | num_convs=1, 45 | concat_input=False, 46 | dropout_ratio=0.1, 47 | num_classes=19, 48 | norm_cfg=norm_cfg, 49 | align_corners=False, 50 | loss_decode=dict( 51 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=0.4)), 52 | # model training and testing settings 53 | train_cfg=dict(), 54 | test_cfg=dict(mode='whole')) -------------------------------------------------------------------------------- /configs/_base_/models/upernet_ch256_mit.py: -------------------------------------------------------------------------------- 1 | _base_ = ['upernet_mit.py'] 2 | 3 | model = dict(decode_head=dict(channels=256, )) 4 | -------------------------------------------------------------------------------- /configs/_base_/models/upernet_mit.py: -------------------------------------------------------------------------------- 1 | # model settings 2 | norm_cfg = dict(type='BN', requires_grad=True) 3 | find_unused_parameters = True 4 | model = dict( 5 | type='EncoderDecoder', 6 | pretrained=None, 7 | backbone=dict(type='IMTRv21_5', style='pytorch'), 8 | decode_head=dict( 9 | type='UPerHead', 10 | in_channels=[64, 128, 320, 512], 11 | in_index=[0, 1, 2, 3], 12 | pool_scales=(1, 2, 3, 6), 13 | channels=512, 14 | dropout_ratio=0.1, 15 | num_classes=19, 16 | norm_cfg=norm_cfg, 17 | align_corners=False, 18 | loss_decode=dict( 19 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 20 | # model training and testing settings 21 | train_cfg=dict(), 22 | test_cfg=dict(mode='whole')) 23 | -------------------------------------------------------------------------------- /configs/_base_/models/upernet_r101.py: -------------------------------------------------------------------------------- 1 | # model settings 2 | norm_cfg = dict(type='BN', requires_grad=True) 3 | find_unused_parameters = True 4 | model = dict( 5 | type='EncoderDecoder', 6 | pretrained='pretrained/resnet101_v1c-e67eebb6.pth', 7 | backbone=dict( 8 | type='ResNetV1c', 9 | depth=101, 10 | num_stages=4, 11 | out_indices=(0, 1, 2, 3), 12 | dilations=(1, 1, 2, 4), 13 | strides=(1, 2, 1, 1), 14 | norm_cfg=norm_cfg, 15 | norm_eval=False, 16 | style='pytorch', 17 | contract_dilation=True), 18 | decode_head=dict( 19 | type='UPerHead', 20 | in_channels=[256, 512, 1024, 2048], 21 | in_index=[0, 1, 2, 3], 22 | pool_scales=(1, 2, 3, 6), 23 | channels=512, 24 | dropout_ratio=0.1, 25 | num_classes=19, 26 | norm_cfg=norm_cfg, 27 | align_corners=False, 28 | loss_decode=dict( 29 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 30 | # model training and testing settings 31 | train_cfg=dict(), 32 | test_cfg=dict(mode='whole')) 33 | -------------------------------------------------------------------------------- /configs/_base_/models/upernet_swin.py: -------------------------------------------------------------------------------- 1 | # model settings 2 | norm_cfg = dict(type='BN', requires_grad=True) 3 | backbone_norm_cfg = dict(type='LN', requires_grad=True) 4 | model = dict( 5 | type='EncoderDecoder', 6 | pretrained=None, 7 | backbone=dict( 8 | type='SwinTransformer', 9 | pretrain_img_size=224, 10 | embed_dims=96, 11 | patch_size=4, 12 | window_size=7, 13 | mlp_ratio=4, 14 | depths=[2, 2, 6, 2], 15 | num_heads=[3, 6, 12, 24], 16 | strides=(4, 2, 2, 2), 17 | out_indices=(0, 1, 2, 3), 18 | qkv_bias=True, 19 | qk_scale=None, 20 | patch_norm=True, 21 | drop_rate=0., 22 | attn_drop_rate=0., 23 | drop_path_rate=0.3, 24 | use_abs_pos_embed=False, 25 | act_cfg=dict(type='GELU'), 26 | norm_cfg=backbone_norm_cfg), 27 | decode_head=dict( 28 | type='UPerHead', 29 | in_channels=[96, 192, 384, 768], 30 | in_index=[0, 1, 2, 3], 31 | pool_scales=(1, 2, 3, 6), 32 | channels=512, 33 | dropout_ratio=0.1, 34 | num_classes=19, 35 | norm_cfg=norm_cfg, 36 | align_corners=False, 37 | loss_decode=dict( 38 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 39 | auxiliary_head=dict( 40 | type='FCNHead', 41 | in_channels=384, 42 | in_index=2, 43 | channels=256, 44 | num_convs=1, 45 | concat_input=False, 46 | dropout_ratio=0.1, 47 | num_classes=19, 48 | norm_cfg=norm_cfg, 49 | align_corners=False, 50 | loss_decode=dict( 51 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=0.4)), 52 | # model training and testing settings 53 | train_cfg=dict(), 54 | test_cfg=dict(mode='whole')) -------------------------------------------------------------------------------- /configs/_base_/schedules/adamw.py: -------------------------------------------------------------------------------- 1 | # optimizer 2 | optimizer = dict( 3 | type='AdamW', lr=0.00006, betas=(0.9, 0.999), weight_decay=0.01) 4 | optimizer_config = dict() 5 | -------------------------------------------------------------------------------- /configs/_base_/schedules/poly10.py: -------------------------------------------------------------------------------- 1 | # learning policy 2 | lr_config = dict(policy='poly', power=1.0, min_lr=1e-4, by_epoch=False) 3 | -------------------------------------------------------------------------------- /configs/_base_/schedules/poly10warm.py: -------------------------------------------------------------------------------- 1 | # learning policy 2 | lr_config = dict( 3 | policy='poly', 4 | warmup='linear', 5 | warmup_iters=1500, 6 | warmup_ratio=1e-6, 7 | power=1.0, 8 | min_lr=0.0, 9 | by_epoch=False) 10 | -------------------------------------------------------------------------------- /configs/_base_/uda/dacs.py: -------------------------------------------------------------------------------- 1 | # Baseline UDA 2 | uda = dict( 3 | type='DACS', 4 | alpha=0.99, 5 | pseudo_threshold=0.968, 6 | pseudo_weight_ignore_top=0, 7 | pseudo_weight_ignore_bottom=0, 8 | imnet_feature_dist_lambda=0, 9 | imnet_feature_dist_classes=None, 10 | imnet_feature_dist_scale_min_ratio=None, 11 | mix='class', 12 | blur=True, 13 | color_jitter_strength=0.2, 14 | color_jitter_probability=0.2, 15 | debug_img_interval=1000, 16 | print_grad_magnitude=False, 17 | ) 18 | use_ddp_wrapper = True 19 | -------------------------------------------------------------------------------- /configs/_base_/uda/dacs_a999_fdthings.py: -------------------------------------------------------------------------------- 1 | # UDA with Thing-Class ImageNet Feature Distance + Increased Alpha 2 | _base_ = ['dacs.py'] 3 | uda = dict( 4 | alpha=0.999, 5 | imnet_feature_dist_lambda=0.005, 6 | imnet_feature_dist_classes=[6, 7, 11, 12, 13, 14, 15, 16, 17, 18], 7 | imnet_feature_dist_scale_min_ratio=0.75, 8 | ) 9 | -------------------------------------------------------------------------------- /configs/_base_/uda/dacs_fd.py: -------------------------------------------------------------------------------- 1 | # UDA with ImageNet Feature Distance 2 | _base_ = ['dacs.py'] 3 | uda = dict(imnet_feature_dist_lambda=0.005, ) 4 | -------------------------------------------------------------------------------- /configs/_base_/uda/dacs_fdthings.py: -------------------------------------------------------------------------------- 1 | # UDA with Thing-Class ImageNet Feature Distance 2 | _base_ = ['dacs.py'] 3 | uda = dict( 4 | imnet_feature_dist_lambda=0.005, 5 | imnet_feature_dist_classes=[6, 7, 11, 12, 13, 14, 15, 16, 17, 18], 6 | imnet_feature_dist_scale_method='ratio', 7 | imnet_feature_dist_scale_min_ratio=0.75, 8 | ) 9 | -------------------------------------------------------------------------------- /configs/_base_/uda/nesterov.py: -------------------------------------------------------------------------------- 1 | # Baseline UDA 2 | uda = dict( 3 | type='NESTEROV', 4 | alpha=0.99, 5 | pseudo_threshold=0.968, 6 | pseudo_weight_ignore_top=0, 7 | pseudo_weight_ignore_bottom=0, 8 | imnet_feature_dist_lambda=0, 9 | imnet_feature_dist_classes=None, 10 | imnet_feature_dist_scale_min_ratio=None, 11 | mix='class', 12 | blur=True, 13 | color_jitter_strength=0.2, 14 | color_jitter_probability=0.2, 15 | debug_img_interval=1000, 16 | print_grad_magnitude=False, 17 | ) 18 | use_ddp_wrapper = True 19 | -------------------------------------------------------------------------------- /configs/fst_d/gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_beit_base_s0_step3.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/default_runtime.py', 3 | # DAFormer Network Architecture 4 | '../_base_/models/beit_base.py', 5 | # GTA->Cityscapes Data Loading 6 | '../_base_/datasets/uda_gta_to_cityscapes_640x640.py', 7 | # Basic UDA Self-Training 8 | '../_base_/uda/nesterov.py', 9 | # AdamW Optimizer 10 | '../_base_/schedules/adamw.py', 11 | # Linear Learning Rate Warmup with Subsequent Linear Decay 12 | '../_base_/schedules/poly10warm.py' 13 | ] 14 | # Random Seed 15 | seed = 0 16 | # Modifications to Basic UDA 17 | uda = dict( 18 | # Increased Alpha 19 | alpha=0.999, 20 | # Thing-Class Feature Distance 21 | imnet_feature_dist_lambda=0.005, 22 | imnet_feature_dist_classes=[6, 7, 11, 12, 13, 14, 15, 16, 17, 18], 23 | imnet_feature_dist_scale_min_ratio=0.75, 24 | # Pseudo-Label Crop 25 | pseudo_weight_ignore_top=15, 26 | pseudo_weight_ignore_bottom=120, 27 | ahead_step=3 28 | ) 29 | data = dict( 30 | train=dict( 31 | # Rare Class Sampling 32 | rare_class_sampling=dict( 33 | min_pixels=3000, class_temp=0.01, min_crop_ratio=0.5))) 34 | # Optimizer Hyperparameters 35 | optimizer_config = None 36 | optimizer = dict( 37 | lr=6e-05, 38 | paramwise_cfg=dict( 39 | custom_keys=dict( 40 | head=dict(lr_mult=10.0), 41 | pos_block=dict(decay_mult=0.0), 42 | norm=dict(decay_mult=0.0)))) 43 | n_gpus = 1 44 | runner = dict(type='IterBasedRunner', max_iters=40000) 45 | # Logging Configuration 46 | checkpoint_config = dict(by_epoch=False, interval=40000, max_keep_ckpts=0) 47 | evaluation = dict(interval=2000, metric='mIoU', save_best='mIoU') 48 | # Meta Information for Result Analysis 49 | name = 'gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_beit_base_s0_step3' 50 | exp = 'basic' 51 | name_dataset = 'gta2cityscapes' 52 | name_architecture = 'beit_upernet' 53 | name_encoder = 'beit_b' 54 | name_decoder = 'upernet' 55 | name_uda = 'dacs_a999_fd_things_rcs0.01_cpl' 56 | name_opt = 'adamw_6e-05_pmTrue_poly10warm_1x2_40k' -------------------------------------------------------------------------------- /configs/fst_d/gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_mitb5_s0_step3.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/default_runtime.py', 3 | # DAFormer Network Architecture 4 | '../_base_/models/daformer_sepaspp_mitb5.py', 5 | # GTA->Cityscapes Data Loading 6 | '../_base_/datasets/uda_gta_to_cityscapes_512x512.py', 7 | # Basic UDA Self-Training 8 | '../_base_/uda/nesterov.py', 9 | # AdamW Optimizer 10 | '../_base_/schedules/adamw.py', 11 | # Linear Learning Rate Warmup with Subsequent Linear Decay 12 | '../_base_/schedules/poly10warm.py' 13 | ] 14 | # Random Seed 15 | seed = 0 16 | # Modifications to Basic UDA 17 | uda = dict( 18 | # Increased Alpha 19 | alpha=0.999, 20 | # Thing-Class Feature Distance 21 | imnet_feature_dist_lambda=0.005, 22 | imnet_feature_dist_classes=[6, 7, 11, 12, 13, 14, 15, 16, 17, 18], 23 | imnet_feature_dist_scale_min_ratio=0.75, 24 | # Pseudo-Label Crop 25 | pseudo_weight_ignore_top=15, 26 | pseudo_weight_ignore_bottom=120, 27 | ahead_step=3) 28 | data = dict( 29 | train=dict( 30 | # Rare Class Sampling 31 | rare_class_sampling=dict( 32 | min_pixels=3000, class_temp=0.01, min_crop_ratio=0.5))) 33 | # Optimizer Hyperparameters 34 | optimizer_config = None 35 | optimizer = dict( 36 | lr=6e-05, 37 | paramwise_cfg=dict( 38 | custom_keys=dict( 39 | head=dict(lr_mult=10.0), 40 | pos_block=dict(decay_mult=0.0), 41 | norm=dict(decay_mult=0.0)))) 42 | n_gpus = 1 43 | runner = dict(type='IterBasedRunner', max_iters=40000) 44 | # Logging Configuration 45 | checkpoint_config = dict(by_epoch=False, interval=40000, max_keep_ckpts=0) 46 | evaluation = dict(interval=2000, metric='mIoU', save_best='mIoU') 47 | # Meta Information for Result Analysis 48 | name = 'gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_mitb5_s0_step3' 49 | exp = 'basic' 50 | name_dataset = 'gta2cityscapes' 51 | name_architecture = 'nesterov_sepaspp_mitb5' 52 | name_encoder = 'mitb5' 53 | name_decoder = 'daformer_sepaspp' 54 | name_uda = 'dacs_a999_fd_things_rcs0.01_cpl' 55 | name_opt = 'adamw_6e-05_pmTrue_poly10warm_1x2_40k' -------------------------------------------------------------------------------- /configs/fst_d/gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_pspnet_s0_step3.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/default_runtime.py', 3 | # DAFormer Network Architecture 4 | '../_base_/models/pspnet_r101-d8.py', 5 | # GTA->Cityscapes Data Loading 6 | '../_base_/datasets/uda_gta_to_cityscapes_512x512.py', 7 | # Basic UDA Self-Training 8 | '../_base_/uda/nesterov.py', 9 | # AdamW Optimizer 10 | '../_base_/schedules/adamw.py', 11 | # Linear Learning Rate Warmup with Subsequent Linear Decay 12 | '../_base_/schedules/poly10warm.py' 13 | ] 14 | # Random Seed 15 | seed = 0 16 | # Modifications to Basic UDA 17 | uda = dict( 18 | # Increased Alpha 19 | alpha=0.999, 20 | # Thing-Class Feature Distance 21 | imnet_feature_dist_lambda=0.005, 22 | imnet_feature_dist_classes=[6, 7, 11, 12, 13, 14, 15, 16, 17, 18], 23 | imnet_feature_dist_scale_min_ratio=0.75, 24 | # Pseudo-Label Crop 25 | pseudo_weight_ignore_top=15, 26 | pseudo_weight_ignore_bottom=120, 27 | ahead_step=3) 28 | data = dict( 29 | train=dict( 30 | # Rare Class Sampling 31 | rare_class_sampling=dict( 32 | min_pixels=3000, class_temp=0.01, min_crop_ratio=0.5))) 33 | # Optimizer Hyperparameters 34 | optimizer_config = None 35 | optimizer = dict( 36 | lr=6e-05, 37 | paramwise_cfg=dict( 38 | custom_keys=dict( 39 | head=dict(lr_mult=10.0), 40 | pos_block=dict(decay_mult=0.0), 41 | norm=dict(decay_mult=0.0)))) 42 | n_gpus = 1 43 | runner = dict(type='IterBasedRunner', max_iters=40000) 44 | 45 | # Logging Configuration 46 | checkpoint_config = dict(by_epoch=False, interval=40001, max_keep_ckpts=0) 47 | evaluation = dict(interval=2000, metric='mIoU') 48 | # Meta Information for Result Analysis 49 | name = 'gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_r101_pspnet_s0_step3' 50 | exp = 'basic' 51 | name_dataset = 'gta2cityscapes' 52 | name_architecture = 'nesterov_sepaspp_mitb5' 53 | name_encoder = 'mitb5' 54 | name_decoder = 'daformer_sepaspp' 55 | name_uda = 'dacs_a999_fd_things_rcs0.01_cpl' 56 | name_opt = 'adamw_6e-05_pmTrue_poly10warm_1x2_40k' -------------------------------------------------------------------------------- /configs/fst_d/gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_r101_s0_step3.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/default_runtime.py', 3 | # DAFormer Network Architecture 4 | # '../_base_/models/daformer_sepaspp_mitb5.py', 5 | '../_base_/models/deeplabv2red_r101-d8.py', 6 | # GTA->Cityscapes Data Loading 7 | '../_base_/datasets/uda_gta_to_cityscapes_512x512.py', 8 | # Basic UDA Self-Training 9 | '../_base_/uda/nesterov.py', 10 | # AdamW Optimizer 11 | '../_base_/schedules/adamw.py', 12 | # Linear Learning Rate Warmup with Subsequent Linear Decay 13 | '../_base_/schedules/poly10warm.py' 14 | ] 15 | # Random Seed 16 | seed = 0 17 | # Modifications to Basic UDA 18 | uda = dict( 19 | # Increased Alpha 20 | alpha=0.999, 21 | # Thing-Class Feature Distance 22 | imnet_feature_dist_lambda=0.005, 23 | imnet_feature_dist_classes=[6, 7, 11, 12, 13, 14, 15, 16, 17, 18], 24 | imnet_feature_dist_scale_min_ratio=0.75, 25 | # Pseudo-Label Crop 26 | pseudo_weight_ignore_top=15, 27 | pseudo_weight_ignore_bottom=120, 28 | ahead_step=3) 29 | data = dict( 30 | train=dict( 31 | # Rare Class Sampling 32 | rare_class_sampling=dict( 33 | min_pixels=3000, class_temp=0.01, min_crop_ratio=0.5))) 34 | # Optimizer Hyperparameters 35 | optimizer_config = None 36 | optimizer = dict( 37 | lr=6e-05, 38 | paramwise_cfg=dict( 39 | custom_keys=dict( 40 | head=dict(lr_mult=10.0), 41 | pos_block=dict(decay_mult=0.0), 42 | norm=dict(decay_mult=0.0)))) 43 | n_gpus = 1 44 | runner = dict(type='IterBasedRunner', max_iters=40000) 45 | # Logging Configuration 46 | checkpoint_config = dict(by_epoch=False, interval=40000, max_keep_ckpts=1) 47 | evaluation = dict(interval=2000, metric='mIoU', save_best='mIoU') 48 | # Meta Information for Result Analysis 49 | name = 'gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_r101_s0_step3' 50 | exp = 'basic' 51 | name_dataset = 'gta2cityscapes' 52 | name_architecture = 'nesterov_dlv2head_r101' 53 | name_encoder = 'r101' 54 | name_decoder = 'dlv2head' 55 | name_uda = 'dacs_a999_fd_things_rcs0.01_cpl' 56 | name_opt = 'adamw_6e-05_pmTrue_poly10warm_1x2_40k' -------------------------------------------------------------------------------- /configs/fst_d/gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_r50_s0_step3.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/default_runtime.py', 3 | # DAFormer Network Architecture 4 | # '../_base_/models/daformer_sepaspp_mitb5.py', 5 | '../_base_/models/deeplabv2red_r50-d8.py', 6 | # GTA->Cityscapes Data Loading 7 | '../_base_/datasets/uda_gta_to_cityscapes_512x512.py', 8 | # Basic UDA Self-Training 9 | '../_base_/uda/nesterov.py', 10 | # AdamW Optimizer 11 | '../_base_/schedules/adamw.py', 12 | # Linear Learning Rate Warmup with Subsequent Linear Decay 13 | '../_base_/schedules/poly10warm.py' 14 | ] 15 | # Random Seed 16 | seed = 0 17 | # Modifications to Basic UDA 18 | uda = dict( 19 | # Increased Alpha 20 | alpha=0.999, 21 | # Thing-Class Feature Distance 22 | imnet_feature_dist_lambda=0.005, 23 | imnet_feature_dist_classes=[6, 7, 11, 12, 13, 14, 15, 16, 17, 18], 24 | imnet_feature_dist_scale_min_ratio=0.75, 25 | # Pseudo-Label Crop 26 | pseudo_weight_ignore_top=15, 27 | pseudo_weight_ignore_bottom=120, 28 | ahead_step=3) 29 | data = dict( 30 | train=dict( 31 | # Rare Class Sampling 32 | rare_class_sampling=dict( 33 | min_pixels=3000, class_temp=0.01, min_crop_ratio=0.5))) 34 | # Optimizer Hyperparameters 35 | optimizer_config = None 36 | optimizer = dict( 37 | lr=6e-05, 38 | paramwise_cfg=dict( 39 | custom_keys=dict( 40 | head=dict(lr_mult=10.0), 41 | pos_block=dict(decay_mult=0.0), 42 | norm=dict(decay_mult=0.0)))) 43 | n_gpus = 1 44 | runner = dict(type='IterBasedRunner', max_iters=40000) 45 | # Logging Configuration 46 | checkpoint_config = dict(by_epoch=False, interval=40000, max_keep_ckpts=0) 47 | evaluation = dict(interval=2000, metric='mIoU') 48 | # Meta Information for Result Analysis 49 | name = 'gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_r50_s0_step3' 50 | exp = 'basic' 51 | name_dataset = 'gta2cityscapes' 52 | name_architecture = 'nesterov_dlv2head_r50' 53 | name_encoder = 'r50' 54 | name_decoder = 'dlv2head' 55 | name_uda = 'dacs_a999_fd_things_rcs0.01_cpl' 56 | name_opt = 'adamw_6e-05_pmTrue_poly10warm_1x2_40k' -------------------------------------------------------------------------------- /configs/fst_d/gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_swin_s0_step3.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/default_runtime.py', 3 | # DAFormer Network Architecture 4 | '../_base_/models/swin_base_patch4_window12.py', 5 | # GTA->Cityscapes Data Loading 6 | '../_base_/datasets/uda_gta_to_cityscapes_512x512.py', 7 | # Basic UDA Self-Training 8 | '../_base_/uda/nesterov.py', 9 | # AdamW Optimizer 10 | '../_base_/schedules/adamw.py', 11 | # Linear Learning Rate Warmup with Subsequent Linear Decay 12 | '../_base_/schedules/poly10warm.py' 13 | ] 14 | # Random Seed 15 | seed = 0 16 | # Modifications to Basic UDA 17 | uda = dict( 18 | # Increased Alpha 19 | alpha=0.999, 20 | # Thing-Class Feature Distance 21 | imnet_feature_dist_lambda=0.005, 22 | imnet_feature_dist_classes=[6, 7, 11, 12, 13, 14, 15, 16, 17, 18], 23 | imnet_feature_dist_scale_min_ratio=0.75, 24 | # Pseudo-Label Crop 25 | pseudo_weight_ignore_top=15, 26 | pseudo_weight_ignore_bottom=120, 27 | ahead_step=3) 28 | data = dict( 29 | train=dict( 30 | # Rare Class Sampling 31 | rare_class_sampling=dict( 32 | min_pixels=3000, class_temp=0.01, min_crop_ratio=0.5))) 33 | # Optimizer Hyperparameters 34 | optimizer_config = None 35 | optimizer = dict( 36 | lr=6e-05, 37 | paramwise_cfg=dict( 38 | custom_keys=dict( 39 | head=dict(lr_mult=10.0), 40 | pos_block=dict(decay_mult=0.0), 41 | norm=dict(decay_mult=0.0)))) 42 | n_gpus = 1 43 | runner = dict(type='IterBasedRunner', max_iters=40000) 44 | # Logging Configuration 45 | checkpoint_config = dict(by_epoch=False, interval=40000, max_keep_ckpts=0) 46 | evaluation = dict(interval=2000, metric='mIoU', save_best='mIoU') 47 | # Meta Information for Result Analysis 48 | name = 'gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_swin_s0_step3' 49 | exp = 'basic' 50 | name_dataset = 'gta2cityscapes' 51 | name_architecture = 'nesterov_swin_upernet' 52 | name_encoder = 'swin_b' 53 | name_decoder = 'upernet' 54 | name_uda = 'dacs_a999_fd_things_rcs0.01_cpl' 55 | name_opt = 'adamw_6e-05_pmTrue_poly10warm_1x2_40k' -------------------------------------------------------------------------------- /configs/fst_w/stepstep_gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_wider_differentdata_r101_s0_step3.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/default_runtime.py', 3 | # DAFormer Network Architecture 4 | # '../_base_/models/daformer_sepaspp_mitb5.py', 5 | '../_base_/models/deeplabv2red_r101-d8.py', 6 | # GTA->Cityscapes Data Loading 7 | '../_base_/datasets/stepuda_gta_to_cityscapes_512x512.py', # stepuda 8 | # Basic UDA Self-Training 9 | '../_base_/uda/nesterov.py', 10 | # AdamW Optimizer 11 | '../_base_/schedules/adamw.py', 12 | # Linear Learning Rate Warmup with Subsequent Linear Decay 13 | '../_base_/schedules/poly10warm.py' 14 | ] 15 | # Random Seed 16 | seed = 0 17 | # Modifications to Basic UDA 18 | uda = dict( 19 | # Increased Alpha 20 | type='Wider_NESTEROV_DifData', 21 | alpha=0.999, 22 | # Thing-Class Feature Distance 23 | imnet_feature_dist_lambda=0.005, 24 | imnet_feature_dist_classes=[6, 7, 11, 12, 13, 14, 15, 16, 17, 18], 25 | imnet_feature_dist_scale_min_ratio=0.75, 26 | # Pseudo-Label Crop 27 | pseudo_weight_ignore_top=15, 28 | pseudo_weight_ignore_bottom=120, 29 | ahead_step=3) 30 | 31 | data = dict( 32 | train=dict( 33 | ahead_step=3, # used for data loader 34 | # Rare Class Sampling 35 | rare_class_sampling=dict( 36 | min_pixels=3000, class_temp=0.01, min_crop_ratio=0.5))) 37 | # Optimizer Hyperparameters 38 | optimizer_config = None 39 | optimizer = dict( 40 | lr=6e-05, 41 | paramwise_cfg=dict( 42 | custom_keys=dict( 43 | head=dict(lr_mult=10.0), 44 | pos_block=dict(decay_mult=0.0), 45 | norm=dict(decay_mult=0.0)))) 46 | n_gpus = 1 47 | runner = dict(type='IterBasedRunner', max_iters=40000) 48 | # Logging Configuration 49 | checkpoint_config = dict(by_epoch=False, interval=40001, max_keep_ckpts=0) 50 | evaluation = dict(interval=2000, metric='mIoU') 51 | 52 | # Meta Information for Result Analysis 53 | name = 'step_diffferentdata_gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterovw_r101_s0_step3' 54 | exp = 'basic' 55 | name_dataset = 'stepgta2cityscapes' 56 | name_architecture = 'wider_nesterov_dlv2head_r101' 57 | name_encoder = 'r101' 58 | name_decoder = 'dlv2head' 59 | name_uda = 'dacs_a999_fd_things_rcs0.01_cpl' 60 | name_opt = 'adamw_6e-05_pmTrue_poly10warm_1x2_40k' 61 | 62 | -------------------------------------------------------------------------------- /mmseg/__init__.py: -------------------------------------------------------------------------------- 1 | import mmcv 2 | 3 | from .version import __version__, version_info 4 | 5 | MMCV_MIN = '1.3.7' 6 | MMCV_MAX = '1.4.0' 7 | 8 | 9 | def digit_version(version_str): 10 | digit_version = [] 11 | for x in version_str.split('.'): 12 | if x.isdigit(): 13 | digit_version.append(int(x)) 14 | elif x.find('rc') != -1: 15 | patch_version = x.split('rc') 16 | digit_version.append(int(patch_version[0]) - 1) 17 | digit_version.append(int(patch_version[1])) 18 | return digit_version 19 | 20 | 21 | mmcv_min_version = digit_version(MMCV_MIN) 22 | mmcv_max_version = digit_version(MMCV_MAX) 23 | mmcv_version = digit_version(mmcv.__version__) 24 | 25 | 26 | assert (mmcv_min_version <= mmcv_version <= mmcv_max_version), \ 27 | f'MMCV=={mmcv.__version__} is used but incompatible. ' \ 28 | f'Please install mmcv>={mmcv_min_version}, <={mmcv_max_version}.' 29 | 30 | __all__ = ['__version__', 'version_info'] 31 | -------------------------------------------------------------------------------- /mmseg/apis/__init__.py: -------------------------------------------------------------------------------- 1 | from .inference import inference_segmentor, init_segmentor, show_result_pyplot 2 | from .test import multi_gpu_test, single_gpu_test 3 | from .train import get_root_logger, set_random_seed, train_segmentor 4 | 5 | __all__ = [ 6 | 'get_root_logger', 'set_random_seed', 'train_segmentor', 'init_segmentor', 7 | 'inference_segmentor', 'multi_gpu_test', 'single_gpu_test', 8 | 'show_result_pyplot' 9 | ] 10 | -------------------------------------------------------------------------------- /mmseg/core/__init__.py: -------------------------------------------------------------------------------- 1 | from .evaluation import * # noqa: F401, F403 2 | from .seg import * # noqa: F401, F403 3 | from .utils import * # noqa: F401, F403 4 | -------------------------------------------------------------------------------- /mmseg/core/evaluation/__init__.py: -------------------------------------------------------------------------------- 1 | from .class_names import get_classes, get_palette 2 | from .eval_hooks import DistEvalHook, EvalHook 3 | from .metrics import eval_metrics, mean_dice, mean_fscore, mean_iou 4 | 5 | __all__ = [ 6 | 'EvalHook', 'DistEvalHook', 'mean_dice', 'mean_iou', 'mean_fscore', 7 | 'eval_metrics', 'get_classes', 'get_palette' 8 | ] 9 | -------------------------------------------------------------------------------- /mmseg/core/evaluation/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/core/evaluation/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/core/evaluation/__pycache__/class_names.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/core/evaluation/__pycache__/class_names.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/core/evaluation/__pycache__/eval_hooks.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/core/evaluation/__pycache__/eval_hooks.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/core/evaluation/__pycache__/metrics.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/core/evaluation/__pycache__/metrics.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/core/evaluation/eval_hooks.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | 3 | import os.path as osp 4 | 5 | import torch.distributed as dist 6 | from mmcv.runner import DistEvalHook as _DistEvalHook 7 | from mmcv.runner import EvalHook as _EvalHook 8 | from torch.nn.modules.batchnorm import _BatchNorm 9 | 10 | 11 | class EvalHook(_EvalHook): 12 | """Single GPU EvalHook, with efficient test support. 13 | 14 | Args: 15 | by_epoch (bool): Determine perform evaluation by epoch or by iteration. 16 | If set to True, it will perform by epoch. Otherwise, by iteration. 17 | Default: False. 18 | efficient_test (bool): Whether save the results as local numpy files to 19 | save CPU memory during evaluation. Default: False. 20 | Returns: 21 | list: The prediction results. 22 | """ 23 | 24 | greater_keys = ['mIoU', 'mAcc', 'aAcc'] 25 | 26 | def __init__(self, *args, by_epoch=False, efficient_test=False, **kwargs): 27 | super().__init__(*args, by_epoch=by_epoch, **kwargs) 28 | self.efficient_test = efficient_test 29 | 30 | def _do_evaluate(self, runner): 31 | """perform evaluation and save ckpt.""" 32 | if not self._should_evaluate(runner): 33 | return 34 | 35 | from mmseg.apis import single_gpu_test 36 | results = single_gpu_test( 37 | runner.model, 38 | self.dataloader, 39 | show=False, 40 | efficient_test=self.efficient_test) 41 | runner.log_buffer.output['eval_iter_num'] = len(self.dataloader) 42 | key_score = self.evaluate(runner, results) 43 | if self.save_best: 44 | self._save_ckpt(runner, key_score) 45 | 46 | 47 | class DistEvalHook(_DistEvalHook): 48 | """Distributed EvalHook, with efficient test support. 49 | 50 | Args: 51 | by_epoch (bool): Determine perform evaluation by epoch or by iteration. 52 | If set to True, it will perform by epoch. Otherwise, by iteration. 53 | Default: False. 54 | efficient_test (bool): Whether save the results as local numpy files to 55 | save CPU memory during evaluation. Default: False. 56 | Returns: 57 | list: The prediction results. 58 | """ 59 | 60 | greater_keys = ['mIoU', 'mAcc', 'aAcc'] 61 | 62 | def __init__(self, *args, by_epoch=False, efficient_test=False, **kwargs): 63 | super().__init__(*args, by_epoch=by_epoch, **kwargs) 64 | self.efficient_test = efficient_test 65 | 66 | def _do_evaluate(self, runner): 67 | """perform evaluation and save ckpt.""" 68 | # Synchronization of BatchNorm's buffer (running_mean 69 | # and running_var) is not supported in the DDP of pytorch, 70 | # which may cause the inconsistent performance of models in 71 | # different ranks, so we broadcast BatchNorm's buffers 72 | # of rank 0 to other ranks to avoid this. 73 | if self.broadcast_bn_buffer: 74 | model = runner.model 75 | for name, module in model.named_modules(): 76 | if isinstance(module, 77 | _BatchNorm) and module.track_running_stats: 78 | dist.broadcast(module.running_var, 0) 79 | dist.broadcast(module.running_mean, 0) 80 | 81 | if not self._should_evaluate(runner): 82 | return 83 | 84 | tmpdir = self.tmpdir 85 | if tmpdir is None: 86 | tmpdir = osp.join(runner.work_dir, '.eval_hook') 87 | 88 | from mmseg.apis import multi_gpu_test 89 | results = multi_gpu_test( 90 | runner.model, 91 | self.dataloader, 92 | tmpdir=tmpdir, 93 | gpu_collect=self.gpu_collect, 94 | efficient_test=self.efficient_test) 95 | if runner.rank == 0: 96 | print('\n') 97 | runner.log_buffer.output['eval_iter_num'] = len(self.dataloader) 98 | key_score = self.evaluate(runner, results) 99 | 100 | if self.save_best: 101 | self._save_ckpt(runner, key_score) 102 | -------------------------------------------------------------------------------- /mmseg/core/seg/__init__.py: -------------------------------------------------------------------------------- 1 | from .builder import build_pixel_sampler 2 | from .sampler import BasePixelSampler, OHEMPixelSampler 3 | 4 | __all__ = ['build_pixel_sampler', 'BasePixelSampler', 'OHEMPixelSampler'] 5 | -------------------------------------------------------------------------------- /mmseg/core/seg/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/core/seg/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/core/seg/__pycache__/builder.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/core/seg/__pycache__/builder.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/core/seg/builder.py: -------------------------------------------------------------------------------- 1 | from mmcv.utils import Registry, build_from_cfg 2 | 3 | PIXEL_SAMPLERS = Registry('pixel sampler') 4 | 5 | 6 | def build_pixel_sampler(cfg, **default_args): 7 | """Build pixel sampler for segmentation map.""" 8 | return build_from_cfg(cfg, PIXEL_SAMPLERS, default_args) 9 | -------------------------------------------------------------------------------- /mmseg/core/seg/sampler/__init__.py: -------------------------------------------------------------------------------- 1 | from .base_pixel_sampler import BasePixelSampler 2 | from .ohem_pixel_sampler import OHEMPixelSampler 3 | 4 | __all__ = ['BasePixelSampler', 'OHEMPixelSampler'] 5 | -------------------------------------------------------------------------------- /mmseg/core/seg/sampler/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/core/seg/sampler/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/core/seg/sampler/__pycache__/base_pixel_sampler.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/core/seg/sampler/__pycache__/base_pixel_sampler.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/core/seg/sampler/__pycache__/ohem_pixel_sampler.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/core/seg/sampler/__pycache__/ohem_pixel_sampler.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/core/seg/sampler/base_pixel_sampler.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | 3 | from abc import ABCMeta, abstractmethod 4 | 5 | 6 | class BasePixelSampler(metaclass=ABCMeta): 7 | """Base class of pixel sampler.""" 8 | 9 | def __init__(self, **kwargs): 10 | pass 11 | 12 | @abstractmethod 13 | def sample(self, seg_logit, seg_label): 14 | """Placeholder for sample function.""" 15 | -------------------------------------------------------------------------------- /mmseg/core/seg/sampler/ohem_pixel_sampler.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | 3 | import torch 4 | import torch.nn.functional as F 5 | 6 | from ..builder import PIXEL_SAMPLERS 7 | from .base_pixel_sampler import BasePixelSampler 8 | 9 | 10 | @PIXEL_SAMPLERS.register_module() 11 | class OHEMPixelSampler(BasePixelSampler): 12 | """Online Hard Example Mining Sampler for segmentation. 13 | 14 | Args: 15 | context (nn.Module): The context of sampler, subclass of 16 | :obj:`BaseDecodeHead`. 17 | thresh (float, optional): The threshold for hard example selection. 18 | Below which, are prediction with low confidence. If not 19 | specified, the hard examples will be pixels of top ``min_kept`` 20 | loss. Default: None. 21 | min_kept (int, optional): The minimum number of predictions to keep. 22 | Default: 100000. 23 | """ 24 | 25 | def __init__(self, context, thresh=None, min_kept=100000): 26 | super(OHEMPixelSampler, self).__init__() 27 | self.context = context 28 | assert min_kept > 1 29 | self.thresh = thresh 30 | self.min_kept = min_kept 31 | 32 | def sample(self, seg_logit, seg_label): 33 | """Sample pixels that have high loss or with low prediction confidence. 34 | 35 | Args: 36 | seg_logit (torch.Tensor): segmentation logits, shape (N, C, H, W) 37 | seg_label (torch.Tensor): segmentation label, shape (N, 1, H, W) 38 | 39 | Returns: 40 | torch.Tensor: segmentation weight, shape (N, H, W) 41 | """ 42 | with torch.no_grad(): 43 | assert seg_logit.shape[2:] == seg_label.shape[2:] 44 | assert seg_label.shape[1] == 1 45 | seg_label = seg_label.squeeze(1).long() 46 | batch_kept = self.min_kept * seg_label.size(0) 47 | valid_mask = seg_label != self.context.ignore_index 48 | seg_weight = seg_logit.new_zeros(size=seg_label.size()) 49 | valid_seg_weight = seg_weight[valid_mask] 50 | if self.thresh is not None: 51 | seg_prob = F.softmax(seg_logit, dim=1) 52 | 53 | tmp_seg_label = seg_label.clone().unsqueeze(1) 54 | tmp_seg_label[tmp_seg_label == self.context.ignore_index] = 0 55 | seg_prob = seg_prob.gather(1, tmp_seg_label).squeeze(1) 56 | sort_prob, sort_indices = seg_prob[valid_mask].sort() 57 | 58 | if sort_prob.numel() > 0: 59 | min_threshold = sort_prob[min(batch_kept, 60 | sort_prob.numel() - 1)] 61 | else: 62 | min_threshold = 0.0 63 | threshold = max(min_threshold, self.thresh) 64 | valid_seg_weight[seg_prob[valid_mask] < threshold] = 1. 65 | else: 66 | losses = self.context.loss_decode( 67 | seg_logit, 68 | seg_label, 69 | weight=None, 70 | ignore_index=self.context.ignore_index, 71 | reduction_override='none') 72 | # faster than topk according to https://github.com/pytorch/pytorch/issues/22812 # noqa 73 | _, sort_indices = losses[valid_mask].sort(descending=True) 74 | valid_seg_weight[sort_indices[:batch_kept]] = 1. 75 | 76 | seg_weight[valid_mask] = valid_seg_weight 77 | 78 | return seg_weight 79 | -------------------------------------------------------------------------------- /mmseg/core/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .misc import add_prefix 2 | 3 | __all__ = ['add_prefix'] 4 | -------------------------------------------------------------------------------- /mmseg/core/utils/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/core/utils/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/core/utils/__pycache__/misc.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/core/utils/__pycache__/misc.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/core/utils/misc.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | 3 | 4 | def add_prefix(inputs, prefix): 5 | """Add prefix for dict. 6 | 7 | Args: 8 | inputs (dict): The input dict with str keys. 9 | prefix (str): The prefix to add. 10 | 11 | Returns: 12 | 13 | dict: The dict with keys updated with ``prefix``. 14 | """ 15 | 16 | outputs = dict() 17 | for name, value in inputs.items(): 18 | outputs[f'{prefix}.{name}'] = value 19 | 20 | return outputs 21 | -------------------------------------------------------------------------------- /mmseg/datasets/__init__.py: -------------------------------------------------------------------------------- 1 | from .builder import DATASETS, PIPELINES, build_dataloader, build_dataset 2 | from .cityscapes import CityscapesDataset 3 | from .custom import CustomDataset 4 | from .dataset_wrappers import ConcatDataset, RepeatDataset 5 | from .gta import GTADataset 6 | from .synthia import SynthiaDataset 7 | from .uda_dataset import UDADataset 8 | from .step_uda_dataset import StepUDADataset 9 | from .gta_custom import GTACustomDataset 10 | 11 | __all__ = [ 12 | 'CustomDataset', 13 | 'build_dataloader', 14 | 'ConcatDataset', 15 | 'RepeatDataset', 16 | 'DATASETS', 17 | 'build_dataset', 18 | 'PIPELINES', 19 | 'CityscapesDataset', 20 | 'GTADataset', 21 | 'SynthiaDataset', 22 | 'UDADataset', 23 | ] 24 | -------------------------------------------------------------------------------- /mmseg/datasets/dataset_wrappers.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | 3 | from torch.utils.data.dataset import ConcatDataset as _ConcatDataset 4 | 5 | from .builder import DATASETS 6 | 7 | 8 | @DATASETS.register_module() 9 | class ConcatDataset(_ConcatDataset): 10 | """A wrapper of concatenated dataset. 11 | 12 | Same as :obj:`torch.utils.data.dataset.ConcatDataset`, but 13 | concat the group flag for image aspect ratio. 14 | 15 | Args: 16 | datasets (list[:obj:`Dataset`]): A list of datasets. 17 | """ 18 | 19 | def __init__(self, datasets): 20 | super(ConcatDataset, self).__init__(datasets) 21 | self.CLASSES = datasets[0].CLASSES 22 | self.PALETTE = datasets[0].PALETTE 23 | 24 | 25 | @DATASETS.register_module() 26 | class RepeatDataset(object): 27 | """A wrapper of repeated dataset. 28 | 29 | The length of repeated dataset will be `times` larger than the original 30 | dataset. This is useful when the data loading time is long but the dataset 31 | is small. Using RepeatDataset can reduce the data loading time between 32 | epochs. 33 | 34 | Args: 35 | dataset (:obj:`Dataset`): The dataset to be repeated. 36 | times (int): Repeat times. 37 | """ 38 | 39 | def __init__(self, dataset, times): 40 | self.dataset = dataset 41 | self.times = times 42 | self.CLASSES = dataset.CLASSES 43 | self.PALETTE = dataset.PALETTE 44 | self._ori_len = len(self.dataset) 45 | 46 | def __getitem__(self, idx): 47 | """Get item from original dataset.""" 48 | return self.dataset[idx % self._ori_len] 49 | 50 | def __len__(self): 51 | """The length is multiplied by ``times``""" 52 | return self.times * self._ori_len 53 | -------------------------------------------------------------------------------- /mmseg/datasets/gta.py: -------------------------------------------------------------------------------- 1 | from . import CityscapesDataset 2 | from .builder import DATASETS 3 | from .custom import CustomDataset 4 | 5 | 6 | @DATASETS.register_module() 7 | class GTADataset(CustomDataset): 8 | CLASSES = CityscapesDataset.CLASSES 9 | PALETTE = CityscapesDataset.PALETTE 10 | 11 | def __init__(self, **kwargs): 12 | assert kwargs.get('split') in [None, 'train'] 13 | if 'split' in kwargs: 14 | kwargs.pop('split') 15 | super(GTADataset, self).__init__( 16 | img_suffix='.png', 17 | seg_map_suffix='_labelTrainIds.png', 18 | split=None, 19 | **kwargs) 20 | -------------------------------------------------------------------------------- /mmseg/datasets/pipelines/__init__.py: -------------------------------------------------------------------------------- 1 | from .compose import Compose 2 | from .formating import (Collect, ImageToTensor, ToDataContainer, ToTensor, 3 | Transpose, to_tensor) 4 | from .loading import LoadAnnotations, LoadImageFromFile 5 | from .test_time_aug import MultiScaleFlipAug 6 | from .transforms import (CLAHE, AdjustGamma, Normalize, Pad, 7 | PhotoMetricDistortion, RandomCrop, RandomFlip, 8 | RandomRotate, Rerange, Resize, RGB2Gray, SegRescale) 9 | 10 | __all__ = [ 11 | 'Compose', 'to_tensor', 'ToTensor', 'ImageToTensor', 'ToDataContainer', 12 | 'Transpose', 'Collect', 'LoadAnnotations', 'LoadImageFromFile', 13 | 'MultiScaleFlipAug', 'Resize', 'RandomFlip', 'Pad', 'RandomCrop', 14 | 'Normalize', 'SegRescale', 'PhotoMetricDistortion', 'RandomRotate', 15 | 'AdjustGamma', 'CLAHE', 'Rerange', 'RGB2Gray' 16 | ] 17 | -------------------------------------------------------------------------------- /mmseg/datasets/pipelines/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/datasets/pipelines/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/datasets/pipelines/__pycache__/compose.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/datasets/pipelines/__pycache__/compose.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/datasets/pipelines/__pycache__/formating.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/datasets/pipelines/__pycache__/formating.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/datasets/pipelines/__pycache__/loading.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/datasets/pipelines/__pycache__/loading.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/datasets/pipelines/__pycache__/test_time_aug.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/datasets/pipelines/__pycache__/test_time_aug.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/datasets/pipelines/__pycache__/transforms.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/datasets/pipelines/__pycache__/transforms.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/datasets/pipelines/compose.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | 3 | import collections 4 | 5 | from mmcv.utils import build_from_cfg 6 | 7 | from ..builder import PIPELINES 8 | 9 | 10 | @PIPELINES.register_module() 11 | class Compose(object): 12 | """Compose multiple transforms sequentially. 13 | 14 | Args: 15 | transforms (Sequence[dict | callable]): Sequence of transform object or 16 | config dict to be composed. 17 | """ 18 | 19 | def __init__(self, transforms): 20 | assert isinstance(transforms, collections.abc.Sequence) 21 | self.transforms = [] 22 | for transform in transforms: 23 | if isinstance(transform, dict): 24 | transform = build_from_cfg(transform, PIPELINES) 25 | self.transforms.append(transform) 26 | elif callable(transform): 27 | self.transforms.append(transform) 28 | else: 29 | raise TypeError('transform must be callable or a dict') 30 | 31 | def __call__(self, data): 32 | """Call function to apply transforms sequentially. 33 | 34 | Args: 35 | data (dict): A result dict contains the data to transform. 36 | 37 | Returns: 38 | dict: Transformed data. 39 | """ 40 | 41 | for t in self.transforms: 42 | data = t(data) 43 | if data is None: 44 | return None 45 | return data 46 | 47 | def __repr__(self): 48 | format_string = self.__class__.__name__ + '(' 49 | for t in self.transforms: 50 | format_string += '\n' 51 | format_string += f' {t}' 52 | format_string += '\n)' 53 | return format_string 54 | -------------------------------------------------------------------------------- /mmseg/datasets/synthia.py: -------------------------------------------------------------------------------- 1 | from . import CityscapesDataset 2 | from .builder import DATASETS 3 | from .custom import CustomDataset 4 | 5 | 6 | @DATASETS.register_module() 7 | class SynthiaDataset(CustomDataset): 8 | CLASSES = CityscapesDataset.CLASSES 9 | PALETTE = CityscapesDataset.PALETTE 10 | 11 | def __init__(self, **kwargs): 12 | assert kwargs.get('split') in [None, 'train'] 13 | if 'split' in kwargs: 14 | kwargs.pop('split') 15 | super(SynthiaDataset, self).__init__( 16 | img_suffix='.png', 17 | seg_map_suffix='_labelTrainIds.png', 18 | split=None, 19 | **kwargs) 20 | -------------------------------------------------------------------------------- /mmseg/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .backbones import * # noqa: F401,F403 2 | from .builder import (BACKBONES, HEADS, LOSSES, SEGMENTORS, UDA, 3 | build_backbone, build_head, build_loss, build_segmentor) 4 | from .decode_heads import * # noqa: F401,F403 5 | from .losses import * # noqa: F401,F403 6 | from .necks import * # noqa: F401,F403 7 | from .segmentors import * # noqa: F401,F403 8 | from .uda import * # noqa: F401,F403 9 | 10 | __all__ = [ 11 | 'BACKBONES', 'HEADS', 'LOSSES', 'SEGMENTORS', 'UDA', 'build_backbone', 12 | 'build_head', 'build_loss', 'build_segmentor' 13 | ] 14 | -------------------------------------------------------------------------------- /mmseg/models/backbones/__init__.py: -------------------------------------------------------------------------------- 1 | from .mix_transformer import (MixVisionTransformer, mit_b0, mit_b1, mit_b2, 2 | mit_b3, mit_b4, mit_b5) 3 | from .resnest import ResNeSt 4 | from .resnet import ResNet, ResNetV1c, ResNetV1d 5 | from .resnext import ResNeXt 6 | from .beit import BEiT 7 | from .swin import SwinTransformer 8 | 9 | __all__ = [ 10 | 'ResNet', 11 | 'ResNetV1c', 12 | 'ResNetV1d', 13 | 'ResNeXt', 14 | 'ResNeSt', 15 | 'MixVisionTransformer', 16 | 'mit_b0', 17 | 'mit_b1', 18 | 'mit_b2', 19 | 'mit_b3', 20 | 'mit_b4', 21 | 'mit_b5', 22 | 'BEiT', 23 | 'SwinTransformer' 24 | ] 25 | -------------------------------------------------------------------------------- /mmseg/models/builder.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | # Modifications: Support UDA models 3 | 4 | import warnings 5 | 6 | from mmcv.cnn import MODELS as MMCV_MODELS 7 | from mmcv.cnn.bricks.registry import ATTENTION as MMCV_ATTENTION 8 | from mmcv.utils import Registry 9 | 10 | MODELS = Registry('models', parent=MMCV_MODELS) 11 | ATTENTION = Registry('attention', parent=MMCV_ATTENTION) 12 | 13 | BACKBONES = MODELS 14 | NECKS = MODELS 15 | HEADS = MODELS 16 | LOSSES = MODELS 17 | SEGMENTORS = MODELS 18 | UDA = MODELS 19 | 20 | 21 | def build_backbone(cfg): 22 | """Build backbone.""" 23 | return BACKBONES.build(cfg) 24 | 25 | 26 | def build_neck(cfg): 27 | """Build neck.""" 28 | return NECKS.build(cfg) 29 | 30 | 31 | def build_head(cfg): 32 | """Build head.""" 33 | return HEADS.build(cfg) 34 | 35 | 36 | def build_loss(cfg): 37 | """Build loss.""" 38 | return LOSSES.build(cfg) 39 | 40 | 41 | def build_train_model(cfg, train_cfg=None, test_cfg=None): 42 | """Build model.""" 43 | if train_cfg is not None or test_cfg is not None: 44 | warnings.warn( 45 | 'train_cfg and test_cfg is deprecated, ' 46 | 'please specify them in model', UserWarning) 47 | assert cfg.model.get('train_cfg') is None or train_cfg is None, \ 48 | 'train_cfg specified in both outer field and model field ' 49 | assert cfg.model.get('test_cfg') is None or test_cfg is None, \ 50 | 'test_cfg specified in both outer field and model field ' 51 | if 'uda' in cfg: 52 | cfg.uda['model'] = cfg.model 53 | cfg.uda['max_iters'] = cfg.runner.max_iters 54 | return UDA.build( 55 | cfg.uda, default_args=dict(train_cfg=train_cfg, test_cfg=test_cfg)) 56 | else: 57 | return SEGMENTORS.build( 58 | cfg.model, 59 | default_args=dict(train_cfg=train_cfg, test_cfg=test_cfg)) 60 | 61 | 62 | def build_segmentor(cfg, train_cfg=None, test_cfg=None): 63 | """Build segmentor.""" 64 | if train_cfg is not None or test_cfg is not None: 65 | warnings.warn( 66 | 'train_cfg and test_cfg is deprecated, ' 67 | 'please specify them in model', UserWarning) 68 | assert cfg.get('train_cfg') is None or train_cfg is None, \ 69 | 'train_cfg specified in both outer field and model field ' 70 | assert cfg.get('test_cfg') is None or test_cfg is None, \ 71 | 'test_cfg specified in both outer field and model field ' 72 | return SEGMENTORS.build( 73 | cfg, default_args=dict(train_cfg=train_cfg, test_cfg=test_cfg)) 74 | -------------------------------------------------------------------------------- /mmseg/models/decode_heads/sep_aspp_head.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | 3 | import torch 4 | import torch.nn as nn 5 | from mmcv.cnn import ConvModule, DepthwiseSeparableConvModule 6 | 7 | from mmseg.ops import resize 8 | from ..builder import HEADS 9 | from .aspp_head import ASPPHead, ASPPModule 10 | 11 | 12 | class DepthwiseSeparableASPPModule(ASPPModule): 13 | """Atrous Spatial Pyramid Pooling (ASPP) Module with depthwise separable 14 | conv.""" 15 | 16 | def __init__(self, **kwargs): 17 | super(DepthwiseSeparableASPPModule, self).__init__(**kwargs) 18 | for i, dilation in enumerate(self.dilations): 19 | if dilation > 1: 20 | self[i] = DepthwiseSeparableConvModule( 21 | self.in_channels, 22 | self.channels, 23 | 3, 24 | dilation=dilation, 25 | padding=dilation, 26 | norm_cfg=self.norm_cfg, 27 | act_cfg=self.act_cfg) 28 | 29 | 30 | @HEADS.register_module() 31 | class DepthwiseSeparableASPPHead(ASPPHead): 32 | """Encoder-Decoder with Atrous Separable Convolution for Semantic Image 33 | Segmentation. 34 | 35 | This head is the implementation of `DeepLabV3+ 36 | `_. 37 | 38 | Args: 39 | c1_in_channels (int): The input channels of c1 decoder. If is 0, 40 | the no decoder will be used. 41 | c1_channels (int): The intermediate channels of c1 decoder. 42 | """ 43 | 44 | def __init__(self, c1_in_channels, c1_channels, **kwargs): 45 | super(DepthwiseSeparableASPPHead, self).__init__(**kwargs) 46 | assert c1_in_channels >= 0 47 | self.aspp_modules = DepthwiseSeparableASPPModule( 48 | dilations=self.dilations, 49 | in_channels=self.in_channels, 50 | channels=self.channels, 51 | conv_cfg=self.conv_cfg, 52 | norm_cfg=self.norm_cfg, 53 | act_cfg=self.act_cfg) 54 | if c1_in_channels > 0: 55 | self.c1_bottleneck = ConvModule( 56 | c1_in_channels, 57 | c1_channels, 58 | 1, 59 | conv_cfg=self.conv_cfg, 60 | norm_cfg=self.norm_cfg, 61 | act_cfg=self.act_cfg) 62 | else: 63 | self.c1_bottleneck = None 64 | self.sep_bottleneck = nn.Sequential( 65 | DepthwiseSeparableConvModule( 66 | self.channels + c1_channels, 67 | self.channels, 68 | 3, 69 | padding=1, 70 | norm_cfg=self.norm_cfg, 71 | act_cfg=self.act_cfg), 72 | DepthwiseSeparableConvModule( 73 | self.channels, 74 | self.channels, 75 | 3, 76 | padding=1, 77 | norm_cfg=self.norm_cfg, 78 | act_cfg=self.act_cfg)) 79 | 80 | def forward(self, inputs): 81 | """Forward function.""" 82 | x = self._transform_inputs(inputs) 83 | aspp_outs = [ 84 | resize( 85 | self.image_pool(x), 86 | size=x.size()[2:], 87 | mode='bilinear', 88 | align_corners=self.align_corners) 89 | ] 90 | aspp_outs.extend(self.aspp_modules(x)) 91 | aspp_outs = torch.cat(aspp_outs, dim=1) 92 | output = self.bottleneck(aspp_outs) 93 | if self.c1_bottleneck is not None: 94 | c1_output = self.c1_bottleneck(inputs[0]) 95 | output = resize( 96 | input=output, 97 | size=c1_output.shape[2:], 98 | mode='bilinear', 99 | align_corners=self.align_corners) 100 | output = torch.cat([output, c1_output], dim=1) 101 | output = self.sep_bottleneck(output) 102 | output = self.cls_seg(output) 103 | return output 104 | -------------------------------------------------------------------------------- /mmseg/models/losses/__init__.py: -------------------------------------------------------------------------------- 1 | from .accuracy import Accuracy, accuracy 2 | from .cross_entropy_loss import (CrossEntropyLoss, binary_cross_entropy, 3 | cross_entropy, mask_cross_entropy) 4 | from .utils import reduce_loss, weight_reduce_loss, weighted_loss 5 | 6 | __all__ = [ 7 | 'accuracy', 'Accuracy', 'cross_entropy', 'binary_cross_entropy', 8 | 'mask_cross_entropy', 'CrossEntropyLoss', 'reduce_loss', 9 | 'weight_reduce_loss', 'weighted_loss' 10 | ] 11 | -------------------------------------------------------------------------------- /mmseg/models/losses/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/models/losses/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/models/losses/__pycache__/accuracy.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/models/losses/__pycache__/accuracy.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/models/losses/__pycache__/cross_entropy_loss.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/models/losses/__pycache__/cross_entropy_loss.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/models/losses/__pycache__/utils.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/models/losses/__pycache__/utils.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/models/losses/accuracy.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | 3 | import torch.nn as nn 4 | 5 | 6 | def accuracy(pred, target, topk=1, thresh=None): 7 | """Calculate accuracy according to the prediction and target. 8 | 9 | Args: 10 | pred (torch.Tensor): The model prediction, shape (N, num_class, ...) 11 | target (torch.Tensor): The target of each prediction, shape (N, , ...) 12 | topk (int | tuple[int], optional): If the predictions in ``topk`` 13 | matches the target, the predictions will be regarded as 14 | correct ones. Defaults to 1. 15 | thresh (float, optional): If not None, predictions with scores under 16 | this threshold are considered incorrect. Default to None. 17 | 18 | Returns: 19 | float | tuple[float]: If the input ``topk`` is a single integer, 20 | the function will return a single float as accuracy. If 21 | ``topk`` is a tuple containing multiple integers, the 22 | function will return a tuple containing accuracies of 23 | each ``topk`` number. 24 | """ 25 | assert isinstance(topk, (int, tuple)) 26 | if isinstance(topk, int): 27 | topk = (topk, ) 28 | return_single = True 29 | else: 30 | return_single = False 31 | 32 | maxk = max(topk) 33 | if pred.size(0) == 0: 34 | accu = [pred.new_tensor(0.) for i in range(len(topk))] 35 | return accu[0] if return_single else accu 36 | assert pred.ndim == target.ndim + 1 37 | assert pred.size(0) == target.size(0) 38 | assert maxk <= pred.size(1), \ 39 | f'maxk {maxk} exceeds pred dimension {pred.size(1)}' 40 | pred_value, pred_label = pred.topk(maxk, dim=1) 41 | # transpose to shape (maxk, N, ...) 42 | pred_label = pred_label.transpose(0, 1) 43 | correct = pred_label.eq(target.unsqueeze(0).expand_as(pred_label)) 44 | if thresh is not None: 45 | # Only prediction values larger than thresh are counted as correct 46 | correct = correct & (pred_value > thresh).t() 47 | res = [] 48 | for k in topk: 49 | correct_k = correct[:k].reshape(-1).float().sum(0, keepdim=True) 50 | res.append(correct_k.mul_(100.0 / target.numel())) 51 | return res[0] if return_single else res 52 | 53 | 54 | class Accuracy(nn.Module): 55 | """Accuracy calculation module.""" 56 | 57 | def __init__(self, topk=(1, ), thresh=None): 58 | """Module to calculate the accuracy. 59 | 60 | Args: 61 | topk (tuple, optional): The criterion used to calculate the 62 | accuracy. Defaults to (1,). 63 | thresh (float, optional): If not None, predictions with scores 64 | under this threshold are considered incorrect. Default to None. 65 | """ 66 | super().__init__() 67 | self.topk = topk 68 | self.thresh = thresh 69 | 70 | def forward(self, pred, target): 71 | """Forward function to calculate accuracy. 72 | 73 | Args: 74 | pred (torch.Tensor): Prediction of models. 75 | target (torch.Tensor): Target for each prediction. 76 | 77 | Returns: 78 | tuple[float]: The accuracies under different topk criterions. 79 | """ 80 | return accuracy(pred, target, self.topk, self.thresh) 81 | -------------------------------------------------------------------------------- /mmseg/models/losses/utils.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | 3 | import functools 4 | 5 | import mmcv 6 | import numpy as np 7 | import torch.nn.functional as F 8 | 9 | 10 | def get_class_weight(class_weight): 11 | """Get class weight for loss function. 12 | 13 | Args: 14 | class_weight (list[float] | str | None): If class_weight is a str, 15 | take it as a file name and read from it. 16 | """ 17 | if isinstance(class_weight, str): 18 | # take it as a file path 19 | if class_weight.endswith('.npy'): 20 | class_weight = np.load(class_weight) 21 | else: 22 | # pkl, json or yaml 23 | class_weight = mmcv.load(class_weight) 24 | 25 | return class_weight 26 | 27 | 28 | def reduce_loss(loss, reduction): 29 | """Reduce loss as specified. 30 | 31 | Args: 32 | loss (Tensor): Elementwise loss tensor. 33 | reduction (str): Options are "none", "mean" and "sum". 34 | 35 | Return: 36 | Tensor: Reduced loss tensor. 37 | """ 38 | reduction_enum = F._Reduction.get_enum(reduction) 39 | # none: 0, elementwise_mean:1, sum: 2 40 | if reduction_enum == 0: 41 | return loss 42 | elif reduction_enum == 1: 43 | return loss.mean() 44 | elif reduction_enum == 2: 45 | return loss.sum() 46 | 47 | 48 | def weight_reduce_loss(loss, weight=None, reduction='mean', avg_factor=None): 49 | """Apply element-wise weight and reduce loss. 50 | 51 | Args: 52 | loss (Tensor): Element-wise loss. 53 | weight (Tensor): Element-wise weights. 54 | reduction (str): Same as built-in losses of PyTorch. 55 | avg_factor (float): Avarage factor when computing the mean of losses. 56 | 57 | Returns: 58 | Tensor: Processed loss values. 59 | """ 60 | # if weight is specified, apply element-wise weight 61 | if weight is not None: 62 | assert weight.dim() == loss.dim() 63 | if weight.dim() > 1: 64 | assert weight.size(1) == 1 or weight.size(1) == loss.size(1) 65 | loss = loss * weight 66 | 67 | # if avg_factor is not specified, just reduce the loss 68 | if avg_factor is None: 69 | loss = reduce_loss(loss, reduction) 70 | else: 71 | # if reduction is mean, then average the loss by avg_factor 72 | if reduction == 'mean': 73 | loss = loss.sum() / avg_factor 74 | # if reduction is 'none', then do nothing, otherwise raise an error 75 | elif reduction != 'none': 76 | raise ValueError('avg_factor can not be used with reduction="sum"') 77 | return loss 78 | 79 | 80 | def weighted_loss(loss_func): 81 | """Create a weighted version of a given loss function. 82 | 83 | To use this decorator, the loss function must have the signature like 84 | `loss_func(pred, target, **kwargs)`. The function only needs to compute 85 | element-wise loss without any reduction. This decorator will add weight 86 | and reduction arguments to the function. The decorated function will have 87 | the signature like `loss_func(pred, target, weight=None, reduction='mean', 88 | avg_factor=None, **kwargs)`. 89 | 90 | :Example: 91 | 92 | >>> import torch 93 | >>> @weighted_loss 94 | >>> def l1_loss(pred, target): 95 | >>> return (pred - target).abs() 96 | 97 | >>> pred = torch.Tensor([0, 2, 3]) 98 | >>> target = torch.Tensor([1, 1, 1]) 99 | >>> weight = torch.Tensor([1, 0, 1]) 100 | 101 | >>> l1_loss(pred, target) 102 | tensor(1.3333) 103 | >>> l1_loss(pred, target, weight) 104 | tensor(1.) 105 | >>> l1_loss(pred, target, reduction='none') 106 | tensor([1., 1., 2.]) 107 | >>> l1_loss(pred, target, weight, avg_factor=2) 108 | tensor(1.5000) 109 | """ 110 | 111 | @functools.wraps(loss_func) 112 | def wrapper(pred, 113 | target, 114 | weight=None, 115 | reduction='mean', 116 | avg_factor=None, 117 | **kwargs): 118 | # get element-wise loss 119 | loss = loss_func(pred, target, **kwargs) 120 | loss = weight_reduce_loss(loss, weight, reduction, avg_factor) 121 | return loss 122 | 123 | return wrapper 124 | -------------------------------------------------------------------------------- /mmseg/models/necks/__init__.py: -------------------------------------------------------------------------------- 1 | from .segformer_adapter import SegFormerAdapter 2 | from .featurepyramid import Feature2Pyramid 3 | __all__ = ['SegFormerAdapter', 'Feature2Pyramid'] 4 | -------------------------------------------------------------------------------- /mmseg/models/necks/featurepyramid.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) OpenMMLab. All rights reserved. 2 | import torch.nn as nn 3 | from mmcv.cnn import build_norm_layer 4 | 5 | from ..builder import NECKS 6 | 7 | 8 | @NECKS.register_module() 9 | class Feature2Pyramid(nn.Module): 10 | """Feature2Pyramid. 11 | A neck structure connect ViT backbone and decoder_heads. 12 | Args: 13 | embed_dims (int): Embedding dimension. 14 | rescales (list[float]): Different sampling multiples were 15 | used to obtain pyramid features. Default: [4, 2, 1, 0.5]. 16 | norm_cfg (dict): Config dict for normalization layer. 17 | Default: dict(type='SyncBN', requires_grad=True). 18 | """ 19 | 20 | def __init__(self, 21 | embed_dim, 22 | rescales=[4, 2, 1, 0.5], 23 | norm_cfg=dict(type='SyncBN', requires_grad=True)): 24 | super(Feature2Pyramid, self).__init__() 25 | self.rescales = rescales 26 | self.upsample_4x = None 27 | for k in self.rescales: 28 | if k == 4: 29 | self.upsample_4x = nn.Sequential( 30 | nn.ConvTranspose2d( 31 | embed_dim, embed_dim, kernel_size=2, stride=2), 32 | build_norm_layer(norm_cfg, embed_dim)[1], 33 | nn.GELU(), 34 | nn.ConvTranspose2d( 35 | embed_dim, embed_dim, kernel_size=2, stride=2), 36 | ) 37 | elif k == 2: 38 | self.upsample_2x = nn.Sequential( 39 | nn.ConvTranspose2d( 40 | embed_dim, embed_dim, kernel_size=2, stride=2)) 41 | elif k == 1: 42 | self.identity = nn.Identity() 43 | elif k == 0.5: 44 | self.downsample_2x = nn.MaxPool2d(kernel_size=2, stride=2) 45 | elif k == 0.25: 46 | self.downsample_4x = nn.MaxPool2d(kernel_size=4, stride=4) 47 | else: 48 | raise KeyError(f'invalid {k} for feature2pyramid') 49 | 50 | def forward(self, inputs): 51 | assert len(inputs) == len(self.rescales) 52 | outputs = [] 53 | if self.upsample_4x is not None: 54 | ops = [ 55 | self.upsample_4x, self.upsample_2x, self.identity, 56 | self.downsample_2x 57 | ] 58 | else: 59 | ops = [ 60 | self.upsample_2x, self.identity, self.downsample_2x, 61 | self.downsample_4x 62 | ] 63 | for i in range(len(inputs)): 64 | outputs.append(ops[i](inputs[i])) 65 | return tuple(outputs) -------------------------------------------------------------------------------- /mmseg/models/necks/segformer_adapter.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | 4 | from mmseg.ops import resize 5 | from ..builder import NECKS 6 | 7 | 8 | @NECKS.register_module() 9 | class SegFormerAdapter(nn.Module): 10 | 11 | def __init__(self, out_layers=[3], scales=[4]): 12 | super(SegFormerAdapter, self).__init__() 13 | self.out_layers = out_layers 14 | self.scales = scales 15 | 16 | def forward(self, x): 17 | _c = {} 18 | for i, s in zip(self.out_layers, self.scales): 19 | if s == 1: 20 | _c[i] = x[i] 21 | else: 22 | _c[i] = resize( 23 | x[i], scale_factor=s, mode='bilinear', align_corners=False) 24 | # mmcv.print_log(f'{i}: {x[i].shape}, {_c[i].shape}', 'mmseg') 25 | 26 | x[-1] = torch.cat(list(_c.values()), dim=1) 27 | return x 28 | -------------------------------------------------------------------------------- /mmseg/models/segmentors/__init__.py: -------------------------------------------------------------------------------- 1 | from .base import BaseSegmentor 2 | from .encoder_decoder import EncoderDecoder 3 | 4 | __all__ = ['BaseSegmentor', 'EncoderDecoder'] 5 | -------------------------------------------------------------------------------- /mmseg/models/uda/__init__.py: -------------------------------------------------------------------------------- 1 | from pkgutil import ImpImporter 2 | from mmseg.models.uda.dacs import DACS 3 | # from mmseg.models.uda.nesterov import NESTEROV 4 | # from mmseg.models.uda.wider_nesterov import NESTEROVW 5 | # from mmseg.models.uda.nesterov_alpha import NESTEROV_ALPHA 6 | # from mmseg.models.uda.nesterov_naive import NESTEROV_NAIVE 7 | # from mmseg.models.uda.wider_nesterov_different_data import Wider_NESTEROV_DifData 8 | # from mmseg.models.uda.deeper_nesterov_different_data import Deeper_NESTEROV_DifData 9 | # from mmseg.models.uda.source_only import SourceOnly 10 | # from mmseg.models.uda.nesterov_naive_different_data import NESTEROV_NAIVE_DifData 11 | # from mmseg.models.uda.wider_and_deeper_nesterov_different_data_v1 import Wider_Deeper_NESTEROV_DifData_v1 12 | # from mmseg.models.uda.wider_and_deeper_nesterov_different_data_v2 import Wider_Deeper_NESTEROV_DifData_v2 13 | 14 | 15 | from mmseg.models.uda.fst_w import Wider_NESTEROV_DifData # FST-W 16 | from mmseg.models.uda.fst_d import NESTEROV # FST-D 17 | from mmseg.models.uda.source_only import SourceOnly 18 | 19 | __all__ = [ 20 | 'DACS', 21 | 'SourceOnly', 22 | 'NESTEROV', 23 | 'Wider_NESTEROV_DifData' 24 | ] -------------------------------------------------------------------------------- /mmseg/models/uda/uda_decorator.py: -------------------------------------------------------------------------------- 1 | from copy import deepcopy 2 | 3 | from mmcv.parallel import MMDistributedDataParallel 4 | 5 | from mmseg.models import BaseSegmentor, build_segmentor 6 | 7 | 8 | def get_module(module): 9 | """Get `nn.ModuleDict` to fit the `MMDistributedDataParallel` interface. 10 | 11 | Args: 12 | module (MMDistributedDataParallel | nn.ModuleDict): The input 13 | module that needs processing. 14 | 15 | Returns: 16 | nn.ModuleDict: The ModuleDict of multiple networks. 17 | """ 18 | if isinstance(module, MMDistributedDataParallel): 19 | return module.module 20 | 21 | return module 22 | 23 | 24 | class UDADecorator(BaseSegmentor): 25 | 26 | def __init__(self, **cfg): 27 | super(BaseSegmentor, self).__init__() 28 | 29 | self.model = build_segmentor(deepcopy(cfg['model'])) 30 | self.train_cfg = cfg['model']['train_cfg'] 31 | self.test_cfg = cfg['model']['test_cfg'] 32 | self.num_classes = cfg['model']['decode_head']['num_classes'] 33 | 34 | def get_model(self): 35 | return get_module(self.model) 36 | 37 | def extract_feat(self, img): 38 | """Extract features from images.""" 39 | return self.get_model().extract_feat(img) 40 | 41 | def encode_decode(self, img, img_metas): 42 | """Encode images with backbone and decode into a semantic segmentation 43 | map of the same size as input.""" 44 | return self.get_model().encode_decode(img, img_metas) 45 | 46 | def forward_train(self, 47 | img, 48 | img_metas, 49 | gt_semantic_seg, 50 | target_img, 51 | target_img_metas, 52 | return_feat=False): 53 | """Forward function for training. 54 | 55 | Args: 56 | img (Tensor): Input images. 57 | img_metas (list[dict]): List of image info dict where each dict 58 | has: 'img_shape', 'scale_factor', 'flip', and may also contain 59 | 'filename', 'ori_shape', 'pad_shape', and 'img_norm_cfg'. 60 | For details on the values of these keys see 61 | `mmseg/datasets/pipelines/formatting.py:Collect`. 62 | gt_semantic_seg (Tensor): Semantic segmentation masks 63 | used if the architecture supports semantic segmentation task. 64 | 65 | Returns: 66 | dict[str, Tensor]: a dictionary of loss components 67 | """ 68 | losses = self.get_model().forward_train( 69 | img, img_metas, gt_semantic_seg, return_feat=return_feat) 70 | return losses 71 | 72 | def inference(self, img, img_meta, rescale): 73 | """Inference with slide/whole style. 74 | 75 | Args: 76 | img (Tensor): The input image of shape (N, 3, H, W). 77 | img_meta (dict): Image info dict where each dict has: 'img_shape', 78 | 'scale_factor', 'flip', and may also contain 79 | 'filename', 'ori_shape', 'pad_shape', and 'img_norm_cfg'. 80 | For details on the values of these keys see 81 | `mmseg/datasets/pipelines/formatting.py:Collect`. 82 | rescale (bool): Whether rescale back to original shape. 83 | 84 | Returns: 85 | Tensor: The output segmentation map. 86 | """ 87 | return self.get_model().inference(img, img_meta, rescale) 88 | 89 | def simple_test(self, img, img_meta, rescale=True): 90 | """Simple test with single image.""" 91 | return self.get_model().simple_test(img, img_meta, rescale) 92 | 93 | def aug_test(self, imgs, img_metas, rescale=True): 94 | """Test with augmentations. 95 | 96 | Only rescale=True is supported. 97 | """ 98 | return self.get_model().aug_test(imgs, img_metas, rescale) 99 | -------------------------------------------------------------------------------- /mmseg/models/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .ckpt_convert import mit_convert 2 | from .make_divisible import make_divisible 3 | from .res_layer import ResLayer 4 | from .self_attention_block import SelfAttentionBlock 5 | from .shape_convert import nchw_to_nlc, nlc_to_nchw 6 | 7 | __all__ = [ 8 | 'ResLayer', 'SelfAttentionBlock', 'make_divisible', 'mit_convert', 9 | 'nchw_to_nlc', 'nlc_to_nchw' 10 | ] 11 | -------------------------------------------------------------------------------- /mmseg/models/utils/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/models/utils/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/models/utils/__pycache__/ckpt_convert.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/models/utils/__pycache__/ckpt_convert.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/models/utils/__pycache__/dacs_transforms.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/models/utils/__pycache__/dacs_transforms.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/models/utils/__pycache__/embed.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/models/utils/__pycache__/embed.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/models/utils/__pycache__/make_divisible.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/models/utils/__pycache__/make_divisible.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/models/utils/__pycache__/res_layer.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/models/utils/__pycache__/res_layer.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/models/utils/__pycache__/self_attention_block.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/models/utils/__pycache__/self_attention_block.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/models/utils/__pycache__/shape_convert.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/models/utils/__pycache__/shape_convert.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/models/utils/__pycache__/visualization.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/mmseg/models/utils/__pycache__/visualization.cpython-38.pyc -------------------------------------------------------------------------------- /mmseg/models/utils/ckpt_convert.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | 3 | from collections import OrderedDict 4 | 5 | import torch 6 | 7 | 8 | def mit_convert(ckpt): 9 | new_ckpt = OrderedDict() 10 | # Process the concat between q linear weights and kv linear weights 11 | for k, v in ckpt.items(): 12 | if k.startswith('head'): 13 | continue 14 | elif k.startswith('patch_embed'): 15 | stage_i = int(k.split('.')[0].replace('patch_embed', '')) 16 | new_k = k.replace(f'patch_embed{stage_i}', f'layers.{stage_i-1}.0') 17 | new_v = v 18 | if 'proj.' in new_k: 19 | new_k = new_k.replace('proj.', 'projection.') 20 | elif k.startswith('block'): 21 | stage_i = int(k.split('.')[0].replace('block', '')) 22 | new_k = k.replace(f'block{stage_i}', f'layers.{stage_i-1}.1') 23 | new_v = v 24 | if 'attn.q.' in new_k: 25 | sub_item_k = k.replace('q.', 'kv.') 26 | new_k = new_k.replace('q.', 'attn.in_proj_') 27 | new_v = torch.cat([v, ckpt[sub_item_k]], dim=0) 28 | elif 'attn.kv.' in new_k: 29 | continue 30 | elif 'attn.proj.' in new_k: 31 | new_k = new_k.replace('proj.', 'attn.out_proj.') 32 | elif 'attn.sr.' in new_k: 33 | new_k = new_k.replace('sr.', 'sr.') 34 | elif 'mlp.' in new_k: 35 | string = f'{new_k}-' 36 | new_k = new_k.replace('mlp.', 'ffn.layers.') 37 | if 'fc1.weight' in new_k or 'fc2.weight' in new_k: 38 | new_v = v.reshape((*v.shape, 1, 1)) 39 | new_k = new_k.replace('fc1.', '0.') 40 | new_k = new_k.replace('dwconv.dwconv.', '1.') 41 | new_k = new_k.replace('fc2.', '4.') 42 | string += f'{new_k} {v.shape}-{new_v.shape}' 43 | # print(string) 44 | elif k.startswith('norm'): 45 | stage_i = int(k.split('.')[0].replace('norm', '')) 46 | new_k = k.replace(f'norm{stage_i}', f'layers.{stage_i-1}.2') 47 | new_v = v 48 | else: 49 | new_k = k 50 | new_v = v 51 | new_ckpt[new_k] = new_v 52 | return new_ckpt 53 | -------------------------------------------------------------------------------- /mmseg/models/utils/dacs_transforms.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/vikolss/DACS 2 | 3 | import kornia 4 | import numpy as np 5 | import torch 6 | import torch.nn as nn 7 | 8 | 9 | def strong_transform(param, data=None, target=None): 10 | assert ((data is not None) or (target is not None)) 11 | data, target = one_mix(mask=param['mix'], data=data, target=target) 12 | data, target = color_jitter( 13 | color_jitter=param['color_jitter'], 14 | s=param['color_jitter_s'], 15 | p=param['color_jitter_p'], 16 | mean=param['mean'], 17 | std=param['std'], 18 | data=data, 19 | target=target) 20 | data, target = gaussian_blur(blur=param['blur'], data=data, target=target) 21 | return data, target 22 | 23 | 24 | def get_mean_std(img_metas, dev): 25 | mean = [ 26 | torch.as_tensor(img_metas[i]['img_norm_cfg']['mean'], device=dev) 27 | for i in range(len(img_metas)) 28 | ] 29 | mean = torch.stack(mean).view(-1, 3, 1, 1) 30 | std = [ 31 | torch.as_tensor(img_metas[i]['img_norm_cfg']['std'], device=dev) 32 | for i in range(len(img_metas)) 33 | ] 34 | std = torch.stack(std).view(-1, 3, 1, 1) 35 | return mean, std 36 | 37 | 38 | def denorm(img, mean, std): 39 | return img.mul(std).add(mean) / 255.0 40 | 41 | 42 | def denorm_(img, mean, std): 43 | img.mul_(std).add_(mean).div_(255.0) 44 | 45 | 46 | def renorm_(img, mean, std): 47 | img.mul_(255.0).sub_(mean).div_(std) 48 | 49 | 50 | def color_jitter(color_jitter, mean, std, data=None, target=None, s=.25, p=.2): 51 | # s is the strength of colorjitter 52 | if not (data is None): 53 | if data.shape[1] == 3: 54 | if color_jitter > p: 55 | if isinstance(s, dict): 56 | seq = nn.Sequential(kornia.augmentation.ColorJitter(**s)) 57 | else: 58 | seq = nn.Sequential( 59 | kornia.augmentation.ColorJitter( 60 | brightness=s, contrast=s, saturation=s, hue=s)) 61 | denorm_(data, mean, std) 62 | data = seq(data) 63 | renorm_(data, mean, std) 64 | return data, target 65 | 66 | 67 | def gaussian_blur(blur, data=None, target=None): 68 | if not (data is None): 69 | if data.shape[1] == 3: 70 | if blur > 0.5: 71 | sigma = np.random.uniform(0.15, 1.15) 72 | kernel_size_y = int( 73 | np.floor( 74 | np.ceil(0.1 * data.shape[2]) - 0.5 + 75 | np.ceil(0.1 * data.shape[2]) % 2)) 76 | kernel_size_x = int( 77 | np.floor( 78 | np.ceil(0.1 * data.shape[3]) - 0.5 + 79 | np.ceil(0.1 * data.shape[3]) % 2)) 80 | kernel_size = (kernel_size_y, kernel_size_x) 81 | seq = nn.Sequential( 82 | kornia.filters.GaussianBlur2d( 83 | kernel_size=kernel_size, sigma=(sigma, sigma))) 84 | data = seq(data) 85 | return data, target 86 | 87 | 88 | def get_class_masks(labels): 89 | class_masks = [] 90 | for label in labels: 91 | classes = torch.unique(labels) 92 | nclasses = classes.shape[0] 93 | class_choice = np.random.choice( 94 | nclasses, int((nclasses + nclasses % 2) / 2), replace=False) 95 | classes = classes[torch.Tensor(class_choice).long()] 96 | class_masks.append(generate_class_mask(label, classes).unsqueeze(0)) 97 | return class_masks 98 | 99 | 100 | def generate_class_mask(label, classes): 101 | label, classes = torch.broadcast_tensors(label, 102 | classes.unsqueeze(1).unsqueeze(2)) 103 | class_mask = label.eq(classes).sum(0, keepdims=True) 104 | return class_mask 105 | 106 | 107 | def one_mix(mask, data=None, target=None): 108 | if mask is None: 109 | return data, target 110 | if not (data is None): 111 | stackedMask0, _ = torch.broadcast_tensors(mask[0], data[0]) 112 | data = (stackedMask0 * data[0] + 113 | (1 - stackedMask0) * data[1]).unsqueeze(0) 114 | if not (target is None): 115 | stackedMask0, _ = torch.broadcast_tensors(mask[0], target[0]) 116 | target = (stackedMask0 * target[0] + 117 | (1 - stackedMask0) * target[1]).unsqueeze(0) 118 | return data, target 119 | -------------------------------------------------------------------------------- /mmseg/models/utils/make_divisible.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | 3 | 4 | def make_divisible(value, divisor, min_value=None, min_ratio=0.9): 5 | """Make divisible function. 6 | 7 | This function rounds the channel number to the nearest value that can be 8 | divisible by the divisor. It is taken from the original tf repo. It ensures 9 | that all layers have a channel number that is divisible by divisor. It can 10 | be seen here: https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py # noqa 11 | 12 | Args: 13 | value (int): The original channel number. 14 | divisor (int): The divisor to fully divide the channel number. 15 | min_value (int): The minimum value of the output channel. 16 | Default: None, means that the minimum value equal to the divisor. 17 | min_ratio (float): The minimum ratio of the rounded channel number to 18 | the original channel number. Default: 0.9. 19 | 20 | Returns: 21 | int: The modified output channel number. 22 | """ 23 | 24 | if min_value is None: 25 | min_value = divisor 26 | new_value = max(min_value, int(value + divisor / 2) // divisor * divisor) 27 | # Make sure that round down does not go down by more than (1-min_ratio). 28 | if new_value < min_ratio * value: 29 | new_value += divisor 30 | return new_value 31 | -------------------------------------------------------------------------------- /mmseg/models/utils/res_layer.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | 3 | from mmcv.cnn import build_conv_layer, build_norm_layer 4 | from mmcv.runner import Sequential 5 | from torch import nn as nn 6 | 7 | 8 | class ResLayer(Sequential): 9 | """ResLayer to build ResNet style backbone. 10 | 11 | Args: 12 | block (nn.Module): block used to build ResLayer. 13 | inplanes (int): inplanes of block. 14 | planes (int): planes of block. 15 | num_blocks (int): number of blocks. 16 | stride (int): stride of the first block. Default: 1 17 | avg_down (bool): Use AvgPool instead of stride conv when 18 | downsampling in the bottleneck. Default: False 19 | conv_cfg (dict): dictionary to construct and config conv layer. 20 | Default: None 21 | norm_cfg (dict): dictionary to construct and config norm layer. 22 | Default: dict(type='BN') 23 | multi_grid (int | None): Multi grid dilation rates of last 24 | stage. Default: None 25 | contract_dilation (bool): Whether contract first dilation of each layer 26 | Default: False 27 | """ 28 | 29 | def __init__(self, 30 | block, 31 | inplanes, 32 | planes, 33 | num_blocks, 34 | stride=1, 35 | dilation=1, 36 | avg_down=False, 37 | conv_cfg=None, 38 | norm_cfg=dict(type='BN'), 39 | multi_grid=None, 40 | contract_dilation=False, 41 | **kwargs): 42 | self.block = block 43 | 44 | downsample = None 45 | if stride != 1 or inplanes != planes * block.expansion: 46 | downsample = [] 47 | conv_stride = stride 48 | if avg_down: 49 | conv_stride = 1 50 | downsample.append( 51 | nn.AvgPool2d( 52 | kernel_size=stride, 53 | stride=stride, 54 | ceil_mode=True, 55 | count_include_pad=False)) 56 | downsample.extend([ 57 | build_conv_layer( 58 | conv_cfg, 59 | inplanes, 60 | planes * block.expansion, 61 | kernel_size=1, 62 | stride=conv_stride, 63 | bias=False), 64 | build_norm_layer(norm_cfg, planes * block.expansion)[1] 65 | ]) 66 | downsample = nn.Sequential(*downsample) 67 | 68 | layers = [] 69 | if multi_grid is None: 70 | if dilation > 1 and contract_dilation: 71 | first_dilation = dilation // 2 72 | else: 73 | first_dilation = dilation 74 | else: 75 | first_dilation = multi_grid[0] 76 | layers.append( 77 | block( 78 | inplanes=inplanes, 79 | planes=planes, 80 | stride=stride, 81 | dilation=first_dilation, 82 | downsample=downsample, 83 | conv_cfg=conv_cfg, 84 | norm_cfg=norm_cfg, 85 | **kwargs)) 86 | inplanes = planes * block.expansion 87 | for i in range(1, num_blocks): 88 | layers.append( 89 | block( 90 | inplanes=inplanes, 91 | planes=planes, 92 | stride=1, 93 | dilation=dilation if multi_grid is None else multi_grid[i], 94 | conv_cfg=conv_cfg, 95 | norm_cfg=norm_cfg, 96 | **kwargs)) 97 | super(ResLayer, self).__init__(*layers) 98 | -------------------------------------------------------------------------------- /mmseg/models/utils/shape_convert.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | 3 | 4 | def nlc_to_nchw(x, hw_shape): 5 | """Convert [N, L, C] shape tensor to [N, C, H, W] shape tensor. 6 | 7 | Args: 8 | x (Tensor): The input tensor of shape [N, L, C] before convertion. 9 | hw_shape (Sequence[int]): The height and width of output feature map. 10 | 11 | Returns: 12 | Tensor: The output tensor of shape [N, C, H, W] after convertion. 13 | """ 14 | H, W = hw_shape 15 | assert len(x.shape) == 3 16 | B, L, C = x.shape 17 | assert L == H * W, 'The seq_len doesn\'t match H, W' 18 | return x.transpose(1, 2).reshape(B, C, H, W) 19 | 20 | 21 | def nchw_to_nlc(x): 22 | """Flatten [N, C, H, W] shape tensor to [N, L, C] shape tensor. 23 | 24 | Args: 25 | x (Tensor): The input tensor of shape [N, C, H, W] before convertion. 26 | 27 | Returns: 28 | Tensor: The output tensor of shape [N, L, C] after convertion. 29 | """ 30 | assert len(x.shape) == 4 31 | return x.flatten(2).transpose(1, 2).contiguous() 32 | -------------------------------------------------------------------------------- /mmseg/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .collect_env import collect_env 2 | from .logger import get_root_logger 3 | 4 | __all__ = ['get_root_logger', 'collect_env'] 5 | -------------------------------------------------------------------------------- /mmseg/utils/collect_env.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | # Modifications: Add code archive generation 3 | 4 | import os 5 | import tarfile 6 | 7 | from mmcv.utils import collect_env as collect_base_env 8 | from mmcv.utils import get_git_hash 9 | 10 | import mmseg 11 | 12 | 13 | def collect_env(): 14 | """Collect the information of the running environments.""" 15 | env_info = collect_base_env() 16 | env_info['MMSegmentation'] = f'{mmseg.__version__}+{get_git_hash()[:7]}' 17 | 18 | return env_info 19 | 20 | 21 | def is_source_file(x): 22 | if x.isdir() or x.name.endswith(('.py', '.sh', '.yml', '.json', '.txt')) \ 23 | and '.mim' not in x.name and 'jobs/' not in x.name: 24 | # print(x.name) 25 | return x 26 | else: 27 | return None 28 | 29 | 30 | def gen_code_archive(out_dir, file='code.tar.gz'): 31 | archive = os.path.join(out_dir, file) 32 | os.makedirs(os.path.dirname(archive), exist_ok=True) 33 | with tarfile.open(archive, mode='w:gz') as tar: 34 | tar.add('.', filter=is_source_file) 35 | return archive 36 | 37 | 38 | if __name__ == '__main__': 39 | for name, val in collect_env().items(): 40 | print('{}: {}'.format(name, val)) 41 | -------------------------------------------------------------------------------- /mmseg/utils/logger.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | 3 | import logging 4 | 5 | from mmcv.utils import get_logger 6 | 7 | 8 | def get_root_logger(log_file=None, log_level=logging.INFO): 9 | """Get the root logger. 10 | 11 | The logger will be initialized if it has not been initialized. By default a 12 | StreamHandler will be added. If `log_file` is specified, a FileHandler will 13 | also be added. The name of the root logger is the top-level package name, 14 | e.g., "mmseg". 15 | 16 | Args: 17 | log_file (str | None): The log filename. If specified, a FileHandler 18 | will be added to the root logger. 19 | log_level (int): The root logger level. Note that only the process of 20 | rank 0 is affected, while other processes will set the level to 21 | "Error" and be silent most of the time. 22 | 23 | Returns: 24 | logging.Logger: The root logger. 25 | """ 26 | 27 | logger = get_logger(name='mmseg', log_file=log_file, log_level=log_level) 28 | 29 | return logger 30 | -------------------------------------------------------------------------------- /mmseg/utils/utils.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | 3 | import numpy as np 4 | import torch 5 | import torch.nn.functional as F 6 | 7 | 8 | @contextlib.contextmanager 9 | def np_local_seed(seed): 10 | state = np.random.get_state() 11 | np.random.seed(seed) 12 | try: 13 | yield 14 | finally: 15 | np.random.set_state(state) 16 | 17 | 18 | def downscale_label_ratio(gt, 19 | scale_factor, 20 | min_ratio, 21 | n_classes, 22 | ignore_index=255): 23 | assert scale_factor > 1 24 | bs, orig_c, orig_h, orig_w = gt.shape 25 | assert orig_c == 1 26 | trg_h, trg_w = orig_h // scale_factor, orig_w // scale_factor 27 | ignore_substitute = n_classes 28 | 29 | out = gt.clone() # otw. next line would modify original gt 30 | out[out == ignore_index] = ignore_substitute 31 | out = F.one_hot( 32 | out.squeeze(1), num_classes=n_classes + 1).permute(0, 3, 1, 2) 33 | assert list(out.shape) == [bs, n_classes + 1, orig_h, orig_w], out.shape 34 | out = F.avg_pool2d(out.float(), kernel_size=scale_factor) 35 | gt_ratio, out = torch.max(out, dim=1, keepdim=True) 36 | out[out == ignore_substitute] = ignore_index 37 | out[gt_ratio < min_ratio] = ignore_index 38 | assert list(out.shape) == [bs, 1, trg_h, trg_w], out.shape 39 | return out 40 | -------------------------------------------------------------------------------- /mmseg/version.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Open-MMLab. All rights reserved. 2 | 3 | __version__ = '0.16.0' 4 | 5 | 6 | def parse_version_info(version_str): 7 | version_info = [] 8 | for x in version_str.split('.'): 9 | if x.isdigit(): 10 | version_info.append(int(x)) 11 | elif x.find('rc') != -1: 12 | patch_version = x.split('rc') 13 | version_info.append(int(patch_version[0])) 14 | version_info.append(f'rc{patch_version[1]}') 15 | return tuple(version_info) 16 | 17 | 18 | version_info = parse_version_info(__version__) 19 | -------------------------------------------------------------------------------- /run_experiments.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | from ast import arg 3 | import json 4 | import os 5 | import subprocess 6 | import uuid 7 | from datetime import datetime 8 | 9 | import torch 10 | from experiments import generate_experiment_cfgs 11 | from mmcv import Config, get_git_hash 12 | from tools import train 13 | 14 | 15 | def run_command(command): 16 | p = subprocess.Popen( 17 | command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) 18 | for line in iter(p.stdout.readline, b''): 19 | print(line.decode('utf-8'), end='') 20 | 21 | 22 | def rsync(src, dst): 23 | rsync_cmd = f'rsync -a {src} {dst}' 24 | print(rsync_cmd) 25 | run_command(rsync_cmd) 26 | 27 | 28 | if __name__ == '__main__': 29 | parser = argparse.ArgumentParser() 30 | group = parser.add_mutually_exclusive_group(required=True) 31 | group.add_argument( 32 | '--exp', 33 | type=int, 34 | default=None, 35 | help='Experiment id as defined in experiment.py', 36 | ) 37 | group.add_argument( 38 | '--config', 39 | default=None, 40 | help='Path to config file', 41 | ) 42 | 43 | 44 | parser.add_argument( 45 | '--machine', type=str, choices=['local'], default='local') 46 | parser.add_argument('--debug', action='store_true') 47 | 48 | args = parser.parse_args() 49 | 50 | 51 | assert (args.config is None) != (args.exp is None), \ 52 | 'Either config or exp has to be defined.' 53 | 54 | GEN_CONFIG_DIR = 'configs/generated/' 55 | JOB_DIR = 'jobs' 56 | cfgs, config_files = [], [] 57 | 58 | 59 | # Training with Predefined Config 60 | if args.config is not None: 61 | cfg = Config.fromfile(args.config) 62 | # Specify Name and Work Directory 63 | exp_name = f'{args.machine}-{cfg["exp"]}' 64 | unique_name = f'{datetime.now().strftime("%y%m%d_%H%M")}_' \ 65 | f'{cfg["name"]}_{str(uuid.uuid4())[:5]}' 66 | child_cfg = { 67 | '_base_': args.config.replace('configs', '../..'), 68 | 'name': unique_name, 69 | 'work_dir': os.path.join('work_dirs', exp_name, unique_name), 70 | 'git_rev': get_git_hash() 71 | } 72 | cfg_out_file = f"{GEN_CONFIG_DIR}/{exp_name}/{child_cfg['name']}.json" 73 | os.makedirs(os.path.dirname(cfg_out_file), exist_ok=True) 74 | assert not os.path.isfile(cfg_out_file) 75 | with open(cfg_out_file, 'w') as of: 76 | json.dump(child_cfg, of, indent=4) 77 | config_files.append(cfg_out_file) 78 | cfgs.append(cfg) 79 | 80 | # Training with Generated Configs from experiments.py 81 | if args.exp is not None: 82 | exp_name = f'{args.machine}-exp{args.exp}' 83 | cfgs = generate_experiment_cfgs(args.exp) 84 | # Generate Configs 85 | for i, cfg in enumerate(cfgs): 86 | if args.debug: 87 | cfg.setdefault('log_config', {})['interval'] = 10 88 | cfg['evaluation'] = dict(interval=200, metric='mIoU') 89 | if 'dacs' in cfg['name']: 90 | cfg.setdefault('uda', {})['debug_img_interval'] = 10 91 | # cfg.setdefault('uda', {})['print_grad_magnitude'] = True 92 | # Generate Config File 93 | cfg['name'] = f'{datetime.now().strftime("%y%m%d_%H%M")}_' \ 94 | f'{cfg["name"]}_{str(uuid.uuid4())[:5]}' 95 | cfg['work_dir'] = os.path.join('work_dirs', exp_name, cfg['name']) 96 | cfg['git_rev'] = get_git_hash() 97 | cfg['_base_'] = ['../../' + e for e in cfg['_base_']] 98 | cfg_out_file = f"{GEN_CONFIG_DIR}/{exp_name}/{cfg['name']}.json" 99 | os.makedirs(os.path.dirname(cfg_out_file), exist_ok=True) 100 | assert not os.path.isfile(cfg_out_file) 101 | with open(cfg_out_file, 'w') as of: 102 | json.dump(cfg, of, indent=4) 103 | config_files.append(cfg_out_file) 104 | 105 | if args.machine == 'local': 106 | for i, cfg in enumerate(cfgs): 107 | print('Run job {}'.format(cfg['name'])) 108 | train.main([config_files[i]]) 109 | torch.cuda.empty_cache() 110 | else: 111 | raise NotImplementedError(args.machine) 112 | -------------------------------------------------------------------------------- /semi_seg/.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | *.iml 3 | *.xml 4 | 5 | # for here 6 | dev/ 7 | data/cityscapes/ 8 | data/VOC2012/ 9 | events/ 10 | log/ 11 | checkpoints/ 12 | viewer*/ 13 | train.log.* 14 | debug.py 15 | *.pth.tar 16 | *.npy 17 | 18 | # Data files and directories common in repo root 19 | logs/ 20 | *.h5 21 | results/ 22 | temp/ 23 | tmp/ 24 | test/ 25 | storage/ 26 | 27 | # Byte-compiled / optimized / DLL files 28 | __pycache__/ 29 | *.py[cod] 30 | *$py.class 31 | 32 | # Distribution / packaging 33 | .Python 34 | env/ 35 | build/ 36 | develop-eggs/ 37 | dist/ 38 | downloads/ 39 | eggs/ 40 | .eggs/ 41 | lib/ 42 | lib64/ 43 | parts/ 44 | sdist/ 45 | var/ 46 | wheels/ 47 | *.egg-info/ 48 | .installed.cfg 49 | *.egg 50 | arun_log/ 51 | 52 | # Installer logs 53 | pip-log.txt 54 | pip-delete-this-directory.txt 55 | 56 | # VS Studio Code 57 | .vscode 58 | 59 | # PyCharm 60 | .idea/ 61 | 62 | # Dropbox 63 | .dropbox.attr 64 | 65 | # Jupyter Notebook 66 | .ipynb_checkpoints 67 | 68 | # pyenv 69 | .python-version 70 | 71 | # dotenv 72 | .env 73 | 74 | # virtualenv 75 | .venv 76 | venv/ 77 | ENV/ 78 | 79 | # model_convert 80 | to_caffe/ 81 | to_kestrel/ 82 | *.tar 83 | to_kestrel.yaml 84 | *petreloss*.conf 85 | -------------------------------------------------------------------------------- /semi_seg/data/splits/pascal/183/labeled.txt: -------------------------------------------------------------------------------- 1 | 2008_006748 2 | 2011_000453 3 | 2010_002338 4 | 2009_000161 5 | 2009_003860 6 | 2007_008945 7 | 2007_002488 8 | 2008_001056 9 | 2008_000515 10 | 2010_002286 11 | 2009_000603 12 | 2010_005500 13 | 2009_000015 14 | 2008_001358 15 | 2011_001400 16 | 2010_001386 17 | 2007_009580 18 | 2007_006899 19 | 2007_006317 20 | 2008_003252 21 | 2010_005232 22 | 2011_002350 23 | 2011_002920 24 | 2009_004117 25 | 2011_002246 26 | 2008_003200 27 | 2007_005988 28 | 2009_001339 29 | 2010_005429 30 | 2009_001117 31 | 2008_005668 32 | 2008_002338 33 | 2007_005273 34 | 2011_000382 35 | 2009_000408 36 | 2009_000420 37 | 2010_003380 38 | 2007_005262 39 | 2010_003799 40 | 2008_005843 41 | 2007_003715 42 | 2009_004425 43 | 2009_003172 44 | 2011_000152 45 | 2007_000528 46 | 2011_003246 47 | 2007_008307 48 | 2007_007585 49 | 2011_001810 50 | 2008_006490 51 | 2007_009052 52 | 2009_003975 53 | 2010_000075 54 | 2007_002967 55 | 2007_003118 56 | 2008_005214 57 | 2007_000738 58 | 2009_000285 59 | 2007_007481 60 | 2010_001418 61 | 2011_002335 62 | 2007_002273 63 | 2011_001166 64 | 2011_003038 65 | 2008_005006 66 | 2010_000117 67 | 2010_002625 68 | 2009_002993 69 | 2007_005790 70 | 2008_003180 71 | 2009_001095 72 | 2010_001329 73 | 2011_002559 74 | 2009_001070 75 | 2010_005318 76 | 2011_000122 77 | 2009_003697 78 | 2010_002892 79 | 2009_002019 80 | 2008_002471 81 | 2007_005314 82 | 2007_007398 83 | 2008_008343 84 | 2007_003207 85 | 2009_002588 86 | 2009_002422 87 | 2008_002697 88 | 2011_001754 89 | 2008_007375 90 | 2008_003060 91 | 2011_001259 92 | 2010_004171 93 | 2009_000655 94 | 2010_004478 95 | 2011_001855 96 | 2007_009649 97 | 2007_003267 98 | 2008_001188 99 | 2010_004900 100 | 2011_000449 101 | 2008_004869 102 | 2008_004838 103 | 2010_002907 104 | 2008_004259 105 | 2008_003429 106 | 2011_000999 107 | 2011_001632 108 | 2011_000577 109 | 2010_005505 110 | 2010_004365 111 | 2007_007948 112 | 2008_005713 113 | 2008_006920 114 | 2010_000132 115 | 2008_006182 116 | 2007_005212 117 | 2009_000746 118 | 2009_005236 119 | 2010_005876 120 | 2007_002462 121 | 2009_000409 122 | 2008_008525 123 | 2011_002114 124 | 2010_003887 125 | 2009_005287 126 | 2010_002815 127 | 2010_002203 128 | 2010_003717 129 | 2010_005277 130 | 2008_000832 131 | 2009_003757 132 | 2007_006477 133 | 2008_003480 134 | 2009_003783 135 | 2009_003646 136 | 2011_000068 137 | 2010_002573 138 | 2010_001160 139 | 2011_002447 140 | 2008_002215 141 | 2011_002709 142 | 2010_004721 143 | 2008_003065 144 | 2009_002314 145 | 2007_009605 146 | 2007_007230 147 | 2008_003373 148 | 2011_002135 149 | 2008_003939 150 | 2010_001706 151 | 2008_002218 152 | 2009_003034 153 | 2010_001247 154 | 2010_001922 155 | 2007_009832 156 | 2011_000208 157 | 2010_002527 158 | 2010_002154 159 | 2009_001203 160 | 2007_003251 161 | 2010_002962 162 | 2007_000515 163 | 2009_002387 164 | 2007_006400 165 | 2009_003249 166 | 2009_000454 167 | 2009_004539 168 | 2009_001544 169 | 2009_004446 170 | 2010_004683 171 | 2007_007878 172 | 2011_002291 173 | 2011_000108 174 | 2010_004154 175 | 2010_001347 176 | 2008_004892 177 | 2007_005264 178 | 2009_004561 179 | 2011_000468 180 | 2011_000920 181 | 2011_001928 182 | 2008_003562 183 | 2009_001036 -------------------------------------------------------------------------------- /semi_seg/data/splits/pascal/92/labeled.txt: -------------------------------------------------------------------------------- 1 | 2007_000733 2 | 2010_004493 3 | 2010_000466 4 | 2009_000894 5 | 2007_002234 6 | 2009_005145 7 | 2008_008511 8 | 2007_009327 9 | 2007_003431 10 | 2009_005069 11 | 2011_002585 12 | 2009_004409 13 | 2008_000645 14 | 2007_005144 15 | 2009_000895 16 | 2010_003670 17 | 2011_000243 18 | 2010_000978 19 | 2007_005797 20 | 2011_001412 21 | 2010_004074 22 | 2009_001514 23 | 2010_005217 24 | 2010_005775 25 | 2007_005043 26 | 2008_000595 27 | 2010_001933 28 | 2011_003216 29 | 2009_002052 30 | 2008_001761 31 | 2009_002362 32 | 2010_004069 33 | 2009_001270 34 | 2008_006345 35 | 2010_004900 36 | 2009_003249 37 | 2008_004014 38 | 2010_004916 39 | 2008_007242 40 | 2009_004095 41 | 2007_002142 42 | 2011_000882 43 | 2011_001015 44 | 2010_002532 45 | 2011_000069 46 | 2008_000188 47 | 2008_000105 48 | 2009_004790 49 | 2011_002488 50 | 2009_001100 51 | 2010_004560 52 | 2010_004773 53 | 2010_003093 54 | 2007_009082 55 | 2011_001536 56 | 2008_000470 57 | 2008_000284 58 | 2010_005064 59 | 2008_000336 60 | 2008_008462 61 | 2007_001960 62 | 2007_004951 63 | 2008_004112 64 | 2009_001339 65 | 2008_005074 66 | 2010_003010 67 | 2011_000122 68 | 2010_001279 69 | 2010_004363 70 | 2011_002561 71 | 2007_005989 72 | 2010_003799 73 | 2007_006004 74 | 2007_009630 75 | 2008_001159 76 | 2007_007003 77 | 2008_001610 78 | 2007_007415 79 | 2007_002273 80 | 2010_003157 81 | 2011_002107 82 | 2010_005982 83 | 2007_005878 84 | 2011_000457 85 | 2008_000832 86 | 2008_003769 87 | 2010_002047 88 | 2009_002387 89 | 2009_002117 90 | 2011_002920 91 | 2010_004760 92 | 2008_004822 -------------------------------------------------------------------------------- /semi_seg/experiments/cityscapes/372/mt/config.yaml: -------------------------------------------------------------------------------- 1 | dataset: # Required. 2 | type: cityscapes_semi 3 | train: 4 | data_root: ../../../../data/cityscapes 5 | data_list: ../../../../data/splits/cityscapes/372/labeled.txt 6 | flip: True 7 | GaussianBlur: False 8 | rand_resize: [0.5, 2.0] 9 | #rand_rotation: [-10.0, 10.0] 10 | crop: 11 | type: rand 12 | size: [769, 769] # crop image with HxW size 13 | val: 14 | data_root: ../../../../data/cityscapes 15 | data_list: ../../../../data/splits/cityscapes/val.txt 16 | crop: 17 | type: center 18 | size: [769, 769] # crop image with HxW size 19 | batch_size: 2 20 | n_sup: 744 21 | noise_std: 0.1 22 | workers: 2 23 | mean: [123.675, 116.28, 103.53] 24 | std: [58.395, 57.12, 57.375] 25 | ignore_label: 255 26 | 27 | trainer: # Required. 28 | epochs: 80 29 | eval_on: True 30 | optimizer: 31 | type: SGD 32 | kwargs: 33 | lr: 0.01 # 8GPUs 34 | momentum: 0.9 35 | weight_decay: 0.0005 36 | lr_scheduler: 37 | mode: poly 38 | kwargs: 39 | power: 0.9 40 | unsupervised: 41 | TTA: False 42 | 43 | saver: 44 | auto_resume: True 45 | snapshot_dir: checkpoints 46 | pretrain: '' 47 | 48 | criterion: 49 | type: ohem 50 | kwargs: 51 | thresh: 0.7 52 | min_kept: 100000 53 | 54 | net: # Required. 55 | num_classes: 19 56 | sync_bn: True 57 | ema_decay: 0.99 58 | aux_loss: 59 | aux_plane: 1024 60 | loss_weight: 0.4 61 | encoder: 62 | type: fst.models.resnet.resnet101 63 | kwargs: 64 | multi_grid: True 65 | zero_init_residual: True 66 | fpn: True 67 | replace_stride_with_dilation: [False, True, True] #layer0...1 is fixed, layer2...4 68 | decoder: 69 | type: fst.models.decoder.dec_deeplabv3_plus 70 | kwargs: 71 | inner_planes: 256 72 | dilations: [12, 24, 36] 73 | -------------------------------------------------------------------------------- /semi_seg/experiments/cityscapes/372/mt/eval.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | now=$(date +"%Y%m%d_%H%M%S") 3 | job='eval' 4 | ROOT=../../../.. 5 | 6 | mkdir -p log 7 | mkdir -p checkpoints/results 8 | 9 | python $ROOT/eval.py \ 10 | --config=config.yaml \ 11 | --base_size 2048 \ 12 | --scales 1.0 \ 13 | --model_path=checkpoints/ckpt.pth \ 14 | --save_folder=checkpoints/results \ 15 | 2>&1 | tee log/val_last_$now.txt 16 | 17 | python $ROOT/eval.py \ 18 | --config=config.yaml \ 19 | --base_size 2048 \ 20 | --scales 1.0 \ 21 | --model_path=checkpoints/ckpt_best.pth \ 22 | --save_folder=checkpoints/results \ 23 | 2>&1 | tee log/val_best_$now.txt -------------------------------------------------------------------------------- /semi_seg/experiments/cityscapes/372/mt/train.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | now=$(date +"%Y%m%d_%H%M%S") 3 | job='372_mt' 4 | ROOT=../../../.. 5 | 6 | mkdir -p log 7 | 8 | # use torch.distributed.launch 9 | python -m torch.distributed.launch \ 10 | --nproc_per_node=$1 \ 11 | --nnodes=1 \ 12 | --node_rank=0 \ 13 | --master_addr=localhost \ 14 | --master_port=$2 \ 15 | $ROOT/train_semi.py --config=config.yaml --seed 2 --port $2 2>&1 | tee log/seg_$now.txt -------------------------------------------------------------------------------- /semi_seg/experiments/cityscapes/372/mt_fst/config.yaml: -------------------------------------------------------------------------------- 1 | dataset: # Required. 2 | type: cityscapes_semi 3 | train: 4 | data_root: ../../../../data/cityscapes 5 | data_list: ../../../../data/splits/cityscapes/744/labeled.txt 6 | flip: True 7 | GaussianBlur: False 8 | rand_resize: [0.5, 2.0] 9 | #rand_rotation: [-10.0, 10.0] 10 | crop: 11 | type: rand 12 | size: [769, 769] # crop image with HxW size 13 | val: 14 | data_root: ../../../../data/cityscapes 15 | data_list: ../../../../data/splits/cityscapes/val.txt 16 | crop: 17 | type: center 18 | size: [769, 769] # crop image with HxW size 19 | batch_size: 2 20 | n_sup: 744 21 | noise_std: 0.1 22 | workers: 2 23 | mean: [123.675, 116.28, 103.53] 24 | std: [58.395, 57.12, 57.375] 25 | ignore_label: 255 26 | 27 | trainer: # Required. 28 | epochs: 80 29 | fst: True 30 | eval_on: True 31 | optimizer: 32 | type: SGD 33 | kwargs: 34 | lr: 0.01 # 8GPUs 35 | momentum: 0.9 36 | weight_decay: 0.0005 37 | lr_scheduler: 38 | mode: poly 39 | kwargs: 40 | power: 0.9 41 | unsupervised: 42 | TTA: False 43 | 44 | saver: 45 | auto_resume: True 46 | snapshot_dir: checkpoints 47 | pretrain: '' 48 | 49 | criterion: 50 | type: ohem 51 | kwargs: 52 | thresh: 0.7 53 | min_kept: 100000 54 | 55 | net: # Required. 56 | num_classes: 19 57 | sync_bn: True 58 | ema_decay: 0.99 59 | aux_loss: 60 | aux_plane: 1024 61 | loss_weight: 0.4 62 | encoder: 63 | type: fst.models.resnet.resnet101 64 | kwargs: 65 | multi_grid: True 66 | zero_init_residual: True 67 | fpn: True 68 | replace_stride_with_dilation: [False, True, True] #layer0...1 is fixed, layer2...4 69 | decoder: 70 | type: fst.models.decoder.dec_deeplabv3_plus 71 | kwargs: 72 | inner_planes: 256 73 | dilations: [12, 24, 36] 74 | -------------------------------------------------------------------------------- /semi_seg/experiments/cityscapes/372/mt_fst/eval.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | now=$(date +"%Y%m%d_%H%M%S") 3 | job='eval' 4 | ROOT=../../../.. 5 | 6 | mkdir -p log 7 | mkdir -p checkpoints/results 8 | 9 | python $ROOT/eval.py \ 10 | --config=config.yaml \ 11 | --base_size 2048 \ 12 | --scales 1.0 \ 13 | --model_path=checkpoints/ckpt.pth \ 14 | --save_folder=checkpoints/results \ 15 | 2>&1 | tee log/val_last_$now.txt 16 | 17 | python $ROOT/eval.py \ 18 | --config=config.yaml \ 19 | --base_size 2048 \ 20 | --scales 1.0 \ 21 | --model_path=checkpoints/ckpt_best.pth \ 22 | --save_folder=checkpoints/results \ 23 | 2>&1 | tee log/val_best_$now.txt -------------------------------------------------------------------------------- /semi_seg/experiments/cityscapes/372/mt_fst/train.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | now=$(date +"%Y%m%d_%H%M%S") 3 | job='372_mt_fst' 4 | ROOT=../../../.. 5 | 6 | mkdir -p log 7 | 8 | # use torch.distributed.launch 9 | python -m torch.distributed.launch \ 10 | --nproc_per_node=$1 \ 11 | --nnodes=1 \ 12 | --node_rank=0 \ 13 | --master_addr=localhost \ 14 | --master_port=$2 \ 15 | $ROOT/train_semi.py --config=config.yaml --seed 2 --port $2 2>&1 | tee log/seg_$now.txt -------------------------------------------------------------------------------- /semi_seg/experiments/pascal/662/cutmix/config.yaml: -------------------------------------------------------------------------------- 1 | dataset: # Required. 2 | type: pascal_semi 3 | train: 4 | data_root: ../../../../data/VOC2012 5 | data_list: ../../../../data/splits/pascal/662/labeled.txt 6 | flip: True 7 | GaussianBlur: False 8 | rand_resize: [0.5, 2.0] 9 | #rand_rotation: [-10.0, 10.0] 10 | crop: 11 | type: rand 12 | size: [513, 513] # crop image with HxW size 13 | val: 14 | data_root: ../../../../data/VOC2012 15 | data_list: ../../../../data/splits/pascal/val.txt 16 | crop: 17 | type: center 18 | size: [513, 513] # crop image with HxW size 19 | batch_size: 4 20 | n_sup: 662 21 | noise_std: 0.1 22 | workers: 2 23 | mean: [123.675, 116.28, 103.53] 24 | std: [58.395, 57.12, 57.375] 25 | ignore_label: 255 26 | 27 | trainer: # Required. 28 | epochs: 40 29 | eval_on: True 30 | optimizer: 31 | type: SGD 32 | kwargs: 33 | lr: 0.001 # 4GPUs 34 | momentum: 0.9 35 | weight_decay: 0.0001 36 | lr_scheduler: 37 | mode: poly 38 | kwargs: 39 | power: 0.9 40 | unsupervised: 41 | TTA: False 42 | drop_percent: 80 43 | apply_aug: cutmix 44 | 45 | saver: 46 | auto_resume: True 47 | snapshot_dir: checkpoints 48 | pretrain: '' 49 | 50 | criterion: 51 | type: CELoss 52 | kwargs: 53 | use_weight: False 54 | 55 | net: # Required. 56 | num_classes: 21 57 | sync_bn: True 58 | ema_decay: 0.99 59 | encoder: 60 | type: fst.models.resnet.resnet101 61 | kwargs: 62 | multi_grid: True 63 | zero_init_residual: True 64 | fpn: True 65 | replace_stride_with_dilation: [False, True, True] #layer0...1 is fixed, layer2...4 66 | decoder: 67 | type: fst.models.decoder.dec_deeplabv3_plus 68 | kwargs: 69 | inner_planes: 256 70 | dilations: [12, 24, 36] 71 | -------------------------------------------------------------------------------- /semi_seg/experiments/pascal/662/cutmix/train.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | now=$(date +"%Y%m%d_%H%M%S") 3 | job='662_cutmix' 4 | ROOT=../../../.. 5 | 6 | mkdir -p log 7 | 8 | # use torch.distributed.launch 9 | python -m torch.distributed.launch \ 10 | --nproc_per_node=$1 \ 11 | --nnodes=1 \ 12 | --node_rank=0 \ 13 | --master_addr=localhost \ 14 | --master_port=$2 \ 15 | $ROOT/train_semi.py --config=config.yaml --seed 2 --port $2 2>&1 | tee log/seg_$now.txt -------------------------------------------------------------------------------- /semi_seg/experiments/pascal/662/cutmix_fst/config.yaml: -------------------------------------------------------------------------------- 1 | dataset: # Required. 2 | type: pascal_semi 3 | train: 4 | data_root: ../../../../data/VOC2012 5 | data_list: ../../../../data/splits/pascal/662/labeled.txt 6 | flip: True 7 | GaussianBlur: False 8 | rand_resize: [0.5, 2.0] 9 | #rand_rotation: [-10.0, 10.0] 10 | crop: 11 | type: rand 12 | size: [513, 513] # crop image with HxW size 13 | val: 14 | data_root: ../../../../data/VOC2012 15 | data_list: ../../../../data/splits/pascal/val.txt 16 | crop: 17 | type: center 18 | size: [513, 513] # crop image with HxW size 19 | batch_size: 4 20 | n_sup: 662 21 | noise_std: 0.1 22 | workers: 2 23 | mean: [123.675, 116.28, 103.53] 24 | std: [58.395, 57.12, 57.375] 25 | ignore_label: 255 26 | 27 | trainer: # Required. 28 | epochs: 40 29 | eval_on: True 30 | fst: True 31 | optimizer: 32 | type: SGD 33 | kwargs: 34 | lr: 0.001 # 4GPUs 35 | momentum: 0.9 36 | weight_decay: 0.0001 37 | lr_scheduler: 38 | mode: poly 39 | kwargs: 40 | power: 0.9 41 | unsupervised: 42 | TTA: False 43 | drop_percent: 80 44 | apply_aug: cutmix 45 | 46 | saver: 47 | auto_resume: True 48 | snapshot_dir: checkpoints 49 | pretrain: '' 50 | 51 | criterion: 52 | type: CELoss 53 | kwargs: 54 | use_weight: False 55 | 56 | net: # Required. 57 | num_classes: 21 58 | sync_bn: True 59 | ema_decay: 0.99 60 | encoder: 61 | type: fst.models.resnet.resnet101 62 | kwargs: 63 | multi_grid: True 64 | zero_init_residual: True 65 | fpn: True 66 | replace_stride_with_dilation: [False, True, True] #layer0...1 is fixed, layer2...4 67 | decoder: 68 | type: fst.models.decoder.dec_deeplabv3_plus 69 | kwargs: 70 | inner_planes: 256 71 | dilations: [12, 24, 36] 72 | -------------------------------------------------------------------------------- /semi_seg/experiments/pascal/662/cutmix_fst/train.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | now=$(date +"%Y%m%d_%H%M%S") 3 | job='662_cutmix_fst' 4 | ROOT=../../../.. 5 | 6 | mkdir -p log 7 | 8 | # use torch.distributed.launch 9 | python -m torch.distributed.launch \ 10 | --nproc_per_node=$1 \ 11 | --nnodes=1 \ 12 | --node_rank=0 \ 13 | --master_addr=localhost \ 14 | --master_port=$2 \ 15 | $ROOT/train_semi.py --config=config.yaml --seed 2 --port $2 2>&1 | tee log/seg_$now.txt -------------------------------------------------------------------------------- /semi_seg/experiments/pascal/662/mt/config.yaml: -------------------------------------------------------------------------------- 1 | dataset: # Required. 2 | type: pascal_semi 3 | train: 4 | data_root: ../../../../data/VOC2012 5 | data_list: ../../../../data/splits/pascal/662/labeled.txt 6 | flip: True 7 | GaussianBlur: False 8 | rand_resize: [0.5, 2.0] 9 | #rand_rotation: [-10.0, 10.0] 10 | crop: 11 | type: rand 12 | size: [513, 513] # crop image with HxW size 13 | val: 14 | data_root: ../../../../data/VOC2012 15 | data_list: ../../../../data/splits/pascal/val.txt 16 | crop: 17 | type: center 18 | size: [513, 513] # crop image with HxW size 19 | batch_size: 4 20 | n_sup: 662 21 | noise_std: 0.1 22 | workers: 2 23 | mean: [123.675, 116.28, 103.53] 24 | std: [58.395, 57.12, 57.375] 25 | ignore_label: 255 26 | 27 | trainer: # Required. 28 | epochs: 40 29 | eval_on: True 30 | optimizer: 31 | type: SGD 32 | kwargs: 33 | lr: 0.001 # 4GPUs 34 | momentum: 0.9 35 | weight_decay: 0.0001 36 | lr_scheduler: 37 | mode: poly 38 | kwargs: 39 | power: 0.9 40 | unsupervised: 41 | TTA: False 42 | drop_percent: 80 43 | apply_aug: False 44 | 45 | saver: 46 | auto_resume: True 47 | snapshot_dir: checkpoints 48 | pretrain: '' 49 | 50 | criterion: 51 | type: CELoss 52 | kwargs: 53 | use_weight: False 54 | 55 | net: # Required. 56 | num_classes: 21 57 | sync_bn: True 58 | ema_decay: 0.99 59 | encoder: 60 | type: fst.models.resnet.resnet101 61 | kwargs: 62 | multi_grid: True 63 | zero_init_residual: True 64 | fpn: True 65 | replace_stride_with_dilation: [False, True, True] #layer0...1 is fixed, layer2...4 66 | decoder: 67 | type: fst.models.decoder.dec_deeplabv3_plus 68 | kwargs: 69 | inner_planes: 256 70 | dilations: [12, 24, 36] 71 | -------------------------------------------------------------------------------- /semi_seg/experiments/pascal/662/mt/train.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | now=$(date +"%Y%m%d_%H%M%S") 3 | job='662_mt' 4 | ROOT=../../../.. 5 | 6 | mkdir -p log 7 | 8 | # use torch.distributed.launch 9 | python -m torch.distributed.launch \ 10 | --nproc_per_node=$1 \ 11 | --nnodes=1 \ 12 | --node_rank=0 \ 13 | --master_addr=localhost \ 14 | --master_port=$2 \ 15 | $ROOT/train_semi.py --config=config.yaml --seed 2 --port $2 2>&1 | tee log/seg_$now.txt -------------------------------------------------------------------------------- /semi_seg/experiments/pascal/662/mt_fst/config.yaml: -------------------------------------------------------------------------------- 1 | dataset: # Required. 2 | type: pascal_semi 3 | train: 4 | data_root: ../../../../data/VOC2012 5 | data_list: ../../../../data/splits/pascal/662/labeled.txt 6 | flip: True 7 | GaussianBlur: False 8 | rand_resize: [0.5, 2.0] 9 | #rand_rotation: [-10.0, 10.0] 10 | crop: 11 | type: rand 12 | size: [513, 513] # crop image with HxW size 13 | val: 14 | data_root: ../../../../data/VOC2012 15 | data_list: ../../../../data/splits/pascal/val.txt 16 | crop: 17 | type: center 18 | size: [513, 513] # crop image with HxW size 19 | batch_size: 4 20 | n_sup: 662 21 | noise_std: 0.1 22 | workers: 2 23 | mean: [123.675, 116.28, 103.53] 24 | std: [58.395, 57.12, 57.375] 25 | ignore_label: 255 26 | 27 | trainer: # Required. 28 | epochs: 40 29 | fst: True 30 | eval_on: True 31 | optimizer: 32 | type: SGD 33 | kwargs: 34 | lr: 0.001 # 4GPUs 35 | momentum: 0.9 36 | weight_decay: 0.0001 37 | lr_scheduler: 38 | mode: poly 39 | kwargs: 40 | power: 0.9 41 | unsupervised: 42 | TTA: False 43 | drop_percent: 80 44 | apply_aug: False 45 | 46 | saver: 47 | auto_resume: True 48 | snapshot_dir: checkpoints 49 | pretrain: '' 50 | 51 | criterion: 52 | type: CELoss 53 | kwargs: 54 | use_weight: False 55 | 56 | net: # Required. 57 | num_classes: 21 58 | sync_bn: True 59 | ema_decay: 0.99 60 | encoder: 61 | type: fst.models.resnet.resnet101 62 | kwargs: 63 | multi_grid: True 64 | zero_init_residual: True 65 | fpn: True 66 | replace_stride_with_dilation: [False, True, True] #layer0...1 is fixed, layer2...4 67 | decoder: 68 | type: fst.models.decoder.dec_deeplabv3_plus 69 | kwargs: 70 | inner_planes: 256 71 | dilations: [12, 24, 36] 72 | -------------------------------------------------------------------------------- /semi_seg/experiments/pascal/662/mt_fst/train.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | now=$(date +"%Y%m%d_%H%M%S") 3 | job='662_mt_fst' 4 | ROOT=../../../.. 5 | 6 | mkdir -p log 7 | 8 | # use torch.distributed.launch 9 | python -m torch.distributed.launch \ 10 | --nproc_per_node=$1 \ 11 | --nnodes=1 \ 12 | --node_rank=0 \ 13 | --master_addr=localhost \ 14 | --master_port=$2 \ 15 | $ROOT/train_semi.py --config=config.yaml --seed 2 --port $2 2>&1 | tee log/seg_$now.txt -------------------------------------------------------------------------------- /semi_seg/experiments/pascal/662/psp_mt/config.yaml: -------------------------------------------------------------------------------- 1 | dataset: # Required. 2 | type: pascal_semi 3 | train: 4 | data_root: ../../../../data/VOC2012 5 | data_list: ../../../../data/splits/pascal/662/labeled.txt 6 | flip: True 7 | GaussianBlur: False 8 | rand_resize: [0.5, 2.0] 9 | #rand_rotation: [-10.0, 10.0] 10 | crop: 11 | type: rand 12 | size: [513, 513] # crop image with HxW size 13 | val: 14 | data_root: ../../../../data/VOC2012 15 | data_list: ../../../../data/splits/pascal/val.txt 16 | crop: 17 | type: center 18 | size: [513, 513] # crop image with HxW size 19 | batch_size: 4 20 | n_sup: 662 21 | noise_std: 0.1 22 | workers: 2 23 | mean: [123.675, 116.28, 103.53] 24 | std: [58.395, 57.12, 57.375] 25 | ignore_label: 255 26 | 27 | trainer: # Required. 28 | epochs: 40 29 | eval_on: True 30 | optimizer: 31 | type: SGD 32 | kwargs: 33 | lr: 0.001 # 4GPUs 34 | momentum: 0.9 35 | weight_decay: 0.0001 36 | lr_scheduler: 37 | mode: poly 38 | kwargs: 39 | power: 0.9 40 | unsupervised: 41 | TTA: False 42 | drop_percent: 80 43 | apply_aug: False 44 | 45 | saver: 46 | auto_resume: True 47 | snapshot_dir: checkpoints 48 | pretrain: '' 49 | 50 | criterion: 51 | type: CELoss 52 | kwargs: 53 | use_weight: False 54 | 55 | net: # Required. 56 | num_classes: 21 57 | sync_bn: True 58 | ema_decay: 0.99 59 | encoder: 60 | type: fst.models.resnet.resnet101 61 | kwargs: 62 | multi_grid: True 63 | zero_init_residual: True 64 | fpn: True 65 | replace_stride_with_dilation: [False, True, True] #layer0...1 is fixed, layer2...4 66 | decoder: 67 | type: fst.models.decoder.dec_pspnet 68 | kwargs: {} 69 | -------------------------------------------------------------------------------- /semi_seg/experiments/pascal/662/psp_mt/train.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | now=$(date +"%Y%m%d_%H%M%S") 3 | job='662_psp_mt' 4 | ROOT=../../../.. 5 | 6 | mkdir -p log 7 | 8 | # use torch.distributed.launch 9 | python -m torch.distributed.launch \ 10 | --nproc_per_node=$1 \ 11 | --nnodes=1 \ 12 | --node_rank=0 \ 13 | --master_addr=localhost \ 14 | --master_port=$2 \ 15 | $ROOT/train_semi.py --config=config.yaml --seed 2 --port $2 2>&1 | tee log/seg_$now.txt -------------------------------------------------------------------------------- /semi_seg/experiments/pascal/662/psp_mt_fst/config.yaml: -------------------------------------------------------------------------------- 1 | dataset: # Required. 2 | type: pascal_semi 3 | train: 4 | data_root: ../../../../data/VOC2012 5 | data_list: ../../../../data/splits/pascal/662/labeled.txt 6 | flip: True 7 | GaussianBlur: False 8 | rand_resize: [0.5, 2.0] 9 | #rand_rotation: [-10.0, 10.0] 10 | crop: 11 | type: rand 12 | size: [513, 513] # crop image with HxW size 13 | val: 14 | data_root: ../../../../data/VOC2012 15 | data_list: ../../../../data/splits/pascal/val.txt 16 | crop: 17 | type: center 18 | size: [513, 513] # crop image with HxW size 19 | batch_size: 4 20 | n_sup: 662 21 | noise_std: 0.1 22 | workers: 2 23 | mean: [123.675, 116.28, 103.53] 24 | std: [58.395, 57.12, 57.375] 25 | ignore_label: 255 26 | 27 | trainer: # Required. 28 | epochs: 40 29 | fst: True 30 | eval_on: True 31 | optimizer: 32 | type: SGD 33 | kwargs: 34 | lr: 0.001 # 4GPUs 35 | momentum: 0.9 36 | weight_decay: 0.0001 37 | lr_scheduler: 38 | mode: poly 39 | kwargs: 40 | power: 0.9 41 | unsupervised: 42 | TTA: False 43 | drop_percent: 80 44 | apply_aug: False 45 | 46 | saver: 47 | auto_resume: True 48 | snapshot_dir: checkpoints 49 | pretrain: '' 50 | 51 | criterion: 52 | type: CELoss 53 | kwargs: 54 | use_weight: False 55 | 56 | net: # Required. 57 | num_classes: 21 58 | sync_bn: True 59 | ema_decay: 0.99 60 | encoder: 61 | type: fst.models.resnet.resnet101 62 | kwargs: 63 | multi_grid: True 64 | zero_init_residual: True 65 | fpn: True 66 | replace_stride_with_dilation: [False, True, True] #layer0...1 is fixed, layer2...4 67 | decoder: 68 | type: fst.models.decoder.dec_pspnet 69 | kwargs: {} 70 | -------------------------------------------------------------------------------- /semi_seg/experiments/pascal/662/psp_mt_fst/train.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | now=$(date +"%Y%m%d_%H%M%S") 3 | job='662_psp_mt_fst' 4 | ROOT=../../../.. 5 | 6 | mkdir -p log 7 | 8 | # use torch.distributed.launch 9 | python -m torch.distributed.launch \ 10 | --nproc_per_node=$1 \ 11 | --nnodes=1 \ 12 | --node_rank=0 \ 13 | --master_addr=localhost \ 14 | --master_port=$2 \ 15 | $ROOT/train_semi.py --config=config.yaml --seed 2 --port $2 2>&1 | tee log/seg_$now.txt -------------------------------------------------------------------------------- /semi_seg/experiments/pascal/662/v2_mt/config.yaml: -------------------------------------------------------------------------------- 1 | dataset: # Required. 2 | type: pascal_semi 3 | train: 4 | data_root: ../../../../data/VOC2012 5 | data_list: ../../../../data/splits/pascal/662/labeled.txt 6 | flip: True 7 | GaussianBlur: False 8 | rand_resize: [0.5, 2.0] 9 | #rand_rotation: [-10.0, 10.0] 10 | crop: 11 | type: rand 12 | size: [513, 513] # crop image with HxW size 13 | val: 14 | data_root: ../../../../data/VOC2012 15 | data_list: ../../../../data/splits/pascal/val.txt 16 | crop: 17 | type: center 18 | size: [513, 513] # crop image with HxW size 19 | batch_size: 4 20 | n_sup: 662 21 | noise_std: 0.1 22 | workers: 2 23 | mean: [123.675, 116.28, 103.53] 24 | std: [58.395, 57.12, 57.375] 25 | ignore_label: 255 26 | 27 | trainer: # Required. 28 | epochs: 40 29 | eval_on: True 30 | optimizer: 31 | type: SGD 32 | kwargs: 33 | lr: 0.001 # 4GPUs 34 | momentum: 0.9 35 | weight_decay: 0.0001 36 | lr_scheduler: 37 | mode: poly 38 | kwargs: 39 | power: 0.9 40 | unsupervised: 41 | TTA: False 42 | drop_percent: 80 43 | apply_aug: False 44 | 45 | saver: 46 | auto_resume: True 47 | snapshot_dir: checkpoints 48 | pretrain: '' 49 | 50 | criterion: 51 | type: CELoss 52 | kwargs: 53 | use_weight: False 54 | 55 | net: # Required. 56 | num_classes: 21 57 | sync_bn: True 58 | ema_decay: 0.99 59 | encoder: 60 | type: fst.models.resnet.resnet101 61 | kwargs: 62 | multi_grid: True 63 | zero_init_residual: True 64 | fpn: True 65 | replace_stride_with_dilation: [False, True, True] #layer0...1 is fixed, layer2...4 66 | decoder: 67 | type: fst.models.decoder.dec_deeplabv2 68 | kwargs: {} 69 | -------------------------------------------------------------------------------- /semi_seg/experiments/pascal/662/v2_mt/train.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | now=$(date +"%Y%m%d_%H%M%S") 3 | job='662_v2_mt' 4 | ROOT=../../../.. 5 | 6 | mkdir -p log 7 | 8 | # use torch.distributed.launch 9 | python -m torch.distributed.launch \ 10 | --nproc_per_node=$1 \ 11 | --nnodes=1 \ 12 | --node_rank=0 \ 13 | --master_addr=localhost \ 14 | --master_port=$2 \ 15 | $ROOT/train_semi.py --config=config.yaml --seed 2 --port $2 2>&1 | tee log/seg_$now.txt -------------------------------------------------------------------------------- /semi_seg/experiments/pascal/662/v2_mt_fst/config.yaml: -------------------------------------------------------------------------------- 1 | dataset: # Required. 2 | type: pascal_semi 3 | train: 4 | data_root: ../../../../data/VOC2012 5 | data_list: ../../../../data/splits/pascal/662/labeled.txt 6 | flip: True 7 | GaussianBlur: False 8 | rand_resize: [0.5, 2.0] 9 | #rand_rotation: [-10.0, 10.0] 10 | crop: 11 | type: rand 12 | size: [513, 513] # crop image with HxW size 13 | val: 14 | data_root: ../../../../data/VOC2012 15 | data_list: ../../../../data/splits/pascal/val.txt 16 | crop: 17 | type: center 18 | size: [513, 513] # crop image with HxW size 19 | batch_size: 4 20 | n_sup: 662 21 | noise_std: 0.1 22 | workers: 2 23 | mean: [123.675, 116.28, 103.53] 24 | std: [58.395, 57.12, 57.375] 25 | ignore_label: 255 26 | 27 | trainer: # Required. 28 | epochs: 40 29 | fst: True 30 | eval_on: True 31 | optimizer: 32 | type: SGD 33 | kwargs: 34 | lr: 0.001 # 4GPUs 35 | momentum: 0.9 36 | weight_decay: 0.0001 37 | lr_scheduler: 38 | mode: poly 39 | kwargs: 40 | power: 0.9 41 | unsupervised: 42 | TTA: False 43 | drop_percent: 80 44 | apply_aug: False 45 | 46 | saver: 47 | auto_resume: True 48 | snapshot_dir: checkpoints 49 | pretrain: '' 50 | 51 | criterion: 52 | type: CELoss 53 | kwargs: 54 | use_weight: False 55 | 56 | net: # Required. 57 | num_classes: 21 58 | sync_bn: True 59 | ema_decay: 0.99 60 | encoder: 61 | type: fst.models.resnet.resnet101 62 | kwargs: 63 | multi_grid: True 64 | zero_init_residual: True 65 | fpn: True 66 | replace_stride_with_dilation: [False, True, True] #layer0...1 is fixed, layer2...4 67 | decoder: 68 | type: fst.models.decoder.dec_deeplabv2 69 | kwargs: {} 70 | -------------------------------------------------------------------------------- /semi_seg/experiments/pascal/662/v2_mt_fst/train.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | now=$(date +"%Y%m%d_%H%M%S") 3 | job='662_v2_mt_fst' 4 | ROOT=../../../.. 5 | 6 | mkdir -p log 7 | 8 | # use torch.distributed.launch 9 | python -m torch.distributed.launch \ 10 | --nproc_per_node=$1 \ 11 | --nnodes=1 \ 12 | --node_rank=0 \ 13 | --master_addr=localhost \ 14 | --master_port=$2 \ 15 | $ROOT/train_semi.py --config=config.yaml --seed 2 --port $2 2>&1 | tee log/seg_$now.txt -------------------------------------------------------------------------------- /semi_seg/fst/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/semi_seg/fst/__init__.py -------------------------------------------------------------------------------- /semi_seg/fst/dataset/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/semi_seg/fst/dataset/__init__.py -------------------------------------------------------------------------------- /semi_seg/fst/dataset/base.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from PIL import Image 4 | from torch.utils.data import Dataset 5 | 6 | 7 | class BaseDataset(Dataset): 8 | def __init__(self, d_list, **kwargs): 9 | # parse the input list 10 | self.parse_input_list(d_list, **kwargs) 11 | 12 | def parse_input_list(self, d_list, max_sample=-1, start_idx=-1, end_idx=-1): 13 | logger = logging.getLogger("global") 14 | assert isinstance(d_list, str) 15 | if "cityscapes" in d_list: 16 | self.list_sample = [ 17 | [ 18 | line.strip(), 19 | "gtFine/" + line.strip()[12:-15] + "gtFine_labelTrainIds.png", 20 | ] 21 | for line in open(d_list, "r") 22 | ] 23 | elif "pascal" in d_list or "VOC" in d_list: 24 | self.list_sample = [ 25 | [ 26 | "JPEGImages/{}.jpg".format(line.strip()), 27 | "SegmentationClassAug/{}.png".format(line.strip()), 28 | ] 29 | for line in open(d_list, "r") 30 | ] 31 | else: 32 | raise "unknown dataset!" 33 | 34 | if max_sample > 0: 35 | self.list_sample = self.list_sample[0:max_sample] 36 | if start_idx >= 0 and end_idx >= 0: 37 | self.list_sample = self.list_sample[start_idx:end_idx] 38 | 39 | self.num_sample = len(self.list_sample) 40 | assert self.num_sample > 0 41 | logger.info("# samples: {}".format(self.num_sample)) 42 | 43 | def img_loader(self, path, mode): 44 | with open(path, "rb") as f: 45 | img = Image.open(f) 46 | return img.convert(mode) 47 | 48 | def __len__(self): 49 | return self.num_sample 50 | -------------------------------------------------------------------------------- /semi_seg/fst/dataset/builder.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from .cityscapes import build_city_semi_loader, build_cityloader 4 | from .pascal_voc import build_voc_semi_loader, build_vocloader 5 | 6 | logger = logging.getLogger("global") 7 | 8 | 9 | def get_loader(cfg, seed=0): 10 | cfg_dataset = cfg["dataset"] 11 | 12 | if cfg_dataset["type"] == "cityscapes_semi": 13 | train_loader_sup, train_loader_unsup = build_city_semi_loader( 14 | "train", cfg, seed=seed 15 | ) 16 | val_loader = build_cityloader("val", cfg) 17 | logger.info("Get loader Done...") 18 | return train_loader_sup, train_loader_unsup, val_loader 19 | 20 | elif cfg_dataset["type"] == "cityscapes": 21 | train_loader_sup = build_cityloader("train", cfg, seed=seed) 22 | val_loader = build_cityloader("val", cfg) 23 | logger.info("Get loader Done...") 24 | return train_loader_sup, val_loader 25 | 26 | elif cfg_dataset["type"] == "pascal_semi": 27 | train_loader_sup, train_loader_unsup = build_voc_semi_loader( 28 | "train", cfg, seed=seed 29 | ) 30 | val_loader = build_vocloader("val", cfg) 31 | logger.info("Get loader Done...") 32 | return train_loader_sup, train_loader_unsup, val_loader 33 | 34 | elif cfg_dataset["type"] == "pascal": 35 | train_loader_sup = build_vocloader("train", cfg, seed=seed) 36 | val_loader = build_vocloader("val", cfg) 37 | logger.info("Get loader Done...") 38 | return train_loader_sup, val_loader 39 | 40 | else: 41 | raise NotImplementedError( 42 | "dataset type {} is not supported".format(cfg_dataset) 43 | ) 44 | -------------------------------------------------------------------------------- /semi_seg/fst/dataset/sampler.py: -------------------------------------------------------------------------------- 1 | import copy 2 | import logging 3 | import math 4 | 5 | import numpy as np 6 | import torch.distributed as dist 7 | from torch.utils.data.sampler import Sampler 8 | 9 | logger = logging.getLogger("global_logger") 10 | 11 | 12 | class DistributedGivenIterationSampler(Sampler): 13 | def __init__( 14 | self, dataset, total_iter, batch_size, world_size=None, rank=None, last_iter=-1 15 | ): 16 | if world_size is None: 17 | world_size = dist.get_world_size() 18 | if rank is None: 19 | rank = dist.get_rank() 20 | assert rank < world_size 21 | self.dataset = dataset 22 | self.total_iter = total_iter 23 | self.batch_size = batch_size 24 | self.world_size = world_size 25 | self.rank = rank 26 | self.last_iter = last_iter 27 | 28 | self.total_size = self.total_iter * self.batch_size 29 | 30 | self.indices = self.gen_new_list() 31 | self.call = 0 32 | 33 | def __iter__(self): 34 | if self.call == 0: 35 | self.call = 1 36 | return iter(self.indices[(self.last_iter + 1) * self.batch_size :]) 37 | else: 38 | raise RuntimeError( 39 | "this sampler is not designed to be called more than once!!" 40 | ) 41 | 42 | def gen_new_list(self): 43 | if self.rank == 0: 44 | logger.info("# DistributedGivenIterationSampler") 45 | 46 | # each process shuffle all list with same seed, and pick one piece according to rank 47 | np.random.seed(0) 48 | 49 | all_size = self.total_size * self.world_size 50 | indices = np.arange(len(self.dataset)) 51 | indices = indices[:all_size] 52 | num_repeat = (all_size - 1) // indices.shape[0] + 1 53 | indices = np.tile(indices, num_repeat) 54 | indices = indices[:all_size] 55 | 56 | np.random.shuffle(indices) 57 | beg = self.total_size * self.rank 58 | indices = indices[beg : beg + self.total_size] 59 | 60 | assert len(indices) == self.total_size 61 | 62 | return indices 63 | 64 | def __len__(self): 65 | # note here we do not take last iter into consideration, since __len__ 66 | # should only be used for displaying, the correct remaining size is 67 | # handled by dataloader 68 | # return self.total_size - (self.last_iter+1)*self.batch_size 69 | return self.total_size 70 | -------------------------------------------------------------------------------- /semi_seg/fst/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/semi_seg/fst/models/__init__.py -------------------------------------------------------------------------------- /semi_seg/fst/models/base.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | from torch.nn import functional as F 4 | 5 | 6 | def get_syncbn(): 7 | # return nn.BatchNorm2d 8 | return nn.SyncBatchNorm 9 | 10 | 11 | class ASPP(nn.Module): 12 | """ 13 | Reference: 14 | Chen, Liang-Chieh, et al. *"Rethinking Atrous Convolution for Semantic Image Segmentation."* 15 | """ 16 | 17 | def __init__( 18 | self, in_planes, inner_planes=256, sync_bn=False, dilations=(12, 24, 36) 19 | ): 20 | super(ASPP, self).__init__() 21 | 22 | norm_layer = get_syncbn() if sync_bn else nn.BatchNorm2d 23 | self.conv1 = nn.Sequential( 24 | nn.AdaptiveAvgPool2d((1, 1)), 25 | nn.Conv2d( 26 | in_planes, 27 | inner_planes, 28 | kernel_size=1, 29 | padding=0, 30 | dilation=1, 31 | bias=False, 32 | ), 33 | norm_layer(inner_planes), 34 | nn.ReLU(inplace=True), 35 | ) 36 | self.conv2 = nn.Sequential( 37 | nn.Conv2d( 38 | in_planes, 39 | inner_planes, 40 | kernel_size=1, 41 | padding=0, 42 | dilation=1, 43 | bias=False, 44 | ), 45 | norm_layer(inner_planes), 46 | nn.ReLU(inplace=True), 47 | ) 48 | self.conv3 = nn.Sequential( 49 | nn.Conv2d( 50 | in_planes, 51 | inner_planes, 52 | kernel_size=3, 53 | padding=dilations[0], 54 | dilation=dilations[0], 55 | bias=False, 56 | ), 57 | norm_layer(inner_planes), 58 | nn.ReLU(inplace=True), 59 | ) 60 | self.conv4 = nn.Sequential( 61 | nn.Conv2d( 62 | in_planes, 63 | inner_planes, 64 | kernel_size=3, 65 | padding=dilations[1], 66 | dilation=dilations[1], 67 | bias=False, 68 | ), 69 | norm_layer(inner_planes), 70 | nn.ReLU(inplace=True), 71 | ) 72 | self.conv5 = nn.Sequential( 73 | nn.Conv2d( 74 | in_planes, 75 | inner_planes, 76 | kernel_size=3, 77 | padding=dilations[2], 78 | dilation=dilations[2], 79 | bias=False, 80 | ), 81 | norm_layer(inner_planes), 82 | nn.ReLU(inplace=True), 83 | ) 84 | 85 | self.out_planes = (len(dilations) + 2) * inner_planes 86 | 87 | def get_outplanes(self): 88 | return self.out_planes 89 | 90 | def forward(self, x): 91 | _, _, h, w = x.size() 92 | feat1 = F.interpolate( 93 | self.conv1(x), size=(h, w), mode="bilinear", align_corners=True 94 | ) 95 | feat2 = self.conv2(x) 96 | feat3 = self.conv3(x) 97 | feat4 = self.conv4(x) 98 | feat5 = self.conv5(x) 99 | aspp_out = torch.cat((feat1, feat2, feat3, feat4, feat5), 1) 100 | return aspp_out 101 | -------------------------------------------------------------------------------- /semi_seg/fst/models/model_helper.py: -------------------------------------------------------------------------------- 1 | import importlib 2 | 3 | import torch.nn as nn 4 | from torch.nn import functional as F 5 | 6 | from .decoder import Aux_Module 7 | 8 | 9 | class ModelBuilder(nn.Module): 10 | def __init__(self, net_cfg): 11 | super(ModelBuilder, self).__init__() 12 | self._sync_bn = net_cfg["sync_bn"] 13 | self._num_classes = net_cfg["num_classes"] 14 | 15 | self.encoder = self._build_encoder(net_cfg["encoder"]) 16 | self.decoder = self._build_decoder(net_cfg["decoder"]) 17 | 18 | self._use_auxloss = True if net_cfg.get("aux_loss", False) else False 19 | self.fpn = True if net_cfg["encoder"]["kwargs"].get("fpn", False) else False 20 | if self._use_auxloss: 21 | cfg_aux = net_cfg["aux_loss"] 22 | self.loss_weight = cfg_aux["loss_weight"] 23 | self.auxor = Aux_Module( 24 | cfg_aux["aux_plane"], self._num_classes, self._sync_bn 25 | ) 26 | 27 | def _build_encoder(self, enc_cfg): 28 | enc_cfg["kwargs"].update({"sync_bn": self._sync_bn}) 29 | encoder = self._build_module(enc_cfg["type"], enc_cfg["kwargs"]) 30 | return encoder 31 | 32 | def _build_decoder(self, dec_cfg): 33 | dec_cfg["kwargs"].update( 34 | { 35 | "in_planes": self.encoder.get_outplanes(), 36 | "sync_bn": self._sync_bn, 37 | "num_classes": self._num_classes, 38 | } 39 | ) 40 | decoder = self._build_module(dec_cfg["type"], dec_cfg["kwargs"]) 41 | return decoder 42 | 43 | def _build_module(self, mtype, kwargs): 44 | module_name, class_name = mtype.rsplit(".", 1) 45 | module = importlib.import_module(module_name) 46 | cls = getattr(module, class_name) 47 | return cls(**kwargs) 48 | 49 | def forward(self, x): 50 | if self._use_auxloss: 51 | if self.fpn: 52 | # feat1 used as dsn loss as default, f1 is layer2's output as default 53 | f1, f2, feat1, feat2 = self.encoder(x) 54 | outs = self.decoder([f1, f2, feat1, feat2]) 55 | else: 56 | feat1, feat2 = self.encoder(x) 57 | outs = self.decoder(feat2) 58 | 59 | pred_aux = self.auxor(feat1) 60 | 61 | outs.update({"aux": pred_aux}) 62 | return outs 63 | else: 64 | feat = self.encoder(x) 65 | outs = self.decoder(feat) 66 | return outs 67 | -------------------------------------------------------------------------------- /semi_seg/fst/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/semi_seg/fst/utils/__init__.py -------------------------------------------------------------------------------- /semi_seg/fst/utils/dist_helper.py: -------------------------------------------------------------------------------- 1 | import copy 2 | import math 3 | import os 4 | import random 5 | import subprocess 6 | 7 | import numpy as np 8 | import torch 9 | import torch.distributed as dist 10 | from torch.utils.data.sampler import Sampler 11 | 12 | 13 | def setup_distributed(backend="nccl", port=None): 14 | """AdaHessian Optimizer 15 | Lifted from https://github.com/BIGBALLON/distribuuuu/blob/master/distribuuuu/utils.py 16 | Originally licensed MIT, Copyright (c) 2020 Wei Li 17 | """ 18 | num_gpus = torch.cuda.device_count() 19 | 20 | if "SLURM_JOB_ID" in os.environ: 21 | rank = int(os.environ["SLURM_PROCID"]) 22 | world_size = int(os.environ["SLURM_NTASKS"]) 23 | node_list = os.environ["SLURM_NODELIST"] 24 | addr = subprocess.getoutput(f"scontrol show hostname {node_list} | head -n1") 25 | # specify master port 26 | if port is not None: 27 | os.environ["MASTER_PORT"] = str(port) 28 | elif "MASTER_PORT" not in os.environ: 29 | os.environ["MASTER_PORT"] = "10685" 30 | if "MASTER_ADDR" not in os.environ: 31 | os.environ["MASTER_ADDR"] = addr 32 | os.environ["WORLD_SIZE"] = str(world_size) 33 | os.environ["LOCAL_RANK"] = str(rank % num_gpus) 34 | os.environ["RANK"] = str(rank) 35 | else: 36 | rank = int(os.environ["RANK"]) 37 | world_size = int(os.environ["WORLD_SIZE"]) 38 | 39 | torch.cuda.set_device(rank % num_gpus) 40 | 41 | dist.init_process_group( 42 | backend=backend, 43 | world_size=world_size, 44 | rank=rank, 45 | ) 46 | return rank, world_size 47 | 48 | 49 | def gather_together(data): 50 | world_size = dist.get_world_size() 51 | gather_data = [torch.zeros_like(data).cuda() for _ in range(world_size)] 52 | dist.all_gather(gather_data, data) 53 | return gather_data 54 | 55 | 56 | class DistributedGivenIterationSampler(Sampler): 57 | def __init__( 58 | self, dataset, total_iter, batch_size, world_size=None, rank=None, last_iter=-1 59 | ): 60 | if world_size is None: 61 | world_size = dist.get_world_size() 62 | if rank is None: 63 | rank = dist.get_rank() 64 | assert rank < world_size 65 | self.dataset = dataset 66 | self.total_iter = total_iter 67 | self.batch_size = batch_size 68 | self.world_size = world_size 69 | self.rank = rank 70 | self.last_iter = last_iter 71 | 72 | self.total_size = self.total_iter * self.batch_size 73 | 74 | self.indices = self.gen_new_list() 75 | self.call = 0 76 | 77 | def __iter__(self): 78 | if self.call == 0: 79 | self.call = 1 80 | return iter(self.indices[(self.last_iter + 1) * self.batch_size :]) 81 | else: 82 | raise RuntimeError( 83 | "this sampler is not designed to be called more than once!!" 84 | ) 85 | 86 | def gen_new_list(self): 87 | # each process shuffle all list with same seed, and pick one piece according to rank 88 | np.random.seed(0) 89 | 90 | all_size = self.total_size * self.world_size 91 | indices = np.arange(len(self.dataset)) 92 | indices = indices[:all_size] 93 | num_repeat = (all_size - 1) // indices.shape[0] + 1 94 | indices = np.tile(indices, num_repeat) 95 | indices = indices[:all_size] 96 | 97 | np.random.shuffle(indices) 98 | beg = self.total_size * self.rank 99 | indices = indices[beg : beg + self.total_size] 100 | 101 | assert len(indices) == self.total_size 102 | 103 | return indices 104 | 105 | def __len__(self): 106 | # note here we do not take last iter into consideration, since __len__ 107 | # should only be used for displaying, the correct remaining size is 108 | # handled by dataloader 109 | # return self.total_size - (self.last_iter+1)*self.batch_size 110 | return self.total_size 111 | -------------------------------------------------------------------------------- /semi_seg/fst/utils/lr_helper.py: -------------------------------------------------------------------------------- 1 | """Learning Rate Schedulers""" 2 | from __future__ import division 3 | 4 | import copy 5 | import logging 6 | import warnings 7 | from math import cos, pi 8 | 9 | import torch.optim as optim 10 | 11 | 12 | def get_optimizer(parms, cfg_optim): 13 | """ 14 | Get the optimizer 15 | """ 16 | optim_type = cfg_optim["type"] 17 | optim_kwargs = cfg_optim["kwargs"] 18 | if optim_type == "SGD": 19 | optimizer = optim.SGD(parms, **optim_kwargs) 20 | elif optim_type == "adam": 21 | optimizer = optim.Adam(parms, **optim_kwargs) 22 | else: 23 | optimizer = None 24 | 25 | assert optimizer is not None, "optimizer type is not supported by LightSeg" 26 | 27 | return optimizer 28 | 29 | 30 | def get_scheduler(cfg_trainer, len_data, optimizer, start_epoch=0, use_iteration=False): 31 | epochs = ( 32 | cfg_trainer["epochs"] if not use_iteration else 1 33 | ) # if use_iteration = True, only one epoch be use 34 | lr_mode = cfg_trainer["lr_scheduler"]["mode"] 35 | lr_args = cfg_trainer["lr_scheduler"]["kwargs"] 36 | lr_scheduler = LRScheduler( 37 | lr_mode, lr_args, len_data, optimizer, epochs, start_epoch 38 | ) 39 | return lr_scheduler 40 | 41 | 42 | class LRScheduler(object): 43 | def __init__(self, mode, lr_args, data_size, optimizer, num_epochs, start_epochs): 44 | super(LRScheduler, self).__init__() 45 | logger = logging.getLogger("global") 46 | 47 | assert mode in ["multistep", "poly", "cosine"] 48 | self.mode = mode 49 | self.optimizer = optimizer 50 | self.data_size = data_size 51 | 52 | self.cur_iter = start_epochs * data_size 53 | self.max_iter = num_epochs * data_size 54 | 55 | # set learning rate 56 | self.base_lr = [ 57 | param_group["lr"] for param_group in self.optimizer.param_groups 58 | ] 59 | self.cur_lr = [lr for lr in self.base_lr] 60 | 61 | # poly kwargs 62 | # TODO 63 | if mode == "poly": 64 | self.power = lr_args["power"] if lr_args.get("power", False) else 0.9 65 | logger.info("The kwargs for lr scheduler: {}".format(self.power)) 66 | if mode == "milestones": 67 | default_mist = list(range(0, num_epochs, num_epochs // 3))[1:] 68 | self.milestones = ( 69 | lr_args["milestones"] 70 | if lr_args.get("milestones", False) 71 | else default_mist 72 | ) 73 | logger.info("The kwargs for lr scheduler: {}".format(self.milestones)) 74 | if mode == "cosine": 75 | self.targetlr = lr_args["targetlr"] 76 | logger.info("The kwargs for lr scheduler: {}".format(self.targetlr)) 77 | 78 | def step(self): 79 | self._step() 80 | self.update_lr() 81 | self.cur_iter += 1 82 | 83 | def _step(self): 84 | if self.mode == "step": 85 | epoch = self.cur_iter // self.data_size 86 | power = sum([1 for s in self.milestones if s <= epoch]) 87 | for i, lr in enumerate(self.base_lr): 88 | adj_lr = lr * pow(0.1, power) 89 | self.cur_lr[i] = adj_lr 90 | elif self.mode == "poly": 91 | for i, lr in enumerate(self.base_lr): 92 | adj_lr = lr * ( 93 | (1 - float(self.cur_iter) / self.max_iter) ** (self.power) 94 | ) 95 | self.cur_lr[i] = adj_lr 96 | elif self.mode == "cosine": 97 | for i, lr in enumerate(self.base_lr): 98 | adj_lr = ( 99 | self.targetlr 100 | + (lr - self.targetlr) 101 | * (1 + cos(pi * self.cur_iter / self.max_iter)) 102 | / 2 103 | ) 104 | self.cur_lr[i] = adj_lr 105 | else: 106 | raise NotImplementedError 107 | 108 | def get_lr(self): 109 | return self.cur_lr 110 | 111 | def update_lr(self): 112 | for param_group, lr in zip(self.optimizer.param_groups, self.cur_lr): 113 | param_group["lr"] = lr 114 | -------------------------------------------------------------------------------- /semi_seg/requirements.txt: -------------------------------------------------------------------------------- 1 | pyyaml>=5.4.0 2 | easydict 3 | tensorboardX 4 | opencv-python 5 | scipy 6 | sklearn 7 | scikit-image 8 | einops -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TEST_ROOT=$1 4 | CONFIG_FILE="${TEST_ROOT}/*${TEST_ROOT: -1}.json" 5 | CHECKPOINT_FILE="${TEST_ROOT}/latest.pth" 6 | SHOW_DIR="${TEST_ROOT}/preds/" 7 | echo 'Config File:' $CONFIG_FILE 8 | echo 'Checkpoint File:' $CHECKPOINT_FILE 9 | echo 'Predictions Output Directory:' $SHOW_DIR 10 | python -m tools.test ${CONFIG_FILE} ${CHECKPOINT_FILE} --eval mIoU --show-dir ${SHOW_DIR} --opacity 1 11 | -------------------------------------------------------------------------------- /tools/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usr922/FST/5b44c0154dd7e6e10e7511360d16ca2f942b3b51/tools/__init__.py -------------------------------------------------------------------------------- /tools/beit_convert.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) OpenMMLab. All rights reserved. 2 | import argparse 3 | import os.path as osp 4 | from collections import OrderedDict 5 | 6 | import mmcv 7 | import torch 8 | from mmcv.runner import CheckpointLoader 9 | 10 | 11 | def convert_beit(ckpt): 12 | new_ckpt = OrderedDict() 13 | 14 | for k, v in ckpt.items(): 15 | if k.startswith('patch_embed'): 16 | new_key = k.replace('patch_embed.proj', 'patch_embed.projection') 17 | new_ckpt[new_key] = v 18 | if k.startswith('blocks'): 19 | new_key = k.replace('blocks', 'layers') 20 | if 'norm' in new_key: 21 | new_key = new_key.replace('norm', 'ln') 22 | elif 'mlp.fc1' in new_key: 23 | new_key = new_key.replace('mlp.fc1', 'ffn.layers.0.0') 24 | elif 'mlp.fc2' in new_key: 25 | new_key = new_key.replace('mlp.fc2', 'ffn.layers.1') 26 | new_ckpt[new_key] = v 27 | else: 28 | new_key = k 29 | new_ckpt[new_key] = v 30 | 31 | return new_ckpt 32 | 33 | 34 | def main(): 35 | parser = argparse.ArgumentParser( 36 | description='Convert keys in official pretrained beit models to' 37 | 'MMSegmentation style.') 38 | parser.add_argument('src', help='src model path or url') 39 | # The dst path must be a full path of the new checkpoint. 40 | parser.add_argument('dst', help='save path') 41 | args = parser.parse_args() 42 | 43 | checkpoint = CheckpointLoader.load_checkpoint(args.src, map_location='cpu') 44 | if 'state_dict' in checkpoint: 45 | state_dict = checkpoint['state_dict'] 46 | elif 'model' in checkpoint: 47 | state_dict = checkpoint['model'] 48 | else: 49 | state_dict = checkpoint 50 | weight = convert_beit(state_dict) 51 | mmcv.mkdir_or_exist(osp.dirname(args.dst)) 52 | torch.save(weight, args.dst) 53 | 54 | 55 | if __name__ == '__main__': 56 | main() -------------------------------------------------------------------------------- /tools/convert_datasets/cityscapes.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | # Modifications: Add class stats computation 3 | 4 | import argparse 5 | import json 6 | import os.path as osp 7 | 8 | import mmcv 9 | import numpy as np 10 | from cityscapesscripts.preparation.json2labelImg import json2labelImg 11 | from PIL import Image 12 | 13 | 14 | def convert_json_to_label(json_file): 15 | label_file = json_file.replace('_polygons.json', '_labelTrainIds.png') 16 | json2labelImg(json_file, label_file, 'trainIds') 17 | 18 | if 'train/' in json_file: 19 | pil_label = Image.open(label_file) 20 | label = np.asarray(pil_label) 21 | sample_class_stats = {} 22 | for c in range(19): 23 | n = int(np.sum(label == c)) 24 | if n > 0: 25 | sample_class_stats[int(c)] = n 26 | sample_class_stats['file'] = label_file 27 | return sample_class_stats 28 | else: 29 | return None 30 | 31 | 32 | def parse_args(): 33 | parser = argparse.ArgumentParser( 34 | description='Convert Cityscapes annotations to TrainIds') 35 | parser.add_argument('cityscapes_path', help='cityscapes data path') 36 | parser.add_argument('--gt-dir', default='gtFine', type=str) 37 | parser.add_argument('-o', '--out-dir', help='output path') 38 | parser.add_argument( 39 | '--nproc', default=1, type=int, help='number of process') 40 | args = parser.parse_args() 41 | return args 42 | 43 | 44 | def save_class_stats(out_dir, sample_class_stats): 45 | sample_class_stats = [e for e in sample_class_stats if e is not None] 46 | with open(osp.join(out_dir, 'sample_class_stats.json'), 'w') as of: 47 | json.dump(sample_class_stats, of, indent=2) 48 | 49 | sample_class_stats_dict = {} 50 | for stats in sample_class_stats: 51 | f = stats.pop('file') 52 | sample_class_stats_dict[f] = stats 53 | with open(osp.join(out_dir, 'sample_class_stats_dict.json'), 'w') as of: 54 | json.dump(sample_class_stats_dict, of, indent=2) 55 | 56 | samples_with_class = {} 57 | for file, stats in sample_class_stats_dict.items(): 58 | for c, n in stats.items(): 59 | if c not in samples_with_class: 60 | samples_with_class[c] = [(file, n)] 61 | else: 62 | samples_with_class[c].append((file, n)) 63 | with open(osp.join(out_dir, 'samples_with_class.json'), 'w') as of: 64 | json.dump(samples_with_class, of, indent=2) 65 | 66 | 67 | def main(): 68 | args = parse_args() 69 | cityscapes_path = args.cityscapes_path 70 | out_dir = args.out_dir if args.out_dir else cityscapes_path 71 | mmcv.mkdir_or_exist(out_dir) 72 | 73 | gt_dir = osp.join(cityscapes_path, args.gt_dir) 74 | 75 | poly_files = [] 76 | for poly in mmcv.scandir(gt_dir, '_polygons.json', recursive=True): 77 | poly_file = osp.join(gt_dir, poly) 78 | poly_files.append(poly_file) 79 | 80 | only_postprocessing = False 81 | if not only_postprocessing: 82 | if args.nproc > 1: 83 | sample_class_stats = mmcv.track_parallel_progress( 84 | convert_json_to_label, poly_files, args.nproc) 85 | else: 86 | sample_class_stats = mmcv.track_progress(convert_json_to_label, 87 | poly_files) 88 | else: 89 | with open(osp.join(out_dir, 'sample_class_stats.json'), 'r') as of: 90 | sample_class_stats = json.load(of) 91 | 92 | save_class_stats(out_dir, sample_class_stats) 93 | 94 | split_names = ['train', 'val', 'test'] 95 | 96 | for split in split_names: 97 | filenames = [] 98 | for poly in mmcv.scandir( 99 | osp.join(gt_dir, split), '_polygons.json', recursive=True): 100 | filenames.append(poly.replace('_gtFine_polygons.json', '')) 101 | with open(osp.join(out_dir, f'{split}.txt'), 'w') as f: 102 | f.writelines(f + '\n' for f in filenames) 103 | 104 | 105 | if __name__ == '__main__': 106 | main() 107 | -------------------------------------------------------------------------------- /tools/convert_datasets/gta.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import json 3 | import os.path as osp 4 | 5 | import mmcv 6 | import numpy as np 7 | from PIL import Image 8 | 9 | 10 | def convert_to_train_id(file): 11 | # re-assign labels to match the format of Cityscapes 12 | pil_label = Image.open(file) 13 | label = np.asarray(pil_label) 14 | id_to_trainid = { 15 | 7: 0, 16 | 8: 1, 17 | 11: 2, 18 | 12: 3, 19 | 13: 4, 20 | 17: 5, 21 | 19: 6, 22 | 20: 7, 23 | 21: 8, 24 | 22: 9, 25 | 23: 10, 26 | 24: 11, 27 | 25: 12, 28 | 26: 13, 29 | 27: 14, 30 | 28: 15, 31 | 31: 16, 32 | 32: 17, 33 | 33: 18 34 | } 35 | label_copy = 255 * np.ones(label.shape, dtype=np.uint8) 36 | sample_class_stats = {} 37 | for k, v in id_to_trainid.items(): 38 | k_mask = label == k 39 | label_copy[k_mask] = v 40 | n = int(np.sum(k_mask)) 41 | if n > 0: 42 | sample_class_stats[v] = n 43 | new_file = file.replace('.png', '_labelTrainIds.png') 44 | assert file != new_file 45 | sample_class_stats['file'] = new_file 46 | Image.fromarray(label_copy, mode='L').save(new_file) 47 | return sample_class_stats 48 | 49 | 50 | def parse_args(): 51 | parser = argparse.ArgumentParser( 52 | description='Convert GTA annotations to TrainIds') 53 | parser.add_argument('gta_path', help='gta data path') 54 | parser.add_argument('--gt-dir', default='labels', type=str) 55 | parser.add_argument('-o', '--out-dir', help='output path') 56 | parser.add_argument( 57 | '--nproc', default=4, type=int, help='number of process') 58 | args = parser.parse_args() 59 | return args 60 | 61 | 62 | def save_class_stats(out_dir, sample_class_stats): 63 | with open(osp.join(out_dir, 'sample_class_stats.json'), 'w') as of: 64 | json.dump(sample_class_stats, of, indent=2) 65 | 66 | sample_class_stats_dict = {} 67 | for stats in sample_class_stats: 68 | f = stats.pop('file') 69 | sample_class_stats_dict[f] = stats 70 | with open(osp.join(out_dir, 'sample_class_stats_dict.json'), 'w') as of: 71 | json.dump(sample_class_stats_dict, of, indent=2) 72 | 73 | samples_with_class = {} 74 | for file, stats in sample_class_stats_dict.items(): 75 | for c, n in stats.items(): 76 | if c not in samples_with_class: 77 | samples_with_class[c] = [(file, n)] 78 | else: 79 | samples_with_class[c].append((file, n)) 80 | with open(osp.join(out_dir, 'samples_with_class.json'), 'w') as of: 81 | json.dump(samples_with_class, of, indent=2) 82 | 83 | 84 | def main(): 85 | args = parse_args() 86 | gta_path = args.gta_path 87 | out_dir = args.out_dir if args.out_dir else gta_path 88 | mmcv.mkdir_or_exist(out_dir) 89 | 90 | gt_dir = osp.join(gta_path, args.gt_dir) 91 | 92 | poly_files = [] 93 | for poly in mmcv.scandir( 94 | gt_dir, suffix=tuple(f'{i}.png' for i in range(10)), 95 | recursive=True): 96 | poly_file = osp.join(gt_dir, poly) 97 | poly_files.append(poly_file) 98 | poly_files = sorted(poly_files) 99 | 100 | only_postprocessing = False 101 | if not only_postprocessing: 102 | if args.nproc > 1: 103 | sample_class_stats = mmcv.track_parallel_progress( 104 | convert_to_train_id, poly_files, args.nproc) 105 | else: 106 | sample_class_stats = mmcv.track_progress(convert_to_train_id, 107 | poly_files) 108 | else: 109 | with open(osp.join(out_dir, 'sample_class_stats.json'), 'r') as of: 110 | sample_class_stats = json.load(of) 111 | 112 | save_class_stats(out_dir, sample_class_stats) 113 | 114 | 115 | if __name__ == '__main__': 116 | main() 117 | -------------------------------------------------------------------------------- /tools/convert_datasets/synthia.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import json 3 | import os.path as osp 4 | 5 | import cv2 6 | import mmcv 7 | import numpy as np 8 | from PIL import Image 9 | 10 | 11 | def convert_to_train_id(file): 12 | # re-assign labels to match the format of Cityscapes 13 | # PIL does not work with the image format, but cv2 does 14 | label = cv2.imread(file, cv2.IMREAD_UNCHANGED)[:, :, -1] 15 | # mapping based on README.txt from SYNTHIA_RAND_CITYSCAPES 16 | id_to_trainid = { 17 | 3: 0, 18 | 4: 1, 19 | 2: 2, 20 | 21: 3, 21 | 5: 4, 22 | 7: 5, 23 | 15: 6, 24 | 9: 7, 25 | 6: 8, 26 | 16: 9, # not present in synthia 27 | 1: 10, 28 | 10: 11, 29 | 17: 12, 30 | 8: 13, 31 | 18: 14, # not present in synthia 32 | 19: 15, 33 | 20: 16, # not present in synthia 34 | 12: 17, 35 | 11: 18 36 | } 37 | label_copy = 255 * np.ones(label.shape, dtype=np.uint8) 38 | sample_class_stats = {} 39 | for k, v in id_to_trainid.items(): 40 | k_mask = label == k 41 | label_copy[k_mask] = v 42 | n = int(np.sum(k_mask)) 43 | if n > 0: 44 | sample_class_stats[v] = n 45 | new_file = file.replace('.png', '_labelTrainIds.png') 46 | assert file != new_file 47 | sample_class_stats['file'] = new_file 48 | Image.fromarray(label_copy, mode='L').save(new_file) 49 | return sample_class_stats 50 | 51 | 52 | def parse_args(): 53 | parser = argparse.ArgumentParser( 54 | description='Convert SYNTHIA annotations to TrainIds') 55 | parser.add_argument('synthia_path', help='gta data path') 56 | parser.add_argument('--gt-dir', default='GT/LABELS', type=str) 57 | parser.add_argument('-o', '--out-dir', help='output path') 58 | parser.add_argument( 59 | '--nproc', default=4, type=int, help='number of process') 60 | args = parser.parse_args() 61 | return args 62 | 63 | 64 | def save_class_stats(out_dir, sample_class_stats): 65 | with open(osp.join(out_dir, 'sample_class_stats.json'), 'w') as of: 66 | json.dump(sample_class_stats, of, indent=2) 67 | 68 | sample_class_stats_dict = {} 69 | for stats in sample_class_stats: 70 | f = stats.pop('file') 71 | sample_class_stats_dict[f] = stats 72 | with open(osp.join(out_dir, 'sample_class_stats_dict.json'), 'w') as of: 73 | json.dump(sample_class_stats_dict, of, indent=2) 74 | 75 | samples_with_class = {} 76 | for file, stats in sample_class_stats_dict.items(): 77 | for c, n in stats.items(): 78 | if c not in samples_with_class: 79 | samples_with_class[c] = [(file, n)] 80 | else: 81 | samples_with_class[c].append((file, n)) 82 | with open(osp.join(out_dir, 'samples_with_class.json'), 'w') as of: 83 | json.dump(samples_with_class, of, indent=2) 84 | 85 | 86 | def main(): 87 | args = parse_args() 88 | synthia_path = args.synthia_path 89 | out_dir = args.out_dir if args.out_dir else synthia_path 90 | mmcv.mkdir_or_exist(out_dir) 91 | 92 | gt_dir = osp.join(synthia_path, args.gt_dir) 93 | 94 | poly_files = [] 95 | for poly in mmcv.scandir( 96 | gt_dir, suffix=tuple(f'{i}.png' for i in range(10)), 97 | recursive=True): 98 | poly_file = osp.join(gt_dir, poly) 99 | poly_files.append(poly_file) 100 | poly_files = sorted(poly_files) 101 | 102 | only_postprocessing = False 103 | if not only_postprocessing: 104 | if args.nproc > 1: 105 | sample_class_stats = mmcv.track_parallel_progress( 106 | convert_to_train_id, poly_files, args.nproc) 107 | else: 108 | sample_class_stats = mmcv.track_progress(convert_to_train_id, 109 | poly_files) 110 | else: 111 | with open(osp.join(out_dir, 'sample_class_stats.json'), 'r') as of: 112 | sample_class_stats = json.load(of) 113 | 114 | save_class_stats(out_dir, sample_class_stats) 115 | 116 | 117 | if __name__ == '__main__': 118 | main() 119 | -------------------------------------------------------------------------------- /tools/download_checkpoints.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Instructions for Manual Download: 4 | # 5 | # Please, download the [MiT weights](https://drive.google.com/drive/folders/1b7bwrInTW4VLEm27YawHOAMSMikga2Ia?usp=sharing) 6 | # pretrained on ImageNet-1K provided by the official 7 | # [SegFormer repository](https://github.com/NVlabs/SegFormer) and put them in a 8 | # folder `pretrained/` within this project. For most of the experiments, only 9 | # mit_b5.pth is necessary. 10 | # 11 | # Please, download the checkpoint of DAFormer on GTA->Cityscapes from 12 | # [here](https://drive.google.com/file/d/1pG3kDClZDGwp1vSTEXmTchkGHmnLQNdP/view?usp=sharing). 13 | # and extract it to `work_dirs/` 14 | 15 | # Automatic Downloads: 16 | set -e # exit when any command fails 17 | mkdir -p pretrained/ 18 | cd pretrained/ 19 | gdown --id 1d3wU8KNjPL4EqMCIEO_rO-O3-REpG82T # MiT-B3 weights 20 | gdown --id 1BUtU42moYrOFbsMCE-LTTkUE-mrWnfG2 # MiT-B4 weights 21 | gdown --id 1d7I50jVjtCddnhpf-lqj8-f13UyCzoW1 # MiT-B5 weights 22 | cd ../ 23 | 24 | mkdir -p work_dirs/ 25 | cd work_dirs/ 26 | gdown --id 1pG3kDClZDGwp1vSTEXmTchkGHmnLQNdP # DAFormer on GTA->Cityscapes 27 | tar -xzf 211108_1622_gta2cs_daformer_s0_7f24c.tar.gz 28 | rm 211108_1622_gta2cs_daformer_s0_7f24c.tar.gz 29 | cd ../ 30 | -------------------------------------------------------------------------------- /tools/get_param_count.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | 3 | import argparse 4 | import json 5 | import logging 6 | from copy import deepcopy 7 | 8 | from experiments import generate_experiment_cfgs 9 | from mmcv import Config, get_logger 10 | from prettytable import PrettyTable 11 | 12 | from mmseg.models import build_segmentor 13 | 14 | 15 | def human_format(num): 16 | magnitude = 0 17 | while abs(num) >= 1000: 18 | magnitude += 1 19 | num /= 1000.0 20 | # add more suffixes if you need them 21 | return '%.2f%s' % (num, ['', 'K', 'M', 'G', 'T', 'P'][magnitude]) 22 | 23 | 24 | def count_parameters(model): 25 | table = PrettyTable(['Modules', 'Parameters']) 26 | total_params = 0 27 | for name, parameter in model.named_parameters(): 28 | if not parameter.requires_grad: 29 | continue 30 | param = parameter.numel() 31 | table.add_row([name, human_format(param)]) 32 | total_params += param 33 | # print(table) 34 | print(f'Total Trainable Params: {human_format(total_params)}') 35 | return total_params 36 | 37 | 38 | # Run: python -m tools.param_count 39 | if __name__ == '__main__': 40 | parser = argparse.ArgumentParser() 41 | parser.add_argument( 42 | '--exp', 43 | nargs='?', 44 | type=int, 45 | default=100, 46 | help='Experiment id as defined in experiment.py', 47 | ) 48 | args = parser.parse_args() 49 | get_logger('mmseg', log_level=logging.ERROR) 50 | cfgs = generate_experiment_cfgs(args.exp) 51 | for cfg in cfgs: 52 | with open('configs/tmp_param.json', 'w') as f: 53 | json.dump(cfg, f) 54 | cfg = Config.fromfile('configs/tmp_param.json') 55 | 56 | model = build_segmentor(deepcopy(cfg['model'])) 57 | # model.init_weights() 58 | # count_parameters(model) 59 | print(f'Encoder {cfg["name_encoder"]}:') 60 | count_parameters(model.backbone) 61 | print(f'Decoder {cfg["name_decoder"]}:') 62 | count_parameters(model.decode_head) 63 | -------------------------------------------------------------------------------- /tools/print_config.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | 3 | import argparse 4 | 5 | from mmcv import Config, DictAction 6 | 7 | from mmseg.apis import init_segmentor 8 | 9 | 10 | def parse_args(): 11 | parser = argparse.ArgumentParser(description='Print the whole config') 12 | parser.add_argument('config', help='config file path') 13 | parser.add_argument( 14 | '--graph', action='store_true', help='print the models graph') 15 | parser.add_argument( 16 | '--options', nargs='+', action=DictAction, help='arguments in dict') 17 | args = parser.parse_args() 18 | 19 | return args 20 | 21 | 22 | def main(): 23 | args = parse_args() 24 | 25 | cfg = Config.fromfile(args.config) 26 | if args.options is not None: 27 | cfg.merge_from_dict(args.options) 28 | print(f'Config:\n{cfg.pretty_text}') 29 | # dump config 30 | cfg.dump('example.py') 31 | # dump models graph 32 | if args.graph: 33 | model = init_segmentor(args.config, device='cpu') 34 | print(f'Model graph:\n{str(model)}') 35 | with open('example-graph.txt', 'w') as f: 36 | f.writelines(str(model)) 37 | 38 | 39 | if __name__ == '__main__': 40 | main() 41 | -------------------------------------------------------------------------------- /tools/publish_model.py: -------------------------------------------------------------------------------- 1 | # Obtained from: https://github.com/open-mmlab/mmsegmentation/tree/v0.16.0 2 | # Modifications: Remove auxiliary models 3 | 4 | import argparse 5 | 6 | import torch 7 | 8 | # import subprocess 9 | 10 | 11 | def parse_args(): 12 | parser = argparse.ArgumentParser( 13 | description='Process a checkpoint to be published') 14 | parser.add_argument('in_file', help='input checkpoint filename') 15 | parser.add_argument('out_file', help='output checkpoint filename') 16 | args = parser.parse_args() 17 | return args 18 | 19 | 20 | def process_checkpoint(in_file, out_file): 21 | checkpoint = torch.load(in_file, map_location='cpu') 22 | # remove optimizer for smaller file size 23 | if 'optimizer' in checkpoint: 24 | del checkpoint['optimizer'] 25 | # remove auxiliary models 26 | for k in list(checkpoint['state_dict'].keys()): 27 | if 'imnet_model' in k or 'ema_model' in k: 28 | del checkpoint['state_dict'][k] 29 | # if it is necessary to remove some sensitive data in checkpoint['meta'], 30 | # add the code here. 31 | if 'meta' in checkpoint: 32 | del checkpoint['meta'] 33 | # inspect checkpoint 34 | print('Checkpoint keys:', checkpoint.keys()) 35 | print('Checkpoint state_dict keys:', checkpoint['state_dict'].keys()) 36 | # save checkpoint 37 | torch.save(checkpoint, out_file) 38 | # sha = subprocess.check_output(['sha256sum', out_file]).decode() 39 | # final_file = out_file.rstrip('.pth') + '-{}.pth'.format(sha[:8]) 40 | # subprocess.Popen(['mv', out_file, final_file]) 41 | 42 | 43 | def main(): 44 | args = parse_args() 45 | process_checkpoint(args.in_file, args.out_file) 46 | 47 | 48 | if __name__ == '__main__': 49 | main() 50 | -------------------------------------------------------------------------------- /tools/swin_convert.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) OpenMMLab. All rights reserved. 2 | import argparse 3 | import os.path as osp 4 | from collections import OrderedDict 5 | 6 | import mmcv 7 | import torch 8 | from mmcv.runner import CheckpointLoader 9 | 10 | 11 | def convert_swin(ckpt): 12 | new_ckpt = OrderedDict() 13 | 14 | def correct_unfold_reduction_order(x): 15 | out_channel, in_channel = x.shape 16 | x = x.reshape(out_channel, 4, in_channel // 4) 17 | x = x[:, [0, 2, 1, 3], :].transpose(1, 18 | 2).reshape(out_channel, in_channel) 19 | return x 20 | 21 | def correct_unfold_norm_order(x): 22 | in_channel = x.shape[0] 23 | x = x.reshape(4, in_channel // 4) 24 | x = x[[0, 2, 1, 3], :].transpose(0, 1).reshape(in_channel) 25 | return x 26 | 27 | for k, v in ckpt.items(): 28 | if k.startswith('head'): 29 | continue 30 | elif k.startswith('layers'): 31 | new_v = v 32 | if 'attn.' in k: 33 | new_k = k.replace('attn.', 'attn.w_msa.') 34 | elif 'mlp.' in k: 35 | if 'mlp.fc1.' in k: 36 | new_k = k.replace('mlp.fc1.', 'ffn.layers.0.0.') 37 | elif 'mlp.fc2.' in k: 38 | new_k = k.replace('mlp.fc2.', 'ffn.layers.1.') 39 | else: 40 | new_k = k.replace('mlp.', 'ffn.') 41 | elif 'downsample' in k: 42 | new_k = k 43 | if 'reduction.' in k: 44 | new_v = correct_unfold_reduction_order(v) 45 | elif 'norm.' in k: 46 | new_v = correct_unfold_norm_order(v) 47 | else: 48 | new_k = k 49 | new_k = new_k.replace('layers', 'stages', 1) 50 | elif k.startswith('patch_embed'): 51 | new_v = v 52 | if 'proj' in k: 53 | new_k = k.replace('proj', 'projection') 54 | else: 55 | new_k = k 56 | else: 57 | new_v = v 58 | new_k = k 59 | 60 | new_ckpt[new_k] = new_v 61 | 62 | return new_ckpt 63 | 64 | 65 | def main(): 66 | parser = argparse.ArgumentParser( 67 | description='Convert keys in official pretrained swin models to' 68 | 'MMSegmentation style.') 69 | parser.add_argument('src', help='src model path or url') 70 | # The dst path must be a full path of the new checkpoint. 71 | parser.add_argument('dst', help='save path') 72 | args = parser.parse_args() 73 | 74 | checkpoint = CheckpointLoader.load_checkpoint(args.src, map_location='cpu') 75 | if 'state_dict' in checkpoint: 76 | state_dict = checkpoint['state_dict'] 77 | elif 'model' in checkpoint: 78 | state_dict = checkpoint['model'] 79 | else: 80 | state_dict = checkpoint 81 | weight = convert_swin(state_dict) 82 | mmcv.mkdir_or_exist(osp.dirname(args.dst)) 83 | torch.save(weight, args.dst) 84 | 85 | 86 | if __name__ == '__main__': 87 | main() -------------------------------------------------------------------------------- /train.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | g=$(($1<8?$1:8)) 3 | now=$(date +"%Y%m%d_%H%M%S") 4 | export PYTHONPATH=$ROOT:$PYTHONPATH 5 | 6 | # resnet-101 7 | python run_experiments.py --config configs/fst-d/gta2cs_uda_warm_fdthings_rcs_croppl_a999_nesterov_r101_s0_step3.py --------------------------------------------------------------------------------