class FastPyramidPooling(HybridBlock): def __init__(self, in_channels, out_channels, in_size): super(FastPyramidPooling, self).__init__() down_sizes = [1, 2, 3, 6] mid_channels = in_channels // 4 with self.name_scope(): self.branches = Concurrent() self.branches.add(Identity()) for down_size in down_sizes: self.branches.add(PoolingBranch( in_channels=in_channels, out_channels=mid_channels, in_size=in_size, down_size=down_size)) self.conv = conv1x1_block( in_channels=(in_channels * 2), out_channels=out_channels) def hybrid_forward(self, F, x): x = self.branches(x) x = self.conv(x) return x
class FastPyramidPooling(nn.Layer): """ Fast-SCNN specific fast pyramid pooling block. Parameters: ---------- in_channels : int Number of input channels. out_channels : int Number of output channels. in_size : tuple of 2 int or None Spatial size of input image. data_format : str, default 'channels_last' The ordering of the dimensions in tensors. """ def __init__(self, in_channels, out_channels, in_size, data_format="channels_last", **kwargs): super(FastPyramidPooling, self).__init__(**kwargs) down_sizes = [1, 2, 3, 6] mid_channels = in_channels // 4 self.branches = Concurrent( data_format=data_format, name="branches") self.branches.add(Identity(name="branch1")) for i, down_size in enumerate(down_sizes): self.branches.add(PoolingBranch( in_channels=in_channels, out_channels=mid_channels, in_size=in_size, down_size=down_size, data_format=data_format, name="branch{}".format(i + 2))) self.conv = conv1x1_block( in_channels=(in_channels * 2), out_channels=out_channels, data_format=data_format, name="conv") def call(self, x, training=None): x = self.branches(x, training=training) x = self.conv(x, training=training) return x