hrfpn.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import paddle
  15. import paddle.nn.functional as F
  16. import paddle.nn as nn
  17. from ppdet.core.workspace import register
  18. from ..shape_spec import ShapeSpec
  19. __all__ = ['HRFPN']
  20. @register
  21. class HRFPN(nn.Layer):
  22. """
  23. Args:
  24. in_channels (list): number of input feature channels from backbone
  25. out_channel (int): number of output feature channels
  26. share_conv (bool): whether to share conv for different layers' reduction
  27. extra_stage (int): add extra stage for returning HRFPN fpn_feats
  28. spatial_scales (list): feature map scaling factor
  29. """
  30. def __init__(self,
  31. in_channels=[18, 36, 72, 144],
  32. out_channel=256,
  33. share_conv=False,
  34. extra_stage=1,
  35. spatial_scales=[1. / 4, 1. / 8, 1. / 16, 1. / 32],
  36. use_bias=False):
  37. super(HRFPN, self).__init__()
  38. in_channel = sum(in_channels)
  39. self.in_channel = in_channel
  40. self.out_channel = out_channel
  41. self.share_conv = share_conv
  42. for i in range(extra_stage):
  43. spatial_scales = spatial_scales + [spatial_scales[-1] / 2.]
  44. self.spatial_scales = spatial_scales
  45. self.num_out = len(self.spatial_scales)
  46. self.use_bias = use_bias
  47. bias_attr = False if use_bias is False else None
  48. self.reduction = nn.Conv2D(
  49. in_channels=in_channel,
  50. out_channels=out_channel,
  51. kernel_size=1,
  52. bias_attr=bias_attr)
  53. if share_conv:
  54. self.fpn_conv = nn.Conv2D(
  55. in_channels=out_channel,
  56. out_channels=out_channel,
  57. kernel_size=3,
  58. padding=1,
  59. bias_attr=bias_attr)
  60. else:
  61. self.fpn_conv = []
  62. for i in range(self.num_out):
  63. conv_name = "fpn_conv_" + str(i)
  64. conv = self.add_sublayer(
  65. conv_name,
  66. nn.Conv2D(
  67. in_channels=out_channel,
  68. out_channels=out_channel,
  69. kernel_size=3,
  70. padding=1,
  71. bias_attr=bias_attr))
  72. self.fpn_conv.append(conv)
  73. def forward(self, body_feats):
  74. num_backbone_stages = len(body_feats)
  75. outs = []
  76. outs.append(body_feats[0])
  77. # resize
  78. for i in range(1, num_backbone_stages):
  79. resized = F.interpolate(
  80. body_feats[i], scale_factor=2**i, mode='bilinear')
  81. outs.append(resized)
  82. # concat
  83. out = paddle.concat(outs, axis=1)
  84. assert out.shape[
  85. 1] == self.in_channel, 'in_channel should be {}, be received {}'.format(
  86. out.shape[1], self.in_channel)
  87. # reduction
  88. out = self.reduction(out)
  89. # conv
  90. outs = [out]
  91. for i in range(1, self.num_out):
  92. outs.append(F.avg_pool2d(out, kernel_size=2**i, stride=2**i))
  93. outputs = []
  94. for i in range(self.num_out):
  95. conv_func = self.fpn_conv if self.share_conv else self.fpn_conv[i]
  96. conv = conv_func(outs[i])
  97. outputs.append(conv)
  98. fpn_feats = [outputs[k] for k in range(self.num_out)]
  99. return fpn_feats
  100. @classmethod
  101. def from_config(cls, cfg, input_shape):
  102. return {
  103. 'in_channels': [i.channels for i in input_shape],
  104. 'spatial_scales': [1.0 / i.stride for i in input_shape],
  105. }
  106. @property
  107. def out_shape(self):
  108. return [
  109. ShapeSpec(
  110. channels=self.out_channel, stride=1. / s)
  111. for s in self.spatial_scales
  112. ]