Spaces:
Configuration error
Configuration error
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"); | |
# you may not use this file except in compliance with the License. | |
# You may obtain a copy of the License at | |
# | |
# http://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
# See the License for the specific language governing permissions and | |
# limitations under the License. | |
import paddle.nn as nn | |
import paddle.nn.functional as F | |
import paddle | |
from paddleseg import utils | |
from paddleseg.cvlibs import manager, param_init | |
from paddleseg.models import layers | |
class FCN(nn.Layer): | |
""" | |
A simple implementation for FCN based on PaddlePaddle. | |
The original article refers to | |
Evan Shelhamer, et, al. "Fully Convolutional Networks for Semantic Segmentation" | |
(https://arxiv.org/abs/1411.4038). | |
Args: | |
num_classes (int): The unique number of target classes. | |
backbone (paddle.nn.Layer): Backbone networks. | |
backbone_indices (tuple, optional): The values in the tuple indicate the indices of output of backbone. | |
Default: (-1, ). | |
channels (int, optional): The channels between conv layer and the last layer of FCNHead. | |
If None, it will be the number of channels of input features. Default: None. | |
align_corners (bool): An argument of F.interpolate. It should be set to False when the output size of feature | |
is even, e.g. 1024x512, otherwise it is True, e.g. 769x769. Default: False. | |
pretrained (str, optional): The path or url of pretrained model. Default: None | |
""" | |
def __init__(self, | |
num_classes, | |
backbone, | |
backbone_indices=(-1, ), | |
channels=None, | |
align_corners=False, | |
pretrained=None, | |
bias=True, | |
data_format="NCHW"): | |
super(FCN, self).__init__() | |
if data_format != 'NCHW': | |
raise ('fcn only support NCHW data format') | |
self.backbone = backbone | |
backbone_channels = [ | |
backbone.feat_channels[i] for i in backbone_indices | |
] | |
self.head = FCNHead( | |
num_classes, | |
backbone_indices, | |
backbone_channels, | |
channels, | |
bias=bias) | |
self.align_corners = align_corners | |
self.pretrained = pretrained | |
self.data_format = data_format | |
self.init_weight() | |
def forward(self, x): | |
feat_list = self.backbone(x) | |
logit_list = self.head(feat_list) | |
return [ | |
F.interpolate( | |
logit, | |
paddle.shape(x)[2:], | |
mode='bilinear', | |
align_corners=self.align_corners) for logit in logit_list | |
] | |
def init_weight(self): | |
if self.pretrained is not None: | |
utils.load_entire_model(self, self.pretrained) | |
class FCNHead(nn.Layer): | |
""" | |
A simple implementation for FCNHead based on PaddlePaddle | |
Args: | |
num_classes (int): The unique number of target classes. | |
backbone_indices (tuple, optional): The values in the tuple indicate the indices of output of backbone. | |
Default: (-1, ). | |
channels (int, optional): The channels between conv layer and the last layer of FCNHead. | |
If None, it will be the number of channels of input features. Default: None. | |
pretrained (str, optional): The path of pretrained model. Default: None | |
""" | |
def __init__(self, | |
num_classes, | |
backbone_indices=(-1, ), | |
backbone_channels=(270, ), | |
channels=None, | |
bias=True): | |
super(FCNHead, self).__init__() | |
self.num_classes = num_classes | |
self.backbone_indices = backbone_indices | |
if channels is None: | |
channels = backbone_channels[0] | |
self.conv_1 = layers.ConvBNReLU( | |
in_channels=backbone_channels[0], | |
out_channels=channels, | |
kernel_size=1, | |
stride=1, | |
bias_attr=bias) | |
self.cls = nn.Conv2D( | |
in_channels=channels, | |
out_channels=self.num_classes, | |
kernel_size=1, | |
stride=1, | |
bias_attr=bias) | |
self.init_weight() | |
def forward(self, feat_list): | |
logit_list = [] | |
x = feat_list[self.backbone_indices[0]] | |
x = self.conv_1(x) | |
logit = self.cls(x) | |
logit_list.append(logit) | |
return logit_list | |
def init_weight(self): | |
for layer in self.sublayers(): | |
if isinstance(layer, nn.Conv2D): | |
param_init.normal_init(layer.weight, std=0.001) | |
elif isinstance(layer, (nn.BatchNorm, nn.SyncBatchNorm)): | |
param_init.constant_init(layer.weight, value=1.0) | |
param_init.constant_init(layer.bias, value=0.0) | |