pspnet.py 3.5 KB
Newer Older
P
pengmian 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# -*- coding: utf-8 -*- 
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import math
import paddle
import paddle.fluid as fluid
from paddle.fluid.param_attr import ParamAttr
from models.libs.model_libs import scope, name_scope
from models.libs.model_libs import avg_pool , conv, bn
from models.backbone.resnet import ResNet as resnet_backbone
from utils.config import cfg

def get_logit_interp(input, num_classes, out_shape, name="logit"):
P
pengmian 已提交
15
    # 根据类别数决定最后一层卷积输出, 并插值回原始尺寸
P
pengmian 已提交
16 17 18 19 20 21 22
    param_attr = fluid.ParamAttr(
        name=name + 'weights',
        regularizer=fluid.regularizer.L2DecayRegularizer(
            regularization_coeff=0.0),
        initializer=fluid.initializer.TruncatedNormal(loc=0.0, scale=0.01))

    with scope(name):
P
pengmian 已提交
23 24 25 26 27 28
        logit = conv(input,
                    num_classes,
                    filter_size=1,
                    param_attr=param_attr,
                    bias_attr=True,
                    name=name+'_conv')
P
pengmian 已提交
29 30 31 32 33 34 35 36
        logit_interp = fluid.layers.resize_bilinear(
                    logit, 
                    out_shape=out_shape,
                    name='logit_interp') 
    return logit_interp


def psp_module(input, out_features):
P
pengmian 已提交
37 38 39 40 41
    # Pyramid Scene Parsing 金字塔池化模块
    # 输入:backbone输出的特征
    # 输出:对输入进行不同尺度pooling, 卷积操作后插值回原始尺寸,并concat
    #       最后进行一个卷积及BN操作
    
P
pengmian 已提交
42 43 44 45 46 47
    cat_layers = []
    sizes = (1,2,3,6)
    for size in sizes:
        psp_name = "psp_conv" + str(size)
        with scope(psp_name):
            pool = fluid.layers.adaptive_pool2d(input, 
P
pengmian 已提交
48 49 50 51 52 53 54
                    pool_size=[size, size], 
                    pool_type='avg', 
                    name=psp_name+'_adapool')
            data = conv(pool, out_features, 
                    filter_size=1,
                    bias_attr=True, 
                    name= psp_name + '_conv')
P
pengmian 已提交
55 56
            data_bn = bn(data, act='relu')
            interp = fluid.layers.resize_bilinear(data_bn, 
P
pengmian 已提交
57 58
                    out_shape=input.shape[2:], 
                    name=psp_name+'_interp') 
P
pengmian 已提交
59 60 61
        cat_layers.append(interp)
    cat_layers = [input] + cat_layers[::-1]
    cat = fluid.layers.concat(cat_layers, axis=1, name='psp_cat')
P
pengmian 已提交
62 63 64

    psp_end_name = "psp_conv_end"
    with scope(psp_end_name):
P
pengmian 已提交
65
        data = conv(cat, 
P
pengmian 已提交
66 67 68 69 70
                    out_features, 
                    filter_size=3,
                    padding=1, 
                    bias_attr=True,
                    name=psp_end_name)
P
pengmian 已提交
71 72 73 74 75
        out = bn(data, act='relu')

    return out

def resnet(input):
P
pengmian 已提交
76 77 78 79
    # PSPNET backbone: resnet, 默认resnet50
    # end_points: resnet终止层数
    # dilation_dict: resnet block数及对应的膨胀卷积尺度
    scale = cfg.MODEL.ICNET.DEPTH_MULTIPLIER
P
pengmian 已提交
80 81 82 83 84
    scale = cfg.MODEL.PSPNET.DEPTH_MULTIPLIER
    layers = cfg.MODEL.PSPNET.LAYERS
    end_points = layers - 1
    dilation_dict = {2:2, 3:4}
    model = resnet_backbone(layers, scale, stem='pspnet')
P
pengmian 已提交
85 86 87
    data, _ = model.net(input, 
                        end_points=end_points, 
                        dilation_dict=dilation_dict)
P
pengmian 已提交
88 89 90 91

    return data

def pspnet(input, num_classes):
P
pengmian 已提交
92
    # Backbone: ResNet
P
pengmian 已提交
93
    res = resnet(input)
P
pengmian 已提交
94
    # PSP模块
P
pengmian 已提交
95
    psp = psp_module(res, 512)
P
pengmian 已提交
96 97 98
    dropout = fluid.layers.dropout(psp, dropout_prob=0.1, name="dropout")
    # 根据类别数决定最后一层卷积输出, 并插值回原始尺寸
    logit = get_logit_interp(dropout, num_classes, input.shape[2:])
P
pengmian 已提交
99 100
    return logit