├── Testing ├── models │ ├── __init__.py │ ├── fanet │ │ ├── __init__.py │ │ ├── modules │ │ │ ├── __init__.py │ │ │ ├── src │ │ │ │ ├── checks.h │ │ │ │ ├── utils │ │ │ │ │ ├── checks.h │ │ │ │ │ ├── common.h │ │ │ │ │ └── cuda.cuh │ │ │ │ ├── inplace_abn.cpp │ │ │ │ ├── inplace_abn.h │ │ │ │ └── inplace_abn_cpu.cpp │ │ │ ├── misc.py │ │ │ ├── dense.py │ │ │ ├── deeplab.py │ │ │ ├── residual.py │ │ │ └── bn.py │ │ └── fanet.py │ ├── icnet │ │ └── __init__.py │ ├── shelfnet │ │ ├── __init__.py │ │ ├── modules │ │ │ ├── __init__.py │ │ │ ├── src │ │ │ │ ├── checks.h │ │ │ │ ├── utils │ │ │ │ │ ├── checks.h │ │ │ │ │ ├── common.h │ │ │ │ │ └── cuda.cuh │ │ │ │ ├── inplace_abn.cpp │ │ │ │ ├── inplace_abn.h │ │ │ │ └── inplace_abn_cpu.cpp │ │ │ ├── misc.py │ │ │ ├── dense.py │ │ │ ├── deeplab.py │ │ │ ├── residual.py │ │ │ └── bn.py │ │ ├── resnet.py │ │ └── shelfnet.py │ ├── swiftnet │ │ ├── __init__.py │ │ ├── resnet │ │ │ └── __init__.py │ │ ├── semseg.py │ │ └── util.py │ ├── bisenet │ │ ├── __init__.py │ │ └── modules │ │ │ ├── __init__.py │ │ │ ├── src │ │ │ ├── checks.h │ │ │ ├── utils │ │ │ │ ├── checks.h │ │ │ │ ├── common.h │ │ │ │ └── cuda.cuh │ │ │ ├── inplace_abn.cpp │ │ │ ├── inplace_abn.h │ │ │ └── inplace_abn_cpu.cpp │ │ │ ├── misc.py │ │ │ ├── dense.py │ │ │ ├── deeplab.py │ │ │ ├── residual.py │ │ │ └── bn.py │ ├── erfnet │ │ └── erfnet.py │ └── segnet │ │ └── segnet.py ├── readme.md └── speeding.py ├── Train ├── ptsemseg │ ├── __init__.py │ ├── models │ │ ├── fanet │ │ │ ├── __init__.py │ │ │ ├── ._fanet.py │ │ │ └── modules │ │ │ │ ├── __init__.py │ │ │ │ ├── src │ │ │ │ ├── checks.h │ │ │ │ ├── utils │ │ │ │ │ ├── checks.h │ │ │ │ │ ├── common.h │ │ │ │ │ └── cuda.cuh │ │ │ │ ├── inplace_abn.cpp │ │ │ │ ├── inplace_abn.h │ │ │ │ └── inplace_abn_cpu.cpp │ │ │ │ ├── misc.py │ │ │ │ ├── dense.py │ │ │ │ ├── deeplab.py │ │ │ │ ├── residual.py │ │ │ │ └── bn.py │ │ ├── .DS_Store │ │ ├── ._.DS_Store │ │ └── __init__.py │ ├── loader │ │ ├── __init__.py │ │ ├── ccri_loader.py │ │ ├── context_loader.py │ │ ├── ade20k_loader.py │ │ ├── cocostuff_loader.py │ │ └── cityscapes_loader.py │ ├── loss │ │ ├── __init__.py │ │ └── loss.py │ ├── optimizers │ │ ├── __init__.py │ │ └── adaoptimizer.py │ ├── augmentations │ │ └── __init__.py │ ├── schedulers │ │ ├── __init__.py │ │ └── schedulers.py │ ├── utils.py │ └── metrics.py ├── test_fa_res.sh ├── run_fa_res.sh └── configs │ └── FA_Res18_CCRI.yml ├── License └── README.md /Testing/models/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Train/ptsemseg/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Testing/models/fanet/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Testing/models/icnet/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Testing/models/shelfnet/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Testing/models/swiftnet/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Testing/models/swiftnet/resnet/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Testing/models/bisenet/__init__.py: -------------------------------------------------------------------------------- 1 | from .bisenet import * -------------------------------------------------------------------------------- /Train/ptsemseg/models/fanet/__init__.py: -------------------------------------------------------------------------------- 1 | from .fanet import * 2 | -------------------------------------------------------------------------------- /Train/test_fa_res.sh: -------------------------------------------------------------------------------- 1 | 2 | python validate_ss.py --config ./configs/FA_Res18_CCRI.yml 3 | -------------------------------------------------------------------------------- /Train/ptsemseg/models/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinanshan/FANet/HEAD/Train/ptsemseg/models/.DS_Store -------------------------------------------------------------------------------- /Train/ptsemseg/models/._.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinanshan/FANet/HEAD/Train/ptsemseg/models/._.DS_Store -------------------------------------------------------------------------------- /Train/ptsemseg/models/fanet/._fanet.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feinanshan/FANet/HEAD/Train/ptsemseg/models/fanet/._fanet.py -------------------------------------------------------------------------------- /Train/run_fa_res.sh: -------------------------------------------------------------------------------- 1 | python -m torch.distributed.launch --nproc_per_node=1 --master_port=44248 train.py --config ./configs/FA_Res18_CCRI.yml 2 | -------------------------------------------------------------------------------- /Testing/readme.md: -------------------------------------------------------------------------------- 1 | - Run `CUDA_VISIBLE_DEVICES=1 python3 speeding.py` for speed comparison 2 | - In our paper, we adopt a single Titan X GPU for evaluation. 3 | - We don't consider the Batch Normalization layer when evaluatin speed, as it can be incorporated into Conv layers. 4 | -------------------------------------------------------------------------------- /Testing/models/bisenet/modules/__init__.py: -------------------------------------------------------------------------------- 1 | from .bn import ABN, InPlaceABN, InPlaceABNSync 2 | from .functions import ACT_RELU, ACT_LEAKY_RELU, ACT_ELU, ACT_NONE 3 | from .misc import GlobalAvgPool2d, SingleGPU 4 | from .residual import IdentityResidualBlock 5 | from .dense import DenseModule 6 | -------------------------------------------------------------------------------- /Testing/models/fanet/modules/__init__.py: -------------------------------------------------------------------------------- 1 | from .bn import ABN, InPlaceABN, InPlaceABNSync 2 | from .functions import ACT_RELU, ACT_LEAKY_RELU, ACT_ELU, ACT_NONE 3 | from .misc import GlobalAvgPool2d, SingleGPU 4 | from .residual import IdentityResidualBlock 5 | from .dense import DenseModule 6 | -------------------------------------------------------------------------------- /Testing/models/shelfnet/modules/__init__.py: -------------------------------------------------------------------------------- 1 | from .bn import ABN, InPlaceABN, InPlaceABNSync 2 | from .functions import ACT_RELU, ACT_LEAKY_RELU, ACT_ELU, ACT_NONE 3 | from .misc import GlobalAvgPool2d, SingleGPU 4 | from .residual import IdentityResidualBlock 5 | from .dense import DenseModule 6 | -------------------------------------------------------------------------------- /Train/ptsemseg/models/fanet/modules/__init__.py: -------------------------------------------------------------------------------- 1 | from .bn import ABN, InPlaceABN, InPlaceABNSync 2 | from .functions import ACT_RELU, ACT_LEAKY_RELU, ACT_ELU, ACT_NONE 3 | from .misc import GlobalAvgPool2d, SingleGPU 4 | from .residual import IdentityResidualBlock 5 | from .dense import DenseModule 6 | -------------------------------------------------------------------------------- /Testing/models/bisenet/modules/src/checks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Define AT_CHECK for old version of ATen where the same function was called AT_ASSERT 6 | #ifndef AT_CHECK 7 | #define AT_CHECK AT_ASSERT 8 | #endif 9 | 10 | #define CHECK_CUDA(x) AT_CHECK((x).type().is_cuda(), #x " must be a CUDA tensor") 11 | #define CHECK_CPU(x) AT_CHECK(!(x).type().is_cuda(), #x " must be a CPU tensor") 12 | #define CHECK_CONTIGUOUS(x) AT_CHECK((x).is_contiguous(), #x " must be contiguous") 13 | 14 | #define CHECK_CUDA_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x) 15 | #define CHECK_CPU_INPUT(x) CHECK_CPU(x); CHECK_CONTIGUOUS(x) -------------------------------------------------------------------------------- /Testing/models/fanet/modules/src/checks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Define AT_CHECK for old version of ATen where the same function was called AT_ASSERT 6 | #ifndef AT_CHECK 7 | #define AT_CHECK AT_ASSERT 8 | #endif 9 | 10 | #define CHECK_CUDA(x) AT_CHECK((x).type().is_cuda(), #x " must be a CUDA tensor") 11 | #define CHECK_CPU(x) AT_CHECK(!(x).type().is_cuda(), #x " must be a CPU tensor") 12 | #define CHECK_CONTIGUOUS(x) AT_CHECK((x).is_contiguous(), #x " must be contiguous") 13 | 14 | #define CHECK_CUDA_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x) 15 | #define CHECK_CPU_INPUT(x) CHECK_CPU(x); CHECK_CONTIGUOUS(x) -------------------------------------------------------------------------------- /Testing/models/fanet/modules/src/utils/checks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Define AT_CHECK for old version of ATen where the same function was called AT_ASSERT 6 | #ifndef AT_CHECK 7 | #define AT_CHECK AT_ASSERT 8 | #endif 9 | 10 | #define CHECK_CUDA(x) AT_CHECK((x).type().is_cuda(), #x " must be a CUDA tensor") 11 | #define CHECK_CPU(x) AT_CHECK(!(x).type().is_cuda(), #x " must be a CPU tensor") 12 | #define CHECK_CONTIGUOUS(x) AT_CHECK((x).is_contiguous(), #x " must be contiguous") 13 | 14 | #define CHECK_CUDA_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x) 15 | #define CHECK_CPU_INPUT(x) CHECK_CPU(x); CHECK_CONTIGUOUS(x) -------------------------------------------------------------------------------- /Testing/models/shelfnet/modules/src/checks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Define AT_CHECK for old version of ATen where the same function was called AT_ASSERT 6 | #ifndef AT_CHECK 7 | #define AT_CHECK AT_ASSERT 8 | #endif 9 | 10 | #define CHECK_CUDA(x) AT_CHECK((x).type().is_cuda(), #x " must be a CUDA tensor") 11 | #define CHECK_CPU(x) AT_CHECK(!(x).type().is_cuda(), #x " must be a CPU tensor") 12 | #define CHECK_CONTIGUOUS(x) AT_CHECK((x).is_contiguous(), #x " must be contiguous") 13 | 14 | #define CHECK_CUDA_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x) 15 | #define CHECK_CPU_INPUT(x) CHECK_CPU(x); CHECK_CONTIGUOUS(x) -------------------------------------------------------------------------------- /Train/ptsemseg/models/fanet/modules/src/checks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Define AT_CHECK for old version of ATen where the same function was called AT_ASSERT 6 | #ifndef AT_CHECK 7 | #define AT_CHECK AT_ASSERT 8 | #endif 9 | 10 | #define CHECK_CUDA(x) AT_CHECK((x).type().is_cuda(), #x " must be a CUDA tensor") 11 | #define CHECK_CPU(x) AT_CHECK(!(x).type().is_cuda(), #x " must be a CPU tensor") 12 | #define CHECK_CONTIGUOUS(x) AT_CHECK((x).is_contiguous(), #x " must be contiguous") 13 | 14 | #define CHECK_CUDA_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x) 15 | #define CHECK_CPU_INPUT(x) CHECK_CPU(x); CHECK_CONTIGUOUS(x) -------------------------------------------------------------------------------- /Testing/models/bisenet/modules/src/utils/checks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Define AT_CHECK for old version of ATen where the same function was called AT_ASSERT 6 | #ifndef AT_CHECK 7 | #define AT_CHECK AT_ASSERT 8 | #endif 9 | 10 | #define CHECK_CUDA(x) AT_CHECK((x).type().is_cuda(), #x " must be a CUDA tensor") 11 | #define CHECK_CPU(x) AT_CHECK(!(x).type().is_cuda(), #x " must be a CPU tensor") 12 | #define CHECK_CONTIGUOUS(x) AT_CHECK((x).is_contiguous(), #x " must be contiguous") 13 | 14 | #define CHECK_CUDA_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x) 15 | #define CHECK_CPU_INPUT(x) CHECK_CPU(x); CHECK_CONTIGUOUS(x) -------------------------------------------------------------------------------- /Testing/models/shelfnet/modules/src/utils/checks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Define AT_CHECK for old version of ATen where the same function was called AT_ASSERT 6 | #ifndef AT_CHECK 7 | #define AT_CHECK AT_ASSERT 8 | #endif 9 | 10 | #define CHECK_CUDA(x) AT_CHECK((x).type().is_cuda(), #x " must be a CUDA tensor") 11 | #define CHECK_CPU(x) AT_CHECK(!(x).type().is_cuda(), #x " must be a CPU tensor") 12 | #define CHECK_CONTIGUOUS(x) AT_CHECK((x).is_contiguous(), #x " must be contiguous") 13 | 14 | #define CHECK_CUDA_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x) 15 | #define CHECK_CPU_INPUT(x) CHECK_CPU(x); CHECK_CONTIGUOUS(x) -------------------------------------------------------------------------------- /Train/ptsemseg/models/fanet/modules/src/utils/checks.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Define AT_CHECK for old version of ATen where the same function was called AT_ASSERT 6 | #ifndef AT_CHECK 7 | #define AT_CHECK AT_ASSERT 8 | #endif 9 | 10 | #define CHECK_CUDA(x) AT_CHECK((x).type().is_cuda(), #x " must be a CUDA tensor") 11 | #define CHECK_CPU(x) AT_CHECK(!(x).type().is_cuda(), #x " must be a CPU tensor") 12 | #define CHECK_CONTIGUOUS(x) AT_CHECK((x).is_contiguous(), #x " must be contiguous") 13 | 14 | #define CHECK_CUDA_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x) 15 | #define CHECK_CPU_INPUT(x) CHECK_CPU(x); CHECK_CONTIGUOUS(x) -------------------------------------------------------------------------------- /Train/ptsemseg/loader/__init__.py: -------------------------------------------------------------------------------- 1 | import json 2 | from ptsemseg.loader.cityscapes_loader import cityscapesLoader 3 | from ptsemseg.loader.context_loader import contextLoader 4 | from ptsemseg.loader.ade20k_loader import ade20kLoader 5 | from ptsemseg.loader.cocostuff_loader import cocostuffLoader 6 | from ptsemseg.loader.ccri_loader import CCRILoader 7 | 8 | 9 | def get_loader(name): 10 | """get_loader 11 | 12 | :param name: 13 | """ 14 | return { 15 | "cityscapes": cityscapesLoader, 16 | "pascal_context": contextLoader, 17 | "ade20k": ade20kLoader, 18 | "cocostuff": cocostuffLoader, 19 | "ccri": CCRILoader, 20 | }[name] 21 | -------------------------------------------------------------------------------- /Testing/models/fanet/modules/misc.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import torch 3 | import torch.distributed as dist 4 | 5 | class GlobalAvgPool2d(nn.Module): 6 | def __init__(self): 7 | """Global average pooling over the input's spatial dimensions""" 8 | super(GlobalAvgPool2d, self).__init__() 9 | 10 | def forward(self, inputs): 11 | in_size = inputs.size() 12 | return inputs.view((in_size[0], in_size[1], -1)).mean(dim=2) 13 | 14 | class SingleGPU(nn.Module): 15 | def __init__(self, module): 16 | super(SingleGPU, self).__init__() 17 | self.module=module 18 | 19 | def forward(self, input): 20 | return self.module(input.cuda(non_blocking=True)) 21 | 22 | -------------------------------------------------------------------------------- /Testing/models/bisenet/modules/misc.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import torch 3 | import torch.distributed as dist 4 | 5 | class GlobalAvgPool2d(nn.Module): 6 | def __init__(self): 7 | """Global average pooling over the input's spatial dimensions""" 8 | super(GlobalAvgPool2d, self).__init__() 9 | 10 | def forward(self, inputs): 11 | in_size = inputs.size() 12 | return inputs.view((in_size[0], in_size[1], -1)).mean(dim=2) 13 | 14 | class SingleGPU(nn.Module): 15 | def __init__(self, module): 16 | super(SingleGPU, self).__init__() 17 | self.module=module 18 | 19 | def forward(self, input): 20 | return self.module(input.cuda(non_blocking=True)) 21 | 22 | -------------------------------------------------------------------------------- /Testing/models/shelfnet/modules/misc.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import torch 3 | import torch.distributed as dist 4 | 5 | class GlobalAvgPool2d(nn.Module): 6 | def __init__(self): 7 | """Global average pooling over the input's spatial dimensions""" 8 | super(GlobalAvgPool2d, self).__init__() 9 | 10 | def forward(self, inputs): 11 | in_size = inputs.size() 12 | return inputs.view((in_size[0], in_size[1], -1)).mean(dim=2) 13 | 14 | class SingleGPU(nn.Module): 15 | def __init__(self, module): 16 | super(SingleGPU, self).__init__() 17 | self.module=module 18 | 19 | def forward(self, input): 20 | return self.module(input.cuda(non_blocking=True)) 21 | 22 | -------------------------------------------------------------------------------- /Train/ptsemseg/models/fanet/modules/misc.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import torch 3 | import torch.distributed as dist 4 | 5 | class GlobalAvgPool2d(nn.Module): 6 | def __init__(self): 7 | """Global average pooling over the input's spatial dimensions""" 8 | super(GlobalAvgPool2d, self).__init__() 9 | 10 | def forward(self, inputs): 11 | in_size = inputs.size() 12 | return inputs.view((in_size[0], in_size[1], -1)).mean(dim=2) 13 | 14 | class SingleGPU(nn.Module): 15 | def __init__(self, module): 16 | super(SingleGPU, self).__init__() 17 | self.module=module 18 | 19 | def forward(self, input): 20 | return self.module(input.cuda(non_blocking=True)) 21 | 22 | -------------------------------------------------------------------------------- /Train/ptsemseg/loss/__init__.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import torch 3 | import functools 4 | 5 | from ptsemseg.loss.loss import ( 6 | CrossEntropyLoss, 7 | OhemCELoss2D, 8 | ) 9 | 10 | 11 | logger = logging.getLogger("ptsemseg") 12 | 13 | key2loss = { 14 | "CrossEntropyLoss": CrossEntropyLoss, 15 | "OhemCELoss2D": OhemCELoss2D, 16 | } 17 | 18 | 19 | def get_loss_function(cfg): 20 | assert(cfg["loss"] is not None) 21 | loss_dict = cfg["loss"] 22 | loss_name = loss_dict["name"] 23 | loss_params = {k: v for k, v in loss_dict.items() if k != "name"} 24 | if loss_name not in key2loss: 25 | raise NotImplementedError("Loss {} not implemented".format(loss_name)) 26 | 27 | if loss_name == "OhemCELoss2D": 28 | n_img_per_gpu = int(cfg["batch_size"]/torch.cuda.device_count()) 29 | cropsize = cfg["train_augmentations"]["rcrop"] 30 | n_min = n_img_per_gpu * cropsize[0] * cropsize[1] // 16 31 | loss_params["n_min"] = n_min 32 | 33 | logger.info("Using {} with {} params".format(loss_name, loss_params)) 34 | return key2loss[loss_name](**loss_params) 35 | -------------------------------------------------------------------------------- /License: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Ping Hu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Train/ptsemseg/optimizers/__init__.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import copy 3 | 4 | from torch.optim import SGD, Adam, ASGD, Adamax, Adadelta, Adagrad, RMSprop 5 | from .adaoptimizer import AdaOptimizer 6 | 7 | key2opt = { 8 | "sgd": SGD, 9 | "adam": Adam, 10 | "asgd": ASGD, 11 | "adamax": Adamax, 12 | "adadelta": Adadelta, 13 | "adagrad": Adagrad, 14 | "rmsprop": RMSprop, 15 | "adaoptimizer": AdaOptimizer, 16 | } 17 | 18 | 19 | def get_optimizer(cfg, model): 20 | if cfg["optimizer"] is None: 21 | return SGD(model.parameters()) 22 | 23 | else: 24 | opt_name = cfg["optimizer"]["name"] 25 | if opt_name not in key2opt: 26 | raise NotImplementedError("Optimizer {} not implemented".format(opt_name)) 27 | 28 | optimizer_cls = key2opt[opt_name] 29 | if opt_name == "adaoptimizer": 30 | param_dict = copy.deepcopy(cfg["optimizer"]) 31 | param_dict.pop("name") 32 | optimizer = optimizer_cls(model, **param_dict) # module for multi GPU 33 | 34 | else: 35 | param_dict = copy.deepcopy(cfg["optimizer"]) 36 | param_dict.pop("name") 37 | optimizer = optimizer_cls(model.parameters(), **param_dict) 38 | 39 | return optimizer 40 | -------------------------------------------------------------------------------- /Train/ptsemseg/augmentations/__init__.py: -------------------------------------------------------------------------------- 1 | from ptsemseg.augmentations.augmentations import ( 2 | AdjustContrast, 3 | AdjustGamma, 4 | AdjustBrightness, 5 | AdjustSaturation, 6 | AdjustHue, 7 | RandomCrop, 8 | RandomHorizontallyFlip, 9 | RandomVerticallyFlip, 10 | Scale, 11 | RandomScale, 12 | RandomSizedCrop, 13 | RandomRotate, 14 | RandomTranslate, 15 | CenterCrop, 16 | Compose, 17 | Normalize, 18 | Color_Normalize, 19 | BGR, 20 | ) 21 | 22 | 23 | key2aug = { 24 | "gamma": AdjustGamma, 25 | "hue": AdjustHue, 26 | "brightness": AdjustBrightness, 27 | "saturation": AdjustSaturation, 28 | "contrast": AdjustContrast, 29 | "rcrop": RandomCrop, 30 | "hflip": RandomHorizontallyFlip, 31 | "vflip": RandomVerticallyFlip, 32 | "scale": Scale, 33 | "rscale": RandomScale, 34 | "rsizecrop": RandomSizedCrop, 35 | "rotate": RandomRotate, 36 | "translate": RandomTranslate, 37 | "ccrop": CenterCrop, 38 | "cnorm": Color_Normalize, 39 | "norm": Normalize, 40 | "bgr": BGR, 41 | } 42 | 43 | 44 | def get_composed_augmentations(aug_dict): 45 | 46 | 47 | augmentations = [] 48 | for aug_key, aug_param in aug_dict.items(): 49 | augmentations.append(key2aug[aug_key](aug_param)) 50 | return Compose(augmentations) 51 | -------------------------------------------------------------------------------- /Train/ptsemseg/models/__init__.py: -------------------------------------------------------------------------------- 1 | import copy 2 | import torchvision.models as models 3 | import torch.nn as nn 4 | 5 | from ptsemseg.models.fanet import FANet 6 | 7 | class BatchNorm2d(nn.BatchNorm2d): 8 | '''(conv => BN => ReLU) * 2''' 9 | 10 | def __init__(self, num_features, activation='none'): 11 | super(BatchNorm2d, self).__init__(num_features=num_features) 12 | if activation == 'leaky_relu': 13 | self.activation = nn.LeakyReLU() 14 | elif activation == 'none': 15 | self.activation = lambda x:x 16 | else: 17 | raise Exception("Accepted activation: ['leaky_relu']") 18 | 19 | def forward(self, x): 20 | return self.activation(super(BatchNorm2d, self).forward(x)) 21 | 22 | 23 | def get_model(model_dict, nclass, loss_fn=None): 24 | name = model_dict["arch"] 25 | model = _get_model_instance(name) 26 | param_dict = copy.deepcopy(model_dict) 27 | param_dict.pop("arch") 28 | param_dict["loss_fn"] = loss_fn 29 | param_dict['norm_layer'] = BatchNorm2d 30 | 31 | model = model(nclass=nclass, **param_dict) 32 | return model 33 | 34 | 35 | def _get_model_instance(name): 36 | try: 37 | return { 38 | "fanet": FANet 39 | }[name] 40 | except: 41 | raise ("Model {} not available".format(name)) 42 | -------------------------------------------------------------------------------- /Train/configs/FA_Res18_CCRI.yml: -------------------------------------------------------------------------------- 1 | model: 2 | arch: fanet 3 | backbone: resnet18 4 | data: 5 | dataset: ccri 6 | train_split: train 7 | val_split: test 8 | img_rows: 720 9 | img_cols: 1280 10 | path: /dataset/CCRI/ 11 | training: 12 | n_workers: 2 13 | train_iters: 40000 14 | batch_size: 16 15 | val_interval: 500 16 | print_interval: 25 17 | loss: 18 | name: OhemCELoss2D 19 | thresh: 0.7 20 | ignore_index: 250 21 | optimizer: 22 | name: adaoptimizer 23 | momentum: 0.9 24 | lr_multi: 1 25 | bn_wd_disable: False 26 | wd: 5.0e-4 27 | lr0: 1.0e-2 28 | max_iter: 40000 29 | power: 0.9 30 | warmup_steps: 1000 31 | warmup_start_lr: 1.0e-5 32 | train_augmentations: 33 | rotate: 5 34 | brightness: 0.5 35 | contrast: 0.5 36 | saturation: 0.5 37 | scale: [512,512] 38 | rscale: [0.5,2] 39 | hflip: 0.5 40 | rcrop: [384,384] 41 | norm: 255.0 42 | cnorm: [[.485, .456, .406],[.229, .224, .225]] 43 | resume: 44 | visdom: False 45 | 46 | validating: 47 | densecrf: False 48 | resume: model_best.pth 49 | n_workers: 1 50 | batch_size: 1 51 | outpath: 52 | val_augmentations: 53 | scale: [512,512] 54 | norm: 255.0 55 | cnorm: [[.485, .456, .406],[.229, .224, .225]] 56 | -------------------------------------------------------------------------------- /Train/ptsemseg/loss/loss.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import math 3 | import torch.nn as nn 4 | 5 | __all__ = ['CrossEntropyLoss', 'OhemCELoss2D'] 6 | 7 | class CrossEntropyLoss(nn.CrossEntropyLoss): 8 | """2D Cross Entropy Loss with Auxilary Loss""" 9 | def __init__(self, 10 | weight=None, 11 | ignore_index=-1): 12 | 13 | super(CrossEntropyLoss, self).__init__(weight, None, ignore_index) 14 | 15 | def forward(self, pred, target): 16 | return super(CrossEntropyLoss, self).forward(pred, target) 17 | 18 | 19 | 20 | class OhemCELoss2D(nn.CrossEntropyLoss): 21 | """2D Cross Entropy Loss with Auxilary Loss""" 22 | def __init__(self, 23 | n_min, 24 | thresh=0.7, 25 | ignore_index=-1): 26 | 27 | super(OhemCELoss2D, self).__init__(None, None, ignore_index, reduction='none') 28 | 29 | self.thresh = -math.log(thresh) 30 | self.n_min = n_min 31 | self.ignore_index = ignore_index 32 | 33 | 34 | def forward(self, pred, target): 35 | return self.OhemCELoss(pred, target) 36 | 37 | def OhemCELoss(self, logits, labels): 38 | N, C, H, W = logits.size() 39 | loss = super(OhemCELoss2D, self).forward(logits, labels).view(-1) 40 | loss, _ = torch.sort(loss, descending=True) 41 | if loss[self.n_min] > self.thresh: 42 | loss = loss[loss>self.thresh] 43 | else: 44 | loss = loss[:self.n_min] 45 | return torch.mean(loss) -------------------------------------------------------------------------------- /Testing/models/swiftnet/semseg.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | from itertools import chain 4 | 5 | from .resnet.resnet_single_scale import resnet18 6 | from .util import _BNReluConv, upsample 7 | 8 | 9 | class SwiftNet(nn.Module): 10 | def __init__(self, num_classes=19, use_bn=False): 11 | super(SwiftNet, self).__init__() 12 | self.backbone = resnet18(use_bn=False) 13 | self.num_classes = num_classes 14 | self.logits = _BNReluConv(self.backbone.num_features, self.num_classes, batch_norm=use_bn) 15 | 16 | def forward(self, pyramid): 17 | features = self.backbone(pyramid) 18 | logits = self.logits.forward(features[0]) 19 | return logits 20 | 21 | def prepare_data(self, batch, image_size, device=torch.device('cuda')): 22 | if image_size is None: 23 | image_size = batch['target_size'] 24 | pyramid = [p.clone().detach().requires_grad_(False).to(device) for p in batch['pyramid']] 25 | return { 26 | 'pyramid': pyramid, 27 | 'image_size': image_size, 28 | 'target_size': batch['target_size_feats'] 29 | } 30 | 31 | def do_forward(self, batch, image_size=None): 32 | data = self.prepare_data(batch, image_size) 33 | return self.forward(**data) 34 | 35 | def random_init_params(self): 36 | return chain(*([self.logits.parameters(), self.backbone.random_init_params()])) 37 | 38 | def fine_tune_params(self): 39 | return self.backbone.fine_tune_params() 40 | -------------------------------------------------------------------------------- /Testing/models/fanet/modules/dense.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | import torch 4 | import torch.nn as nn 5 | 6 | from .bn import ABN 7 | 8 | 9 | class DenseModule(nn.Module): 10 | def __init__(self, in_channels, growth, layers, bottleneck_factor=4, norm_act=ABN, dilation=1): 11 | super(DenseModule, self).__init__() 12 | self.in_channels = in_channels 13 | self.growth = growth 14 | self.layers = layers 15 | 16 | self.convs1 = nn.ModuleList() 17 | self.convs3 = nn.ModuleList() 18 | for i in range(self.layers): 19 | self.convs1.append(nn.Sequential(OrderedDict([ 20 | ("bn", norm_act(in_channels)), 21 | ("conv", nn.Conv2d(in_channels, self.growth * bottleneck_factor, 1, bias=False)) 22 | ]))) 23 | self.convs3.append(nn.Sequential(OrderedDict([ 24 | ("bn", norm_act(self.growth * bottleneck_factor)), 25 | ("conv", nn.Conv2d(self.growth * bottleneck_factor, self.growth, 3, padding=dilation, bias=False, 26 | dilation=dilation)) 27 | ]))) 28 | in_channels += self.growth 29 | 30 | @property 31 | def out_channels(self): 32 | return self.in_channels + self.growth * self.layers 33 | 34 | def forward(self, x): 35 | inputs = [x] 36 | for i in range(self.layers): 37 | x = torch.cat(inputs, dim=1) 38 | x = self.convs1[i](x) 39 | x = self.convs3[i](x) 40 | inputs += [x] 41 | 42 | return torch.cat(inputs, dim=1) 43 | -------------------------------------------------------------------------------- /Testing/models/bisenet/modules/dense.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | import torch 4 | import torch.nn as nn 5 | 6 | from .bn import ABN 7 | 8 | 9 | class DenseModule(nn.Module): 10 | def __init__(self, in_channels, growth, layers, bottleneck_factor=4, norm_act=ABN, dilation=1): 11 | super(DenseModule, self).__init__() 12 | self.in_channels = in_channels 13 | self.growth = growth 14 | self.layers = layers 15 | 16 | self.convs1 = nn.ModuleList() 17 | self.convs3 = nn.ModuleList() 18 | for i in range(self.layers): 19 | self.convs1.append(nn.Sequential(OrderedDict([ 20 | ("bn", norm_act(in_channels)), 21 | ("conv", nn.Conv2d(in_channels, self.growth * bottleneck_factor, 1, bias=False)) 22 | ]))) 23 | self.convs3.append(nn.Sequential(OrderedDict([ 24 | ("bn", norm_act(self.growth * bottleneck_factor)), 25 | ("conv", nn.Conv2d(self.growth * bottleneck_factor, self.growth, 3, padding=dilation, bias=False, 26 | dilation=dilation)) 27 | ]))) 28 | in_channels += self.growth 29 | 30 | @property 31 | def out_channels(self): 32 | return self.in_channels + self.growth * self.layers 33 | 34 | def forward(self, x): 35 | inputs = [x] 36 | for i in range(self.layers): 37 | x = torch.cat(inputs, dim=1) 38 | x = self.convs1[i](x) 39 | x = self.convs3[i](x) 40 | inputs += [x] 41 | 42 | return torch.cat(inputs, dim=1) 43 | -------------------------------------------------------------------------------- /Testing/models/shelfnet/modules/dense.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | import torch 4 | import torch.nn as nn 5 | 6 | from .bn import ABN 7 | 8 | 9 | class DenseModule(nn.Module): 10 | def __init__(self, in_channels, growth, layers, bottleneck_factor=4, norm_act=ABN, dilation=1): 11 | super(DenseModule, self).__init__() 12 | self.in_channels = in_channels 13 | self.growth = growth 14 | self.layers = layers 15 | 16 | self.convs1 = nn.ModuleList() 17 | self.convs3 = nn.ModuleList() 18 | for i in range(self.layers): 19 | self.convs1.append(nn.Sequential(OrderedDict([ 20 | ("bn", norm_act(in_channels)), 21 | ("conv", nn.Conv2d(in_channels, self.growth * bottleneck_factor, 1, bias=False)) 22 | ]))) 23 | self.convs3.append(nn.Sequential(OrderedDict([ 24 | ("bn", norm_act(self.growth * bottleneck_factor)), 25 | ("conv", nn.Conv2d(self.growth * bottleneck_factor, self.growth, 3, padding=dilation, bias=False, 26 | dilation=dilation)) 27 | ]))) 28 | in_channels += self.growth 29 | 30 | @property 31 | def out_channels(self): 32 | return self.in_channels + self.growth * self.layers 33 | 34 | def forward(self, x): 35 | inputs = [x] 36 | for i in range(self.layers): 37 | x = torch.cat(inputs, dim=1) 38 | x = self.convs1[i](x) 39 | x = self.convs3[i](x) 40 | inputs += [x] 41 | 42 | return torch.cat(inputs, dim=1) 43 | -------------------------------------------------------------------------------- /Testing/models/bisenet/modules/src/utils/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | /* 6 | * Functions to share code between CPU and GPU 7 | */ 8 | 9 | #ifdef __CUDACC__ 10 | // CUDA versions 11 | 12 | #define HOST_DEVICE __host__ __device__ 13 | #define INLINE_HOST_DEVICE __host__ __device__ inline 14 | #define FLOOR(x) floor(x) 15 | 16 | #if __CUDA_ARCH__ >= 600 17 | // Recent compute capabilities have block-level atomicAdd for all data types, so we use that 18 | #define ACCUM(x,y) atomicAdd_block(&(x),(y)) 19 | #else 20 | // Older architectures don't have block-level atomicAdd, nor atomicAdd for doubles, so we defer to atomicAdd for float 21 | // and use the known atomicCAS-based implementation for double 22 | template 23 | __device__ inline data_t atomic_add(data_t *address, data_t val) { 24 | return atomicAdd(address, val); 25 | } 26 | 27 | template<> 28 | __device__ inline double atomic_add(double *address, double val) { 29 | unsigned long long int* address_as_ull = (unsigned long long int*)address; 30 | unsigned long long int old = *address_as_ull, assumed; 31 | do { 32 | assumed = old; 33 | old = atomicCAS(address_as_ull, assumed, __double_as_longlong(val + __longlong_as_double(assumed))); 34 | } while (assumed != old); 35 | return __longlong_as_double(old); 36 | } 37 | 38 | #define ACCUM(x,y) atomic_add(&(x),(y)) 39 | #endif // #if __CUDA_ARCH__ >= 600 40 | 41 | #else 42 | // CPU versions 43 | 44 | #define HOST_DEVICE 45 | #define INLINE_HOST_DEVICE inline 46 | #define FLOOR(x) std::floor(x) 47 | #define ACCUM(x,y) (x) += (y) 48 | 49 | #endif // #ifdef __CUDACC__ -------------------------------------------------------------------------------- /Testing/models/fanet/modules/src/utils/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | /* 6 | * Functions to share code between CPU and GPU 7 | */ 8 | 9 | #ifdef __CUDACC__ 10 | // CUDA versions 11 | 12 | #define HOST_DEVICE __host__ __device__ 13 | #define INLINE_HOST_DEVICE __host__ __device__ inline 14 | #define FLOOR(x) floor(x) 15 | 16 | #if __CUDA_ARCH__ >= 600 17 | // Recent compute capabilities have block-level atomicAdd for all data types, so we use that 18 | #define ACCUM(x,y) atomicAdd_block(&(x),(y)) 19 | #else 20 | // Older architectures don't have block-level atomicAdd, nor atomicAdd for doubles, so we defer to atomicAdd for float 21 | // and use the known atomicCAS-based implementation for double 22 | template 23 | __device__ inline data_t atomic_add(data_t *address, data_t val) { 24 | return atomicAdd(address, val); 25 | } 26 | 27 | template<> 28 | __device__ inline double atomic_add(double *address, double val) { 29 | unsigned long long int* address_as_ull = (unsigned long long int*)address; 30 | unsigned long long int old = *address_as_ull, assumed; 31 | do { 32 | assumed = old; 33 | old = atomicCAS(address_as_ull, assumed, __double_as_longlong(val + __longlong_as_double(assumed))); 34 | } while (assumed != old); 35 | return __longlong_as_double(old); 36 | } 37 | 38 | #define ACCUM(x,y) atomic_add(&(x),(y)) 39 | #endif // #if __CUDA_ARCH__ >= 600 40 | 41 | #else 42 | // CPU versions 43 | 44 | #define HOST_DEVICE 45 | #define INLINE_HOST_DEVICE inline 46 | #define FLOOR(x) std::floor(x) 47 | #define ACCUM(x,y) (x) += (y) 48 | 49 | #endif // #ifdef __CUDACC__ -------------------------------------------------------------------------------- /Train/ptsemseg/models/fanet/modules/dense.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | import torch 4 | import torch.nn as nn 5 | 6 | from .bn import ABN 7 | 8 | 9 | class DenseModule(nn.Module): 10 | def __init__(self, in_channels, growth, layers, bottleneck_factor=4, norm_act=ABN, dilation=1): 11 | super(DenseModule, self).__init__() 12 | self.in_channels = in_channels 13 | self.growth = growth 14 | self.layers = layers 15 | 16 | self.convs1 = nn.ModuleList() 17 | self.convs3 = nn.ModuleList() 18 | for i in range(self.layers): 19 | self.convs1.append(nn.Sequential(OrderedDict([ 20 | ("bn", norm_act(in_channels)), 21 | ("conv", nn.Conv2d(in_channels, self.growth * bottleneck_factor, 1, bias=False)) 22 | ]))) 23 | self.convs3.append(nn.Sequential(OrderedDict([ 24 | ("bn", norm_act(self.growth * bottleneck_factor)), 25 | ("conv", nn.Conv2d(self.growth * bottleneck_factor, self.growth, 3, padding=dilation, bias=False, 26 | dilation=dilation)) 27 | ]))) 28 | in_channels += self.growth 29 | 30 | @property 31 | def out_channels(self): 32 | return self.in_channels + self.growth * self.layers 33 | 34 | def forward(self, x): 35 | inputs = [x] 36 | for i in range(self.layers): 37 | x = torch.cat(inputs, dim=1) 38 | x = self.convs1[i](x) 39 | x = self.convs3[i](x) 40 | inputs += [x] 41 | 42 | return torch.cat(inputs, dim=1) 43 | -------------------------------------------------------------------------------- /Testing/models/shelfnet/modules/src/utils/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | /* 6 | * Functions to share code between CPU and GPU 7 | */ 8 | 9 | #ifdef __CUDACC__ 10 | // CUDA versions 11 | 12 | #define HOST_DEVICE __host__ __device__ 13 | #define INLINE_HOST_DEVICE __host__ __device__ inline 14 | #define FLOOR(x) floor(x) 15 | 16 | #if __CUDA_ARCH__ >= 600 17 | // Recent compute capabilities have block-level atomicAdd for all data types, so we use that 18 | #define ACCUM(x,y) atomicAdd_block(&(x),(y)) 19 | #else 20 | // Older architectures don't have block-level atomicAdd, nor atomicAdd for doubles, so we defer to atomicAdd for float 21 | // and use the known atomicCAS-based implementation for double 22 | template 23 | __device__ inline data_t atomic_add(data_t *address, data_t val) { 24 | return atomicAdd(address, val); 25 | } 26 | 27 | template<> 28 | __device__ inline double atomic_add(double *address, double val) { 29 | unsigned long long int* address_as_ull = (unsigned long long int*)address; 30 | unsigned long long int old = *address_as_ull, assumed; 31 | do { 32 | assumed = old; 33 | old = atomicCAS(address_as_ull, assumed, __double_as_longlong(val + __longlong_as_double(assumed))); 34 | } while (assumed != old); 35 | return __longlong_as_double(old); 36 | } 37 | 38 | #define ACCUM(x,y) atomic_add(&(x),(y)) 39 | #endif // #if __CUDA_ARCH__ >= 600 40 | 41 | #else 42 | // CPU versions 43 | 44 | #define HOST_DEVICE 45 | #define INLINE_HOST_DEVICE inline 46 | #define FLOOR(x) std::floor(x) 47 | #define ACCUM(x,y) (x) += (y) 48 | 49 | #endif // #ifdef __CUDACC__ -------------------------------------------------------------------------------- /Train/ptsemseg/models/fanet/modules/src/utils/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | /* 6 | * Functions to share code between CPU and GPU 7 | */ 8 | 9 | #ifdef __CUDACC__ 10 | // CUDA versions 11 | 12 | #define HOST_DEVICE __host__ __device__ 13 | #define INLINE_HOST_DEVICE __host__ __device__ inline 14 | #define FLOOR(x) floor(x) 15 | 16 | #if __CUDA_ARCH__ >= 600 17 | // Recent compute capabilities have block-level atomicAdd for all data types, so we use that 18 | #define ACCUM(x,y) atomicAdd_block(&(x),(y)) 19 | #else 20 | // Older architectures don't have block-level atomicAdd, nor atomicAdd for doubles, so we defer to atomicAdd for float 21 | // and use the known atomicCAS-based implementation for double 22 | template 23 | __device__ inline data_t atomic_add(data_t *address, data_t val) { 24 | return atomicAdd(address, val); 25 | } 26 | 27 | template<> 28 | __device__ inline double atomic_add(double *address, double val) { 29 | unsigned long long int* address_as_ull = (unsigned long long int*)address; 30 | unsigned long long int old = *address_as_ull, assumed; 31 | do { 32 | assumed = old; 33 | old = atomicCAS(address_as_ull, assumed, __double_as_longlong(val + __longlong_as_double(assumed))); 34 | } while (assumed != old); 35 | return __longlong_as_double(old); 36 | } 37 | 38 | #define ACCUM(x,y) atomic_add(&(x),(y)) 39 | #endif // #if __CUDA_ARCH__ >= 600 40 | 41 | #else 42 | // CPU versions 43 | 44 | #define HOST_DEVICE 45 | #define INLINE_HOST_DEVICE inline 46 | #define FLOOR(x) std::floor(x) 47 | #define ACCUM(x,y) (x) += (y) 48 | 49 | #endif // #ifdef __CUDACC__ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FANet 2 | Real-time Semantic Segmentation with Fast Attention 3 | 4 | [Ping Hu](http://cs-people.bu.edu/pinghu/), [Federico Perazzi](https://fperazzi.github.io/), [Fabian Caba Heilbron](http://fabiancaba.com/), [Oliver Wang](http://www.oliverwang.info/), [Zhe Lin](http://sites.google.com/site/zhelin625/), [Kate Saenko](http://ai.bu.edu/ksaenko.html/) , [Stan Sclaroff](http://www.cs.bu.edu/~sclaroff/) 5 | 6 | [[Paper Link](https://arxiv.org/abs/2007.03815)] [[Project Page](https://cs-people.bu.edu/pinghu/FANet.html)] 7 | 8 | Accurate semantic segmentation requires rich contextual cues (large receptive fields) and fine spatial details (high resolution), both of which incur high computational costs. In this paper, we propose a novel architecture that addresses both challenges and achieves state-of-the-art performance for semantic segmentation of high-resolution images and videos in real-time. The proposed architecture relies on our fast attention, which is a simple modification of the popular self-attention mechanism and captures the same rich contextual information at a small fraction of the computational cost, by changing the order of operations. Moreover, to efficiently process high-resolution input, we apply an additional spatial reduction to intermediate feature stages of the network with minimal loss in accuracy thanks to the use of the fast attention module to fuse features. We validate our method with a series of experiments, and show that results on multiple datasets demonstrate superior performance with better accuracy and speed compared to existing approaches for real-time semantic segmentation. On Cityscapes, our network achieves 74.4% mIoU at 72 FPS and 75.5% mIoU at 58 FPS on a single Titan X GPU, which is ~50% faster than the state-of-the-art while retaining the same accuracy. 9 | 10 | 11 | -------------------------------------------------------------------------------- /Train/ptsemseg/schedulers/__init__.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from torch.optim.lr_scheduler import MultiStepLR, ExponentialLR, CosineAnnealingLR 4 | 5 | from ptsemseg.schedulers.schedulers import WarmUpLR, ConstantLR, PolynomialLR 6 | 7 | logger = logging.getLogger("ptsemseg") 8 | 9 | key2scheduler = { 10 | "constant_lr": ConstantLR, 11 | "poly_lr": PolynomialLR, 12 | "multi_step": MultiStepLR, 13 | "cosine_annealing": CosineAnnealingLR, 14 | "exp_lr": ExponentialLR, 15 | } 16 | 17 | 18 | def get_scheduler(optimizer, scheduler_dict): 19 | if scheduler_dict is None: 20 | logger.info("Using No LR Scheduling") 21 | return ConstantLR(optimizer) 22 | 23 | s_type = scheduler_dict["name"] 24 | scheduler_dict.pop("name") 25 | 26 | logging.info("Using {} scheduler with {} params".format(s_type, scheduler_dict)) 27 | 28 | warmup_dict = {} 29 | if "warmup_iters" in scheduler_dict: 30 | # This can be done in a more pythonic way... 31 | warmup_dict["warmup_iters"] = scheduler_dict.get("warmup_iters", 100) 32 | warmup_dict["mode"] = scheduler_dict.get("warmup_mode", "linear") 33 | warmup_dict["gamma"] = scheduler_dict.get("warmup_factor", 0.2) 34 | 35 | logger.info( 36 | "Using Warmup with {} iters {} gamma and {} mode".format( 37 | warmup_dict["warmup_iters"], warmup_dict["gamma"], warmup_dict["mode"] 38 | ) 39 | ) 40 | 41 | scheduler_dict.pop("warmup_iters", None) 42 | scheduler_dict.pop("warmup_mode", None) 43 | scheduler_dict.pop("warmup_factor", None) 44 | 45 | base_scheduler = key2scheduler[s_type](optimizer, **scheduler_dict) 46 | return WarmUpLR(optimizer, base_scheduler, **warmup_dict) 47 | 48 | return key2scheduler[s_type](optimizer, **scheduler_dict) 49 | -------------------------------------------------------------------------------- /Train/ptsemseg/schedulers/schedulers.py: -------------------------------------------------------------------------------- 1 | from torch.optim.lr_scheduler import _LRScheduler 2 | 3 | 4 | class ConstantLR(_LRScheduler): 5 | def __init__(self, optimizer, last_epoch=-1): 6 | super(ConstantLR, self).__init__(optimizer, last_epoch) 7 | 8 | def get_lr(self): 9 | return [base_lr for base_lr in self.base_lrs] 10 | 11 | 12 | class PolynomialLR(_LRScheduler): 13 | def __init__(self, optimizer, max_iter, decay_iter=1, gamma=0.9, last_epoch=-1): 14 | self.decay_iter = decay_iter 15 | self.max_iter = max_iter 16 | self.gamma = gamma 17 | super(PolynomialLR, self).__init__(optimizer, last_epoch) 18 | 19 | def get_lr(self): 20 | if self.last_epoch % self.decay_iter or self.last_epoch % self.max_iter: 21 | return [base_lr for base_lr in self.base_lrs] 22 | else: 23 | factor = (1 - self.last_epoch / float(self.max_iter)) ** self.gamma 24 | return [base_lr * factor for base_lr in self.base_lrs] 25 | 26 | 27 | class WarmUpLR(_LRScheduler): 28 | def __init__( 29 | self, optimizer, scheduler, mode="linear", warmup_iters=100, gamma=0.2, last_epoch=-1 30 | ): 31 | self.mode = mode 32 | self.scheduler = scheduler 33 | self.warmup_iters = warmup_iters 34 | self.gamma = gamma 35 | super(WarmUpLR, self).__init__(optimizer, last_epoch) 36 | 37 | def get_lr(self): 38 | cold_lrs = self.scheduler.get_lr() 39 | 40 | if self.last_epoch < self.warmup_iters: 41 | if self.mode == "linear": 42 | alpha = self.last_epoch / float(self.warmup_iters) 43 | factor = self.gamma * (1 - alpha) + alpha 44 | 45 | elif self.mode == "constant": 46 | factor = self.gamma 47 | else: 48 | raise KeyError("WarmUp type {} not implemented".format(self.mode)) 49 | 50 | return [factor * base_lr for base_lr in cold_lrs] 51 | 52 | return cold_lrs 53 | -------------------------------------------------------------------------------- /Train/ptsemseg/utils.py: -------------------------------------------------------------------------------- 1 | """ 2 | Misc Utility functions 3 | """ 4 | import os 5 | import logging 6 | import datetime 7 | import numpy as np 8 | 9 | from collections import OrderedDict 10 | 11 | 12 | def recursive_glob(rootdir=".", suffix=""): 13 | """Performs recursive glob with given suffix and rootdir 14 | :param rootdir is the root directory 15 | :param suffix is the suffix to be searched 16 | """ 17 | return [ 18 | os.path.join(looproot, filename) 19 | for looproot, _, filenames in os.walk(rootdir) 20 | for filename in filenames 21 | if filename.endswith(suffix) 22 | ] 23 | 24 | 25 | def alpha_blend(input_image, segmentation_mask, alpha=0.5): 26 | """Alpha Blending utility to overlay RGB masks on RBG images 27 | :param input_image is a np.ndarray with 3 channels 28 | :param segmentation_mask is a np.ndarray with 3 channels 29 | :param alpha is a float value 30 | """ 31 | blended = np.zeros(input_image.size, dtype=np.float32) 32 | blended = input_image * alpha + segmentation_mask * (1 - alpha) 33 | return blended 34 | 35 | 36 | def convert_state_dict(state_dict): 37 | """Converts a state dict saved from a dataParallel module to normal 38 | module state_dict inplace 39 | :param state_dict is the loaded DataParallel model_state 40 | """ 41 | new_state_dict = OrderedDict() 42 | for k, v in state_dict.items(): 43 | name = k[7:] # remove `module.` 44 | new_state_dict[name] = v 45 | return new_state_dict 46 | 47 | 48 | def get_logger(logdir): 49 | logger = logging.getLogger("ptsemseg") 50 | ts = str(datetime.datetime.now()).split(".")[0].replace(" ", "_") 51 | ts = ts.replace(":", "_").replace("-", "_") 52 | file_path = os.path.join(logdir, "run_{}.log".format(ts)) 53 | hdlr = logging.FileHandler(file_path) 54 | formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s") 55 | hdlr.setFormatter(formatter) 56 | logger.addHandler(hdlr) 57 | logger.setLevel(logging.INFO) 58 | return logger 59 | -------------------------------------------------------------------------------- /Testing/models/bisenet/modules/src/utils/cuda.cuh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | * General settings and functions 5 | */ 6 | const int WARP_SIZE = 32; 7 | const int MAX_BLOCK_SIZE = 1024; 8 | 9 | static int getNumThreads(int nElem) { 10 | int threadSizes[6] = {32, 64, 128, 256, 512, MAX_BLOCK_SIZE}; 11 | for (int i = 0; i < 6; ++i) { 12 | if (nElem <= threadSizes[i]) { 13 | return threadSizes[i]; 14 | } 15 | } 16 | return MAX_BLOCK_SIZE; 17 | } 18 | 19 | /* 20 | * Reduction utilities 21 | */ 22 | template 23 | __device__ __forceinline__ T WARP_SHFL_XOR(T value, int laneMask, int width = warpSize, 24 | unsigned int mask = 0xffffffff) { 25 | #if CUDART_VERSION >= 9000 26 | return __shfl_xor_sync(mask, value, laneMask, width); 27 | #else 28 | return __shfl_xor(value, laneMask, width); 29 | #endif 30 | } 31 | 32 | __device__ __forceinline__ int getMSB(int val) { return 31 - __clz(val); } 33 | 34 | template 35 | struct Pair { 36 | T v1, v2; 37 | __device__ Pair() {} 38 | __device__ Pair(T _v1, T _v2) : v1(_v1), v2(_v2) {} 39 | __device__ Pair(T v) : v1(v), v2(v) {} 40 | __device__ Pair(int v) : v1(v), v2(v) {} 41 | __device__ Pair &operator+=(const Pair &a) { 42 | v1 += a.v1; 43 | v2 += a.v2; 44 | return *this; 45 | } 46 | }; 47 | 48 | template 49 | static __device__ __forceinline__ T warpSum(T val) { 50 | #if __CUDA_ARCH__ >= 300 51 | for (int i = 0; i < getMSB(WARP_SIZE); ++i) { 52 | val += WARP_SHFL_XOR(val, 1 << i, WARP_SIZE); 53 | } 54 | #else 55 | __shared__ T values[MAX_BLOCK_SIZE]; 56 | values[threadIdx.x] = val; 57 | __threadfence_block(); 58 | const int base = (threadIdx.x / WARP_SIZE) * WARP_SIZE; 59 | for (int i = 1; i < WARP_SIZE; i++) { 60 | val += values[base + ((i + threadIdx.x) % WARP_SIZE)]; 61 | } 62 | #endif 63 | return val; 64 | } 65 | 66 | template 67 | static __device__ __forceinline__ Pair warpSum(Pair value) { 68 | value.v1 = warpSum(value.v1); 69 | value.v2 = warpSum(value.v2); 70 | return value; 71 | } -------------------------------------------------------------------------------- /Testing/models/fanet/modules/src/utils/cuda.cuh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | * General settings and functions 5 | */ 6 | const int WARP_SIZE = 32; 7 | const int MAX_BLOCK_SIZE = 1024; 8 | 9 | static int getNumThreads(int nElem) { 10 | int threadSizes[6] = {32, 64, 128, 256, 512, MAX_BLOCK_SIZE}; 11 | for (int i = 0; i < 6; ++i) { 12 | if (nElem <= threadSizes[i]) { 13 | return threadSizes[i]; 14 | } 15 | } 16 | return MAX_BLOCK_SIZE; 17 | } 18 | 19 | /* 20 | * Reduction utilities 21 | */ 22 | template 23 | __device__ __forceinline__ T WARP_SHFL_XOR(T value, int laneMask, int width = warpSize, 24 | unsigned int mask = 0xffffffff) { 25 | #if CUDART_VERSION >= 9000 26 | return __shfl_xor_sync(mask, value, laneMask, width); 27 | #else 28 | return __shfl_xor(value, laneMask, width); 29 | #endif 30 | } 31 | 32 | __device__ __forceinline__ int getMSB(int val) { return 31 - __clz(val); } 33 | 34 | template 35 | struct Pair { 36 | T v1, v2; 37 | __device__ Pair() {} 38 | __device__ Pair(T _v1, T _v2) : v1(_v1), v2(_v2) {} 39 | __device__ Pair(T v) : v1(v), v2(v) {} 40 | __device__ Pair(int v) : v1(v), v2(v) {} 41 | __device__ Pair &operator+=(const Pair &a) { 42 | v1 += a.v1; 43 | v2 += a.v2; 44 | return *this; 45 | } 46 | }; 47 | 48 | template 49 | static __device__ __forceinline__ T warpSum(T val) { 50 | #if __CUDA_ARCH__ >= 300 51 | for (int i = 0; i < getMSB(WARP_SIZE); ++i) { 52 | val += WARP_SHFL_XOR(val, 1 << i, WARP_SIZE); 53 | } 54 | #else 55 | __shared__ T values[MAX_BLOCK_SIZE]; 56 | values[threadIdx.x] = val; 57 | __threadfence_block(); 58 | const int base = (threadIdx.x / WARP_SIZE) * WARP_SIZE; 59 | for (int i = 1; i < WARP_SIZE; i++) { 60 | val += values[base + ((i + threadIdx.x) % WARP_SIZE)]; 61 | } 62 | #endif 63 | return val; 64 | } 65 | 66 | template 67 | static __device__ __forceinline__ Pair warpSum(Pair value) { 68 | value.v1 = warpSum(value.v1); 69 | value.v2 = warpSum(value.v2); 70 | return value; 71 | } -------------------------------------------------------------------------------- /Testing/models/shelfnet/modules/src/utils/cuda.cuh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | * General settings and functions 5 | */ 6 | const int WARP_SIZE = 32; 7 | const int MAX_BLOCK_SIZE = 1024; 8 | 9 | static int getNumThreads(int nElem) { 10 | int threadSizes[6] = {32, 64, 128, 256, 512, MAX_BLOCK_SIZE}; 11 | for (int i = 0; i < 6; ++i) { 12 | if (nElem <= threadSizes[i]) { 13 | return threadSizes[i]; 14 | } 15 | } 16 | return MAX_BLOCK_SIZE; 17 | } 18 | 19 | /* 20 | * Reduction utilities 21 | */ 22 | template 23 | __device__ __forceinline__ T WARP_SHFL_XOR(T value, int laneMask, int width = warpSize, 24 | unsigned int mask = 0xffffffff) { 25 | #if CUDART_VERSION >= 9000 26 | return __shfl_xor_sync(mask, value, laneMask, width); 27 | #else 28 | return __shfl_xor(value, laneMask, width); 29 | #endif 30 | } 31 | 32 | __device__ __forceinline__ int getMSB(int val) { return 31 - __clz(val); } 33 | 34 | template 35 | struct Pair { 36 | T v1, v2; 37 | __device__ Pair() {} 38 | __device__ Pair(T _v1, T _v2) : v1(_v1), v2(_v2) {} 39 | __device__ Pair(T v) : v1(v), v2(v) {} 40 | __device__ Pair(int v) : v1(v), v2(v) {} 41 | __device__ Pair &operator+=(const Pair &a) { 42 | v1 += a.v1; 43 | v2 += a.v2; 44 | return *this; 45 | } 46 | }; 47 | 48 | template 49 | static __device__ __forceinline__ T warpSum(T val) { 50 | #if __CUDA_ARCH__ >= 300 51 | for (int i = 0; i < getMSB(WARP_SIZE); ++i) { 52 | val += WARP_SHFL_XOR(val, 1 << i, WARP_SIZE); 53 | } 54 | #else 55 | __shared__ T values[MAX_BLOCK_SIZE]; 56 | values[threadIdx.x] = val; 57 | __threadfence_block(); 58 | const int base = (threadIdx.x / WARP_SIZE) * WARP_SIZE; 59 | for (int i = 1; i < WARP_SIZE; i++) { 60 | val += values[base + ((i + threadIdx.x) % WARP_SIZE)]; 61 | } 62 | #endif 63 | return val; 64 | } 65 | 66 | template 67 | static __device__ __forceinline__ Pair warpSum(Pair value) { 68 | value.v1 = warpSum(value.v1); 69 | value.v2 = warpSum(value.v2); 70 | return value; 71 | } -------------------------------------------------------------------------------- /Train/ptsemseg/models/fanet/modules/src/utils/cuda.cuh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | * General settings and functions 5 | */ 6 | const int WARP_SIZE = 32; 7 | const int MAX_BLOCK_SIZE = 1024; 8 | 9 | static int getNumThreads(int nElem) { 10 | int threadSizes[6] = {32, 64, 128, 256, 512, MAX_BLOCK_SIZE}; 11 | for (int i = 0; i < 6; ++i) { 12 | if (nElem <= threadSizes[i]) { 13 | return threadSizes[i]; 14 | } 15 | } 16 | return MAX_BLOCK_SIZE; 17 | } 18 | 19 | /* 20 | * Reduction utilities 21 | */ 22 | template 23 | __device__ __forceinline__ T WARP_SHFL_XOR(T value, int laneMask, int width = warpSize, 24 | unsigned int mask = 0xffffffff) { 25 | #if CUDART_VERSION >= 9000 26 | return __shfl_xor_sync(mask, value, laneMask, width); 27 | #else 28 | return __shfl_xor(value, laneMask, width); 29 | #endif 30 | } 31 | 32 | __device__ __forceinline__ int getMSB(int val) { return 31 - __clz(val); } 33 | 34 | template 35 | struct Pair { 36 | T v1, v2; 37 | __device__ Pair() {} 38 | __device__ Pair(T _v1, T _v2) : v1(_v1), v2(_v2) {} 39 | __device__ Pair(T v) : v1(v), v2(v) {} 40 | __device__ Pair(int v) : v1(v), v2(v) {} 41 | __device__ Pair &operator+=(const Pair &a) { 42 | v1 += a.v1; 43 | v2 += a.v2; 44 | return *this; 45 | } 46 | }; 47 | 48 | template 49 | static __device__ __forceinline__ T warpSum(T val) { 50 | #if __CUDA_ARCH__ >= 300 51 | for (int i = 0; i < getMSB(WARP_SIZE); ++i) { 52 | val += WARP_SHFL_XOR(val, 1 << i, WARP_SIZE); 53 | } 54 | #else 55 | __shared__ T values[MAX_BLOCK_SIZE]; 56 | values[threadIdx.x] = val; 57 | __threadfence_block(); 58 | const int base = (threadIdx.x / WARP_SIZE) * WARP_SIZE; 59 | for (int i = 1; i < WARP_SIZE; i++) { 60 | val += values[base + ((i + threadIdx.x) % WARP_SIZE)]; 61 | } 62 | #endif 63 | return val; 64 | } 65 | 66 | template 67 | static __device__ __forceinline__ Pair warpSum(Pair value) { 68 | value.v1 = warpSum(value.v1); 69 | value.v2 = warpSum(value.v2); 70 | return value; 71 | } -------------------------------------------------------------------------------- /Testing/speeding.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import oyaml as yaml 3 | from torchstat import stat 4 | import time,os 5 | 6 | from models.bisenet.bisenet import BiSeNet 7 | from models.swiftnet.semseg import SwiftNet 8 | from models.icnet.icnet import ICNet 9 | from models.erfnet.erfnet import ERFNet 10 | from models.segnet.segnet import SegNet 11 | from models.shelfnet.shelfnet import ShelfNet18 12 | from models.fanet.fanet import FANet 13 | 14 | #os.environ["CUDA_VISIBLE_DEVICES"]="1" 15 | 16 | def run(model,size,name): 17 | model.cuda() 18 | model.eval() 19 | t_cnt = 0.0 20 | with torch.no_grad(): 21 | 22 | input = torch.rand(size).cuda() 23 | torch.cuda.synchronize() 24 | x = model(input) 25 | x = model(input) 26 | torch.cuda.synchronize() 27 | 28 | 29 | for i in range(100): 30 | 31 | torch.cuda.synchronize() 32 | start_ts = time.time() 33 | x = model(input) 34 | torch.cuda.synchronize() 35 | end_ts = time.time() 36 | 37 | t_cnt += end_ts-start_ts 38 | print("=======================================") 39 | print("Model Name: "+name) 40 | print("FPS: %f"%(100/t_cnt)) 41 | #print("=======================================") 42 | 43 | if __name__ == "__main__": 44 | 45 | segnet = SegNet() 46 | run(segnet,size=(1,3,360,640),name='SegNet') 47 | 48 | icnet = ICNet() 49 | run(icnet,size=(1,3,1025,2049),name='ICNet') 50 | 51 | erfnet = ERFNet() 52 | run(erfnet,size=(1,3,512,1024),name='ERFNet') 53 | 54 | bisenet = BiSeNet() 55 | run(bisenet,size=(1,3,768,1536),name='BiSeNet') 56 | 57 | shelfnet = ShelfNet18() 58 | run(shelfnet,size=(1,3,1024,2048),name='ShelfNet') 59 | 60 | swiftnet = SwiftNet() 61 | run(swiftnet,size=(1,3,1024,2048),name='SwiftNet') 62 | 63 | fanet18 = FANet(backbone='resnet18') 64 | run(fanet18,size=(1,3,1024,2048),name='FANet-18') 65 | 66 | fanet34 = FANet(backbone='resnet34') 67 | run(fanet34,size=(1,3,1024,2048),name='FANet-34') 68 | 69 | 70 | print("=======================================") 71 | print("Note: ") 72 | print("In the paper, a single Titan X GPU is adopted for evaluation.") 73 | print("=======================================") 74 | 75 | -------------------------------------------------------------------------------- /Train/ptsemseg/metrics.py: -------------------------------------------------------------------------------- 1 | # Adapted from score written by wkentaro 2 | # https://github.com/wkentaro/pytorch-fcn/blob/master/torchfcn/utils.py 3 | 4 | import numpy as np 5 | 6 | 7 | class runningScore(object): 8 | def __init__(self, n_classes): 9 | self.n_classes = n_classes 10 | self.confusion_matrix = np.zeros((n_classes, n_classes)) 11 | 12 | def _fast_hist(self, label_true, label_pred, n_class): 13 | mask = (label_true >= 0) & (label_true < n_class) 14 | hist = np.bincount( 15 | n_class * label_true[mask].astype(int) + label_pred[mask], minlength=n_class ** 2 16 | ).reshape(n_class, n_class) 17 | return hist 18 | 19 | def update(self, label_trues, label_preds): 20 | for lt, lp in zip(label_trues, label_preds): 21 | self.confusion_matrix += self._fast_hist(lt.flatten(), lp.flatten(), self.n_classes) 22 | 23 | def get_scores(self): 24 | """Returns accuracy score evaluation result. 25 | - overall accuracy 26 | - mean accuracy 27 | - mean IU 28 | - fwavacc 29 | """ 30 | hist = self.confusion_matrix 31 | acc = np.diag(hist).sum() / hist.sum() 32 | acc_cls = np.diag(hist) / hist.sum(axis=1) 33 | acc_cls = np.nanmean(acc_cls) 34 | iu = np.diag(hist) / (hist.sum(axis=1) + hist.sum(axis=0) - np.diag(hist)) 35 | mean_iu = np.nanmean(iu) 36 | freq = hist.sum(axis=1) / hist.sum() 37 | fwavacc = (freq[freq > 0] * iu[freq > 0]).sum() 38 | cls_iu = dict(zip(range(self.n_classes), iu)) 39 | 40 | return ( 41 | { 42 | "Overall Acc: \t": acc, 43 | "Mean Acc : \t": acc_cls, 44 | "FreqW Acc : \t": fwavacc, 45 | "Mean IoU : \t": mean_iu, 46 | }, 47 | cls_iu, 48 | ) 49 | 50 | def reset(self): 51 | self.confusion_matrix = np.zeros((self.n_classes, self.n_classes)) 52 | 53 | 54 | class averageMeter(object): 55 | """Computes and stores the average and current value""" 56 | 57 | def __init__(self): 58 | self.reset() 59 | 60 | def reset(self): 61 | self.val = 0 62 | self.avg = 0 63 | self.sum = 0 64 | self.count = 0 65 | 66 | def update(self, val, n=1): 67 | self.val = val 68 | self.sum += val * n 69 | self.count += n 70 | self.avg = self.sum / self.count 71 | -------------------------------------------------------------------------------- /Testing/models/fanet/modules/src/inplace_abn.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "inplace_abn.h" 6 | 7 | std::vector mean_var(at::Tensor x) { 8 | if (x.is_cuda()) { 9 | if (x.type().scalarType() == at::ScalarType::Half) { 10 | return mean_var_cuda_h(x); 11 | } else { 12 | return mean_var_cuda(x); 13 | } 14 | } else { 15 | return mean_var_cpu(x); 16 | } 17 | } 18 | 19 | at::Tensor forward(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 20 | bool affine, float eps) { 21 | if (x.is_cuda()) { 22 | if (x.type().scalarType() == at::ScalarType::Half) { 23 | return forward_cuda_h(x, mean, var, weight, bias, affine, eps); 24 | } else { 25 | return forward_cuda(x, mean, var, weight, bias, affine, eps); 26 | } 27 | } else { 28 | return forward_cpu(x, mean, var, weight, bias, affine, eps); 29 | } 30 | } 31 | 32 | std::vector edz_eydz(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 33 | bool affine, float eps) { 34 | if (z.is_cuda()) { 35 | if (z.type().scalarType() == at::ScalarType::Half) { 36 | return edz_eydz_cuda_h(z, dz, weight, bias, affine, eps); 37 | } else { 38 | return edz_eydz_cuda(z, dz, weight, bias, affine, eps); 39 | } 40 | } else { 41 | return edz_eydz_cpu(z, dz, weight, bias, affine, eps); 42 | } 43 | } 44 | 45 | at::Tensor backward(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 46 | at::Tensor edz, at::Tensor eydz, bool affine, float eps) { 47 | if (z.is_cuda()) { 48 | if (z.type().scalarType() == at::ScalarType::Half) { 49 | return backward_cuda_h(z, dz, var, weight, bias, edz, eydz, affine, eps); 50 | } else { 51 | return backward_cuda(z, dz, var, weight, bias, edz, eydz, affine, eps); 52 | } 53 | } else { 54 | return backward_cpu(z, dz, var, weight, bias, edz, eydz, affine, eps); 55 | } 56 | } 57 | 58 | void leaky_relu_forward(at::Tensor z, float slope) { 59 | at::leaky_relu_(z, slope); 60 | } 61 | 62 | void leaky_relu_backward(at::Tensor z, at::Tensor dz, float slope) { 63 | if (z.is_cuda()) { 64 | if (z.type().scalarType() == at::ScalarType::Half) { 65 | return leaky_relu_backward_cuda_h(z, dz, slope); 66 | } else { 67 | return leaky_relu_backward_cuda(z, dz, slope); 68 | } 69 | } else { 70 | return leaky_relu_backward_cpu(z, dz, slope); 71 | } 72 | } 73 | 74 | void elu_forward(at::Tensor z) { 75 | at::elu_(z); 76 | } 77 | 78 | void elu_backward(at::Tensor z, at::Tensor dz) { 79 | if (z.is_cuda()) { 80 | return elu_backward_cuda(z, dz); 81 | } else { 82 | return elu_backward_cpu(z, dz); 83 | } 84 | } 85 | 86 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 87 | m.def("mean_var", &mean_var, "Mean and variance computation"); 88 | m.def("forward", &forward, "In-place forward computation"); 89 | m.def("edz_eydz", &edz_eydz, "First part of backward computation"); 90 | m.def("backward", &backward, "Second part of backward computation"); 91 | m.def("leaky_relu_forward", &leaky_relu_forward, "Leaky relu forward computation"); 92 | m.def("leaky_relu_backward", &leaky_relu_backward, "Leaky relu backward computation and inversion"); 93 | m.def("elu_forward", &elu_forward, "Elu forward computation"); 94 | m.def("elu_backward", &elu_backward, "Elu backward computation and inversion"); 95 | } 96 | -------------------------------------------------------------------------------- /Testing/models/bisenet/modules/src/inplace_abn.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "inplace_abn.h" 6 | 7 | std::vector mean_var(at::Tensor x) { 8 | if (x.is_cuda()) { 9 | if (x.type().scalarType() == at::ScalarType::Half) { 10 | return mean_var_cuda_h(x); 11 | } else { 12 | return mean_var_cuda(x); 13 | } 14 | } else { 15 | return mean_var_cpu(x); 16 | } 17 | } 18 | 19 | at::Tensor forward(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 20 | bool affine, float eps) { 21 | if (x.is_cuda()) { 22 | if (x.type().scalarType() == at::ScalarType::Half) { 23 | return forward_cuda_h(x, mean, var, weight, bias, affine, eps); 24 | } else { 25 | return forward_cuda(x, mean, var, weight, bias, affine, eps); 26 | } 27 | } else { 28 | return forward_cpu(x, mean, var, weight, bias, affine, eps); 29 | } 30 | } 31 | 32 | std::vector edz_eydz(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 33 | bool affine, float eps) { 34 | if (z.is_cuda()) { 35 | if (z.type().scalarType() == at::ScalarType::Half) { 36 | return edz_eydz_cuda_h(z, dz, weight, bias, affine, eps); 37 | } else { 38 | return edz_eydz_cuda(z, dz, weight, bias, affine, eps); 39 | } 40 | } else { 41 | return edz_eydz_cpu(z, dz, weight, bias, affine, eps); 42 | } 43 | } 44 | 45 | at::Tensor backward(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 46 | at::Tensor edz, at::Tensor eydz, bool affine, float eps) { 47 | if (z.is_cuda()) { 48 | if (z.type().scalarType() == at::ScalarType::Half) { 49 | return backward_cuda_h(z, dz, var, weight, bias, edz, eydz, affine, eps); 50 | } else { 51 | return backward_cuda(z, dz, var, weight, bias, edz, eydz, affine, eps); 52 | } 53 | } else { 54 | return backward_cpu(z, dz, var, weight, bias, edz, eydz, affine, eps); 55 | } 56 | } 57 | 58 | void leaky_relu_forward(at::Tensor z, float slope) { 59 | at::leaky_relu_(z, slope); 60 | } 61 | 62 | void leaky_relu_backward(at::Tensor z, at::Tensor dz, float slope) { 63 | if (z.is_cuda()) { 64 | if (z.type().scalarType() == at::ScalarType::Half) { 65 | return leaky_relu_backward_cuda_h(z, dz, slope); 66 | } else { 67 | return leaky_relu_backward_cuda(z, dz, slope); 68 | } 69 | } else { 70 | return leaky_relu_backward_cpu(z, dz, slope); 71 | } 72 | } 73 | 74 | void elu_forward(at::Tensor z) { 75 | at::elu_(z); 76 | } 77 | 78 | void elu_backward(at::Tensor z, at::Tensor dz) { 79 | if (z.is_cuda()) { 80 | return elu_backward_cuda(z, dz); 81 | } else { 82 | return elu_backward_cpu(z, dz); 83 | } 84 | } 85 | 86 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 87 | m.def("mean_var", &mean_var, "Mean and variance computation"); 88 | m.def("forward", &forward, "In-place forward computation"); 89 | m.def("edz_eydz", &edz_eydz, "First part of backward computation"); 90 | m.def("backward", &backward, "Second part of backward computation"); 91 | m.def("leaky_relu_forward", &leaky_relu_forward, "Leaky relu forward computation"); 92 | m.def("leaky_relu_backward", &leaky_relu_backward, "Leaky relu backward computation and inversion"); 93 | m.def("elu_forward", &elu_forward, "Elu forward computation"); 94 | m.def("elu_backward", &elu_backward, "Elu backward computation and inversion"); 95 | } 96 | -------------------------------------------------------------------------------- /Testing/models/shelfnet/modules/src/inplace_abn.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "inplace_abn.h" 6 | 7 | std::vector mean_var(at::Tensor x) { 8 | if (x.is_cuda()) { 9 | if (x.type().scalarType() == at::ScalarType::Half) { 10 | return mean_var_cuda_h(x); 11 | } else { 12 | return mean_var_cuda(x); 13 | } 14 | } else { 15 | return mean_var_cpu(x); 16 | } 17 | } 18 | 19 | at::Tensor forward(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 20 | bool affine, float eps) { 21 | if (x.is_cuda()) { 22 | if (x.type().scalarType() == at::ScalarType::Half) { 23 | return forward_cuda_h(x, mean, var, weight, bias, affine, eps); 24 | } else { 25 | return forward_cuda(x, mean, var, weight, bias, affine, eps); 26 | } 27 | } else { 28 | return forward_cpu(x, mean, var, weight, bias, affine, eps); 29 | } 30 | } 31 | 32 | std::vector edz_eydz(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 33 | bool affine, float eps) { 34 | if (z.is_cuda()) { 35 | if (z.type().scalarType() == at::ScalarType::Half) { 36 | return edz_eydz_cuda_h(z, dz, weight, bias, affine, eps); 37 | } else { 38 | return edz_eydz_cuda(z, dz, weight, bias, affine, eps); 39 | } 40 | } else { 41 | return edz_eydz_cpu(z, dz, weight, bias, affine, eps); 42 | } 43 | } 44 | 45 | at::Tensor backward(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 46 | at::Tensor edz, at::Tensor eydz, bool affine, float eps) { 47 | if (z.is_cuda()) { 48 | if (z.type().scalarType() == at::ScalarType::Half) { 49 | return backward_cuda_h(z, dz, var, weight, bias, edz, eydz, affine, eps); 50 | } else { 51 | return backward_cuda(z, dz, var, weight, bias, edz, eydz, affine, eps); 52 | } 53 | } else { 54 | return backward_cpu(z, dz, var, weight, bias, edz, eydz, affine, eps); 55 | } 56 | } 57 | 58 | void leaky_relu_forward(at::Tensor z, float slope) { 59 | at::leaky_relu_(z, slope); 60 | } 61 | 62 | void leaky_relu_backward(at::Tensor z, at::Tensor dz, float slope) { 63 | if (z.is_cuda()) { 64 | if (z.type().scalarType() == at::ScalarType::Half) { 65 | return leaky_relu_backward_cuda_h(z, dz, slope); 66 | } else { 67 | return leaky_relu_backward_cuda(z, dz, slope); 68 | } 69 | } else { 70 | return leaky_relu_backward_cpu(z, dz, slope); 71 | } 72 | } 73 | 74 | void elu_forward(at::Tensor z) { 75 | at::elu_(z); 76 | } 77 | 78 | void elu_backward(at::Tensor z, at::Tensor dz) { 79 | if (z.is_cuda()) { 80 | return elu_backward_cuda(z, dz); 81 | } else { 82 | return elu_backward_cpu(z, dz); 83 | } 84 | } 85 | 86 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 87 | m.def("mean_var", &mean_var, "Mean and variance computation"); 88 | m.def("forward", &forward, "In-place forward computation"); 89 | m.def("edz_eydz", &edz_eydz, "First part of backward computation"); 90 | m.def("backward", &backward, "Second part of backward computation"); 91 | m.def("leaky_relu_forward", &leaky_relu_forward, "Leaky relu forward computation"); 92 | m.def("leaky_relu_backward", &leaky_relu_backward, "Leaky relu backward computation and inversion"); 93 | m.def("elu_forward", &elu_forward, "Elu forward computation"); 94 | m.def("elu_backward", &elu_backward, "Elu backward computation and inversion"); 95 | } 96 | -------------------------------------------------------------------------------- /Train/ptsemseg/models/fanet/modules/src/inplace_abn.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "inplace_abn.h" 6 | 7 | std::vector mean_var(at::Tensor x) { 8 | if (x.is_cuda()) { 9 | if (x.type().scalarType() == at::ScalarType::Half) { 10 | return mean_var_cuda_h(x); 11 | } else { 12 | return mean_var_cuda(x); 13 | } 14 | } else { 15 | return mean_var_cpu(x); 16 | } 17 | } 18 | 19 | at::Tensor forward(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 20 | bool affine, float eps) { 21 | if (x.is_cuda()) { 22 | if (x.type().scalarType() == at::ScalarType::Half) { 23 | return forward_cuda_h(x, mean, var, weight, bias, affine, eps); 24 | } else { 25 | return forward_cuda(x, mean, var, weight, bias, affine, eps); 26 | } 27 | } else { 28 | return forward_cpu(x, mean, var, weight, bias, affine, eps); 29 | } 30 | } 31 | 32 | std::vector edz_eydz(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 33 | bool affine, float eps) { 34 | if (z.is_cuda()) { 35 | if (z.type().scalarType() == at::ScalarType::Half) { 36 | return edz_eydz_cuda_h(z, dz, weight, bias, affine, eps); 37 | } else { 38 | return edz_eydz_cuda(z, dz, weight, bias, affine, eps); 39 | } 40 | } else { 41 | return edz_eydz_cpu(z, dz, weight, bias, affine, eps); 42 | } 43 | } 44 | 45 | at::Tensor backward(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 46 | at::Tensor edz, at::Tensor eydz, bool affine, float eps) { 47 | if (z.is_cuda()) { 48 | if (z.type().scalarType() == at::ScalarType::Half) { 49 | return backward_cuda_h(z, dz, var, weight, bias, edz, eydz, affine, eps); 50 | } else { 51 | return backward_cuda(z, dz, var, weight, bias, edz, eydz, affine, eps); 52 | } 53 | } else { 54 | return backward_cpu(z, dz, var, weight, bias, edz, eydz, affine, eps); 55 | } 56 | } 57 | 58 | void leaky_relu_forward(at::Tensor z, float slope) { 59 | at::leaky_relu_(z, slope); 60 | } 61 | 62 | void leaky_relu_backward(at::Tensor z, at::Tensor dz, float slope) { 63 | if (z.is_cuda()) { 64 | if (z.type().scalarType() == at::ScalarType::Half) { 65 | return leaky_relu_backward_cuda_h(z, dz, slope); 66 | } else { 67 | return leaky_relu_backward_cuda(z, dz, slope); 68 | } 69 | } else { 70 | return leaky_relu_backward_cpu(z, dz, slope); 71 | } 72 | } 73 | 74 | void elu_forward(at::Tensor z) { 75 | at::elu_(z); 76 | } 77 | 78 | void elu_backward(at::Tensor z, at::Tensor dz) { 79 | if (z.is_cuda()) { 80 | return elu_backward_cuda(z, dz); 81 | } else { 82 | return elu_backward_cpu(z, dz); 83 | } 84 | } 85 | 86 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { 87 | m.def("mean_var", &mean_var, "Mean and variance computation"); 88 | m.def("forward", &forward, "In-place forward computation"); 89 | m.def("edz_eydz", &edz_eydz, "First part of backward computation"); 90 | m.def("backward", &backward, "Second part of backward computation"); 91 | m.def("leaky_relu_forward", &leaky_relu_forward, "Leaky relu forward computation"); 92 | m.def("leaky_relu_backward", &leaky_relu_backward, "Leaky relu backward computation and inversion"); 93 | m.def("elu_forward", &elu_forward, "Elu forward computation"); 94 | m.def("elu_backward", &elu_backward, "Elu backward computation and inversion"); 95 | } 96 | -------------------------------------------------------------------------------- /Testing/models/fanet/modules/src/inplace_abn.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | std::vector mean_var_cpu(at::Tensor x); 8 | std::vector mean_var_cuda(at::Tensor x); 9 | std::vector mean_var_cuda_h(at::Tensor x); 10 | 11 | at::Tensor forward_cpu(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 12 | bool affine, float eps); 13 | at::Tensor forward_cuda(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 14 | bool affine, float eps); 15 | at::Tensor forward_cuda_h(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 16 | bool affine, float eps); 17 | 18 | std::vector edz_eydz_cpu(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 19 | bool affine, float eps); 20 | std::vector edz_eydz_cuda(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 21 | bool affine, float eps); 22 | std::vector edz_eydz_cuda_h(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 23 | bool affine, float eps); 24 | 25 | at::Tensor backward_cpu(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 26 | at::Tensor edz, at::Tensor eydz, bool affine, float eps); 27 | at::Tensor backward_cuda(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 28 | at::Tensor edz, at::Tensor eydz, bool affine, float eps); 29 | at::Tensor backward_cuda_h(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 30 | at::Tensor edz, at::Tensor eydz, bool affine, float eps); 31 | 32 | void leaky_relu_backward_cpu(at::Tensor z, at::Tensor dz, float slope); 33 | void leaky_relu_backward_cuda(at::Tensor z, at::Tensor dz, float slope); 34 | void leaky_relu_backward_cuda_h(at::Tensor z, at::Tensor dz, float slope); 35 | 36 | void elu_backward_cpu(at::Tensor z, at::Tensor dz); 37 | void elu_backward_cuda(at::Tensor z, at::Tensor dz); 38 | 39 | static void get_dims(at::Tensor x, int64_t& num, int64_t& chn, int64_t& sp) { 40 | num = x.size(0); 41 | chn = x.size(1); 42 | sp = 1; 43 | for (int64_t i = 2; i < x.ndimension(); ++i) 44 | sp *= x.size(i); 45 | } 46 | 47 | /* 48 | * Specialized CUDA reduction functions for BN 49 | */ 50 | #ifdef __CUDACC__ 51 | 52 | #include "utils/cuda.cuh" 53 | 54 | template 55 | __device__ T reduce(Op op, int plane, int N, int S) { 56 | T sum = (T)0; 57 | for (int batch = 0; batch < N; ++batch) { 58 | for (int x = threadIdx.x; x < S; x += blockDim.x) { 59 | sum += op(batch, plane, x); 60 | } 61 | } 62 | 63 | // sum over NumThreads within a warp 64 | sum = warpSum(sum); 65 | 66 | // 'transpose', and reduce within warp again 67 | __shared__ T shared[32]; 68 | __syncthreads(); 69 | if (threadIdx.x % WARP_SIZE == 0) { 70 | shared[threadIdx.x / WARP_SIZE] = sum; 71 | } 72 | if (threadIdx.x >= blockDim.x / WARP_SIZE && threadIdx.x < WARP_SIZE) { 73 | // zero out the other entries in shared 74 | shared[threadIdx.x] = (T)0; 75 | } 76 | __syncthreads(); 77 | if (threadIdx.x / WARP_SIZE == 0) { 78 | sum = warpSum(shared[threadIdx.x]); 79 | if (threadIdx.x == 0) { 80 | shared[0] = sum; 81 | } 82 | } 83 | __syncthreads(); 84 | 85 | // Everyone picks it up, should be broadcast into the whole gradInput 86 | return shared[0]; 87 | } 88 | #endif 89 | -------------------------------------------------------------------------------- /Testing/models/bisenet/modules/src/inplace_abn.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | std::vector mean_var_cpu(at::Tensor x); 8 | std::vector mean_var_cuda(at::Tensor x); 9 | std::vector mean_var_cuda_h(at::Tensor x); 10 | 11 | at::Tensor forward_cpu(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 12 | bool affine, float eps); 13 | at::Tensor forward_cuda(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 14 | bool affine, float eps); 15 | at::Tensor forward_cuda_h(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 16 | bool affine, float eps); 17 | 18 | std::vector edz_eydz_cpu(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 19 | bool affine, float eps); 20 | std::vector edz_eydz_cuda(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 21 | bool affine, float eps); 22 | std::vector edz_eydz_cuda_h(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 23 | bool affine, float eps); 24 | 25 | at::Tensor backward_cpu(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 26 | at::Tensor edz, at::Tensor eydz, bool affine, float eps); 27 | at::Tensor backward_cuda(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 28 | at::Tensor edz, at::Tensor eydz, bool affine, float eps); 29 | at::Tensor backward_cuda_h(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 30 | at::Tensor edz, at::Tensor eydz, bool affine, float eps); 31 | 32 | void leaky_relu_backward_cpu(at::Tensor z, at::Tensor dz, float slope); 33 | void leaky_relu_backward_cuda(at::Tensor z, at::Tensor dz, float slope); 34 | void leaky_relu_backward_cuda_h(at::Tensor z, at::Tensor dz, float slope); 35 | 36 | void elu_backward_cpu(at::Tensor z, at::Tensor dz); 37 | void elu_backward_cuda(at::Tensor z, at::Tensor dz); 38 | 39 | static void get_dims(at::Tensor x, int64_t& num, int64_t& chn, int64_t& sp) { 40 | num = x.size(0); 41 | chn = x.size(1); 42 | sp = 1; 43 | for (int64_t i = 2; i < x.ndimension(); ++i) 44 | sp *= x.size(i); 45 | } 46 | 47 | /* 48 | * Specialized CUDA reduction functions for BN 49 | */ 50 | #ifdef __CUDACC__ 51 | 52 | #include "utils/cuda.cuh" 53 | 54 | template 55 | __device__ T reduce(Op op, int plane, int N, int S) { 56 | T sum = (T)0; 57 | for (int batch = 0; batch < N; ++batch) { 58 | for (int x = threadIdx.x; x < S; x += blockDim.x) { 59 | sum += op(batch, plane, x); 60 | } 61 | } 62 | 63 | // sum over NumThreads within a warp 64 | sum = warpSum(sum); 65 | 66 | // 'transpose', and reduce within warp again 67 | __shared__ T shared[32]; 68 | __syncthreads(); 69 | if (threadIdx.x % WARP_SIZE == 0) { 70 | shared[threadIdx.x / WARP_SIZE] = sum; 71 | } 72 | if (threadIdx.x >= blockDim.x / WARP_SIZE && threadIdx.x < WARP_SIZE) { 73 | // zero out the other entries in shared 74 | shared[threadIdx.x] = (T)0; 75 | } 76 | __syncthreads(); 77 | if (threadIdx.x / WARP_SIZE == 0) { 78 | sum = warpSum(shared[threadIdx.x]); 79 | if (threadIdx.x == 0) { 80 | shared[0] = sum; 81 | } 82 | } 83 | __syncthreads(); 84 | 85 | // Everyone picks it up, should be broadcast into the whole gradInput 86 | return shared[0]; 87 | } 88 | #endif 89 | -------------------------------------------------------------------------------- /Testing/models/shelfnet/modules/src/inplace_abn.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | std::vector mean_var_cpu(at::Tensor x); 8 | std::vector mean_var_cuda(at::Tensor x); 9 | std::vector mean_var_cuda_h(at::Tensor x); 10 | 11 | at::Tensor forward_cpu(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 12 | bool affine, float eps); 13 | at::Tensor forward_cuda(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 14 | bool affine, float eps); 15 | at::Tensor forward_cuda_h(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 16 | bool affine, float eps); 17 | 18 | std::vector edz_eydz_cpu(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 19 | bool affine, float eps); 20 | std::vector edz_eydz_cuda(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 21 | bool affine, float eps); 22 | std::vector edz_eydz_cuda_h(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 23 | bool affine, float eps); 24 | 25 | at::Tensor backward_cpu(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 26 | at::Tensor edz, at::Tensor eydz, bool affine, float eps); 27 | at::Tensor backward_cuda(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 28 | at::Tensor edz, at::Tensor eydz, bool affine, float eps); 29 | at::Tensor backward_cuda_h(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 30 | at::Tensor edz, at::Tensor eydz, bool affine, float eps); 31 | 32 | void leaky_relu_backward_cpu(at::Tensor z, at::Tensor dz, float slope); 33 | void leaky_relu_backward_cuda(at::Tensor z, at::Tensor dz, float slope); 34 | void leaky_relu_backward_cuda_h(at::Tensor z, at::Tensor dz, float slope); 35 | 36 | void elu_backward_cpu(at::Tensor z, at::Tensor dz); 37 | void elu_backward_cuda(at::Tensor z, at::Tensor dz); 38 | 39 | static void get_dims(at::Tensor x, int64_t& num, int64_t& chn, int64_t& sp) { 40 | num = x.size(0); 41 | chn = x.size(1); 42 | sp = 1; 43 | for (int64_t i = 2; i < x.ndimension(); ++i) 44 | sp *= x.size(i); 45 | } 46 | 47 | /* 48 | * Specialized CUDA reduction functions for BN 49 | */ 50 | #ifdef __CUDACC__ 51 | 52 | #include "utils/cuda.cuh" 53 | 54 | template 55 | __device__ T reduce(Op op, int plane, int N, int S) { 56 | T sum = (T)0; 57 | for (int batch = 0; batch < N; ++batch) { 58 | for (int x = threadIdx.x; x < S; x += blockDim.x) { 59 | sum += op(batch, plane, x); 60 | } 61 | } 62 | 63 | // sum over NumThreads within a warp 64 | sum = warpSum(sum); 65 | 66 | // 'transpose', and reduce within warp again 67 | __shared__ T shared[32]; 68 | __syncthreads(); 69 | if (threadIdx.x % WARP_SIZE == 0) { 70 | shared[threadIdx.x / WARP_SIZE] = sum; 71 | } 72 | if (threadIdx.x >= blockDim.x / WARP_SIZE && threadIdx.x < WARP_SIZE) { 73 | // zero out the other entries in shared 74 | shared[threadIdx.x] = (T)0; 75 | } 76 | __syncthreads(); 77 | if (threadIdx.x / WARP_SIZE == 0) { 78 | sum = warpSum(shared[threadIdx.x]); 79 | if (threadIdx.x == 0) { 80 | shared[0] = sum; 81 | } 82 | } 83 | __syncthreads(); 84 | 85 | // Everyone picks it up, should be broadcast into the whole gradInput 86 | return shared[0]; 87 | } 88 | #endif 89 | -------------------------------------------------------------------------------- /Train/ptsemseg/models/fanet/modules/src/inplace_abn.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | std::vector mean_var_cpu(at::Tensor x); 8 | std::vector mean_var_cuda(at::Tensor x); 9 | std::vector mean_var_cuda_h(at::Tensor x); 10 | 11 | at::Tensor forward_cpu(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 12 | bool affine, float eps); 13 | at::Tensor forward_cuda(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 14 | bool affine, float eps); 15 | at::Tensor forward_cuda_h(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 16 | bool affine, float eps); 17 | 18 | std::vector edz_eydz_cpu(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 19 | bool affine, float eps); 20 | std::vector edz_eydz_cuda(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 21 | bool affine, float eps); 22 | std::vector edz_eydz_cuda_h(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 23 | bool affine, float eps); 24 | 25 | at::Tensor backward_cpu(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 26 | at::Tensor edz, at::Tensor eydz, bool affine, float eps); 27 | at::Tensor backward_cuda(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 28 | at::Tensor edz, at::Tensor eydz, bool affine, float eps); 29 | at::Tensor backward_cuda_h(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 30 | at::Tensor edz, at::Tensor eydz, bool affine, float eps); 31 | 32 | void leaky_relu_backward_cpu(at::Tensor z, at::Tensor dz, float slope); 33 | void leaky_relu_backward_cuda(at::Tensor z, at::Tensor dz, float slope); 34 | void leaky_relu_backward_cuda_h(at::Tensor z, at::Tensor dz, float slope); 35 | 36 | void elu_backward_cpu(at::Tensor z, at::Tensor dz); 37 | void elu_backward_cuda(at::Tensor z, at::Tensor dz); 38 | 39 | static void get_dims(at::Tensor x, int64_t& num, int64_t& chn, int64_t& sp) { 40 | num = x.size(0); 41 | chn = x.size(1); 42 | sp = 1; 43 | for (int64_t i = 2; i < x.ndimension(); ++i) 44 | sp *= x.size(i); 45 | } 46 | 47 | /* 48 | * Specialized CUDA reduction functions for BN 49 | */ 50 | #ifdef __CUDACC__ 51 | 52 | #include "utils/cuda.cuh" 53 | 54 | template 55 | __device__ T reduce(Op op, int plane, int N, int S) { 56 | T sum = (T)0; 57 | for (int batch = 0; batch < N; ++batch) { 58 | for (int x = threadIdx.x; x < S; x += blockDim.x) { 59 | sum += op(batch, plane, x); 60 | } 61 | } 62 | 63 | // sum over NumThreads within a warp 64 | sum = warpSum(sum); 65 | 66 | // 'transpose', and reduce within warp again 67 | __shared__ T shared[32]; 68 | __syncthreads(); 69 | if (threadIdx.x % WARP_SIZE == 0) { 70 | shared[threadIdx.x / WARP_SIZE] = sum; 71 | } 72 | if (threadIdx.x >= blockDim.x / WARP_SIZE && threadIdx.x < WARP_SIZE) { 73 | // zero out the other entries in shared 74 | shared[threadIdx.x] = (T)0; 75 | } 76 | __syncthreads(); 77 | if (threadIdx.x / WARP_SIZE == 0) { 78 | sum = warpSum(shared[threadIdx.x]); 79 | if (threadIdx.x == 0) { 80 | shared[0] = sum; 81 | } 82 | } 83 | __syncthreads(); 84 | 85 | // Everyone picks it up, should be broadcast into the whole gradInput 86 | return shared[0]; 87 | } 88 | #endif 89 | -------------------------------------------------------------------------------- /Testing/models/bisenet/modules/deeplab.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as functional 4 | 5 | from models._util import try_index 6 | from .bn import ABN 7 | 8 | 9 | class DeeplabV3(nn.Module): 10 | def __init__(self, 11 | in_channels, 12 | out_channels, 13 | hidden_channels=256, 14 | dilations=(12, 24, 36), 15 | norm_act=ABN, 16 | pooling_size=None): 17 | super(DeeplabV3, self).__init__() 18 | self.pooling_size = pooling_size 19 | 20 | self.map_convs = nn.ModuleList([ 21 | nn.Conv2d(in_channels, hidden_channels, 1, bias=False), 22 | nn.Conv2d(in_channels, hidden_channels, 3, bias=False, dilation=dilations[0], padding=dilations[0]), 23 | nn.Conv2d(in_channels, hidden_channels, 3, bias=False, dilation=dilations[1], padding=dilations[1]), 24 | nn.Conv2d(in_channels, hidden_channels, 3, bias=False, dilation=dilations[2], padding=dilations[2]) 25 | ]) 26 | self.map_bn = norm_act(hidden_channels * 4) 27 | 28 | self.global_pooling_conv = nn.Conv2d(in_channels, hidden_channels, 1, bias=False) 29 | self.global_pooling_bn = norm_act(hidden_channels) 30 | 31 | self.red_conv = nn.Conv2d(hidden_channels * 4, out_channels, 1, bias=False) 32 | self.pool_red_conv = nn.Conv2d(hidden_channels, out_channels, 1, bias=False) 33 | self.red_bn = norm_act(out_channels) 34 | 35 | self.reset_parameters(self.map_bn.activation, self.map_bn.slope) 36 | 37 | def reset_parameters(self, activation, slope): 38 | gain = nn.init.calculate_gain(activation, slope) 39 | for m in self.modules(): 40 | if isinstance(m, nn.Conv2d): 41 | nn.init.xavier_normal_(m.weight.data, gain) 42 | if hasattr(m, "bias") and m.bias is not None: 43 | nn.init.constant_(m.bias, 0) 44 | elif isinstance(m, ABN): 45 | if hasattr(m, "weight") and m.weight is not None: 46 | nn.init.constant_(m.weight, 1) 47 | if hasattr(m, "bias") and m.bias is not None: 48 | nn.init.constant_(m.bias, 0) 49 | 50 | def forward(self, x): 51 | # Map convolutions 52 | out = torch.cat([m(x) for m in self.map_convs], dim=1) 53 | out = self.map_bn(out) 54 | out = self.red_conv(out) 55 | 56 | # Global pooling 57 | pool = self._global_pooling(x) 58 | pool = self.global_pooling_conv(pool) 59 | pool = self.global_pooling_bn(pool) 60 | pool = self.pool_red_conv(pool) 61 | if self.training or self.pooling_size is None: 62 | pool = pool.repeat(1, 1, x.size(2), x.size(3)) 63 | 64 | out += pool 65 | out = self.red_bn(out) 66 | return out 67 | 68 | def _global_pooling(self, x): 69 | if self.training or self.pooling_size is None: 70 | pool = x.view(x.size(0), x.size(1), -1).mean(dim=-1) 71 | pool = pool.view(x.size(0), x.size(1), 1, 1) 72 | else: 73 | pooling_size = (min(try_index(self.pooling_size, 0), x.shape[2]), 74 | min(try_index(self.pooling_size, 1), x.shape[3])) 75 | padding = ( 76 | (pooling_size[1] - 1) // 2, 77 | (pooling_size[1] - 1) // 2 if pooling_size[1] % 2 == 1 else (pooling_size[1] - 1) // 2 + 1, 78 | (pooling_size[0] - 1) // 2, 79 | (pooling_size[0] - 1) // 2 if pooling_size[0] % 2 == 1 else (pooling_size[0] - 1) // 2 + 1 80 | ) 81 | 82 | pool = functional.avg_pool2d(x, pooling_size, stride=1) 83 | pool = functional.pad(pool, pad=padding, mode="replicate") 84 | return pool 85 | -------------------------------------------------------------------------------- /Testing/models/fanet/modules/deeplab.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as functional 4 | 5 | from models._util import try_index 6 | from .bn import ABN 7 | 8 | 9 | class DeeplabV3(nn.Module): 10 | def __init__(self, 11 | in_channels, 12 | out_channels, 13 | hidden_channels=256, 14 | dilations=(12, 24, 36), 15 | norm_act=ABN, 16 | pooling_size=None): 17 | super(DeeplabV3, self).__init__() 18 | self.pooling_size = pooling_size 19 | 20 | self.map_convs = nn.ModuleList([ 21 | nn.Conv2d(in_channels, hidden_channels, 1, bias=False), 22 | nn.Conv2d(in_channels, hidden_channels, 3, bias=False, dilation=dilations[0], padding=dilations[0]), 23 | nn.Conv2d(in_channels, hidden_channels, 3, bias=False, dilation=dilations[1], padding=dilations[1]), 24 | nn.Conv2d(in_channels, hidden_channels, 3, bias=False, dilation=dilations[2], padding=dilations[2]) 25 | ]) 26 | self.map_bn = norm_act(hidden_channels * 4) 27 | 28 | self.global_pooling_conv = nn.Conv2d(in_channels, hidden_channels, 1, bias=False) 29 | self.global_pooling_bn = norm_act(hidden_channels) 30 | 31 | self.red_conv = nn.Conv2d(hidden_channels * 4, out_channels, 1, bias=False) 32 | self.pool_red_conv = nn.Conv2d(hidden_channels, out_channels, 1, bias=False) 33 | self.red_bn = norm_act(out_channels) 34 | 35 | self.reset_parameters(self.map_bn.activation, self.map_bn.slope) 36 | 37 | def reset_parameters(self, activation, slope): 38 | gain = nn.init.calculate_gain(activation, slope) 39 | for m in self.modules(): 40 | if isinstance(m, nn.Conv2d): 41 | nn.init.xavier_normal_(m.weight.data, gain) 42 | if hasattr(m, "bias") and m.bias is not None: 43 | nn.init.constant_(m.bias, 0) 44 | elif isinstance(m, ABN): 45 | if hasattr(m, "weight") and m.weight is not None: 46 | nn.init.constant_(m.weight, 1) 47 | if hasattr(m, "bias") and m.bias is not None: 48 | nn.init.constant_(m.bias, 0) 49 | 50 | def forward(self, x): 51 | # Map convolutions 52 | out = torch.cat([m(x) for m in self.map_convs], dim=1) 53 | out = self.map_bn(out) 54 | out = self.red_conv(out) 55 | 56 | # Global pooling 57 | pool = self._global_pooling(x) 58 | pool = self.global_pooling_conv(pool) 59 | pool = self.global_pooling_bn(pool) 60 | pool = self.pool_red_conv(pool) 61 | if self.training or self.pooling_size is None: 62 | pool = pool.repeat(1, 1, x.size(2), x.size(3)) 63 | 64 | out += pool 65 | out = self.red_bn(out) 66 | return out 67 | 68 | def _global_pooling(self, x): 69 | if self.training or self.pooling_size is None: 70 | pool = x.view(x.size(0), x.size(1), -1).mean(dim=-1) 71 | pool = pool.view(x.size(0), x.size(1), 1, 1) 72 | else: 73 | pooling_size = (min(try_index(self.pooling_size, 0), x.shape[2]), 74 | min(try_index(self.pooling_size, 1), x.shape[3])) 75 | padding = ( 76 | (pooling_size[1] - 1) // 2, 77 | (pooling_size[1] - 1) // 2 if pooling_size[1] % 2 == 1 else (pooling_size[1] - 1) // 2 + 1, 78 | (pooling_size[0] - 1) // 2, 79 | (pooling_size[0] - 1) // 2 if pooling_size[0] % 2 == 1 else (pooling_size[0] - 1) // 2 + 1 80 | ) 81 | 82 | pool = functional.avg_pool2d(x, pooling_size, stride=1) 83 | pool = functional.pad(pool, pad=padding, mode="replicate") 84 | return pool 85 | -------------------------------------------------------------------------------- /Testing/models/shelfnet/modules/deeplab.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as functional 4 | 5 | from models._util import try_index 6 | from .bn import ABN 7 | 8 | 9 | class DeeplabV3(nn.Module): 10 | def __init__(self, 11 | in_channels, 12 | out_channels, 13 | hidden_channels=256, 14 | dilations=(12, 24, 36), 15 | norm_act=ABN, 16 | pooling_size=None): 17 | super(DeeplabV3, self).__init__() 18 | self.pooling_size = pooling_size 19 | 20 | self.map_convs = nn.ModuleList([ 21 | nn.Conv2d(in_channels, hidden_channels, 1, bias=False), 22 | nn.Conv2d(in_channels, hidden_channels, 3, bias=False, dilation=dilations[0], padding=dilations[0]), 23 | nn.Conv2d(in_channels, hidden_channels, 3, bias=False, dilation=dilations[1], padding=dilations[1]), 24 | nn.Conv2d(in_channels, hidden_channels, 3, bias=False, dilation=dilations[2], padding=dilations[2]) 25 | ]) 26 | self.map_bn = norm_act(hidden_channels * 4) 27 | 28 | self.global_pooling_conv = nn.Conv2d(in_channels, hidden_channels, 1, bias=False) 29 | self.global_pooling_bn = norm_act(hidden_channels) 30 | 31 | self.red_conv = nn.Conv2d(hidden_channels * 4, out_channels, 1, bias=False) 32 | self.pool_red_conv = nn.Conv2d(hidden_channels, out_channels, 1, bias=False) 33 | self.red_bn = norm_act(out_channels) 34 | 35 | self.reset_parameters(self.map_bn.activation, self.map_bn.slope) 36 | 37 | def reset_parameters(self, activation, slope): 38 | gain = nn.init.calculate_gain(activation, slope) 39 | for m in self.modules(): 40 | if isinstance(m, nn.Conv2d): 41 | nn.init.xavier_normal_(m.weight.data, gain) 42 | if hasattr(m, "bias") and m.bias is not None: 43 | nn.init.constant_(m.bias, 0) 44 | elif isinstance(m, ABN): 45 | if hasattr(m, "weight") and m.weight is not None: 46 | nn.init.constant_(m.weight, 1) 47 | if hasattr(m, "bias") and m.bias is not None: 48 | nn.init.constant_(m.bias, 0) 49 | 50 | def forward(self, x): 51 | # Map convolutions 52 | out = torch.cat([m(x) for m in self.map_convs], dim=1) 53 | out = self.map_bn(out) 54 | out = self.red_conv(out) 55 | 56 | # Global pooling 57 | pool = self._global_pooling(x) 58 | pool = self.global_pooling_conv(pool) 59 | pool = self.global_pooling_bn(pool) 60 | pool = self.pool_red_conv(pool) 61 | if self.training or self.pooling_size is None: 62 | pool = pool.repeat(1, 1, x.size(2), x.size(3)) 63 | 64 | out += pool 65 | out = self.red_bn(out) 66 | return out 67 | 68 | def _global_pooling(self, x): 69 | if self.training or self.pooling_size is None: 70 | pool = x.view(x.size(0), x.size(1), -1).mean(dim=-1) 71 | pool = pool.view(x.size(0), x.size(1), 1, 1) 72 | else: 73 | pooling_size = (min(try_index(self.pooling_size, 0), x.shape[2]), 74 | min(try_index(self.pooling_size, 1), x.shape[3])) 75 | padding = ( 76 | (pooling_size[1] - 1) // 2, 77 | (pooling_size[1] - 1) // 2 if pooling_size[1] % 2 == 1 else (pooling_size[1] - 1) // 2 + 1, 78 | (pooling_size[0] - 1) // 2, 79 | (pooling_size[0] - 1) // 2 if pooling_size[0] % 2 == 1 else (pooling_size[0] - 1) // 2 + 1 80 | ) 81 | 82 | pool = functional.avg_pool2d(x, pooling_size, stride=1) 83 | pool = functional.pad(pool, pad=padding, mode="replicate") 84 | return pool 85 | -------------------------------------------------------------------------------- /Train/ptsemseg/models/fanet/modules/deeplab.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as functional 4 | 5 | from models._util import try_index 6 | from .bn import ABN 7 | 8 | 9 | class DeeplabV3(nn.Module): 10 | def __init__(self, 11 | in_channels, 12 | out_channels, 13 | hidden_channels=256, 14 | dilations=(12, 24, 36), 15 | norm_act=ABN, 16 | pooling_size=None): 17 | super(DeeplabV3, self).__init__() 18 | self.pooling_size = pooling_size 19 | 20 | self.map_convs = nn.ModuleList([ 21 | nn.Conv2d(in_channels, hidden_channels, 1, bias=False), 22 | nn.Conv2d(in_channels, hidden_channels, 3, bias=False, dilation=dilations[0], padding=dilations[0]), 23 | nn.Conv2d(in_channels, hidden_channels, 3, bias=False, dilation=dilations[1], padding=dilations[1]), 24 | nn.Conv2d(in_channels, hidden_channels, 3, bias=False, dilation=dilations[2], padding=dilations[2]) 25 | ]) 26 | self.map_bn = norm_act(hidden_channels * 4) 27 | 28 | self.global_pooling_conv = nn.Conv2d(in_channels, hidden_channels, 1, bias=False) 29 | self.global_pooling_bn = norm_act(hidden_channels) 30 | 31 | self.red_conv = nn.Conv2d(hidden_channels * 4, out_channels, 1, bias=False) 32 | self.pool_red_conv = nn.Conv2d(hidden_channels, out_channels, 1, bias=False) 33 | self.red_bn = norm_act(out_channels) 34 | 35 | self.reset_parameters(self.map_bn.activation, self.map_bn.slope) 36 | 37 | def reset_parameters(self, activation, slope): 38 | gain = nn.init.calculate_gain(activation, slope) 39 | for m in self.modules(): 40 | if isinstance(m, nn.Conv2d): 41 | nn.init.xavier_normal_(m.weight.data, gain) 42 | if hasattr(m, "bias") and m.bias is not None: 43 | nn.init.constant_(m.bias, 0) 44 | elif isinstance(m, ABN): 45 | if hasattr(m, "weight") and m.weight is not None: 46 | nn.init.constant_(m.weight, 1) 47 | if hasattr(m, "bias") and m.bias is not None: 48 | nn.init.constant_(m.bias, 0) 49 | 50 | def forward(self, x): 51 | # Map convolutions 52 | out = torch.cat([m(x) for m in self.map_convs], dim=1) 53 | out = self.map_bn(out) 54 | out = self.red_conv(out) 55 | 56 | # Global pooling 57 | pool = self._global_pooling(x) 58 | pool = self.global_pooling_conv(pool) 59 | pool = self.global_pooling_bn(pool) 60 | pool = self.pool_red_conv(pool) 61 | if self.training or self.pooling_size is None: 62 | pool = pool.repeat(1, 1, x.size(2), x.size(3)) 63 | 64 | out += pool 65 | out = self.red_bn(out) 66 | return out 67 | 68 | def _global_pooling(self, x): 69 | if self.training or self.pooling_size is None: 70 | pool = x.view(x.size(0), x.size(1), -1).mean(dim=-1) 71 | pool = pool.view(x.size(0), x.size(1), 1, 1) 72 | else: 73 | pooling_size = (min(try_index(self.pooling_size, 0), x.shape[2]), 74 | min(try_index(self.pooling_size, 1), x.shape[3])) 75 | padding = ( 76 | (pooling_size[1] - 1) // 2, 77 | (pooling_size[1] - 1) // 2 if pooling_size[1] % 2 == 1 else (pooling_size[1] - 1) // 2 + 1, 78 | (pooling_size[0] - 1) // 2, 79 | (pooling_size[0] - 1) // 2 if pooling_size[0] % 2 == 1 else (pooling_size[0] - 1) // 2 + 1 80 | ) 81 | 82 | pool = functional.avg_pool2d(x, pooling_size, stride=1) 83 | pool = functional.pad(pool, pad=padding, mode="replicate") 84 | return pool 85 | -------------------------------------------------------------------------------- /Train/ptsemseg/loader/ccri_loader.py: -------------------------------------------------------------------------------- 1 | import os 2 | import torch 3 | import numpy as np 4 | import imageio as m 5 | import pdb 6 | 7 | from torch.utils import data 8 | import torchvision.transforms.functional as TF 9 | from ptsemseg.utils import recursive_glob 10 | from ptsemseg.augmentations import Compose, RandomHorizontallyFlip, RandomRotate, Scale 11 | 12 | 13 | class CCRILoader(data.Dataset): 14 | 15 | colors = [ 16 | (0, 0, 0), 17 | (92, 177, 172), 18 | (50, 183, 250), 19 | (155, 188, 221), 20 | (189, 177, 252), 21 | (221, 255, 51), 22 | (255, 53, 94), 23 | (170, 240, 209), 24 | (255, 204, 51), 25 | (198, 116, 54), 26 | (61, 245, 61), 27 | (65, 105, 146), 28 | (240, 120, 240), 29 | (61, 61, 245) 30 | ] 31 | 32 | label_colours = dict(zip(range(14), colors)) 33 | 34 | 35 | 36 | def __init__( 37 | self, 38 | root, 39 | split, 40 | augmentations=None, 41 | model_name=None, 42 | test_mode = False 43 | ): 44 | """__init__ 45 | 46 | :param root: 47 | :param split: 48 | :param is_transform: 49 | :param img_size: 50 | :param augmentations 51 | """ 52 | self.test_mode = test_mode 53 | self.root = root 54 | self.split = split 55 | self.augmentations = augmentations 56 | self.model_name=model_name 57 | self.n_classes = 14 58 | 59 | self.images_base = os.path.join(self.root, "IMG", self.split) 60 | self.annotations_base = os.path.join(self.root, "GT", self.split) 61 | 62 | self.files = recursive_glob(rootdir=self.images_base, suffix=".png") 63 | 64 | self.valid_classes = range(14) 65 | 66 | self.ignore_index = 250 67 | self.class_map = dict(zip(self.valid_classes, range(14))) 68 | 69 | if len(self.files)==0: 70 | raise Exception("No files for split=[%s] found in %s" % (split, self.images_base)) 71 | 72 | print("Found %d images in: %s" % (len(self.files),split)) 73 | 74 | 75 | def __len__(self): 76 | """__len__""" 77 | return len(self.files) 78 | 79 | def __getitem__(self, index): 80 | """__getitem__ 81 | 82 | :param index: 83 | """ 84 | img_path = self.files[index].rstrip() 85 | lbl_path = os.path.join( 86 | self.annotations_base, 87 | os.path.basename(img_path), 88 | ) 89 | 90 | img = m.imread(img_path) 91 | img = np.array(img, dtype=np.uint8) 92 | 93 | h_,w_,c_ = img.shape 94 | 95 | lbl = m.imread(lbl_path) 96 | 97 | if self.augmentations is not None: 98 | img, lbl = self.augmentations(img, lbl) 99 | 100 | img = img.transpose(2, 0, 1) 101 | img = torch.from_numpy(img).float() 102 | lbl = torch.from_numpy(lbl).long() 103 | if self.test_mode: 104 | return img, lbl, os.path.basename(img_path), w_, h_ 105 | else: 106 | return img, lbl 107 | 108 | 109 | 110 | 111 | def decode_segmap(self, temp): 112 | r = temp.copy() 113 | g = temp.copy() 114 | b = temp.copy() 115 | for l in range(0, self.n_classes): 116 | r[temp == l] = self.label_colours[l][0] 117 | g[temp == l] = self.label_colours[l][1] 118 | b[temp == l] = self.label_colours[l][2] 119 | 120 | rgb = np.zeros((temp.shape[0], temp.shape[1], 3)) 121 | rgb[:, :, 0] = r / 255.0 122 | rgb[:, :, 1] = g / 255.0 123 | rgb[:, :, 2] = b / 255.0 124 | return rgb 125 | 126 | -------------------------------------------------------------------------------- /Testing/models/fanet/modules/residual.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | import torch.nn as nn 4 | 5 | from .bn import ABN 6 | 7 | 8 | class IdentityResidualBlock(nn.Module): 9 | def __init__(self, 10 | in_channels, 11 | channels, 12 | stride=1, 13 | dilation=1, 14 | groups=1, 15 | norm_act=ABN, 16 | dropout=None): 17 | """Configurable identity-mapping residual block 18 | 19 | Parameters 20 | ---------- 21 | in_channels : int 22 | Number of input channels. 23 | channels : list of int 24 | Number of channels in the internal feature maps. Can either have two or three elements: if three construct 25 | a residual block with two `3 x 3` convolutions, otherwise construct a bottleneck block with `1 x 1`, then 26 | `3 x 3` then `1 x 1` convolutions. 27 | stride : int 28 | Stride of the first `3 x 3` convolution 29 | dilation : int 30 | Dilation to apply to the `3 x 3` convolutions. 31 | groups : int 32 | Number of convolution groups. This is used to create ResNeXt-style blocks and is only compatible with 33 | bottleneck blocks. 34 | norm_act : callable 35 | Function to create normalization / activation Module. 36 | dropout: callable 37 | Function to create Dropout Module. 38 | """ 39 | super(IdentityResidualBlock, self).__init__() 40 | 41 | # Check parameters for inconsistencies 42 | if len(channels) != 2 and len(channels) != 3: 43 | raise ValueError("channels must contain either two or three values") 44 | if len(channels) == 2 and groups != 1: 45 | raise ValueError("groups > 1 are only valid if len(channels) == 3") 46 | 47 | is_bottleneck = len(channels) == 3 48 | need_proj_conv = stride != 1 or in_channels != channels[-1] 49 | 50 | self.bn1 = norm_act(in_channels) 51 | if not is_bottleneck: 52 | layers = [ 53 | ("conv1", nn.Conv2d(in_channels, channels[0], 3, stride=stride, padding=dilation, bias=False, 54 | dilation=dilation)), 55 | ("bn2", norm_act(channels[0])), 56 | ("conv2", nn.Conv2d(channels[0], channels[1], 3, stride=1, padding=dilation, bias=False, 57 | dilation=dilation)) 58 | ] 59 | if dropout is not None: 60 | layers = layers[0:2] + [("dropout", dropout())] + layers[2:] 61 | else: 62 | layers = [ 63 | ("conv1", nn.Conv2d(in_channels, channels[0], 1, stride=stride, padding=0, bias=False)), 64 | ("bn2", norm_act(channels[0])), 65 | ("conv2", nn.Conv2d(channels[0], channels[1], 3, stride=1, padding=dilation, bias=False, 66 | groups=groups, dilation=dilation)), 67 | ("bn3", norm_act(channels[1])), 68 | ("conv3", nn.Conv2d(channels[1], channels[2], 1, stride=1, padding=0, bias=False)) 69 | ] 70 | if dropout is not None: 71 | layers = layers[0:4] + [("dropout", dropout())] + layers[4:] 72 | self.convs = nn.Sequential(OrderedDict(layers)) 73 | 74 | if need_proj_conv: 75 | self.proj_conv = nn.Conv2d(in_channels, channels[-1], 1, stride=stride, padding=0, bias=False) 76 | 77 | def forward(self, x): 78 | if hasattr(self, "proj_conv"): 79 | bn1 = self.bn1(x) 80 | shortcut = self.proj_conv(bn1) 81 | else: 82 | shortcut = x.clone() 83 | bn1 = self.bn1(x) 84 | 85 | out = self.convs(bn1) 86 | out.add_(shortcut) 87 | 88 | return out 89 | -------------------------------------------------------------------------------- /Testing/models/fanet/modules/src/inplace_abn_cpu.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "utils/checks.h" 6 | #include "inplace_abn.h" 7 | 8 | at::Tensor reduce_sum(at::Tensor x) { 9 | if (x.ndimension() == 2) { 10 | return x.sum(0); 11 | } else { 12 | auto x_view = x.view({x.size(0), x.size(1), -1}); 13 | return x_view.sum(-1).sum(0); 14 | } 15 | } 16 | 17 | at::Tensor broadcast_to(at::Tensor v, at::Tensor x) { 18 | if (x.ndimension() == 2) { 19 | return v; 20 | } else { 21 | std::vector broadcast_size = {1, -1}; 22 | for (int64_t i = 2; i < x.ndimension(); ++i) 23 | broadcast_size.push_back(1); 24 | 25 | return v.view(broadcast_size); 26 | } 27 | } 28 | 29 | int64_t count(at::Tensor x) { 30 | int64_t count = x.size(0); 31 | for (int64_t i = 2; i < x.ndimension(); ++i) 32 | count *= x.size(i); 33 | 34 | return count; 35 | } 36 | 37 | at::Tensor invert_affine(at::Tensor z, at::Tensor weight, at::Tensor bias, bool affine, float eps) { 38 | if (affine) { 39 | return (z - broadcast_to(bias, z)) / broadcast_to(at::abs(weight) + eps, z); 40 | } else { 41 | return z; 42 | } 43 | } 44 | 45 | std::vector mean_var_cpu(at::Tensor x) { 46 | auto num = count(x); 47 | auto mean = reduce_sum(x) / num; 48 | auto diff = x - broadcast_to(mean, x); 49 | auto var = reduce_sum(diff.pow(2)) / num; 50 | 51 | return {mean, var}; 52 | } 53 | 54 | at::Tensor forward_cpu(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 55 | bool affine, float eps) { 56 | auto gamma = affine ? at::abs(weight) + eps : at::ones_like(var); 57 | auto mul = at::rsqrt(var + eps) * gamma; 58 | 59 | x.sub_(broadcast_to(mean, x)); 60 | x.mul_(broadcast_to(mul, x)); 61 | if (affine) x.add_(broadcast_to(bias, x)); 62 | 63 | return x; 64 | } 65 | 66 | std::vector edz_eydz_cpu(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 67 | bool affine, float eps) { 68 | auto edz = reduce_sum(dz); 69 | auto y = invert_affine(z, weight, bias, affine, eps); 70 | auto eydz = reduce_sum(y * dz); 71 | 72 | return {edz, eydz}; 73 | } 74 | 75 | at::Tensor backward_cpu(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 76 | at::Tensor edz, at::Tensor eydz, bool affine, float eps) { 77 | auto y = invert_affine(z, weight, bias, affine, eps); 78 | auto mul = affine ? at::rsqrt(var + eps) * (at::abs(weight) + eps) : at::rsqrt(var + eps); 79 | 80 | auto num = count(z); 81 | auto dx = (dz - broadcast_to(edz / num, dz) - y * broadcast_to(eydz / num, dz)) * broadcast_to(mul, dz); 82 | return dx; 83 | } 84 | 85 | void leaky_relu_backward_cpu(at::Tensor z, at::Tensor dz, float slope) { 86 | CHECK_CPU_INPUT(z); 87 | CHECK_CPU_INPUT(dz); 88 | 89 | AT_DISPATCH_FLOATING_TYPES(z.type(), "leaky_relu_backward_cpu", ([&] { 90 | int64_t count = z.numel(); 91 | auto *_z = z.data(); 92 | auto *_dz = dz.data(); 93 | 94 | for (int64_t i = 0; i < count; ++i) { 95 | if (_z[i] < 0) { 96 | _z[i] *= 1 / slope; 97 | _dz[i] *= slope; 98 | } 99 | } 100 | })); 101 | } 102 | 103 | void elu_backward_cpu(at::Tensor z, at::Tensor dz) { 104 | CHECK_CPU_INPUT(z); 105 | CHECK_CPU_INPUT(dz); 106 | 107 | AT_DISPATCH_FLOATING_TYPES(z.type(), "elu_backward_cpu", ([&] { 108 | int64_t count = z.numel(); 109 | auto *_z = z.data(); 110 | auto *_dz = dz.data(); 111 | 112 | for (int64_t i = 0; i < count; ++i) { 113 | if (_z[i] < 0) { 114 | _z[i] = log1p(_z[i]); 115 | _dz[i] *= (_z[i] + 1.f); 116 | } 117 | } 118 | })); 119 | } 120 | -------------------------------------------------------------------------------- /Testing/models/bisenet/modules/residual.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | import torch.nn as nn 4 | 5 | from .bn import ABN 6 | 7 | 8 | class IdentityResidualBlock(nn.Module): 9 | def __init__(self, 10 | in_channels, 11 | channels, 12 | stride=1, 13 | dilation=1, 14 | groups=1, 15 | norm_act=ABN, 16 | dropout=None): 17 | """Configurable identity-mapping residual block 18 | 19 | Parameters 20 | ---------- 21 | in_channels : int 22 | Number of input channels. 23 | channels : list of int 24 | Number of channels in the internal feature maps. Can either have two or three elements: if three construct 25 | a residual block with two `3 x 3` convolutions, otherwise construct a bottleneck block with `1 x 1`, then 26 | `3 x 3` then `1 x 1` convolutions. 27 | stride : int 28 | Stride of the first `3 x 3` convolution 29 | dilation : int 30 | Dilation to apply to the `3 x 3` convolutions. 31 | groups : int 32 | Number of convolution groups. This is used to create ResNeXt-style blocks and is only compatible with 33 | bottleneck blocks. 34 | norm_act : callable 35 | Function to create normalization / activation Module. 36 | dropout: callable 37 | Function to create Dropout Module. 38 | """ 39 | super(IdentityResidualBlock, self).__init__() 40 | 41 | # Check parameters for inconsistencies 42 | if len(channels) != 2 and len(channels) != 3: 43 | raise ValueError("channels must contain either two or three values") 44 | if len(channels) == 2 and groups != 1: 45 | raise ValueError("groups > 1 are only valid if len(channels) == 3") 46 | 47 | is_bottleneck = len(channels) == 3 48 | need_proj_conv = stride != 1 or in_channels != channels[-1] 49 | 50 | self.bn1 = norm_act(in_channels) 51 | if not is_bottleneck: 52 | layers = [ 53 | ("conv1", nn.Conv2d(in_channels, channels[0], 3, stride=stride, padding=dilation, bias=False, 54 | dilation=dilation)), 55 | ("bn2", norm_act(channels[0])), 56 | ("conv2", nn.Conv2d(channels[0], channels[1], 3, stride=1, padding=dilation, bias=False, 57 | dilation=dilation)) 58 | ] 59 | if dropout is not None: 60 | layers = layers[0:2] + [("dropout", dropout())] + layers[2:] 61 | else: 62 | layers = [ 63 | ("conv1", nn.Conv2d(in_channels, channels[0], 1, stride=stride, padding=0, bias=False)), 64 | ("bn2", norm_act(channels[0])), 65 | ("conv2", nn.Conv2d(channels[0], channels[1], 3, stride=1, padding=dilation, bias=False, 66 | groups=groups, dilation=dilation)), 67 | ("bn3", norm_act(channels[1])), 68 | ("conv3", nn.Conv2d(channels[1], channels[2], 1, stride=1, padding=0, bias=False)) 69 | ] 70 | if dropout is not None: 71 | layers = layers[0:4] + [("dropout", dropout())] + layers[4:] 72 | self.convs = nn.Sequential(OrderedDict(layers)) 73 | 74 | if need_proj_conv: 75 | self.proj_conv = nn.Conv2d(in_channels, channels[-1], 1, stride=stride, padding=0, bias=False) 76 | 77 | def forward(self, x): 78 | if hasattr(self, "proj_conv"): 79 | bn1 = self.bn1(x) 80 | shortcut = self.proj_conv(bn1) 81 | else: 82 | shortcut = x.clone() 83 | bn1 = self.bn1(x) 84 | 85 | out = self.convs(bn1) 86 | out.add_(shortcut) 87 | 88 | return out 89 | -------------------------------------------------------------------------------- /Testing/models/bisenet/modules/src/inplace_abn_cpu.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "utils/checks.h" 6 | #include "inplace_abn.h" 7 | 8 | at::Tensor reduce_sum(at::Tensor x) { 9 | if (x.ndimension() == 2) { 10 | return x.sum(0); 11 | } else { 12 | auto x_view = x.view({x.size(0), x.size(1), -1}); 13 | return x_view.sum(-1).sum(0); 14 | } 15 | } 16 | 17 | at::Tensor broadcast_to(at::Tensor v, at::Tensor x) { 18 | if (x.ndimension() == 2) { 19 | return v; 20 | } else { 21 | std::vector broadcast_size = {1, -1}; 22 | for (int64_t i = 2; i < x.ndimension(); ++i) 23 | broadcast_size.push_back(1); 24 | 25 | return v.view(broadcast_size); 26 | } 27 | } 28 | 29 | int64_t count(at::Tensor x) { 30 | int64_t count = x.size(0); 31 | for (int64_t i = 2; i < x.ndimension(); ++i) 32 | count *= x.size(i); 33 | 34 | return count; 35 | } 36 | 37 | at::Tensor invert_affine(at::Tensor z, at::Tensor weight, at::Tensor bias, bool affine, float eps) { 38 | if (affine) { 39 | return (z - broadcast_to(bias, z)) / broadcast_to(at::abs(weight) + eps, z); 40 | } else { 41 | return z; 42 | } 43 | } 44 | 45 | std::vector mean_var_cpu(at::Tensor x) { 46 | auto num = count(x); 47 | auto mean = reduce_sum(x) / num; 48 | auto diff = x - broadcast_to(mean, x); 49 | auto var = reduce_sum(diff.pow(2)) / num; 50 | 51 | return {mean, var}; 52 | } 53 | 54 | at::Tensor forward_cpu(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 55 | bool affine, float eps) { 56 | auto gamma = affine ? at::abs(weight) + eps : at::ones_like(var); 57 | auto mul = at::rsqrt(var + eps) * gamma; 58 | 59 | x.sub_(broadcast_to(mean, x)); 60 | x.mul_(broadcast_to(mul, x)); 61 | if (affine) x.add_(broadcast_to(bias, x)); 62 | 63 | return x; 64 | } 65 | 66 | std::vector edz_eydz_cpu(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 67 | bool affine, float eps) { 68 | auto edz = reduce_sum(dz); 69 | auto y = invert_affine(z, weight, bias, affine, eps); 70 | auto eydz = reduce_sum(y * dz); 71 | 72 | return {edz, eydz}; 73 | } 74 | 75 | at::Tensor backward_cpu(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 76 | at::Tensor edz, at::Tensor eydz, bool affine, float eps) { 77 | auto y = invert_affine(z, weight, bias, affine, eps); 78 | auto mul = affine ? at::rsqrt(var + eps) * (at::abs(weight) + eps) : at::rsqrt(var + eps); 79 | 80 | auto num = count(z); 81 | auto dx = (dz - broadcast_to(edz / num, dz) - y * broadcast_to(eydz / num, dz)) * broadcast_to(mul, dz); 82 | return dx; 83 | } 84 | 85 | void leaky_relu_backward_cpu(at::Tensor z, at::Tensor dz, float slope) { 86 | CHECK_CPU_INPUT(z); 87 | CHECK_CPU_INPUT(dz); 88 | 89 | AT_DISPATCH_FLOATING_TYPES(z.type(), "leaky_relu_backward_cpu", ([&] { 90 | int64_t count = z.numel(); 91 | auto *_z = z.data(); 92 | auto *_dz = dz.data(); 93 | 94 | for (int64_t i = 0; i < count; ++i) { 95 | if (_z[i] < 0) { 96 | _z[i] *= 1 / slope; 97 | _dz[i] *= slope; 98 | } 99 | } 100 | })); 101 | } 102 | 103 | void elu_backward_cpu(at::Tensor z, at::Tensor dz) { 104 | CHECK_CPU_INPUT(z); 105 | CHECK_CPU_INPUT(dz); 106 | 107 | AT_DISPATCH_FLOATING_TYPES(z.type(), "elu_backward_cpu", ([&] { 108 | int64_t count = z.numel(); 109 | auto *_z = z.data(); 110 | auto *_dz = dz.data(); 111 | 112 | for (int64_t i = 0; i < count; ++i) { 113 | if (_z[i] < 0) { 114 | _z[i] = log1p(_z[i]); 115 | _dz[i] *= (_z[i] + 1.f); 116 | } 117 | } 118 | })); 119 | } 120 | -------------------------------------------------------------------------------- /Testing/models/shelfnet/modules/residual.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | import torch.nn as nn 4 | 5 | from .bn import ABN 6 | 7 | 8 | class IdentityResidualBlock(nn.Module): 9 | def __init__(self, 10 | in_channels, 11 | channels, 12 | stride=1, 13 | dilation=1, 14 | groups=1, 15 | norm_act=ABN, 16 | dropout=None): 17 | """Configurable identity-mapping residual block 18 | 19 | Parameters 20 | ---------- 21 | in_channels : int 22 | Number of input channels. 23 | channels : list of int 24 | Number of channels in the internal feature maps. Can either have two or three elements: if three construct 25 | a residual block with two `3 x 3` convolutions, otherwise construct a bottleneck block with `1 x 1`, then 26 | `3 x 3` then `1 x 1` convolutions. 27 | stride : int 28 | Stride of the first `3 x 3` convolution 29 | dilation : int 30 | Dilation to apply to the `3 x 3` convolutions. 31 | groups : int 32 | Number of convolution groups. This is used to create ResNeXt-style blocks and is only compatible with 33 | bottleneck blocks. 34 | norm_act : callable 35 | Function to create normalization / activation Module. 36 | dropout: callable 37 | Function to create Dropout Module. 38 | """ 39 | super(IdentityResidualBlock, self).__init__() 40 | 41 | # Check parameters for inconsistencies 42 | if len(channels) != 2 and len(channels) != 3: 43 | raise ValueError("channels must contain either two or three values") 44 | if len(channels) == 2 and groups != 1: 45 | raise ValueError("groups > 1 are only valid if len(channels) == 3") 46 | 47 | is_bottleneck = len(channels) == 3 48 | need_proj_conv = stride != 1 or in_channels != channels[-1] 49 | 50 | self.bn1 = norm_act(in_channels) 51 | if not is_bottleneck: 52 | layers = [ 53 | ("conv1", nn.Conv2d(in_channels, channels[0], 3, stride=stride, padding=dilation, bias=False, 54 | dilation=dilation)), 55 | ("bn2", norm_act(channels[0])), 56 | ("conv2", nn.Conv2d(channels[0], channels[1], 3, stride=1, padding=dilation, bias=False, 57 | dilation=dilation)) 58 | ] 59 | if dropout is not None: 60 | layers = layers[0:2] + [("dropout", dropout())] + layers[2:] 61 | else: 62 | layers = [ 63 | ("conv1", nn.Conv2d(in_channels, channels[0], 1, stride=stride, padding=0, bias=False)), 64 | ("bn2", norm_act(channels[0])), 65 | ("conv2", nn.Conv2d(channels[0], channels[1], 3, stride=1, padding=dilation, bias=False, 66 | groups=groups, dilation=dilation)), 67 | ("bn3", norm_act(channels[1])), 68 | ("conv3", nn.Conv2d(channels[1], channels[2], 1, stride=1, padding=0, bias=False)) 69 | ] 70 | if dropout is not None: 71 | layers = layers[0:4] + [("dropout", dropout())] + layers[4:] 72 | self.convs = nn.Sequential(OrderedDict(layers)) 73 | 74 | if need_proj_conv: 75 | self.proj_conv = nn.Conv2d(in_channels, channels[-1], 1, stride=stride, padding=0, bias=False) 76 | 77 | def forward(self, x): 78 | if hasattr(self, "proj_conv"): 79 | bn1 = self.bn1(x) 80 | shortcut = self.proj_conv(bn1) 81 | else: 82 | shortcut = x.clone() 83 | bn1 = self.bn1(x) 84 | 85 | out = self.convs(bn1) 86 | out.add_(shortcut) 87 | 88 | return out 89 | -------------------------------------------------------------------------------- /Testing/models/shelfnet/modules/src/inplace_abn_cpu.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "utils/checks.h" 6 | #include "inplace_abn.h" 7 | 8 | at::Tensor reduce_sum(at::Tensor x) { 9 | if (x.ndimension() == 2) { 10 | return x.sum(0); 11 | } else { 12 | auto x_view = x.view({x.size(0), x.size(1), -1}); 13 | return x_view.sum(-1).sum(0); 14 | } 15 | } 16 | 17 | at::Tensor broadcast_to(at::Tensor v, at::Tensor x) { 18 | if (x.ndimension() == 2) { 19 | return v; 20 | } else { 21 | std::vector broadcast_size = {1, -1}; 22 | for (int64_t i = 2; i < x.ndimension(); ++i) 23 | broadcast_size.push_back(1); 24 | 25 | return v.view(broadcast_size); 26 | } 27 | } 28 | 29 | int64_t count(at::Tensor x) { 30 | int64_t count = x.size(0); 31 | for (int64_t i = 2; i < x.ndimension(); ++i) 32 | count *= x.size(i); 33 | 34 | return count; 35 | } 36 | 37 | at::Tensor invert_affine(at::Tensor z, at::Tensor weight, at::Tensor bias, bool affine, float eps) { 38 | if (affine) { 39 | return (z - broadcast_to(bias, z)) / broadcast_to(at::abs(weight) + eps, z); 40 | } else { 41 | return z; 42 | } 43 | } 44 | 45 | std::vector mean_var_cpu(at::Tensor x) { 46 | auto num = count(x); 47 | auto mean = reduce_sum(x) / num; 48 | auto diff = x - broadcast_to(mean, x); 49 | auto var = reduce_sum(diff.pow(2)) / num; 50 | 51 | return {mean, var}; 52 | } 53 | 54 | at::Tensor forward_cpu(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 55 | bool affine, float eps) { 56 | auto gamma = affine ? at::abs(weight) + eps : at::ones_like(var); 57 | auto mul = at::rsqrt(var + eps) * gamma; 58 | 59 | x.sub_(broadcast_to(mean, x)); 60 | x.mul_(broadcast_to(mul, x)); 61 | if (affine) x.add_(broadcast_to(bias, x)); 62 | 63 | return x; 64 | } 65 | 66 | std::vector edz_eydz_cpu(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 67 | bool affine, float eps) { 68 | auto edz = reduce_sum(dz); 69 | auto y = invert_affine(z, weight, bias, affine, eps); 70 | auto eydz = reduce_sum(y * dz); 71 | 72 | return {edz, eydz}; 73 | } 74 | 75 | at::Tensor backward_cpu(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 76 | at::Tensor edz, at::Tensor eydz, bool affine, float eps) { 77 | auto y = invert_affine(z, weight, bias, affine, eps); 78 | auto mul = affine ? at::rsqrt(var + eps) * (at::abs(weight) + eps) : at::rsqrt(var + eps); 79 | 80 | auto num = count(z); 81 | auto dx = (dz - broadcast_to(edz / num, dz) - y * broadcast_to(eydz / num, dz)) * broadcast_to(mul, dz); 82 | return dx; 83 | } 84 | 85 | void leaky_relu_backward_cpu(at::Tensor z, at::Tensor dz, float slope) { 86 | CHECK_CPU_INPUT(z); 87 | CHECK_CPU_INPUT(dz); 88 | 89 | AT_DISPATCH_FLOATING_TYPES(z.type(), "leaky_relu_backward_cpu", ([&] { 90 | int64_t count = z.numel(); 91 | auto *_z = z.data(); 92 | auto *_dz = dz.data(); 93 | 94 | for (int64_t i = 0; i < count; ++i) { 95 | if (_z[i] < 0) { 96 | _z[i] *= 1 / slope; 97 | _dz[i] *= slope; 98 | } 99 | } 100 | })); 101 | } 102 | 103 | void elu_backward_cpu(at::Tensor z, at::Tensor dz) { 104 | CHECK_CPU_INPUT(z); 105 | CHECK_CPU_INPUT(dz); 106 | 107 | AT_DISPATCH_FLOATING_TYPES(z.type(), "elu_backward_cpu", ([&] { 108 | int64_t count = z.numel(); 109 | auto *_z = z.data(); 110 | auto *_dz = dz.data(); 111 | 112 | for (int64_t i = 0; i < count; ++i) { 113 | if (_z[i] < 0) { 114 | _z[i] = log1p(_z[i]); 115 | _dz[i] *= (_z[i] + 1.f); 116 | } 117 | } 118 | })); 119 | } 120 | -------------------------------------------------------------------------------- /Train/ptsemseg/models/fanet/modules/residual.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | import torch.nn as nn 4 | 5 | from .bn import ABN 6 | 7 | 8 | class IdentityResidualBlock(nn.Module): 9 | def __init__(self, 10 | in_channels, 11 | channels, 12 | stride=1, 13 | dilation=1, 14 | groups=1, 15 | norm_act=ABN, 16 | dropout=None): 17 | """Configurable identity-mapping residual block 18 | 19 | Parameters 20 | ---------- 21 | in_channels : int 22 | Number of input channels. 23 | channels : list of int 24 | Number of channels in the internal feature maps. Can either have two or three elements: if three construct 25 | a residual block with two `3 x 3` convolutions, otherwise construct a bottleneck block with `1 x 1`, then 26 | `3 x 3` then `1 x 1` convolutions. 27 | stride : int 28 | Stride of the first `3 x 3` convolution 29 | dilation : int 30 | Dilation to apply to the `3 x 3` convolutions. 31 | groups : int 32 | Number of convolution groups. This is used to create ResNeXt-style blocks and is only compatible with 33 | bottleneck blocks. 34 | norm_act : callable 35 | Function to create normalization / activation Module. 36 | dropout: callable 37 | Function to create Dropout Module. 38 | """ 39 | super(IdentityResidualBlock, self).__init__() 40 | 41 | # Check parameters for inconsistencies 42 | if len(channels) != 2 and len(channels) != 3: 43 | raise ValueError("channels must contain either two or three values") 44 | if len(channels) == 2 and groups != 1: 45 | raise ValueError("groups > 1 are only valid if len(channels) == 3") 46 | 47 | is_bottleneck = len(channels) == 3 48 | need_proj_conv = stride != 1 or in_channels != channels[-1] 49 | 50 | self.bn1 = norm_act(in_channels) 51 | if not is_bottleneck: 52 | layers = [ 53 | ("conv1", nn.Conv2d(in_channels, channels[0], 3, stride=stride, padding=dilation, bias=False, 54 | dilation=dilation)), 55 | ("bn2", norm_act(channels[0])), 56 | ("conv2", nn.Conv2d(channels[0], channels[1], 3, stride=1, padding=dilation, bias=False, 57 | dilation=dilation)) 58 | ] 59 | if dropout is not None: 60 | layers = layers[0:2] + [("dropout", dropout())] + layers[2:] 61 | else: 62 | layers = [ 63 | ("conv1", nn.Conv2d(in_channels, channels[0], 1, stride=stride, padding=0, bias=False)), 64 | ("bn2", norm_act(channels[0])), 65 | ("conv2", nn.Conv2d(channels[0], channels[1], 3, stride=1, padding=dilation, bias=False, 66 | groups=groups, dilation=dilation)), 67 | ("bn3", norm_act(channels[1])), 68 | ("conv3", nn.Conv2d(channels[1], channels[2], 1, stride=1, padding=0, bias=False)) 69 | ] 70 | if dropout is not None: 71 | layers = layers[0:4] + [("dropout", dropout())] + layers[4:] 72 | self.convs = nn.Sequential(OrderedDict(layers)) 73 | 74 | if need_proj_conv: 75 | self.proj_conv = nn.Conv2d(in_channels, channels[-1], 1, stride=stride, padding=0, bias=False) 76 | 77 | def forward(self, x): 78 | if hasattr(self, "proj_conv"): 79 | bn1 = self.bn1(x) 80 | shortcut = self.proj_conv(bn1) 81 | else: 82 | shortcut = x.clone() 83 | bn1 = self.bn1(x) 84 | 85 | out = self.convs(bn1) 86 | out.add_(shortcut) 87 | 88 | return out 89 | -------------------------------------------------------------------------------- /Train/ptsemseg/models/fanet/modules/src/inplace_abn_cpu.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "utils/checks.h" 6 | #include "inplace_abn.h" 7 | 8 | at::Tensor reduce_sum(at::Tensor x) { 9 | if (x.ndimension() == 2) { 10 | return x.sum(0); 11 | } else { 12 | auto x_view = x.view({x.size(0), x.size(1), -1}); 13 | return x_view.sum(-1).sum(0); 14 | } 15 | } 16 | 17 | at::Tensor broadcast_to(at::Tensor v, at::Tensor x) { 18 | if (x.ndimension() == 2) { 19 | return v; 20 | } else { 21 | std::vector broadcast_size = {1, -1}; 22 | for (int64_t i = 2; i < x.ndimension(); ++i) 23 | broadcast_size.push_back(1); 24 | 25 | return v.view(broadcast_size); 26 | } 27 | } 28 | 29 | int64_t count(at::Tensor x) { 30 | int64_t count = x.size(0); 31 | for (int64_t i = 2; i < x.ndimension(); ++i) 32 | count *= x.size(i); 33 | 34 | return count; 35 | } 36 | 37 | at::Tensor invert_affine(at::Tensor z, at::Tensor weight, at::Tensor bias, bool affine, float eps) { 38 | if (affine) { 39 | return (z - broadcast_to(bias, z)) / broadcast_to(at::abs(weight) + eps, z); 40 | } else { 41 | return z; 42 | } 43 | } 44 | 45 | std::vector mean_var_cpu(at::Tensor x) { 46 | auto num = count(x); 47 | auto mean = reduce_sum(x) / num; 48 | auto diff = x - broadcast_to(mean, x); 49 | auto var = reduce_sum(diff.pow(2)) / num; 50 | 51 | return {mean, var}; 52 | } 53 | 54 | at::Tensor forward_cpu(at::Tensor x, at::Tensor mean, at::Tensor var, at::Tensor weight, at::Tensor bias, 55 | bool affine, float eps) { 56 | auto gamma = affine ? at::abs(weight) + eps : at::ones_like(var); 57 | auto mul = at::rsqrt(var + eps) * gamma; 58 | 59 | x.sub_(broadcast_to(mean, x)); 60 | x.mul_(broadcast_to(mul, x)); 61 | if (affine) x.add_(broadcast_to(bias, x)); 62 | 63 | return x; 64 | } 65 | 66 | std::vector edz_eydz_cpu(at::Tensor z, at::Tensor dz, at::Tensor weight, at::Tensor bias, 67 | bool affine, float eps) { 68 | auto edz = reduce_sum(dz); 69 | auto y = invert_affine(z, weight, bias, affine, eps); 70 | auto eydz = reduce_sum(y * dz); 71 | 72 | return {edz, eydz}; 73 | } 74 | 75 | at::Tensor backward_cpu(at::Tensor z, at::Tensor dz, at::Tensor var, at::Tensor weight, at::Tensor bias, 76 | at::Tensor edz, at::Tensor eydz, bool affine, float eps) { 77 | auto y = invert_affine(z, weight, bias, affine, eps); 78 | auto mul = affine ? at::rsqrt(var + eps) * (at::abs(weight) + eps) : at::rsqrt(var + eps); 79 | 80 | auto num = count(z); 81 | auto dx = (dz - broadcast_to(edz / num, dz) - y * broadcast_to(eydz / num, dz)) * broadcast_to(mul, dz); 82 | return dx; 83 | } 84 | 85 | void leaky_relu_backward_cpu(at::Tensor z, at::Tensor dz, float slope) { 86 | CHECK_CPU_INPUT(z); 87 | CHECK_CPU_INPUT(dz); 88 | 89 | AT_DISPATCH_FLOATING_TYPES(z.type(), "leaky_relu_backward_cpu", ([&] { 90 | int64_t count = z.numel(); 91 | auto *_z = z.data(); 92 | auto *_dz = dz.data(); 93 | 94 | for (int64_t i = 0; i < count; ++i) { 95 | if (_z[i] < 0) { 96 | _z[i] *= 1 / slope; 97 | _dz[i] *= slope; 98 | } 99 | } 100 | })); 101 | } 102 | 103 | void elu_backward_cpu(at::Tensor z, at::Tensor dz) { 104 | CHECK_CPU_INPUT(z); 105 | CHECK_CPU_INPUT(dz); 106 | 107 | AT_DISPATCH_FLOATING_TYPES(z.type(), "elu_backward_cpu", ([&] { 108 | int64_t count = z.numel(); 109 | auto *_z = z.data(); 110 | auto *_dz = dz.data(); 111 | 112 | for (int64_t i = 0; i < count; ++i) { 113 | if (_z[i] < 0) { 114 | _z[i] = log1p(_z[i]); 115 | _dz[i] *= (_z[i] + 1.f); 116 | } 117 | } 118 | })); 119 | } 120 | -------------------------------------------------------------------------------- /Testing/models/swiftnet/util.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | upsample = lambda x, size: F.interpolate(x, size, mode='bilinear', align_corners=False) 6 | batchnorm_momentum = 0.01 / 2 7 | 8 | 9 | def get_n_params(parameters): 10 | pp = 0 11 | for p in parameters: 12 | nn = 1 13 | for s in list(p.size()): 14 | nn = nn * s 15 | pp += nn 16 | return pp 17 | 18 | 19 | class _BNReluConv(nn.Sequential): 20 | def __init__(self, num_maps_in, num_maps_out, k=3, batch_norm=True, bn_momentum=0.1, bias=False, dilation=1): 21 | super(_BNReluConv, self).__init__() 22 | if batch_norm: 23 | self.add_module('norm', nn.BatchNorm2d(num_maps_in, momentum=bn_momentum)) 24 | self.add_module('relu', nn.ReLU(inplace=batch_norm is True)) 25 | padding = k // 2 26 | self.add_module('conv', nn.Conv2d(num_maps_in, num_maps_out, 27 | kernel_size=k, padding=padding, bias=bias, dilation=dilation)) 28 | 29 | 30 | class _Upsample(nn.Module): 31 | def __init__(self, num_maps_in, skip_maps_in, num_maps_out, use_bn=True, k=3): 32 | super(_Upsample, self).__init__() 33 | #print(f'Upsample layer: in = {num_maps_in}, skip = {skip_maps_in}, out = {num_maps_out}') 34 | self.bottleneck = _BNReluConv(skip_maps_in, num_maps_in, k=1, batch_norm=use_bn) 35 | self.blend_conv = _BNReluConv(num_maps_in, num_maps_out, k=k, batch_norm=use_bn) 36 | 37 | def forward(self, x, skip): 38 | skip = self.bottleneck.forward(skip) 39 | skip_size = skip.size()[2:4] 40 | x = upsample(x, skip_size) 41 | x = x + skip 42 | x = self.blend_conv.forward(x) 43 | return x 44 | 45 | 46 | class SpatialPyramidPooling(nn.Module): 47 | def __init__(self, num_maps_in, num_levels, bt_size=512, level_size=128, out_size=128, 48 | grids=(6, 3, 2, 1), square_grid=False, bn_momentum=0.1, use_bn=True): 49 | super(SpatialPyramidPooling, self).__init__() 50 | self.grids = grids 51 | self.square_grid = square_grid 52 | self.spp = nn.Sequential() 53 | self.spp.add_module('spp_bn', 54 | _BNReluConv(num_maps_in, bt_size, k=1, bn_momentum=bn_momentum, batch_norm=use_bn)) 55 | num_features = bt_size 56 | final_size = num_features 57 | for i in range(num_levels): 58 | final_size += level_size 59 | self.spp.add_module('spp' + str(i), 60 | _BNReluConv(num_features, level_size, k=1, bn_momentum=bn_momentum, batch_norm=use_bn)) 61 | self.spp.add_module('spp_fuse', 62 | _BNReluConv(final_size, out_size, k=1, bn_momentum=bn_momentum, batch_norm=use_bn)) 63 | 64 | def forward(self, x): 65 | levels = [] 66 | target_size = x.size()[2:4] 67 | 68 | ar = target_size[1] / target_size[0] 69 | 70 | x = self.spp[0].forward(x) 71 | levels.append(x) 72 | num = len(self.spp) - 1 73 | 74 | for i in range(1, num): 75 | if not self.square_grid: 76 | grid_size = (self.grids[i - 1], max(1, round(ar * self.grids[i - 1]))) 77 | x_pooled = F.adaptive_avg_pool2d(x, grid_size) 78 | else: 79 | x_pooled = F.adaptive_avg_pool2d(x, self.grids[i - 1]) 80 | level = self.spp[i].forward(x_pooled) 81 | 82 | level = upsample(level, target_size) 83 | levels.append(level) 84 | x = torch.cat(levels, 1) 85 | x = self.spp[-1].forward(x) 86 | return x 87 | 88 | 89 | class _UpsampleBlend(nn.Module): 90 | def __init__(self, num_features, use_bn=True): 91 | super(_UpsampleBlend, self).__init__() 92 | self.blend_conv = _BNReluConv(num_features, num_features, k=3, batch_norm=use_bn) 93 | 94 | def forward(self, x, skip): 95 | skip_size = skip.size()[2:4] 96 | x = upsample(x, skip_size) 97 | x = x + skip 98 | x = self.blend_conv.forward(x) 99 | return x 100 | -------------------------------------------------------------------------------- /Testing/models/shelfnet/resnet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- encoding: utf-8 -*- 3 | 4 | import torch 5 | import torch.nn as nn 6 | import torch.nn.functional as F 7 | import torch.utils.model_zoo as modelzoo 8 | 9 | #from .modules.bn import InPlaceABNSync as BatchNorm2d 10 | 11 | resnet18_url = 'https://download.pytorch.org/models/resnet18-5c106cde.pth' 12 | 13 | class BatchNorm2d(nn.Module): 14 | '''(conv => BN => ReLU) * 2''' 15 | def __init__(self, num_features, activation='none'): 16 | super(BatchNorm2d, self).__init__() 17 | 18 | def forward(self, x): 19 | return x 20 | 21 | def conv3x3(in_planes, out_planes, stride=1): 22 | """3x3 convolution with padding""" 23 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, 24 | padding=1, bias=False) 25 | 26 | 27 | class BasicBlock(nn.Module): 28 | def __init__(self, in_chan, out_chan, stride=1): 29 | super(BasicBlock, self).__init__() 30 | self.conv1 = conv3x3(in_chan, out_chan, stride) 31 | self.bn1 = BatchNorm2d(out_chan) 32 | self.conv2 = conv3x3(out_chan, out_chan) 33 | self.bn2 = BatchNorm2d(out_chan, activation='none') 34 | self.relu = nn.ReLU(inplace=True) 35 | self.downsample = None 36 | if in_chan != out_chan or stride != 1: 37 | self.downsample = nn.Sequential( 38 | nn.Conv2d(in_chan, out_chan, 39 | kernel_size=1, stride=stride, bias=False), 40 | BatchNorm2d(out_chan, activation='none'), 41 | ) 42 | 43 | def forward(self, x): 44 | residual = self.conv1(x) 45 | residual = self.bn1(residual) 46 | residual = self.conv2(residual) 47 | residual = self.bn2(residual) 48 | 49 | shortcut = x 50 | if self.downsample is not None: 51 | shortcut = self.downsample(x) 52 | 53 | out = shortcut + residual 54 | out = self.relu(out) 55 | return out 56 | 57 | 58 | def create_layer_basic(in_chan, out_chan, bnum, stride=1): 59 | layers = [BasicBlock(in_chan, out_chan, stride=stride)] 60 | for i in range(bnum-1): 61 | layers.append(BasicBlock(out_chan, out_chan, stride=1)) 62 | return nn.Sequential(*layers) 63 | 64 | 65 | class Resnet18(nn.Module): 66 | def __init__(self): 67 | super(Resnet18, self).__init__() 68 | self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, 69 | bias=False) 70 | self.bn1 = BatchNorm2d(64) 71 | self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) 72 | self.layer1 = create_layer_basic(64, 64, bnum=2, stride=1) 73 | self.layer2 = create_layer_basic(64, 128, bnum=2, stride=2) 74 | self.layer3 = create_layer_basic(128, 256, bnum=2, stride=2) 75 | self.layer4 = create_layer_basic(256, 512, bnum=2, stride=2) 76 | self.init_weight() 77 | 78 | def forward(self, x): 79 | x = self.conv1(x) 80 | x = self.bn1(x) 81 | x = self.maxpool(x) 82 | 83 | x = self.layer1(x) 84 | feat8 = self.layer2(x) # 1/8 85 | feat16 = self.layer3(feat8) # 1/16 86 | feat32 = self.layer4(feat16) # 1/32 87 | return feat8, feat16, feat32 88 | 89 | def init_weight(self): 90 | state_dict = modelzoo.load_url(resnet18_url) 91 | self_state_dict = self.state_dict() 92 | for k, v in state_dict.items(): 93 | if 'fc' in k: continue 94 | self_state_dict.update({k: v}) 95 | #self.load_state_dict(self_state_dict) 96 | 97 | def get_params(self): 98 | wd_params, nowd_params = [], [] 99 | for name, module in self.named_modules(): 100 | if isinstance(module, (nn.Linear, nn.Conv2d)): 101 | wd_params.append(module.weight) 102 | if not module.bias is None: 103 | nowd_params.append(module.bias) 104 | elif isinstance(module, (BatchNorm2d, nn.BatchNorm2d)): 105 | nowd_params += list(module.parameters()) 106 | return wd_params, nowd_params 107 | 108 | 109 | if __name__ == "__main__": 110 | net = Resnet18() 111 | x = torch.randn(16, 3, 224, 224) 112 | out = net(x) 113 | print(out[0].size()) 114 | print(out[1].size()) 115 | print(out[2].size()) 116 | net.get_params() 117 | -------------------------------------------------------------------------------- /Train/ptsemseg/loader/context_loader.py: -------------------------------------------------------------------------------- 1 | import os 2 | import torch 3 | import numpy as np 4 | import imageio as m 5 | import cv2 6 | from torch.utils import data 7 | import torchvision.transforms.functional as TF 8 | from ptsemseg.utils import recursive_glob 9 | from ptsemseg.augmentations import Compose, RandomHorizontallyFlip, RandomRotate, Scale 10 | 11 | def color_map( N=59, normalized=False): 12 | """ 13 | Return Color Map in PASCAL VOC format 14 | """ 15 | 16 | def bitget(byteval, idx): 17 | return (byteval & (1 << idx)) != 0 18 | 19 | dtype = "float32" if normalized else "uint8" 20 | cmap = np.zeros((N, 3), dtype=dtype) 21 | for i in range(N): 22 | r = g = b = 0 23 | c = i 24 | for j in range(8): 25 | r = r | (bitget(c, 0) << 7 - j) 26 | g = g | (bitget(c, 1) << 7 - j) 27 | b = b | (bitget(c, 2) << 7 - j) 28 | c = c >> 3 29 | 30 | cmap[i] = np.array([r, g, b]) 31 | 32 | cmap = cmap / 255.0 if normalized else cmap 33 | return cmap 34 | 35 | class contextLoader(data.Dataset): 36 | 37 | colors = color_map(N=256) 38 | label_colours = dict(zip(range(256), colors)) 39 | 40 | def __init__( 41 | self, 42 | root, 43 | split="train", 44 | augmentations=None, 45 | test_mode=False, 46 | model_name=None 47 | ): 48 | self.root = root 49 | self.split = split 50 | self.augmentations = augmentations 51 | self.test_mode=test_mode 52 | self.model_name=model_name 53 | self.n_classes = 59 54 | self.files = {} 55 | 56 | self.images_base = os.path.join(self.root, "Img", self.split) 57 | self.annotations_base = os.path.join(self.root, "trainval59", self.split) 58 | 59 | self.files[split] = recursive_glob(rootdir=self.annotations_base, suffix=".png") 60 | 61 | self.void_classes = [0] 62 | self.valid_classes = range(1,60) 63 | self.class_names = [] 64 | 65 | self.ignore_index = 250 66 | self.class_map = dict(zip(self.valid_classes, range(59))) 67 | 68 | if not self.files[split]: 69 | raise Exception("No files for split=[%s] found in %s" % (split, self.images_base)) 70 | 71 | print("Found %d %s images" % (len(self.files[split]), split)) 72 | 73 | def __len__(self): 74 | """__len__""" 75 | return len(self.files[self.split]) 76 | 77 | def __getitem__(self, index): 78 | """__getitem__ 79 | 80 | :param index: 81 | """ 82 | lbl_path = self.files[self.split][index].rstrip() 83 | img_path = os.path.join( 84 | self.images_base, 85 | os.path.basename(lbl_path))[:-3]+'jpg' 86 | 87 | img = m.imread(img_path) 88 | img = np.array(img, dtype=np.uint8) 89 | h,w,c = img.shape 90 | 91 | lbl = m.imread(lbl_path) 92 | lbl = cv2.resize(lbl,(w,h), interpolation = cv2.INTER_NEAREST) 93 | 94 | 95 | lbl = self.encode_segmap(np.array(lbl, dtype=np.uint8)) 96 | '''import cv2 97 | cv2.namedWindow("Image") 98 | cv2.imshow("Image", self.decode_segmap(lbl)) 99 | cv2.waitKey(0) 100 | cv2.destroyAllWindows()''' 101 | 102 | if self.augmentations is not None: 103 | img, lbl = self.augmentations(img, lbl) 104 | 105 | img = img.transpose(2, 0, 1) 106 | img = torch.from_numpy(img).float() 107 | lbl = torch.from_numpy(lbl).long() 108 | if self.test_mode: 109 | return img, lbl, 1, 1, 1 110 | return img, lbl 111 | 112 | def decode_segmap(self, temp): 113 | r = temp.copy() 114 | g = temp.copy() 115 | b = temp.copy() 116 | for l in range(0, self.n_classes): 117 | r[temp == l] = self.label_colours[l][0] 118 | g[temp == l] = self.label_colours[l][1] 119 | b[temp == l] = self.label_colours[l][2] 120 | 121 | rgb = np.zeros((temp.shape[0], temp.shape[1], 3)) 122 | rgb[:, :, 0] = r / 255.0 123 | rgb[:, :, 1] = g / 255.0 124 | rgb[:, :, 2] = b / 255.0 125 | return rgb 126 | 127 | 128 | def encode_segmap(self, mask): 129 | mask_ = mask.copy() 130 | mask_ = mask_*0 131 | # Put all void classes to zero 132 | for _voidc in self.void_classes: 133 | mask_[mask == _voidc] = self.ignore_index 134 | for _validc in self.valid_classes: 135 | mask_[mask == _validc] = self.class_map[_validc] 136 | return mask_.astype(np.uint8) 137 | -------------------------------------------------------------------------------- /Train/ptsemseg/loader/ade20k_loader.py: -------------------------------------------------------------------------------- 1 | import os 2 | import torch 3 | import numpy as np 4 | import imageio as m 5 | import cv2 6 | from torch.utils import data 7 | import torchvision.transforms.functional as TF 8 | from ptsemseg.utils import recursive_glob 9 | from ptsemseg.augmentations import Compose, RandomHorizontallyFlip, RandomRotate, Scale 10 | 11 | def color_map( N=40, normalized=False): 12 | """ 13 | Return Color Map in PASCAL VOC format 14 | """ 15 | 16 | def bitget(byteval, idx): 17 | return (byteval & (1 << idx)) != 0 18 | 19 | dtype = "float32" if normalized else "uint8" 20 | cmap = np.zeros((N, 3), dtype=dtype) 21 | for i in range(N): 22 | r = g = b = 0 23 | c = i 24 | for j in range(8): 25 | r = r | (bitget(c, 0) << 7 - j) 26 | g = g | (bitget(c, 1) << 7 - j) 27 | b = b | (bitget(c, 2) << 7 - j) 28 | c = c >> 3 29 | 30 | cmap[i] = np.array([r, g, b]) 31 | 32 | cmap = cmap / 255.0 if normalized else cmap 33 | return cmap 34 | 35 | class ade20kLoader(data.Dataset): 36 | 37 | colors = color_map(N=256) 38 | label_colours = dict(zip(range(256), colors)) 39 | 40 | def __init__( 41 | self, 42 | root, 43 | split="train", 44 | augmentations=None, 45 | test_mode=False, 46 | model_name=None 47 | ): 48 | self.root = root 49 | self.split = split 50 | self.augmentations = augmentations 51 | self.test_mode=test_mode 52 | self.model_name=model_name 53 | self.n_classes = 150 54 | self.files = {} 55 | 56 | self.images_base = os.path.join(self.root, "IMG", self.split) 57 | self.annotations_base = os.path.join(self.root, "GT", self.split) 58 | 59 | self.files[split] = recursive_glob(rootdir=self.annotations_base, suffix=".png") 60 | 61 | self.void_classes = [0] 62 | self.valid_classes = range(1,151) 63 | self.class_names = [] 64 | 65 | self.ignore_index = 250 66 | self.class_map = dict(zip(self.valid_classes, range(150))) 67 | 68 | if not self.files[split]: 69 | raise Exception("No files for split=[%s] found in %s" % (split, self.images_base)) 70 | 71 | print("Found %d %s images" % (len(self.files[split]), split)) 72 | 73 | def __len__(self): 74 | """__len__""" 75 | return len(self.files[self.split]) 76 | 77 | def __getitem__(self, index): 78 | """__getitem__ 79 | 80 | :param index: 81 | """ 82 | lbl_path = self.files[self.split][index].rstrip() 83 | img_path = os.path.join( 84 | self.images_base, 85 | os.path.basename(lbl_path))[:-3]+'jpg' 86 | 87 | img = m.imread(img_path) 88 | img = np.array(img, dtype=np.uint8) 89 | if len(img.shape)==2: 90 | img = img[:,:, np.newaxis] 91 | img = img.repeat(3, axis=2) 92 | 93 | h,w,c = img.shape 94 | 95 | lbl = m.imread(lbl_path) 96 | lbl = cv2.resize(lbl,(w,h), interpolation = cv2.INTER_NEAREST) 97 | lbl = self.encode_segmap(np.array(lbl, dtype=np.uint8)) 98 | 99 | '''import cv2 100 | cv2.namedWindow("Image") 101 | cv2.imshow("Image", self.decode_segmap(lbl)) 102 | cv2.waitKey(0) 103 | cv2.destroyAllWindows()''' 104 | 105 | if self.augmentations is not None: 106 | img, lbl = self.augmentations(img, lbl) 107 | 108 | img = img.transpose(2, 0, 1) 109 | img = torch.from_numpy(img).float() 110 | lbl = torch.from_numpy(lbl).long() 111 | 112 | if self.test_mode: 113 | return img, lbl, os.path.basename(lbl_path)[:-3], h, w 114 | return img, lbl 115 | 116 | def decode_segmap(self, temp): 117 | r = temp.copy() 118 | g = temp.copy() 119 | b = temp.copy() 120 | for l in range(0, self.n_classes): 121 | r[temp == l] = self.label_colours[l][0] 122 | g[temp == l] = self.label_colours[l][1] 123 | b[temp == l] = self.label_colours[l][2] 124 | 125 | rgb = np.zeros((temp.shape[0], temp.shape[1], 3)) 126 | rgb[:, :, 0] = r / 255.0 127 | rgb[:, :, 1] = g / 255.0 128 | rgb[:, :, 2] = b / 255.0 129 | return rgb 130 | 131 | def encode_segmap(self, mask): 132 | mask_ = mask.copy() 133 | mask_ = mask_*0 134 | # Put all void classes to zero 135 | for _voidc in self.void_classes: 136 | mask_[mask == _voidc] = self.ignore_index 137 | for _validc in self.valid_classes: 138 | mask_[mask == _validc] = self.class_map[_validc] 139 | return mask_.astype(np.uint8) 140 | 141 | def decode_pred(self, mask): 142 | # Put all void classes to zero 143 | for _predc in range(self.n_classes): 144 | mask[mask == _predc] = self.valid_classes[_predc] 145 | return mask.astype(np.uint8) 146 | -------------------------------------------------------------------------------- /Train/ptsemseg/optimizers/adaoptimizer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- encoding: utf-8 -*- 3 | 4 | import pdb 5 | import torch 6 | import logging 7 | 8 | logger = logging.getLogger() 9 | 10 | class AdaOptimizer(object): 11 | def __init__(self, 12 | model, 13 | lr0=0.02, 14 | momentum=0.9, 15 | wd=1.0e-4, 16 | warmup_steps=-1000, 17 | warmup_start_lr=1.0e-5, 18 | max_iter=150000, 19 | power=0.9, 20 | type_='sgd', 21 | betas=(0.9, 0.999), 22 | lr_multi=10, 23 | bn_wd_disable=False, 24 | *args, **kwargs): 25 | 26 | self.type_ = type_ 27 | self.betas = betas 28 | self.lr_multi = lr_multi 29 | self.bn_wd_disable = bn_wd_disable 30 | self.warmup_steps = warmup_steps 31 | self.warmup_start_lr = warmup_start_lr 32 | self.lr0 = lr0 33 | self.lr = self.lr0 34 | self.max_iter = float(max_iter) 35 | self.power = power 36 | self.it = 0 37 | wd_params, nowd_params, lr_mul_wd_params, lr_mul_nowd_params = model.get_params() 38 | if bn_wd_disable: 39 | param_list = [ 40 | {'params': wd_params}, 41 | {'params': nowd_params, 'weight_decay': 0}, 42 | {'params': lr_mul_wd_params, 'lr_mul': True}, 43 | {'params': lr_mul_nowd_params, 'weight_decay': 0, 'lr_mul': True}] 44 | else: 45 | param_list = [ 46 | {'params': wd_params}, 47 | {'params': nowd_params}, 48 | {'params': lr_mul_wd_params, 'lr_mul': True}, 49 | {'params': lr_mul_nowd_params, 'lr_mul': True}] 50 | 51 | if self.type_ == 'sgd': 52 | self.optim = torch.optim.SGD( 53 | param_list, 54 | lr = lr0, 55 | momentum = momentum, 56 | weight_decay = wd) 57 | 58 | elif self.type_ == 'AdamW': 59 | self.optim = torch.optim.AdamW( 60 | param_list, 61 | lr = lr0, 62 | betas = tuple(betas), 63 | weight_decay = wd) 64 | 65 | self.warmup_factor = (self.lr0/self.warmup_start_lr)**(1./self.warmup_steps) 66 | 67 | 68 | def get_lr(self): 69 | if self.it <= self.warmup_steps: 70 | lr = self.warmup_start_lr*(self.warmup_factor**self.it) 71 | else: 72 | factor = (1-(self.it-self.warmup_steps)/(self.max_iter-self.warmup_steps))**self.power 73 | lr = self.lr0 * factor 74 | return lr 75 | 76 | def state_dict(self): #now it should works.. 77 | 78 | ########### Save the device for each params################# 79 | ############################################################# 80 | device_list = [] 81 | for state in self.optim.state.values(): 82 | for k, v in state.items(): 83 | if isinstance(v, torch.Tensor): 84 | device_list.append(v.device) 85 | ############################################################## 86 | 87 | hyper_param = {'type_':self.type_, 'betas':self.betas, 'warmup_steps': self.warmup_steps, 'warmup_start_lr': self.warmup_start_lr, 'lr0': self.lr0, 'bn_wd_disable': self.bn_wd_disable, 88 | 'lr': self.lr, 'max_iter':self.max_iter, 'power': self.power, 'lr_multi': self.lr_multi, 'it': self.it, 'sgd': self.optim.state_dict(), 89 | 'device_list': device_list,'warmup_factor': self.warmup_factor} 90 | return hyper_param 91 | 92 | def load_state_dict(self, ckpt): 93 | sgd_state_dict = ckpt.pop('sgd', None) 94 | 95 | self.optim.load_state_dict(sgd_state_dict) 96 | 97 | ############### Recover the params to devices ####### 98 | ##################################################### 99 | device_list = ckpt.pop('device_list', None) 100 | 101 | for state in self.optim.state.values(): 102 | for (k, v),dvi in zip(state.items(), device_list): 103 | if isinstance(v, torch.Tensor): 104 | state[k] = v.to(dvi) 105 | ##################################################### 106 | 107 | 108 | for key, val in ckpt.items(): 109 | self.__setattr__(key, val) 110 | 111 | 112 | def step(self): 113 | self.lr = self.get_lr() 114 | for pg in self.optim.param_groups: 115 | if pg.get('lr_mul', False): 116 | pg['lr'] = self.lr * self.lr_multi 117 | else: 118 | pg['lr'] = self.lr 119 | if self.optim.defaults.get('lr_mul', False): 120 | self.optim.defaults['lr'] = self.lr * self.lr_multi 121 | else: 122 | self.optim.defaults['lr'] = self.lr 123 | self.it += 1 124 | self.optim.step() 125 | if self.it == self.warmup_steps+2: 126 | logger.info('==> warmup done, start to implement poly lr strategy') 127 | 128 | def zero_grad(self): 129 | self.optim.zero_grad() 130 | 131 | -------------------------------------------------------------------------------- /Testing/models/erfnet/erfnet.py: -------------------------------------------------------------------------------- 1 | # ERFNET full network definition for Pytorch 2 | # Sept 2017 3 | # Eduardo Romera 4 | ####################### 5 | 6 | import torch 7 | import torch.nn as nn 8 | import torch.nn.init as init 9 | import torch.nn.functional as F 10 | 11 | 12 | class DownsamplerBlock (nn.Module): 13 | def __init__(self, ninput, noutput): 14 | super().__init__() 15 | 16 | self.conv = nn.Conv2d(ninput, noutput-ninput, (3, 3), stride=2, padding=1, bias=True) 17 | self.pool = nn.MaxPool2d(2, stride=2) 18 | self.bn = nn.Identity() 19 | 20 | def forward(self, input): 21 | output = torch.cat([self.conv(input), self.pool(input)], 1) 22 | output = self.bn(output) 23 | return F.relu(output) 24 | 25 | 26 | class non_bottleneck_1d (nn.Module): 27 | def __init__(self, chann, dropprob, dilated): 28 | super().__init__() 29 | 30 | self.conv3x1_1 = nn.Conv2d(chann, chann, (3, 1), stride=1, padding=(1,0), bias=True) 31 | 32 | self.conv1x3_1 = nn.Conv2d(chann, chann, (1,3), stride=1, padding=(0,1), bias=True) 33 | 34 | self.bn1 = nn.Identity() 35 | 36 | self.conv3x1_2 = nn.Conv2d(chann, chann, (3, 1), stride=1, padding=(1*dilated,0), bias=True, dilation = (dilated,1)) 37 | 38 | self.conv1x3_2 = nn.Conv2d(chann, chann, (1,3), stride=1, padding=(0,1*dilated), bias=True, dilation = (1, dilated)) 39 | 40 | self.bn2 = nn.Identity() 41 | 42 | self.dropout = nn.Dropout2d(dropprob) 43 | 44 | 45 | def forward(self, input): 46 | 47 | output = self.conv3x1_1(input) 48 | output = F.relu(output) 49 | output = self.conv1x3_1(output) 50 | output = self.bn1(output) 51 | output = F.relu(output) 52 | 53 | output = self.conv3x1_2(output) 54 | output = F.relu(output) 55 | output = self.conv1x3_2(output) 56 | output = self.bn2(output) 57 | 58 | if (self.dropout.p != 0): 59 | output = self.dropout(output) 60 | 61 | return F.relu(output+input) #+input = identity (residual connection) 62 | 63 | 64 | class Encoder(nn.Module): 65 | def __init__(self, num_classes): 66 | super().__init__() 67 | self.initial_block = DownsamplerBlock(3,16) 68 | 69 | self.layers = nn.ModuleList() 70 | 71 | self.layers.append(DownsamplerBlock(16,64)) 72 | 73 | for x in range(0, 5): #5 times 74 | self.layers.append(non_bottleneck_1d(64, 0.1, 1)) 75 | 76 | self.layers.append(DownsamplerBlock(64,128)) 77 | 78 | for x in range(0, 2): #2 times 79 | self.layers.append(non_bottleneck_1d(128, 0.1, 2)) 80 | self.layers.append(non_bottleneck_1d(128, 0.1, 4)) 81 | self.layers.append(non_bottleneck_1d(128, 0.1, 8)) 82 | self.layers.append(non_bottleneck_1d(128, 0.1, 16)) 83 | 84 | #only for encoder mode: 85 | self.output_conv = nn.Conv2d(128, num_classes, 1, stride=1, padding=0, bias=True) 86 | 87 | def forward(self, input, predict=False): 88 | output = self.initial_block(input) 89 | 90 | for layer in self.layers: 91 | output = layer(output) 92 | 93 | if predict: 94 | output = self.output_conv(output) 95 | 96 | return output 97 | 98 | 99 | class UpsamplerBlock (nn.Module): 100 | def __init__(self, ninput, noutput): 101 | super().__init__() 102 | self.conv = nn.ConvTranspose2d(ninput, noutput, 3, stride=2, padding=1, output_padding=1, bias=True) 103 | self.bn = nn.Identity() 104 | 105 | def forward(self, input): 106 | output = self.conv(input) 107 | output = self.bn(output) 108 | return F.relu(output) 109 | 110 | class Decoder (nn.Module): 111 | def __init__(self, num_classes): 112 | super().__init__() 113 | 114 | self.layers = nn.ModuleList() 115 | 116 | self.layers.append(UpsamplerBlock(128,64)) 117 | self.layers.append(non_bottleneck_1d(64, 0, 1)) 118 | self.layers.append(non_bottleneck_1d(64, 0, 1)) 119 | 120 | self.layers.append(UpsamplerBlock(64,16)) 121 | self.layers.append(non_bottleneck_1d(16, 0, 1)) 122 | self.layers.append(non_bottleneck_1d(16, 0, 1)) 123 | 124 | self.output_conv = nn.ConvTranspose2d( 16, num_classes, 2, stride=2, padding=0, output_padding=0, bias=True) 125 | 126 | def forward(self, input): 127 | output = input 128 | 129 | for layer in self.layers: 130 | output = layer(output) 131 | 132 | output = self.output_conv(output) 133 | 134 | return output 135 | 136 | 137 | class ERFNet(nn.Module): 138 | def __init__(self, num_classes=19, encoder=None): #use encoder to pass pretrained encoder 139 | super().__init__() 140 | 141 | if (encoder == None): 142 | self.encoder = Encoder(num_classes) 143 | else: 144 | self.encoder = encoder 145 | self.decoder = Decoder(num_classes) 146 | 147 | def forward(self, input, only_encode=False): 148 | if only_encode: 149 | return self.encoder.forward(input, predict=True) 150 | else: 151 | output = self.encoder(input) #predict=False by default 152 | return self.decoder.forward(output) 153 | -------------------------------------------------------------------------------- /Testing/models/fanet/modules/bn.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as functional 4 | 5 | try: 6 | from queue import Queue 7 | except ImportError: 8 | from Queue import Queue 9 | 10 | from .functions import * 11 | 12 | 13 | class ABN(nn.Module): 14 | """Activated Batch Normalization 15 | 16 | This gathers a `BatchNorm2d` and an activation function in a single module 17 | """ 18 | 19 | def __init__(self, num_features, eps=1e-5, momentum=0.1, affine=True, activation="leaky_relu", slope=0.01): 20 | """Creates an Activated Batch Normalization module 21 | 22 | Parameters 23 | ---------- 24 | num_features : int 25 | Number of feature channels in the input and output. 26 | eps : float 27 | Small constant to prevent numerical issues. 28 | momentum : float 29 | Momentum factor applied to compute running statistics as. 30 | affine : bool 31 | If `True` apply learned scale and shift transformation after normalization. 32 | activation : str 33 | Name of the activation functions, one of: `leaky_relu`, `elu` or `none`. 34 | slope : float 35 | Negative slope for the `leaky_relu` activation. 36 | """ 37 | super(ABN, self).__init__() 38 | self.num_features = num_features 39 | self.affine = affine 40 | self.eps = eps 41 | self.momentum = momentum 42 | self.activation = activation 43 | self.slope = slope 44 | if self.affine: 45 | self.weight = nn.Parameter(torch.ones(num_features)) 46 | self.bias = nn.Parameter(torch.zeros(num_features)) 47 | else: 48 | self.register_parameter('weight', None) 49 | self.register_parameter('bias', None) 50 | self.register_buffer('running_mean', torch.zeros(num_features)) 51 | self.register_buffer('running_var', torch.ones(num_features)) 52 | self.reset_parameters() 53 | 54 | def reset_parameters(self): 55 | nn.init.constant_(self.running_mean, 0) 56 | nn.init.constant_(self.running_var, 1) 57 | if self.affine: 58 | nn.init.constant_(self.weight, 1) 59 | nn.init.constant_(self.bias, 0) 60 | 61 | def forward(self, x): 62 | x = functional.batch_norm(x, self.running_mean, self.running_var, self.weight, self.bias, 63 | self.training, self.momentum, self.eps) 64 | 65 | if self.activation == ACT_RELU: 66 | return functional.relu(x, inplace=True) 67 | elif self.activation == ACT_LEAKY_RELU: 68 | return functional.leaky_relu(x, negative_slope=self.slope, inplace=True) 69 | elif self.activation == ACT_ELU: 70 | return functional.elu(x, inplace=True) 71 | else: 72 | return x 73 | 74 | def __repr__(self): 75 | rep = '{name}({num_features}, eps={eps}, momentum={momentum},' \ 76 | ' affine={affine}, activation={activation}' 77 | if self.activation == "leaky_relu": 78 | rep += ', slope={slope})' 79 | else: 80 | rep += ')' 81 | return rep.format(name=self.__class__.__name__, **self.__dict__) 82 | 83 | 84 | class InPlaceABN(ABN): 85 | """InPlace Activated Batch Normalization""" 86 | 87 | def __init__(self, num_features, eps=1e-5, momentum=0.1, affine=True, activation="leaky_relu", slope=0.01): 88 | """Creates an InPlace Activated Batch Normalization module 89 | 90 | Parameters 91 | ---------- 92 | num_features : int 93 | Number of feature channels in the input and output. 94 | eps : float 95 | Small constant to prevent numerical issues. 96 | momentum : float 97 | Momentum factor applied to compute running statistics as. 98 | affine : bool 99 | If `True` apply learned scale and shift transformation after normalization. 100 | activation : str 101 | Name of the activation functions, one of: `leaky_relu`, `elu` or `none`. 102 | slope : float 103 | Negative slope for the `leaky_relu` activation. 104 | """ 105 | super(InPlaceABN, self).__init__(num_features, eps, momentum, affine, activation, slope) 106 | 107 | def forward(self, x): 108 | return inplace_abn(x, self.weight, self.bias, self.running_mean, self.running_var, 109 | self.training, self.momentum, self.eps, self.activation, self.slope) 110 | 111 | 112 | class InPlaceABNSync(ABN): 113 | """InPlace Activated Batch Normalization with cross-GPU synchronization 114 | This assumes that it will be replicated across GPUs using the same mechanism as in `nn.DistributedDataParallel`. 115 | """ 116 | 117 | def forward(self, x): 118 | return inplace_abn_sync(x, self.weight, self.bias, self.running_mean, self.running_var, 119 | self.training, self.momentum, self.eps, self.activation, self.slope) 120 | 121 | def __repr__(self): 122 | rep = '{name}({num_features}, eps={eps}, momentum={momentum},' \ 123 | ' affine={affine}, activation={activation}' 124 | if self.activation == "leaky_relu": 125 | rep += ', slope={slope})' 126 | else: 127 | rep += ')' 128 | return rep.format(name=self.__class__.__name__, **self.__dict__) 129 | 130 | 131 | -------------------------------------------------------------------------------- /Testing/models/bisenet/modules/bn.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as functional 4 | 5 | try: 6 | from queue import Queue 7 | except ImportError: 8 | from Queue import Queue 9 | 10 | from .functions import * 11 | 12 | 13 | class ABN(nn.Module): 14 | """Activated Batch Normalization 15 | 16 | This gathers a `BatchNorm2d` and an activation function in a single module 17 | """ 18 | 19 | def __init__(self, num_features, eps=1e-5, momentum=0.1, affine=True, activation="leaky_relu", slope=0.01): 20 | """Creates an Activated Batch Normalization module 21 | 22 | Parameters 23 | ---------- 24 | num_features : int 25 | Number of feature channels in the input and output. 26 | eps : float 27 | Small constant to prevent numerical issues. 28 | momentum : float 29 | Momentum factor applied to compute running statistics as. 30 | affine : bool 31 | If `True` apply learned scale and shift transformation after normalization. 32 | activation : str 33 | Name of the activation functions, one of: `leaky_relu`, `elu` or `none`. 34 | slope : float 35 | Negative slope for the `leaky_relu` activation. 36 | """ 37 | super(ABN, self).__init__() 38 | self.num_features = num_features 39 | self.affine = affine 40 | self.eps = eps 41 | self.momentum = momentum 42 | self.activation = activation 43 | self.slope = slope 44 | if self.affine: 45 | self.weight = nn.Parameter(torch.ones(num_features)) 46 | self.bias = nn.Parameter(torch.zeros(num_features)) 47 | else: 48 | self.register_parameter('weight', None) 49 | self.register_parameter('bias', None) 50 | self.register_buffer('running_mean', torch.zeros(num_features)) 51 | self.register_buffer('running_var', torch.ones(num_features)) 52 | self.reset_parameters() 53 | 54 | def reset_parameters(self): 55 | nn.init.constant_(self.running_mean, 0) 56 | nn.init.constant_(self.running_var, 1) 57 | if self.affine: 58 | nn.init.constant_(self.weight, 1) 59 | nn.init.constant_(self.bias, 0) 60 | 61 | def forward(self, x): 62 | x = functional.batch_norm(x, self.running_mean, self.running_var, self.weight, self.bias, 63 | self.training, self.momentum, self.eps) 64 | 65 | if self.activation == ACT_RELU: 66 | return functional.relu(x, inplace=True) 67 | elif self.activation == ACT_LEAKY_RELU: 68 | return functional.leaky_relu(x, negative_slope=self.slope, inplace=True) 69 | elif self.activation == ACT_ELU: 70 | return functional.elu(x, inplace=True) 71 | else: 72 | return x 73 | 74 | def __repr__(self): 75 | rep = '{name}({num_features}, eps={eps}, momentum={momentum},' \ 76 | ' affine={affine}, activation={activation}' 77 | if self.activation == "leaky_relu": 78 | rep += ', slope={slope})' 79 | else: 80 | rep += ')' 81 | return rep.format(name=self.__class__.__name__, **self.__dict__) 82 | 83 | 84 | class InPlaceABN(ABN): 85 | """InPlace Activated Batch Normalization""" 86 | 87 | def __init__(self, num_features, eps=1e-5, momentum=0.1, affine=True, activation="leaky_relu", slope=0.01): 88 | """Creates an InPlace Activated Batch Normalization module 89 | 90 | Parameters 91 | ---------- 92 | num_features : int 93 | Number of feature channels in the input and output. 94 | eps : float 95 | Small constant to prevent numerical issues. 96 | momentum : float 97 | Momentum factor applied to compute running statistics as. 98 | affine : bool 99 | If `True` apply learned scale and shift transformation after normalization. 100 | activation : str 101 | Name of the activation functions, one of: `leaky_relu`, `elu` or `none`. 102 | slope : float 103 | Negative slope for the `leaky_relu` activation. 104 | """ 105 | super(InPlaceABN, self).__init__(num_features, eps, momentum, affine, activation, slope) 106 | 107 | def forward(self, x): 108 | return inplace_abn(x, self.weight, self.bias, self.running_mean, self.running_var, 109 | self.training, self.momentum, self.eps, self.activation, self.slope) 110 | 111 | 112 | class InPlaceABNSync(ABN): 113 | """InPlace Activated Batch Normalization with cross-GPU synchronization 114 | This assumes that it will be replicated across GPUs using the same mechanism as in `nn.DistributedDataParallel`. 115 | """ 116 | 117 | def forward(self, x): 118 | return inplace_abn_sync(x, self.weight, self.bias, self.running_mean, self.running_var, 119 | self.training, self.momentum, self.eps, self.activation, self.slope) 120 | 121 | def __repr__(self): 122 | rep = '{name}({num_features}, eps={eps}, momentum={momentum},' \ 123 | ' affine={affine}, activation={activation}' 124 | if self.activation == "leaky_relu": 125 | rep += ', slope={slope})' 126 | else: 127 | rep += ')' 128 | return rep.format(name=self.__class__.__name__, **self.__dict__) 129 | 130 | 131 | -------------------------------------------------------------------------------- /Testing/models/shelfnet/modules/bn.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as functional 4 | 5 | try: 6 | from queue import Queue 7 | except ImportError: 8 | from Queue import Queue 9 | 10 | from .functions import * 11 | 12 | 13 | class ABN(nn.Module): 14 | """Activated Batch Normalization 15 | 16 | This gathers a `BatchNorm2d` and an activation function in a single module 17 | """ 18 | 19 | def __init__(self, num_features, eps=1e-5, momentum=0.1, affine=True, activation="leaky_relu", slope=0.01): 20 | """Creates an Activated Batch Normalization module 21 | 22 | Parameters 23 | ---------- 24 | num_features : int 25 | Number of feature channels in the input and output. 26 | eps : float 27 | Small constant to prevent numerical issues. 28 | momentum : float 29 | Momentum factor applied to compute running statistics as. 30 | affine : bool 31 | If `True` apply learned scale and shift transformation after normalization. 32 | activation : str 33 | Name of the activation functions, one of: `leaky_relu`, `elu` or `none`. 34 | slope : float 35 | Negative slope for the `leaky_relu` activation. 36 | """ 37 | super(ABN, self).__init__() 38 | self.num_features = num_features 39 | self.affine = affine 40 | self.eps = eps 41 | self.momentum = momentum 42 | self.activation = activation 43 | self.slope = slope 44 | if self.affine: 45 | self.weight = nn.Parameter(torch.ones(num_features)) 46 | self.bias = nn.Parameter(torch.zeros(num_features)) 47 | else: 48 | self.register_parameter('weight', None) 49 | self.register_parameter('bias', None) 50 | self.register_buffer('running_mean', torch.zeros(num_features)) 51 | self.register_buffer('running_var', torch.ones(num_features)) 52 | self.reset_parameters() 53 | 54 | def reset_parameters(self): 55 | nn.init.constant_(self.running_mean, 0) 56 | nn.init.constant_(self.running_var, 1) 57 | if self.affine: 58 | nn.init.constant_(self.weight, 1) 59 | nn.init.constant_(self.bias, 0) 60 | 61 | def forward(self, x): 62 | x = functional.batch_norm(x, self.running_mean, self.running_var, self.weight, self.bias, 63 | self.training, self.momentum, self.eps) 64 | 65 | if self.activation == ACT_RELU: 66 | return functional.relu(x, inplace=True) 67 | elif self.activation == ACT_LEAKY_RELU: 68 | return functional.leaky_relu(x, negative_slope=self.slope, inplace=True) 69 | elif self.activation == ACT_ELU: 70 | return functional.elu(x, inplace=True) 71 | else: 72 | return x 73 | 74 | def __repr__(self): 75 | rep = '{name}({num_features}, eps={eps}, momentum={momentum},' \ 76 | ' affine={affine}, activation={activation}' 77 | if self.activation == "leaky_relu": 78 | rep += ', slope={slope})' 79 | else: 80 | rep += ')' 81 | return rep.format(name=self.__class__.__name__, **self.__dict__) 82 | 83 | 84 | class InPlaceABN(ABN): 85 | """InPlace Activated Batch Normalization""" 86 | 87 | def __init__(self, num_features, eps=1e-5, momentum=0.1, affine=True, activation="leaky_relu", slope=0.01): 88 | """Creates an InPlace Activated Batch Normalization module 89 | 90 | Parameters 91 | ---------- 92 | num_features : int 93 | Number of feature channels in the input and output. 94 | eps : float 95 | Small constant to prevent numerical issues. 96 | momentum : float 97 | Momentum factor applied to compute running statistics as. 98 | affine : bool 99 | If `True` apply learned scale and shift transformation after normalization. 100 | activation : str 101 | Name of the activation functions, one of: `leaky_relu`, `elu` or `none`. 102 | slope : float 103 | Negative slope for the `leaky_relu` activation. 104 | """ 105 | super(InPlaceABN, self).__init__(num_features, eps, momentum, affine, activation, slope) 106 | 107 | def forward(self, x): 108 | return inplace_abn(x, self.weight, self.bias, self.running_mean, self.running_var, 109 | self.training, self.momentum, self.eps, self.activation, self.slope) 110 | 111 | 112 | class InPlaceABNSync(ABN): 113 | """InPlace Activated Batch Normalization with cross-GPU synchronization 114 | This assumes that it will be replicated across GPUs using the same mechanism as in `nn.DistributedDataParallel`. 115 | """ 116 | 117 | def forward(self, x): 118 | return inplace_abn_sync(x, self.weight, self.bias, self.running_mean, self.running_var, 119 | self.training, self.momentum, self.eps, self.activation, self.slope) 120 | 121 | def __repr__(self): 122 | rep = '{name}({num_features}, eps={eps}, momentum={momentum},' \ 123 | ' affine={affine}, activation={activation}' 124 | if self.activation == "leaky_relu": 125 | rep += ', slope={slope})' 126 | else: 127 | rep += ')' 128 | return rep.format(name=self.__class__.__name__, **self.__dict__) 129 | 130 | 131 | -------------------------------------------------------------------------------- /Train/ptsemseg/models/fanet/modules/bn.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as functional 4 | 5 | try: 6 | from queue import Queue 7 | except ImportError: 8 | from Queue import Queue 9 | 10 | from .functions import * 11 | 12 | 13 | class ABN(nn.Module): 14 | """Activated Batch Normalization 15 | 16 | This gathers a `BatchNorm2d` and an activation function in a single module 17 | """ 18 | 19 | def __init__(self, num_features, eps=1e-5, momentum=0.1, affine=True, activation="leaky_relu", slope=0.01): 20 | """Creates an Activated Batch Normalization module 21 | 22 | Parameters 23 | ---------- 24 | num_features : int 25 | Number of feature channels in the input and output. 26 | eps : float 27 | Small constant to prevent numerical issues. 28 | momentum : float 29 | Momentum factor applied to compute running statistics as. 30 | affine : bool 31 | If `True` apply learned scale and shift transformation after normalization. 32 | activation : str 33 | Name of the activation functions, one of: `leaky_relu`, `elu` or `none`. 34 | slope : float 35 | Negative slope for the `leaky_relu` activation. 36 | """ 37 | super(ABN, self).__init__() 38 | self.num_features = num_features 39 | self.affine = affine 40 | self.eps = eps 41 | self.momentum = momentum 42 | self.activation = activation 43 | self.slope = slope 44 | if self.affine: 45 | self.weight = nn.Parameter(torch.ones(num_features)) 46 | self.bias = nn.Parameter(torch.zeros(num_features)) 47 | else: 48 | self.register_parameter('weight', None) 49 | self.register_parameter('bias', None) 50 | self.register_buffer('running_mean', torch.zeros(num_features)) 51 | self.register_buffer('running_var', torch.ones(num_features)) 52 | self.reset_parameters() 53 | 54 | def reset_parameters(self): 55 | nn.init.constant_(self.running_mean, 0) 56 | nn.init.constant_(self.running_var, 1) 57 | if self.affine: 58 | nn.init.constant_(self.weight, 1) 59 | nn.init.constant_(self.bias, 0) 60 | 61 | def forward(self, x): 62 | x = functional.batch_norm(x, self.running_mean, self.running_var, self.weight, self.bias, 63 | self.training, self.momentum, self.eps) 64 | 65 | if self.activation == ACT_RELU: 66 | return functional.relu(x, inplace=True) 67 | elif self.activation == ACT_LEAKY_RELU: 68 | return functional.leaky_relu(x, negative_slope=self.slope, inplace=True) 69 | elif self.activation == ACT_ELU: 70 | return functional.elu(x, inplace=True) 71 | else: 72 | return x 73 | 74 | def __repr__(self): 75 | rep = '{name}({num_features}, eps={eps}, momentum={momentum},' \ 76 | ' affine={affine}, activation={activation}' 77 | if self.activation == "leaky_relu": 78 | rep += ', slope={slope})' 79 | else: 80 | rep += ')' 81 | return rep.format(name=self.__class__.__name__, **self.__dict__) 82 | 83 | 84 | class InPlaceABN(ABN): 85 | """InPlace Activated Batch Normalization""" 86 | 87 | def __init__(self, num_features, eps=1e-5, momentum=0.1, affine=True, activation="leaky_relu", slope=0.01): 88 | """Creates an InPlace Activated Batch Normalization module 89 | 90 | Parameters 91 | ---------- 92 | num_features : int 93 | Number of feature channels in the input and output. 94 | eps : float 95 | Small constant to prevent numerical issues. 96 | momentum : float 97 | Momentum factor applied to compute running statistics as. 98 | affine : bool 99 | If `True` apply learned scale and shift transformation after normalization. 100 | activation : str 101 | Name of the activation functions, one of: `leaky_relu`, `elu` or `none`. 102 | slope : float 103 | Negative slope for the `leaky_relu` activation. 104 | """ 105 | super(InPlaceABN, self).__init__(num_features, eps, momentum, affine, activation, slope) 106 | 107 | def forward(self, x): 108 | return inplace_abn(x, self.weight, self.bias, self.running_mean, self.running_var, 109 | self.training, self.momentum, self.eps, self.activation, self.slope) 110 | 111 | 112 | class InPlaceABNSync(ABN): 113 | """InPlace Activated Batch Normalization with cross-GPU synchronization 114 | This assumes that it will be replicated across GPUs using the same mechanism as in `nn.DistributedDataParallel`. 115 | """ 116 | 117 | def forward(self, x): 118 | return inplace_abn_sync(x, self.weight, self.bias, self.running_mean, self.running_var, 119 | self.training, self.momentum, self.eps, self.activation, self.slope) 120 | 121 | def __repr__(self): 122 | rep = '{name}({num_features}, eps={eps}, momentum={momentum},' \ 123 | ' affine={affine}, activation={activation}' 124 | if self.activation == "leaky_relu": 125 | rep += ', slope={slope})' 126 | else: 127 | rep += ')' 128 | return rep.format(name=self.__class__.__name__, **self.__dict__) 129 | 130 | 131 | -------------------------------------------------------------------------------- /Testing/models/shelfnet/shelfnet.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | import torchvision 5 | 6 | from .resnet import Resnet18 7 | #from .modules.bn import InPlaceABNSync 8 | from .ShelfBlock import Decoder, LadderBlock 9 | 10 | class InPlaceABNSync(nn.Module): 11 | '''(conv => BN => ReLU) * 2''' 12 | def __init__(self, num_features): 13 | super(InPlaceABNSync, self).__init__() 14 | 15 | def forward(self, x): 16 | return x 17 | 18 | 19 | 20 | class ConvBNReLU(nn.Module): 21 | def __init__(self, in_chan, out_chan, ks=3, stride=1, padding=1, *args, **kwargs): 22 | super(ConvBNReLU, self).__init__() 23 | self.conv = nn.Conv2d(in_chan, 24 | out_chan, 25 | kernel_size = ks, 26 | stride = stride, 27 | padding = padding, 28 | bias = False) 29 | self.bn = InPlaceABNSync(out_chan) 30 | self.init_weight() 31 | 32 | def forward(self, x): 33 | x = self.conv(x) 34 | x = self.bn(x) 35 | return x 36 | 37 | def init_weight(self): 38 | for ly in self.children(): 39 | if isinstance(ly, nn.Conv2d): 40 | nn.init.kaiming_normal_(ly.weight, a=1) 41 | if not ly.bias is None: nn.init.constant_(ly.bias, 0) 42 | 43 | def get_params(self): 44 | wd_params, nowd_params = [], [] 45 | for name, module in self.named_modules(): 46 | if isinstance(module, nn.Linear) or isinstance(module, nn.Conv2d): 47 | wd_params.append(module.weight) 48 | if not module.bias is None: 49 | nowd_params.append(module.bias) 50 | elif isinstance(module, InPlaceABNSync) or isinstance(module, torch.nn.BatchNorm2d): 51 | nowd_params += list(module.parameters()) 52 | return wd_params, nowd_params 53 | 54 | 55 | class NetOutput(nn.Module): 56 | def __init__(self, in_chan, mid_chan, n_classes, *args, **kwargs): 57 | super(NetOutput, self).__init__() 58 | self.conv = ConvBNReLU(in_chan, mid_chan, ks=3, stride=1, padding=1) 59 | self.conv_out = nn.Conv2d(mid_chan, n_classes, kernel_size=3, bias=False, 60 | padding=1) 61 | self.init_weight() 62 | 63 | def forward(self, x): 64 | x = self.conv(x) 65 | x = self.conv_out(x) 66 | return x 67 | 68 | def init_weight(self): 69 | for ly in self.children(): 70 | if isinstance(ly, nn.Conv2d): 71 | nn.init.kaiming_normal_(ly.weight, a=1) 72 | if not ly.bias is None: nn.init.constant_(ly.bias, 0) 73 | 74 | def get_params(self): 75 | wd_params, nowd_params = [], [] 76 | for name, module in self.named_modules(): 77 | if isinstance(module, nn.Linear) or isinstance(module, nn.Conv2d): 78 | wd_params.append(module.weight) 79 | if not module.bias is None: 80 | nowd_params.append(module.bias) 81 | elif isinstance(module, InPlaceABNSync) or isinstance(module, torch.nn.BatchNorm2d): 82 | nowd_params += list(module.parameters()) 83 | return wd_params, nowd_params 84 | 85 | 86 | class ShelfNet18(nn.Module): 87 | def __init__(self, n_classes=19, *args, **kwargs): 88 | super(ShelfNet18, self).__init__() 89 | self.backbone = Resnet18() 90 | 91 | self.decoder = Decoder(planes=64,layers=3,kernel=3) 92 | self.ladder = LadderBlock(planes=64,layers=3, kernel=3) 93 | 94 | self.conv_out = NetOutput(64, 64, n_classes) 95 | self.conv_out16 = NetOutput(128, 64, n_classes) 96 | self.conv_out32 = NetOutput(256, 64, n_classes) 97 | 98 | self.trans1 = ConvBNReLU(128,64,ks=1,stride=1,padding=0) 99 | self.trans2 = ConvBNReLU(256, 128, ks=1, stride=1, padding=0) 100 | self.trans3 = ConvBNReLU(512, 256, ks=1, stride=1, padding=0) 101 | def forward(self, x, aux = False): 102 | H, W = x.size()[2:] 103 | 104 | feat8, feat16, feat32 = self.backbone(x) 105 | 106 | feat8 = self.trans1(feat8) 107 | feat16 = self.trans2(feat16) 108 | feat32 = self.trans3(feat32) 109 | 110 | out = self.decoder([feat8, feat16, feat32]) 111 | 112 | out2 = self.ladder(out) 113 | 114 | feat_cp8, feat_cp16, feat_cp32 = out2[-1], out2[-2], out2[-3] 115 | 116 | feat_out = self.conv_out(feat_cp8) 117 | feat_out = F.interpolate(feat_out, (H, W), mode='bilinear', align_corners=True) 118 | 119 | if aux: 120 | feat_out16 = self.conv_out16(feat_cp16) 121 | feat_out16 = F.interpolate(feat_out16, (H, W), mode='bilinear', align_corners=True) 122 | 123 | feat_out32 = self.conv_out32(feat_cp32) 124 | feat_out32 = F.interpolate(feat_out32, (H, W), mode='bilinear', align_corners=True) 125 | 126 | return feat_out, feat_out16, feat_out32 127 | else: 128 | return feat_out 129 | 130 | def get_params(self): 131 | wd_params, nowd_params, lr_mul_wd_params, lr_mul_nowd_params = [], [], [], [] 132 | for name, child in self.named_children(): 133 | child_wd_params, child_nowd_params = child.get_params() 134 | if isinstance(child, LadderBlock) or isinstance(child, NetOutput) or isinstance(child, Decoder)\ 135 | or isinstance(child, ConvBNReLU): 136 | lr_mul_wd_params += child_wd_params 137 | lr_mul_nowd_params += child_nowd_params 138 | else: 139 | wd_params += child_wd_params 140 | nowd_params += child_nowd_params 141 | return wd_params, nowd_params, lr_mul_wd_params, lr_mul_nowd_params 142 | -------------------------------------------------------------------------------- /Train/ptsemseg/loader/cocostuff_loader.py: -------------------------------------------------------------------------------- 1 | import os 2 | import torch 3 | import numpy as np 4 | import imageio as m 5 | import cv2 6 | from torch.utils import data 7 | import torchvision.transforms.functional as TF 8 | from ptsemseg.utils import recursive_glob 9 | from ptsemseg.augmentations import Compose, RandomHorizontallyFlip, RandomRotate, Scale 10 | 11 | def color_map( N=40, normalized=False): 12 | """ 13 | Return Color Map in PASCAL VOC format 14 | """ 15 | 16 | def bitget(byteval, idx): 17 | return (byteval & (1 << idx)) != 0 18 | 19 | dtype = "float32" if normalized else "uint8" 20 | cmap = np.zeros((N, 3), dtype=dtype) 21 | for i in range(N): 22 | r = g = b = 0 23 | c = i 24 | for j in range(8): 25 | r = r | (bitget(c, 0) << 7 - j) 26 | g = g | (bitget(c, 1) << 7 - j) 27 | b = b | (bitget(c, 2) << 7 - j) 28 | c = c >> 3 29 | 30 | cmap[i] = np.array([r, g, b]) 31 | 32 | cmap = cmap / 255.0 if normalized else cmap 33 | return cmap 34 | 35 | class cocostuffLoader(data.Dataset): 36 | 37 | colors = color_map(N=256) 38 | label_colours = dict(zip(range(256), colors)) 39 | 40 | def __init__( 41 | self, 42 | root, 43 | split="train", 44 | augmentations=None, 45 | test_mode=False, 46 | model_name=None 47 | ): 48 | self.root = root 49 | self.split = split 50 | self.augmentations = augmentations 51 | self.test_mode=test_mode 52 | self.model_name=model_name 53 | self.n_classes = 171 54 | self.files = {} 55 | 56 | self.images_base = os.path.join(self.root, "IMG", self.split) 57 | self.annotations_base = os.path.join(self.root, "GT", self.split) 58 | 59 | self.files[split] = recursive_glob(rootdir=self.annotations_base, suffix=".png") 60 | 61 | self.void_classes = [0] 62 | self.valid_classes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 63 | 21, 22, 23, 24, 25, 27, 28, 31, 32, 33, 34, 35, 36, 37, 38, 39, 64 | 40, 41, 42, 43, 44, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 65 | 59, 60, 61, 62, 63, 64, 65, 67, 70, 72, 73, 74, 75, 76, 77, 66 | 78, 79, 80, 81, 82, 84, 85, 86, 87, 88, 89, 90, 92, 93, 94, 95, 96, 67 | 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 68 | 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 69 | 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 70 | 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 71 | 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 72 | 177, 178, 179, 180, 181, 182] 73 | 74 | self.ignore_index = 250 75 | self.class_map = dict(zip(self.valid_classes, range(171))) 76 | 77 | if not self.files[split]: 78 | raise Exception("No files for split=[%s] found in %s" % (split, self.images_base)) 79 | 80 | print("Found %d %s images" % (len(self.files[split]), split)) 81 | 82 | def __len__(self): 83 | """__len__""" 84 | return len(self.files[self.split]) 85 | 86 | def __getitem__(self, index): 87 | """__getitem__ 88 | 89 | :param index: 90 | """ 91 | lbl_path = self.files[self.split][index].rstrip() 92 | img_path = os.path.join( 93 | self.images_base, 94 | os.path.basename(lbl_path))[:-3]+'jpg' 95 | 96 | img = m.imread(img_path) 97 | img = np.array(img, dtype=np.uint8) 98 | h,w,c = img.shape 99 | 100 | lbl = m.imread(lbl_path) 101 | lbl = cv2.resize(lbl,(w,h), interpolation = cv2.INTER_NEAREST) 102 | lbl = self.encode_segmap(np.array(lbl, dtype=np.uint8)) 103 | 104 | '''import cv2 105 | cv2.namedWindow("Image") 106 | cv2.imshow("Image", self.decode_segmap(lbl)) 107 | cv2.waitKey(0) 108 | cv2.destroyAllWindows()''' 109 | 110 | if self.augmentations is not None: 111 | img, lbl = self.augmentations(img, lbl) 112 | 113 | img = img.transpose(2, 0, 1) 114 | img = torch.from_numpy(img).float() 115 | lbl = torch.from_numpy(lbl).long() 116 | 117 | if self.test_mode: 118 | return img, lbl, os.path.basename(lbl_path)[:-3], h, w 119 | return img, lbl 120 | 121 | def decode_segmap(self, temp): 122 | r = temp.copy() 123 | g = temp.copy() 124 | b = temp.copy() 125 | for l in range(0, self.n_classes): 126 | r[temp == l] = self.label_colours[l][0] 127 | g[temp == l] = self.label_colours[l][1] 128 | b[temp == l] = self.label_colours[l][2] 129 | 130 | rgb = np.zeros((temp.shape[0], temp.shape[1], 3)) 131 | rgb[:, :, 0] = r / 255.0 132 | rgb[:, :, 1] = g / 255.0 133 | rgb[:, :, 2] = b / 255.0 134 | return rgb 135 | 136 | def encode_segmap(self, mask): 137 | mask_ = mask.copy() 138 | mask_ = mask_*0 139 | # Put all void classes to zero 140 | for _voidc in self.void_classes: 141 | mask_[mask == _voidc] = self.ignore_index 142 | for _validc in self.valid_classes: 143 | mask_[mask == _validc] = self.class_map[_validc] 144 | return mask_.astype(np.uint8) 145 | 146 | def decode_pred(self, mask): 147 | # Put all void classes to zero 148 | for _predc in range(self.n_classes): 149 | mask[mask == _predc] = self.valid_classes[_predc] 150 | return mask.astype(np.uint8) 151 | -------------------------------------------------------------------------------- /Testing/models/segnet/segnet.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | 6 | 7 | __all__ = ["SegNet"] 8 | 9 | class SegNet(nn.Module): 10 | def __init__(self,classes= 19): 11 | super(SegNet, self).__init__() 12 | 13 | batchNorm_momentum = 0.1 14 | 15 | self.conv11 = nn.Conv2d(3, 64, kernel_size=3, padding=1) 16 | self.bn11 = nn.Identity() 17 | self.conv12 = nn.Conv2d(64, 64, kernel_size=3, padding=1) 18 | self.bn12 = nn.Identity() 19 | 20 | self.conv21 = nn.Conv2d(64, 128, kernel_size=3, padding=1) 21 | self.bn21 = nn.Identity() 22 | self.conv22 = nn.Conv2d(128, 128, kernel_size=3, padding=1) 23 | self.bn22 = nn.Identity() 24 | 25 | self.conv31 = nn.Conv2d(128, 256, kernel_size=3, padding=1) 26 | self.bn31 = nn.Identity() 27 | self.conv32 = nn.Conv2d(256, 256, kernel_size=3, padding=1) 28 | self.bn32 = nn.Identity() 29 | self.conv33 = nn.Conv2d(256, 256, kernel_size=3, padding=1) 30 | self.bn33 = nn.Identity() 31 | 32 | self.conv41 = nn.Conv2d(256, 512, kernel_size=3, padding=1) 33 | self.bn41 = nn.Identity() 34 | self.conv42 = nn.Conv2d(512, 512, kernel_size=3, padding=1) 35 | self.bn42 = nn.Identity() 36 | self.conv43 = nn.Conv2d(512, 512, kernel_size=3, padding=1) 37 | self.bn43 = nn.Identity() 38 | 39 | self.conv51 = nn.Conv2d(512, 512, kernel_size=3, padding=1) 40 | self.bn51 = nn.Identity() 41 | self.conv52 = nn.Conv2d(512, 512, kernel_size=3, padding=1) 42 | self.bn52 = nn.Identity() 43 | self.conv53 = nn.Conv2d(512, 512, kernel_size=3, padding=1) 44 | self.bn53 = nn.Identity() 45 | 46 | self.conv53d = nn.Conv2d(512, 512, kernel_size=3, padding=1) 47 | self.bn53d = nn.Identity() 48 | self.conv52d = nn.Conv2d(512, 512, kernel_size=3, padding=1) 49 | self.bn52d = nn.Identity() 50 | self.conv51d = nn.Conv2d(512, 512, kernel_size=3, padding=1) 51 | self.bn51d = nn.Identity() 52 | 53 | self.conv43d = nn.Conv2d(512, 512, kernel_size=3, padding=1) 54 | self.bn43d = nn.Identity() 55 | self.conv42d = nn.Conv2d(512, 512, kernel_size=3, padding=1) 56 | self.bn42d = nn.Identity() 57 | self.conv41d = nn.Conv2d(512, 256, kernel_size=3, padding=1) 58 | self.bn41d = nn.Identity() 59 | 60 | self.conv33d = nn.Conv2d(256, 256, kernel_size=3, padding=1) 61 | self.bn33d = nn.Identity() 62 | self.conv32d = nn.Conv2d(256, 256, kernel_size=3, padding=1) 63 | self.bn32d = nn.Identity() 64 | self.conv31d = nn.Conv2d(256, 128, kernel_size=3, padding=1) 65 | self.bn31d = nn.Identity() 66 | 67 | self.conv22d = nn.Conv2d(128, 128, kernel_size=3, padding=1) 68 | self.bn22d = nn.Identity() 69 | self.conv21d = nn.Conv2d(128, 64, kernel_size=3, padding=1) 70 | self.bn21d = nn.Identity() 71 | 72 | self.conv12d = nn.Conv2d(64, 64, kernel_size=3, padding=1) 73 | self.bn12d = nn.Identity() 74 | self.conv11d = nn.Conv2d(64, classes, kernel_size=3, padding=1) 75 | 76 | 77 | def forward(self, x): 78 | 79 | # Stage 1 80 | x11 = F.relu(self.bn11(self.conv11(x))) 81 | x12 = F.relu(self.bn12(self.conv12(x11))) 82 | x1_size = x12.size() 83 | x1p, id1 = F.max_pool2d(x12,kernel_size=2, stride=2,return_indices=True) 84 | 85 | # Stage 2 86 | x21 = F.relu(self.bn21(self.conv21(x1p))) 87 | x22 = F.relu(self.bn22(self.conv22(x21))) 88 | x2_size = x22.size() 89 | x2p, id2 = F.max_pool2d(x22,kernel_size=2, stride=2,return_indices=True) 90 | 91 | # Stage 3 92 | x31 = F.relu(self.bn31(self.conv31(x2p))) 93 | x32 = F.relu(self.bn32(self.conv32(x31))) 94 | x33 = F.relu(self.bn33(self.conv33(x32))) 95 | x3_size = x33.size() 96 | x3p, id3 = F.max_pool2d(x33,kernel_size=2, stride=2,return_indices=True) 97 | 98 | # Stage 4 99 | x41 = F.relu(self.bn41(self.conv41(x3p))) 100 | x42 = F.relu(self.bn42(self.conv42(x41))) 101 | x43 = F.relu(self.bn43(self.conv43(x42))) 102 | x4_size = x43.size() 103 | x4p, id4 = F.max_pool2d(x43,kernel_size=2, stride=2,return_indices=True) 104 | 105 | # Stage 5 106 | x51 = F.relu(self.bn51(self.conv51(x4p))) 107 | x52 = F.relu(self.bn52(self.conv52(x51))) 108 | x53 = F.relu(self.bn53(self.conv53(x52))) 109 | x5_size = x53.size() 110 | x5p, id5 = F.max_pool2d(x53,kernel_size=2, stride=2,return_indices=True) 111 | 112 | 113 | # Stage 5d 114 | x5d = F.max_unpool2d(x5p, id5, kernel_size=2, stride=2, output_size=x5_size) 115 | x53d = F.relu(self.bn53d(self.conv53d(x5d))) 116 | x52d = F.relu(self.bn52d(self.conv52d(x53d))) 117 | x51d = F.relu(self.bn51d(self.conv51d(x52d))) 118 | 119 | # Stage 4d 120 | x4d = F.max_unpool2d(x51d, id4, kernel_size=2, stride=2, output_size=x4_size) 121 | x43d = F.relu(self.bn43d(self.conv43d(x4d))) 122 | x42d = F.relu(self.bn42d(self.conv42d(x43d))) 123 | x41d = F.relu(self.bn41d(self.conv41d(x42d))) 124 | 125 | # Stage 3d 126 | x3d = F.max_unpool2d(x41d, id3, kernel_size=2, stride=2, output_size=x3_size) 127 | x33d = F.relu(self.bn33d(self.conv33d(x3d))) 128 | x32d = F.relu(self.bn32d(self.conv32d(x33d))) 129 | x31d = F.relu(self.bn31d(self.conv31d(x32d))) 130 | 131 | # Stage 2d 132 | x2d = F.max_unpool2d(x31d, id2, kernel_size=2, stride=2, output_size=x2_size) 133 | x22d = F.relu(self.bn22d(self.conv22d(x2d))) 134 | x21d = F.relu(self.bn21d(self.conv21d(x22d))) 135 | 136 | # Stage 1d 137 | x1d = F.max_unpool2d(x21d, id1, kernel_size=2, stride=2, output_size=x1_size) 138 | x12d = F.relu(self.bn12d(self.conv12d(x1d))) 139 | x11d = self.conv11d(x12d) 140 | 141 | return x11d 142 | 143 | def load_from_segnet(self, model_path): 144 | s_dict = self.state_dict()# create a copy of the state dict 145 | th = torch.load(model_path).state_dict() # load the weigths 146 | # for name in th: 147 | # s_dict[corresp_name[name]] = th[name] 148 | self.load_state_dict(th) 149 | 150 | 151 | 152 | """print layers and params of network""" 153 | if __name__ == '__main__': 154 | device = torch.device("cuda" if torch.cuda.is_available() else "cpu") 155 | model = SegNet(classes=19).to(device) 156 | summary(model,(3,512,1024)) 157 | -------------------------------------------------------------------------------- /Train/ptsemseg/loader/cityscapes_loader.py: -------------------------------------------------------------------------------- 1 | import os 2 | import torch 3 | import numpy as np 4 | import imageio as m 5 | import pdb 6 | 7 | from torch.utils import data 8 | import torchvision.transforms.functional as TF 9 | from ptsemseg.utils import recursive_glob 10 | from ptsemseg.augmentations import Compose, RandomHorizontallyFlip, RandomRotate, Scale 11 | 12 | 13 | class cityscapesLoader(data.Dataset): 14 | """cityscapesLoader 15 | 16 | https://www.cityscapes-dataset.com 17 | 18 | Data is derived from CityScapes, and can be downloaded from here: 19 | https://www.cityscapes-dataset.com/downloads/ 20 | 21 | Many Thanks to @fvisin for the loader repo: 22 | https://github.com/fvisin/dataset_loaders/blob/master/dataset_loaders/images/cityscapes.py 23 | """ 24 | 25 | colors = [ # [ 0, 0, 0], 26 | [128, 64, 128], 27 | [244, 35, 232], 28 | [70, 70, 70], 29 | [102, 102, 156], 30 | [190, 153, 153], 31 | [153, 153, 153], 32 | [250, 170, 30], 33 | [220, 220, 0], 34 | [107, 142, 35], 35 | [152, 251, 152], 36 | [0, 130, 180], 37 | [220, 20, 60], 38 | [255, 0, 0], 39 | [0, 0, 142], 40 | [0, 0, 70], 41 | [0, 60, 100], 42 | [0, 80, 100], 43 | [0, 0, 230], 44 | [119, 11, 32], 45 | ] 46 | 47 | label_colours = dict(zip(range(19), colors)) 48 | 49 | 50 | 51 | def __init__( 52 | self, 53 | root, 54 | split, 55 | augmentations=None, 56 | model_name=None, 57 | test_mode = False 58 | ): 59 | """__init__ 60 | 61 | :param root: 62 | :param split: 63 | :param is_transform: 64 | :param img_size: 65 | :param augmentations 66 | """ 67 | self.test_mode = test_mode 68 | self.root = root 69 | self.split = split 70 | self.augmentations = augmentations 71 | self.model_name=model_name 72 | self.n_classes = 19 73 | self.files = self.read_list() 74 | 75 | 76 | self.void_classes = [0, 1, 2, 3, 4, 5, 6, 9, 10, 14, 15, 16, 18, 29, 30, -1] 77 | self.valid_classes = [7, 8, 11, 12, 13, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 31, 32, 33] 78 | self.class_names = [ 79 | "unlabelled", 80 | "road", 81 | "sidewalk", 82 | "building", 83 | "wall", 84 | "fence", 85 | "pole", 86 | "traffic_light", 87 | "traffic_sign", 88 | "vegetation", 89 | "terrain", 90 | "sky", 91 | "person", 92 | "rider", 93 | "car", 94 | "truck", 95 | "bus", 96 | "train", 97 | "motorcycle", 98 | "bicycle", 99 | ] 100 | 101 | self.ignore_index = 250 102 | self.class_map = dict(zip(self.valid_classes, range(19))) 103 | 104 | if len(self.files)==0: 105 | raise Exception("No files for split=[%s] found in %s" % (split, self.images_base)) 106 | 107 | print("Found %d images in: %s" % (len(self.files),split)) 108 | 109 | def read_list(self): 110 | list_ = [] 111 | for line in open(self.split): 112 | img, ann = line.strip('\n').split('\t') 113 | list_.append([os.path.join(self.root,img),os.path.join(self.root,ann)]) 114 | return list_ 115 | 116 | 117 | def __len__(self): 118 | """__len__""" 119 | return len(self.files) 120 | 121 | def __getitem__(self, index): 122 | """__getitem__ 123 | 124 | :param index: 125 | """ 126 | img_path = self.files[index][0].rstrip() 127 | lbl_path = self.files[index][1].rstrip() 128 | 129 | lbl_name = lbl_path.split('/')[-1] 130 | 131 | 132 | img = m.imread(img_path) 133 | img = np.array(img, dtype=np.uint8) 134 | 135 | h_,w_,c_ = img.shape 136 | 137 | lbl = m.imread(lbl_path) 138 | if len(lbl.shape)==3: 139 | lbl = lbl[:,:,0] 140 | lbl = self.encode_segmap(np.array(lbl, dtype=np.uint8)) 141 | 142 | if self.augmentations is not None: 143 | img, lbl = self.augmentations(img, lbl) 144 | 145 | '''import cv2 146 | cv2.namedWindow("Image") 147 | cv2.imshow("Image", img) 148 | cv2.waitKey(0) 149 | cv2.destroyAllWindows() 150 | pdb.set_trace()''' 151 | 152 | img = img.transpose(2, 0, 1) 153 | img = torch.from_numpy(img).float() 154 | lbl = torch.from_numpy(lbl).long() 155 | if self.test_mode: 156 | return img, lbl, lbl_name, w_, h_ 157 | else: 158 | return img, lbl 159 | 160 | 161 | 162 | 163 | def decode_segmap(self, temp): 164 | r = temp.copy() 165 | g = temp.copy() 166 | b = temp.copy() 167 | for l in range(0, self.n_classes): 168 | r[temp == l] = self.label_colours[l][0] 169 | g[temp == l] = self.label_colours[l][1] 170 | b[temp == l] = self.label_colours[l][2] 171 | 172 | rgb = np.zeros((temp.shape[0], temp.shape[1], 3)) 173 | rgb[:, :, 0] = b / 255.0 174 | rgb[:, :, 1] = g / 255.0 175 | rgb[:, :, 2] = r / 255.0 176 | return rgb 177 | 178 | def encode_segmap(self, mask): 179 | # Put all void classes to zero 180 | for _voidc in self.void_classes: 181 | mask[mask == _voidc] = self.ignore_index 182 | for _validc in self.valid_classes: 183 | mask[mask == _validc] = self.class_map[_validc] 184 | return mask 185 | 186 | def decode_pred(self, mask): 187 | # Put all void classes to zero 188 | mask_ = mask.copy() 189 | mask_ = mask_*0 190 | for _predc in range(self.n_classes): 191 | mask_[mask == _predc] = self.valid_classes[_predc] 192 | return mask_.astype(np.uint8) 193 | 194 | 195 | if __name__ == "__main__": 196 | import matplotlib.pyplot as plt 197 | 198 | augmentations = Compose([Scale(2048), RandomRotate(10), RandomHorizontallyFlip(0.5)]) 199 | 200 | local_path = "/datasets01/cityscapes/112817/" 201 | dst = cityscapesLoader(local_path, is_transform=True, augmentations=augmentations) 202 | bs = 4 203 | trainloader = data.DataLoader(dst, batch_size=bs, num_workers=0) 204 | for i, data_samples in enumerate(trainloader): 205 | imgs, labels = data_samples 206 | import pdb 207 | 208 | pdb.set_trace() 209 | imgs = imgs.numpy()[:, ::-1, :, :] 210 | imgs = np.transpose(imgs, [0, 2, 3, 1]) 211 | f, axarr = plt.subplots(bs, 2) 212 | for j in range(bs): 213 | axarr[j][0].imshow(imgs[j]) 214 | axarr[j][1].imshow(dst.decode_segmap(labels.numpy()[j])) 215 | plt.show() 216 | a = input() 217 | if a == "ex": 218 | break 219 | else: 220 | plt.close() 221 | -------------------------------------------------------------------------------- /Testing/models/fanet/fanet.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | from .resnet import Resnet18,Resnet34,Resnet50,Resnet101,Resnet152 5 | 6 | 7 | class BatchNorm2d(nn.BatchNorm2d): 8 | '''(conv => BN => ReLU) * 2''' 9 | def __init__(self, num_features, activation='none'): 10 | super(BatchNorm2d, self).__init__(num_features=num_features) 11 | if activation == 'leaky_relu': 12 | self.activation = nn.LeakyReLU() 13 | elif activation == 'none': 14 | self.activation = lambda x:x 15 | else: 16 | raise Exception("Accepted activation: ['leaky_relu']") 17 | 18 | def forward(self, x): 19 | return self.activation(x) 20 | 21 | 22 | 23 | 24 | up_kwargs = {'mode': 'bilinear', 'align_corners': True} 25 | 26 | class FANet(nn.Module): 27 | def __init__(self, 28 | nclass=19, 29 | backbone='resnet18', 30 | norm_layer=BatchNorm2d): 31 | super(FANet, self).__init__() 32 | 33 | self.norm_layer = norm_layer 34 | self._up_kwargs = up_kwargs 35 | self.nclass = nclass 36 | self.backbone = backbone 37 | if backbone == 'resnet18': 38 | self.expansion = 1 39 | self.resnet = Resnet18(norm_layer=norm_layer) 40 | elif backbone == 'resnet34': 41 | self.expansion = 1 42 | self.resnet = Resnet34(norm_layer=norm_layer) 43 | elif backbone == 'resnet50': 44 | self.expansion = 4 45 | self.resnet = Resnet50(norm_layer=norm_layer) 46 | elif backbone == 'resnet101': 47 | self.expansion = 4 48 | self.resnet = Resnet101(norm_layer=norm_layer) 49 | elif backbone == 'resnet152': 50 | self.expansion = 4 51 | self.resnet = Resnet152(norm_layer=norm_layer) 52 | else: 53 | raise RuntimeError('unknown backbone: {}'.format(backbone)) 54 | 55 | self.fam_32 = FastAttModule(512*self.expansion,256,128,norm_layer=norm_layer) 56 | self.fam_16 = FastAttModule(256*self.expansion,256,128,norm_layer=norm_layer) 57 | self.fam_8 = FastAttModule(128*self.expansion,256,128,norm_layer=norm_layer) 58 | self.fam_4 = FastAttModule(64*self.expansion,256,128,norm_layer=norm_layer) 59 | 60 | self.clslayer = FPNOutput(256, 256, nclass,norm_layer=norm_layer) 61 | 62 | def forward(self, x, lbl=None): 63 | 64 | _, _, h, w = x.size() 65 | 66 | feat4, feat8, feat16, feat32 = self.resnet(x) 67 | 68 | upfeat_32, smfeat_32 = self.fam_32(feat32,None,True,True) 69 | upfeat_16, smfeat_16 = self.fam_16(feat16,upfeat_32,True,True) 70 | upfeat_8 = self.fam_8(feat8,upfeat_16,True,False) 71 | smfeat_4 = self.fam_4(feat4,upfeat_8,False,True) 72 | 73 | x = self._upsample_cat(smfeat_16, smfeat_4) 74 | 75 | outputs = self.clslayer(x) 76 | 77 | return outputs 78 | 79 | def _upsample_cat(self, x1, x2): 80 | '''Upsample and concatenate feature maps. 81 | ''' 82 | _,_,H,W = x2.size() 83 | x1 = F.interpolate(x1, (H,W), **self._up_kwargs) 84 | x = torch.cat([x1,x2],dim=1) 85 | return x 86 | 87 | 88 | class ConvBNReLU(nn.Module): 89 | def __init__(self, in_chan, out_chan, ks=3, stride=1, padding=1, norm_layer=None, activation='leaky_relu',*args, **kwargs): 90 | super(ConvBNReLU, self).__init__() 91 | self.conv = nn.Conv2d(in_chan, 92 | out_chan, 93 | kernel_size = ks, 94 | stride = stride, 95 | padding = padding, 96 | bias = False) 97 | self.norm_layer = norm_layer 98 | if self.norm_layer is not None: 99 | self.bn = norm_layer(out_chan, activation=activation) 100 | else: 101 | self.bn = lambda x:x 102 | 103 | def forward(self, x): 104 | x = self.conv(x) 105 | x = self.bn(x) 106 | return x 107 | 108 | 109 | class FPNOutput(nn.Module): 110 | def __init__(self, in_chan, mid_chan, n_classes, norm_layer=None, *args, **kwargs): 111 | super(FPNOutput, self).__init__() 112 | self.norm_layer = norm_layer 113 | self.conv = ConvBNReLU(in_chan, mid_chan, ks=3, stride=1, padding=1, norm_layer=norm_layer) 114 | self.conv_out = nn.Conv2d(mid_chan, n_classes, kernel_size=1, bias=False) 115 | 116 | def forward(self, x): 117 | x = self.conv(x) 118 | x = self.conv_out(x) 119 | return x 120 | 121 | 122 | 123 | class FastAttModule(nn.Module): 124 | def __init__(self, in_chan, mid_chn=256, out_chan=128, norm_layer=None, *args, **kwargs): 125 | super(FastAttModule, self).__init__() 126 | self.norm_layer = norm_layer 127 | self._up_kwargs = up_kwargs 128 | mid_chn = int(in_chan/2) 129 | self.w_qs = ConvBNReLU(in_chan, 32, ks=1, stride=1, padding=0, norm_layer=norm_layer, activation='none') 130 | 131 | self.w_ks = ConvBNReLU(in_chan, 32, ks=1, stride=1, padding=0, norm_layer=norm_layer, activation='none') 132 | 133 | self.w_vs = ConvBNReLU(in_chan, in_chan, ks=1, stride=1, padding=0, norm_layer=norm_layer) 134 | 135 | self.latlayer3 = ConvBNReLU(in_chan, in_chan, ks=1, stride=1, padding=0, norm_layer=norm_layer) 136 | 137 | self.up = ConvBNReLU(in_chan, mid_chn, ks=1, stride=1, padding=1, norm_layer=norm_layer) 138 | self.smooth = ConvBNReLU(in_chan, out_chan, ks=3, stride=1, padding=1, norm_layer=norm_layer) 139 | 140 | 141 | def forward(self, feat, up_fea_in,up_flag, smf_flag): 142 | 143 | query = self.w_qs(feat) 144 | key = self.w_ks(feat) 145 | value = self.w_vs(feat) 146 | 147 | N,C,H,W = feat.size() 148 | 149 | query_ = query.view(N,32,-1).permute(0, 2, 1) 150 | query = F.normalize(query_, p=2, dim=2, eps=1e-12) 151 | 152 | key_ = key.view(N,32,-1) 153 | key = F.normalize(key_, p=2, dim=1, eps=1e-12) 154 | 155 | value = value.view(N,C,-1).permute(0, 2, 1) 156 | 157 | f = torch.matmul(key, value) 158 | y = torch.matmul(query, f) 159 | y = y.permute(0, 2, 1).contiguous() 160 | 161 | y = y.view(N, C, H, W) 162 | W_y = self.latlayer3(y) 163 | p_feat = W_y + feat 164 | 165 | if up_flag and smf_flag: 166 | if up_fea_in is not None: 167 | p_feat = self._upsample_add(up_fea_in, p_feat) 168 | up_feat = self.up(p_feat) 169 | smooth_feat = self.smooth(p_feat) 170 | return up_feat, smooth_feat 171 | 172 | if up_flag and not smf_flag: 173 | if up_fea_in is not None: 174 | p_feat = self._upsample_add(up_fea_in, p_feat) 175 | up_feat = self.up(p_feat) 176 | return up_feat 177 | 178 | if not up_flag and smf_flag: 179 | if up_fea_in is not None: 180 | p_feat = self._upsample_add(up_fea_in, p_feat) 181 | smooth_feat = self.smooth(p_feat) 182 | return smooth_feat 183 | 184 | 185 | def _upsample_add(self, x, y): 186 | '''Upsample and add two feature maps. 187 | ''' 188 | _,_,H,W = y.size() 189 | return F.interpolate(x, (H,W), **self._up_kwargs) + y 190 | --------------------------------------------------------------------------------