├── Pytorch ├── mmseg │ ├── models │ │ ├── decode_heads │ │ │ ├── .~untitled.txt │ │ │ ├── __init__.py │ │ │ ├── cc_head.py │ │ │ ├── nl_head.py │ │ │ ├── gc_head.py │ │ │ ├── sep_fcn_head.py │ │ │ ├── cascade_decode_head.py │ │ │ ├── fpn_head.py │ │ │ ├── fcn_head.py │ │ │ ├── lraspp_head.py │ │ │ ├── psp_head.py │ │ │ ├── sep_aspp_head.py │ │ │ └── aspp_head.py │ │ ├── necks │ │ │ └── __init__.py │ │ ├── segmentors │ │ │ ├── __init__.py │ │ │ └── cascade_encoder_decoder.py │ │ ├── utils │ │ │ ├── __init__.py │ │ │ ├── make_divisible.py │ │ │ ├── se_layer.py │ │ │ └── res_layer.py │ │ ├── backbones │ │ │ └── __init__.py │ │ ├── __init__.py │ │ ├── losses │ │ │ ├── __init__.py │ │ │ ├── tree_triplet_loss.py │ │ │ ├── accuracy.py │ │ │ └── utils.py │ │ └── builder.py │ ├── core │ │ ├── utils │ │ │ ├── __init__.py │ │ │ └── misc.py │ │ ├── __init__.py │ │ ├── seg │ │ │ ├── sampler │ │ │ │ ├── __init__.py │ │ │ │ ├── base_pixel_sampler.py │ │ │ │ └── ohem_pixel_sampler.py │ │ │ ├── __init__.py │ │ │ └── builder.py │ │ └── evaluation │ │ │ └── __init__.py │ ├── ops │ │ ├── __init__.py │ │ ├── wrappers.py │ │ └── encoding.py │ ├── utils │ │ ├── __init__.py │ │ ├── collect_env.py │ │ └── logger.py │ ├── apis │ │ └── __init__.py │ ├── version.py │ ├── datasets │ │ ├── __init__.py │ │ ├── hrf.py │ │ ├── stare.py │ │ ├── drive.py │ │ ├── chase_db1.py │ │ ├── pipelines │ │ │ ├── __init__.py │ │ │ └── compose.py │ │ ├── voc.py │ │ ├── dataset_wrappers.py │ │ └── pascal_context.py │ └── __init__.py ├── mmcv_custom │ └── __init__.py ├── configs │ ├── fcn │ │ ├── fcn_r101-d8_512x512_80k_ade20k.py │ │ ├── fcn_r101-d8_512x512_160k_ade20k.py │ │ ├── fcn_r101-d8_512x512_20k_voc12aug.py │ │ ├── fcn_r101-d8_512x512_40k_voc12aug.py │ │ ├── fcn_r101-d8_512x1024_40k_cityscapes.py │ │ ├── fcn_r101-d8_512x1024_80k_cityscapes.py │ │ ├── fcn_r101-d8_769x769_40k_cityscapes.py │ │ ├── fcn_r101-d8_769x769_80k_cityscapes.py │ │ ├── fcn_r50b-d8_512x1024_80k_cityscapes.py │ │ ├── fcn_r50b-d8_769x769_80k_cityscapes.py │ │ ├── fcn_r101-d8_480x480_40k_pascal_context.py │ │ ├── fcn_r101-d8_480x480_80k_pascal_context.py │ │ ├── fcn_r101b-d8_512x1024_80k_cityscapes.py │ │ ├── fcn_r101b-d8_769x769_80k_cityscapes.py │ │ ├── fcn_r50-d8_512x1024_40k_cityscapes.py │ │ ├── fcn_r50-d8_512x1024_80k_cityscapes.py │ │ ├── fcn_r50-d8_512x512_160k_ade20k.py │ │ ├── fcn_r50-d8_512x512_80k_ade20k.py │ │ ├── fcn_r50-d8_512x512_20k_voc12aug.py │ │ ├── fcn_r50-d8_512x512_40k_voc12aug.py │ │ ├── fcn_r18-d8_512x1024_80k_cityscapes.py │ │ ├── fcn_r18-d8_769x769_80k_cityscapes.py │ │ ├── fcn_r18b-d8_769x769_80k_cityscapes.py │ │ ├── fcn_r18b-d8_512x1024_80k_cityscapes.py │ │ ├── fcn_r50-d8_769x769_40k_cityscapes.py │ │ ├── fcn_r50-d8_769x769_80k_cityscapes.py │ │ ├── fcn_r50-d8_480x480_40k_pascal_context.py │ │ └── fcn_r50-d8_480x480_80k_pascal_context.py │ ├── sem_fpn │ │ ├── fpn_r101_512x512_160k_ade20k.py │ │ ├── fpn_r101_512x1024_80k_cityscapes.py │ │ ├── fpn_r50_512x1024_80k_cityscapes.py │ │ ├── fpn_r50_512x512_160k_ade20k.py │ │ └── README.md │ ├── upernet │ │ ├── upernet_r101_512x512_80k_ade20k.py │ │ ├── upernet_r101_512x512_160k_ade20k.py │ │ ├── upernet_r101_512x512_20k_voc12aug.py │ │ ├── upernet_r101_512x512_40k_voc12aug.py │ │ ├── upernet_r101_512x1024_40k_cityscapes.py │ │ ├── upernet_r101_512x1024_80k_cityscapes.py │ │ ├── upernet_r101_769x769_40k_cityscapes.py │ │ ├── upernet_r101_769x769_80k_cityscapes.py │ │ ├── upernet_r50_512x1024_40k_cityscapes.py │ │ ├── upernet_r50_512x1024_80k_cityscapes.py │ │ ├── upernet_r50_512x512_160k_ade20k.py │ │ ├── upernet_r50_512x512_80k_ade20k.py │ │ ├── upernet_r50_512x512_20k_voc12aug.py │ │ ├── upernet_r50_512x512_40k_voc12aug.py │ │ ├── upernet_r50_769x769_40k_cityscapes.py │ │ └── upernet_r50_769x769_80k_cityscapes.py │ ├── point_rend │ │ ├── pointrend_r101_512x512_160k_ade20k.py │ │ ├── pointrend_r101_512x1024_80k_cityscapes.py │ │ ├── pointrend_r50_512x1024_80k_cityscapes.py │ │ ├── pointrend_r50_512x512_160k_ade20k.py │ │ └── README.md │ ├── deeplabv3 │ │ ├── deeplabv3_r101-d8_512x512_160k_ade20k.py │ │ ├── deeplabv3_r101-d8_512x512_80k_ade20k.py │ │ ├── deeplabv3_r101-d8_512x512_20k_voc12aug.py │ │ ├── deeplabv3_r101-d8_512x512_40k_voc12aug.py │ │ ├── deeplabv3_r101-d8_769x769_40k_cityscapes.py │ │ ├── deeplabv3_r101-d8_769x769_80k_cityscapes.py │ │ ├── deeplabv3_r50b-d8_769x769_80k_cityscapes.py │ │ ├── deeplabv3_r101-d8_512x1024_40k_cityscapes.py │ │ ├── deeplabv3_r101-d8_512x1024_80k_cityscapes.py │ │ ├── deeplabv3_r50b-d8_512x1024_80k_cityscapes.py │ │ ├── deeplabv3_r101-d8_480x480_40k_pascal_context.py │ │ ├── deeplabv3_r101-d8_480x480_80k_pascal_context.py │ │ ├── deeplabv3_r101b-d8_769x769_80k_cityscapes.py │ │ ├── deeplabv3_r101b-d8_512x1024_80k_cityscapes.py │ │ ├── deeplabv3_r50-d8_512x1024_40k_cityscapes.py │ │ ├── deeplabv3_r50-d8_512x1024_80k_cityscapes.py │ │ ├── deeplabv3_r50-d8_512x512_80k_ade20k.py │ │ ├── deeplabv3_r50-d8_512x512_160k_ade20k.py │ │ ├── deeplabv3_r50-d8_512x512_20k_voc12aug.py │ │ ├── deeplabv3_r50-d8_512x512_40k_voc12aug.py │ │ ├── deeplabv3_r18-d8_769x769_80k_cityscapes.py │ │ ├── deeplabv3_r18-d8_512x1024_80k_cityscapes.py │ │ ├── deeplabv3_r18b-d8_512x1024_80k_cityscapes.py │ │ ├── deeplabv3_r18b-d8_769x769_80k_cityscapes.py │ │ ├── deeplabv3_r50-d8_769x769_40k_cityscapes.py │ │ ├── deeplabv3_r50-d8_769x769_80k_cityscapes.py │ │ ├── deeplabv3_r101-d16-mg124_512x1024_40k_cityscapes.py │ │ ├── deeplabv3_r101-d16-mg124_512x1024_80k_cityscapes.py │ │ ├── deeplabv3_r50-d8_480x480_40k_pascal_context.py │ │ └── deeplabv3_r50-d8_480x480_80k_pascal_context.py │ ├── nonlocal_net │ │ ├── nonlocal_r101-d8_512x512_160k_ade20k.py │ │ ├── nonlocal_r101-d8_512x512_80k_ade20k.py │ │ ├── nonlocal_r101-d8_512x512_20k_voc12aug.py │ │ ├── nonlocal_r101-d8_512x512_40k_voc12aug.py │ │ ├── nonlocal_r101-d8_512x1024_40k_cityscapes.py │ │ ├── nonlocal_r101-d8_512x1024_80k_cityscapes.py │ │ ├── nonlocal_r101-d8_769x769_40k_cityscapes.py │ │ ├── nonlocal_r101-d8_769x769_80k_cityscapes.py │ │ ├── nonlocal_r50-d8_512x1024_40k_cityscapes.py │ │ ├── nonlocal_r50-d8_512x1024_80k_cityscapes.py │ │ ├── nonlocal_r50-d8_512x512_80k_ade20k.py │ │ ├── nonlocal_r50-d8_512x512_160k_ade20k.py │ │ ├── nonlocal_r50-d8_512x512_20k_voc12aug.py │ │ ├── nonlocal_r50-d8_512x512_40k_voc12aug.py │ │ ├── nonlocal_r50-d8_769x769_40k_cityscapes.py │ │ └── nonlocal_r50-d8_769x769_80k_cityscapes.py │ ├── fp16 │ │ ├── fcn_r101-d8_512x1024_80k_fp16_cityscapes.py │ │ ├── pspnet_r101-d8_512x1024_80k_fp16_cityscapes.py │ │ ├── deeplabv3_r101-d8_512x1024_80k_fp16_cityscapes.py │ │ ├── deeplabv3plus_r101-d8_512x1024_80k_fp16_cityscapes.py │ │ └── README.md │ ├── unet │ │ ├── fcn_unet_s5-d16_128x128_40k_stare.py │ │ ├── fcn_unet_s5-d16_256x256_40k_hrf.py │ │ ├── fcn_unet_s5-d16_64x64_40k_drive.py │ │ ├── pspnet_unet_s5-d16_256x256_40k_hrf.py │ │ ├── pspnet_unet_s5-d16_64x64_40k_drive.py │ │ ├── deeplabv3_unet_s5-d16_256x256_40k_hrf.py │ │ ├── deeplabv3_unet_s5-d16_64x64_40k_drive.py │ │ ├── fcn_unet_s5-d16_128x128_40k_chase_db1.py │ │ ├── pspnet_unet_s5-d16_128x128_40k_stare.py │ │ ├── deeplabv3_unet_s5-d16_128x128_40k_stare.py │ │ ├── pspnet_unet_s5-d16_128x128_40k_chase_db1.py │ │ └── deeplabv3_unet_s5-d16_128x128_40k_chase_db1.py │ ├── _base_ │ │ ├── datasets │ │ │ ├── pascal_voc12_aug.py │ │ │ ├── autonue.py │ │ │ ├── cityscapes.py │ │ │ ├── pascal_person_part.py │ │ │ ├── mapillary.py │ │ │ ├── LIP.py │ │ │ ├── ade20k.py │ │ │ ├── pascal_voc12.py │ │ │ └── pascal_context.py │ │ ├── default_runtime.py │ │ ├── schedules │ │ │ ├── schedule_120k.py │ │ │ ├── schedule_60k.py │ │ │ ├── schedule_80k.py │ │ │ └── schedule_160k.py │ │ └── models │ │ │ ├── fpn_r50.py │ │ │ ├── deeplabv3_r50-d8.py │ │ │ ├── fcn_r50-d8.py │ │ │ ├── upernet_r50.py │ │ │ ├── deeplabv3plus_r50-d8.py │ │ │ ├── deeplabv3plus_r50-d8_vd.py │ │ │ ├── deeplabv3plus_r50-d8_vd_contrast.py │ │ │ └── fcn_hr18.py │ ├── resnest │ │ ├── fcn_s101-d8_512x512_160k_ade20k.py │ │ ├── fcn_s101-d8_512x1024_80k_cityscapes.py │ │ ├── pspnet_s101-d8_512x512_160k_ade20k.py │ │ ├── deeplabv3_s101-d8_512x512_160k_ade20k.py │ │ ├── pspnet_s101-d8_512x1024_80k_cityscapes.py │ │ ├── deeplabv3_s101-d8_512x1024_80k_cityscapes.py │ │ ├── deeplabv3plus_s101-d8_512x512_160k_ade20k.py │ │ └── deeplabv3plus_s101-d8_512x1024_80k_cityscapes.py │ └── deeplabv3plus │ │ ├── deeplabv3plus_r101-d8_480x480_160k_LIP_hiera_triplet.py │ │ ├── deeplabv3plus_r101-d8_512x1024_80k_cityscapes_hiera_triplet.py │ │ └── deeplabv3plus_r101-d8_480x480_60k_pascal_person_part_hiera_triplet.py ├── tools │ ├── dist_train.sh │ ├── dist_test.sh │ ├── slurm_train.sh │ ├── slurm_test.sh │ ├── print_config.py │ ├── publish_model.py │ ├── get_flops.py │ ├── convert_datasets │ │ ├── cityscapes.py │ │ ├── pascal_context.py │ │ ├── voc_aug.py │ │ └── chase_db1.py │ └── benchmark.py ├── tests │ ├── test_utils │ │ ├── test_make_divisible.py │ │ └── test_se_layer.py │ ├── test_models │ │ └── test_necks.py │ ├── test_inference.py │ └── test_sampler.py ├── setup.cfg ├── docker │ └── Dockerfile └── README.MD ├── fig.png ├── PaddlePaddle └── README.MD └── README.md /Pytorch/mmseg/models/decode_heads/.~untitled.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /fig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingorX/HieraSeg/HEAD/fig.png -------------------------------------------------------------------------------- /Pytorch/mmseg/models/necks/__init__.py: -------------------------------------------------------------------------------- 1 | from .fpn import FPN 2 | 3 | __all__ = ['FPN'] 4 | -------------------------------------------------------------------------------- /Pytorch/mmseg/core/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .misc import add_prefix 2 | 3 | __all__ = ['add_prefix'] 4 | -------------------------------------------------------------------------------- /Pytorch/mmcv_custom/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .checkpoint import load_checkpoint 4 | 5 | __all__ = ['load_checkpoint'] 6 | -------------------------------------------------------------------------------- /Pytorch/mmseg/ops/__init__.py: -------------------------------------------------------------------------------- 1 | from .encoding import Encoding 2 | from .wrappers import Upsample, resize 3 | 4 | __all__ = ['Upsample', 'resize', 'Encoding'] 5 | -------------------------------------------------------------------------------- /Pytorch/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 | -------------------------------------------------------------------------------- /Pytorch/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 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r101-d8_512x512_80k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_512x512_80k_ade20k.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/sem_fpn/fpn_r101_512x512_160k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = './fpn_r50_512x512_160k_ade20k.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r101-d8_512x512_160k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_512x512_160k_ade20k.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r101-d8_512x512_20k_voc12aug.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_512x512_20k_voc12aug.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r101-d8_512x512_40k_voc12aug.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_512x512_40k_voc12aug.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/upernet/upernet_r101_512x512_80k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = './upernet_r50_512x512_80k_ade20k.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r101-d8_512x1024_40k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_512x1024_40k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r101-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_512x1024_80k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r101-d8_769x769_40k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_769x769_40k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r101-d8_769x769_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_769x769_80k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r50b-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_512x1024_80k_cityscapes.py' 2 | model = dict(pretrained='torchvision://resnet50', backbone=dict(type='ResNet')) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r50b-d8_769x769_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_769x769_80k_cityscapes.py' 2 | model = dict(pretrained='torchvision://resnet50', backbone=dict(type='ResNet')) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/sem_fpn/fpn_r101_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './fpn_r50_512x1024_80k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/upernet/upernet_r101_512x512_160k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = './upernet_r50_512x512_160k_ade20k.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/upernet/upernet_r101_512x512_20k_voc12aug.py: -------------------------------------------------------------------------------- 1 | _base_ = './upernet_r50_512x512_20k_voc12aug.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/upernet/upernet_r101_512x512_40k_voc12aug.py: -------------------------------------------------------------------------------- 1 | _base_ = './upernet_r50_512x512_40k_voc12aug.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r101-d8_480x480_40k_pascal_context.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_480x480_40k_pascal_context.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r101-d8_480x480_80k_pascal_context.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_480x480_80k_pascal_context.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/point_rend/pointrend_r101_512x512_160k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = './pointrend_r50_512x512_160k_ade20k.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/upernet/upernet_r101_512x1024_40k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './upernet_r50_512x1024_40k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/upernet/upernet_r101_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './upernet_r50_512x1024_80k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/upernet/upernet_r101_769x769_40k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './upernet_r50_769x769_40k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/upernet/upernet_r101_769x769_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './upernet_r50_769x769_80k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r101-d8_512x512_160k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_512x512_160k_ade20k.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r101-d8_512x512_80k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_512x512_80k_ade20k.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/nonlocal_net/nonlocal_r101-d8_512x512_160k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = './nonlocal_r50-d8_512x512_160k_ade20k.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/nonlocal_net/nonlocal_r101-d8_512x512_80k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = './nonlocal_r50-d8_512x512_80k_ade20k.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/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 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r101-d8_512x512_20k_voc12aug.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_512x512_20k_voc12aug.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r101-d8_512x512_40k_voc12aug.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_512x512_40k_voc12aug.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r101-d8_769x769_40k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_769x769_40k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r101-d8_769x769_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_769x769_80k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r50b-d8_769x769_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_769x769_80k_cityscapes.py' 2 | model = dict(pretrained='torchvision://resnet50', backbone=dict(type='ResNet')) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/nonlocal_net/nonlocal_r101-d8_512x512_20k_voc12aug.py: -------------------------------------------------------------------------------- 1 | _base_ = './nonlocal_r50-d8_512x512_20k_voc12aug.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/nonlocal_net/nonlocal_r101-d8_512x512_40k_voc12aug.py: -------------------------------------------------------------------------------- 1 | _base_ = './nonlocal_r50-d8_512x512_40k_voc12aug.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/point_rend/pointrend_r101_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './pointrend_r50_512x1024_80k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r101-d8_512x1024_40k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_512x1024_40k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r101-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_512x1024_80k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r50b-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_512x1024_80k_cityscapes.py' 2 | model = dict(pretrained='torchvision://resnet50', backbone=dict(type='ResNet')) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/fp16/fcn_r101-d8_512x1024_80k_fp16_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = '../fcn/fcn_r101-d8_512x1024_80k_cityscapes.py' 2 | # fp16 settings 3 | optimizer_config = dict(type='Fp16OptimizerHook', loss_scale=512.) 4 | -------------------------------------------------------------------------------- /Pytorch/configs/nonlocal_net/nonlocal_r101-d8_512x1024_40k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './nonlocal_r50-d8_512x1024_40k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/nonlocal_net/nonlocal_r101-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './nonlocal_r50-d8_512x1024_80k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/nonlocal_net/nonlocal_r101-d8_769x769_40k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './nonlocal_r50-d8_769x769_40k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/nonlocal_net/nonlocal_r101-d8_769x769_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './nonlocal_r50-d8_769x769_80k_cityscapes.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/segmentors/__init__.py: -------------------------------------------------------------------------------- 1 | from .cascade_encoder_decoder import CascadeEncoderDecoder 2 | from .encoder_decoder import EncoderDecoder 3 | 4 | __all__ = ['EncoderDecoder', 'CascadeEncoderDecoder'] 5 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r101-d8_480x480_40k_pascal_context.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_480x480_40k_pascal_context.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r101-d8_480x480_80k_pascal_context.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_480x480_80k_pascal_context.py' 2 | model = dict(pretrained='open-mmlab://resnet101_v1c', backbone=dict(depth=101)) 3 | -------------------------------------------------------------------------------- /Pytorch/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 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r101b-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_512x1024_80k_cityscapes.py' 2 | model = dict( 3 | pretrained='torchvision://resnet101', 4 | backbone=dict(type='ResNet', depth=101)) 5 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r101b-d8_769x769_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_769x769_80k_cityscapes.py' 2 | model = dict( 3 | pretrained='torchvision://resnet101', 4 | backbone=dict(type='ResNet', depth=101)) 5 | -------------------------------------------------------------------------------- /Pytorch/configs/fp16/pspnet_r101-d8_512x1024_80k_fp16_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = '../pspnet/pspnet_r101-d8_512x1024_80k_cityscapes.py' 2 | # fp16 settings 3 | optimizer_config = dict(type='Fp16OptimizerHook', loss_scale=512.) 4 | -------------------------------------------------------------------------------- /Pytorch/configs/sem_fpn/fpn_r50_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/fpn_r50.py', '../_base_/datasets/cityscapes.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_80k.py' 4 | ] 5 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r50-d8_512x1024_40k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/fcn_r50-d8.py', '../_base_/datasets/cityscapes.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' 4 | ] 5 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r50-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/fcn_r50-d8.py', '../_base_/datasets/cityscapes.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_80k.py' 4 | ] 5 | -------------------------------------------------------------------------------- /Pytorch/configs/fp16/deeplabv3_r101-d8_512x1024_80k_fp16_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = '../deeplabv3/deeplabv3_r101-d8_512x1024_80k_cityscapes.py' 2 | # fp16 settings 3 | optimizer_config = dict(type='Fp16OptimizerHook', loss_scale=512.) 4 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r101b-d8_769x769_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_769x769_80k_cityscapes.py' 2 | model = dict( 3 | pretrained='torchvision://resnet101', 4 | backbone=dict(type='ResNet', depth=101)) 5 | -------------------------------------------------------------------------------- /Pytorch/configs/upernet/upernet_r50_512x1024_40k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/upernet_r50.py', '../_base_/datasets/cityscapes.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' 4 | ] 5 | -------------------------------------------------------------------------------- /Pytorch/configs/upernet/upernet_r50_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/upernet_r50.py', '../_base_/datasets/cityscapes.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_80k.py' 4 | ] 5 | -------------------------------------------------------------------------------- /PaddlePaddle/README.MD: -------------------------------------------------------------------------------- 1 | # Deep Hierarchical Semantic Segmentation 2 | 3 | This repo will release the paddlepaddle version code and configuration files to reproduce semantic segmentaion results of [HieraSeg](https://arxiv.org/abs/2203.14335). 4 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r101b-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_512x1024_80k_cityscapes.py' 2 | model = dict( 3 | pretrained='torchvision://resnet101', 4 | backbone=dict(type='ResNet', depth=101)) 5 | -------------------------------------------------------------------------------- /Pytorch/configs/fp16/deeplabv3plus_r101-d8_512x1024_80k_fp16_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = '../deeplabv3plus/deeplabv3plus_r101-d8_512x1024_80k_cityscapes.py' 2 | # fp16 settings 3 | optimizer_config = dict(type='Fp16OptimizerHook', loss_scale=512.) 4 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r50-d8_512x1024_40k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/deeplabv3_r50-d8.py', '../_base_/datasets/cityscapes.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' 4 | ] 5 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r50-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/deeplabv3_r50-d8.py', '../_base_/datasets/cityscapes.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_80k.py' 4 | ] 5 | -------------------------------------------------------------------------------- /Pytorch/configs/nonlocal_net/nonlocal_r50-d8_512x1024_40k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/nonlocal_r50-d8.py', '../_base_/datasets/cityscapes.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' 4 | ] 5 | -------------------------------------------------------------------------------- /Pytorch/configs/nonlocal_net/nonlocal_r50-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/nonlocal_r50-d8.py', '../_base_/datasets/cityscapes.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_80k.py' 4 | ] 5 | -------------------------------------------------------------------------------- /Pytorch/configs/sem_fpn/fpn_r50_512x512_160k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/fpn_r50.py', '../_base_/datasets/ade20k.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_160k.py' 4 | ] 5 | model = dict(decode_head=dict(num_classes=150)) 6 | -------------------------------------------------------------------------------- /Pytorch/configs/point_rend/pointrend_r50_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/pointrend_r50.py', '../_base_/datasets/cityscapes.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_80k.py' 4 | ] 5 | lr_config = dict(warmup='linear', warmup_iters=200) 6 | -------------------------------------------------------------------------------- /Pytorch/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 | -------------------------------------------------------------------------------- /Pytorch/tools/dist_train.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CONFIG=$1 4 | GPUS=$2 5 | PORT=${PORT:-29527} 6 | 7 | PYTHONPATH="$(dirname $0)/..":$PYTHONPATH \ 8 | python -m torch.distributed.launch --nproc_per_node=$GPUS --master_port=$PORT \ 9 | $(dirname "$0")/train.py $CONFIG --launcher pytorch ${@:3} 10 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r50-d8_512x512_160k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/fcn_r50-d8.py', '../_base_/datasets/ade20k.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_160k.py' 4 | ] 5 | model = dict( 6 | decode_head=dict(num_classes=150), auxiliary_head=dict(num_classes=150)) 7 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r50-d8_512x512_80k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/fcn_r50-d8.py', '../_base_/datasets/ade20k.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_80k.py' 4 | ] 5 | model = dict( 6 | decode_head=dict(num_classes=150), auxiliary_head=dict(num_classes=150)) 7 | -------------------------------------------------------------------------------- /Pytorch/configs/upernet/upernet_r50_512x512_160k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/upernet_r50.py', '../_base_/datasets/ade20k.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_160k.py' 4 | ] 5 | model = dict( 6 | decode_head=dict(num_classes=150), auxiliary_head=dict(num_classes=150)) 7 | -------------------------------------------------------------------------------- /Pytorch/configs/upernet/upernet_r50_512x512_80k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/upernet_r50.py', '../_base_/datasets/ade20k.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_80k.py' 4 | ] 5 | model = dict( 6 | decode_head=dict(num_classes=150), auxiliary_head=dict(num_classes=150)) 7 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r50-d8_512x512_20k_voc12aug.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/fcn_r50-d8.py', '../_base_/datasets/pascal_voc12_aug.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_20k.py' 4 | ] 5 | model = dict( 6 | decode_head=dict(num_classes=21), auxiliary_head=dict(num_classes=21)) 7 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r50-d8_512x512_40k_voc12aug.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/fcn_r50-d8.py', '../_base_/datasets/pascal_voc12_aug.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' 4 | ] 5 | model = dict( 6 | decode_head=dict(num_classes=21), auxiliary_head=dict(num_classes=21)) 7 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r50-d8_512x512_80k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/deeplabv3_r50-d8.py', '../_base_/datasets/ade20k.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_80k.py' 4 | ] 5 | model = dict( 6 | decode_head=dict(num_classes=150), auxiliary_head=dict(num_classes=150)) 7 | -------------------------------------------------------------------------------- /Pytorch/configs/nonlocal_net/nonlocal_r50-d8_512x512_80k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/nonlocal_r50-d8.py', '../_base_/datasets/ade20k.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_80k.py' 4 | ] 5 | model = dict( 6 | decode_head=dict(num_classes=150), auxiliary_head=dict(num_classes=150)) 7 | -------------------------------------------------------------------------------- /Pytorch/configs/unet/fcn_unet_s5-d16_128x128_40k_stare.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/fcn_unet_s5-d16.py', '../_base_/datasets/stare.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' 4 | ] 5 | model = dict(test_cfg=dict(crop_size=(128, 128), stride=(85, 85))) 6 | evaluation = dict(metric='mDice') 7 | -------------------------------------------------------------------------------- /Pytorch/configs/unet/fcn_unet_s5-d16_256x256_40k_hrf.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/fcn_unet_s5-d16.py', '../_base_/datasets/hrf.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' 4 | ] 5 | model = dict(test_cfg=dict(crop_size=(256, 256), stride=(170, 170))) 6 | evaluation = dict(metric='mDice') 7 | -------------------------------------------------------------------------------- /Pytorch/configs/unet/fcn_unet_s5-d16_64x64_40k_drive.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/fcn_unet_s5-d16.py', '../_base_/datasets/drive.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' 4 | ] 5 | model = dict(test_cfg=dict(crop_size=(64, 64), stride=(42, 42))) 6 | evaluation = dict(metric='mDice') 7 | -------------------------------------------------------------------------------- /Pytorch/tools/dist_test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CONFIG=$1 4 | CHECKPOINT=$2 5 | GPUS=$3 6 | PORT=${PORT:-29512} 7 | PYTHONPATH="$(dirname $0)/..":$PYTHONPATH \ 8 | python -m torch.distributed.launch --nproc_per_node=$GPUS --master_port=$PORT \ 9 | $(dirname "$0")/test.py $CONFIG $CHECKPOINT --launcher pytorch ${@:4} 10 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r50-d8_512x512_160k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/deeplabv3_r50-d8.py', '../_base_/datasets/ade20k.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_160k.py' 4 | ] 5 | model = dict( 6 | decode_head=dict(num_classes=150), auxiliary_head=dict(num_classes=150)) 7 | -------------------------------------------------------------------------------- /Pytorch/configs/nonlocal_net/nonlocal_r50-d8_512x512_160k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/nonlocal_r50-d8.py', '../_base_/datasets/ade20k.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_160k.py' 4 | ] 5 | model = dict( 6 | decode_head=dict(num_classes=150), auxiliary_head=dict(num_classes=150)) 7 | -------------------------------------------------------------------------------- /Pytorch/configs/unet/pspnet_unet_s5-d16_256x256_40k_hrf.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/pspnet_unet_s5-d16.py', '../_base_/datasets/hrf.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' 4 | ] 5 | model = dict(test_cfg=dict(crop_size=(256, 256), stride=(170, 170))) 6 | evaluation = dict(metric='mDice') 7 | -------------------------------------------------------------------------------- /Pytorch/configs/unet/pspnet_unet_s5-d16_64x64_40k_drive.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/pspnet_unet_s5-d16.py', '../_base_/datasets/drive.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' 4 | ] 5 | model = dict(test_cfg=dict(crop_size=(64, 64), stride=(42, 42))) 6 | evaluation = dict(metric='mDice') 7 | -------------------------------------------------------------------------------- /Pytorch/configs/upernet/upernet_r50_512x512_20k_voc12aug.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/upernet_r50.py', 3 | '../_base_/datasets/pascal_voc12_aug.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_20k.py' 5 | ] 6 | model = dict( 7 | decode_head=dict(num_classes=21), auxiliary_head=dict(num_classes=21)) 8 | -------------------------------------------------------------------------------- /Pytorch/configs/upernet/upernet_r50_512x512_40k_voc12aug.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/upernet_r50.py', 3 | '../_base_/datasets/pascal_voc12_aug.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_40k.py' 5 | ] 6 | model = dict( 7 | decode_head=dict(num_classes=21), auxiliary_head=dict(num_classes=21)) 8 | -------------------------------------------------------------------------------- /Pytorch/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_iou 4 | 5 | __all__ = [ 6 | 'EvalHook', 'DistEvalHook', 'mean_dice', 'mean_iou', 'eval_metrics', 7 | 'get_classes', 'get_palette' 8 | ] 9 | -------------------------------------------------------------------------------- /Pytorch/configs/unet/deeplabv3_unet_s5-d16_256x256_40k_hrf.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/deeplabv3_unet_s5-d16.py', '../_base_/datasets/hrf.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' 4 | ] 5 | model = dict(test_cfg=dict(crop_size=(256, 256), stride=(170, 170))) 6 | evaluation = dict(metric='mDice') 7 | -------------------------------------------------------------------------------- /Pytorch/configs/unet/deeplabv3_unet_s5-d16_64x64_40k_drive.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/deeplabv3_unet_s5-d16.py', '../_base_/datasets/drive.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' 4 | ] 5 | model = dict(test_cfg=dict(crop_size=(64, 64), stride=(42, 42))) 6 | evaluation = dict(metric='mDice') 7 | -------------------------------------------------------------------------------- /Pytorch/configs/unet/fcn_unet_s5-d16_128x128_40k_chase_db1.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/fcn_unet_s5-d16.py', '../_base_/datasets/chase_db1.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' 4 | ] 5 | model = dict(test_cfg=dict(crop_size=(128, 128), stride=(85, 85))) 6 | evaluation = dict(metric='mDice') 7 | -------------------------------------------------------------------------------- /Pytorch/configs/unet/pspnet_unet_s5-d16_128x128_40k_stare.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/pspnet_unet_s5-d16.py', '../_base_/datasets/stare.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' 4 | ] 5 | model = dict(test_cfg=dict(crop_size=(128, 128), stride=(85, 85))) 6 | evaluation = dict(metric='mDice') 7 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/datasets/pascal_voc12_aug.py: -------------------------------------------------------------------------------- 1 | _base_ = './pascal_voc12.py' 2 | # dataset settings 3 | data = dict( 4 | train=dict( 5 | ann_dir=['SegmentationClass', 'SegmentationClassAug'], 6 | split=[ 7 | 'ImageSets/Segmentation/train.txt', 8 | 'ImageSets/Segmentation/aug.txt' 9 | ])) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/unet/deeplabv3_unet_s5-d16_128x128_40k_stare.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/deeplabv3_unet_s5-d16.py', '../_base_/datasets/stare.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' 4 | ] 5 | model = dict(test_cfg=dict(crop_size=(128, 128), stride=(85, 85))) 6 | evaluation = dict(metric='mDice') 7 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r50-d8_512x512_20k_voc12aug.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/deeplabv3_r50-d8.py', 3 | '../_base_/datasets/pascal_voc12_aug.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_20k.py' 5 | ] 6 | model = dict( 7 | decode_head=dict(num_classes=21), auxiliary_head=dict(num_classes=21)) 8 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r50-d8_512x512_40k_voc12aug.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/deeplabv3_r50-d8.py', 3 | '../_base_/datasets/pascal_voc12_aug.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_40k.py' 5 | ] 6 | model = dict( 7 | decode_head=dict(num_classes=21), auxiliary_head=dict(num_classes=21)) 8 | -------------------------------------------------------------------------------- /Pytorch/configs/nonlocal_net/nonlocal_r50-d8_512x512_20k_voc12aug.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/nonlocal_r50-d8.py', 3 | '../_base_/datasets/pascal_voc12_aug.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_20k.py' 5 | ] 6 | model = dict( 7 | decode_head=dict(num_classes=21), auxiliary_head=dict(num_classes=21)) 8 | -------------------------------------------------------------------------------- /Pytorch/configs/nonlocal_net/nonlocal_r50-d8_512x512_40k_voc12aug.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/nonlocal_r50-d8.py', 3 | '../_base_/datasets/pascal_voc12_aug.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_40k.py' 5 | ] 6 | model = dict( 7 | decode_head=dict(num_classes=21), auxiliary_head=dict(num_classes=21)) 8 | -------------------------------------------------------------------------------- /Pytorch/configs/resnest/fcn_s101-d8_512x512_160k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = '../fcn/fcn_r101-d8_512x512_160k_ade20k.py' 2 | model = dict( 3 | pretrained='open-mmlab://resnest101', 4 | backbone=dict( 5 | type='ResNeSt', 6 | stem_channels=128, 7 | radix=2, 8 | reduction_factor=4, 9 | avg_down_stride=True)) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/resnest/fcn_s101-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = '../fcn/fcn_r101-d8_512x1024_80k_cityscapes.py' 2 | model = dict( 3 | pretrained='open-mmlab://resnest101', 4 | backbone=dict( 5 | type='ResNeSt', 6 | stem_channels=128, 7 | radix=2, 8 | reduction_factor=4, 9 | avg_down_stride=True)) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/resnest/pspnet_s101-d8_512x512_160k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = '../pspnet/pspnet_r101-d8_512x512_160k_ade20k.py' 2 | model = dict( 3 | pretrained='open-mmlab://resnest101', 4 | backbone=dict( 5 | type='ResNeSt', 6 | stem_channels=128, 7 | radix=2, 8 | reduction_factor=4, 9 | avg_down_stride=True)) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/unet/pspnet_unet_s5-d16_128x128_40k_chase_db1.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/pspnet_unet_s5-d16.py', 3 | '../_base_/datasets/chase_db1.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_40k.py' 5 | ] 6 | model = dict(test_cfg=dict(crop_size=(128, 128), stride=(85, 85))) 7 | evaluation = dict(metric='mDice') 8 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r18-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_512x1024_80k_cityscapes.py' 2 | model = dict( 3 | pretrained='open-mmlab://resnet18_v1c', 4 | backbone=dict(depth=18), 5 | decode_head=dict( 6 | in_channels=512, 7 | channels=128, 8 | ), 9 | auxiliary_head=dict(in_channels=256, channels=64)) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r18-d8_769x769_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_769x769_80k_cityscapes.py' 2 | model = dict( 3 | pretrained='open-mmlab://resnet18_v1c', 4 | backbone=dict(depth=18), 5 | decode_head=dict( 6 | in_channels=512, 7 | channels=128, 8 | ), 9 | auxiliary_head=dict(in_channels=256, channels=64)) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/unet/deeplabv3_unet_s5-d16_128x128_40k_chase_db1.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/deeplabv3_unet_s5-d16.py', 3 | '../_base_/datasets/chase_db1.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_40k.py' 5 | ] 6 | model = dict(test_cfg=dict(crop_size=(128, 128), stride=(85, 85))) 7 | evaluation = dict(metric='mDice') 8 | -------------------------------------------------------------------------------- /Pytorch/configs/resnest/deeplabv3_s101-d8_512x512_160k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = '../deeplabv3/deeplabv3_r101-d8_512x512_160k_ade20k.py' 2 | model = dict( 3 | pretrained='open-mmlab://resnest101', 4 | backbone=dict( 5 | type='ResNeSt', 6 | stem_channels=128, 7 | radix=2, 8 | reduction_factor=4, 9 | avg_down_stride=True)) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/resnest/pspnet_s101-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = '../pspnet/pspnet_r101-d8_512x1024_80k_cityscapes.py' 2 | model = dict( 3 | pretrained='open-mmlab://resnest101', 4 | backbone=dict( 5 | type='ResNeSt', 6 | stem_channels=128, 7 | radix=2, 8 | reduction_factor=4, 9 | avg_down_stride=True)) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r18b-d8_769x769_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_769x769_80k_cityscapes.py' 2 | model = dict( 3 | pretrained='torchvision://resnet18', 4 | backbone=dict(type='ResNet', depth=18), 5 | decode_head=dict( 6 | in_channels=512, 7 | channels=128, 8 | ), 9 | auxiliary_head=dict(in_channels=256, channels=64)) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r18-d8_769x769_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_769x769_80k_cityscapes.py' 2 | model = dict( 3 | pretrained='open-mmlab://resnet18_v1c', 4 | backbone=dict(depth=18), 5 | decode_head=dict( 6 | in_channels=512, 7 | channels=128, 8 | ), 9 | auxiliary_head=dict(in_channels=256, channels=64)) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r18b-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './fcn_r50-d8_512x1024_80k_cityscapes.py' 2 | model = dict( 3 | pretrained='torchvision://resnet18', 4 | backbone=dict(type='ResNet', depth=18), 5 | decode_head=dict( 6 | in_channels=512, 7 | channels=128, 8 | ), 9 | auxiliary_head=dict(in_channels=256, channels=64)) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/resnest/deeplabv3_s101-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = '../deeplabv3/deeplabv3_r101-d8_512x1024_80k_cityscapes.py' 2 | model = dict( 3 | pretrained='open-mmlab://resnest101', 4 | backbone=dict( 5 | type='ResNeSt', 6 | stem_channels=128, 7 | radix=2, 8 | reduction_factor=4, 9 | avg_down_stride=True)) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r18-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_512x1024_80k_cityscapes.py' 2 | model = dict( 3 | pretrained='open-mmlab://resnet18_v1c', 4 | backbone=dict(depth=18), 5 | decode_head=dict( 6 | in_channels=512, 7 | channels=128, 8 | ), 9 | auxiliary_head=dict(in_channels=256, channels=64)) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/resnest/deeplabv3plus_s101-d8_512x512_160k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = '../deeplabv3plus/deeplabv3plus_r101-d8_512x512_160k_ade20k.py' 2 | model = dict( 3 | pretrained='open-mmlab://resnest101', 4 | backbone=dict( 5 | type='ResNeSt', 6 | stem_channels=128, 7 | radix=2, 8 | reduction_factor=4, 9 | avg_down_stride=True)) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/resnest/deeplabv3plus_s101-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = '../deeplabv3plus/deeplabv3plus_r101-d8_512x1024_80k_cityscapes.py' 2 | model = dict( 3 | pretrained='open-mmlab://resnest101', 4 | backbone=dict( 5 | type='ResNeSt', 6 | stem_channels=128, 7 | radix=2, 8 | reduction_factor=4, 9 | avg_down_stride=True)) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r18b-d8_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_512x1024_80k_cityscapes.py' 2 | model = dict( 3 | pretrained='torchvision://resnet18', 4 | backbone=dict(type='ResNet', depth=18), 5 | decode_head=dict( 6 | in_channels=512, 7 | channels=128, 8 | ), 9 | auxiliary_head=dict(in_channels=256, channels=64)) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r18b-d8_769x769_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_769x769_80k_cityscapes.py' 2 | model = dict( 3 | pretrained='torchvision://resnet18', 4 | backbone=dict(type='ResNet', depth=18), 5 | decode_head=dict( 6 | in_channels=512, 7 | channels=128, 8 | ), 9 | auxiliary_head=dict(in_channels=256, channels=64)) 10 | -------------------------------------------------------------------------------- /Pytorch/mmseg/core/seg/sampler/base_pixel_sampler.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | 3 | 4 | class BasePixelSampler(metaclass=ABCMeta): 5 | """Base class of pixel sampler.""" 6 | 7 | def __init__(self, **kwargs): 8 | pass 9 | 10 | @abstractmethod 11 | def sample(self, seg_logit, seg_label): 12 | """Placeholder for sample function.""" 13 | pass 14 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/default_runtime.py: -------------------------------------------------------------------------------- 1 | # yapf:disable 2 | log_config = dict( 3 | interval=50, 4 | hooks=[ 5 | dict(type='TextLoggerHook', by_epoch=False), 6 | # dict(type='TensorboardLoggerHook') 7 | ]) 8 | # yapf:enable 9 | dist_params = dict(backend='nccl') 10 | log_level = 'INFO' 11 | load_from = None 12 | resume_from = None 13 | workflow = [('train', 1)] 14 | cudnn_benchmark = True 15 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r50-d8_769x769_40k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/fcn_r50-d8.py', 3 | '../_base_/datasets/cityscapes_769x769.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_40k.py' 5 | ] 6 | model = dict( 7 | decode_head=dict(align_corners=True), 8 | auxiliary_head=dict(align_corners=True), 9 | test_cfg=dict(mode='slide', crop_size=(769, 769), stride=(513, 513))) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r50-d8_769x769_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/fcn_r50-d8.py', 3 | '../_base_/datasets/cityscapes_769x769.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_80k.py' 5 | ] 6 | model = dict( 7 | decode_head=dict(align_corners=True), 8 | auxiliary_head=dict(align_corners=True), 9 | test_cfg=dict(mode='slide', crop_size=(769, 769), stride=(513, 513))) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r50-d8_480x480_40k_pascal_context.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/fcn_r50-d8.py', '../_base_/datasets/pascal_context.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' 4 | ] 5 | model = dict( 6 | decode_head=dict(num_classes=60), 7 | test_cfg=dict(mode='slide', crop_size=(480, 480), stride=(320, 320))) 8 | optimizer = dict(type='SGD', lr=0.004, momentum=0.9, weight_decay=0.0001) 9 | -------------------------------------------------------------------------------- /Pytorch/configs/fcn/fcn_r50-d8_480x480_80k_pascal_context.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/fcn_r50-d8.py', '../_base_/datasets/pascal_context.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_80k.py' 4 | ] 5 | model = dict( 6 | decode_head=dict(num_classes=60), 7 | test_cfg=dict(mode='slide', crop_size=(480, 480), stride=(320, 320))) 8 | optimizer = dict(type='SGD', lr=0.004, momentum=0.9, weight_decay=0.0001) 9 | -------------------------------------------------------------------------------- /Pytorch/configs/upernet/upernet_r50_769x769_40k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/upernet_r50.py', 3 | '../_base_/datasets/cityscapes_769x769.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_40k.py' 5 | ] 6 | model = dict( 7 | decode_head=dict(align_corners=True), 8 | auxiliary_head=dict(align_corners=True), 9 | test_cfg=dict(mode='slide', crop_size=(769, 769), stride=(513, 513))) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/upernet/upernet_r50_769x769_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/upernet_r50.py', 3 | '../_base_/datasets/cityscapes_769x769.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_80k.py' 5 | ] 6 | model = dict( 7 | decode_head=dict(align_corners=True), 8 | auxiliary_head=dict(align_corners=True), 9 | test_cfg=dict(mode='slide', crop_size=(769, 769), stride=(513, 513))) 10 | -------------------------------------------------------------------------------- /Pytorch/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 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .inverted_residual import InvertedResidual, InvertedResidualV3 2 | from .make_divisible import make_divisible 3 | from .res_layer import ResLayer 4 | from .self_attention_block import SelfAttentionBlock 5 | from .up_conv_block import UpConvBlock 6 | 7 | __all__ = [ 8 | 'ResLayer', 'SelfAttentionBlock', 'make_divisible', 'InvertedResidual', 9 | 'UpConvBlock', 'InvertedResidualV3' 10 | ] 11 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r50-d8_769x769_40k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/deeplabv3_r50-d8.py', 3 | '../_base_/datasets/cityscapes_769x769.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_40k.py' 5 | ] 6 | model = dict( 7 | decode_head=dict(align_corners=True), 8 | auxiliary_head=dict(align_corners=True), 9 | test_cfg=dict(mode='slide', crop_size=(769, 769), stride=(513, 513))) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r50-d8_769x769_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/deeplabv3_r50-d8.py', 3 | '../_base_/datasets/cityscapes_769x769.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_80k.py' 5 | ] 6 | model = dict( 7 | decode_head=dict(align_corners=True), 8 | auxiliary_head=dict(align_corners=True), 9 | test_cfg=dict(mode='slide', crop_size=(769, 769), stride=(513, 513))) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/nonlocal_net/nonlocal_r50-d8_769x769_40k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/nonlocal_r50-d8.py', 3 | '../_base_/datasets/cityscapes_769x769.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_40k.py' 5 | ] 6 | model = dict( 7 | decode_head=dict(align_corners=True), 8 | auxiliary_head=dict(align_corners=True), 9 | test_cfg=dict(mode='slide', crop_size=(769, 769), stride=(513, 513))) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/nonlocal_net/nonlocal_r50-d8_769x769_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/nonlocal_r50-d8.py', 3 | '../_base_/datasets/cityscapes_769x769.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_80k.py' 5 | ] 6 | model = dict( 7 | decode_head=dict(align_corners=True), 8 | auxiliary_head=dict(align_corners=True), 9 | test_cfg=dict(mode='slide', crop_size=(769, 769), stride=(513, 513))) 10 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/schedules/schedule_120k.py: -------------------------------------------------------------------------------- 1 | # optimizer 2 | optimizer = dict(type='SGD', lr=0.007, momentum=0.9, weight_decay=0.0005) 3 | optimizer_config = dict() 4 | # learning policy 5 | lr_config = dict(policy='poly', power=0.9, min_lr=5e-5, by_epoch=False) 6 | # runtime settings 7 | runner = dict(type='IterBasedRunner', max_iters=120000) 8 | checkpoint_config = dict(by_epoch=False, interval=8000) 9 | evaluation = dict(interval=8000, metric='mIoU') 10 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/schedules/schedule_60k.py: -------------------------------------------------------------------------------- 1 | # optimizer 2 | optimizer = dict(type='SGD', lr=0.007, momentum=0.9, weight_decay=0.00005) 3 | optimizer_config = dict() 4 | # learning policy 5 | lr_config = dict(policy='poly', power=0.9, min_lr=5e-5, by_epoch=False) 6 | # runtime settings 7 | runner = dict(type='IterBasedRunner', max_iters=60000) 8 | checkpoint_config = dict(by_epoch=False, interval=6000) 9 | evaluation = dict(interval=6000, metric='mIoU') 10 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/schedules/schedule_80k.py: -------------------------------------------------------------------------------- 1 | # optimizer 2 | optimizer = dict(type='SGD', lr=0.01, momentum=0.9, weight_decay=0.00005) 3 | optimizer_config = dict() 4 | # learning policy 5 | lr_config = dict(policy='poly', power=0.9, min_lr=5e-5, by_epoch=False) 6 | # runtime settings 7 | runner = dict(type='IterBasedRunner', max_iters=80000) 8 | checkpoint_config = dict(by_epoch=False, interval=8000) 9 | evaluation = dict(interval=8000, metric='mIoU') 10 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/schedules/schedule_160k.py: -------------------------------------------------------------------------------- 1 | # optimizer 2 | optimizer = dict(type='SGD', lr=0.007, momentum=0.9, weight_decay=0.00005) 3 | optimizer_config = dict() 4 | # learning policy 5 | lr_config = dict(policy='poly', power=0.9, min_lr=5e-5, by_epoch=False) 6 | # runtime settings 7 | runner = dict(type='IterBasedRunner', max_iters=160000) 8 | checkpoint_config = dict(by_epoch=False, interval=16000) 9 | evaluation = dict(interval=16000, metric='mIoU') 10 | -------------------------------------------------------------------------------- /Pytorch/mmseg/core/utils/misc.py: -------------------------------------------------------------------------------- 1 | def add_prefix(inputs, prefix): 2 | """Add prefix for dict. 3 | 4 | Args: 5 | inputs (dict): The input dict with str keys. 6 | prefix (str): The prefix to add. 7 | 8 | Returns: 9 | 10 | dict: The dict with keys updated with ``prefix``. 11 | """ 12 | 13 | outputs = dict() 14 | for name, value in inputs.items(): 15 | outputs[f'{prefix}.{name}'] = value 16 | 17 | return outputs 18 | -------------------------------------------------------------------------------- /Pytorch/tests/test_utils/test_make_divisible.py: -------------------------------------------------------------------------------- 1 | from mmseg.models.utils import make_divisible 2 | 3 | 4 | def test_make_divisible(): 5 | # test with min_value = None 6 | assert make_divisible(10, 4) == 12 7 | assert make_divisible(9, 4) == 12 8 | assert make_divisible(1, 4) == 4 9 | 10 | # test with min_value = 8 11 | assert make_divisible(10, 4, 8) == 12 12 | assert make_divisible(9, 4, 8) == 12 13 | assert make_divisible(1, 4, 8) == 8 14 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r101-d16-mg124_512x1024_40k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_512x1024_40k_cityscapes.py' 2 | model = dict( 3 | pretrained='open-mmlab://resnet101_v1c', 4 | backbone=dict( 5 | depth=101, 6 | dilations=(1, 1, 1, 2), 7 | strides=(1, 2, 2, 1), 8 | multi_grid=(1, 2, 4)), 9 | decode_head=dict( 10 | dilations=(1, 6, 12, 18), 11 | sampler=dict(type='OHEMPixelSampler', min_kept=100000))) 12 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r101-d16-mg124_512x1024_80k_cityscapes.py: -------------------------------------------------------------------------------- 1 | _base_ = './deeplabv3_r50-d8_512x1024_80k_cityscapes.py' 2 | model = dict( 3 | pretrained='open-mmlab://resnet101_v1c', 4 | backbone=dict( 5 | depth=101, 6 | dilations=(1, 1, 1, 2), 7 | strides=(1, 2, 2, 1), 8 | multi_grid=(1, 2, 4)), 9 | decode_head=dict( 10 | dilations=(1, 6, 12, 18), 11 | sampler=dict(type='OHEMPixelSampler', min_kept=100000))) 12 | -------------------------------------------------------------------------------- /Pytorch/setup.cfg: -------------------------------------------------------------------------------- 1 | [yapf] 2 | based_on_style = pep8 3 | blank_line_before_nested_class_or_def = true 4 | split_before_expression_after_opening_paren = true 5 | 6 | [isort] 7 | line_length = 79 8 | multi_line_output = 0 9 | known_standard_library = setuptools 10 | known_first_party = mmseg 11 | known_third_party = PIL,cityscapesscripts,cv2,detail,matplotlib,mmcv,numpy,onnxruntime,oss2,pytest,scipy,terminaltables,torch 12 | no_lines_before = STDLIB,LOCALFOLDER 13 | default_section = THIRDPARTY 14 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r50-d8_480x480_40k_pascal_context.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/deeplabv3_r50-d8.py', 3 | '../_base_/datasets/pascal_context.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_40k.py' 5 | ] 6 | model = dict( 7 | decode_head=dict(num_classes=60), 8 | auxiliary_head=dict(num_classes=60), 9 | test_cfg=dict(mode='slide', crop_size=(480, 480), stride=(320, 320))) 10 | optimizer = dict(type='SGD', lr=0.004, momentum=0.9, weight_decay=0.0001) 11 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3/deeplabv3_r50-d8_480x480_80k_pascal_context.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/deeplabv3_r50-d8.py', 3 | '../_base_/datasets/pascal_context.py', '../_base_/default_runtime.py', 4 | '../_base_/schedules/schedule_80k.py' 5 | ] 6 | model = dict( 7 | decode_head=dict(num_classes=60), 8 | auxiliary_head=dict(num_classes=60), 9 | test_cfg=dict(mode='slide', crop_size=(480, 480), stride=(320, 320))) 10 | optimizer = dict(type='SGD', lr=0.004, momentum=0.9, weight_decay=0.0001) 11 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/backbones/__init__.py: -------------------------------------------------------------------------------- 1 | from .cgnet import CGNet 2 | from .fast_scnn import FastSCNN 3 | from .hrnet import HRNet 4 | from .mobilenet_v2 import MobileNetV2 5 | from .mobilenet_v3 import MobileNetV3 6 | from .resnest import ResNeSt 7 | from .resnet import ResNet, ResNetV1c, ResNetV1d 8 | from .resnext import ResNeXt 9 | from .unet import UNet 10 | 11 | __all__ = [ 12 | 'ResNet', 'ResNetV1c', 'ResNetV1d', 'ResNeXt', 'HRNet', 'FastSCNN', 13 | 'ResNeSt', 'MobileNetV2', 'UNet', 'CGNet', 'MobileNetV3' 14 | ] 15 | -------------------------------------------------------------------------------- /Pytorch/mmseg/utils/collect_env.py: -------------------------------------------------------------------------------- 1 | from mmcv.utils import collect_env as collect_base_env 2 | from mmcv.utils import get_git_hash 3 | 4 | import mmseg 5 | 6 | 7 | def collect_env(): 8 | """Collect the information of the running environments.""" 9 | env_info = collect_base_env() 10 | env_info['MMSegmentation'] = f'{mmseg.__version__}+{get_git_hash()[:7]}' 11 | 12 | return env_info 13 | 14 | 15 | if __name__ == '__main__': 16 | for name, val in collect_env().items(): 17 | print('{}: {}'.format(name, val)) 18 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .backbones import * # noqa: F401,F403 2 | from .builder import (BACKBONES, HEADS, LOSSES, SEGMENTORS, build_backbone, 3 | 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 | 9 | __all__ = [ 10 | 'BACKBONES', 'HEADS', 'LOSSES', 'SEGMENTORS', 'build_backbone', 11 | 'build_head', 'build_loss', 'build_segmentor' 12 | ] 13 | -------------------------------------------------------------------------------- /Pytorch/mmseg/version.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Open-MMLab. All rights reserved. 2 | 3 | __version__ = '0.11.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 | -------------------------------------------------------------------------------- /Pytorch/tests/test_models/test_necks.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from mmseg.models import FPN 4 | 5 | 6 | def test_fpn(): 7 | in_channels = [256, 512, 1024, 2048] 8 | inputs = [ 9 | torch.randn(1, c, 56 // 2**i, 56 // 2**i) 10 | for i, c in enumerate(in_channels) 11 | ] 12 | 13 | fpn = FPN(in_channels, 256, len(in_channels)) 14 | outputs = fpn(inputs) 15 | assert outputs[0].shape == torch.Size([1, 256, 56, 56]) 16 | assert outputs[1].shape == torch.Size([1, 256, 28, 28]) 17 | assert outputs[2].shape == torch.Size([1, 256, 14, 14]) 18 | assert outputs[3].shape == torch.Size([1, 256, 7, 7]) 19 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3plus/deeplabv3plus_r101-d8_480x480_160k_LIP_hiera_triplet.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/deeplabv3plus_r50-d8_vd_contrast.py', '../_base_/datasets/LIP.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_160k.py' 4 | ] 5 | model = dict(pretrained='https://assets-1257038460.cos.ap-beijing.myqcloud.com/resnet101_v1d.pth', backbone=dict(depth=101), 6 | decode_head=dict(num_classes=25,loss_decode=dict(type='RMIHieraTripletLoss',num_classes=20, loss_weight=1.0)), 7 | auxiliary_head=dict(num_classes=20), 8 | test_cfg=dict(mode='whole', is_hiera=True, hiera_num_classes=5)) 9 | -------------------------------------------------------------------------------- /Pytorch/tools/slurm_train.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -x 4 | 5 | PARTITION=$1 6 | JOB_NAME=$2 7 | CONFIG=$3 8 | GPUS=${GPUS:-4} 9 | GPUS_PER_NODE=${GPUS_PER_NODE:-4} 10 | CPUS_PER_TASK=${CPUS_PER_TASK:-5} 11 | SRUN_ARGS=${SRUN_ARGS:-""} 12 | PY_ARGS=${@:4} 13 | 14 | PYTHONPATH="$(dirname $0)/..":$PYTHONPATH \ 15 | srun -p ${PARTITION} \ 16 | --job-name=${JOB_NAME} \ 17 | --gres=gpu:${GPUS_PER_NODE} \ 18 | --ntasks=${GPUS} \ 19 | --ntasks-per-node=${GPUS_PER_NODE} \ 20 | --cpus-per-task=${CPUS_PER_TASK} \ 21 | --kill-on-bad-exit=1 \ 22 | ${SRUN_ARGS} \ 23 | python -u tools/train.py ${CONFIG} --launcher="slurm" ${PY_ARGS} 24 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3plus/deeplabv3plus_r101-d8_512x1024_80k_cityscapes_hiera_triplet.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/deeplabv3plus_r50-d8_vd_contrast.py', '../_base_/datasets/cityscapes.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_80k.py' 4 | ] 5 | model = dict(pretrained='https://assets-1257038460.cos.ap-beijing.myqcloud.com/resnet101_v1d.pth', backbone=dict(depth=101), 6 | decode_head=dict(num_classes=26,loss_decode=dict(type='HieraTripletLossCityscape',num_classes=19, loss_weight=1.0)), 7 | auxiliary_head=dict(num_classes=19), 8 | test_cfg=dict(mode='whole', is_hiera=True, hiera_num_classes=7)) 9 | -------------------------------------------------------------------------------- /Pytorch/configs/deeplabv3plus/deeplabv3plus_r101-d8_480x480_60k_pascal_person_part_hiera_triplet.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/deeplabv3plus_r50-d8_vd_contrast.py', '../_base_/datasets/pascal_person_part.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_60k.py' 4 | ] 5 | model = dict(pretrained='https://assets-1257038460.cos.ap-beijing.myqcloud.com/resnet101_v1d.pth', backbone=dict(depth=101), 6 | decode_head=dict(num_classes=12,loss_decode=dict(type='RMIHieraTripletLoss',num_classes=7, loss_weight=1.0)), 7 | auxiliary_head=dict(num_classes=7), 8 | test_cfg=dict(mode='whole', is_hiera=True, hiera_num_classes=5)) 9 | -------------------------------------------------------------------------------- /Pytorch/tools/slurm_test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -x 4 | 5 | PARTITION=$1 6 | JOB_NAME=$2 7 | CONFIG=$3 8 | CHECKPOINT=$4 9 | GPUS=${GPUS:-4} 10 | GPUS_PER_NODE=${GPUS_PER_NODE:-4} 11 | CPUS_PER_TASK=${CPUS_PER_TASK:-5} 12 | PY_ARGS=${@:5} 13 | SRUN_ARGS=${SRUN_ARGS:-""} 14 | 15 | PYTHONPATH="$(dirname $0)/..":$PYTHONPATH \ 16 | srun -p ${PARTITION} \ 17 | --job-name=${JOB_NAME} \ 18 | --gres=gpu:${GPUS_PER_NODE} \ 19 | --ntasks=${GPUS} \ 20 | --ntasks-per-node=${GPUS_PER_NODE} \ 21 | --cpus-per-task=${CPUS_PER_TASK} \ 22 | --kill-on-bad-exit=1 \ 23 | ${SRUN_ARGS} \ 24 | python -u tools/test.py ${CONFIG} ${CHECKPOINT} --launcher="slurm" ${PY_ARGS} 25 | -------------------------------------------------------------------------------- /Pytorch/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 .lovasz_loss import LovaszLoss 5 | from .utils import reduce_loss, weight_reduce_loss, weighted_loss 6 | from .rmi_hiera_triplet_loss import RMIHieraTripletLoss 7 | from .hiera_triplet_loss_cityscape import HieraTripletLossCityscape 8 | 9 | __all__ = [ 10 | 'accuracy', 'Accuracy', 'cross_entropy', 'binary_cross_entropy', 11 | 'mask_cross_entropy', 'CrossEntropyLoss', 'reduce_loss', 12 | 'weight_reduce_loss', 'weighted_loss', 'LovaszLoss', 'RMIHieraTripletLoss', 'HieraTripletLossCityscape' 13 | ] 14 | -------------------------------------------------------------------------------- /Pytorch/tools/print_config.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | from mmcv import Config, DictAction 4 | 5 | 6 | def parse_args(): 7 | parser = argparse.ArgumentParser(description='Print the whole config') 8 | parser.add_argument('config', help='config file path') 9 | parser.add_argument( 10 | '--options', nargs='+', action=DictAction, help='arguments in dict') 11 | args = parser.parse_args() 12 | 13 | return args 14 | 15 | 16 | def main(): 17 | args = parse_args() 18 | 19 | cfg = Config.fromfile(args.config) 20 | if args.options is not None: 21 | cfg.merge_from_dict(args.options) 22 | print(f'Config:\n{cfg.pretty_text}') 23 | # dump config 24 | cfg.dump('example.py') 25 | 26 | 27 | if __name__ == '__main__': 28 | main() 29 | -------------------------------------------------------------------------------- /Pytorch/mmseg/datasets/__init__.py: -------------------------------------------------------------------------------- 1 | from .ade import ADE20KDataset 2 | from .builder import DATASETS, PIPELINES, build_dataloader, build_dataset 3 | from .chase_db1 import ChaseDB1Dataset 4 | from .cityscapes import CityscapesDataset 5 | from .custom import CustomDataset 6 | from .dataset_wrappers import ConcatDataset, RepeatDataset 7 | from .drive import DRIVEDataset 8 | from .hrf import HRFDataset 9 | from .pascal_context import PascalContextDataset 10 | from .stare import STAREDataset 11 | from .voc import PascalVOCDataset 12 | 13 | __all__ = [ 14 | 'CustomDataset', 'build_dataloader', 'ConcatDataset', 'RepeatDataset', 15 | 'DATASETS', 'build_dataset', 'PIPELINES', 'CityscapesDataset', 16 | 'PascalVOCDataset', 'ADE20KDataset', 'PascalContextDataset', 17 | 'ChaseDB1Dataset', 'DRIVEDataset', 'HRFDataset', 'STAREDataset' 18 | ] 19 | -------------------------------------------------------------------------------- /Pytorch/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG PYTORCH="1.6.0" 2 | ARG CUDA="10.1" 3 | ARG CUDNN="7" 4 | 5 | FROM pytorch/pytorch:${PYTORCH}-cuda${CUDA}-cudnn${CUDNN}-devel 6 | 7 | ENV TORCH_CUDA_ARCH_LIST="6.0 6.1 7.0+PTX" 8 | ENV TORCH_NVCC_FLAGS="-Xfatbin -compress-all" 9 | ENV CMAKE_PREFIX_PATH="$(dirname $(which conda))/../" 10 | 11 | RUN apt-get update && apt-get install -y git ninja-build libglib2.0-0 libsm6 libxrender-dev libxext6 \ 12 | && apt-get clean \ 13 | && rm -rf /var/lib/apt/lists/* 14 | 15 | # Install mmsegmentation 16 | RUN conda clean --all 17 | 18 | RUN pip install mmcv-full==latest+torch1.6.0+cu101 -f https://download.openmmlab.com/mmcv/dist/index.html 19 | RUN git clone https://github.com/open-mmlab/mmsegmenation.git /mmsegmentation 20 | WORKDIR /mmsegmentation 21 | RUN pip install -r requirements/build.txt 22 | RUN pip install --no-cache-dir -e . 23 | -------------------------------------------------------------------------------- /Pytorch/mmseg/datasets/hrf.py: -------------------------------------------------------------------------------- 1 | import os.path as osp 2 | 3 | from .builder import DATASETS 4 | from .custom import CustomDataset 5 | 6 | 7 | @DATASETS.register_module() 8 | class HRFDataset(CustomDataset): 9 | """HRF dataset. 10 | 11 | In segmentation map annotation for HRF, 0 stands for background, which is 12 | included in 2 categories. ``reduce_zero_label`` is fixed to False. The 13 | ``img_suffix`` is fixed to '.png' and ``seg_map_suffix`` is fixed to 14 | '.png'. 15 | """ 16 | 17 | CLASSES = ('background', 'vessel') 18 | 19 | PALETTE = [[120, 120, 120], [6, 230, 230]] 20 | 21 | def __init__(self, **kwargs): 22 | super(HRFDataset, self).__init__( 23 | img_suffix='.png', 24 | seg_map_suffix='.png', 25 | reduce_zero_label=False, 26 | **kwargs) 27 | assert osp.exists(self.img_dir) 28 | -------------------------------------------------------------------------------- /Pytorch/mmseg/datasets/stare.py: -------------------------------------------------------------------------------- 1 | import os.path as osp 2 | 3 | from .builder import DATASETS 4 | from .custom import CustomDataset 5 | 6 | 7 | @DATASETS.register_module() 8 | class STAREDataset(CustomDataset): 9 | """STARE dataset. 10 | 11 | In segmentation map annotation for STARE, 0 stands for background, which is 12 | included in 2 categories. ``reduce_zero_label`` is fixed to False. The 13 | ``img_suffix`` is fixed to '.png' and ``seg_map_suffix`` is fixed to 14 | '.ah.png'. 15 | """ 16 | 17 | CLASSES = ('background', 'vessel') 18 | 19 | PALETTE = [[120, 120, 120], [6, 230, 230]] 20 | 21 | def __init__(self, **kwargs): 22 | super(STAREDataset, self).__init__( 23 | img_suffix='.png', 24 | seg_map_suffix='.ah.png', 25 | reduce_zero_label=False, 26 | **kwargs) 27 | assert osp.exists(self.img_dir) 28 | -------------------------------------------------------------------------------- /Pytorch/mmseg/datasets/drive.py: -------------------------------------------------------------------------------- 1 | import os.path as osp 2 | 3 | from .builder import DATASETS 4 | from .custom import CustomDataset 5 | 6 | 7 | @DATASETS.register_module() 8 | class DRIVEDataset(CustomDataset): 9 | """DRIVE dataset. 10 | 11 | In segmentation map annotation for DRIVE, 0 stands for background, which is 12 | included in 2 categories. ``reduce_zero_label`` is fixed to False. The 13 | ``img_suffix`` is fixed to '.png' and ``seg_map_suffix`` is fixed to 14 | '_manual1.png'. 15 | """ 16 | 17 | CLASSES = ('background', 'vessel') 18 | 19 | PALETTE = [[120, 120, 120], [6, 230, 230]] 20 | 21 | def __init__(self, **kwargs): 22 | super(DRIVEDataset, self).__init__( 23 | img_suffix='.png', 24 | seg_map_suffix='_manual1.png', 25 | reduce_zero_label=False, 26 | **kwargs) 27 | assert osp.exists(self.img_dir) 28 | -------------------------------------------------------------------------------- /Pytorch/mmseg/datasets/chase_db1.py: -------------------------------------------------------------------------------- 1 | import os.path as osp 2 | 3 | from .builder import DATASETS 4 | from .custom import CustomDataset 5 | 6 | 7 | @DATASETS.register_module() 8 | class ChaseDB1Dataset(CustomDataset): 9 | """Chase_db1 dataset. 10 | 11 | In segmentation map annotation for Chase_db1, 0 stands for background, 12 | which is included in 2 categories. ``reduce_zero_label`` is fixed to False. 13 | The ``img_suffix`` is fixed to '.png' and ``seg_map_suffix`` is fixed to 14 | '_1stHO.png'. 15 | """ 16 | 17 | CLASSES = ('background', 'vessel') 18 | 19 | PALETTE = [[120, 120, 120], [6, 230, 230]] 20 | 21 | def __init__(self, **kwargs): 22 | super(ChaseDB1Dataset, self).__init__( 23 | img_suffix='.png', 24 | seg_map_suffix='_1stHO.png', 25 | reduce_zero_label=False, 26 | **kwargs) 27 | assert osp.exists(self.img_dir) 28 | -------------------------------------------------------------------------------- /Pytorch/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, RandomSwapFlip, 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', 'RandomSwapFlip', 'Pad', 'RandomCrop', 14 | 'Normalize', 'SegRescale', 'PhotoMetricDistortion', 'RandomRotate', 15 | 'AdjustGamma', 'CLAHE', 'Rerange', 'RGB2Gray' 16 | ] 17 | -------------------------------------------------------------------------------- /Pytorch/mmseg/__init__.py: -------------------------------------------------------------------------------- 1 | import mmcv 2 | 3 | from .version import __version__, version_info 4 | 5 | MMCV_MIN = '1.1.4' 6 | MMCV_MAX = '1.3.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 | -------------------------------------------------------------------------------- /Pytorch/mmseg/utils/logger.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from mmcv.utils import get_logger 4 | 5 | 6 | def get_root_logger(log_file=None, log_level=logging.INFO): 7 | """Get the root logger. 8 | 9 | The logger will be initialized if it has not been initialized. By default a 10 | StreamHandler will be added. If `log_file` is specified, a FileHandler will 11 | also be added. The name of the root logger is the top-level package name, 12 | e.g., "mmseg". 13 | 14 | Args: 15 | log_file (str | None): The log filename. If specified, a FileHandler 16 | will be added to the root logger. 17 | log_level (int): The root logger level. Note that only the process of 18 | rank 0 is affected, while other processes will set the level to 19 | "Error" and be silent most of the time. 20 | 21 | Returns: 22 | logging.Logger: The root logger. 23 | """ 24 | 25 | logger = get_logger(name='mmseg', log_file=log_file, log_level=log_level) 26 | 27 | return logger 28 | -------------------------------------------------------------------------------- /Pytorch/tests/test_inference.py: -------------------------------------------------------------------------------- 1 | import os.path as osp 2 | 3 | import mmcv 4 | 5 | from mmseg.apis import inference_segmentor, init_segmentor 6 | 7 | 8 | def test_test_time_augmentation_on_cpu(): 9 | config_file = 'configs/pspnet/pspnet_r50-d8_512x1024_40k_cityscapes.py' 10 | config = mmcv.Config.fromfile(config_file) 11 | 12 | # Remove pretrain model download for testing 13 | config.model.pretrained = None 14 | # Replace SyncBN with BN to inference on CPU 15 | norm_cfg = dict(type='BN', requires_grad=True) 16 | config.model.backbone.norm_cfg = norm_cfg 17 | config.model.decode_head.norm_cfg = norm_cfg 18 | config.model.auxiliary_head.norm_cfg = norm_cfg 19 | 20 | # Enable test time augmentation 21 | config.data.test.pipeline[1].flip = True 22 | 23 | checkpoint_file = None 24 | model = init_segmentor(config, checkpoint_file, device='cpu') 25 | 26 | img = mmcv.imread( 27 | osp.join(osp.dirname(__file__), 'data/color.jpg'), 'color') 28 | result = inference_segmentor(model, img) 29 | assert result[0].shape == (288, 512) 30 | -------------------------------------------------------------------------------- /Pytorch/configs/point_rend/pointrend_r50_512x512_160k_ade20k.py: -------------------------------------------------------------------------------- 1 | _base_ = [ 2 | '../_base_/models/pointrend_r50.py', '../_base_/datasets/ade20k.py', 3 | '../_base_/default_runtime.py', '../_base_/schedules/schedule_160k.py' 4 | ] 5 | norm_cfg = dict(type='SyncBN', requires_grad=True) 6 | model = dict(decode_head=[ 7 | dict( 8 | type='FPNHead', 9 | in_channels=[256, 256, 256, 256], 10 | in_index=[0, 1, 2, 3], 11 | feature_strides=[4, 8, 16, 32], 12 | channels=128, 13 | dropout_ratio=-1, 14 | num_classes=150, 15 | norm_cfg=norm_cfg, 16 | align_corners=False, 17 | loss_decode=dict( 18 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 19 | dict( 20 | type='PointHead', 21 | in_channels=[256], 22 | in_index=[0], 23 | channels=256, 24 | num_fcs=3, 25 | coarse_pred_each_layer=True, 26 | dropout_ratio=-1, 27 | num_classes=150, 28 | align_corners=False, 29 | loss_decode=dict( 30 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)) 31 | ]) 32 | lr_config = dict(warmup='linear', warmup_iters=200) 33 | -------------------------------------------------------------------------------- /Pytorch/tools/publish_model.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import subprocess 3 | 4 | import torch 5 | 6 | 7 | def parse_args(): 8 | parser = argparse.ArgumentParser( 9 | description='Process a checkpoint to be published') 10 | parser.add_argument('in_file', help='input checkpoint filename') 11 | parser.add_argument('out_file', help='output checkpoint filename') 12 | args = parser.parse_args() 13 | return args 14 | 15 | 16 | def process_checkpoint(in_file, out_file): 17 | checkpoint = torch.load(in_file, map_location='cpu') 18 | # remove optimizer for smaller file size 19 | if 'optimizer' in checkpoint: 20 | del checkpoint['optimizer'] 21 | # if it is necessary to remove some sensitive data in checkpoint['meta'], 22 | # add the code here. 23 | torch.save(checkpoint, out_file) 24 | sha = subprocess.check_output(['sha256sum', out_file]).decode() 25 | final_file = out_file.rstrip('.pth') + '-{}.pth'.format(sha[:8]) 26 | subprocess.Popen(['mv', out_file, final_file]) 27 | 28 | 29 | def main(): 30 | args = parse_args() 31 | process_checkpoint(args.in_file, args.out_file) 32 | 33 | 34 | if __name__ == '__main__': 35 | main() 36 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/models/fpn_r50.py: -------------------------------------------------------------------------------- 1 | # model settings 2 | norm_cfg = dict(type='SyncBN', requires_grad=True) 3 | model = dict( 4 | type='EncoderDecoder', 5 | pretrained='open-mmlab://resnet50_v1c', 6 | backbone=dict( 7 | type='ResNetV1c', 8 | depth=50, 9 | num_stages=4, 10 | out_indices=(0, 1, 2, 3), 11 | dilations=(1, 1, 1, 1), 12 | strides=(1, 2, 2, 2), 13 | norm_cfg=norm_cfg, 14 | norm_eval=False, 15 | style='pytorch', 16 | contract_dilation=True), 17 | neck=dict( 18 | type='FPN', 19 | in_channels=[256, 512, 1024, 2048], 20 | out_channels=256, 21 | num_outs=4), 22 | decode_head=dict( 23 | type='FPNHead', 24 | in_channels=[256, 256, 256, 256], 25 | in_index=[0, 1, 2, 3], 26 | feature_strides=[4, 8, 16, 32], 27 | channels=128, 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 | -------------------------------------------------------------------------------- /Pytorch/mmseg/datasets/voc.py: -------------------------------------------------------------------------------- 1 | import os.path as osp 2 | 3 | from .builder import DATASETS 4 | from .custom import CustomDataset 5 | 6 | 7 | @DATASETS.register_module() 8 | class PascalVOCDataset(CustomDataset): 9 | """Pascal VOC dataset. 10 | 11 | Args: 12 | split (str): Split txt file for Pascal VOC. 13 | """ 14 | 15 | CLASSES = ('background', 'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 16 | 'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 17 | 'horse', 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 18 | 'train', 'tvmonitor') 19 | 20 | PALETTE = [[0, 0, 0], [128, 0, 0], [0, 128, 0], [128, 128, 0], [0, 0, 128], 21 | [128, 0, 128], [0, 128, 128], [128, 128, 128], [64, 0, 0], 22 | [192, 0, 0], [64, 128, 0], [192, 128, 0], [64, 0, 128], 23 | [192, 0, 128], [64, 128, 128], [192, 128, 128], [0, 64, 0], 24 | [128, 64, 0], [0, 192, 0], [128, 192, 0], [0, 64, 128]] 25 | 26 | def __init__(self, split, **kwargs): 27 | super(PascalVOCDataset, self).__init__( 28 | img_suffix='.jpg', seg_map_suffix='.png', split=split, **kwargs) 29 | assert osp.exists(self.img_dir) and self.split is not None 30 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/decode_heads/__init__.py: -------------------------------------------------------------------------------- 1 | from .ann_head import ANNHead 2 | from .apc_head import APCHead 3 | from .aspp_head import ASPPHead 4 | from .cc_head import CCHead 5 | from .da_head import DAHead 6 | from .dm_head import DMHead 7 | from .dnl_head import DNLHead 8 | from .ema_head import EMAHead 9 | from .enc_head import EncHead 10 | from .fcn_head import FCNHead 11 | from .fpn_head import FPNHead 12 | from .gc_head import GCHead 13 | from .lraspp_head import LRASPPHead 14 | from .nl_head import NLHead 15 | from .point_head import PointHead 16 | from .psa_head import PSAHead 17 | from .psp_head import PSPHead 18 | from .sep_aspp_head import DepthwiseSeparableASPPHead 19 | from .sep_fcn_head import DepthwiseSeparableFCNHead 20 | from .uper_head import UPerHead 21 | from .mla_head import MLAHead 22 | from .fcn_contrast_head import FCNContrastHead 23 | from .sep_aspp_contrast_head import DepthwiseSeparableASPPContrastHead 24 | 25 | __all__ = [ 26 | 'FCNHead', 'PSPHead', 'ASPPHead', 'PSAHead', 'NLHead', 'GCHead', 'CCHead', 27 | 'UPerHead', 'DepthwiseSeparableASPPHead', 'ANNHead', 'DAHead', 'PointHead', 28 | 'EncHead', 'DepthwiseSeparableFCNHead', 'FPNHead', 'EMAHead', 'DNLHead', 29 | 'APCHead', 'DMHead', 'LRASPPHead', 'MLAHead', 'FCNContrastHead', 'DepthwiseSeparableASPPContrastHead' 30 | ] 31 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/utils/make_divisible.py: -------------------------------------------------------------------------------- 1 | def make_divisible(value, divisor, min_value=None, min_ratio=0.9): 2 | """Make divisible function. 3 | 4 | This function rounds the channel number to the nearest value that can be 5 | divisible by the divisor. It is taken from the original tf repo. It ensures 6 | that all layers have a channel number that is divisible by divisor. It can 7 | be seen here: https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py # noqa 8 | 9 | Args: 10 | value (int): The original channel number. 11 | divisor (int): The divisor to fully divide the channel number. 12 | min_value (int): The minimum value of the output channel. 13 | Default: None, means that the minimum value equal to the divisor. 14 | min_ratio (float): The minimum ratio of the rounded channel number to 15 | the original channel number. Default: 0.9. 16 | 17 | Returns: 18 | int: The modified output channel number. 19 | """ 20 | 21 | if min_value is None: 22 | min_value = divisor 23 | new_value = max(min_value, int(value + divisor / 2) // divisor * divisor) 24 | # Make sure that round down does not go down by more than (1-min_ratio). 25 | if new_value < min_ratio * value: 26 | new_value += divisor 27 | return new_value 28 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/decode_heads/cc_head.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from ..builder import HEADS 4 | from .fcn_head import FCNHead 5 | 6 | try: 7 | from mmcv.ops import CrissCrossAttention 8 | except ModuleNotFoundError: 9 | CrissCrossAttention = None 10 | 11 | 12 | @HEADS.register_module() 13 | class CCHead(FCNHead): 14 | """CCNet: Criss-Cross Attention for Semantic Segmentation. 15 | 16 | This head is the implementation of `CCNet 17 | `_. 18 | 19 | Args: 20 | recurrence (int): Number of recurrence of Criss Cross Attention 21 | module. Default: 2. 22 | """ 23 | 24 | def __init__(self, recurrence=2, **kwargs): 25 | if CrissCrossAttention is None: 26 | raise RuntimeError('Please install mmcv-full for ' 27 | 'CrissCrossAttention ops') 28 | super(CCHead, self).__init__(num_convs=2, **kwargs) 29 | self.recurrence = recurrence 30 | self.cca = CrissCrossAttention(self.channels) 31 | 32 | def forward(self, inputs): 33 | """Forward function.""" 34 | x = self._transform_inputs(inputs) 35 | output = self.convs[0](x) 36 | for _ in range(self.recurrence): 37 | output = self.cca(output) 38 | output = self.convs[1](output) 39 | if self.concat_input: 40 | output = self.conv_cat(torch.cat([x, output], dim=1)) 41 | output = self.cls_seg(output) 42 | return output 43 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/models/deeplabv3_r50-d8.py: -------------------------------------------------------------------------------- 1 | # model settings 2 | norm_cfg = dict(type='SyncBN', requires_grad=True) 3 | model = dict( 4 | type='EncoderDecoder', 5 | pretrained='open-mmlab://resnet50_v1c', 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='ASPPHead', 19 | in_channels=2048, 20 | in_index=3, 21 | channels=512, 22 | dilations=(1, 12, 24, 36), 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 | auxiliary_head=dict( 30 | type='FCNHead', 31 | in_channels=1024, 32 | in_index=2, 33 | channels=256, 34 | num_convs=1, 35 | concat_input=False, 36 | dropout_ratio=0.1, 37 | num_classes=19, 38 | norm_cfg=norm_cfg, 39 | align_corners=False, 40 | loss_decode=dict( 41 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=0.4)), 42 | # model training and testing settings 43 | train_cfg=dict(), 44 | test_cfg=dict(mode='whole')) 45 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/models/fcn_r50-d8.py: -------------------------------------------------------------------------------- 1 | # model settings 2 | norm_cfg = dict(type='SyncBN', requires_grad=True) 3 | model = dict( 4 | type='EncoderDecoder', 5 | pretrained='open-mmlab://resnet50_v1c', 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='FCNHead', 19 | in_channels=2048, 20 | in_index=3, 21 | channels=512, 22 | num_convs=2, 23 | concat_input=True, 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 | auxiliary_head=dict( 31 | type='FCNHead', 32 | in_channels=1024, 33 | in_index=2, 34 | channels=256, 35 | num_convs=1, 36 | concat_input=False, 37 | dropout_ratio=0.1, 38 | num_classes=19, 39 | norm_cfg=norm_cfg, 40 | align_corners=False, 41 | loss_decode=dict( 42 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=0.4)), 43 | # model training and testing settings 44 | train_cfg=dict(), 45 | test_cfg=dict(mode='whole')) 46 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/models/upernet_r50.py: -------------------------------------------------------------------------------- 1 | # model settings 2 | norm_cfg = dict(type='SyncBN', requires_grad=True) 3 | model = dict( 4 | type='EncoderDecoder', 5 | pretrained='open-mmlab://resnet50_v1c', 6 | backbone=dict( 7 | type='ResNetV1c', 8 | depth=50, 9 | num_stages=4, 10 | out_indices=(0, 1, 2, 3), 11 | dilations=(1, 1, 1, 1), 12 | strides=(1, 2, 2, 2), 13 | norm_cfg=norm_cfg, 14 | norm_eval=False, 15 | style='pytorch', 16 | contract_dilation=True), 17 | decode_head=dict( 18 | type='UPerHead', 19 | in_channels=[256, 512, 1024, 2048], 20 | in_index=[0, 1, 2, 3], 21 | pool_scales=(1, 2, 3, 6), 22 | channels=512, 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 | auxiliary_head=dict( 30 | type='FCNHead', 31 | in_channels=1024, 32 | in_index=2, 33 | channels=256, 34 | num_convs=1, 35 | concat_input=False, 36 | dropout_ratio=0.1, 37 | num_classes=19, 38 | norm_cfg=norm_cfg, 39 | align_corners=False, 40 | loss_decode=dict( 41 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=0.4)), 42 | # model training and testing settings 43 | train_cfg=dict(), 44 | test_cfg=dict(mode='whole')) 45 | -------------------------------------------------------------------------------- /Pytorch/tests/test_sampler.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import torch 3 | 4 | from mmseg.core import OHEMPixelSampler 5 | from mmseg.models.decode_heads import FCNHead 6 | 7 | 8 | def _context_for_ohem(): 9 | return FCNHead(in_channels=32, channels=16, num_classes=19) 10 | 11 | 12 | def test_ohem_sampler(): 13 | 14 | with pytest.raises(AssertionError): 15 | # seg_logit and seg_label must be of the same size 16 | sampler = OHEMPixelSampler(context=_context_for_ohem()) 17 | seg_logit = torch.randn(1, 19, 45, 45) 18 | seg_label = torch.randint(0, 19, size=(1, 1, 89, 89)) 19 | sampler.sample(seg_logit, seg_label) 20 | 21 | # test with thresh 22 | sampler = OHEMPixelSampler( 23 | context=_context_for_ohem(), thresh=0.7, min_kept=200) 24 | seg_logit = torch.randn(1, 19, 45, 45) 25 | seg_label = torch.randint(0, 19, size=(1, 1, 45, 45)) 26 | seg_weight = sampler.sample(seg_logit, seg_label) 27 | assert seg_weight.shape[0] == seg_logit.shape[0] 28 | assert seg_weight.shape[1:] == seg_logit.shape[2:] 29 | assert seg_weight.sum() > 200 30 | 31 | # test w.o thresh 32 | sampler = OHEMPixelSampler(context=_context_for_ohem(), min_kept=200) 33 | seg_logit = torch.randn(1, 19, 45, 45) 34 | seg_label = torch.randint(0, 19, size=(1, 1, 45, 45)) 35 | seg_weight = sampler.sample(seg_logit, seg_label) 36 | assert seg_weight.shape[0] == seg_logit.shape[0] 37 | assert seg_weight.shape[1:] == seg_logit.shape[2:] 38 | assert seg_weight.sum() == 200 39 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/models/deeplabv3plus_r50-d8.py: -------------------------------------------------------------------------------- 1 | # model settings 2 | norm_cfg = dict(type='SyncBN', requires_grad=True) 3 | model = dict( 4 | type='EncoderDecoder', 5 | pretrained='open-mmlab://resnet50_v1c', 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='DepthwiseSeparableASPPHead', 19 | in_channels=2048, 20 | in_index=3, 21 | channels=512, 22 | dilations=(1, 12, 24, 36), 23 | c1_in_channels=256, 24 | c1_channels=48, 25 | dropout_ratio=0.1, 26 | num_classes=19, 27 | norm_cfg=norm_cfg, 28 | align_corners=False, 29 | loss_decode=dict( 30 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 31 | auxiliary_head=dict( 32 | type='FCNHead', 33 | in_channels=1024, 34 | in_index=2, 35 | channels=256, 36 | num_convs=1, 37 | concat_input=False, 38 | dropout_ratio=0.1, 39 | num_classes=19, 40 | norm_cfg=norm_cfg, 41 | align_corners=False, 42 | loss_decode=dict( 43 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=0.4)), 44 | # model training and testing settings 45 | train_cfg=dict(), 46 | test_cfg=dict(mode='whole')) 47 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/models/deeplabv3plus_r50-d8_vd.py: -------------------------------------------------------------------------------- 1 | # model settings 2 | norm_cfg = dict(type='SyncBN', requires_grad=True) 3 | model = dict( 4 | type='EncoderDecoder', 5 | pretrained='open-mmlab://resnet50_v1d', 6 | backbone=dict( 7 | type='ResNetV1d', 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='DepthwiseSeparableASPPHead', 19 | in_channels=2048, 20 | in_index=3, 21 | channels=512, 22 | dilations=(1, 12, 24, 36), 23 | c1_in_channels=256, 24 | c1_channels=48, 25 | dropout_ratio=0.1, 26 | num_classes=19, 27 | norm_cfg=norm_cfg, 28 | align_corners=False, 29 | loss_decode=dict( 30 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 31 | auxiliary_head=dict( 32 | type='FCNHead', 33 | in_channels=1024, 34 | in_index=2, 35 | channels=256, 36 | num_convs=1, 37 | concat_input=False, 38 | dropout_ratio=0.1, 39 | num_classes=19, 40 | norm_cfg=norm_cfg, 41 | align_corners=False, 42 | loss_decode=dict( 43 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=0.4)), 44 | # model training and testing settings 45 | train_cfg=dict(), 46 | test_cfg=dict(mode='whole')) 47 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/models/deeplabv3plus_r50-d8_vd_contrast.py: -------------------------------------------------------------------------------- 1 | # model settings 2 | norm_cfg = dict(type='SyncBN', requires_grad=True) 3 | model = dict( 4 | type='EncoderDecoder', 5 | pretrained='open-mmlab://resnet50_v1d', 6 | backbone=dict( 7 | type='ResNetV1d', 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='DepthwiseSeparableASPPContrastHead', 19 | in_channels=2048, 20 | in_index=3, 21 | channels=512, 22 | dilations=(1, 12, 24, 36), 23 | c1_in_channels=256, 24 | c1_channels=48, 25 | dropout_ratio=0.1, 26 | num_classes=19, 27 | norm_cfg=norm_cfg, 28 | align_corners=False, 29 | loss_decode=dict( 30 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 31 | auxiliary_head=dict( 32 | type='FCNHead', 33 | in_channels=1024, 34 | in_index=2, 35 | channels=256, 36 | num_convs=1, 37 | concat_input=False, 38 | dropout_ratio=0.1, 39 | num_classes=19, 40 | norm_cfg=norm_cfg, 41 | align_corners=False, 42 | loss_decode=dict( 43 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=0.4)), 44 | # model training and testing settings 45 | train_cfg=dict(), 46 | test_cfg=dict(mode='whole')) 47 | -------------------------------------------------------------------------------- /Pytorch/tests/test_utils/test_se_layer.py: -------------------------------------------------------------------------------- 1 | import mmcv 2 | import pytest 3 | import torch 4 | 5 | from mmseg.models.utils.se_layer import SELayer 6 | 7 | 8 | def test_se_layer(): 9 | with pytest.raises(AssertionError): 10 | # test act_cfg assertion. 11 | SELayer(32, act_cfg=(dict(type='ReLU'), )) 12 | 13 | # test config with channels = 16. 14 | se_layer = SELayer(16) 15 | assert se_layer.conv1.conv.kernel_size == (1, 1) 16 | assert se_layer.conv1.conv.stride == (1, 1) 17 | assert se_layer.conv1.conv.padding == (0, 0) 18 | assert isinstance(se_layer.conv1.activate, torch.nn.ReLU) 19 | assert se_layer.conv2.conv.kernel_size == (1, 1) 20 | assert se_layer.conv2.conv.stride == (1, 1) 21 | assert se_layer.conv2.conv.padding == (0, 0) 22 | assert isinstance(se_layer.conv2.activate, mmcv.cnn.HSigmoid) 23 | 24 | x = torch.rand(1, 16, 64, 64) 25 | output = se_layer(x) 26 | assert output.shape == (1, 16, 64, 64) 27 | 28 | # test config with channels = 16, act_cfg = dict(type='ReLU'). 29 | se_layer = SELayer(16, act_cfg=dict(type='ReLU')) 30 | assert se_layer.conv1.conv.kernel_size == (1, 1) 31 | assert se_layer.conv1.conv.stride == (1, 1) 32 | assert se_layer.conv1.conv.padding == (0, 0) 33 | assert isinstance(se_layer.conv1.activate, torch.nn.ReLU) 34 | assert se_layer.conv2.conv.kernel_size == (1, 1) 35 | assert se_layer.conv2.conv.stride == (1, 1) 36 | assert se_layer.conv2.conv.padding == (0, 0) 37 | assert isinstance(se_layer.conv2.activate, torch.nn.ReLU) 38 | 39 | x = torch.rand(1, 16, 64, 64) 40 | output = se_layer(x) 41 | assert output.shape == (1, 16, 64, 64) 42 | -------------------------------------------------------------------------------- /Pytorch/mmseg/datasets/pipelines/compose.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | from mmcv.utils import build_from_cfg 4 | 5 | from ..builder import PIPELINES 6 | 7 | 8 | @PIPELINES.register_module() 9 | class Compose(object): 10 | """Compose multiple transforms sequentially. 11 | 12 | Args: 13 | transforms (Sequence[dict | callable]): Sequence of transform object or 14 | config dict to be composed. 15 | """ 16 | 17 | def __init__(self, transforms): 18 | assert isinstance(transforms, collections.abc.Sequence) 19 | self.transforms = [] 20 | for transform in transforms: 21 | if isinstance(transform, dict): 22 | transform = build_from_cfg(transform, PIPELINES) 23 | self.transforms.append(transform) 24 | elif callable(transform): 25 | self.transforms.append(transform) 26 | else: 27 | raise TypeError('transform must be callable or a dict') 28 | 29 | def __call__(self, data): 30 | """Call function to apply transforms sequentially. 31 | 32 | Args: 33 | data (dict): A result dict contains the data to transform. 34 | 35 | Returns: 36 | dict: Transformed data. 37 | """ 38 | 39 | for t in self.transforms: 40 | data = t(data) 41 | if data is None: 42 | return None 43 | return data 44 | 45 | def __repr__(self): 46 | format_string = self.__class__.__name__ + '(' 47 | for t in self.transforms: 48 | format_string += '\n' 49 | format_string += f' {t}' 50 | format_string += '\n)' 51 | return format_string 52 | -------------------------------------------------------------------------------- /Pytorch/mmseg/datasets/dataset_wrappers.py: -------------------------------------------------------------------------------- 1 | from torch.utils.data.dataset import ConcatDataset as _ConcatDataset 2 | 3 | from .builder import DATASETS 4 | 5 | 6 | @DATASETS.register_module() 7 | class ConcatDataset(_ConcatDataset): 8 | """A wrapper of concatenated dataset. 9 | 10 | Same as :obj:`torch.utils.data.dataset.ConcatDataset`, but 11 | concat the group flag for image aspect ratio. 12 | 13 | Args: 14 | datasets (list[:obj:`Dataset`]): A list of datasets. 15 | """ 16 | 17 | def __init__(self, datasets): 18 | super(ConcatDataset, self).__init__(datasets) 19 | self.CLASSES = datasets[0].CLASSES 20 | self.PALETTE = datasets[0].PALETTE 21 | 22 | 23 | @DATASETS.register_module() 24 | class RepeatDataset(object): 25 | """A wrapper of repeated dataset. 26 | 27 | The length of repeated dataset will be `times` larger than the original 28 | dataset. This is useful when the data loading time is long but the dataset 29 | is small. Using RepeatDataset can reduce the data loading time between 30 | epochs. 31 | 32 | Args: 33 | dataset (:obj:`Dataset`): The dataset to be repeated. 34 | times (int): Repeat times. 35 | """ 36 | 37 | def __init__(self, dataset, times): 38 | self.dataset = dataset 39 | self.times = times 40 | self.CLASSES = dataset.CLASSES 41 | self.PALETTE = dataset.PALETTE 42 | self._ori_len = len(self.dataset) 43 | 44 | def __getitem__(self, idx): 45 | """Get item from original dataset.""" 46 | return self.dataset[idx % self._ori_len] 47 | 48 | def __len__(self): 49 | """The length is multiplied by ``times``""" 50 | return self.times * self._ori_len 51 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/decode_heads/nl_head.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from mmcv.cnn import NonLocal2d 3 | 4 | from ..builder import HEADS 5 | from .fcn_head import FCNHead 6 | 7 | 8 | @HEADS.register_module() 9 | class NLHead(FCNHead): 10 | """Non-local Neural Networks. 11 | 12 | This head is the implementation of `NLNet 13 | `_. 14 | 15 | Args: 16 | reduction (int): Reduction factor of projection transform. Default: 2. 17 | use_scale (bool): Whether to scale pairwise_weight by 18 | sqrt(1/inter_channels). Default: True. 19 | mode (str): The nonlocal mode. Options are 'embedded_gaussian', 20 | 'dot_product'. Default: 'embedded_gaussian.'. 21 | """ 22 | 23 | def __init__(self, 24 | reduction=2, 25 | use_scale=True, 26 | mode='embedded_gaussian', 27 | **kwargs): 28 | super(NLHead, self).__init__(num_convs=2, **kwargs) 29 | self.reduction = reduction 30 | self.use_scale = use_scale 31 | self.mode = mode 32 | self.nl_block = NonLocal2d( 33 | in_channels=self.channels, 34 | reduction=self.reduction, 35 | use_scale=self.use_scale, 36 | conv_cfg=self.conv_cfg, 37 | norm_cfg=self.norm_cfg, 38 | mode=self.mode) 39 | 40 | def forward(self, inputs): 41 | """Forward function.""" 42 | x = self._transform_inputs(inputs) 43 | output = self.convs[0](x) 44 | output = self.nl_block(output) 45 | output = self.convs[1](output) 46 | if self.concat_input: 47 | output = self.conv_cat(torch.cat([x, output], dim=1)) 48 | output = self.cls_seg(output) 49 | return output 50 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/decode_heads/gc_head.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from mmcv.cnn import ContextBlock 3 | 4 | from ..builder import HEADS 5 | from .fcn_head import FCNHead 6 | 7 | 8 | @HEADS.register_module() 9 | class GCHead(FCNHead): 10 | """GCNet: Non-local Networks Meet Squeeze-Excitation Networks and Beyond. 11 | 12 | This head is the implementation of `GCNet 13 | `_. 14 | 15 | Args: 16 | ratio (float): Multiplier of channels ratio. Default: 1/4. 17 | pooling_type (str): The pooling type of context aggregation. 18 | Options are 'att', 'avg'. Default: 'avg'. 19 | fusion_types (tuple[str]): The fusion type for feature fusion. 20 | Options are 'channel_add', 'channel_mul'. Defautl: ('channel_add',) 21 | """ 22 | 23 | def __init__(self, 24 | ratio=1 / 4., 25 | pooling_type='att', 26 | fusion_types=('channel_add', ), 27 | **kwargs): 28 | super(GCHead, self).__init__(num_convs=2, **kwargs) 29 | self.ratio = ratio 30 | self.pooling_type = pooling_type 31 | self.fusion_types = fusion_types 32 | self.gc_block = ContextBlock( 33 | in_channels=self.channels, 34 | ratio=self.ratio, 35 | pooling_type=self.pooling_type, 36 | fusion_types=self.fusion_types) 37 | 38 | def forward(self, inputs): 39 | """Forward function.""" 40 | x = self._transform_inputs(inputs) 41 | output = self.convs[0](x) 42 | output = self.gc_block(output) 43 | output = self.convs[1](output) 44 | if self.concat_input: 45 | output = self.conv_cat(torch.cat([x, output], dim=1)) 46 | output = self.cls_seg(output) 47 | return output 48 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/models/fcn_hr18.py: -------------------------------------------------------------------------------- 1 | # model settings 2 | norm_cfg = dict(type='SyncBN', requires_grad=True) 3 | model = dict( 4 | type='EncoderDecoder', 5 | pretrained='open-mmlab://msra/hrnetv2_w18', 6 | backbone=dict( 7 | type='HRNet', 8 | norm_cfg=norm_cfg, 9 | norm_eval=False, 10 | extra=dict( 11 | stage1=dict( 12 | num_modules=1, 13 | num_branches=1, 14 | block='BOTTLENECK', 15 | num_blocks=(4, ), 16 | num_channels=(64, )), 17 | stage2=dict( 18 | num_modules=1, 19 | num_branches=2, 20 | block='BASIC', 21 | num_blocks=(4, 4), 22 | num_channels=(18, 36)), 23 | stage3=dict( 24 | num_modules=4, 25 | num_branches=3, 26 | block='BASIC', 27 | num_blocks=(4, 4, 4), 28 | num_channels=(18, 36, 72)), 29 | stage4=dict( 30 | num_modules=3, 31 | num_branches=4, 32 | block='BASIC', 33 | num_blocks=(4, 4, 4, 4), 34 | num_channels=(18, 36, 72, 144)))), 35 | decode_head=dict( 36 | type='FCNHead', 37 | in_channels=[18, 36, 72, 144], 38 | in_index=(0, 1, 2, 3), 39 | channels=sum([18, 36, 72, 144]), 40 | input_transform='resize_concat', 41 | kernel_size=1, 42 | num_convs=1, 43 | concat_input=False, 44 | dropout_ratio=-1, 45 | num_classes=19, 46 | norm_cfg=norm_cfg, 47 | align_corners=False, 48 | loss_decode=dict( 49 | type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0)), 50 | # model training and testing settings 51 | train_cfg=dict(), 52 | test_cfg=dict(mode='whole')) 53 | -------------------------------------------------------------------------------- /Pytorch/tools/get_flops.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | from mmcv import Config 4 | from mmcv.cnn import get_model_complexity_info 5 | 6 | from mmseg.models import build_segmentor 7 | 8 | 9 | def parse_args(): 10 | parser = argparse.ArgumentParser(description='Train a segmentor') 11 | parser.add_argument('config', help='train config file path') 12 | parser.add_argument( 13 | '--shape', 14 | type=int, 15 | nargs='+', 16 | default=[2048, 1024], 17 | help='input image size') 18 | args = parser.parse_args() 19 | return args 20 | 21 | 22 | def main(): 23 | 24 | args = parse_args() 25 | 26 | if len(args.shape) == 1: 27 | input_shape = (3, args.shape[0], args.shape[0]) 28 | elif len(args.shape) == 2: 29 | input_shape = (3, ) + tuple(args.shape) 30 | else: 31 | raise ValueError('invalid input shape') 32 | 33 | cfg = Config.fromfile(args.config) 34 | cfg.model.pretrained = None 35 | model = build_segmentor( 36 | cfg.model, 37 | train_cfg=cfg.get('train_cfg'), 38 | test_cfg=cfg.get('test_cfg')).cuda() 39 | model.eval() 40 | 41 | if hasattr(model, 'forward_dummy'): 42 | model.forward = model.forward_dummy 43 | else: 44 | raise NotImplementedError( 45 | 'FLOPs counter is currently not currently supported with {}'. 46 | format(model.__class__.__name__)) 47 | 48 | flops, params = get_model_complexity_info(model, input_shape) 49 | split_line = '=' * 30 50 | print('{0}\nInput shape: {1}\nFlops: {2}\nParams: {3}\n{0}'.format( 51 | split_line, input_shape, flops, params)) 52 | print('!!!Please be cautious if you use the results in papers. ' 53 | 'You may need to check if all ops are supported and verify that the ' 54 | 'flops computation is correct.') 55 | 56 | 57 | if __name__ == '__main__': 58 | main() 59 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/datasets/autonue.py: -------------------------------------------------------------------------------- 1 | # dataset settings 2 | dataset_type = 'CustomDataset' 3 | data_root = 'data/IDD_Segmentation' 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 = (1024, 1024) 7 | train_pipeline = [ 8 | dict(type='LoadImageFromFile'), 9 | dict(type='LoadAnnotations'), 10 | dict(type='Resize', img_scale=(1920, 1080), ratio_range=(0.5, 2.0)), 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=(1920, 1080), 24 | # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75], 25 | flip=False, 26 | transforms=[ 27 | dict(type='Resize', keep_ratio=True), 28 | dict(type='RandomFlip'), 29 | dict(type='Normalize', **img_norm_cfg), 30 | dict(type='ImageToTensor', keys=['img']), 31 | dict(type='Collect', keys=['img']), 32 | ]) 33 | ] 34 | data = dict( 35 | samples_per_gpu=2, 36 | workers_per_gpu=2, 37 | train=dict( 38 | type=dataset_type, 39 | data_root=data_root, 40 | img_dir='img_dir/train', 41 | ann_dir='ann_dir/train', 42 | pipeline=train_pipeline), 43 | val=dict( 44 | type=dataset_type, 45 | data_root=data_root, 46 | img_dir='img_dir/val', 47 | ann_dir='ann_dir/val', 48 | pipeline=test_pipeline), 49 | test=dict( 50 | type=dataset_type, 51 | data_root=data_root, 52 | img_dir='img_dir/val', 53 | ann_dir='ann_dir/val', 54 | pipeline=test_pipeline)) 55 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/datasets/cityscapes.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, 1024) 7 | train_pipeline = [ 8 | dict(type='LoadImageFromFile'), 9 | dict(type='LoadAnnotations'), 10 | dict(type='Resize', img_scale=(2048, 1024), ratio_range=(0.5, 2.0)), 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=(2048, 1024), 24 | # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75], 25 | flip=False, 26 | transforms=[ 27 | dict(type='Resize', keep_ratio=True), 28 | dict(type='RandomFlip'), 29 | dict(type='Normalize', **img_norm_cfg), 30 | dict(type='ImageToTensor', keys=['img']), 31 | dict(type='Collect', keys=['img']), 32 | ]) 33 | ] 34 | data = dict( 35 | samples_per_gpu=2, 36 | workers_per_gpu=2, 37 | train=dict( 38 | type=dataset_type, 39 | data_root=data_root, 40 | img_dir='leftImg8bit/train', 41 | ann_dir='gtFine/train', 42 | pipeline=train_pipeline), 43 | val=dict( 44 | type=dataset_type, 45 | data_root=data_root, 46 | img_dir='leftImg8bit/val', 47 | ann_dir='gtFine/val', 48 | pipeline=test_pipeline), 49 | test=dict( 50 | type=dataset_type, 51 | data_root=data_root, 52 | img_dir='leftImg8bit/val', 53 | ann_dir='gtFine/val', 54 | pipeline=test_pipeline)) 55 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/datasets/pascal_person_part.py: -------------------------------------------------------------------------------- 1 | # dataset settings 2 | dataset_type = 'CustomDataset' 3 | data_root = 'data/pascal_person_part' 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 = (480, 480) 7 | train_pipeline = [ 8 | dict(type='LoadImageFromFile'), 9 | dict(type='LoadAnnotations'), 10 | dict(type='Resize', img_scale=(1920, 480), ratio_range=(0.5, 2.0)), 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=(1920, 480), 24 | # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75], 25 | flip=False, 26 | transforms=[ 27 | dict(type='Resize', keep_ratio=True), 28 | dict(type='RandomFlip'), 29 | dict(type='Normalize', **img_norm_cfg), 30 | dict(type='ImageToTensor', keys=['img']), 31 | dict(type='Collect', keys=['img']), 32 | ]) 33 | ] 34 | data = dict( 35 | samples_per_gpu=4, 36 | workers_per_gpu=4, 37 | train=dict( 38 | type=dataset_type, 39 | data_root=data_root, 40 | img_dir='img_dir/train', 41 | ann_dir='ann_dir/train', 42 | pipeline=train_pipeline), 43 | val=dict( 44 | type=dataset_type, 45 | data_root=data_root, 46 | img_dir='img_dir/val', 47 | ann_dir='ann_dir/val', 48 | pipeline=test_pipeline), 49 | test=dict( 50 | type=dataset_type, 51 | data_root=data_root, 52 | img_dir='img_dir/val', 53 | ann_dir='ann_dir/val', 54 | pipeline=test_pipeline)) 55 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/datasets/mapillary.py: -------------------------------------------------------------------------------- 1 | # dataset settings 2 | dataset_type = 'CustomDataset' 3 | data_root = 'data/mapillary' 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, 1024) 7 | train_pipeline = [ 8 | dict(type='LoadImageFromFile'), 9 | dict(type='LoadAnnotations'), 10 | dict(type='Resize', img_scale=(1920, 1080), ratio_range=(0.5, 2.0)), 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=(1920, 1080), 24 | # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75], 25 | flip=False, 26 | transforms=[ 27 | dict(type='Resize', keep_ratio=True), 28 | dict(type='RandomFlip'), 29 | dict(type='Normalize', **img_norm_cfg), 30 | dict(type='ImageToTensor', keys=['img']), 31 | dict(type='Collect', keys=['img']), 32 | ]) 33 | ] 34 | data = dict( 35 | samples_per_gpu=2, 36 | workers_per_gpu=2, 37 | train=dict( 38 | type=dataset_type, 39 | data_root=data_root, 40 | img_dir='training/images', 41 | ann_dir='training/v2.0/labels', 42 | pipeline=train_pipeline), 43 | val=dict( 44 | type=dataset_type, 45 | data_root=data_root, 46 | img_dir='validation/images', 47 | ann_dir='validation/v2.0/labels', 48 | pipeline=test_pipeline), 49 | test=dict( 50 | type=dataset_type, 51 | data_root=data_root, 52 | img_dir='validation/images', 53 | ann_dir='validation/v2.0/labels', 54 | pipeline=test_pipeline)) 55 | -------------------------------------------------------------------------------- /Pytorch/tools/convert_datasets/cityscapes.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os.path as osp 3 | 4 | import mmcv 5 | from cityscapesscripts.preparation.json2labelImg import json2labelImg 6 | 7 | 8 | def convert_json_to_label(json_file): 9 | label_file = json_file.replace('_polygons.json', '_labelTrainIds.png') 10 | json2labelImg(json_file, label_file, 'trainIds') 11 | 12 | 13 | def parse_args(): 14 | parser = argparse.ArgumentParser( 15 | description='Convert Cityscapes annotations to TrainIds') 16 | parser.add_argument('cityscapes_path', help='cityscapes data path') 17 | parser.add_argument('--gt-dir', default='gtFine', type=str) 18 | parser.add_argument('-o', '--out-dir', help='output path') 19 | parser.add_argument( 20 | '--nproc', default=1, type=int, help='number of process') 21 | args = parser.parse_args() 22 | return args 23 | 24 | 25 | def main(): 26 | args = parse_args() 27 | cityscapes_path = args.cityscapes_path 28 | out_dir = args.out_dir if args.out_dir else cityscapes_path 29 | mmcv.mkdir_or_exist(out_dir) 30 | 31 | gt_dir = osp.join(cityscapes_path, args.gt_dir) 32 | 33 | poly_files = [] 34 | for poly in mmcv.scandir(gt_dir, '_polygons.json', recursive=True): 35 | poly_file = osp.join(gt_dir, poly) 36 | poly_files.append(poly_file) 37 | if args.nproc > 1: 38 | mmcv.track_parallel_progress(convert_json_to_label, poly_files, 39 | args.nproc) 40 | else: 41 | mmcv.track_progress(convert_json_to_label, poly_files) 42 | 43 | split_names = ['train', 'val', 'test'] 44 | 45 | for split in split_names: 46 | filenames = [] 47 | for poly in mmcv.scandir( 48 | osp.join(gt_dir, split), '_polygons.json', recursive=True): 49 | filenames.append(poly.replace('_gtFine_polygons.json', '')) 50 | with open(osp.join(out_dir, f'{split}.txt'), 'w') as f: 51 | f.writelines(f + '\n' for f in filenames) 52 | 53 | 54 | if __name__ == '__main__': 55 | main() 56 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/datasets/LIP.py: -------------------------------------------------------------------------------- 1 | # dataset settings 2 | dataset_type = 'CustomDataset' 3 | data_root = 'data/LIP' 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 = (480, 480) 7 | train_pipeline = [ 8 | dict(type='LoadImageFromFile'), 9 | dict(type='LoadAnnotations'), 10 | dict(type='Resize', img_scale=(1920, 480), ratio_range=(0.5, 2.0)), 11 | dict(type='RandomCrop', crop_size=crop_size, cat_max_ratio=0.75), 12 | dict(type='RandomSwapFlip', prob=0.5, swap_index_left=[14, 16, 18], swap_index_right=[15, 17, 19]), 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=(1920, 480), 24 | # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75], 25 | flip=False, 26 | transforms=[ 27 | dict(type='Resize', keep_ratio=True), 28 | dict(type='RandomFlip'), 29 | dict(type='Normalize', **img_norm_cfg), 30 | dict(type='ImageToTensor', keys=['img']), 31 | dict(type='Collect', keys=['img']), 32 | ]) 33 | ] 34 | data = dict( 35 | samples_per_gpu=4, 36 | workers_per_gpu=4, 37 | train=dict( 38 | type=dataset_type, 39 | data_root=data_root, 40 | img_dir='img_dir/train', 41 | ann_dir='ann_dir/train', 42 | pipeline=train_pipeline), 43 | val=dict( 44 | type=dataset_type, 45 | data_root=data_root, 46 | img_dir='img_dir/val', 47 | ann_dir='ann_dir/val', 48 | pipeline=test_pipeline), 49 | test=dict( 50 | type=dataset_type, 51 | data_root=data_root, 52 | img_dir='img_dir/train', 53 | ann_dir='ann_dir/train', 54 | pipeline=test_pipeline)) 55 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/datasets/ade20k.py: -------------------------------------------------------------------------------- 1 | # dataset settings 2 | dataset_type = 'ADE20KDataset' 3 | data_root = 'data/ade/ADEChallengeData2016' 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 | train_pipeline = [ 8 | dict(type='LoadImageFromFile'), 9 | dict(type='LoadAnnotations', reduce_zero_label=True), 10 | dict(type='Resize', img_scale=(2048, 512), ratio_range=(0.5, 2.0)), 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=None, 24 | # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75], 25 | flip=False, 26 | transforms=[ 27 | dict(type='Resize', keep_ratio=True), 28 | dict(type='RandomFlip'), 29 | dict(type='Normalize', **img_norm_cfg), 30 | dict(type='ImageToTensor', keys=['img']), 31 | dict(type='Collect', keys=['img']), 32 | ]) 33 | ] 34 | data = dict( 35 | samples_per_gpu=4, 36 | workers_per_gpu=4, 37 | train=dict( 38 | type=dataset_type, 39 | data_root=data_root, 40 | img_dir='images/training', 41 | ann_dir='annotations/training', 42 | pipeline=train_pipeline), 43 | val=dict( 44 | type=dataset_type, 45 | data_root=data_root, 46 | img_dir='images/validation', 47 | ann_dir='annotations/validation', 48 | pipeline=test_pipeline), 49 | test=dict( 50 | type=dataset_type, 51 | data_root=data_root, 52 | img_dir='images/validation', 53 | ann_dir='annotations/validation', 54 | pipeline=test_pipeline)) 55 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/builder.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | 3 | from mmcv.utils import Registry, build_from_cfg 4 | from torch import nn 5 | 6 | BACKBONES = Registry('backbone') 7 | NECKS = Registry('neck') 8 | HEADS = Registry('head') 9 | LOSSES = Registry('loss') 10 | SEGMENTORS = Registry('segmentor') 11 | 12 | 13 | def build(cfg, registry, default_args=None): 14 | """Build a module. 15 | 16 | Args: 17 | cfg (dict, list[dict]): The config of modules, is is either a dict 18 | or a list of configs. 19 | registry (:obj:`Registry`): A registry the module belongs to. 20 | default_args (dict, optional): Default arguments to build the module. 21 | Defaults to None. 22 | 23 | Returns: 24 | nn.Module: A built nn module. 25 | """ 26 | 27 | if isinstance(cfg, list): 28 | modules = [ 29 | build_from_cfg(cfg_, registry, default_args) for cfg_ in cfg 30 | ] 31 | return nn.Sequential(*modules) 32 | else: 33 | return build_from_cfg(cfg, registry, default_args) 34 | 35 | 36 | def build_backbone(cfg): 37 | """Build backbone.""" 38 | return build(cfg, BACKBONES) 39 | 40 | 41 | def build_neck(cfg): 42 | """Build neck.""" 43 | return build(cfg, NECKS) 44 | 45 | 46 | def build_head(cfg): 47 | """Build head.""" 48 | return build(cfg, HEADS) 49 | 50 | 51 | def build_loss(cfg): 52 | """Build loss.""" 53 | return build(cfg, LOSSES) 54 | 55 | 56 | def build_segmentor(cfg, train_cfg=None, test_cfg=None): 57 | """Build segmentor.""" 58 | if train_cfg is not None or test_cfg is not None: 59 | warnings.warn( 60 | 'train_cfg and test_cfg is deprecated, ' 61 | 'please specify them in model', UserWarning) 62 | assert cfg.get('train_cfg') is None or train_cfg is None, \ 63 | 'train_cfg specified in both outer field and model field ' 64 | assert cfg.get('test_cfg') is None or test_cfg is None, \ 65 | 'test_cfg specified in both outer field and model field ' 66 | return build(cfg, SEGMENTORS, dict(train_cfg=train_cfg, test_cfg=test_cfg)) 67 | -------------------------------------------------------------------------------- /Pytorch/mmseg/ops/wrappers.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | 3 | import torch 4 | import torch.nn as nn 5 | import torch.nn.functional as F 6 | 7 | 8 | def resize(input, 9 | size=None, 10 | scale_factor=None, 11 | mode='nearest', 12 | align_corners=None, 13 | warning=True): 14 | if warning: 15 | if size is not None and align_corners: 16 | input_h, input_w = tuple(int(x) for x in input.shape[2:]) 17 | output_h, output_w = tuple(int(x) for x in size) 18 | if output_h > input_h or output_w > output_h: 19 | if ((output_h > 1 and output_w > 1 and input_h > 1 20 | and input_w > 1) and (output_h - 1) % (input_h - 1) 21 | and (output_w - 1) % (input_w - 1)): 22 | warnings.warn( 23 | f'When align_corners={align_corners}, ' 24 | 'the output would more aligned if ' 25 | f'input size {(input_h, input_w)} is `x+1` and ' 26 | f'out size {(output_h, output_w)} is `nx+1`') 27 | if isinstance(size, torch.Size): 28 | size = tuple(int(x) for x in size) 29 | return F.interpolate(input, size, scale_factor, mode, align_corners) 30 | 31 | 32 | class Upsample(nn.Module): 33 | 34 | def __init__(self, 35 | size=None, 36 | scale_factor=None, 37 | mode='nearest', 38 | align_corners=None): 39 | super(Upsample, self).__init__() 40 | self.size = size 41 | if isinstance(scale_factor, tuple): 42 | self.scale_factor = tuple(float(factor) for factor in scale_factor) 43 | else: 44 | self.scale_factor = float(scale_factor) if scale_factor else None 45 | self.mode = mode 46 | self.align_corners = align_corners 47 | 48 | def forward(self, x): 49 | if not self.size: 50 | size = [int(t * self.scale_factor) for t in x.shape[-2:]] 51 | else: 52 | size = self.size 53 | return resize(x, size, None, self.mode, self.align_corners) 54 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/datasets/pascal_voc12.py: -------------------------------------------------------------------------------- 1 | # dataset settings 2 | dataset_type = 'PascalVOCDataset' 3 | data_root = 'data/VOCdevkit/VOC2012' 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=(2048, 512), ratio_range=(0.5, 2.0)), 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=(2048, 512), 24 | # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75], 25 | flip=False, 26 | transforms=[ 27 | dict(type='Resize', keep_ratio=True), 28 | dict(type='RandomFlip'), 29 | dict(type='Normalize', **img_norm_cfg), 30 | dict(type='ImageToTensor', keys=['img']), 31 | dict(type='Collect', keys=['img']), 32 | ]) 33 | ] 34 | data = dict( 35 | samples_per_gpu=4, 36 | workers_per_gpu=4, 37 | train=dict( 38 | type=dataset_type, 39 | data_root=data_root, 40 | img_dir='JPEGImages', 41 | ann_dir='SegmentationClass', 42 | split='ImageSets/Segmentation/train.txt', 43 | pipeline=train_pipeline), 44 | val=dict( 45 | type=dataset_type, 46 | data_root=data_root, 47 | img_dir='JPEGImages', 48 | ann_dir='SegmentationClass', 49 | split='ImageSets/Segmentation/val.txt', 50 | pipeline=test_pipeline), 51 | test=dict( 52 | type=dataset_type, 53 | data_root=data_root, 54 | img_dir='JPEGImages', 55 | ann_dir='SegmentationClass', 56 | split='ImageSets/Segmentation/val.txt', 57 | pipeline=test_pipeline)) 58 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/decode_heads/sep_fcn_head.py: -------------------------------------------------------------------------------- 1 | from mmcv.cnn import DepthwiseSeparableConvModule 2 | 3 | from ..builder import HEADS 4 | from .fcn_head import FCNHead 5 | 6 | 7 | @HEADS.register_module() 8 | class DepthwiseSeparableFCNHead(FCNHead): 9 | """Depthwise-Separable Fully Convolutional Network for Semantic 10 | Segmentation. 11 | 12 | This head is implemented according to Fast-SCNN paper. 13 | Args: 14 | in_channels(int): Number of output channels of FFM. 15 | channels(int): Number of middle-stage channels in the decode head. 16 | concat_input(bool): Whether to concatenate original decode input into 17 | the result of several consecutive convolution layers. 18 | Default: True. 19 | num_classes(int): Used to determine the dimension of 20 | final prediction tensor. 21 | in_index(int): Correspond with 'out_indices' in FastSCNN backbone. 22 | norm_cfg (dict | None): Config of norm layers. 23 | align_corners (bool): align_corners argument of F.interpolate. 24 | Default: False. 25 | loss_decode(dict): Config of loss type and some 26 | relevant additional options. 27 | """ 28 | 29 | def __init__(self, **kwargs): 30 | super(DepthwiseSeparableFCNHead, self).__init__(**kwargs) 31 | self.convs[0] = DepthwiseSeparableConvModule( 32 | self.in_channels, 33 | self.channels, 34 | kernel_size=self.kernel_size, 35 | padding=self.kernel_size // 2, 36 | norm_cfg=self.norm_cfg) 37 | for i in range(1, self.num_convs): 38 | self.convs[i] = DepthwiseSeparableConvModule( 39 | self.channels, 40 | self.channels, 41 | kernel_size=self.kernel_size, 42 | padding=self.kernel_size // 2, 43 | norm_cfg=self.norm_cfg) 44 | 45 | if self.concat_input: 46 | self.conv_cat = DepthwiseSeparableConvModule( 47 | self.in_channels + self.channels, 48 | self.channels, 49 | kernel_size=self.kernel_size, 50 | padding=self.kernel_size // 2, 51 | norm_cfg=self.norm_cfg) 52 | -------------------------------------------------------------------------------- /Pytorch/configs/_base_/datasets/pascal_context.py: -------------------------------------------------------------------------------- 1 | # dataset settings 2 | dataset_type = 'PascalContextDataset' 3 | data_root = 'data/VOCdevkit/VOC2010/' 4 | img_norm_cfg = dict( 5 | mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True) 6 | 7 | img_scale = (520, 520) 8 | crop_size = (480, 480) 9 | 10 | train_pipeline = [ 11 | dict(type='LoadImageFromFile'), 12 | dict(type='LoadAnnotations'), 13 | dict(type='Resize', img_scale=img_scale, ratio_range=(0.5, 2.0)), 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=img_scale, 27 | # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75], 28 | flip=False, 29 | transforms=[ 30 | dict(type='Resize', keep_ratio=True), 31 | dict(type='RandomFlip'), 32 | dict(type='Normalize', **img_norm_cfg), 33 | dict(type='ImageToTensor', keys=['img']), 34 | dict(type='Collect', keys=['img']), 35 | ]) 36 | ] 37 | data = dict( 38 | samples_per_gpu=4, 39 | workers_per_gpu=4, 40 | train=dict( 41 | type=dataset_type, 42 | data_root=data_root, 43 | img_dir='JPEGImages', 44 | ann_dir='SegmentationClassContext', 45 | split='ImageSets/SegmentationContext/train.txt', 46 | pipeline=train_pipeline), 47 | val=dict( 48 | type=dataset_type, 49 | data_root=data_root, 50 | img_dir='JPEGImages', 51 | ann_dir='SegmentationClassContext', 52 | split='ImageSets/SegmentationContext/val.txt', 53 | pipeline=test_pipeline), 54 | test=dict( 55 | type=dataset_type, 56 | data_root=data_root, 57 | img_dir='JPEGImages', 58 | ann_dir='SegmentationClassContext', 59 | split='ImageSets/SegmentationContext/val.txt', 60 | pipeline=test_pipeline)) 61 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/utils/se_layer.py: -------------------------------------------------------------------------------- 1 | import mmcv 2 | import torch.nn as nn 3 | from mmcv.cnn import ConvModule 4 | 5 | from .make_divisible import make_divisible 6 | 7 | 8 | class SELayer(nn.Module): 9 | """Squeeze-and-Excitation Module. 10 | 11 | Args: 12 | channels (int): The input (and output) channels of the SE layer. 13 | ratio (int): Squeeze ratio in SELayer, the intermediate channel will be 14 | ``int(channels/ratio)``. Default: 16. 15 | conv_cfg (None or dict): Config dict for convolution layer. 16 | Default: None, which means using conv2d. 17 | act_cfg (dict or Sequence[dict]): Config dict for activation layer. 18 | If act_cfg is a dict, two activation layers will be configurated 19 | by this dict. If act_cfg is a sequence of dicts, the first 20 | activation layer will be configurated by the first dict and the 21 | second activation layer will be configurated by the second dict. 22 | Default: (dict(type='ReLU'), dict(type='HSigmoid', bias=3.0, 23 | divisor=6.0)). 24 | """ 25 | 26 | def __init__(self, 27 | channels, 28 | ratio=16, 29 | conv_cfg=None, 30 | act_cfg=(dict(type='ReLU'), 31 | dict(type='HSigmoid', bias=3.0, divisor=6.0))): 32 | super(SELayer, self).__init__() 33 | if isinstance(act_cfg, dict): 34 | act_cfg = (act_cfg, act_cfg) 35 | assert len(act_cfg) == 2 36 | assert mmcv.is_tuple_of(act_cfg, dict) 37 | self.global_avgpool = nn.AdaptiveAvgPool2d(1) 38 | self.conv1 = ConvModule( 39 | in_channels=channels, 40 | out_channels=make_divisible(channels // ratio, 8), 41 | kernel_size=1, 42 | stride=1, 43 | conv_cfg=conv_cfg, 44 | act_cfg=act_cfg[0]) 45 | self.conv2 = ConvModule( 46 | in_channels=make_divisible(channels // ratio, 8), 47 | out_channels=channels, 48 | kernel_size=1, 49 | stride=1, 50 | conv_cfg=conv_cfg, 51 | act_cfg=act_cfg[1]) 52 | 53 | def forward(self, x): 54 | out = self.global_avgpool(x) 55 | out = self.conv1(out) 56 | out = self.conv2(out) 57 | return x * out 58 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/decode_heads/cascade_decode_head.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | 3 | from .decode_head import BaseDecodeHead 4 | 5 | 6 | class BaseCascadeDecodeHead(BaseDecodeHead, metaclass=ABCMeta): 7 | """Base class for cascade decode head used in 8 | :class:`CascadeEncoderDecoder.""" 9 | 10 | def __init__(self, *args, **kwargs): 11 | super(BaseCascadeDecodeHead, self).__init__(*args, **kwargs) 12 | 13 | @abstractmethod 14 | def forward(self, inputs, prev_output): 15 | """Placeholder of forward function.""" 16 | pass 17 | 18 | def forward_train(self, inputs, prev_output, img_metas, gt_semantic_seg, 19 | train_cfg): 20 | """Forward function for training. 21 | Args: 22 | inputs (list[Tensor]): List of multi-level img features. 23 | prev_output (Tensor): The output of previous decode head. 24 | img_metas (list[dict]): List of image info dict where each dict 25 | has: 'img_shape', 'scale_factor', 'flip', and may also contain 26 | 'filename', 'ori_shape', 'pad_shape', and 'img_norm_cfg'. 27 | For details on the values of these keys see 28 | `mmseg/datasets/pipelines/formatting.py:Collect`. 29 | gt_semantic_seg (Tensor): Semantic segmentation masks 30 | used if the architecture supports semantic segmentation task. 31 | train_cfg (dict): The training config. 32 | 33 | Returns: 34 | dict[str, Tensor]: a dictionary of loss components 35 | """ 36 | seg_logits = self.forward(inputs, prev_output) 37 | losses = self.losses(seg_logits, gt_semantic_seg) 38 | 39 | return losses 40 | 41 | def forward_test(self, inputs, prev_output, img_metas, test_cfg): 42 | """Forward function for testing. 43 | 44 | Args: 45 | inputs (list[Tensor]): List of multi-level img features. 46 | prev_output (Tensor): The output of previous decode head. 47 | img_metas (list[dict]): List of image info dict where each dict 48 | has: 'img_shape', 'scale_factor', 'flip', and may also contain 49 | 'filename', 'ori_shape', 'pad_shape', and 'img_norm_cfg'. 50 | For details on the values of these keys see 51 | `mmseg/datasets/pipelines/formatting.py:Collect`. 52 | test_cfg (dict): The testing config. 53 | 54 | Returns: 55 | Tensor: Output segmentation map. 56 | """ 57 | return self.forward(inputs, prev_output) 58 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/decode_heads/fpn_head.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import torch.nn as nn 3 | from mmcv.cnn import ConvModule 4 | 5 | from mmseg.ops import resize 6 | from ..builder import HEADS 7 | from .decode_head import BaseDecodeHead 8 | 9 | 10 | @HEADS.register_module() 11 | class FPNHead(BaseDecodeHead): 12 | """Panoptic Feature Pyramid Networks. 13 | 14 | This head is the implementation of `Semantic FPN 15 | `_. 16 | 17 | Args: 18 | feature_strides (tuple[int]): The strides for input feature maps. 19 | stack_lateral. All strides suppose to be power of 2. The first 20 | one is of largest resolution. 21 | """ 22 | 23 | def __init__(self, feature_strides, **kwargs): 24 | super(FPNHead, self).__init__( 25 | input_transform='multiple_select', **kwargs) 26 | assert len(feature_strides) == len(self.in_channels) 27 | assert min(feature_strides) == feature_strides[0] 28 | self.feature_strides = feature_strides 29 | 30 | self.scale_heads = nn.ModuleList() 31 | for i in range(len(feature_strides)): 32 | head_length = max( 33 | 1, 34 | int(np.log2(feature_strides[i]) - np.log2(feature_strides[0]))) 35 | scale_head = [] 36 | for k in range(head_length): 37 | scale_head.append( 38 | ConvModule( 39 | self.in_channels[i] if k == 0 else self.channels, 40 | self.channels, 41 | 3, 42 | padding=1, 43 | conv_cfg=self.conv_cfg, 44 | norm_cfg=self.norm_cfg, 45 | act_cfg=self.act_cfg)) 46 | if feature_strides[i] != feature_strides[0]: 47 | scale_head.append( 48 | nn.Upsample( 49 | scale_factor=2, 50 | mode='bilinear', 51 | align_corners=self.align_corners)) 52 | self.scale_heads.append(nn.Sequential(*scale_head)) 53 | 54 | def forward(self, inputs): 55 | 56 | x = self._transform_inputs(inputs) 57 | 58 | output = self.scale_heads[0](x[0]) 59 | for i in range(1, len(self.feature_strides)): 60 | # non inplace 61 | output = output + resize( 62 | self.scale_heads[i](x[i]), 63 | size=output.shape[2:], 64 | mode='bilinear', 65 | align_corners=self.align_corners) 66 | 67 | output = self.cls_seg(output) 68 | return output 69 | -------------------------------------------------------------------------------- /Pytorch/tools/benchmark.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import time 3 | 4 | import torch 5 | from mmcv import Config 6 | from mmcv.parallel import MMDataParallel 7 | from mmcv.runner import load_checkpoint 8 | 9 | from mmseg.datasets import build_dataloader, build_dataset 10 | from mmseg.models import build_segmentor 11 | 12 | 13 | def parse_args(): 14 | parser = argparse.ArgumentParser(description='MMSeg benchmark a model') 15 | parser.add_argument('config', help='test config file path') 16 | parser.add_argument('checkpoint', help='checkpoint file') 17 | parser.add_argument( 18 | '--log-interval', type=int, default=50, help='interval of logging') 19 | args = parser.parse_args() 20 | return args 21 | 22 | 23 | def main(): 24 | args = parse_args() 25 | 26 | cfg = Config.fromfile(args.config) 27 | # set cudnn_benchmark 28 | torch.backends.cudnn.benchmark = False 29 | cfg.model.pretrained = None 30 | cfg.data.test.test_mode = True 31 | 32 | # build the dataloader 33 | # TODO: support multiple images per gpu (only minor changes are needed) 34 | dataset = build_dataset(cfg.data.test) 35 | data_loader = build_dataloader( 36 | dataset, 37 | samples_per_gpu=1, 38 | workers_per_gpu=cfg.data.workers_per_gpu, 39 | dist=False, 40 | shuffle=False) 41 | 42 | # build the model and load checkpoint 43 | cfg.model.train_cfg = None 44 | model = build_segmentor(cfg.model, test_cfg=cfg.get('test_cfg')) 45 | load_checkpoint(model, args.checkpoint, map_location='cpu') 46 | 47 | model = MMDataParallel(model, device_ids=[0]) 48 | 49 | model.eval() 50 | 51 | # the first several iterations may be very slow so skip them 52 | num_warmup = 5 53 | pure_inf_time = 0 54 | total_iters = 200 55 | 56 | # benchmark with 200 image and take the average 57 | for i, data in enumerate(data_loader): 58 | 59 | torch.cuda.synchronize() 60 | start_time = time.perf_counter() 61 | 62 | with torch.no_grad(): 63 | model(return_loss=False, rescale=True, **data) 64 | 65 | torch.cuda.synchronize() 66 | elapsed = time.perf_counter() - start_time 67 | 68 | if i >= num_warmup: 69 | pure_inf_time += elapsed 70 | if (i + 1) % args.log_interval == 0: 71 | fps = (i + 1 - num_warmup) / pure_inf_time 72 | print(f'Done image [{i + 1:<3}/ {total_iters}], ' 73 | f'fps: {fps:.2f} img / s') 74 | 75 | if (i + 1) == total_iters: 76 | fps = (i + 1 - num_warmup) / pure_inf_time 77 | print(f'Overall fps: {fps:.2f} img / s') 78 | break 79 | 80 | 81 | if __name__ == '__main__': 82 | main() 83 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/decode_heads/fcn_head.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | from mmcv.cnn import ConvModule 4 | 5 | from ..builder import HEADS 6 | from .decode_head import BaseDecodeHead 7 | 8 | 9 | @HEADS.register_module() 10 | class FCNHead(BaseDecodeHead): 11 | """Fully Convolution Networks for Semantic Segmentation. 12 | 13 | This head is implemented of `FCNNet `_. 14 | 15 | Args: 16 | num_convs (int): Number of convs in the head. Default: 2. 17 | kernel_size (int): The kernel size for convs in the head. Default: 3. 18 | concat_input (bool): Whether concat the input and output of convs 19 | before classification layer. 20 | """ 21 | 22 | def __init__(self, 23 | num_convs=2, 24 | kernel_size=3, 25 | concat_input=True, 26 | **kwargs): 27 | assert num_convs >= 0 28 | self.num_convs = num_convs 29 | self.concat_input = concat_input 30 | self.kernel_size = kernel_size 31 | super(FCNHead, self).__init__(**kwargs) 32 | if num_convs == 0: 33 | assert self.in_channels == self.channels 34 | 35 | convs = [] 36 | convs.append( 37 | ConvModule( 38 | self.in_channels, 39 | self.channels, 40 | kernel_size=kernel_size, 41 | padding=kernel_size // 2, 42 | conv_cfg=self.conv_cfg, 43 | norm_cfg=self.norm_cfg, 44 | act_cfg=self.act_cfg)) 45 | for i in range(num_convs - 1): 46 | convs.append( 47 | ConvModule( 48 | self.channels, 49 | self.channels, 50 | kernel_size=kernel_size, 51 | padding=kernel_size // 2, 52 | conv_cfg=self.conv_cfg, 53 | norm_cfg=self.norm_cfg, 54 | act_cfg=self.act_cfg)) 55 | if num_convs == 0: 56 | self.convs = nn.Identity() 57 | else: 58 | self.convs = nn.Sequential(*convs) 59 | if self.concat_input: 60 | self.conv_cat = ConvModule( 61 | self.in_channels + self.channels, 62 | self.channels, 63 | kernel_size=kernel_size, 64 | padding=kernel_size // 2, 65 | conv_cfg=self.conv_cfg, 66 | norm_cfg=self.norm_cfg, 67 | act_cfg=self.act_cfg) 68 | 69 | def forward(self, inputs): 70 | """Forward function.""" 71 | x = self._transform_inputs(inputs) 72 | output = self.convs(x) 73 | if self.concat_input: 74 | output = self.conv_cat(torch.cat([x, output], dim=1)) 75 | output = self.cls_seg(output) 76 | return output 77 | -------------------------------------------------------------------------------- /Pytorch/mmseg/datasets/pascal_context.py: -------------------------------------------------------------------------------- 1 | import os.path as osp 2 | 3 | from .builder import DATASETS 4 | from .custom import CustomDataset 5 | 6 | 7 | @DATASETS.register_module() 8 | class PascalContextDataset(CustomDataset): 9 | """PascalContext dataset. 10 | 11 | In segmentation map annotation for PascalContext, 0 stands for background, 12 | which is included in 60 categories. ``reduce_zero_label`` is fixed to 13 | False. The ``img_suffix`` is fixed to '.jpg' and ``seg_map_suffix`` is 14 | fixed to '.png'. 15 | 16 | Args: 17 | split (str): Split txt file for PascalContext. 18 | """ 19 | 20 | CLASSES = ('background', 'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 21 | 'bus', 'car', 'cat', 'chair', 'cow', 'table', 'dog', 'horse', 22 | 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', 23 | 'tvmonitor', 'bag', 'bed', 'bench', 'book', 'building', 24 | 'cabinet', 'ceiling', 'cloth', 'computer', 'cup', 'door', 25 | 'fence', 'floor', 'flower', 'food', 'grass', 'ground', 26 | 'keyboard', 'light', 'mountain', 'mouse', 'curtain', 'platform', 27 | 'sign', 'plate', 'road', 'rock', 'shelves', 'sidewalk', 'sky', 28 | 'snow', 'bedclothes', 'track', 'tree', 'truck', 'wall', 'water', 29 | 'window', 'wood') 30 | 31 | PALETTE = [[120, 120, 120], [180, 120, 120], [6, 230, 230], [80, 50, 50], 32 | [4, 200, 3], [120, 120, 80], [140, 140, 140], [204, 5, 255], 33 | [230, 230, 230], [4, 250, 7], [224, 5, 255], [235, 255, 7], 34 | [150, 5, 61], [120, 120, 70], [8, 255, 51], [255, 6, 82], 35 | [143, 255, 140], [204, 255, 4], [255, 51, 7], [204, 70, 3], 36 | [0, 102, 200], [61, 230, 250], [255, 6, 51], [11, 102, 255], 37 | [255, 7, 71], [255, 9, 224], [9, 7, 230], [220, 220, 220], 38 | [255, 9, 92], [112, 9, 255], [8, 255, 214], [7, 255, 224], 39 | [255, 184, 6], [10, 255, 71], [255, 41, 10], [7, 255, 255], 40 | [224, 255, 8], [102, 8, 255], [255, 61, 6], [255, 194, 7], 41 | [255, 122, 8], [0, 255, 20], [255, 8, 41], [255, 5, 153], 42 | [6, 51, 255], [235, 12, 255], [160, 150, 20], [0, 163, 255], 43 | [140, 140, 140], [250, 10, 15], [20, 255, 0], [31, 255, 0], 44 | [255, 31, 0], [255, 224, 0], [153, 255, 0], [0, 0, 255], 45 | [255, 71, 0], [0, 235, 255], [0, 173, 255], [31, 0, 255]] 46 | 47 | def __init__(self, split, **kwargs): 48 | super(PascalContextDataset, self).__init__( 49 | img_suffix='.jpg', 50 | seg_map_suffix='.png', 51 | split=split, 52 | reduce_zero_label=False, 53 | **kwargs) 54 | assert osp.exists(self.img_dir) and self.split is not None 55 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/losses/tree_triplet_loss.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | import math 5 | 6 | class TreeTripletLoss(nn.Module): 7 | def __init__(self, num_classes, hiera_map, hiera_index, ignore_index=255): 8 | super(TreeTripletLoss, self).__init__() 9 | 10 | self.ignore_label = ignore_index 11 | self.num_classes = num_classes 12 | self.hiera_map = hiera_map 13 | self.hiera_index = hiera_index 14 | 15 | def forward(self, feats, labels=None, max_triplet=200): 16 | batch_size = feats.shape[0] 17 | labels = labels.unsqueeze(1).float().clone() 18 | labels = torch.nn.functional.interpolate(labels, 19 | (feats.shape[2], feats.shape[3]), mode='nearest') 20 | labels = labels.squeeze(1).long() 21 | assert labels.shape[-1] == feats.shape[-1], '{} {}'.format(labels.shape, feats.shape) 22 | 23 | labels = labels.view(-1) 24 | feats = feats.permute(0, 2, 3, 1) 25 | feats = feats.contiguous().view(-1, feats.shape[-1]) 26 | 27 | triplet_loss=0 28 | exist_classes = torch.unique(labels) 29 | exist_classes = [x for x in exist_classes if x != 255] 30 | class_count=0 31 | 32 | for ii in exist_classes: 33 | index_range = self.hiera_index[self.hiera_map[ii]] 34 | index_anchor = labels==ii 35 | index_pos = (labels>=index_range[0]) & (labels=index_range[-1]) 37 | 38 | min_size = min(torch.sum(index_anchor), torch.sum(index_pos), torch.sum(index_neg), max_triplet) 39 | 40 | # label_anchor = labels[index_anchor][:min_size] 41 | # label_pos = labels[index_pos][:min_size] 42 | # label_neg = labels[index_neg][:min_size] 43 | 44 | feats_anchor = feats[index_anchor][:min_size] 45 | feats_pos = feats[index_pos][:min_size] 46 | feats_neg = feats[index_neg][:min_size] 47 | 48 | distance = torch.zeros(min_size,2).cuda() 49 | distance[:,0:1] = 1-(feats_anchor*feats_pos).sum(1, True) 50 | distance[:,1:2] = 1-(feats_anchor*feats_neg).sum(1, True) 51 | 52 | # margin always 0.1 + (4-2)/4 since the hierarchy is three level 53 | # TODO: should include label of pos is the same as anchor 54 | margin = 0.6*torch.ones(min_size).cuda() 55 | 56 | tl = distance[:,0] - distance[:,1] + margin 57 | tl = F.relu(tl) 58 | 59 | if tl.size(0)>0: 60 | triplet_loss += tl.mean() 61 | class_count+=1 62 | if class_count==0: 63 | return None, torch.tensor([0]).cuda() 64 | triplet_loss /=class_count 65 | return triplet_loss, torch.tensor([class_count]).cuda() 66 | -------------------------------------------------------------------------------- /Pytorch/mmseg/ops/encoding.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn as nn 3 | from torch.nn import functional as F 4 | 5 | 6 | class Encoding(nn.Module): 7 | """Encoding Layer: a learnable residual encoder. 8 | 9 | Input is of shape (batch_size, channels, height, width). 10 | Output is of shape (batch_size, num_codes, channels). 11 | 12 | Args: 13 | channels: dimension of the features or feature channels 14 | num_codes: number of code words 15 | """ 16 | 17 | def __init__(self, channels, num_codes): 18 | super(Encoding, self).__init__() 19 | # init codewords and smoothing factor 20 | self.channels, self.num_codes = channels, num_codes 21 | std = 1. / ((num_codes * channels)**0.5) 22 | # [num_codes, channels] 23 | self.codewords = nn.Parameter( 24 | torch.empty(num_codes, channels, 25 | dtype=torch.float).uniform_(-std, std), 26 | requires_grad=True) 27 | # [num_codes] 28 | self.scale = nn.Parameter( 29 | torch.empty(num_codes, dtype=torch.float).uniform_(-1, 0), 30 | requires_grad=True) 31 | 32 | @staticmethod 33 | def scaled_l2(x, codewords, scale): 34 | num_codes, channels = codewords.size() 35 | batch_size = x.size(0) 36 | reshaped_scale = scale.view((1, 1, num_codes)) 37 | expanded_x = x.unsqueeze(2).expand( 38 | (batch_size, x.size(1), num_codes, channels)) 39 | reshaped_codewords = codewords.view((1, 1, num_codes, channels)) 40 | 41 | scaled_l2_norm = reshaped_scale * ( 42 | expanded_x - reshaped_codewords).pow(2).sum(dim=3) 43 | return scaled_l2_norm 44 | 45 | @staticmethod 46 | def aggregate(assigment_weights, x, codewords): 47 | num_codes, channels = codewords.size() 48 | reshaped_codewords = codewords.view((1, 1, num_codes, channels)) 49 | batch_size = x.size(0) 50 | 51 | expanded_x = x.unsqueeze(2).expand( 52 | (batch_size, x.size(1), num_codes, channels)) 53 | encoded_feat = (assigment_weights.unsqueeze(3) * 54 | (expanded_x - reshaped_codewords)).sum(dim=1) 55 | return encoded_feat 56 | 57 | def forward(self, x): 58 | assert x.dim() == 4 and x.size(1) == self.channels 59 | # [batch_size, channels, height, width] 60 | batch_size = x.size(0) 61 | # [batch_size, height x width, channels] 62 | x = x.view(batch_size, self.channels, -1).transpose(1, 2).contiguous() 63 | # assignment_weights: [batch_size, channels, num_codes] 64 | assigment_weights = F.softmax( 65 | self.scaled_l2(x, self.codewords, self.scale), dim=2) 66 | # aggregate 67 | encoded_feat = self.aggregate(assigment_weights, x, self.codewords) 68 | return encoded_feat 69 | 70 | def __repr__(self): 71 | repr_str = self.__class__.__name__ 72 | repr_str += f'(Nx{self.channels}xHxW =>Nx{self.num_codes}' \ 73 | f'x{self.channels})' 74 | return repr_str 75 | -------------------------------------------------------------------------------- /Pytorch/tools/convert_datasets/pascal_context.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os.path as osp 3 | from functools import partial 4 | 5 | import mmcv 6 | import numpy as np 7 | from detail import Detail 8 | from PIL import Image 9 | 10 | _mapping = np.sort( 11 | np.array([ 12 | 0, 2, 259, 260, 415, 324, 9, 258, 144, 18, 19, 22, 23, 397, 25, 284, 13 | 158, 159, 416, 33, 162, 420, 454, 295, 296, 427, 44, 45, 46, 308, 59, 14 | 440, 445, 31, 232, 65, 354, 424, 68, 326, 72, 458, 34, 207, 80, 355, 15 | 85, 347, 220, 349, 360, 98, 187, 104, 105, 366, 189, 368, 113, 115 16 | ])) 17 | _key = np.array(range(len(_mapping))).astype('uint8') 18 | 19 | 20 | def generate_labels(img_id, detail, out_dir): 21 | 22 | def _class_to_index(mask, _mapping, _key): 23 | # assert the values 24 | values = np.unique(mask) 25 | for i in range(len(values)): 26 | assert (values[i] in _mapping) 27 | index = np.digitize(mask.ravel(), _mapping, right=True) 28 | return _key[index].reshape(mask.shape) 29 | 30 | mask = Image.fromarray( 31 | _class_to_index(detail.getMask(img_id), _mapping=_mapping, _key=_key)) 32 | filename = img_id['file_name'] 33 | mask.save(osp.join(out_dir, filename.replace('jpg', 'png'))) 34 | return osp.splitext(osp.basename(filename))[0] 35 | 36 | 37 | def parse_args(): 38 | parser = argparse.ArgumentParser( 39 | description='Convert PASCAL VOC annotations to mmsegmentation format') 40 | parser.add_argument('devkit_path', help='pascal voc devkit path') 41 | parser.add_argument('json_path', help='annoation json filepath') 42 | parser.add_argument('-o', '--out_dir', help='output path') 43 | args = parser.parse_args() 44 | return args 45 | 46 | 47 | def main(): 48 | args = parse_args() 49 | devkit_path = args.devkit_path 50 | if args.out_dir is None: 51 | out_dir = osp.join(devkit_path, 'VOC2010', 'SegmentationClassContext') 52 | else: 53 | out_dir = args.out_dir 54 | json_path = args.json_path 55 | mmcv.mkdir_or_exist(out_dir) 56 | img_dir = osp.join(devkit_path, 'VOC2010', 'JPEGImages') 57 | 58 | train_detail = Detail(json_path, img_dir, 'train') 59 | train_ids = train_detail.getImgs() 60 | 61 | val_detail = Detail(json_path, img_dir, 'val') 62 | val_ids = val_detail.getImgs() 63 | 64 | mmcv.mkdir_or_exist( 65 | osp.join(devkit_path, 'VOC2010/ImageSets/SegmentationContext')) 66 | 67 | train_list = mmcv.track_progress( 68 | partial(generate_labels, detail=train_detail, out_dir=out_dir), 69 | train_ids) 70 | with open( 71 | osp.join(devkit_path, 'VOC2010/ImageSets/SegmentationContext', 72 | 'train.txt'), 'w') as f: 73 | f.writelines(line + '\n' for line in sorted(train_list)) 74 | 75 | val_list = mmcv.track_progress( 76 | partial(generate_labels, detail=val_detail, out_dir=out_dir), val_ids) 77 | with open( 78 | osp.join(devkit_path, 'VOC2010/ImageSets/SegmentationContext', 79 | 'val.txt'), 'w') as f: 80 | f.writelines(line + '\n' for line in sorted(val_list)) 81 | 82 | print('Done!') 83 | 84 | 85 | if __name__ == '__main__': 86 | main() 87 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/losses/accuracy.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | 3 | 4 | def accuracy(pred, target, topk=1, thresh=None): 5 | """Calculate accuracy according to the prediction and target. 6 | 7 | Args: 8 | pred (torch.Tensor): The model prediction, shape (N, num_class, ...) 9 | target (torch.Tensor): The target of each prediction, shape (N, , ...) 10 | topk (int | tuple[int], optional): If the predictions in ``topk`` 11 | matches the target, the predictions will be regarded as 12 | correct ones. Defaults to 1. 13 | thresh (float, optional): If not None, predictions with scores under 14 | this threshold are considered incorrect. Default to None. 15 | 16 | Returns: 17 | float | tuple[float]: If the input ``topk`` is a single integer, 18 | the function will return a single float as accuracy. If 19 | ``topk`` is a tuple containing multiple integers, the 20 | function will return a tuple containing accuracies of 21 | each ``topk`` number. 22 | """ 23 | assert isinstance(topk, (int, tuple)) 24 | if isinstance(topk, int): 25 | topk = (topk, ) 26 | return_single = True 27 | else: 28 | return_single = False 29 | 30 | maxk = max(topk) 31 | if pred.size(0) == 0: 32 | accu = [pred.new_tensor(0.) for i in range(len(topk))] 33 | return accu[0] if return_single else accu 34 | assert pred.ndim == target.ndim + 1 35 | assert pred.size(0) == target.size(0) 36 | assert maxk <= pred.size(1), \ 37 | f'maxk {maxk} exceeds pred dimension {pred.size(1)}' 38 | pred_value, pred_label = pred.topk(maxk, dim=1) 39 | # transpose to shape (maxk, N, ...) 40 | pred_label = pred_label.transpose(0, 1) 41 | correct = pred_label.eq(target.unsqueeze(0).expand_as(pred_label)) 42 | if thresh is not None: 43 | # Only prediction values larger than thresh are counted as correct 44 | correct = correct & (pred_value > thresh).t() 45 | res = [] 46 | for k in topk: 47 | correct_k = correct[:k].view(-1).float().sum(0, keepdim=True) 48 | res.append(correct_k.mul_(100.0 / target.numel())) 49 | return res[0] if return_single else res 50 | 51 | 52 | class Accuracy(nn.Module): 53 | """Accuracy calculation module.""" 54 | 55 | def __init__(self, topk=(1, ), thresh=None): 56 | """Module to calculate the accuracy. 57 | 58 | Args: 59 | topk (tuple, optional): The criterion used to calculate the 60 | accuracy. Defaults to (1,). 61 | thresh (float, optional): If not None, predictions with scores 62 | under this threshold are considered incorrect. Default to None. 63 | """ 64 | super().__init__() 65 | self.topk = topk 66 | self.thresh = thresh 67 | 68 | def forward(self, pred, target): 69 | """Forward function to calculate accuracy. 70 | 71 | Args: 72 | pred (torch.Tensor): Prediction of models. 73 | target (torch.Tensor): Target for each prediction. 74 | 75 | Returns: 76 | tuple[float]: The accuracies under different topk criterions. 77 | """ 78 | return accuracy(pred, target, self.topk, self.thresh) 79 | -------------------------------------------------------------------------------- /Pytorch/configs/fp16/README.md: -------------------------------------------------------------------------------- 1 | # Mixed Precision Training 2 | 3 | ## Introduction 4 | 5 | [OTHERS] 6 | 7 | ```latex 8 | @article{micikevicius2017mixed, 9 | title={Mixed precision training}, 10 | author={Micikevicius, Paulius and Narang, Sharan and Alben, Jonah and Diamos, Gregory and Elsen, Erich and Garcia, David and Ginsburg, Boris and Houston, Michael and Kuchaiev, Oleksii and Venkatesh, Ganesh and others}, 11 | journal={arXiv preprint arXiv:1710.03740}, 12 | year={2017} 13 | } 14 | ``` 15 | 16 | ## Results and models 17 | 18 | ### Cityscapes 19 | 20 | | Method | Backbone | Crop Size | Lr schd | Mem (GB) | Inf time (fps) | mIoU | mIoU(ms+flip) | download | 21 | |--------|----------|-----------|--------:|----------|----------------|------:|--------------:|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 22 | | FCN | R-101-D8 | 512x1024 | 80000 | 5.50 | 2.66 | 76.80 | - | [model](https://download.openmmlab.com/mmsegmentation/v0.5/fp16/fcn_r101-d8_512x1024_80k_fp16_cityscapes/fcn_r101-d8_512x1024_80k_fp16_cityscapes-50245227.pth) | [log](https://download.openmmlab.com/mmsegmentation/v0.5/fp16/fcn_r101-d8_512x1024_80k_fp16_cityscapes/fcn_r101-d8_512x1024_80k_fp16_cityscapes_20200717_230921.log.json) | 23 | | PSPNet | R-101-D8 | 512x1024 | 80000 | 5.47 | 2.68 | 79.46 | - | [model](https://download.openmmlab.com/mmsegmentation/v0.5/fp16/pspnet_r101-d8_512x1024_80k_fp16_cityscapes/pspnet_r101-d8_512x1024_80k_fp16_cityscapes-ade37931.pth) | [log](https://download.openmmlab.com/mmsegmentation/v0.5/fp16/pspnet_r101-d8_512x1024_80k_fp16_cityscapes/pspnet_r101-d8_512x1024_80k_fp16_cityscapes_20200717_230919.log.json) | 24 | | DeepLabV3 | R-101-D8 | 512x1024 | 80000 | 5.91 | 1.93 | 80.48 | - | [model](https://download.openmmlab.com/mmsegmentation/v0.5/fp16/deeplabv3_r101-d8_512x1024_80k_fp16_cityscapes/deeplabv3_r101-d8_512x1024_80k_fp16_cityscapes-bc86dc84.pth) | [log](https://download.openmmlab.com/mmsegmentation/v0.5/fp16/deeplabv3_r101-d8_512x1024_80k_fp16_cityscapes/deeplabv3_r101-d8_512x1024_80k_fp16_cityscapes_20200717_230920.log.json) | 25 | | DeepLabV3+ | R-101-D8 | 512x1024 | 80000 | 6.46 | 2.60 | 80.46 | - | [model](https://download.openmmlab.com/mmsegmentation/v0.5/fp16/deeplabv3plus_r101-d8_512x1024_80k_fp16_cityscapes/deeplabv3plus_r101-d8_512x1024_80k_fp16_cityscapes-cc58bc8d.pth) | [log](https://download.openmmlab.com/mmsegmentation/v0.5/fp16/deeplabv3plus_r101-d8_512x1024_80k_fp16_cityscapes/deeplabv3plus_r101-d8_512x1024_80k_fp16_cityscapes_20200717_230920.log.json) | 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HieraSeg (CVPR'22) 2 | [Liulei Li](https://scholar.google.com/citations?user=eCrBWngAAAAJ&hl=en), [Tianfei Zhou](https://www.tfzhou.com/), [Wenguan Wang](https://sites.google.com/view/wenguanwang/)†, [Jianwu Li](https://scholar.google.com/citations?hl=en&user=rWIZNIwAAAAJ), [Yi Yang](https://scholar.google.com/citations?user=RMSuNFwAAAAJ&hl=en) 3 | 4 | [[`arXiv`](https://arxiv.org/abs/2203.14335)] [[`BibTeX`](#CitingHieraSeg)] 5 | 6 | ## Updates 7 | * The Pytorch implementation has already been released! 8 | * New work [GMMSeg](https://arxiv.org/abs/2210.02025), the first generative neural framework for semantic segmentation has been accepted by NeurIPS2022! [[code for GMMSeg](https://github.com/leonnnop/GMMSeg)] 9 | * This repo will release an official **PaddlePaddle** implementation for paper: Deep Hierarchical Semantic Segmentation. 10 | 11 | ## Abstract 12 | Humans are able to recognize structured relations in observation, allowing us to decompose complex scenes into simpler parts and abstract the visual world in multiple levels. However, such hierarchical reasoning ability of human perception remains largely unexplored in current literature of semantic segmentation. Existing work is often aware of flatten labels and predicts target classes exclusively for each pixel. In this paper, we instead address hierarchical semantic segmentation (HSS), which aims at structured, pixel-wise description of visual observation in terms of a class hierarchy. We devise HSSN, a general HSS framework that tackles two critical issues in this task: i) how to efficiently adapt existing hierarchy-agnostic segmentation networks to the HSS setting, and ii) how to leverage the hierarchy information to regularize HSS network learning. To address i), HSSN directly casts HSS as a pixel-wise multi-label classification task, only bringing minimal architecture change to current segmentation models. To solve ii), HSSN first explores inherent properties of the hierarchy as a training objective, which enforces segmentation predictions to obey the hierarchy structure. Further, with hierarchy-induced margin constraints, HSSN reshapes the pixel embedding space, so as to generate well-structured pixel representations and improve segmentation eventually. We conduct experiments on four semantic segmentation datasets (i.e., Mapillary Vistas 2.0, Cityscapes, LIP, and PASCAL-Person-Part), with different class hierarchies, segmentation network architectures and backbones, showing the generalization and superiority of HSSN. 13 |

