fpn.py 3.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
import numpy as np
import paddle.fluid as fluid
from paddle.fluid.dygraph import Layer
from paddle.fluid.dygraph import Conv2D, Pool2D, BatchNorm
from paddle.fluid.param_attr import ParamAttr
from paddle.fluid.initializer import Xavier
from paddle.fluid.regularizer import L2Decay
from ppdet.core.workspace import register, serializable


@register
@serializable
class FPN(Layer):
    def __init__(self,
                 in_channels,
                 out_channel,
                 min_level=0,
                 max_level=4,
                 spatial_scale=[0.25, 0.125, 0.0625, 0.03125]):

        super(FPN, self).__init__()
        self.lateral_convs = []
        self.fpn_convs = []
        fan = out_channel * 3 * 3

        for i in range(min_level, max_level):
            if i == 3:
                lateral_name = 'fpn_inner_res5_sum'
            else:
                lateral_name = 'fpn_inner_res{}_sum_lateral'.format(i + 2)
            in_c = in_channels[i]
            lateral = self.add_sublayer(
                lateral_name,
                Conv2D(
                    num_channels=in_c,
                    num_filters=out_channel,
                    filter_size=1,
                    param_attr=ParamAttr(
                        #name=lateral_name+'_w', 
                        initializer=Xavier(fan_out=in_c)),
                    bias_attr=ParamAttr(
                        #name=lateral_name+'_b', 
                        learning_rate=2.,
                        regularizer=L2Decay(0.))))
            self.lateral_convs.append(lateral)

            fpn_name = 'fpn_res{}_sum'.format(i + 2)
            fpn_conv = self.add_sublayer(
                fpn_name,
                Conv2D(
                    num_channels=out_channel,
                    num_filters=out_channel,
                    filter_size=3,
                    padding=1,
                    param_attr=ParamAttr(
                        #name=fpn_name+'_w', 
                        initializer=Xavier(fan_out=fan)),
                    bias_attr=ParamAttr(
                        #name=fpn_name+'_b', 
                        learning_rate=2.,
                        regularizer=L2Decay(0.))))
            self.fpn_convs.append(fpn_conv)

        self.min_level = min_level
        self.max_level = max_level
        self.spatial_scale = spatial_scale

    def forward(self, body_feats):
        laterals = []
        for lvl in range(self.min_level, self.max_level):
            laterals.append(self.lateral_convs[lvl](body_feats[lvl]))

        for lvl in range(self.max_level - 1, self.min_level, -1):
            upsample = fluid.layers.resize_nearest(laterals[lvl], scale=2.)
            laterals[lvl - 1] = laterals[lvl - 1] + upsample

        fpn_output = []
        for lvl in range(self.min_level, self.max_level):
            fpn_output.append(self.fpn_convs[lvl](laterals[lvl]))

        extension = fluid.layers.pool2d(fpn_output[-1], 1, 'max', pool_stride=2)

        spatial_scale = self.spatial_scale + [self.spatial_scale[-1] * 0.5]
        fpn_output.append(extension)
        return fpn_output, spatial_scale