14 | 15 |

16 | 17 | ## Other Related Work 18 | [GMMSeg: Gaussian Mixture based Generative Semantic Segmentation Models](https://github.com/leonnnop/GMMSeg) 19 | 20 | [Exploring Cross-Image Pixel Contrast for Semantic Segmentation (ICCV21-Oral)](https://github.com/tfzhou/ContrastiveSeg) 21 | 22 | [Rethinking Semantic Segmentation: A Prototype View (CVPR22-Oral)](https://github.com/tfzhou/ProtoSeg) 23 | 24 | ## Citing HieraSeg 25 | ```BibTeX 26 | @article{li2022deep, 27 | title={Deep Hierarchical Semantic Segmentation}, 28 | author={Li, Liulei and Zhou, Tianfei and Wang, Wenguan and Li, Jianwu and Yang, Yi}, 29 | journal={arXiv preprint arXiv:2203.14335}, 30 | year={2022} 31 | } 32 | ``` 33 | -------------------------------------------------------------------------------- /Pytorch/README.MD: -------------------------------------------------------------------------------- 1 | # Deep Hierarchical Semantic Segmentation 2 | 3 | This repo contains the pytorch version code and configuration files to reproduce semantic segmentaion results of [HieraSeg](https://arxiv.org/abs/2203.14335). It is based on [mmsegmentaion](https://github.com/open-mmlab/mmsegmentation). 4 | 5 | ## Results and Models 6 | 7 | | Dataset | Backbone | Crop Size | mIoU (single scale) | config | log | model | 8 | | :---: | :---: | :---: | :---: | :---: | :---: | :---: | 9 | | Cityscapes | Resnet101 | 512x1024 | 81.62 | [config](configs/deeplabv3plus/deeplabv3plus_r101-d8_512x1024_80k_cityscapes_hiera_triplet.py) | [github](https://github.com/qhanghu/HSSN_pytorch/releases/download/1.0/deeplabv3plus_r101-d8_512x1024_80k_cityscapes_hiera_triplet.log) | [github](https://github.com/qhanghu/HSSN_pytorch/releases/download/1.0/deeplabv3plus_r101-d8_512x1024_80k_cityscapes_hiera_triplet.pth) | 10 | | Pascal-Person-Part | ResNet101 | 480x480 | 73.44 | [config](configs/deeplabv3plus/deeplabv3plus_r101-d8_480x480_60k_pascal_person_part_hiera_triplet.py) | [github](https://github.com/qhanghu/HSSN_pytorch/releases/download/1.0/deeplabv3plus_r101-d8_480x480_60k_pascal_person_part_hiera_triplet.log) | [github](https://github.com/qhanghu/HSSN_pytorch/releases/download/1.0/deeplabv3plus_r101-d8_480x480_60k_pascal_person_part_hiera_triplet.pth) | 11 | | LIP | ResNet101 | 480x480 | 58.71 | [config](configs/deeplabv3plus/deeplabv3plus_r101-d8_480x480_160k_LIP_hiera_triplet.py) | [github](https://github.com/qhanghu/HSSN_pytorch/releases/download/1.0/deeplabv3plus_r101-d8_480x480_160k_LIP_hiera_triplet.log) | [github](https://github.com/qhanghu/HSSN_pytorch/releases/download/1.0/deeplabv3plus_r101-d8_480x480_160k_LIP_hiera_triplet.pth) | 12 | 13 | ## Usage 14 | 15 | ### Installation 16 | 17 | Please refer to [get_started.md](https://github.com/open-mmlab/mmsegmentation/blob/master/docs/en/get_started.md#installation) for installation and dataset preparation. 18 | 19 | ### Requirement 20 | 21 | Pytorch >= 1.8.0 & torchvision >= 0.9.0 22 | 23 | ### Inference 24 | ``` 25 | # single-gpu testing 26 | python tools/test.py --eval mIoU 27 | 28 | # multi-gpu testing 29 | tools/dist_test.sh --eval mIoU 30 | 31 | # multi-gpu, multi-scale testing 32 | tools/dist_test.sh --aug-test --eval mIoU 33 | ``` 34 | 35 | ### Training 36 | 37 | To train with pre-trained models, run: 38 | ``` 39 | # single-gpu training 40 | python tools/train.py --options model.pretrained= [model.backbone.use_checkpoint=True] [other optional arguments] 41 | 42 | # multi-gpu training 43 | tools/dist_train.sh --options model.pretrained= [model.backbone.use_checkpoint=True] [other optional arguments] 44 | ``` 45 | For example, to train on Cityscapes with a `ResNet-101` backbone and 4 gpus, run: 46 | ``` 47 | tools/dist_train.sh configs/deeplabv3plus/deeplabv3plus_r101-d8_512x1024_80k_cityscapes_hiera_triplet.py.py 4 48 | ``` 49 | 50 | **Notes:** 51 | - We use four Tesla A100 GPUs for training. CUDA version: 11.1. 52 | 53 | ## Citing HieraSeg 54 | ```BibTeX 55 | @article{li2022deep, 56 | title={Deep Hierarchical Semantic Segmentation}, 57 | author={Li, Liulei and Zhou, Tianfei and Wang, Wenguan and Li, Jianwu and Yang, Yi}, 58 | journal={CVPR}, 59 | year={2022} 60 | } 61 | ``` 62 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/decode_heads/lraspp_head.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | from mmcv import is_tuple_of 4 | from mmcv.cnn import ConvModule 5 | 6 | from mmseg.ops import resize 7 | from ..builder import HEADS 8 | from .decode_head import BaseDecodeHead 9 | 10 | 11 | @HEADS.register_module() 12 | class LRASPPHead(BaseDecodeHead): 13 | """Lite R-ASPP (LRASPP) head is proposed in Searching for MobileNetV3. 14 | 15 | This head is the improved implementation of `Searching for MobileNetV3 16 | `_. 17 | 18 | Args: 19 | branch_channels (tuple[int]): The number of output channels in every 20 | each branch. Default: (32, 64). 21 | """ 22 | 23 | def __init__(self, branch_channels=(32, 64), **kwargs): 24 | super(LRASPPHead, self).__init__(**kwargs) 25 | if self.input_transform != 'multiple_select': 26 | raise ValueError('in Lite R-ASPP (LRASPP) head, input_transform ' 27 | f'must be \'multiple_select\'. But received ' 28 | f'\'{self.input_transform}\'') 29 | assert is_tuple_of(branch_channels, int) 30 | assert len(branch_channels) == len(self.in_channels) - 1 31 | self.branch_channels = branch_channels 32 | 33 | self.convs = nn.Sequential() 34 | self.conv_ups = nn.Sequential() 35 | for i in range(len(branch_channels)): 36 | self.convs.add_module( 37 | f'conv{i}', 38 | nn.Conv2d( 39 | self.in_channels[i], branch_channels[i], 1, bias=False)) 40 | self.conv_ups.add_module( 41 | f'conv_up{i}', 42 | ConvModule( 43 | self.channels + branch_channels[i], 44 | self.channels, 45 | 1, 46 | norm_cfg=self.norm_cfg, 47 | act_cfg=self.act_cfg, 48 | bias=False)) 49 | 50 | self.conv_up_input = nn.Conv2d(self.channels, self.channels, 1) 51 | 52 | self.aspp_conv = ConvModule( 53 | self.in_channels[-1], 54 | self.channels, 55 | 1, 56 | norm_cfg=self.norm_cfg, 57 | act_cfg=self.act_cfg, 58 | bias=False) 59 | self.image_pool = nn.Sequential( 60 | nn.AvgPool2d(kernel_size=49, stride=(16, 20)), 61 | ConvModule( 62 | self.in_channels[2], 63 | self.channels, 64 | 1, 65 | act_cfg=dict(type='Sigmoid'), 66 | bias=False)) 67 | 68 | def forward(self, inputs): 69 | """Forward function.""" 70 | inputs = self._transform_inputs(inputs) 71 | 72 | x = inputs[-1] 73 | 74 | x = self.aspp_conv(x) * resize( 75 | self.image_pool(x), 76 | size=x.size()[2:], 77 | mode='bilinear', 78 | align_corners=self.align_corners) 79 | x = self.conv_up_input(x) 80 | 81 | for i in range(len(self.branch_channels) - 1, -1, -1): 82 | x = resize( 83 | x, 84 | size=inputs[i].size()[2:], 85 | mode='bilinear', 86 | align_corners=self.align_corners) 87 | x = torch.cat([x, self.convs[i](inputs[i])], 1) 88 | x = self.conv_ups[i](x) 89 | 90 | return self.cls_seg(x) 91 | -------------------------------------------------------------------------------- /Pytorch/tools/convert_datasets/voc_aug.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os.path as osp 3 | from functools import partial 4 | 5 | import mmcv 6 | import numpy as np 7 | from PIL import Image 8 | from scipy.io import loadmat 9 | 10 | AUG_LEN = 10582 11 | 12 | 13 | def convert_mat(mat_file, in_dir, out_dir): 14 | data = loadmat(osp.join(in_dir, mat_file)) 15 | mask = data['GTcls'][0]['Segmentation'][0].astype(np.uint8) 16 | seg_filename = osp.join(out_dir, mat_file.replace('.mat', '.png')) 17 | Image.fromarray(mask).save(seg_filename, 'PNG') 18 | 19 | 20 | def generate_aug_list(merged_list, excluded_list): 21 | return list(set(merged_list) - set(excluded_list)) 22 | 23 | 24 | def parse_args(): 25 | parser = argparse.ArgumentParser( 26 | description='Convert PASCAL VOC annotations to mmsegmentation format') 27 | parser.add_argument('devkit_path', help='pascal voc devkit path') 28 | parser.add_argument('aug_path', help='pascal voc aug path') 29 | parser.add_argument('-o', '--out_dir', help='output path') 30 | parser.add_argument( 31 | '--nproc', default=1, type=int, help='number of process') 32 | args = parser.parse_args() 33 | return args 34 | 35 | 36 | def main(): 37 | args = parse_args() 38 | devkit_path = args.devkit_path 39 | aug_path = args.aug_path 40 | nproc = args.nproc 41 | if args.out_dir is None: 42 | out_dir = osp.join(devkit_path, 'VOC2012', 'SegmentationClassAug') 43 | else: 44 | out_dir = args.out_dir 45 | mmcv.mkdir_or_exist(out_dir) 46 | in_dir = osp.join(aug_path, 'dataset', 'cls') 47 | 48 | mmcv.track_parallel_progress( 49 | partial(convert_mat, in_dir=in_dir, out_dir=out_dir), 50 | list(mmcv.scandir(in_dir, suffix='.mat')), 51 | nproc=nproc) 52 | 53 | full_aug_list = [] 54 | with open(osp.join(aug_path, 'dataset', 'train.txt')) as f: 55 | full_aug_list += [line.strip() for line in f] 56 | with open(osp.join(aug_path, 'dataset', 'val.txt')) as f: 57 | full_aug_list += [line.strip() for line in f] 58 | 59 | with open( 60 | osp.join(devkit_path, 'VOC2012/ImageSets/Segmentation', 61 | 'train.txt')) as f: 62 | ori_train_list = [line.strip() for line in f] 63 | with open( 64 | osp.join(devkit_path, 'VOC2012/ImageSets/Segmentation', 65 | 'val.txt')) as f: 66 | val_list = [line.strip() for line in f] 67 | 68 | aug_train_list = generate_aug_list(ori_train_list + full_aug_list, 69 | val_list) 70 | assert len(aug_train_list) == AUG_LEN, 'len(aug_train_list) != {}'.format( 71 | AUG_LEN) 72 | 73 | with open( 74 | osp.join(devkit_path, 'VOC2012/ImageSets/Segmentation', 75 | 'trainaug.txt'), 'w') as f: 76 | f.writelines(line + '\n' for line in aug_train_list) 77 | 78 | aug_list = generate_aug_list(full_aug_list, ori_train_list + val_list) 79 | assert len(aug_list) == AUG_LEN - len( 80 | ori_train_list), 'len(aug_list) != {}'.format(AUG_LEN - 81 | len(ori_train_list)) 82 | with open( 83 | osp.join(devkit_path, 'VOC2012/ImageSets/Segmentation', 'aug.txt'), 84 | 'w') as f: 85 | f.writelines(line + '\n' for line in aug_list) 86 | 87 | print('Done!') 88 | 89 | 90 | if __name__ == '__main__': 91 | main() 92 | -------------------------------------------------------------------------------- /Pytorch/mmseg/core/seg/sampler/ohem_pixel_sampler.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn.functional as F 3 | 4 | from ..builder import PIXEL_SAMPLERS 5 | from .base_pixel_sampler import BasePixelSampler 6 | 7 | 8 | @PIXEL_SAMPLERS.register_module() 9 | class OHEMPixelSampler(BasePixelSampler): 10 | """Online Hard Example Mining Sampler for segmentation. 11 | 12 | Args: 13 | context (nn.Module): The context of sampler, subclass of 14 | :obj:`BaseDecodeHead`. 15 | thresh (float, optional): The threshold for hard example selection. 16 | Below which, are prediction with low confidence. If not 17 | specified, the hard examples will be pixels of top ``min_kept`` 18 | loss. Default: None. 19 | min_kept (int, optional): The minimum number of predictions to keep. 20 | Default: 100000. 21 | """ 22 | 23 | def __init__(self, context, thresh=None, min_kept=100000): 24 | super(OHEMPixelSampler, self).__init__() 25 | self.context = context 26 | assert min_kept > 1 27 | self.thresh = thresh 28 | self.min_kept = min_kept 29 | 30 | def sample(self, seg_logit, seg_label): 31 | """Sample pixels that have high loss or with low prediction confidence. 32 | 33 | Args: 34 | seg_logit (torch.Tensor): segmentation logits, shape (N, C, H, W) 35 | seg_label (torch.Tensor): segmentation label, shape (N, 1, H, W) 36 | 37 | Returns: 38 | torch.Tensor: segmentation weight, shape (N, H, W) 39 | """ 40 | with torch.no_grad(): 41 | assert seg_logit.shape[2:] == seg_label.shape[2:] 42 | assert seg_label.shape[1] == 1 43 | seg_label = seg_label.squeeze(1).long() 44 | batch_kept = self.min_kept * seg_label.size(0) 45 | valid_mask = seg_label != self.context.ignore_index 46 | seg_weight = seg_logit.new_zeros(size=seg_label.size()) 47 | valid_seg_weight = seg_weight[valid_mask] 48 | if self.thresh is not None: 49 | seg_prob = F.softmax(seg_logit, dim=1) 50 | 51 | tmp_seg_label = seg_label.clone().unsqueeze(1) 52 | tmp_seg_label[tmp_seg_label == self.context.ignore_index] = 0 53 | seg_prob = seg_prob.gather(1, tmp_seg_label).squeeze(1) 54 | sort_prob, sort_indices = seg_prob[valid_mask].sort() 55 | 56 | if sort_prob.numel() > 0: 57 | min_threshold = sort_prob[min(batch_kept, 58 | sort_prob.numel() - 1)] 59 | else: 60 | min_threshold = 0.0 61 | threshold = max(min_threshold, self.thresh) 62 | valid_seg_weight[seg_prob[valid_mask] < threshold] = 1. 63 | else: 64 | losses = self.context.loss_decode( 65 | seg_logit, 66 | seg_label, 67 | weight=None, 68 | ignore_index=self.context.ignore_index, 69 | reduction_override='none') 70 | # faster than topk according to https://github.com/pytorch/pytorch/issues/22812 # noqa 71 | _, sort_indices = losses[valid_mask].sort(descending=True) 72 | valid_seg_weight[sort_indices[:batch_kept]] = 1. 73 | 74 | seg_weight[valid_mask] = valid_seg_weight 75 | 76 | return seg_weight 77 | -------------------------------------------------------------------------------- /Pytorch/tools/convert_datasets/chase_db1.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os 3 | import os.path as osp 4 | import tempfile 5 | import zipfile 6 | 7 | import mmcv 8 | 9 | CHASE_DB1_LEN = 28 * 3 10 | TRAINING_LEN = 60 11 | 12 | 13 | def parse_args(): 14 | parser = argparse.ArgumentParser( 15 | description='Convert CHASE_DB1 dataset to mmsegmentation format') 16 | parser.add_argument('dataset_path', help='path of CHASEDB1.zip') 17 | parser.add_argument('--tmp_dir', help='path of the temporary directory') 18 | parser.add_argument('-o', '--out_dir', help='output path') 19 | args = parser.parse_args() 20 | return args 21 | 22 | 23 | def main(): 24 | args = parse_args() 25 | dataset_path = args.dataset_path 26 | if args.out_dir is None: 27 | out_dir = osp.join('data', 'CHASE_DB1') 28 | else: 29 | out_dir = args.out_dir 30 | 31 | print('Making directories...') 32 | mmcv.mkdir_or_exist(out_dir) 33 | mmcv.mkdir_or_exist(osp.join(out_dir, 'images')) 34 | mmcv.mkdir_or_exist(osp.join(out_dir, 'images', 'training')) 35 | mmcv.mkdir_or_exist(osp.join(out_dir, 'images', 'validation')) 36 | mmcv.mkdir_or_exist(osp.join(out_dir, 'annotations')) 37 | mmcv.mkdir_or_exist(osp.join(out_dir, 'annotations', 'training')) 38 | mmcv.mkdir_or_exist(osp.join(out_dir, 'annotations', 'validation')) 39 | 40 | with tempfile.TemporaryDirectory(dir=args.tmp_dir) as tmp_dir: 41 | print('Extracting CHASEDB1.zip...') 42 | zip_file = zipfile.ZipFile(dataset_path) 43 | zip_file.extractall(tmp_dir) 44 | 45 | print('Generating training dataset...') 46 | 47 | assert len(os.listdir(tmp_dir)) == CHASE_DB1_LEN, \ 48 | 'len(os.listdir(tmp_dir)) != {}'.format(CHASE_DB1_LEN) 49 | 50 | for img_name in sorted(os.listdir(tmp_dir))[:TRAINING_LEN]: 51 | img = mmcv.imread(osp.join(tmp_dir, img_name)) 52 | if osp.splitext(img_name)[1] == '.jpg': 53 | mmcv.imwrite( 54 | img, 55 | osp.join(out_dir, 'images', 'training', 56 | osp.splitext(img_name)[0] + '.png')) 57 | else: 58 | # The annotation img should be divided by 128, because some of 59 | # the annotation imgs are not standard. We should set a 60 | # threshold to convert the nonstandard annotation imgs. The 61 | # value divided by 128 is equivalent to '1 if value >= 128 62 | # else 0' 63 | mmcv.imwrite( 64 | img[:, :, 0] // 128, 65 | osp.join(out_dir, 'annotations', 'training', 66 | osp.splitext(img_name)[0] + '.png')) 67 | 68 | for img_name in sorted(os.listdir(tmp_dir))[TRAINING_LEN:]: 69 | img = mmcv.imread(osp.join(tmp_dir, img_name)) 70 | if osp.splitext(img_name)[1] == '.jpg': 71 | mmcv.imwrite( 72 | img, 73 | osp.join(out_dir, 'images', 'validation', 74 | osp.splitext(img_name)[0] + '.png')) 75 | else: 76 | mmcv.imwrite( 77 | img[:, :, 0] // 128, 78 | osp.join(out_dir, 'annotations', 'validation', 79 | osp.splitext(img_name)[0] + '.png')) 80 | 81 | print('Removing the temporary files...') 82 | 83 | print('Done!') 84 | 85 | 86 | if __name__ == '__main__': 87 | main() 88 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/losses/utils.py: -------------------------------------------------------------------------------- 1 | import functools 2 | 3 | import torch.nn.functional as F 4 | 5 | 6 | def reduce_loss(loss, reduction): 7 | """Reduce loss as specified. 8 | 9 | Args: 10 | loss (Tensor): Elementwise loss tensor. 11 | reduction (str): Options are "none", "mean" and "sum". 12 | 13 | Return: 14 | Tensor: Reduced loss tensor. 15 | """ 16 | reduction_enum = F._Reduction.get_enum(reduction) 17 | # none: 0, elementwise_mean:1, sum: 2 18 | if reduction_enum == 0: 19 | return loss 20 | elif reduction_enum == 1: 21 | return loss.mean() 22 | elif reduction_enum == 2: 23 | return loss.sum() 24 | 25 | 26 | def weight_reduce_loss(loss, weight=None, reduction='mean', avg_factor=None): 27 | """Apply element-wise weight and reduce loss. 28 | 29 | Args: 30 | loss (Tensor): Element-wise loss. 31 | weight (Tensor): Element-wise weights. 32 | reduction (str): Same as built-in losses of PyTorch. 33 | avg_factor (float): Avarage factor when computing the mean of losses. 34 | 35 | Returns: 36 | Tensor: Processed loss values. 37 | """ 38 | # if weight is specified, apply element-wise weight 39 | if weight is not None: 40 | assert weight.dim() == loss.dim() 41 | if weight.dim() > 1: 42 | assert weight.size(1) == 1 or weight.size(1) == loss.size(1) 43 | loss = loss * weight 44 | 45 | # if avg_factor is not specified, just reduce the loss 46 | if avg_factor is None: 47 | loss = reduce_loss(loss, reduction) 48 | else: 49 | # if reduction is mean, then average the loss by avg_factor 50 | if reduction == 'mean': 51 | loss = loss.sum() / avg_factor 52 | # if reduction is 'none', then do nothing, otherwise raise an error 53 | elif reduction != 'none': 54 | raise ValueError('avg_factor can not be used with reduction="sum"') 55 | return loss 56 | 57 | 58 | def weighted_loss(loss_func): 59 | """Create a weighted version of a given loss function. 60 | 61 | To use this decorator, the loss function must have the signature like 62 | `loss_func(pred, target, **kwargs)`. The function only needs to compute 63 | element-wise loss without any reduction. This decorator will add weight 64 | and reduction arguments to the function. The decorated function will have 65 | the signature like `loss_func(pred, target, weight=None, reduction='mean', 66 | avg_factor=None, **kwargs)`. 67 | 68 | :Example: 69 | 70 | >>> import torch 71 | >>> @weighted_loss 72 | >>> def l1_loss(pred, target): 73 | >>> return (pred - target).abs() 74 | 75 | >>> pred = torch.Tensor([0, 2, 3]) 76 | >>> target = torch.Tensor([1, 1, 1]) 77 | >>> weight = torch.Tensor([1, 0, 1]) 78 | 79 | >>> l1_loss(pred, target) 80 | tensor(1.3333) 81 | >>> l1_loss(pred, target, weight) 82 | tensor(1.) 83 | >>> l1_loss(pred, target, reduction='none') 84 | tensor([1., 1., 2.]) 85 | >>> l1_loss(pred, target, weight, avg_factor=2) 86 | tensor(1.5000) 87 | """ 88 | 89 | @functools.wraps(loss_func) 90 | def wrapper(pred, 91 | target, 92 | weight=None, 93 | reduction='mean', 94 | avg_factor=None, 95 | **kwargs): 96 | # get element-wise loss 97 | loss = loss_func(pred, target, **kwargs) 98 | loss = weight_reduce_loss(loss, weight, reduction, avg_factor) 99 | return loss 100 | 101 | return wrapper 102 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/utils/res_layer.py: -------------------------------------------------------------------------------- 1 | from mmcv.cnn import build_conv_layer, build_norm_layer 2 | from torch import nn as nn 3 | 4 | 5 | class ResLayer(nn.Sequential): 6 | """ResLayer to build ResNet style backbone. 7 | 8 | Args: 9 | block (nn.Module): block used to build ResLayer. 10 | inplanes (int): inplanes of block. 11 | planes (int): planes of block. 12 | num_blocks (int): number of blocks. 13 | stride (int): stride of the first block. Default: 1 14 | avg_down (bool): Use AvgPool instead of stride conv when 15 | downsampling in the bottleneck. Default: False 16 | conv_cfg (dict): dictionary to construct and config conv layer. 17 | Default: None 18 | norm_cfg (dict): dictionary to construct and config norm layer. 19 | Default: dict(type='BN') 20 | multi_grid (int | None): Multi grid dilation rates of last 21 | stage. Default: None 22 | contract_dilation (bool): Whether contract first dilation of each layer 23 | Default: False 24 | """ 25 | 26 | def __init__(self, 27 | block, 28 | inplanes, 29 | planes, 30 | num_blocks, 31 | stride=1, 32 | dilation=1, 33 | avg_down=False, 34 | conv_cfg=None, 35 | norm_cfg=dict(type='BN'), 36 | multi_grid=None, 37 | contract_dilation=False, 38 | **kwargs): 39 | self.block = block 40 | 41 | downsample = None 42 | if stride != 1 or inplanes != planes * block.expansion: 43 | downsample = [] 44 | conv_stride = stride 45 | if avg_down: 46 | conv_stride = 1 47 | downsample.append( 48 | nn.AvgPool2d( 49 | kernel_size=stride, 50 | stride=stride, 51 | ceil_mode=True, 52 | count_include_pad=False)) 53 | downsample.extend([ 54 | build_conv_layer( 55 | conv_cfg, 56 | inplanes, 57 | planes * block.expansion, 58 | kernel_size=1, 59 | stride=conv_stride, 60 | bias=False), 61 | build_norm_layer(norm_cfg, planes * block.expansion)[1] 62 | ]) 63 | downsample = nn.Sequential(*downsample) 64 | 65 | layers = [] 66 | if multi_grid is None: 67 | if dilation > 1 and contract_dilation: 68 | first_dilation = dilation // 2 69 | else: 70 | first_dilation = dilation 71 | else: 72 | first_dilation = multi_grid[0] 73 | layers.append( 74 | block( 75 | inplanes=inplanes, 76 | planes=planes, 77 | stride=stride, 78 | dilation=first_dilation, 79 | downsample=downsample, 80 | conv_cfg=conv_cfg, 81 | norm_cfg=norm_cfg, 82 | **kwargs)) 83 | inplanes = planes * block.expansion 84 | for i in range(1, num_blocks): 85 | layers.append( 86 | block( 87 | inplanes=inplanes, 88 | planes=planes, 89 | stride=1, 90 | dilation=dilation if multi_grid is None else multi_grid[i], 91 | conv_cfg=conv_cfg, 92 | norm_cfg=norm_cfg, 93 | **kwargs)) 94 | super(ResLayer, self).__init__(*layers) 95 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/decode_heads/psp_head.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | from mmcv.cnn import ConvModule 4 | 5 | from mmseg.ops import resize 6 | from ..builder import HEADS 7 | from .decode_head import BaseDecodeHead 8 | 9 | 10 | class PPM(nn.ModuleList): 11 | """Pooling Pyramid Module used in PSPNet. 12 | 13 | Args: 14 | pool_scales (tuple[int]): Pooling scales used in Pooling Pyramid 15 | Module. 16 | in_channels (int): Input channels. 17 | channels (int): Channels after modules, before conv_seg. 18 | conv_cfg (dict|None): Config of conv layers. 19 | norm_cfg (dict|None): Config of norm layers. 20 | act_cfg (dict): Config of activation layers. 21 | align_corners (bool): align_corners argument of F.interpolate. 22 | """ 23 | 24 | def __init__(self, pool_scales, in_channels, channels, conv_cfg, norm_cfg, 25 | act_cfg, align_corners): 26 | super(PPM, self).__init__() 27 | self.pool_scales = pool_scales 28 | self.align_corners = align_corners 29 | self.in_channels = in_channels 30 | self.channels = channels 31 | self.conv_cfg = conv_cfg 32 | self.norm_cfg = norm_cfg 33 | self.act_cfg = act_cfg 34 | for pool_scale in pool_scales: 35 | self.append( 36 | nn.Sequential( 37 | nn.AdaptiveAvgPool2d(pool_scale), 38 | ConvModule( 39 | self.in_channels, 40 | self.channels, 41 | 1, 42 | conv_cfg=self.conv_cfg, 43 | norm_cfg=self.norm_cfg, 44 | act_cfg=self.act_cfg))) 45 | 46 | def forward(self, x): 47 | """Forward function.""" 48 | ppm_outs = [] 49 | for ppm in self: 50 | ppm_out = ppm(x) 51 | upsampled_ppm_out = resize( 52 | ppm_out, 53 | size=x.size()[2:], 54 | mode='bilinear', 55 | align_corners=self.align_corners) 56 | ppm_outs.append(upsampled_ppm_out) 57 | return ppm_outs 58 | 59 | 60 | @HEADS.register_module() 61 | class PSPHead(BaseDecodeHead): 62 | """Pyramid Scene Parsing Network. 63 | 64 | This head is the implementation of 65 | `PSPNet `_. 66 | 67 | Args: 68 | pool_scales (tuple[int]): Pooling scales used in Pooling Pyramid 69 | Module. Default: (1, 2, 3, 6). 70 | """ 71 | 72 | def __init__(self, pool_scales=(1, 2, 3, 6), **kwargs): 73 | super(PSPHead, self).__init__(**kwargs) 74 | assert isinstance(pool_scales, (list, tuple)) 75 | self.pool_scales = pool_scales 76 | self.psp_modules = PPM( 77 | self.pool_scales, 78 | self.in_channels, 79 | self.channels, 80 | conv_cfg=self.conv_cfg, 81 | norm_cfg=self.norm_cfg, 82 | act_cfg=self.act_cfg, 83 | align_corners=self.align_corners) 84 | self.bottleneck = ConvModule( 85 | self.in_channels + len(pool_scales) * self.channels, 86 | self.channels, 87 | 3, 88 | padding=1, 89 | conv_cfg=self.conv_cfg, 90 | norm_cfg=self.norm_cfg, 91 | act_cfg=self.act_cfg) 92 | 93 | def forward(self, inputs): 94 | """Forward function.""" 95 | x = self._transform_inputs(inputs) 96 | psp_outs = [x] 97 | psp_outs.extend(self.psp_modules(x)) 98 | psp_outs = torch.cat(psp_outs, dim=1) 99 | output = self.bottleneck(psp_outs) 100 | output = self.cls_seg(output) 101 | return output 102 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/decode_heads/sep_aspp_head.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | from mmcv.cnn import ConvModule, DepthwiseSeparableConvModule 4 | 5 | from mmseg.ops import resize 6 | from ..builder import HEADS 7 | from .aspp_head import ASPPHead, ASPPModule 8 | 9 | 10 | class DepthwiseSeparableASPPModule(ASPPModule): 11 | """Atrous Spatial Pyramid Pooling (ASPP) Module with depthwise separable 12 | conv.""" 13 | 14 | def __init__(self, **kwargs): 15 | super(DepthwiseSeparableASPPModule, self).__init__(**kwargs) 16 | for i, dilation in enumerate(self.dilations): 17 | if dilation > 1: 18 | self[i] = DepthwiseSeparableConvModule( 19 | self.in_channels, 20 | self.channels, 21 | 3, 22 | dilation=dilation, 23 | padding=dilation, 24 | norm_cfg=self.norm_cfg, 25 | act_cfg=self.act_cfg) 26 | 27 | 28 | @HEADS.register_module() 29 | class DepthwiseSeparableASPPHead(ASPPHead): 30 | """Encoder-Decoder with Atrous Separable Convolution for Semantic Image 31 | Segmentation. 32 | This head is the implementation of `DeepLabV3+ 33 | `_. 34 | Args: 35 | c1_in_channels (int): The input channels of c1 decoder. If is 0, 36 | the no decoder will be used. 37 | c1_channels (int): The intermediate channels of c1 decoder. 38 | """ 39 | 40 | def __init__(self, c1_in_channels, c1_channels, **kwargs): 41 | super(DepthwiseSeparableASPPHead, self).__init__(**kwargs) 42 | assert c1_in_channels >= 0 43 | self.aspp_modules = DepthwiseSeparableASPPModule( 44 | dilations=self.dilations, 45 | in_channels=self.in_channels, 46 | channels=self.channels, 47 | conv_cfg=self.conv_cfg, 48 | norm_cfg=self.norm_cfg, 49 | act_cfg=self.act_cfg) 50 | if c1_in_channels > 0: 51 | self.c1_bottleneck = ConvModule( 52 | c1_in_channels, 53 | c1_channels, 54 | 1, 55 | conv_cfg=self.conv_cfg, 56 | norm_cfg=self.norm_cfg, 57 | act_cfg=self.act_cfg) 58 | else: 59 | self.c1_bottleneck = None 60 | self.sep_bottleneck = nn.Sequential( 61 | DepthwiseSeparableConvModule( 62 | self.channels + c1_channels, 63 | self.channels, 64 | 3, 65 | padding=1, 66 | norm_cfg=self.norm_cfg, 67 | act_cfg=self.act_cfg), 68 | DepthwiseSeparableConvModule( 69 | self.channels, 70 | self.channels, 71 | 3, 72 | padding=1, 73 | norm_cfg=self.norm_cfg, 74 | act_cfg=self.act_cfg)) 75 | 76 | def forward(self, inputs): 77 | """Forward function.""" 78 | x = self._transform_inputs(inputs) 79 | aspp_outs = [ 80 | resize( 81 | self.image_pool(x), 82 | size=x.size()[2:], 83 | mode='bilinear', 84 | align_corners=self.align_corners) 85 | ] 86 | aspp_outs.extend(self.aspp_modules(x)) 87 | aspp_outs = torch.cat(aspp_outs, dim=1) 88 | output = self.bottleneck(aspp_outs) 89 | if self.c1_bottleneck is not None: 90 | c1_output = self.c1_bottleneck(inputs[0]) 91 | output = resize( 92 | input=output, 93 | size=c1_output.shape[2:], 94 | mode='bilinear', 95 | align_corners=self.align_corners) 96 | output = torch.cat([output, c1_output], dim=1) 97 | output = self.sep_bottleneck(output) 98 | output = self.cls_seg(output) 99 | return output -------------------------------------------------------------------------------- /Pytorch/mmseg/models/decode_heads/aspp_head.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | from mmcv.cnn import ConvModule 4 | 5 | from mmseg.ops import resize 6 | from ..builder import HEADS 7 | from .decode_head import BaseDecodeHead 8 | 9 | 10 | class ASPPModule(nn.ModuleList): 11 | """Atrous Spatial Pyramid Pooling (ASPP) Module. 12 | 13 | Args: 14 | dilations (tuple[int]): Dilation rate of each layer. 15 | in_channels (int): Input channels. 16 | channels (int): Channels after modules, before conv_seg. 17 | conv_cfg (dict|None): Config of conv layers. 18 | norm_cfg (dict|None): Config of norm layers. 19 | act_cfg (dict): Config of activation layers. 20 | """ 21 | 22 | def __init__(self, dilations, in_channels, channels, conv_cfg, norm_cfg, 23 | act_cfg): 24 | super(ASPPModule, self).__init__() 25 | self.dilations = dilations 26 | self.in_channels = in_channels 27 | self.channels = channels 28 | self.conv_cfg = conv_cfg 29 | self.norm_cfg = norm_cfg 30 | self.act_cfg = act_cfg 31 | for dilation in dilations: 32 | self.append( 33 | ConvModule( 34 | self.in_channels, 35 | self.channels, 36 | 1 if dilation == 1 else 3, 37 | dilation=dilation, 38 | padding=0 if dilation == 1 else dilation, 39 | conv_cfg=self.conv_cfg, 40 | norm_cfg=self.norm_cfg, 41 | act_cfg=self.act_cfg)) 42 | 43 | def forward(self, x): 44 | """Forward function.""" 45 | aspp_outs = [] 46 | for aspp_module in self: 47 | aspp_outs.append(aspp_module(x)) 48 | 49 | return aspp_outs 50 | 51 | 52 | @HEADS.register_module() 53 | class ASPPHead(BaseDecodeHead): 54 | """Rethinking Atrous Convolution for Semantic Image Segmentation. 55 | 56 | This head is the implementation of `DeepLabV3 57 | `_. 58 | 59 | Args: 60 | dilations (tuple[int]): Dilation rates for ASPP module. 61 | Default: (1, 6, 12, 18). 62 | """ 63 | 64 | def __init__(self, dilations=(1, 6, 12, 18), **kwargs): 65 | super(ASPPHead, self).__init__(**kwargs) 66 | assert isinstance(dilations, (list, tuple)) 67 | self.dilations = dilations 68 | self.image_pool = nn.Sequential( 69 | nn.AdaptiveAvgPool2d(1), 70 | ConvModule( 71 | self.in_channels, 72 | self.channels, 73 | 1, 74 | conv_cfg=self.conv_cfg, 75 | norm_cfg=self.norm_cfg, 76 | act_cfg=self.act_cfg)) 77 | self.aspp_modules = ASPPModule( 78 | dilations, 79 | self.in_channels, 80 | self.channels, 81 | conv_cfg=self.conv_cfg, 82 | norm_cfg=self.norm_cfg, 83 | act_cfg=self.act_cfg) 84 | self.bottleneck = ConvModule( 85 | (len(dilations) + 1) * self.channels, 86 | self.channels, 87 | 3, 88 | padding=1, 89 | conv_cfg=self.conv_cfg, 90 | norm_cfg=self.norm_cfg, 91 | act_cfg=self.act_cfg) 92 | 93 | def forward(self, inputs): 94 | """Forward function.""" 95 | x = self._transform_inputs(inputs) 96 | aspp_outs = [ 97 | resize( 98 | self.image_pool(x), 99 | size=x.size()[2:], 100 | mode='bilinear', 101 | align_corners=self.align_corners) 102 | ] 103 | aspp_outs.extend(self.aspp_modules(x)) 104 | aspp_outs = torch.cat(aspp_outs, dim=1) 105 | output = self.bottleneck(aspp_outs) 106 | output = self.cls_seg(output) 107 | return output 108 | -------------------------------------------------------------------------------- /Pytorch/configs/sem_fpn/README.md: -------------------------------------------------------------------------------- 1 | # Panoptic Feature Pyramid Networks 2 | 3 | ## Introduction 4 | 5 | [ALGORITHM] 6 | 7 | ```latex 8 | @article{Kirillov_2019, 9 | title={Panoptic Feature Pyramid Networks}, 10 | ISBN={9781728132938}, 11 | url={http://dx.doi.org/10.1109/CVPR.2019.00656}, 12 | DOI={10.1109/cvpr.2019.00656}, 13 | journal={2019 IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR)}, 14 | publisher={IEEE}, 15 | author={Kirillov, Alexander and Girshick, Ross and He, Kaiming and Dollar, Piotr}, 16 | year={2019}, 17 | month={Jun} 18 | } 19 | ``` 20 | 21 | ## Results and models 22 | 23 | ### Cityscapes 24 | 25 | | Method | Backbone | Crop Size | Lr schd | Mem (GB) | Inf time (fps) | mIoU | mIoU(ms+flip) | download | 26 | |--------|----------|-----------|--------:|---------:|----------------|------:|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 27 | | FPN | R-50 | 512x1024 | 80000 | 2.8 | 13.54 | 74.52 | 76.08 | [model](https://download.openmmlab.com/mmsegmentation/v0.5/sem_fpn/fpn_r50_512x1024_80k_cityscapes/fpn_r50_512x1024_80k_cityscapes_20200717_021437-94018a0d.pth) | [log](https://download.openmmlab.com/mmsegmentation/v0.5/sem_fpn/fpn_r50_512x1024_80k_cityscapes/fpn_r50_512x1024_80k_cityscapes-20200717_021437.log.json) | 28 | | FPN | R-101 | 512x1024 | 80000 | 3.9 | 10.29 | 75.80 | 77.40 | [model](https://download.openmmlab.com/mmsegmentation/v0.5/sem_fpn/fpn_r101_512x1024_80k_cityscapes/fpn_r101_512x1024_80k_cityscapes_20200717_012416-c5800d4c.pth) | [log](https://download.openmmlab.com/mmsegmentation/v0.5/sem_fpn/fpn_r101_512x1024_80k_cityscapes/fpn_r101_512x1024_80k_cityscapes-20200717_012416.log.json) | 29 | 30 | ### ADE20K 31 | 32 | | Method | Backbone | Crop Size | Lr schd | Mem (GB) | Inf time (fps) | mIoU | mIoU(ms+flip) | download | 33 | |--------|----------|-----------|--------:|---------:|----------------|------:|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 34 | | FPN | R-50 | 512x512 | 160000 | 4.9 | 55.77 | 37.49 | 39.09 | [model](https://download.openmmlab.com/mmsegmentation/v0.5/sem_fpn/fpn_r50_512x512_160k_ade20k/fpn_r50_512x512_160k_ade20k_20200718_131734-5b5a6ab9.pth) | [log](https://download.openmmlab.com/mmsegmentation/v0.5/sem_fpn/fpn_r50_512x512_160k_ade20k/fpn_r50_512x512_160k_ade20k-20200718_131734.log.json) | 35 | | FPN | R-101 | 512x512 | 160000 | 5.9 | 40.58 | 39.35 | 40.72 | [model](https://download.openmmlab.com/mmsegmentation/v0.5/sem_fpn/fpn_r101_512x512_160k_ade20k/fpn_r101_512x512_160k_ade20k_20200718_131734-306b5004.pth) | [log](https://download.openmmlab.com/mmsegmentation/v0.5/sem_fpn/fpn_r101_512x512_160k_ade20k/fpn_r101_512x512_160k_ade20k-20200718_131734.log.json) | 36 | -------------------------------------------------------------------------------- /Pytorch/mmseg/models/segmentors/cascade_encoder_decoder.py: -------------------------------------------------------------------------------- 1 | from torch import nn 2 | 3 | from mmseg.core import add_prefix 4 | from mmseg.ops import resize 5 | from .. import builder 6 | from ..builder import SEGMENTORS 7 | from .encoder_decoder import EncoderDecoder 8 | 9 | 10 | @SEGMENTORS.register_module() 11 | class CascadeEncoderDecoder(EncoderDecoder): 12 | """Cascade Encoder Decoder segmentors. 13 | 14 | CascadeEncoderDecoder almost the same as EncoderDecoder, while decoders of 15 | CascadeEncoderDecoder are cascaded. The output of previous decoder_head 16 | will be the input of next decoder_head. 17 | """ 18 | 19 | def __init__(self, 20 | num_stages, 21 | backbone, 22 | decode_head, 23 | neck=None, 24 | auxiliary_head=None, 25 | train_cfg=None, 26 | test_cfg=None, 27 | pretrained=None): 28 | self.num_stages = num_stages 29 | super(CascadeEncoderDecoder, self).__init__( 30 | backbone=backbone, 31 | decode_head=decode_head, 32 | neck=neck, 33 | auxiliary_head=auxiliary_head, 34 | train_cfg=train_cfg, 35 | test_cfg=test_cfg, 36 | pretrained=pretrained) 37 | 38 | def _init_decode_head(self, decode_head): 39 | """Initialize ``decode_head``""" 40 | assert isinstance(decode_head, list) 41 | assert len(decode_head) == self.num_stages 42 | self.decode_head = nn.ModuleList() 43 | for i in range(self.num_stages): 44 | self.decode_head.append(builder.build_head(decode_head[i])) 45 | self.align_corners = self.decode_head[-1].align_corners 46 | self.num_classes = self.decode_head[-1].num_classes 47 | 48 | def init_weights(self, pretrained=None): 49 | """Initialize the weights in backbone and heads. 50 | 51 | Args: 52 | pretrained (str, optional): Path to pre-trained weights. 53 | Defaults to None. 54 | """ 55 | self.backbone.init_weights(pretrained=pretrained) 56 | for i in range(self.num_stages): 57 | self.decode_head[i].init_weights() 58 | if self.with_auxiliary_head: 59 | if isinstance(self.auxiliary_head, nn.ModuleList): 60 | for aux_head in self.auxiliary_head: 61 | aux_head.init_weights() 62 | else: 63 | self.auxiliary_head.init_weights() 64 | 65 | def encode_decode(self, img, img_metas): 66 | """Encode images with backbone and decode into a semantic segmentation 67 | map of the same size as input.""" 68 | x = self.extract_feat(img) 69 | out = self.decode_head[0].forward_test(x, img_metas, self.test_cfg) 70 | for i in range(1, self.num_stages): 71 | out = self.decode_head[i].forward_test(x, out, img_metas, 72 | self.test_cfg) 73 | out = resize( 74 | input=out, 75 | size=img.shape[2:], 76 | mode='bilinear', 77 | align_corners=self.align_corners) 78 | return out 79 | 80 | def _decode_head_forward_train(self, x, img_metas, gt_semantic_seg): 81 | """Run forward function and calculate loss for decode head in 82 | training.""" 83 | losses = dict() 84 | 85 | loss_decode = self.decode_head[0].forward_train( 86 | x, img_metas, gt_semantic_seg, self.train_cfg) 87 | 88 | losses.update(add_prefix(loss_decode, 'decode_0')) 89 | 90 | for i in range(1, self.num_stages): 91 | # forward test again, maybe unnecessary for most methods. 92 | prev_outputs = self.decode_head[i - 1].forward_test( 93 | x, img_metas, self.test_cfg) 94 | loss_decode = self.decode_head[i].forward_train( 95 | x, prev_outputs, img_metas, gt_semantic_seg, self.train_cfg) 96 | losses.update(add_prefix(loss_decode, f'decode_{i}')) 97 | 98 | return losses 99 | -------------------------------------------------------------------------------- /Pytorch/configs/point_rend/README.md: -------------------------------------------------------------------------------- 1 | # PointRend: Image Segmentation as Rendering 2 | 3 | ## Introduction 4 | 5 | [ALGORITHM] 6 | 7 | ``` 8 | @misc{alex2019pointrend, 9 | title={PointRend: Image Segmentation as Rendering}, 10 | author={Alexander Kirillov and Yuxin Wu and Kaiming He and Ross Girshick}, 11 | year={2019}, 12 | eprint={1912.08193}, 13 | archivePrefix={arXiv}, 14 | primaryClass={cs.CV} 15 | } 16 | ``` 17 | 18 | ## Results and models 19 | 20 | ### Cityscapes 21 | 22 | | Method | Backbone | Crop Size | Lr schd | Mem (GB) | Inf time (fps) | mIoU | mIoU(ms+flip) | download | 23 | |-----------|----------|-----------|--------:|---------:|----------------|------:|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 24 | | PointRend | R-50 | 512x1024 | 80000 | 3.1 | 8.48 | 76.47 | 78.13 | [model](https://download.openmmlab.com/mmsegmentation/v0.5/point_rend/pointrend_r50_512x1024_80k_cityscapes/pointrend_r50_512x1024_80k_cityscapes_20200711_015821-bb1ff523.pth) | [log](https://download.openmmlab.com/mmsegmentation/v0.5/point_rend/pointrend_r50_512x1024_80k_cityscapes/pointrend_r50_512x1024_80k_cityscapes-20200715_214714.log.json) | 25 | | PointRend | R-101 | 512x1024 | 80000 | 4.2 | 7.00 | 78.30 | 79.97 | [model](https://download.openmmlab.com/mmsegmentation/v0.5/point_rend/pointrend_r101_512x1024_80k_cityscapes/pointrend_r101_512x1024_80k_cityscapes_20200711_170850-d0ca84be.pth) | [log](https://download.openmmlab.com/mmsegmentation/v0.5/point_rend/pointrend_r101_512x1024_80k_cityscapes/pointrend_r101_512x1024_80k_cityscapes-20200715_214824.log.json) | 26 | 27 | ### ADE20K 28 | 29 | | Method | Backbone | Crop Size | Lr schd | Mem (GB) | Inf time (fps) | mIoU | mIoU(ms+flip) | download | 30 | |-----------|----------|-----------|--------:|---------:|----------------|------:|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 31 | | PointRend | R-50 | 512x512 | 160000 | 5.1 | 17.31 | 37.64 | 39.17 | [model](https://download.openmmlab.com/mmsegmentation/v0.5/point_rend/pointrend_r50_512x512_160k_ade20k/pointrend_r50_512x512_160k_ade20k_20200807_232644-ac3febf2.pth) | [log](https://download.openmmlab.com/mmsegmentation/v0.5/point_rend/pointrend_r50_512x512_160k_ade20k/pointrend_r50_512x512_160k_ade20k-20200807_232644.log.json) | 32 | | PointRend | R-101 | 512x512 | 160000 | 6.1 | 15.50 | 40.02 | 41.60 | [model](https://download.openmmlab.com/mmsegmentation/v0.5/point_rend/pointrend_r101_512x512_160k_ade20k/pointrend_r101_512x512_160k_ade20k_20200808_030852-8834902a.pth) | [log](https://download.openmmlab.com/mmsegmentation/v0.5/point_rend/pointrend_r101_512x512_160k_ade20k/pointrend_r101_512x512_160k_ade20k-20200808_030852.log.json) | 33 | --------------------------------------------------------------------------------